Files
worker/lib/features/orders/presentation/pages/payments_page.dart
Phuoc Nguyen 3741239d83 dang ki du an
2025-11-26 11:21:35 +07:00

196 lines
6.3 KiB
Dart

/// Page: Payments Page
///
/// Displays list of invoices/payments.
library;
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart';
import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/theme/colors.dart';
import 'package:worker/features/orders/data/models/invoice_model.dart';
import 'package:worker/features/orders/presentation/providers/invoices_provider.dart';
import 'package:worker/features/orders/presentation/widgets/invoice_card.dart';
/// Payments Page
///
/// Features:
/// - List of invoice cards
/// - Pull-to-refresh
/// - Empty state
class PaymentsPage extends ConsumerWidget {
const PaymentsPage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final invoicesAsync = ref.watch(invoicesProvider);
return invoicesAsync.when(
data: (invoices) {
// Sort by issue date (newest first)
final sortedInvoices = List<InvoiceModel>.from(invoices)
..sort((a, b) => b.issueDate.compareTo(a.issueDate));
return Scaffold(
backgroundColor: const Color(0xFFF4F6F8),
appBar: AppBar(
leading: IconButton(
icon: const FaIcon(
FontAwesomeIcons.arrowLeft,
color: Colors.black,
size: 20,
),
onPressed: () => context.pop(),
),
title: const Text(
'Thanh toán',
style: TextStyle(color: Colors.black),
),
elevation: AppBarSpecs.elevation,
backgroundColor: AppColors.white,
centerTitle: false,
),
body: sortedInvoices.isEmpty
? _buildEmptyState(ref)
: RefreshIndicator(
onRefresh: () async {
await ref.read(invoicesProvider.notifier).refresh();
},
child: ListView.builder(
padding: const EdgeInsets.all(16),
itemCount: sortedInvoices.length,
itemBuilder: (context, index) {
final invoice = sortedInvoices[index];
return Padding(
padding: const EdgeInsets.only(bottom: 12),
child: InvoiceCard(
invoice: invoice,
onTap: () {
context.push('/payments/${invoice.invoiceId}');
},
onPaymentTap: () {
context.push('/payments/${invoice.invoiceId}');
},
),
);
},
),
),
);
},
loading: () => Scaffold(
backgroundColor: const Color(0xFFF4F6F8),
appBar: AppBar(
leading: IconButton(
icon: const FaIcon(
FontAwesomeIcons.arrowLeft,
color: Colors.black,
size: 20,
),
onPressed: () => context.pop(),
),
title: const Text(
'Thanh toán',
style: TextStyle(color: Colors.black),
),
elevation: AppBarSpecs.elevation,
backgroundColor: AppColors.white,
centerTitle: false,
),
body: const Center(child: CircularProgressIndicator()),
),
error: (error, stack) => Scaffold(
backgroundColor: const Color(0xFFF4F6F8),
appBar: AppBar(
leading: IconButton(
icon: const FaIcon(
FontAwesomeIcons.arrowLeft,
color: Colors.black,
size: 20,
),
onPressed: () => context.pop(),
),
title: const Text(
'Thanh toán',
style: TextStyle(color: Colors.black),
),
elevation: AppBarSpecs.elevation,
backgroundColor: AppColors.white,
centerTitle: false,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FaIcon(
FontAwesomeIcons.circleExclamation,
size: 80,
color: AppColors.danger.withValues(alpha: 0.7),
),
const SizedBox(height: 16),
const Text(
'Có lỗi xảy ra',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
color: AppColors.grey900,
),
),
const SizedBox(height: 8),
Text(
error.toString(),
style: const TextStyle(fontSize: 14, color: AppColors.grey500),
textAlign: TextAlign.center,
),
],
),
),
),
);
}
/// Build empty state
Widget _buildEmptyState(WidgetRef ref) {
return RefreshIndicator(
onRefresh: () async {
await ref.read(invoicesProvider.notifier).refresh();
},
child: ListView(
padding: const EdgeInsets.symmetric(horizontal: 16),
children: [
SizedBox(
height: 500,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FaIcon(
FontAwesomeIcons.receipt,
size: 80,
color: AppColors.grey500.withValues(alpha: 0.5),
),
const SizedBox(height: 16),
const Text(
'Không có hóa đơn nào',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
color: AppColors.grey500,
),
),
const SizedBox(height: 8),
const Text(
'Kéo xuống để làm mới',
style: TextStyle(fontSize: 14, color: AppColors.grey500),
),
],
),
),
),
],
),
);
}
}