Added theme, reworked UI
This commit is contained in:
11
lib/app.dart
11
lib/app.dart
@@ -4,6 +4,7 @@ import 'package:flutter_localizations/flutter_localizations.dart';
|
|||||||
import 'package:tunas/clients/storage/storage_client.dart';
|
import 'package:tunas/clients/storage/storage_client.dart';
|
||||||
import 'package:tunas/pages/home/home_page.dart';
|
import 'package:tunas/pages/home/home_page.dart';
|
||||||
import 'package:tunas/repositories/account/account_repository.dart';
|
import 'package:tunas/repositories/account/account_repository.dart';
|
||||||
|
import 'package:tunas/theme.dart';
|
||||||
|
|
||||||
class App extends StatefulWidget {
|
class App extends StatefulWidget {
|
||||||
const App({super.key});
|
const App({super.key});
|
||||||
@@ -44,13 +45,9 @@ class _AppViewState extends State<AppView> {
|
|||||||
providers: [RepositoryProvider.value(value: _accountRepository)],
|
providers: [RepositoryProvider.value(value: _accountRepository)],
|
||||||
child: MaterialApp(
|
child: MaterialApp(
|
||||||
title: 'Tunas',
|
title: 'Tunas',
|
||||||
theme: ThemeData(
|
theme: ThemeData(useMaterial3: true, colorScheme: lightColorScheme),
|
||||||
colorScheme: ColorScheme.fromSeed(
|
darkTheme: ThemeData(useMaterial3: true, colorScheme: darkColorScheme),
|
||||||
seedColor: const Color.fromARGB(255, 55, 55, 55),
|
themeMode: ThemeMode.dark,
|
||||||
brightness: Brightness.dark
|
|
||||||
),
|
|
||||||
useMaterial3: true
|
|
||||||
),
|
|
||||||
initialRoute: '/home',
|
initialRoute: '/home',
|
||||||
routes: {
|
routes: {
|
||||||
'/home':(context) => const HomePage(),
|
'/home':(context) => const HomePage(),
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'package:tunas/domains/charts/models/month_totals.dart';
|
|||||||
import 'package:tunas/domains/transaction/models/transaction_line.dart';
|
import 'package:tunas/domains/transaction/models/transaction_line.dart';
|
||||||
import 'package:tunas/domains/charts/models/chart_item.dart';
|
import 'package:tunas/domains/charts/models/chart_item.dart';
|
||||||
import 'package:tunas/repositories/account/account_repository.dart';
|
import 'package:tunas/repositories/account/account_repository.dart';
|
||||||
|
import 'package:tunas/repositories/account/models/category.dart';
|
||||||
import 'package:tunas/repositories/account/models/transaction.dart';
|
import 'package:tunas/repositories/account/models/transaction.dart';
|
||||||
|
|
||||||
part 'chart_event.dart';
|
part 'chart_event.dart';
|
||||||
@@ -16,20 +17,30 @@ class ChartBloc extends Bloc<ChartEvent, ChartState> {
|
|||||||
ChartBloc({required AccountRepository accountRepository}) :
|
ChartBloc({required AccountRepository accountRepository}) :
|
||||||
_accountRepository = accountRepository, super(const ChartState()) {
|
_accountRepository = accountRepository, super(const ChartState()) {
|
||||||
|
|
||||||
on<ChartAccountLoad>(_onAccountLoad);
|
on<ChartTransactionsLoad>(_onChartTransactionsLoad);
|
||||||
|
on<ChartCategoriesLoad>(_onChartCategoriesLoad);
|
||||||
on<ChartNextYear>(_onNextYear);
|
on<ChartNextYear>(_onNextYear);
|
||||||
on<ChartPreviousYear>(_onPreviousYear);
|
on<ChartPreviousYear>(_onPreviousYear);
|
||||||
|
|
||||||
_accountRepository
|
_accountRepository
|
||||||
.getTransactionsStream()
|
.getTransactionsStream()
|
||||||
.listen((transactions) => add(ChartAccountLoad(transactions)));
|
.listen((transactions) => add(ChartTransactionsLoad(transactions)));
|
||||||
|
|
||||||
|
_accountRepository
|
||||||
|
.getCategoriesStream()
|
||||||
|
.listen((categories) => add(ChartCategoriesLoad(categories)));
|
||||||
}
|
}
|
||||||
|
|
||||||
_onAccountLoad(ChartAccountLoad event, Emitter<ChartState> emit) {
|
_onChartTransactionsLoad(ChartTransactionsLoad event, Emitter<ChartState> emit) {
|
||||||
ChartState localState = state.copyWith(transactions: event.transactions);
|
ChartState localState = state.copyWith(transactions: event.transactions);
|
||||||
emit(_computeStateStats(localState));
|
emit(_computeStateStats(localState));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onChartCategoriesLoad(ChartCategoriesLoad event, Emitter<ChartState> emit) {
|
||||||
|
ChartState localState = state.copyWith(categories: Map.fromEntries(event.categories.map((category) => MapEntry(category.label, category))));
|
||||||
|
emit(_computeStateStats(localState));
|
||||||
|
}
|
||||||
|
|
||||||
_onNextYear(ChartNextYear event, Emitter<ChartState> emit) {
|
_onNextYear(ChartNextYear event, Emitter<ChartState> emit) {
|
||||||
if (state.lastDate!.year >= state.currentYear + 1) {
|
if (state.lastDate!.year >= state.currentYear + 1) {
|
||||||
ChartState localState = state.copyWith(currentYear: state.currentYear + 1);
|
ChartState localState = state.copyWith(currentYear: state.currentYear + 1);
|
||||||
@@ -123,7 +134,8 @@ class ChartBloc extends Bloc<ChartEvent, ChartState> {
|
|||||||
|
|
||||||
scopedMonthlyTotals[transactionDateDay] = FlSpot(transactionDateDay.toDouble(), transactionLine.subTotal);
|
scopedMonthlyTotals[transactionDateDay] = FlSpot(transactionDateDay.toDouble(), transactionLine.subTotal);
|
||||||
|
|
||||||
if (transaction.category.isEmpty) {
|
final category = state.categories[transaction.category];
|
||||||
|
if (category == null || category.saving) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,15 +213,20 @@ class ChartBloc extends Bloc<ChartEvent, ChartState> {
|
|||||||
List<ChartItem> scopedSimplifiedCategoriesPositiveTotals = [];
|
List<ChartItem> scopedSimplifiedCategoriesPositiveTotals = [];
|
||||||
List<ChartItem> scopedSimplifiedCategoriesNegativeTotals = [];
|
List<ChartItem> scopedSimplifiedCategoriesNegativeTotals = [];
|
||||||
|
|
||||||
scopedCategoriesPositiveTotals.sort((a, b) => a.value.compareTo(b.value));
|
scopedCategoriesPositiveTotals.sort((a, b) => b.value.compareTo(a.value));
|
||||||
scopedCategoriesPositiveTotalsPercents.sort((a, b) => a.value.compareTo(b.value));
|
scopedCategoriesPositiveTotalsPercents.sort((a, b) => b.value.compareTo(a.value));
|
||||||
scopedCategoriesNegativeTotals.sort((a, b) => a.value.compareTo(b.value));
|
scopedCategoriesNegativeTotals.sort((a, b) => a.value.compareTo(b.value));
|
||||||
scopedCategoriesNegativeTotalsPercents.sort((a, b) => a.value.compareTo(b.value));
|
scopedCategoriesNegativeTotalsPercents.sort((a, b) => a.value.compareTo(b.value));
|
||||||
scopedSimplifiedCategoriesPositiveTotals.sort((a, b) => a.value.compareTo(b.value));
|
scopedSimplifiedCategoriesPositiveTotals.sort((a, b) => b.value.compareTo(a.value));
|
||||||
scopedSimplifiedCategoriesPositiveTotalsPercents.sort((a, b) => a.value.compareTo(b.value));
|
scopedSimplifiedCategoriesPositiveTotalsPercents.sort((a, b) => b.value.compareTo(a.value));
|
||||||
scopedSimplifiedCategoriesNegativeTotals.sort((a, b) => a.value.compareTo(b.value));
|
scopedSimplifiedCategoriesNegativeTotals.sort((a, b) => a.value.compareTo(b.value));
|
||||||
scopedSimplifiedCategoriesNegativeTotalsPercents.sort((a, b) => a.value.compareTo(b.value));
|
scopedSimplifiedCategoriesNegativeTotalsPercents.sort((a, b) => a.value.compareTo(b.value));
|
||||||
|
|
||||||
|
for (var monthTotals in scopedCategoriesMonthlyTotals.values) {
|
||||||
|
_sortMapByValues(monthTotals.positives);
|
||||||
|
_sortMapByValues(monthTotals.negatives);
|
||||||
|
}
|
||||||
|
|
||||||
return state.copyWith(
|
return state.copyWith(
|
||||||
scoppedProfit: scoppedTotal,
|
scoppedProfit: scoppedTotal,
|
||||||
scopedCategoriesPositiveTotals: scopedCategoriesPositiveTotals,
|
scopedCategoriesPositiveTotals: scopedCategoriesPositiveTotals,
|
||||||
@@ -226,4 +243,15 @@ class ChartBloc extends Bloc<ChartEvent, ChartState> {
|
|||||||
scopedMonthlyNegativeTotals: scopedMonthlyNegativeTotals,
|
scopedMonthlyNegativeTotals: scopedMonthlyNegativeTotals,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Map<dynamic, dynamic> _sortMapByValues(Map<dynamic, dynamic> map) {
|
||||||
|
final sortedEntries = map.entries.toList()..sort((a, b) {
|
||||||
|
var diff = b.value.compareTo(a.value);
|
||||||
|
return diff;
|
||||||
|
});
|
||||||
|
|
||||||
|
return map
|
||||||
|
..clear()
|
||||||
|
..addEntries(sortedEntries);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,13 +7,21 @@ sealed class ChartEvent extends Equatable {
|
|||||||
List<Object> get props => [];
|
List<Object> get props => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
final class ChartAccountLoad extends ChartEvent {
|
final class ChartTransactionsLoad extends ChartEvent {
|
||||||
final List<Transaction> transactions;
|
final List<Transaction> transactions;
|
||||||
const ChartAccountLoad(this.transactions);
|
const ChartTransactionsLoad(this.transactions);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [transactions];
|
List<Object> get props => [transactions];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final class ChartCategoriesLoad extends ChartEvent {
|
||||||
|
final List<Category> categories;
|
||||||
|
const ChartCategoriesLoad(this.categories);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [categories];
|
||||||
|
}
|
||||||
|
|
||||||
final class ChartNextYear extends ChartEvent {}
|
final class ChartNextYear extends ChartEvent {}
|
||||||
final class ChartPreviousYear extends ChartEvent {}
|
final class ChartPreviousYear extends ChartEvent {}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
part of 'chart_bloc.dart';
|
part of 'chart_bloc.dart';
|
||||||
|
|
||||||
final class ChartState extends Equatable {
|
final class ChartState extends Equatable {
|
||||||
|
final Map<String, Category> categories;
|
||||||
final List<Transaction> transactions;
|
final List<Transaction> transactions;
|
||||||
final List<TransactionLine> transactionsLines;
|
final List<TransactionLine> transactionsLines;
|
||||||
|
|
||||||
@@ -34,6 +35,7 @@ final class ChartState extends Equatable {
|
|||||||
final double scoppedProfit;
|
final double scoppedProfit;
|
||||||
|
|
||||||
const ChartState({
|
const ChartState({
|
||||||
|
this.categories = const {},
|
||||||
this.transactions = const [],
|
this.transactions = const [],
|
||||||
this.transactionsLines = const [],
|
this.transactionsLines = const [],
|
||||||
this.globalTotal = 0,
|
this.globalTotal = 0,
|
||||||
@@ -60,6 +62,7 @@ final class ChartState extends Equatable {
|
|||||||
});
|
});
|
||||||
|
|
||||||
ChartState copyWith({
|
ChartState copyWith({
|
||||||
|
Map<String, Category>? categories,
|
||||||
List<Transaction>? transactions,
|
List<Transaction>? transactions,
|
||||||
List<TransactionLine>? transactionsLines,
|
List<TransactionLine>? transactionsLines,
|
||||||
double? globalTotal,
|
double? globalTotal,
|
||||||
@@ -85,6 +88,7 @@ final class ChartState extends Equatable {
|
|||||||
Map<int, double>? scopedMonthlyNegativeTotals,
|
Map<int, double>? scopedMonthlyNegativeTotals,
|
||||||
}) {
|
}) {
|
||||||
return ChartState(
|
return ChartState(
|
||||||
|
categories: categories ?? this.categories,
|
||||||
transactions: transactions ?? this.transactions,
|
transactions: transactions ?? this.transactions,
|
||||||
transactionsLines: transactionsLines ?? this.transactionsLines,
|
transactionsLines: transactionsLines ?? this.transactionsLines,
|
||||||
globalTotal: globalTotal ?? this.globalTotal,
|
globalTotal: globalTotal ?? this.globalTotal,
|
||||||
@@ -113,6 +117,7 @@ final class ChartState extends Equatable {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [
|
List<Object> get props => [
|
||||||
|
categories,
|
||||||
transactions,
|
transactions,
|
||||||
transactionsLines,
|
transactionsLines,
|
||||||
globalTotal,
|
globalTotal,
|
||||||
|
|||||||
57
lib/pages/common/titled_container.dart
Normal file
57
lib/pages/common/titled_container.dart
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class TitledContainer extends StatelessWidget {
|
||||||
|
final String title;
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
const TitledContainer({super.key, required this.title, required this.child});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).colorScheme.primaryContainer,
|
||||||
|
borderRadius: BorderRadius.circular(15),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Theme.of(context).colorScheme.shadow,
|
||||||
|
blurRadius: 10,
|
||||||
|
offset: const Offset(2, 2),
|
||||||
|
spreadRadius: 0.1,
|
||||||
|
blurStyle: BlurStyle.normal,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
margin: const EdgeInsets.symmetric(vertical: 10, horizontal: 0),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).colorScheme.secondaryContainer,
|
||||||
|
borderRadius: const BorderRadius.only(topLeft: Radius.circular(15), topRight: Radius.circular(15)),
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 15),
|
||||||
|
child: Text(
|
||||||
|
title,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.w300,
|
||||||
|
fontSize: 20,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15),
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,24 +15,25 @@ class DataPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
padding: const EdgeInsets.symmetric(vertical: 9, horizontal: 10),
|
padding: const EdgeInsets.symmetric(vertical: 9, horizontal: 10),
|
||||||
margin: const EdgeInsets.symmetric(vertical: 2, horizontal: 10),
|
margin: const EdgeInsets.symmetric(vertical: 2, horizontal: 10),
|
||||||
child: const Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
const Text(
|
||||||
'Settings',
|
'Settings',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w900,
|
fontWeight: FontWeight.w900,
|
||||||
fontSize: 35,
|
fontSize: 35,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Row(
|
Expanded(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
child: ListView(
|
||||||
children: [
|
children: const [
|
||||||
ImportSettings(),
|
ImportSettings(),
|
||||||
CategoriesSettings(),
|
CategoriesSettings(),
|
||||||
AccountSettings(),
|
AccountSettings(),
|
||||||
],
|
]
|
||||||
)
|
)
|
||||||
|
),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:tunas/domains/account/account_bloc.dart';
|
import 'package:tunas/domains/account/account_bloc.dart';
|
||||||
|
import 'package:tunas/pages/common/titled_container.dart';
|
||||||
|
|
||||||
class AccountSettings extends StatelessWidget {
|
class AccountSettings extends StatelessWidget {
|
||||||
const AccountSettings({super.key});
|
const AccountSettings({super.key});
|
||||||
@@ -16,34 +17,15 @@ class AccountSettings extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<AccountBloc, AccountState>(
|
return BlocBuilder<AccountBloc, AccountState>(
|
||||||
builder: (context, state) => Container(
|
builder: (context, state) => TitledContainer(
|
||||||
decoration: BoxDecoration(
|
title: "Accounts",
|
||||||
color: Colors.blue,
|
child: SingleChildScrollView(
|
||||||
borderRadius: BorderRadius.circular(5),
|
|
||||||
),
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15),
|
|
||||||
margin: const EdgeInsets.all(5),
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
const Text(
|
|
||||||
"Accounts",
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight: FontWeight.w900,
|
|
||||||
fontSize: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
SingleChildScrollView(
|
|
||||||
scrollDirection: Axis.vertical,
|
scrollDirection: Axis.vertical,
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: _computeCategoryList(state.subAccounts),
|
children: _computeCategoryList(state.subAccounts),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,42 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:tunas/domains/category/category_bloc.dart';
|
import 'package:tunas/domains/category/category_bloc.dart';
|
||||||
|
import 'package:tunas/pages/common/titled_container.dart';
|
||||||
import 'package:tunas/repositories/account/models/category.dart';
|
import 'package:tunas/repositories/account/models/category.dart';
|
||||||
|
|
||||||
class CategoriesSettings extends StatelessWidget {
|
class CategoriesSettings extends StatelessWidget {
|
||||||
const CategoriesSettings({super.key});
|
const CategoriesSettings({super.key});
|
||||||
|
|
||||||
List<Widget> _computeCategoryList(List<Category> categories) {
|
List<Widget> _computeCategoryList(BuildContext context, List<Category> categories) {
|
||||||
return categories.map((category) => Row(
|
return categories.map((category) => Row(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
IconButton(
|
||||||
height: 10,
|
onPressed: () {},
|
||||||
width: 10,
|
icon: const Icon(Icons.palette),
|
||||||
color: category.rgbToColor(),
|
color: category.rgbToColor(),
|
||||||
),
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {},
|
||||||
|
icon: const Icon(Icons.savings),
|
||||||
|
color: category.saving ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.error,
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {},
|
||||||
|
icon: const Icon(Icons.foundation),
|
||||||
|
color: category.essential ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.error,
|
||||||
|
),
|
||||||
Container(width: 5),
|
Container(width: 5),
|
||||||
Text(category.label),
|
Expanded(
|
||||||
|
child: Text(category.label)
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {},
|
||||||
|
icon: const Icon(Icons.edit),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {},
|
||||||
|
icon: const Icon(Icons.delete),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)).toList();
|
)).toList();
|
||||||
}
|
}
|
||||||
@@ -23,35 +44,16 @@ class CategoriesSettings extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<CategoryBloc, CategoryState>(
|
return BlocBuilder<CategoryBloc, CategoryState>(
|
||||||
builder: (context, state) => Container(
|
builder: (context, state) => TitledContainer(
|
||||||
decoration: BoxDecoration(
|
title: "Categories",
|
||||||
color: Colors.blue,
|
child: SingleChildScrollView(
|
||||||
borderRadius: BorderRadius.circular(5),
|
|
||||||
),
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15),
|
|
||||||
margin: const EdgeInsets.all(5),
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
const Text(
|
|
||||||
"Categories",
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight: FontWeight.w900,
|
|
||||||
fontSize: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
SingleChildScrollView(
|
|
||||||
scrollDirection: Axis.vertical,
|
scrollDirection: Axis.vertical,
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: _computeCategoryList(state.categories),
|
children: _computeCategoryList(context, state.categories),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
|
||||||
)
|
)
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:tunas/domains/account/account_bloc.dart';
|
import 'package:tunas/domains/account/account_bloc.dart';
|
||||||
|
import 'package:tunas/pages/common/titled_container.dart';
|
||||||
|
|
||||||
class ImportSettings extends StatelessWidget {
|
class ImportSettings extends StatelessWidget {
|
||||||
const ImportSettings({super.key});
|
const ImportSettings({super.key});
|
||||||
@@ -8,25 +9,10 @@ class ImportSettings extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<AccountBloc, AccountState>(
|
return BlocBuilder<AccountBloc, AccountState>(
|
||||||
builder: (context, state) => Container(
|
builder: (context, state) => TitledContainer(
|
||||||
decoration: BoxDecoration(
|
title: "Import",
|
||||||
color: Colors.blue,
|
|
||||||
borderRadius: BorderRadius.circular(5)
|
|
||||||
),
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15),
|
|
||||||
margin: const EdgeInsets.all(5),
|
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
children: [
|
||||||
const Text(
|
|
||||||
"Import",
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight: FontWeight.w900,
|
|
||||||
fontSize: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
FilledButton(
|
FilledButton(
|
||||||
onPressed: () => context.read<AccountBloc>().add(const AccountImportCSV()),
|
onPressed: () => context.read<AccountBloc>().add(const AccountImportCSV()),
|
||||||
child: const Text('Import CSV')
|
child: const Text('Import CSV')
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:tunas/domains/charts/chart_bloc.dart';
|
import 'package:tunas/domains/charts/chart_bloc.dart';
|
||||||
import 'package:tunas/pages/stats/widgets/account_counters.dart';
|
import 'package:tunas/pages/stats/widgets/account_counters.dart';
|
||||||
import 'package:tunas/pages/stats/widgets/categories_totals_chart.dart';
|
import 'package:tunas/pages/stats/widgets/categories_totals_chart.dart';
|
||||||
import 'package:tunas/pages/stats/widgets/main_counter.dart';
|
import 'package:tunas/pages/stats/widgets/global_counter.dart';
|
||||||
import 'package:tunas/pages/stats/widgets/monthly_categories_total_chart.dart';
|
import 'package:tunas/pages/stats/widgets/monthly_categories_total_chart.dart';
|
||||||
import 'package:tunas/pages/stats/widgets/monthly_total_chart.dart';
|
import 'package:tunas/pages/stats/widgets/global_total_chart.dart';
|
||||||
import 'package:tunas/pages/stats/widgets/profit_indicator.dart';
|
import 'package:tunas/pages/stats/widgets/profit_indicator.dart';
|
||||||
import 'package:tunas/pages/stats/widgets/year_selector.dart';
|
import 'package:tunas/pages/stats/widgets/year_selector.dart';
|
||||||
import 'package:tunas/repositories/account/account_repository.dart';
|
import 'package:tunas/repositories/account/account_repository.dart';
|
||||||
@@ -31,7 +31,7 @@ class StatsPage extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: MainCounter(value: state.globalTotal)
|
child: GlobalCounter(value: state.globalTotal)
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ class AccountCounter extends StatelessWidget {
|
|||||||
|
|
||||||
const AccountCounter({super.key, required this.accountsTotals});
|
const AccountCounter({super.key, required this.accountsTotals});
|
||||||
|
|
||||||
List<Row> _renderAccountTotals() {
|
List<Row> _renderAccountTotals(BuildContext context) {
|
||||||
return accountsTotals.entries.toList().map((entry) => Row(
|
return accountsTotals.entries.toList().map((entry) => Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
@@ -21,7 +21,7 @@ class AccountCounter extends StatelessWidget {
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'NovaMono',
|
fontFamily: 'NovaMono',
|
||||||
fontSize: 15,
|
fontSize: 15,
|
||||||
color: entry.value > 0 ? const Color.fromARGB(255, 0, 255, 8) : Colors.red
|
color: entry.value > 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.error
|
||||||
)),
|
)),
|
||||||
],
|
],
|
||||||
)).toList();
|
)).toList();
|
||||||
@@ -33,13 +33,22 @@ class AccountCounter extends StatelessWidget {
|
|||||||
padding: const EdgeInsets.all(10),
|
padding: const EdgeInsets.all(10),
|
||||||
margin: const EdgeInsets.all(20),
|
margin: const EdgeInsets.all(20),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(5),
|
borderRadius: BorderRadius.circular(15),
|
||||||
color: Colors.blue
|
color: Theme.of(context).colorScheme.primaryContainer,
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Theme.of(context).colorScheme.shadow,
|
||||||
|
blurRadius: 10,
|
||||||
|
offset: const Offset(2, 2),
|
||||||
|
spreadRadius: 0.1,
|
||||||
|
blurStyle: BlurStyle.normal,
|
||||||
|
)
|
||||||
|
]
|
||||||
),
|
),
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
children: _renderAccountTotals(),
|
children: _renderAccountTotals(context),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,10 @@ class CategoriesTotalsChart extends StatelessWidget {
|
|||||||
Container(
|
Container(
|
||||||
height: 10,
|
height: 10,
|
||||||
width: 10,
|
width: 10,
|
||||||
|
decoration: BoxDecoration(
|
||||||
color: categoriesColors[item.label],
|
color: categoriesColors[item.label],
|
||||||
|
borderRadius: BorderRadius.circular(15)
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Container(width: 5),
|
Container(width: 5),
|
||||||
Text(item.label),
|
Text(item.label),
|
||||||
@@ -64,8 +67,17 @@ class CategoriesTotalsChart extends StatelessWidget {
|
|||||||
padding: const EdgeInsets.all(10),
|
padding: const EdgeInsets.all(10),
|
||||||
margin: const EdgeInsets.all(20),
|
margin: const EdgeInsets.all(20),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(5),
|
borderRadius: BorderRadius.circular(15),
|
||||||
color: Colors.blue
|
color: Theme.of(context).colorScheme.primaryContainer,
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Theme.of(context).colorScheme.shadow,
|
||||||
|
blurRadius: 10,
|
||||||
|
offset: const Offset(2, 2),
|
||||||
|
spreadRadius: 0.1,
|
||||||
|
blurStyle: BlurStyle.normal,
|
||||||
|
)
|
||||||
|
]
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
@@ -87,7 +99,7 @@ class CategoriesTotalsChart extends StatelessWidget {
|
|||||||
padding: const EdgeInsets.all(10),
|
padding: const EdgeInsets.all(10),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(5),
|
borderRadius: BorderRadius.circular(5),
|
||||||
color: Colors.blueGrey
|
color: Theme.of(context).colorScheme.secondaryContainer
|
||||||
),
|
),
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
scrollDirection: Axis.vertical,
|
scrollDirection: Axis.vertical,
|
||||||
|
|||||||
39
lib/pages/stats/widgets/global_counter.dart
Normal file
39
lib/pages/stats/widgets/global_counter.dart
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
|
class GlobalCounter extends StatelessWidget {
|
||||||
|
final double value;
|
||||||
|
|
||||||
|
const GlobalCounter({super.key, required this.value});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(10),
|
||||||
|
margin: const EdgeInsets.all(20),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(15),
|
||||||
|
color: Theme.of(context).colorScheme.primaryContainer,
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Theme.of(context).colorScheme.shadow,
|
||||||
|
blurRadius: 10,
|
||||||
|
offset: const Offset(2, 2),
|
||||||
|
spreadRadius: 0.1,
|
||||||
|
blurStyle: BlurStyle.normal,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
child: Text(
|
||||||
|
NumberFormat('000.00 €', 'fr_FR').format(value),
|
||||||
|
style: TextStyle(
|
||||||
|
fontFamily: 'NovaMono',
|
||||||
|
fontSize: 60,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: value > 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.error
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,9 +18,7 @@ class GlobalTotalChart extends StatelessWidget {
|
|||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
left: 12,
|
|
||||||
bottom: 12,
|
bottom: 12,
|
||||||
right: 20,
|
|
||||||
top: 20,
|
top: 20,
|
||||||
),
|
),
|
||||||
child: AspectRatio(
|
child: AspectRatio(
|
||||||
@@ -31,7 +29,7 @@ class GlobalTotalChart extends StatelessWidget {
|
|||||||
lineTouchData: LineTouchData(
|
lineTouchData: LineTouchData(
|
||||||
touchTooltipData: LineTouchTooltipData(
|
touchTooltipData: LineTouchTooltipData(
|
||||||
maxContentWidth: 100,
|
maxContentWidth: 100,
|
||||||
tooltipBgColor: Colors.black,
|
tooltipBgColor: Theme.of(context).colorScheme.primaryContainer,
|
||||||
getTooltipItems: (touchedSpots) {
|
getTooltipItems: (touchedSpots) {
|
||||||
return touchedSpots.map((LineBarSpot touchedSpot) {
|
return touchedSpots.map((LineBarSpot touchedSpot) {
|
||||||
final textStyle = TextStyle(
|
final textStyle = TextStyle(
|
||||||
@@ -52,13 +50,18 @@ class GlobalTotalChart extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
lineBarsData: [
|
lineBarsData: [
|
||||||
LineChartBarData(
|
LineChartBarData(
|
||||||
color: Colors.pink,
|
color: Theme.of(context).colorScheme.primary,
|
||||||
spots: monthlyTotals,
|
spots: monthlyTotals,
|
||||||
isCurved: true,
|
isCurved: true,
|
||||||
isStrokeCapRound: true,
|
isStrokeCapRound: true,
|
||||||
barWidth: 3,
|
barWidth: 3,
|
||||||
belowBarData: BarAreaData(
|
belowBarData: BarAreaData(
|
||||||
show: false,
|
show: true,
|
||||||
|
gradient: LinearGradient(
|
||||||
|
colors: [Theme.of(context).colorScheme.primary, Theme.of(context).colorScheme.secondary]
|
||||||
|
.map((color) => color.withOpacity(0.2))
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
dotData: const FlDotData(show: false),
|
dotData: const FlDotData(show: false),
|
||||||
),
|
),
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:intl/intl.dart';
|
|
||||||
|
|
||||||
class MainCounter extends StatelessWidget {
|
|
||||||
final double value;
|
|
||||||
|
|
||||||
const MainCounter({super.key, required this.value});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Container(
|
|
||||||
padding: const EdgeInsets.all(10),
|
|
||||||
margin: const EdgeInsets.all(20),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(5),
|
|
||||||
color: Colors.blue
|
|
||||||
),
|
|
||||||
alignment: Alignment.centerRight,
|
|
||||||
child: Text(
|
|
||||||
NumberFormat('000.00 €', 'fr_FR').format(value),
|
|
||||||
style: TextStyle(
|
|
||||||
fontFamily: 'NovaMono',
|
|
||||||
fontSize: 60,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
color: value > 0 ? const Color.fromARGB(255, 0, 255, 8) : Colors.red
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -100,10 +100,10 @@ class MonthlyCategoriesTotalChart extends StatelessWidget {
|
|||||||
Color color = Colors.black;
|
Color color = Colors.black;
|
||||||
if (rodIndex == 0) {
|
if (rodIndex == 0) {
|
||||||
value = "+$value";
|
value = "+$value";
|
||||||
color = Colors.green;
|
color = Theme.of(context).colorScheme.primary;
|
||||||
} else {
|
} else {
|
||||||
value = "-$value";
|
value = "-$value";
|
||||||
color = Colors.red;
|
color = Theme.of(context).colorScheme.error;
|
||||||
}
|
}
|
||||||
|
|
||||||
return BarTooltipItem(
|
return BarTooltipItem(
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class ProfitIndicator extends StatelessWidget {
|
|||||||
margin: const EdgeInsets.fromLTRB(0, 0, 20, 0),
|
margin: const EdgeInsets.fromLTRB(0, 0, 20, 0),
|
||||||
padding: const EdgeInsets.fromLTRB(10, 5, 10, 5),
|
padding: const EdgeInsets.fromLTRB(10, 5, 10, 5),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.blue,
|
color: Theme.of(context).colorScheme.primaryContainer,
|
||||||
borderRadius: BorderRadius.circular(5)
|
borderRadius: BorderRadius.circular(5)
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
@@ -22,7 +22,7 @@ class ProfitIndicator extends StatelessWidget {
|
|||||||
fontFamily: 'NovaMono',
|
fontFamily: 'NovaMono',
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: profit > 0 ? const Color.fromARGB(255, 0, 255, 8) : Colors.red
|
color: profit > 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.error
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ class YearSelector extends StatelessWidget {
|
|||||||
margin: const EdgeInsets.fromLTRB(20, 0, 0, 0),
|
margin: const EdgeInsets.fromLTRB(20, 0, 0, 0),
|
||||||
padding: const EdgeInsets.fromLTRB(5, 0, 5, 0),
|
padding: const EdgeInsets.fromLTRB(5, 0, 5, 0),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.blue,
|
color: Theme.of(context).colorScheme.primaryContainer,
|
||||||
borderRadius: BorderRadius.circular(5)
|
borderRadius: BorderRadius.circular(5),
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@@ -48,13 +48,13 @@ class TransactionLine extends StatelessWidget {
|
|||||||
Text(
|
Text(
|
||||||
NumberFormat(transaction.value > 0 ? '+#######.00 €' : '#######.00 €', 'fr_FR').format(transaction.value),
|
NumberFormat(transaction.value > 0 ? '+#######.00 €' : '#######.00 €', 'fr_FR').format(transaction.value),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: transaction.value > 0 ? Colors.green : Colors.red
|
color: transaction.value > 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.error
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
NumberFormat('#######.00 €', 'fr_FR').format(subTotal),
|
NumberFormat('#######.00 €', 'fr_FR').format(subTotal),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: subTotal > 0 ? Colors.green : Colors.red
|
color: subTotal > 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.error
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -3,22 +3,30 @@ import 'dart:ui';
|
|||||||
class Category {
|
class Category {
|
||||||
String label;
|
String label;
|
||||||
String color;
|
String color;
|
||||||
|
bool essential;
|
||||||
|
bool saving;
|
||||||
|
|
||||||
Category({
|
Category({
|
||||||
this.label = '',
|
this.label = '',
|
||||||
this.color = '',
|
this.color = '',
|
||||||
|
this.essential = false,
|
||||||
|
this.saving = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory Category.fromJson(Map<String, dynamic> json) {
|
factory Category.fromJson(Map<String, dynamic> json) {
|
||||||
return Category(
|
return Category(
|
||||||
label: json['label'],
|
label: json['label'],
|
||||||
color: json['color']
|
color: json['color'],
|
||||||
|
essential: bool.parse(json['essential']),
|
||||||
|
saving: bool.parse(json['saving']),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String> toJson() => {
|
Map<String, String> toJson() => {
|
||||||
'label': label,
|
'label': label,
|
||||||
'color': color,
|
'color': color,
|
||||||
|
'essential': essential.toString(),
|
||||||
|
'saving': saving.toString(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Color rgbToColor() {
|
Color rgbToColor() {
|
||||||
|
|||||||
69
lib/theme.dart
Normal file
69
lib/theme.dart
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
const lightColorScheme = ColorScheme(
|
||||||
|
brightness: Brightness.light,
|
||||||
|
primary: Color(0xFF006C45),
|
||||||
|
onPrimary: Color(0xFFFFFFFF),
|
||||||
|
primaryContainer: Color(0xFF51FFB1),
|
||||||
|
onPrimaryContainer: Color(0xFF002112),
|
||||||
|
secondary: Color(0xFF4E6355),
|
||||||
|
onSecondary: Color(0xFFFFFFFF),
|
||||||
|
secondaryContainer: Color(0xFFD0E8D7),
|
||||||
|
onSecondaryContainer: Color(0xFF0B1F15),
|
||||||
|
tertiary: Color(0xFF3C6472),
|
||||||
|
onTertiary: Color(0xFFFFFFFF),
|
||||||
|
tertiaryContainer: Color(0xFFBFE9F9),
|
||||||
|
onTertiaryContainer: Color(0xFF001F28),
|
||||||
|
error: Color(0xFFBA1A1A),
|
||||||
|
errorContainer: Color(0xFFFFDAD6),
|
||||||
|
onError: Color(0xFFFFFFFF),
|
||||||
|
onErrorContainer: Color(0xFF410002),
|
||||||
|
background: Color(0xFFFBFDF8),
|
||||||
|
onBackground: Color(0xFF191C1A),
|
||||||
|
surface: Color(0xFFFBFDF8),
|
||||||
|
onSurface: Color(0xFF191C1A),
|
||||||
|
surfaceVariant: Color(0xFFDCE5DC),
|
||||||
|
onSurfaceVariant: Color(0xFF404943),
|
||||||
|
outline: Color(0xFF707972),
|
||||||
|
onInverseSurface: Color(0xFFEFF1ED),
|
||||||
|
inverseSurface: Color(0xFF2E312E),
|
||||||
|
inversePrimary: Color(0xFF21E297),
|
||||||
|
shadow: Color(0xFF000000),
|
||||||
|
surfaceTint: Color(0xFF006C45),
|
||||||
|
outlineVariant: Color(0xFFC0C9C1),
|
||||||
|
scrim: Color(0xFF000000),
|
||||||
|
);
|
||||||
|
|
||||||
|
const darkColorScheme = ColorScheme(
|
||||||
|
brightness: Brightness.dark,
|
||||||
|
primary: Color(0xFF21E297),
|
||||||
|
onPrimary: Color(0xFF003822),
|
||||||
|
primaryContainer: Color(0xFF005233),
|
||||||
|
onPrimaryContainer: Color(0xFF51FFB1),
|
||||||
|
secondary: Color(0xFFB4CCBB),
|
||||||
|
onSecondary: Color(0xFF203529),
|
||||||
|
secondaryContainer: Color(0xFF364B3E),
|
||||||
|
onSecondaryContainer: Color(0xFFD0E8D7),
|
||||||
|
tertiary: Color(0xFFA4CDDD),
|
||||||
|
onTertiary: Color(0xFF043542),
|
||||||
|
tertiaryContainer: Color(0xFF234C59),
|
||||||
|
onTertiaryContainer: Color(0xFFBFE9F9),
|
||||||
|
error: Color(0xFFFFB4AB),
|
||||||
|
errorContainer: Color(0xFF93000A),
|
||||||
|
onError: Color(0xFF690005),
|
||||||
|
onErrorContainer: Color(0xFFFFDAD6),
|
||||||
|
background: Color(0xFF191C1A),
|
||||||
|
onBackground: Color(0xFFE1E3DF),
|
||||||
|
surface: Color(0xFF191C1A),
|
||||||
|
onSurface: Color(0xFFE1E3DF),
|
||||||
|
surfaceVariant: Color(0xFF404943),
|
||||||
|
onSurfaceVariant: Color(0xFFC0C9C1),
|
||||||
|
outline: Color(0xFF8A938B),
|
||||||
|
onInverseSurface: Color(0xFF191C1A),
|
||||||
|
inverseSurface: Color(0xFFE1E3DF),
|
||||||
|
inversePrimary: Color(0xFF006C45),
|
||||||
|
shadow: Color(0xFF000000),
|
||||||
|
surfaceTint: Color(0xFF21E297),
|
||||||
|
outlineVariant: Color(0xFF404943),
|
||||||
|
scrim: Color(0xFF000000),
|
||||||
|
);
|
||||||
20
pubspec.lock
20
pubspec.lock
@@ -121,6 +121,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.65.0"
|
version: "0.65.0"
|
||||||
|
flex_color_picker:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flex_color_picker
|
||||||
|
sha256: "0871edc170153cfc3de316d30625f40a85daecfa76ce541641f3cc0ec7757cbf"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.3.1"
|
||||||
|
flex_seed_scheme:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flex_seed_scheme
|
||||||
|
sha256: "29c12aba221eb8a368a119685371381f8035011d18de5ba277ad11d7dfb8657f"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.4.0"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@@ -130,10 +146,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_bloc
|
name: flutter_bloc
|
||||||
sha256: e74efb89ee6945bcbce74a5b3a5a3376b088e5f21f55c263fc38cbdc6237faae
|
sha256: "87325da1ac757fcc4813e6b34ed5dd61169973871fdf181d6c2109dd6935ece1"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.1.3"
|
version: "8.1.4"
|
||||||
flutter_keyboard_visibility:
|
flutter_keyboard_visibility:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ dependencies:
|
|||||||
cupertino_icons: ^1.0.2
|
cupertino_icons: ^1.0.2
|
||||||
fl_chart: ^0.65.0
|
fl_chart: ^0.65.0
|
||||||
logging: ^1.2.0
|
logging: ^1.2.0
|
||||||
flutter_bloc: ^8.1.3
|
flutter_bloc: ^8.1.4
|
||||||
path_provider: ^2.1.1
|
path_provider: ^2.1.1
|
||||||
equatable: ^2.0.5
|
equatable: ^2.0.5
|
||||||
rxdart: ^0.27.7
|
rxdart: ^0.27.7
|
||||||
@@ -27,6 +27,7 @@ dependencies:
|
|||||||
formz: ^0.6.1
|
formz: ^0.6.1
|
||||||
uuid: ^4.3.2
|
uuid: ^4.3.2
|
||||||
flutter_typeahead: ^5.2.0
|
flutter_typeahead: ^5.2.0
|
||||||
|
flex_color_picker: ^3.3.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
Reference in New Issue
Block a user