import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:skeletonizer/skeletonizer.dart'; import 'package:timeago/timeago.dart' as timeago; /// A reusable transaction list item widget. /// Used by both [HomeScreen] and [HistoryScreen]. class TransactionItemWidget extends StatefulWidget { final Map transaction; final bool enabled; final Future Function()? onRepeat; const TransactionItemWidget({ super.key, required this.transaction, this.enabled = false, this.onRepeat, }); @override State createState() => _TransactionItemWidgetState(); } class _TransactionItemWidgetState extends State { bool _isRepeating = false; Future _handleRepeat() async { if (_isRepeating || widget.onRepeat == null) return; setState(() => _isRepeating = true); try { await widget.onRepeat!(); } finally { if (mounted) setState(() => _isRepeating = false); } } @override Widget build(BuildContext context) { final theme = Theme.of(context); final isDark = theme.brightness == Brightness.dark; final status = widget.transaction['integrationStatus'] as String?; final isSuccess = status == 'SUCCESS'; final isPending = status == 'PENDING'; final statusIcon = isSuccess ? Icons.check_circle_rounded : isPending ? Icons.pending_rounded : Icons.cancel_rounded; final statusColor = isSuccess ? const Color(0xFF10B981) : isPending ? const Color(0xFFF59E0B) : const Color(0xFFEF4444); return Skeletonizer( enabled: widget.enabled, child: Padding( padding: const EdgeInsets.only(bottom: 8), child: Material( color: Colors.transparent, child: InkWell( borderRadius: BorderRadius.circular(16), onTap: () { context.push("/receipt/${widget.transaction['id']}"); }, child: Container( padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 14), decoration: BoxDecoration( color: isDark ? const Color(0xFF1A1A2E) : Colors.white, borderRadius: BorderRadius.circular(16), border: Border.all( color: isDark ? Colors.white.withValues(alpha: 0.06) : Colors.grey.shade200, width: 1, ), boxShadow: [ BoxShadow( color: isDark ? Colors.black.withValues(alpha: 0.2) : Colors.black.withValues(alpha: 0.03), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Main row: provider image, bill name & date, amount Row( children: [ // Provider image Container( width: 44, height: 44, padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: theme.colorScheme.primary.withValues( alpha: 0.1, ), borderRadius: BorderRadius.circular(12), ), child: Image( image: AssetImage( "assets/${widget.transaction['paymentProcessorImage'] ?? ''}", ), errorBuilder: (_, __, ___) => Icon( Icons.receipt_long_rounded, size: 20, color: theme.colorScheme.primary, ), ), ), const SizedBox(width: 14), // Bill name & date Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Flexible( child: Text( widget.transaction['billName'] ?? '', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: isDark ? Colors.white : Colors.black87, ), overflow: TextOverflow.ellipsis, ), ), const SizedBox(width: 8), Icon(statusIcon, size: 16, color: statusColor), ], ), const SizedBox(height: 4), Row( children: [ if (widget.transaction['billProductName'] != null) ...[ Text( widget.transaction['billProductName'], style: TextStyle( fontSize: 12, fontWeight: FontWeight.w400, color: isDark ? Colors.white54 : Colors.grey.shade500, ), ), Text( ' • ', style: TextStyle( fontSize: 11, color: isDark ? Colors.white24 : Colors.grey.shade400, ), ), ], Text( widget.transaction['createdAt'] != null ? timeago.format( DateTime.parse( widget.transaction['createdAt'], ), ) : '', style: TextStyle( fontSize: 12, fontWeight: FontWeight.w400, color: isDark ? Colors.white54 : Colors.grey.shade500, ), ), ], ), ], ), ), // Amount Column( crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( '${(widget.transaction['amount'] as num?)?.toStringAsFixed(2) ?? ''} ${widget.transaction['debitCurrency']}', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w700, color: isDark ? Colors.white : Colors.black87, ), ), Text( '${(widget.transaction['totalAmount'] as num?)?.toStringAsFixed(2) ?? ''} ${widget.transaction['debitCurrency']}', style: TextStyle( fontSize: 12, fontWeight: FontWeight.w500, color: theme.colorScheme.primary.withValues( alpha: 0.7, ), ), ), ], ), ], ), // Quick actions row (only shown when onRepeat is provided) if (widget.onRepeat != null) ...[ const SizedBox(height: 10), Divider( height: 1, color: isDark ? Colors.white.withValues(alpha: 0.06) : Colors.grey.shade200, ), const SizedBox(height: 8), Align( alignment: Alignment.centerRight, child: TextButton.icon( onPressed: _handleRepeat, icon: _isRepeating ? SizedBox( width: 16, height: 16, child: CircularProgressIndicator( strokeWidth: 2, color: theme.colorScheme.primary, ), ) : const Icon(Icons.repeat_rounded, size: 16), label: Text( _isRepeating ? 'Repeating...' : 'Repeat', style: const TextStyle(fontSize: 12), ), style: TextButton.styleFrom( padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 4, ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), ), ), ], ], ), ), ), ), ), ); } }