minor home screen fix
This commit is contained in:
@@ -108,8 +108,11 @@ class HomeController extends ChangeNotifier {
|
||||
model.isLoading = true;
|
||||
if (!_disposed) notifyListeners();
|
||||
|
||||
List<dynamic> response = await http.get('/public/providers');
|
||||
model.providers = response.map((e) => BillProvider.fromJson(e)).toList();
|
||||
final response = await http.get('/public/providers?sort=priority,asc');
|
||||
List<BillProvider> providers = PageableModel.fromJson(response).content
|
||||
.map((e) => BillProvider.fromJson(e as Map<String, dynamic>))
|
||||
.toList();
|
||||
model.providers = providers;
|
||||
model.filterableProviders = model.providers;
|
||||
|
||||
if (model.providers.isNotEmpty) {
|
||||
@@ -141,7 +144,9 @@ class HomeController extends ChangeNotifier {
|
||||
if (!_disposed) notifyListeners();
|
||||
}
|
||||
|
||||
Future<ApiResponse<List<Map<String, dynamic>>>> getTransactions(String userId) async {
|
||||
Future<ApiResponse<List<Map<String, dynamic>>>> getTransactions(
|
||||
String userId,
|
||||
) async {
|
||||
model.isLoading = true;
|
||||
if (!_disposed) notifyListeners();
|
||||
|
||||
@@ -179,8 +184,10 @@ class HomeController extends ChangeNotifier {
|
||||
|
||||
// Simulate fetching categories
|
||||
try {
|
||||
List<dynamic> response = await http.get('/public/categories');
|
||||
model.categories = response.map((e) => Category.fromJson(e)).toList();
|
||||
final response = await http.get('/public/categories');
|
||||
model.categories = (response as List<dynamic>)
|
||||
.map((e) => Category.fromJson(e as Map<String, dynamic>))
|
||||
.toList();
|
||||
|
||||
if (model.categories.isNotEmpty) {
|
||||
updateSelectedCategory(model.categories[0]);
|
||||
|
||||
@@ -35,6 +35,14 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
||||
late Animation<Offset> _transactionsSlideAnimation;
|
||||
late Animation<double> _transactionsFadeAnimation;
|
||||
|
||||
// ── Vibrant category color map ──────────────────────────────
|
||||
static const Map<String, Color> _categoryColorMap = {
|
||||
'ECONET': Color(0xFF1A73E8), // Deep green
|
||||
'NETONE': Color.fromARGB(255, 230, 127, 0), // Bold blue
|
||||
'TELECEL': Color(0xFF7B1FA2), // Vibrant purple
|
||||
'ZESA': Color.fromARGB(255, 230, 58, 0), // Fiery orange
|
||||
};
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@@ -156,6 +164,28 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
/// Derives a vibrant accent colour from the provider's category.
|
||||
Color _resolveProviderColor(BillProvider provider) {
|
||||
// Try exact match on category
|
||||
final exact = _categoryColorMap[provider.category.toUpperCase()];
|
||||
if (exact != null) return exact;
|
||||
|
||||
// Try matching on label
|
||||
final labelMatch = _categoryColorMap[provider.label.toUpperCase()];
|
||||
if (labelMatch != null) return labelMatch;
|
||||
|
||||
// Try matching on provider name keywords
|
||||
final name = provider.name.toUpperCase();
|
||||
for (final entry in _categoryColorMap.entries) {
|
||||
if (name.contains(entry.key)) return entry.value;
|
||||
}
|
||||
|
||||
// Hash-based fallback – deterministic vibrant hue
|
||||
final hash = provider.clientId.hashCode;
|
||||
final hue = (hash % 360).toDouble();
|
||||
return HSVColor.fromAHSV(1.0, hue, 0.75, 0.85).toColor();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
@@ -352,6 +382,7 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
||||
double availableWidth,
|
||||
) {
|
||||
final cardWidth = (availableWidth / 2) - 6;
|
||||
final accent = _resolveProviderColor(provider);
|
||||
|
||||
return SizedBox(
|
||||
width: cardWidth,
|
||||
@@ -368,26 +399,13 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(14),
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: [
|
||||
theme.colorScheme.primary.withValues(alpha: 0.08),
|
||||
theme.colorScheme.tertiary.withValues(alpha: 0.03),
|
||||
theme.colorScheme.primary.withValues(alpha: 0.05),
|
||||
],
|
||||
stops: const [0.0, 0.5, 1.0],
|
||||
),
|
||||
color: isDark ? const Color(0xFF1E1E1E) : Colors.white,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(
|
||||
color: theme.colorScheme.primary.withValues(alpha: 0.1),
|
||||
width: 1,
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: theme.colorScheme.primary.withValues(alpha: 0.06),
|
||||
blurRadius: 10,
|
||||
offset: const Offset(0, 3),
|
||||
color: accent.withValues(alpha: 0.15),
|
||||
blurRadius: 2,
|
||||
offset: const Offset(0, 1),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -400,11 +418,9 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
||||
Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
padding: const EdgeInsets.all(8),
|
||||
padding: const EdgeInsets.all(1),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.primary.withValues(
|
||||
alpha: 0.12,
|
||||
),
|
||||
color: accent.withValues(alpha: 0.12),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Image(
|
||||
@@ -412,14 +428,14 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
||||
errorBuilder: (_, __, ___) => Icon(
|
||||
Icons.payment_rounded,
|
||||
size: 20,
|
||||
color: theme.colorScheme.primary,
|
||||
color: accent,
|
||||
),
|
||||
),
|
||||
),
|
||||
Icon(
|
||||
Icons.chevron_right_rounded,
|
||||
size: 20,
|
||||
color: theme.colorScheme.primary.withValues(alpha: 0.5),
|
||||
color: accent.withValues(alpha: 0.55),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -74,9 +74,9 @@ class TransactionModel {
|
||||
final String? providerImage;
|
||||
final String? paymentProcessorImage;
|
||||
final String confirmationStatus;
|
||||
final String paymentStatus;
|
||||
final String integrationStatus;
|
||||
final String pollingStatus;
|
||||
final String? paymentStatus;
|
||||
final String? integrationStatus;
|
||||
final String? pollingStatus;
|
||||
final String? orderId;
|
||||
final String? orderTrace;
|
||||
final String? orderTransactionTrace;
|
||||
@@ -122,9 +122,9 @@ class TransactionModel {
|
||||
this.providerImage,
|
||||
this.paymentProcessorImage,
|
||||
required this.confirmationStatus,
|
||||
required this.paymentStatus,
|
||||
required this.integrationStatus,
|
||||
required this.pollingStatus,
|
||||
this.paymentStatus,
|
||||
this.integrationStatus,
|
||||
this.pollingStatus,
|
||||
this.orderId,
|
||||
this.orderTrace,
|
||||
this.orderTransactionTrace,
|
||||
|
||||
@@ -41,9 +41,9 @@ TransactionModel _$TransactionModelFromJson(Map<String, dynamic> json) =>
|
||||
providerImage: json['providerImage'] as String?,
|
||||
paymentProcessorImage: json['paymentProcessorImage'] as String?,
|
||||
confirmationStatus: json['confirmationStatus'] as String,
|
||||
paymentStatus: json['paymentStatus'] as String,
|
||||
integrationStatus: json['integrationStatus'] as String,
|
||||
pollingStatus: json['pollingStatus'] as String,
|
||||
paymentStatus: json['paymentStatus'] as String?,
|
||||
integrationStatus: json['integrationStatus'] as String?,
|
||||
pollingStatus: json['pollingStatus'] as String?,
|
||||
orderId: json['orderId'] as String?,
|
||||
orderTrace: json['orderTrace'] as String?,
|
||||
orderTransactionTrace: json['orderTransactionTrace'] as String?,
|
||||
|
||||
Reference in New Issue
Block a user