Inventory Management | Customer Management | Invoice Management Done | Commodity Rate Sync Done
This commit is contained in:
@@ -12,7 +12,13 @@ import '../../transactions/data/models.dart';
|
||||
import '../../budget/presentation/budget_screen.dart';
|
||||
|
||||
import '../providers/insight_provider.dart';
|
||||
import '../../sales/providers/invoices_provider.dart';
|
||||
import '../../sales/providers/customers_provider.dart';
|
||||
import '../../sales/domain/invoice.dart';
|
||||
import '../../sales/presentation/customers_list_screen.dart';
|
||||
import 'widgets/swipeable_account_card.dart';
|
||||
import 'widgets/budget_status_card.dart';
|
||||
import 'widgets/upcoming_dues_widget.dart';
|
||||
import 'widgets/statistics_tab.dart';
|
||||
import '../../../core/widgets/shimmer_loading.dart';
|
||||
import '../../../core/theme/nature_colors.dart';
|
||||
@@ -57,6 +63,8 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
|
||||
ref.invalidate(categoryProvider);
|
||||
ref.invalidate(budgetProvider);
|
||||
ref.invalidate(invitationProvider);
|
||||
ref.invalidate(invoicesProvider);
|
||||
ref.invalidate(customersProvider);
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
@@ -139,6 +147,8 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
|
||||
final categoriesState = ref.watch(categoryProvider);
|
||||
final insight = ref.watch(insightProvider);
|
||||
final walletsState = ref.watch(walletProvider);
|
||||
final invoicesState = ref.watch(invoicesProvider);
|
||||
final customersState = ref.watch(customersProvider);
|
||||
final isBusinessMode = ref.watch(businessModeProvider);
|
||||
final allTransactions = transState.value ?? [];
|
||||
|
||||
@@ -147,10 +157,18 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
|
||||
final endDate = range.end;
|
||||
|
||||
String title;
|
||||
if (_currentIndex == 0) title = 'Dashboard';
|
||||
else if (_currentIndex == 1) title = isBusinessMode ? 'Business Hub' : 'Statistics';
|
||||
else if (_currentIndex == 2) title = 'My Accounts';
|
||||
else title = 'Budgets';
|
||||
if (_currentIndex == 0) {
|
||||
title = 'Dashboard';
|
||||
} else if (isBusinessMode) {
|
||||
if (_currentIndex == 1) title = 'Business Hub';
|
||||
else if (_currentIndex == 2) title = 'Statistics';
|
||||
else if (_currentIndex == 3) title = 'My Accounts';
|
||||
else title = 'Budgets';
|
||||
} else {
|
||||
if (_currentIndex == 1) title = 'Statistics';
|
||||
else if (_currentIndex == 2) title = 'My Accounts';
|
||||
else title = 'Budgets';
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
@@ -308,6 +326,68 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process invoices to get total pending
|
||||
double totalPendingInvoices = 0;
|
||||
Map<int, double> pendingByCustomer = {};
|
||||
|
||||
if (invoicesState.hasValue && customersState.hasValue) {
|
||||
final invoices = invoicesState.value!;
|
||||
|
||||
for (var inv in invoices) {
|
||||
if (inv.status != 'PAID' && inv.status != 'CANCELLED' && inv.customerId != null) {
|
||||
double paidAmount = inv.amountPaid ?? 0;
|
||||
double pendingAmount = inv.totalAmount - paidAmount;
|
||||
if (pendingAmount > 0) {
|
||||
pendingByCustomer[inv.customerId!] = (pendingByCustomer[inv.customerId!] ?? 0) + pendingAmount;
|
||||
totalPendingInvoices += pendingAmount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
receivablesBalance += totalPendingInvoices;
|
||||
|
||||
// Build Payables Carousel Items
|
||||
List<CarouselItemData> payablesItems = [];
|
||||
if (walletsState.hasValue) {
|
||||
final payableWallets = walletsState.value!.where((w) => w.nature == 'PAYABLES' || w.nature == 'LOAN').toList();
|
||||
for (var w in payableWallets) {
|
||||
if (w.balance > 0) {
|
||||
payablesItems.add(CarouselItemData(
|
||||
title: 'To: ${w.name}',
|
||||
amount: w.balance,
|
||||
color: NatureColors.getColor('PAYABLES'),
|
||||
icon: LucideIcons.userMinus,
|
||||
onTap: () {
|
||||
Navigator.push(context, MaterialPageRoute(builder: (_) => WalletLedgerScreen(wallet: w)));
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build Receivables Carousel Items
|
||||
List<CarouselItemData> receivablesItems = [];
|
||||
|
||||
if (invoicesState.hasValue && customersState.hasValue) {
|
||||
final customers = customersState.value!;
|
||||
pendingByCustomer.forEach((custId, amount) {
|
||||
if (amount > 0) {
|
||||
final customerName = customers.where((c) => c.id == custId).firstOrNull?.name ?? 'Unknown Customer';
|
||||
receivablesItems.add(CarouselItemData(
|
||||
title: 'From: $customerName',
|
||||
amount: amount,
|
||||
color: NatureColors.getColor('RECEIVABLES'),
|
||||
icon: LucideIcons.userPlus,
|
||||
onTap: () {
|
||||
// Navigate to customer details or invoices in the future
|
||||
}
|
||||
));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return IndexedStack(
|
||||
index: _currentIndex,
|
||||
children: [
|
||||
@@ -352,7 +432,6 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
|
||||
],
|
||||
const BudgetStatusCard(),
|
||||
const SizedBox(height: 24),
|
||||
|
||||
// Summary Cards Grid
|
||||
GridView.count(
|
||||
crossAxisCount: 2,
|
||||
@@ -362,14 +441,34 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
childAspectRatio: 1.5,
|
||||
children: [
|
||||
_buildSummaryCard(context, 'Balance', cashBalance, NatureColors.getColor('BALANCE'), LucideIcons.wallet, 'CASH'),
|
||||
_buildSummaryCard(context, 'Expense', expenseBalance, NatureColors.getColor('EXPENSE'), LucideIcons.arrowUpRight, 'EXPENSE'),
|
||||
_buildSummaryCard(context, 'Savings', savingsBalance, NatureColors.getColor('SAVINGS'), LucideIcons.piggyBank, 'SAVINGS'),
|
||||
_buildSummaryCard(context, 'Investments', investmentsBalance, NatureColors.getColor('INVESTMENTS'), LucideIcons.trendingUp, 'INVESTMENTS'),
|
||||
_buildSummaryCard(context, 'Payables', payablesBalance, NatureColors.getColor('PAYABLES'), LucideIcons.alertCircle, 'PAYABLES'),
|
||||
_buildSummaryCard(context, 'Receivables', receivablesBalance, NatureColors.getColor('RECEIVABLES'), LucideIcons.arrowDownLeft, 'RECEIVABLES'),
|
||||
_buildSummaryCard(context, 'Balance', cashBalance, NatureColors.getColor('BALANCE'), LucideIcons.wallet, onTap: () => Navigator.push(context, MaterialPageRoute(builder: (_) => const AccountsScreen(initialFilterNature: 'CASH')))),
|
||||
_buildSummaryCard(context, 'Expense', expenseBalance, NatureColors.getColor('EXPENSE'), LucideIcons.arrowUpRight, onTap: () => Navigator.push(context, MaterialPageRoute(builder: (_) => const AccountsScreen(initialFilterNature: 'EXPENSE')))),
|
||||
_buildSummaryCard(context, 'Savings', savingsBalance, NatureColors.getColor('SAVINGS'), LucideIcons.piggyBank, onTap: () => Navigator.push(context, MaterialPageRoute(builder: (_) => const AccountsScreen(initialFilterNature: 'SAVINGS')))),
|
||||
_buildSummaryCard(context, 'Investments', investmentsBalance, NatureColors.getColor('INVESTMENTS'), LucideIcons.trendingUp, onTap: () => Navigator.push(context, MaterialPageRoute(builder: (_) => const AccountsScreen(initialFilterNature: 'INVESTMENTS')))),
|
||||
_buildSummaryCard(context, 'Total Payables', payablesBalance, NatureColors.getColor('PAYABLES'), LucideIcons.alertCircle, onTap: () => Navigator.push(context, MaterialPageRoute(builder: (_) => const AccountsScreen(initialFilterNature: 'PAYABLES')))),
|
||||
_buildSummaryCard(context, 'Total Receivables', receivablesBalance, NatureColors.getColor('RECEIVABLES'), LucideIcons.arrowDownLeft, onTap: () {
|
||||
Navigator.push(context, MaterialPageRoute(builder: (_) => const CustomersListScreen()));
|
||||
}),
|
||||
],
|
||||
),
|
||||
|
||||
const SizedBox(height: 24),
|
||||
const UpcomingDuesWidget(),
|
||||
|
||||
if (payablesItems.isNotEmpty) ...[
|
||||
const SizedBox(height: 24),
|
||||
Text('Upcoming Payables', style: Theme.of(context).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 12),
|
||||
SwipeableAccountCard(items: payablesItems),
|
||||
],
|
||||
|
||||
if (receivablesItems.isNotEmpty) ...[
|
||||
const SizedBox(height: 24),
|
||||
Text('Upcoming Receivables', style: Theme.of(context).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 12),
|
||||
SwipeableAccountCard(items: receivablesItems),
|
||||
],
|
||||
|
||||
const SizedBox(height: 32),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
@@ -515,8 +614,11 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
|
||||
),
|
||||
),
|
||||
|
||||
// ---------------- STATS/BUSINESS TAB ----------------
|
||||
isBusinessMode ? const BusinessHubScreen() : StatisticsTab(
|
||||
// ---------------- BUSINESS TAB ----------------
|
||||
if (isBusinessMode) const BusinessHubScreen(),
|
||||
|
||||
// ---------------- STATS TAB ----------------
|
||||
StatisticsTab(
|
||||
transactions: transactions,
|
||||
wallets: safeWallets,
|
||||
categories: categoriesState.value ?? [],
|
||||
@@ -541,14 +643,17 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
|
||||
},
|
||||
),
|
||||
bottomNavigationBar: BottomNavigationBar(
|
||||
currentIndex: _currentIndex >= 2 ? _currentIndex + 1 : _currentIndex,
|
||||
currentIndex: isBusinessMode
|
||||
? (_currentIndex >= 3 ? _currentIndex + 1 : _currentIndex)
|
||||
: (_currentIndex >= 2 ? _currentIndex + 1 : _currentIndex),
|
||||
type: BottomNavigationBarType.fixed,
|
||||
onTap: (index) {
|
||||
if (index == 2) {
|
||||
final addIndex = isBusinessMode ? 3 : 2;
|
||||
if (index == addIndex) {
|
||||
Navigator.push(context, MaterialPageRoute(builder: (_) => const AddTransactionScreen()));
|
||||
} else {
|
||||
setState(() {
|
||||
_currentIndex = index > 2 ? index - 1 : index;
|
||||
_currentIndex = index > addIndex ? index - 1 : index;
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -558,9 +663,9 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
|
||||
showUnselectedLabels: true,
|
||||
items: [
|
||||
const BottomNavigationBarItem(icon: Icon(LucideIcons.home), label: 'Home'),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(isBusinessMode ? LucideIcons.briefcase : LucideIcons.pieChart),
|
||||
label: isBusinessMode ? 'Business' : 'Stats'),
|
||||
if (isBusinessMode)
|
||||
const BottomNavigationBarItem(icon: Icon(LucideIcons.briefcase), label: 'Business'),
|
||||
const BottomNavigationBarItem(icon: Icon(LucideIcons.pieChart), label: 'Stats'),
|
||||
const BottomNavigationBarItem(icon: Icon(LucideIcons.plusCircle), label: 'Add'),
|
||||
const BottomNavigationBarItem(icon: Icon(LucideIcons.wallet), label: 'Wallets'),
|
||||
const BottomNavigationBarItem(icon: Icon(LucideIcons.target), label: 'Budgets'),
|
||||
@@ -569,16 +674,9 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSummaryCard(BuildContext context, String title, double amount, Color color, IconData icon, [String? nature]) {
|
||||
Widget _buildSummaryCard(BuildContext context, String title, double amount, Color color, IconData icon, {VoidCallback? onTap}) {
|
||||
return GestureDetector(
|
||||
onTap: nature != null ? () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => AccountsScreen(initialFilterNature: nature),
|
||||
),
|
||||
);
|
||||
} : null,
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
|
||||
Reference in New Issue
Block a user