This commit is contained in:
2026-06-13 23:24:00 +03:00
parent 8fb785944c
commit 127a917eac
6 changed files with 231 additions and 36 deletions
+1
View File
@@ -167,6 +167,7 @@ class AppStrings {
String get colorPrimary => _ru ? 'Основной' : 'Primary';
String get colorSecondary => _ru ? 'Второй' : 'Secondary';
String get colorSecond => _ru ? 'Второй' : 'Second';
String get colorSolid => _ru ? 'Однотон' : 'Solid';
String get gradientLinear => _ru ? 'Линейный' : 'Linear';
String get gradientReverse => _ru ? 'Обратный' : 'Reverse';
@@ -85,7 +85,7 @@ class _AccountEditorOverlayState extends State<AccountEditorOverlay> {
Widget build(BuildContext context) {
final mq = MediaQuery.of(widget.context);
final cardTop = mq.padding.top + kToolbarHeight + 16;
const cardHeight = 230.0;
const cardHeight = 190.0;
const editorPanelHeight = 102.0;
final editorPanelTop = cardTop + cardHeight + 20;
final colorPanelTop = editorPanelTop + editorPanelHeight + 12;
@@ -3,7 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../../core/constants.dart';
import '../../../../shared/widgets/byn_sign.dart';
class AccountEditorPanel extends ConsumerWidget {
class AccountEditorPanel extends ConsumerStatefulWidget {
final TextEditingController nameController;
final String selectedCurrency;
final bool showCurrencyDropdown;
@@ -26,15 +26,29 @@ class AccountEditorPanel extends ConsumerWidget {
});
@override
Widget build(BuildContext context, WidgetRef ref) {
ConsumerState<AccountEditorPanel> createState() => _AccountEditorPanelState();
}
class _AccountEditorPanelState extends ConsumerState<AccountEditorPanel> {
bool _showNameError = false;
void _triggerNameError() {
setState(() => _showNameError = true);
Future.delayed(const Duration(seconds: 2), () {
if (mounted) setState(() => _showNameError = false);
});
}
@override
Widget build(BuildContext context) {
return Container(
height: panelHeight,
height: widget.panelHeight,
decoration: BoxDecoration(
color: Theme.of(dashboardContext).colorScheme.surface,
color: Theme.of(widget.dashboardContext).colorScheme.surface,
borderRadius: BorderRadius.circular(20),
border: Border.all(
color: Theme.of(
dashboardContext,
widget.dashboardContext,
).colorScheme.onSurface.withOpacity(0.1),
width: 1.5,
),
@@ -58,7 +72,7 @@ class AccountEditorPanel extends ConsumerWidget {
fontSize: 11,
fontWeight: FontWeight.w600,
color: Theme.of(
dashboardContext,
widget.dashboardContext,
).colorScheme.onSurface.withOpacity(0.6),
),
),
@@ -70,7 +84,7 @@ class AccountEditorPanel extends ConsumerWidget {
Expanded(
flex: 3,
child: TextField(
controller: nameController,
controller: widget.nameController,
buildCounter:
(
context, {
@@ -84,23 +98,23 @@ class AccountEditorPanel extends ConsumerWidget {
hintStyle: TextStyle(
fontSize: 13,
color: Theme.of(
dashboardContext,
widget.dashboardContext,
).colorScheme.onSurface.withOpacity(0.4),
),
filled: true,
fillColor: Theme.of(
dashboardContext,
widget.dashboardContext,
).colorScheme.onSurface.withOpacity(0.05),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(
color:
(showLimitError ||
showDuplicateError ||
nameController.text.trim().isEmpty)
(widget.showLimitError ||
widget.showDuplicateError ||
_showNameError)
? Colors.red
: Theme.of(
dashboardContext,
widget.dashboardContext,
).colorScheme.onSurface.withOpacity(0.15),
width: 1.5,
),
@@ -109,12 +123,12 @@ class AccountEditorPanel extends ConsumerWidget {
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(
color:
(showLimitError ||
showDuplicateError ||
nameController.text.trim().isEmpty)
(widget.showLimitError ||
widget.showDuplicateError ||
_showNameError)
? Colors.red
: Theme.of(
dashboardContext,
widget.dashboardContext,
).colorScheme.onSurface.withOpacity(0.15),
width: 1.5,
),
@@ -123,9 +137,9 @@ class AccountEditorPanel extends ConsumerWidget {
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(
color:
(showLimitError ||
showDuplicateError ||
nameController.text.trim().isEmpty)
(widget.showLimitError ||
widget.showDuplicateError ||
_showNameError)
? Colors.red
: const Color(0xFF7C6DED),
width: 1.5,
@@ -141,19 +155,19 @@ class AccountEditorPanel extends ConsumerWidget {
const SizedBox(width: 8),
Expanded(
child: GestureDetector(
onTap: onCurrencyDropdownToggle,
onTap: widget.onCurrencyDropdownToggle,
child: Container(
height: double.infinity,
decoration: BoxDecoration(
color: Theme.of(
dashboardContext,
widget.dashboardContext,
).colorScheme.onSurface.withOpacity(0.05),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: showCurrencyDropdown
color: widget.showCurrencyDropdown
? const Color(0xFF7C6DED)
: Theme.of(
dashboardContext,
widget.dashboardContext,
).colorScheme.onSurface.withOpacity(0.15),
width: 1.5,
),
@@ -162,17 +176,17 @@ class AccountEditorPanel extends ConsumerWidget {
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
selectedCurrency == 'BYN'
widget.selectedCurrency == 'BYN'
? BynSign(
fontSize: 15,
color: Theme.of(
dashboardContext,
widget.dashboardContext,
).colorScheme.onSurface,
)
: Text(
kDisplayCurrencies
.firstWhere(
(c) => c.$1 == selectedCurrency,
(c) => c.$1 == widget.selectedCurrency,
)
.$2,
style: const TextStyle(
@@ -182,12 +196,12 @@ class AccountEditorPanel extends ConsumerWidget {
),
const SizedBox(width: 4),
Icon(
showCurrencyDropdown
widget.showCurrencyDropdown
? Icons.arrow_drop_up
: Icons.arrow_drop_down,
size: 20,
color: Theme.of(
dashboardContext,
widget.dashboardContext,
).colorScheme.onSurface.withOpacity(0.6),
),
],
@@ -171,7 +171,7 @@ class BalanceCardState extends ConsumerState<BalanceCard>
..rotateY(_tiltY * 0.42),
child: Container(
width: double.infinity,
height: 220,
height: 180,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
gradient: _buildGradient(primary, secondary, gradientType),
@@ -66,7 +66,7 @@ class _BalanceCardCarouselState extends ConsumerState<BalanceCardCarousel> {
return Column(
children: [
SizedBox(
height: 230,
height: 190,
child: OverflowBox(
maxWidth: MediaQuery.of(context).size.width,
child: PageView.builder(
@@ -154,14 +154,14 @@ class _BalanceCardCarouselState extends ConsumerState<BalanceCardCarousel> {
);
},
loading: () => const SizedBox(
height: 220,
height: 180,
child: Center(child: CircularProgressIndicator()),
),
error: (error, stack) {
return Column(
children: [
SizedBox(
height: 220,
height: 180,
child: BalanceCard(
balance: widget.balance,
currencyInfo: widget.currencyInfo,
@@ -198,7 +198,7 @@ class AddAccountCard extends StatelessWidget {
painter: _DashedBorderPainter(),
child: Container(
width: double.infinity,
height: 205,
height: 165,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface.withOpacity(0.4),
borderRadius: BorderRadius.circular(20),
+181 -1
View File
@@ -2,10 +2,188 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:intl/date_symbol_data_local.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:uuid/uuid.dart';
import 'app/app.dart';
import 'core/services/haptic_service.dart';
import 'data/database/app_database.dart';
import 'data/database/app_database.dart' hide Account, Transaction;
import 'data/repositories/account_repository.dart';
import 'data/repositories/transaction_repository.dart';
import 'features/dashboard/provider.dart';
import 'shared/models/account.dart';
import 'shared/models/transaction.dart';
Future<void> seedTestData(AppDatabase database) async {
final accountRepo = AccountRepository(database);
final transactionRepo = TransactionRepository(database);
final existingAccounts = await accountRepo.getAll();
if (existingAccounts.length > 1) {
return;
}
final now = DateTime.now();
final uuid = const Uuid();
final cashId = await accountRepo.add(
Account(
id: 0,
name: 'Cash',
isMain: false,
sortOrder: 1,
currency: 'USD',
createdAt: now,
),
);
final cardId = await accountRepo.add(
Account(
id: 0,
name: 'Card',
isMain: false,
sortOrder: 2,
currency: 'USD',
createdAt: now,
),
);
final savingsId = await accountRepo.add(
Account(
id: 0,
name: 'Savings',
isMain: false,
sortOrder: 3,
currency: 'USD',
createdAt: now,
),
);
final transactions = [
Transaction(
id: uuid.v4(),
amount: 3500.0,
category: 'Salary',
type: TransactionType.income,
date: now.subtract(const Duration(days: 28)),
note: 'Monthly salary',
accountId: cardId,
),
Transaction(
id: uuid.v4(),
amount: 85.50,
category: 'Groceries',
type: TransactionType.expense,
date: now.subtract(const Duration(days: 27)),
note: 'Weekly shopping',
accountId: cardId,
),
Transaction(
id: uuid.v4(),
amount: 45.00,
category: 'Transportation',
type: TransactionType.expense,
date: now.subtract(const Duration(days: 25)),
accountId: cashId,
),
Transaction(
id: uuid.v4(),
amount: 120.00,
category: 'Utilities',
type: TransactionType.expense,
date: now.subtract(const Duration(days: 22)),
note: 'Electricity bill',
accountId: cardId,
),
Transaction(
id: uuid.v4(),
amount: 200.0,
category: 'Freelance',
type: TransactionType.income,
date: now.subtract(const Duration(days: 20)),
note: 'Side project',
accountId: cashId,
),
Transaction(
id: uuid.v4(),
amount: 500.0,
category: 'Savings',
type: TransactionType.expense,
date: now.subtract(const Duration(days: 18)),
note: 'Monthly savings',
accountId: savingsId,
),
Transaction(
id: uuid.v4(),
amount: 65.25,
category: 'Dining',
type: TransactionType.expense,
date: now.subtract(const Duration(days: 15)),
accountId: cardId,
),
Transaction(
id: uuid.v4(),
amount: 30.00,
category: 'Entertainment',
type: TransactionType.expense,
date: now.subtract(const Duration(days: 12)),
note: 'Movie tickets',
accountId: cashId,
),
Transaction(
id: uuid.v4(),
amount: 95.00,
category: 'Groceries',
type: TransactionType.expense,
date: now.subtract(const Duration(days: 10)),
accountId: cardId,
),
Transaction(
id: uuid.v4(),
amount: 150.0,
category: 'Bonus',
type: TransactionType.income,
date: now.subtract(const Duration(days: 8)),
note: 'Performance bonus',
accountId: cardId,
),
Transaction(
id: uuid.v4(),
amount: 75.00,
category: 'Shopping',
type: TransactionType.expense,
date: now.subtract(const Duration(days: 6)),
accountId: cardId,
),
Transaction(
id: uuid.v4(),
amount: 40.00,
category: 'Transportation',
type: TransactionType.expense,
date: now.subtract(const Duration(days: 4)),
accountId: cashId,
),
Transaction(
id: uuid.v4(),
amount: 55.80,
category: 'Dining',
type: TransactionType.expense,
date: now.subtract(const Duration(days: 2)),
note: 'Dinner with friends',
accountId: cardId,
),
Transaction(
id: uuid.v4(),
amount: 100.0,
category: 'Gift',
type: TransactionType.income,
date: now.subtract(const Duration(days: 1)),
accountId: cashId,
),
];
for (final transaction in transactions) {
await transactionRepo.add(transaction);
}
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();
@@ -20,6 +198,8 @@ void main() async {
final database = AppDatabase();
await seedTestData(database);
runApp(
ProviderScope(
overrides: [