import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:marco/helpers/widgets/my_spacing.dart'; import 'package:marco/helpers/widgets/my_text.dart'; /// Returns a formatted color for the expense status. Color getExpenseStatusColor(String? status, {String? colorCode}) { if (colorCode != null && colorCode.isNotEmpty) { try { return Color(int.parse(colorCode.replaceFirst('#', '0xff'))); } catch (_) {} } switch (status) { case 'Approval Pending': return Colors.orange; case 'Process Pending': return Colors.blue; case 'Rejected': return Colors.red; case 'Paid': return Colors.green; default: return Colors.black; } } /// Formats amount to ₹ currency string. String formatExpenseAmount(double amount) { return NumberFormat.currency( locale: 'en_IN', symbol: '₹ ', decimalDigits: 2) .format(amount); } /// Label/Value block as reusable widget. Widget labelValueBlock(String label, String value) => Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ MyText.bodySmall(label, fontWeight: 600), MySpacing.height(4), MyText.bodySmall(value, fontWeight: 500, softWrap: true, maxLines: null), ], ); /// Skeleton loader for lists. Widget buildLoadingSkeleton() => ListView.builder( padding: const EdgeInsets.all(16), itemCount: 5, itemBuilder: (_, __) => Container( margin: const EdgeInsets.only(bottom: 16), height: 80, decoration: BoxDecoration( color: Colors.grey[300], borderRadius: BorderRadius.circular(10)), ), ); /// Expandable description widget. class ExpandableDescription extends StatefulWidget { final String description; const ExpandableDescription({Key? key, required this.description}) : super(key: key); @override State createState() => _ExpandableDescriptionState(); } class _ExpandableDescriptionState extends State { bool isExpanded = false; @override Widget build(BuildContext context) { final isLong = widget.description.length > 100; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ MyText.bodySmall( widget.description, maxLines: isExpanded ? null : 2, overflow: isExpanded ? TextOverflow.visible : TextOverflow.ellipsis, fontWeight: 500, ), if (isLong || !isExpanded) InkWell( onTap: () => setState(() => isExpanded = !isExpanded), child: Padding( padding: const EdgeInsets.only(top: 4), child: MyText.labelSmall( isExpanded ? 'Show less' : 'Show more', fontWeight: 600, color: Colors.blue, ), ), ), ], ); } }