minor home screen fix
This commit is contained in:
@@ -108,8 +108,11 @@ class HomeController extends ChangeNotifier {
|
|||||||
model.isLoading = true;
|
model.isLoading = true;
|
||||||
if (!_disposed) notifyListeners();
|
if (!_disposed) notifyListeners();
|
||||||
|
|
||||||
List<dynamic> response = await http.get('/public/providers');
|
final response = await http.get('/public/providers?sort=priority,asc');
|
||||||
model.providers = response.map((e) => BillProvider.fromJson(e)).toList();
|
List<BillProvider> providers = PageableModel.fromJson(response).content
|
||||||
|
.map((e) => BillProvider.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList();
|
||||||
|
model.providers = providers;
|
||||||
model.filterableProviders = model.providers;
|
model.filterableProviders = model.providers;
|
||||||
|
|
||||||
if (model.providers.isNotEmpty) {
|
if (model.providers.isNotEmpty) {
|
||||||
@@ -141,7 +144,9 @@ class HomeController extends ChangeNotifier {
|
|||||||
if (!_disposed) notifyListeners();
|
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;
|
model.isLoading = true;
|
||||||
if (!_disposed) notifyListeners();
|
if (!_disposed) notifyListeners();
|
||||||
|
|
||||||
@@ -179,8 +184,10 @@ class HomeController extends ChangeNotifier {
|
|||||||
|
|
||||||
// Simulate fetching categories
|
// Simulate fetching categories
|
||||||
try {
|
try {
|
||||||
List<dynamic> response = await http.get('/public/categories');
|
final response = await http.get('/public/categories');
|
||||||
model.categories = response.map((e) => Category.fromJson(e)).toList();
|
model.categories = (response as List<dynamic>)
|
||||||
|
.map((e) => Category.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList();
|
||||||
|
|
||||||
if (model.categories.isNotEmpty) {
|
if (model.categories.isNotEmpty) {
|
||||||
updateSelectedCategory(model.categories[0]);
|
updateSelectedCategory(model.categories[0]);
|
||||||
|
|||||||
@@ -35,6 +35,14 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
|||||||
late Animation<Offset> _transactionsSlideAnimation;
|
late Animation<Offset> _transactionsSlideAnimation;
|
||||||
late Animation<double> _transactionsFadeAnimation;
|
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
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@@ -156,6 +164,28 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
|||||||
super.dispose();
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
@@ -352,6 +382,7 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
|||||||
double availableWidth,
|
double availableWidth,
|
||||||
) {
|
) {
|
||||||
final cardWidth = (availableWidth / 2) - 6;
|
final cardWidth = (availableWidth / 2) - 6;
|
||||||
|
final accent = _resolveProviderColor(provider);
|
||||||
|
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
width: cardWidth,
|
width: cardWidth,
|
||||||
@@ -368,26 +399,13 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
|||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.all(14),
|
padding: const EdgeInsets.all(14),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
gradient: LinearGradient(
|
color: isDark ? const Color(0xFF1E1E1E) : Colors.white,
|
||||||
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],
|
|
||||||
),
|
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
border: Border.all(
|
|
||||||
color: theme.colorScheme.primary.withValues(alpha: 0.1),
|
|
||||||
width: 1,
|
|
||||||
),
|
|
||||||
boxShadow: [
|
boxShadow: [
|
||||||
BoxShadow(
|
BoxShadow(
|
||||||
color: theme.colorScheme.primary.withValues(alpha: 0.06),
|
color: accent.withValues(alpha: 0.15),
|
||||||
blurRadius: 10,
|
blurRadius: 2,
|
||||||
offset: const Offset(0, 3),
|
offset: const Offset(0, 1),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -400,11 +418,9 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
|||||||
Container(
|
Container(
|
||||||
width: 40,
|
width: 40,
|
||||||
height: 40,
|
height: 40,
|
||||||
padding: const EdgeInsets.all(8),
|
padding: const EdgeInsets.all(1),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: theme.colorScheme.primary.withValues(
|
color: accent.withValues(alpha: 0.12),
|
||||||
alpha: 0.12,
|
|
||||||
),
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
),
|
),
|
||||||
child: Image(
|
child: Image(
|
||||||
@@ -412,14 +428,14 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
|||||||
errorBuilder: (_, __, ___) => Icon(
|
errorBuilder: (_, __, ___) => Icon(
|
||||||
Icons.payment_rounded,
|
Icons.payment_rounded,
|
||||||
size: 20,
|
size: 20,
|
||||||
color: theme.colorScheme.primary,
|
color: accent,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Icon(
|
Icon(
|
||||||
Icons.chevron_right_rounded,
|
Icons.chevron_right_rounded,
|
||||||
size: 20,
|
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? providerImage;
|
||||||
final String? paymentProcessorImage;
|
final String? paymentProcessorImage;
|
||||||
final String confirmationStatus;
|
final String confirmationStatus;
|
||||||
final String paymentStatus;
|
final String? paymentStatus;
|
||||||
final String integrationStatus;
|
final String? integrationStatus;
|
||||||
final String pollingStatus;
|
final String? pollingStatus;
|
||||||
final String? orderId;
|
final String? orderId;
|
||||||
final String? orderTrace;
|
final String? orderTrace;
|
||||||
final String? orderTransactionTrace;
|
final String? orderTransactionTrace;
|
||||||
@@ -122,9 +122,9 @@ class TransactionModel {
|
|||||||
this.providerImage,
|
this.providerImage,
|
||||||
this.paymentProcessorImage,
|
this.paymentProcessorImage,
|
||||||
required this.confirmationStatus,
|
required this.confirmationStatus,
|
||||||
required this.paymentStatus,
|
this.paymentStatus,
|
||||||
required this.integrationStatus,
|
this.integrationStatus,
|
||||||
required this.pollingStatus,
|
this.pollingStatus,
|
||||||
this.orderId,
|
this.orderId,
|
||||||
this.orderTrace,
|
this.orderTrace,
|
||||||
this.orderTransactionTrace,
|
this.orderTransactionTrace,
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ TransactionModel _$TransactionModelFromJson(Map<String, dynamic> json) =>
|
|||||||
providerImage: json['providerImage'] as String?,
|
providerImage: json['providerImage'] as String?,
|
||||||
paymentProcessorImage: json['paymentProcessorImage'] as String?,
|
paymentProcessorImage: json['paymentProcessorImage'] as String?,
|
||||||
confirmationStatus: json['confirmationStatus'] as String,
|
confirmationStatus: json['confirmationStatus'] as String,
|
||||||
paymentStatus: json['paymentStatus'] as String,
|
paymentStatus: json['paymentStatus'] as String?,
|
||||||
integrationStatus: json['integrationStatus'] as String,
|
integrationStatus: json['integrationStatus'] as String?,
|
||||||
pollingStatus: json['pollingStatus'] as String,
|
pollingStatus: json['pollingStatus'] as String?,
|
||||||
orderId: json['orderId'] as String?,
|
orderId: json['orderId'] as String?,
|
||||||
orderTrace: json['orderTrace'] as String?,
|
orderTrace: json['orderTrace'] as String?,
|
||||||
orderTransactionTrace: json['orderTransactionTrace'] as String?,
|
orderTransactionTrace: json['orderTransactionTrace'] as String?,
|
||||||
|
|||||||
Reference in New Issue
Block a user