Implement status picker and payment dialog for rent status updates
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
@@ -8,6 +8,140 @@ import 'package:rental_income_tracker/state/rent_controller.dart';
|
||||
class HomeScreen extends StatelessWidget {
|
||||
const HomeScreen({super.key});
|
||||
|
||||
Future<PaymentStatus?> _showStatusPicker(
|
||||
BuildContext context,
|
||||
PaymentStatus current,
|
||||
) async {
|
||||
return showModalBottomSheet<PaymentStatus>(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return SafeArea(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
ListTile(
|
||||
title: const Text('Paid on time'),
|
||||
selected: current == PaymentStatus.onTime,
|
||||
onTap: () => Navigator.of(context).pop(PaymentStatus.onTime),
|
||||
),
|
||||
ListTile(
|
||||
title: const Text('Paid late'),
|
||||
selected: current == PaymentStatus.late,
|
||||
onTap: () => Navigator.of(context).pop(PaymentStatus.late),
|
||||
),
|
||||
ListTile(
|
||||
title: const Text('Not paid'),
|
||||
selected: current == PaymentStatus.notPaid,
|
||||
onTap: () => Navigator.of(context).pop(PaymentStatus.notPaid),
|
||||
),
|
||||
ListTile(
|
||||
title: const Text('Pending'),
|
||||
selected: current == PaymentStatus.pending,
|
||||
onTap: () => Navigator.of(context).pop(PaymentStatus.pending),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<double?> _showPaidUsdDialog(
|
||||
BuildContext context, {
|
||||
required double initialValue,
|
||||
}) async {
|
||||
final controller = TextEditingController(
|
||||
text: initialValue > 0 ? initialValue.toStringAsFixed(2) : '',
|
||||
);
|
||||
|
||||
return showDialog<double>(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: const Text('Enter paid amount (USD)'),
|
||||
content: TextField(
|
||||
controller: controller,
|
||||
keyboardType: const TextInputType.numberWithOptions(decimal: true),
|
||||
decoration: const InputDecoration(labelText: 'USD amount'),
|
||||
autofocus: true,
|
||||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text('Cancel'),
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: () {
|
||||
final value = double.tryParse(controller.text.trim());
|
||||
if (value == null || value <= 0) {
|
||||
return;
|
||||
}
|
||||
Navigator.of(context).pop(value);
|
||||
},
|
||||
child: const Text('Save'),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _handleStatusTap(
|
||||
BuildContext context,
|
||||
RentController controller,
|
||||
RentTableRow row,
|
||||
) async {
|
||||
if (row.status == PaymentStatus.notOccupied) {
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text(
|
||||
'Use Settings -> Unit occupied to manage not-occupied months.',
|
||||
),
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
final nextStatus = await _showStatusPicker(context, row.status);
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
if (nextStatus == null || nextStatus == row.status) {
|
||||
return;
|
||||
}
|
||||
|
||||
double? paidUsd;
|
||||
if (nextStatus == PaymentStatus.onTime ||
|
||||
nextStatus == PaymentStatus.late) {
|
||||
paidUsd = await _showPaidUsdDialog(
|
||||
context,
|
||||
initialValue: row.usdAmount ?? controller.settings.rentUsd,
|
||||
);
|
||||
if (paidUsd == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await controller.setMonthStatusManually(
|
||||
year: row.year,
|
||||
month: row.month,
|
||||
status: nextStatus,
|
||||
paidUsd: paidUsd,
|
||||
);
|
||||
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
if (controller.errorMessage != null) {
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text(controller.errorMessage!)));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<RentController>(
|
||||
@@ -95,8 +229,17 @@ class HomeScreen extends StatelessWidget {
|
||||
_statusIcon(row.status),
|
||||
const SizedBox(width: 8),
|
||||
Text(_statusLabel(row.status)),
|
||||
const SizedBox(width: 8),
|
||||
const Icon(Icons.edit, size: 16),
|
||||
],
|
||||
),
|
||||
onTap: () async {
|
||||
await _handleStatusTap(
|
||||
context,
|
||||
controller,
|
||||
row,
|
||||
);
|
||||
},
|
||||
),
|
||||
DataCell(
|
||||
Text(
|
||||
|
||||
Reference in New Issue
Block a user