mirror of
https://github.com/koloideal/Casha.git
synced 2026-06-10 10:25:28 +03:00
update
This commit is contained in:
@@ -87,9 +87,8 @@ class _AddTransactionScreenState extends ConsumerState<AddTransactionScreen> {
|
|||||||
lastDate: DateTime.now(),
|
lastDate: DateTime.now(),
|
||||||
builder: (context, child) => Theme(
|
builder: (context, child) => Theme(
|
||||||
data: Theme.of(context).copyWith(
|
data: Theme.of(context).copyWith(
|
||||||
colorScheme: const ColorScheme.dark(
|
colorScheme: Theme.of(context).colorScheme.copyWith(
|
||||||
primary: AppColors.accent,
|
primary: AppColors.accent,
|
||||||
surface: AppColors.surface,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: child!,
|
child: child!,
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class _CategoriesScreenState extends ConsumerState<CategoriesScreen> {
|
|||||||
..sort((a, b) => b.value.compareTo(a.value));
|
..sort((a, b) => b.value.compareTo(a.value));
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: AppColors.background,
|
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Column(
|
title: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@@ -41,13 +41,13 @@ class _CategoriesScreenState extends ConsumerState<CategoriesScreen> {
|
|||||||
'Categories',
|
'Categories',
|
||||||
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
color: AppColors.textPrimary,
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'Expense breakdown',
|
'Expense breakdown',
|
||||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||||
color: AppColors.textSecondary,
|
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.6),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -94,7 +94,7 @@ class _CategoriesScreenState extends ConsumerState<CategoriesScreen> {
|
|||||||
'Ranked by Amount',
|
'Ranked by Amount',
|
||||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: AppColors.textPrimary,
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
@@ -134,9 +134,8 @@ class _ChartToggle extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: AppColors.surface,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
border: Border.all(color: AppColors.divider),
|
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@@ -179,7 +178,7 @@ class _ToggleButton extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
child: Icon(
|
child: Icon(
|
||||||
icon,
|
icon,
|
||||||
color: isSelected ? AppColors.accent : AppColors.textSecondary,
|
color: isSelected ? AppColors.accent : Theme.of(context).colorScheme.onSurface.withOpacity(0.6),
|
||||||
size: 20,
|
size: 20,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -209,9 +208,8 @@ class _PieChartCard extends StatelessWidget {
|
|||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(20),
|
padding: const EdgeInsets.all(20),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: AppColors.surface,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
border: Border.all(color: AppColors.divider),
|
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
@@ -247,10 +245,10 @@ class _PieChartCard extends StatelessWidget {
|
|||||||
? '${(val / total * 100).toStringAsFixed(1)}%'
|
? '${(val / total * 100).toStringAsFixed(1)}%'
|
||||||
: '',
|
: '',
|
||||||
radius: isTouched ? 60 : 50,
|
radius: isTouched ? 60 : 50,
|
||||||
titleStyle: const TextStyle(
|
titleStyle: TextStyle(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
color: Colors.white,
|
color: Theme.of(context).colorScheme.onPrimary,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
@@ -262,13 +260,13 @@ class _PieChartCard extends StatelessWidget {
|
|||||||
Text(
|
Text(
|
||||||
'Total',
|
'Total',
|
||||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||||
color: AppColors.textSecondary,
|
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.6),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'$currency${total.toStringAsFixed(2)}',
|
'$currency${total.toStringAsFixed(2)}',
|
||||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||||
color: AppColors.textPrimary,
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -296,9 +294,8 @@ class _BarChartCard extends StatelessWidget {
|
|||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(20),
|
padding: const EdgeInsets.all(20),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: AppColors.surface,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
border: Border.all(color: AppColors.divider),
|
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@@ -306,7 +303,7 @@ class _BarChartCard extends StatelessWidget {
|
|||||||
Text(
|
Text(
|
||||||
'Last 6 Months',
|
'Last 6 Months',
|
||||||
style: Theme.of(context).textTheme.titleSmall?.copyWith(
|
style: Theme.of(context).textTheme.titleSmall?.copyWith(
|
||||||
color: AppColors.textSecondary,
|
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.6),
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -322,8 +319,8 @@ class _BarChartCard extends StatelessWidget {
|
|||||||
getTooltipItem: (group, groupIndex, rod, rodIndex) {
|
getTooltipItem: (group, groupIndex, rod, rodIndex) {
|
||||||
return BarTooltipItem(
|
return BarTooltipItem(
|
||||||
'$currency${rod.toY.toStringAsFixed(2)}',
|
'$currency${rod.toY.toStringAsFixed(2)}',
|
||||||
const TextStyle(
|
TextStyle(
|
||||||
color: Colors.white,
|
color: Theme.of(context).colorScheme.onPrimary,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
),
|
),
|
||||||
@@ -343,8 +340,8 @@ class _BarChartCard extends StatelessWidget {
|
|||||||
padding: const EdgeInsets.only(top: 8),
|
padding: const EdgeInsets.only(top: 8),
|
||||||
child: Text(
|
child: Text(
|
||||||
DateFormat('MMM').format(month),
|
DateFormat('MMM').format(month),
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
color: AppColors.textSecondary,
|
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.6),
|
||||||
fontSize: 11,
|
fontSize: 11,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -369,7 +366,7 @@ class _BarChartCard extends StatelessWidget {
|
|||||||
drawVerticalLine: false,
|
drawVerticalLine: false,
|
||||||
horizontalInterval: adjustedMaxY > 0 ? adjustedMaxY / 4 : 25,
|
horizontalInterval: adjustedMaxY > 0 ? adjustedMaxY / 4 : 25,
|
||||||
getDrawingHorizontalLine: (value) => FlLine(
|
getDrawingHorizontalLine: (value) => FlLine(
|
||||||
color: AppColors.divider,
|
color: Theme.of(context).dividerColor,
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -422,9 +419,8 @@ class _CategoryRow extends StatelessWidget {
|
|||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(14),
|
padding: const EdgeInsets.all(14),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: AppColors.surface,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
border: Border.all(color: AppColors.divider),
|
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
@@ -435,13 +431,13 @@ class _CategoryRow extends StatelessWidget {
|
|||||||
height: 28,
|
height: 28,
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: rank <= 3 ? color.withOpacity(0.2) : AppColors.divider,
|
color: rank <= 3 ? color.withOpacity(0.2) : Theme.of(context).dividerColor,
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
'$rank',
|
'$rank',
|
||||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||||
color: rank <= 3 ? color : AppColors.textSecondary,
|
color: rank <= 3 ? color : Theme.of(context).colorScheme.onSurface.withOpacity(0.6),
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -461,7 +457,7 @@ class _CategoryRow extends StatelessWidget {
|
|||||||
category,
|
category,
|
||||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: AppColors.textPrimary,
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -478,7 +474,7 @@ class _CategoryRow extends StatelessWidget {
|
|||||||
Text(
|
Text(
|
||||||
'${(pct * 100).toStringAsFixed(1)}%',
|
'${(pct * 100).toStringAsFixed(1)}%',
|
||||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||||
color: AppColors.textSecondary,
|
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.6),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -490,7 +486,7 @@ class _CategoryRow extends StatelessWidget {
|
|||||||
borderRadius: BorderRadius.circular(4),
|
borderRadius: BorderRadius.circular(4),
|
||||||
child: LinearProgressIndicator(
|
child: LinearProgressIndicator(
|
||||||
value: pct,
|
value: pct,
|
||||||
backgroundColor: AppColors.divider,
|
backgroundColor: Theme.of(context).dividerColor,
|
||||||
valueColor: AlwaysStoppedAnimation<Color>(color),
|
valueColor: AlwaysStoppedAnimation<Color>(color),
|
||||||
minHeight: 6,
|
minHeight: 6,
|
||||||
),
|
),
|
||||||
@@ -512,21 +508,21 @@ class _EmptyState extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.all(24),
|
padding: const EdgeInsets.all(24),
|
||||||
decoration: const BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: AppColors.surface,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
),
|
),
|
||||||
child: const Icon(
|
child: Icon(
|
||||||
Icons.pie_chart_outline_rounded,
|
Icons.pie_chart_outline_rounded,
|
||||||
size: 48,
|
size: 48,
|
||||||
color: AppColors.textSecondary,
|
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.6),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Text(
|
Text(
|
||||||
'No expense data',
|
'No expense data',
|
||||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||||
color: AppColors.textPrimary,
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -534,7 +530,7 @@ class _EmptyState extends StatelessWidget {
|
|||||||
Text(
|
Text(
|
||||||
'Add some expenses to see the breakdown',
|
'Add some expenses to see the breakdown',
|
||||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||||
color: AppColors.textSecondary,
|
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.6),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -17,6 +17,11 @@ class DashboardScreen extends ConsumerStatefulWidget {
|
|||||||
class _DashboardScreenState extends ConsumerState<DashboardScreen> {
|
class _DashboardScreenState extends ConsumerState<DashboardScreen> {
|
||||||
final _searchController = TextEditingController();
|
final _searchController = TextEditingController();
|
||||||
|
|
||||||
|
Border? _themeBorder(BuildContext context) {
|
||||||
|
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||||
|
return isDark ? null : Border.all(color: const Color(0xFFDDDDEE), width: 1);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_searchController.dispose();
|
_searchController.dispose();
|
||||||
@@ -63,16 +68,15 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
actions: [
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.add_circle_rounded),
|
|
||||||
iconSize: 32,
|
|
||||||
color: AppColors.accent,
|
|
||||||
onPressed: () => context.push('/add'),
|
|
||||||
tooltip: 'Add Transaction',
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
|
floatingActionButton: FloatingActionButton.extended(
|
||||||
|
onPressed: () => context.push('/add'),
|
||||||
|
backgroundColor: const Color(0xFF7C6DED),
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
icon: const Icon(Icons.add),
|
||||||
|
label: const Text('Add', style: TextStyle(fontWeight: FontWeight.w600)),
|
||||||
|
),
|
||||||
|
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: CustomScrollView(
|
child: CustomScrollView(
|
||||||
cacheExtent: 300,
|
cacheExtent: 300,
|
||||||
@@ -129,6 +133,7 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
const SliverPadding(padding: EdgeInsets.only(bottom: 80)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -244,6 +249,11 @@ class _BudgetProgress extends StatelessWidget {
|
|||||||
final CurrencyInfo currencyInfo;
|
final CurrencyInfo currencyInfo;
|
||||||
const _BudgetProgress({required this.spent, required this.budget, required this.currencyInfo});
|
const _BudgetProgress({required this.spent, required this.budget, required this.currencyInfo});
|
||||||
|
|
||||||
|
Border? _themeBorder(BuildContext context) {
|
||||||
|
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||||
|
return isDark ? null : Border.all(color: const Color(0xFFDDDDEE), width: 1);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final ratio = spent / budget;
|
final ratio = spent / budget;
|
||||||
@@ -258,7 +268,7 @@ class _BudgetProgress extends StatelessWidget {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
border: Border.all(color: Theme.of(context).dividerColor),
|
border: _themeBorder(context),
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@@ -436,6 +446,11 @@ class _SummaryCard extends StatelessWidget {
|
|||||||
final CurrencyInfo currencyInfo;
|
final CurrencyInfo currencyInfo;
|
||||||
const _SummaryCard({required this.label, required this.amount, required this.color, required this.icon, required this.currencyInfo});
|
const _SummaryCard({required this.label, required this.amount, required this.color, required this.icon, required this.currencyInfo});
|
||||||
|
|
||||||
|
Border? _themeBorder(BuildContext context) {
|
||||||
|
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||||
|
return isDark ? null : Border.all(color: const Color(0xFFDDDDEE), width: 1);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
@@ -443,7 +458,7 @@ class _SummaryCard extends StatelessWidget {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
border: Border.all(color: Theme.of(context).dividerColor),
|
border: _themeBorder(context),
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
@@ -483,6 +498,11 @@ class _TransactionTile extends StatelessWidget {
|
|||||||
final Transaction transaction;
|
final Transaction transaction;
|
||||||
const _TransactionTile({required this.transaction});
|
const _TransactionTile({required this.transaction});
|
||||||
|
|
||||||
|
Border? _themeBorder(BuildContext context) {
|
||||||
|
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||||
|
return isDark ? null : Border.all(color: const Color(0xFFDDDDEE), width: 1);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final isIncome = transaction.type == TransactionType.income;
|
final isIncome = transaction.type == TransactionType.income;
|
||||||
@@ -497,7 +517,7 @@ class _TransactionTile extends StatelessWidget {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
border: Border.all(color: Theme.of(context).dividerColor),
|
border: _themeBorder(context),
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
Reference in New Issue
Block a user