- Drawer custom (overlay Stack) avec mode installateur PIN SHA-256 - GoRouter + ShellRoute : navigation préservée entre onglets - 6 providers : NavigationProvider, InstallerModeProvider, AppSettingsProvider, EnergySetupProvider, SchedulerProvider, TariffProvider - Écrans Energy Manager : RoleConfigFlow (3 étapes), Scheduler, Tarifs, Timeline - Écrans Paramètres : Apparence, Écrans actifs, AppSettingsScreen - DrawerMenuButton présent dans les 5 AppBars principaux - Simulation : _thingClasses générées avec interfaces EMS pour filtrage des rôles - Compteur solaire : ajout smartmeter aux interfaces compatibles - Thème ETM (etm_theme.dart), ProLockBadge, widgets PowerBar/RoleCard/TimelineSlotCard - Dépendances : go_router, shared_preferences, crypto, url_launcher Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
142 lines
5.1 KiB
Dart
142 lines
5.1 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
/// Système de design ETM PowerSync
|
|
/// Complète AppTheme (couleurs énergie) avec les couleurs de marque ETM.
|
|
class ETMTheme {
|
|
// ── Couleurs de marque ────────────────────────────────────────────────────────
|
|
static const Color primaryColor = Color(0xFF1B3A5C); // ETM dark blue
|
|
static const Color accentColor = Color(0xFF2E75B6); // ETM mid blue
|
|
static const Color successColor = Color(0xFF1E6B3C); // green
|
|
static const Color warningColor = Color(0xFFC55A11); // orange
|
|
static const Color errorColor = Color(0xFFB71C1C); // red
|
|
static const Color proColor = Color(0xFF5B2C8D); // purple (Pro features)
|
|
|
|
// ── Drawer ───────────────────────────────────────────────────────────────────
|
|
static const Color drawerBackground = Color(0xFF0F2133);
|
|
static const Color drawerSurface = Color(0xFF1A3249);
|
|
static const Color drawerItemActive = Color(0xFF2E75B6);
|
|
static const Color drawerTextPrimary = Color(0xFFEEF2F7);
|
|
static const Color drawerTextMuted = Color(0xFF8FA9C4);
|
|
static const double drawerWidth = 285.0;
|
|
|
|
// ── Badge "INSTALLATEUR" ─────────────────────────────────────────────────────
|
|
static const Color installerBadgeColor = Color(0xFFE65100);
|
|
|
|
// ── Widget Pro Lock ──────────────────────────────────────────────────────────
|
|
static Widget proLock(
|
|
BuildContext context,
|
|
String featureName, {
|
|
Widget? child,
|
|
}) {
|
|
return GestureDetector(
|
|
onTap: () => _showProBottomSheet(context, featureName),
|
|
child: Stack(
|
|
children: [
|
|
if (child != null)
|
|
Opacity(opacity: 0.5, child: child),
|
|
Positioned(
|
|
top: 2,
|
|
right: 2,
|
|
child: _ProBadge(),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
static void _showProBottomSheet(BuildContext context, String featureName) {
|
|
showModalBottomSheet(
|
|
context: context,
|
|
shape: const RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
|
|
),
|
|
builder: (_) => _ProBottomSheet(featureName: featureName),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _ProBadge extends StatelessWidget {
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 2),
|
|
decoration: BoxDecoration(
|
|
color: ETMTheme.proColor,
|
|
borderRadius: BorderRadius.circular(6),
|
|
),
|
|
child: const Text(
|
|
'🔒 Pro',
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontSize: 9,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _ProBottomSheet extends StatelessWidget {
|
|
final String featureName;
|
|
const _ProBottomSheet({required this.featureName});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Padding(
|
|
padding: const EdgeInsets.fromLTRB(24, 20, 24, 32),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Container(
|
|
width: 36, height: 4,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
borderRadius: BorderRadius.circular(2),
|
|
),
|
|
),
|
|
const SizedBox(height: 20),
|
|
Container(
|
|
width: 56, height: 56,
|
|
decoration: BoxDecoration(
|
|
color: ETMTheme.proColor.withValues(alpha: 0.12),
|
|
shape: BoxShape.circle,
|
|
),
|
|
child: const Icon(Icons.lock_rounded, color: ETMTheme.proColor, size: 28),
|
|
),
|
|
const SizedBox(height: 16),
|
|
Text(
|
|
featureName,
|
|
style: const TextStyle(
|
|
fontSize: 18,
|
|
fontWeight: FontWeight.bold,
|
|
color: Color(0xFF1A1A2E),
|
|
),
|
|
),
|
|
const SizedBox(height: 8),
|
|
const Text(
|
|
'Cette fonctionnalité est disponible en version Pro.',
|
|
textAlign: TextAlign.center,
|
|
style: TextStyle(fontSize: 14, color: Color(0xFF6B7280)),
|
|
),
|
|
const SizedBox(height: 24),
|
|
SizedBox(
|
|
width: double.infinity,
|
|
child: ElevatedButton(
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: ETMTheme.proColor,
|
|
foregroundColor: Colors.white,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(12),
|
|
),
|
|
padding: const EdgeInsets.symmetric(vertical: 14),
|
|
),
|
|
onPressed: () => Navigator.pop(context),
|
|
child: const Text('En savoir plus'),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|