add dashboard to phone app
This commit is contained in:
@@ -5,7 +5,13 @@ import '../core/providers/theme_provider.dart';
|
||||
|
||||
const _orange = Color(0xFFFF6B00);
|
||||
|
||||
/// Compact row of language pills + theme toggle.
|
||||
const _langs = [
|
||||
('EN', Locale('en')),
|
||||
('FR', Locale('fr')),
|
||||
('AR', Locale('ar')),
|
||||
];
|
||||
|
||||
/// Compact language dropdown + theme toggle.
|
||||
/// [onDark] = true when rendered on a dark background (landing screen).
|
||||
class PreferencesBar extends ConsumerWidget {
|
||||
final bool onDark;
|
||||
@@ -17,69 +23,100 @@ class PreferencesBar extends ConsumerWidget {
|
||||
final currentLocale = ref.watch(localeProvider);
|
||||
final themeMode = ref.watch(themeProvider);
|
||||
final isDark = themeMode == ThemeMode.dark;
|
||||
final cs = Theme.of(context).colorScheme;
|
||||
|
||||
final inactiveText = onDark
|
||||
? Colors.white.withValues(alpha: 0.55)
|
||||
: Theme.of(context).colorScheme.onSurfaceVariant;
|
||||
final activeText = Colors.white;
|
||||
final inactiveBg = onDark
|
||||
final chipBg = onDark
|
||||
? Colors.white.withValues(alpha: 0.12)
|
||||
: Theme.of(context).colorScheme.surfaceContainerHighest;
|
||||
|
||||
const langs = [
|
||||
('EN', Locale('en')),
|
||||
('FR', Locale('fr')),
|
||||
('AR', Locale('ar')),
|
||||
];
|
||||
: cs.surfaceContainerHighest;
|
||||
final iconColor = onDark
|
||||
? Colors.white.withValues(alpha: 0.8)
|
||||
: cs.onSurfaceVariant;
|
||||
final langCode = currentLocale.languageCode.toUpperCase();
|
||||
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// Language pills
|
||||
...langs.map((item) {
|
||||
final (code, locale) = item;
|
||||
final selected =
|
||||
currentLocale.languageCode == locale.languageCode;
|
||||
return GestureDetector(
|
||||
onTap: () => ref.read(localeProvider.notifier).setLocale(locale),
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(right: 6),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 11, vertical: 6),
|
||||
decoration: BoxDecoration(
|
||||
color: selected ? _orange : inactiveBg,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: Text(
|
||||
code,
|
||||
style: TextStyle(
|
||||
color: selected ? activeText : inactiveText,
|
||||
fontSize: 12,
|
||||
fontWeight:
|
||||
selected ? FontWeight.bold : FontWeight.normal,
|
||||
),
|
||||
// ── Language dropdown ──────────────────────────────────────────
|
||||
PopupMenuButton<Locale>(
|
||||
onSelected: (locale) =>
|
||||
ref.read(localeProvider.notifier).setLocale(locale),
|
||||
color: cs.surfaceContainerHigh,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
side: BorderSide(color: cs.outlineVariant),
|
||||
),
|
||||
offset: const Offset(0, 36),
|
||||
itemBuilder: (_) => _langs.map((item) {
|
||||
final (code, locale) = item;
|
||||
final selected =
|
||||
currentLocale.languageCode == locale.languageCode;
|
||||
return PopupMenuItem<Locale>(
|
||||
value: locale,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
code,
|
||||
style: TextStyle(
|
||||
color: selected ? _orange : cs.onSurface,
|
||||
fontWeight: selected
|
||||
? FontWeight.bold
|
||||
: FontWeight.normal,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (selected)
|
||||
const Icon(Icons.check, size: 16, color: _orange),
|
||||
],
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
child: Container(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
|
||||
decoration: BoxDecoration(
|
||||
color: chipBg,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
);
|
||||
}),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
langCode,
|
||||
style: TextStyle(
|
||||
color: onDark ? Colors.white : cs.onSurface,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 2),
|
||||
Icon(
|
||||
Icons.expand_more,
|
||||
size: 14,
|
||||
color: iconColor,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(width: 2),
|
||||
const SizedBox(width: 6),
|
||||
|
||||
// Theme toggle icon
|
||||
// ── Theme toggle ───────────────────────────────────────────────
|
||||
GestureDetector(
|
||||
onTap: () => ref.read(themeProvider.notifier).toggle(),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(7),
|
||||
decoration: BoxDecoration(
|
||||
color: inactiveBg,
|
||||
color: chipBg,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: Icon(
|
||||
isDark ? Icons.light_mode_outlined : Icons.dark_mode_outlined,
|
||||
size: 15,
|
||||
color: onDark
|
||||
? Colors.white.withValues(alpha: 0.8)
|
||||
: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
color: iconColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -63,7 +63,7 @@ class ReservationCard extends StatelessWidget {
|
||||
size: 14, color: Color(0xFF9CA3AF)),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
'\$${reservation.totalAmount.toStringAsFixed(2)}',
|
||||
'\$${(reservation.totalAmount / 100).toStringAsFixed(2)}',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Color(0xFF111928),
|
||||
|
||||
@@ -41,6 +41,8 @@ class StatusBadge extends StatelessWidget {
|
||||
return (const Color(0xFF1A56DB), const Color(0xFFE1EFFE), 'Active');
|
||||
case 'COMPLETED':
|
||||
return (const Color(0xFF5521B5), const Color(0xFFEDEBFE), 'Completed');
|
||||
case 'CLOSED':
|
||||
return (const Color(0xFF374151), const Color(0xFFF3F4F6), 'Closed');
|
||||
case 'CANCELLED':
|
||||
return (const Color(0xFF9B1C1C), const Color(0xFFFDE8E8), 'Cancelled');
|
||||
case 'DRAFT':
|
||||
@@ -49,6 +51,10 @@ class StatusBadge extends StatelessWidget {
|
||||
return (const Color(0xFF9B1C1C), const Color(0xFFFDE8E8), 'No Show');
|
||||
case 'PENDING':
|
||||
return (const Color(0xFFB45309), const Color(0xFFFDF6B2), 'Pending');
|
||||
case 'PARTIAL':
|
||||
return (const Color(0xFFB45309), const Color(0xFFFDF6B2), 'Partial');
|
||||
case 'PAID':
|
||||
return (const Color(0xFF057A55), const Color(0xFFDEF7EC), 'Paid');
|
||||
case 'SUCCEEDED':
|
||||
return (const Color(0xFF057A55), const Color(0xFFDEF7EC), 'Paid');
|
||||
case 'FAILED':
|
||||
|
||||
@@ -55,7 +55,7 @@ class VehicleCard extends StatelessWidget {
|
||||
const Icon(Icons.attach_money,
|
||||
size: 16, color: Color(0xFF1A56DB)),
|
||||
Text(
|
||||
'${vehicle.dailyRate.toStringAsFixed(0)}/day',
|
||||
'\$${(vehicle.dailyRate / 100).toStringAsFixed(0)}/day',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Color(0xFF1A56DB),
|
||||
|
||||
Reference in New Issue
Block a user