Frontend first draft

This commit is contained in:
Arseni
2025-11-13 15:06:15 +03:00
parent e47f343afb
commit ddb54ddfdc
504 changed files with 25498 additions and 1 deletions

View File

@@ -0,0 +1,70 @@
import 'package:flutter/material.dart';
import 'package:pweb/generated/i18n/app_localizations.dart';
class UploadCSVSection extends StatelessWidget {
const UploadCSVSection({super.key});
static const double _verticalSpacing = 10;
static const double _iconTextSpacing = 5;
static const double _buttonVerticalPadding = 12;
static const double _buttonHorizontalPadding = 24;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final l10n = AppLocalizations.of(context)!;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
const Icon(Icons.upload),
const SizedBox(width: _iconTextSpacing),
Text(
l10n.uploadCSV,
style: theme.textTheme.bodyLarge?.copyWith(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
],
),
const SizedBox(height: _verticalSpacing),
Container(
height: 140,
decoration: BoxDecoration(
border: Border.all(color: theme.colorScheme.outline),
borderRadius: BorderRadius.circular(8),
),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.upload_file, size: 36, color: theme.colorScheme.primary),
const SizedBox(height: 8),
ElevatedButton(
onPressed: () {},
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(
horizontal: _buttonHorizontalPadding,
vertical: _buttonVerticalPadding,
),
),
child: Text(l10n.upload),
),
const SizedBox(height: 8),
Text(
l10n.hintUpload,
style: const TextStyle(fontSize: 12),
),
],
),
),
),
],
);
}
}

View File

@@ -0,0 +1,13 @@
class MultiplePayoutRow {
final String token;
final String amount;
final String currency;
final String comment;
const MultiplePayoutRow({
required this.token,
required this.amount,
required this.currency,
required this.comment,
});
}

View File

@@ -0,0 +1,69 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:pweb/generated/i18n/app_localizations.dart';
import 'package:pweb/providers/upload_history.dart';
class UploadHistorySection extends StatelessWidget {
const UploadHistorySection({super.key});
static const double _smallBox = 5;
static const double _radius = 6;
@override
Widget build(BuildContext context) {
final provider = context.watch<UploadHistoryProvider>();
final theme = Theme.of(context);
final l10 = AppLocalizations.of(context)!;
if (provider.isLoading) {
return const Center(child: CircularProgressIndicator());
}
if (provider.error != null) {
return Text("Error: ${provider.error}");
}
final items = provider.data ?? [];
return Column(
children: [
Row(
children: [
const Icon(Icons.history),
const SizedBox(width: _smallBox),
Text(l10.uploadHistory, style: theme.textTheme.bodyLarge),
],
),
DataTable(
columns: [
DataColumn(label: Text(l10.fileNameColumn)),
DataColumn(label: Text(l10.colStatus)),
DataColumn(label: Text(l10.dateColumn)),
DataColumn(label: Text(l10.details)),
],
rows: items.map((file) {
final isError = file.status == "Error";
final statusColor = isError ? Colors.red : Colors.green;
return DataRow(
cells: [
DataCell(Text(file.name)),
DataCell(Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: statusColor.withAlpha(20),
borderRadius: BorderRadius.circular(_radius),
),
child: Text(file.status, style: TextStyle(color: statusColor)),
)),
DataCell(Text(file.time)),
DataCell(TextButton(onPressed: () {}, child: Text(l10.showDetails))),
],
);
}).toList(),
),
],
);
}
}

View File

@@ -0,0 +1,71 @@
import 'package:flutter/material.dart';
import 'package:pweb/generated/i18n/app_localizations.dart';
import 'package:pweb/pages/dashboard/payouts/multiple/form.dart';
class FileFormatSampleSection extends StatelessWidget {
const FileFormatSampleSection({super.key});
static final List<MultiplePayoutRow> sampleRows = [
MultiplePayoutRow(token: "d921...161", amount: "500", currency: "RUB", comment: "cashback001"),
MultiplePayoutRow(token: "d921...162", amount: "100", currency: "USD", comment: "cashback002"),
MultiplePayoutRow(token: "d921...163", amount: "120", currency: "EUR", comment: "cashback003"),
];
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final l10n = AppLocalizations.of(context)!;
final titleStyle = theme.textTheme.bodyLarge?.copyWith(
fontSize: 18,
fontWeight: FontWeight.w600,
);
final linkStyle = theme.textTheme.bodyMedium?.copyWith(
color: theme.colorScheme.primary,
);
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
children: [
const Icon(Icons.filter_list),
const SizedBox(width: 5),
Text(l10n.exampleTitle, style: titleStyle),
],
),
const SizedBox(height: 12),
_buildDataTable(l10n),
const SizedBox(height: 10),
TextButton(
onPressed: () {},
style: TextButton.styleFrom(padding: EdgeInsets.zero),
child: Text(l10n.downloadSampleCSV, style: linkStyle),
),
],
);
}
Widget _buildDataTable(AppLocalizations l10n) {
return DataTable(
columnSpacing: 20,
columns: [
DataColumn(label: Text(l10n.tokenColumn)),
DataColumn(label: Text(l10n.amount)),
DataColumn(label: Text(l10n.currency)),
DataColumn(label: Text(l10n.comment)),
],
rows: sampleRows.map((row) {
return DataRow(cells: [
DataCell(Text(row.token)),
DataCell(Text(row.amount)),
DataCell(Text(row.currency)),
DataCell(Text(row.comment)),
]);
}).toList(),
);
}
}

View File

@@ -0,0 +1,30 @@
import 'package:flutter/material.dart';
import 'package:pweb/generated/i18n/app_localizations.dart';
class TitleMultiplePayout extends StatelessWidget {
const TitleMultiplePayout({super.key});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
AppLocalizations.of(context)!.multiplePayout,
style: theme.textTheme.titleLarge,
),
const SizedBox(width: 20),
Text(
AppLocalizations.of(context)!.howItWorks,
style: theme.textTheme.bodyLarge!.copyWith(
color: theme.colorScheme.primary,
),
),
],
);
}
}

View File

@@ -0,0 +1,57 @@
import 'package:flutter/material.dart';
import 'package:pweb/pages/dashboard/payouts/multiple/csv.dart';
import 'package:pweb/pages/dashboard/payouts/multiple/history.dart';
import 'package:pweb/pages/dashboard/payouts/multiple/sample.dart';
class MultiplePayoutForm extends StatelessWidget {
const MultiplePayoutForm({super.key});
static const double _spacing = 12;
static const double _bottomSpacing = 40;
static final List<Widget> _cards = const [
FileFormatSampleSection(),
UploadCSVSection(),
UploadHistorySection(),
];
@override
Widget build(BuildContext context) {
return Column(
children: [
for (int i = 0; i < _cards.length; i++) ...[
_StyledCard(child: _cards[i]),
if (i < _cards.length - 1) const SizedBox(height: _spacing),
],
const SizedBox(height: _bottomSpacing),
],
);
}
}
class _StyledCard extends StatelessWidget {
final Widget child;
const _StyledCard({required this.child});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return SizedBox(
width: double.infinity,
child: Card(
margin: const EdgeInsets.all(1),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
elevation: 4,
color: theme.colorScheme.onSecondary,
child: Padding(
padding: const EdgeInsets.all(16),
child: child,
),
),
);
}
}