// Dart 3 – Null-safety import 'dart:io'; void main() { print('=== Welcome to Budget Manager ==='); // (3) Data Storage using lists of Map final List> incomeList = []; final List> expenseList = []; // (5) Loop until exit while (true) { _menu(); final choice = _readInt(); if (choice == null) { _warn('Invalid input. Enter a number 1–4.'); continue; } // (5) Control Flow with if/else if (choice == 1) { _addEntry(incomeList, isIncome: true); // (2) Add income } else if (choice == 2) { _addEntry(expenseList, isIncome: false); // (2) Add expense } else if (choice == 3) { _summary(incomeList, expenseList); // (6)(7)(8) Summary + tax } else if (choice == 4) { print('Goodbye!'); return; } else { _warn('Choose a valid option (1–4).'); } } } void _menu() { print('\nMenu:'); print('1) Add income'); print('2) Add expense'); print('3) View summary'); print('4) Exit'); stdout.write('Choose an option: '); } int? _readInt() { final s = stdin.readLineSync(); return s == null ? null : int.tryParse(s.trim()); } double? _readDouble() { final s = stdin.readLineSync(); return s == null ? null : double.tryParse(s.trim()); } void _addEntry(List> target, {required bool isIncome}) { stdout.write('Enter ${isIncome ? "income" : "expense"} description: '); final desc = stdin.readLineSync()?.trim(); if (desc == null || desc.isEmpty) { _warn('Description cannot be empty.'); return; } stdout.write('Enter amount (positive number): '); final amt = _readDouble(); // (4) Input Validation (no negatives / must be numeric) if (amt == null || amt.isNaN || amt <= 0) { _warn('Invalid amount. Enter a positive number.'); return; } target.add({desc: amt}); print('${isIncome ? "Income" : "Expense"} "$desc" added: \$${amt.toStringAsFixed(2)}'); } void _summary( List> incomes, List> expenses, ) { // (7) Arithmetic Operations final totalIncome = incomes.fold( 0.0, (sum, m) => sum + m.values.first, ); final totalExpense = expenses.fold( 0.0, (sum, m) => sum + m.values.first, ); final net = totalIncome - totalExpense; // (6) String Interpolation & clear messages print('\n--- Summary ---'); print('Total income: \$${totalIncome.toStringAsFixed(2)}'); print('Total expenses: \$${totalExpense.toStringAsFixed(2)}'); if (net > 0) { print('Your net profit is \$${net.toStringAsFixed(2)}'); // (8) Optional Tax with ternary operator final tax = net > 0 ? net * 0.15 : 0.0; print('Tax to be paid (15%): \$${tax.toStringAsFixed(2)}'); } else if (net < 0) { print('Your net loss is \$${(-net).toStringAsFixed(2)}'); print('No tax due since there is no profit.'); } else { print('You broke even. Net = \$0.00'); print('No tax due.'); } if (incomes.isNotEmpty) { print('\nIncome items:'); for (final m in incomes) { print('- ${m.keys.first}: \$${m.values.first.toStringAsFixed(2)}'); } } if (expenses.isNotEmpty) { print('\nExpense items:'); for (final m in expenses) { print('- ${m.keys.first}: \$${m.values.first.toStringAsFixed(2)}'); } } } void _warn(String msg) => print('⚠️ $msg');