Inventory Management | Customer Management | Invoice Management Done | Commodity Rate Sync Done

This commit is contained in:
2026-08-20 20:35:41 +05:30
parent ba9a9fd8a4
commit 5f620022f3
101 changed files with 9091 additions and 240 deletions

View File

@@ -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(