- App.tsx: full navigation (Auth stack + Main tabs with 5 screens) - Auth: LoginScreen, RegisterScreen, ForgotPasswordScreen - HomeScreen: dashboard with IoT metrics, weather widget, alerts, quick actions, sensors - MapScreen: interactive map with layer toggles (6 layers) - MarketplaceScreen: categories (6), products (5), search - ChatScreen: AI chat with quick prompts (4), bot responses - ProfileScreen: user info, stats, menu (9 items), logout - AlertsScreen: alert list with severity, acknowledge - SensorsScreen: sensor list with type filters (6 types), search - ZonesScreen: zone cards with stats - SettingsScreen: language picker (FR/EN/ES/DE), privacy, about - Stores: iotStore (sensors, zones, alerts), notificationStore, uiStore + i18n - Hooks: useSensors, useAlerts, useNotifications, useLocation - Components: Card, Button, LoadingSpinner, ErrorBoundary, Header - Services: iotService, notificationService (with axios API client) - Utils: formatters (temp, AQI, noise, dates), validators (email, password, IBAN) - Theme: colors.ts with full design system (Blue Ocean palette) - Ditto: fixed MongoDB connection, new JWT secrets, official gateway image
355 lines
13 KiB
HTML
355 lines
13 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="fr">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Smart App City — 06 Profil Utilisateur</title>
|
||
<link rel="stylesheet" href="shared.css">
|
||
<style>
|
||
.profile-header {
|
||
padding: 20px 16px;
|
||
background: linear-gradient(135deg, var(--primary-500), var(--ocean-500));
|
||
color: white;
|
||
text-align: center;
|
||
}
|
||
.profile-avatar {
|
||
width: 80px; height: 80px;
|
||
border-radius: var(--radius-full);
|
||
background: rgba(255,255,255,0.2);
|
||
display: flex; align-items: center; justify-content: center;
|
||
font-size: 36px;
|
||
margin: 0 auto 12px;
|
||
border: 3px solid rgba(255,255,255,0.3);
|
||
}
|
||
.profile-name {
|
||
font-size: var(--text-lg);
|
||
font-weight: var(--weight-bold);
|
||
margin-bottom: 2px;
|
||
}
|
||
.profile-email {
|
||
font-size: var(--text-sm);
|
||
opacity: 0.8;
|
||
margin-bottom: 8px;
|
||
}
|
||
.profile-badge {
|
||
display: inline-block;
|
||
background: rgba(255,255,255,0.2);
|
||
border-radius: var(--radius-full);
|
||
padding: 4px 12px;
|
||
font-size: var(--text-xs);
|
||
font-weight: var(--weight-semibold);
|
||
}
|
||
|
||
.stat-row {
|
||
display: flex;
|
||
justify-content: center;
|
||
gap: 32px;
|
||
margin-top: 16px;
|
||
}
|
||
.stat-item { text-align: center; }
|
||
.stat-value {
|
||
font-size: var(--text-xl);
|
||
font-weight: var(--weight-bold);
|
||
}
|
||
.stat-label {
|
||
font-size: var(--text-xs);
|
||
opacity: 0.7;
|
||
}
|
||
|
||
.menu-section { padding: 16px; }
|
||
.menu-section-title {
|
||
font-size: var(--text-xs);
|
||
font-weight: var(--weight-semibold);
|
||
color: var(--neutral-400);
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.5px;
|
||
margin-bottom: 8px;
|
||
padding-left: 4px;
|
||
}
|
||
.menu-item {
|
||
display: flex; align-items: center; gap: 14px;
|
||
padding: 14px 12px;
|
||
border-radius: var(--radius-md);
|
||
cursor: pointer;
|
||
transition: background 0.15s;
|
||
}
|
||
.menu-item:hover { background: var(--neutral-50); }
|
||
.menu-icon {
|
||
width: 38px; height: 38px;
|
||
border-radius: var(--radius-md);
|
||
display: flex; align-items: center; justify-content: center;
|
||
font-size: 18px;
|
||
flex-shrink: 0;
|
||
}
|
||
.menu-text { flex: 1; }
|
||
.menu-label {
|
||
font-size: var(--text-sm);
|
||
font-weight: var(--weight-medium);
|
||
}
|
||
.menu-sub {
|
||
font-size: var(--text-xs);
|
||
color: var(--neutral-400);
|
||
}
|
||
.menu-arrow {
|
||
color: var(--neutral-300);
|
||
}
|
||
.menu-value {
|
||
font-size: var(--text-sm);
|
||
color: var(--neutral-500);
|
||
margin-right: 4px;
|
||
}
|
||
|
||
.lang-flags {
|
||
display: flex; gap: 6px;
|
||
}
|
||
.lang-flag {
|
||
width: 24px; height: 24px;
|
||
border-radius: 50%;
|
||
display: flex; align-items: center; justify-content: center;
|
||
font-size: 12px;
|
||
cursor: pointer;
|
||
opacity: 0.5;
|
||
transition: opacity 0.2s;
|
||
}
|
||
.lang-flag.active { opacity: 1; box-shadow: 0 0 0 2px var(--primary-500); }
|
||
|
||
.toggle-switch {
|
||
width: 44px; height: 24px;
|
||
border-radius: 12px;
|
||
background: var(--primary-500);
|
||
position: relative;
|
||
cursor: pointer;
|
||
}
|
||
.toggle-switch::after {
|
||
content: '';
|
||
position: absolute;
|
||
width: 20px; height: 20px;
|
||
border-radius: 50%;
|
||
background: white;
|
||
top: 2px; right: 2px;
|
||
transition: all 0.2s;
|
||
}
|
||
/* Fixed viewport for PDF/iframe embedding */
|
||
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
|
||
</style>
|
||
<style>
|
||
/* Fixed viewport for PDF/iframe embedding */
|
||
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="mobile-frame">
|
||
<!-- Status Bar -->
|
||
<div class="status-bar">
|
||
<span>9:41</span>
|
||
<div style="display:flex;gap:4px;align-items:center;">
|
||
<svg width="16" height="12" viewBox="0 0 16 12"><rect x="0" y="4" width="3" height="8" rx="1" fill="#333"/><rect x="4.5" y="2.5" width="3" height="9.5" rx="1" fill="#333"/><rect x="9" y="0" width="3" height="12" rx="1" fill="#333"/><rect x="13.5" y="0" width="2.5" height="12" rx="1" fill="#ccc"/></svg>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Profile Header -->
|
||
<div class="profile-header">
|
||
<div class="profile-avatar">👤</div>
|
||
<div class="profile-name">Eric FELIXINE</div>
|
||
<div class="profile-email">efelixine@digitribe.fr</div>
|
||
<div class="profile-badge">🏙️ Citoyen Smart City</div>
|
||
<div class="stat-row">
|
||
<div class="stat-item">
|
||
<div class="stat-value">12</div>
|
||
<div class="stat-label">Signalements</div>
|
||
</div>
|
||
<div class="stat-item">
|
||
<div class="stat-value">3.2k</div>
|
||
<div class="stat-label">Points</div>
|
||
</div>
|
||
<div class="stat-item">
|
||
<div class="stat-value">48</div>
|
||
<div class="stat-label">Visites</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Content -->
|
||
<div class="content-area" style="top:230px;background:var(--neutral-50);">
|
||
|
||
<!-- Langue -->
|
||
<div class="menu-section">
|
||
<div class="menu-section-title">Langue / Language / Idioma / Sprache</div>
|
||
<div style="background:white;border-radius:var(--radius-lg);overflow:hidden;border:1px solid var(--neutral-100);">
|
||
<div class="menu-item">
|
||
<div class="menu-text">
|
||
<div class="menu-label">Langue de l'application</div>
|
||
<div class="menu-sub">Sélectionnez votre langue</div>
|
||
</div>
|
||
<div class="lang-flags">
|
||
<div class="lang-flag active" style="background:#E3F2FD;">🇫🇷</div>
|
||
<div class="lang-flag" style="background:#FCE4EC;">🇬🇧</div>
|
||
<div class="lang-flag" style="background:#FFF9C4;">🇪🇸</div>
|
||
<div class="lang-flag" style="background:#F3E5F5;">🇩🇪</div>
|
||
</div>
|
||
<span class="menu-arrow">›</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Mon compte -->
|
||
<div class="menu-section">
|
||
<div class="menu-section-title">Mon compte</div>
|
||
<div style="background:white;border-radius:var(--radius-lg);overflow:hidden;border:1px solid var(--neutral-100);">
|
||
<div class="menu-item">
|
||
<div class="menu-icon" style="background:#E3F2FD;">👤</div>
|
||
<div class="menu-text">
|
||
<div class="menu-label">Informations personnelles</div>
|
||
</div>
|
||
<span class="menu-arrow">›</span>
|
||
</div>
|
||
<div style="height:1px;background:var(--neutral-100);margin:0 12px;"></div>
|
||
<div class="menu-item">
|
||
<div class="menu-icon" style="background:#E8F5E9;">🏙️</div>
|
||
<div class="menu-text">
|
||
<div class="menu-label">Ma ville</div>
|
||
</div>
|
||
<span class="menu-value">Fort-de-France</span>
|
||
<span class="menu-arrow">›</span>
|
||
</div>
|
||
<div style="height:1px;background:var(--neutral-100);margin:0 12px;"></div>
|
||
<div class="menu-item">
|
||
<div class="menu-icon" style="background:#FFF3E0;">📊</div>
|
||
<div class="menu-text">
|
||
<div class="menu-label">Mon activité</div>
|
||
<div class="menu-sub">Signalements, visites, contributions</div>
|
||
</div>
|
||
<span class="menu-arrow">›</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Préférences -->
|
||
<div class="menu-section">
|
||
<div class="menu-section-title">Préférences</div>
|
||
<div style="background:white;border-radius:var(--radius-lg);overflow:hidden;border:1px solid var(--neutral-100);">
|
||
<div class="menu-item">
|
||
<div class="menu-icon" style="background:#F3E5F5;">🌙</div>
|
||
<div class="menu-text">
|
||
<div class="menu-label">Mode sombre</div>
|
||
</div>
|
||
<div class="toggle-switch"></div>
|
||
</div>
|
||
<div style="height:1px;background:var(--neutral-100);margin:0 12px;"></div>
|
||
<div class="menu-item">
|
||
<div class="menu-icon" style="background:#FCE4EC;">🔔</div>
|
||
<div class="menu-text">
|
||
<div class="menu-label">Notifications</div>
|
||
<div class="menu-sub">Alertes, événements, mises à jour</div>
|
||
</div>
|
||
<div class="toggle-switch"></div>
|
||
</div>
|
||
<div style="height:1px;background:var(--neutral-100);margin:0 12px;"></div>
|
||
<div class="menu-item">
|
||
<div class="menu-icon" style="background:#FFF9C4;">📍</div>
|
||
<div class="menu-text">
|
||
<div class="menu-label">Géolocalisation</div>
|
||
<div class="menu-sub">Services basés sur la position</div>
|
||
</div>
|
||
<div class="toggle-switch"></div>
|
||
</div>
|
||
<div style="height:1px;background:var(--neutral-100);margin:0 12px;"></div>
|
||
<div class="menu-item">
|
||
<div class="menu-icon" style="background:#E0F7FA;">🗺️</div>
|
||
<div class="menu-text">
|
||
<div class="menu-label">Unités</div>
|
||
</div>
|
||
<span class="menu-value">Métrique</span>
|
||
<span class="menu-arrow">›</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Beckn / DPI -->
|
||
<div class="menu-section">
|
||
<div class="menu-section-title">Beckn · DPI · OTN</div>
|
||
<div style="background:white;border-radius:var(--radius-lg);overflow:hidden;border:1px solid var(--neutral-100);">
|
||
<div class="menu-item">
|
||
<div class="menu-icon" style="background:#E8F5E9;">💳</div>
|
||
<div class="menu-text">
|
||
<div class="menu-label">Portefeuille numérique</div>
|
||
<div class="menu-sub">Paiements Beckn/DPI</div>
|
||
</div>
|
||
<span class="menu-arrow">›</span>
|
||
</div>
|
||
<div style="height:1px;background:var(--neutral-100);margin:0 12px;"></div>
|
||
<div class="menu-item">
|
||
<div class="menu-icon" style="background:#E3F2FD;">📦</div>
|
||
<div class="menu-text">
|
||
<div class="menu-label">Mes commandes</div>
|
||
<div class="menu-sub">Historique des transactions</div>
|
||
</div>
|
||
<span class="menu-arrow">›</span>
|
||
</div>
|
||
<div style="height:1px;background:var(--neutral-100);margin:0 12px;"></div>
|
||
<div class="menu-item">
|
||
<div class="menu-icon" style="background:#F3E5F5;">🔐</div>
|
||
<div class="menu-text">
|
||
<div class="menu-label">Identité décentralisée (DID)</div>
|
||
</div>
|
||
<span class="menu-arrow">›</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ODK / Signalements -->
|
||
<div class="menu-section">
|
||
<div class="menu-section-title">Signalements</div>
|
||
<div style="background:white;border-radius:var(--radius-lg);overflow:hidden;border:1px solid var(--neutral-100);">
|
||
<div class="menu-item">
|
||
<div class="menu-icon" style="background:#FFF3E0;">📸</div>
|
||
<div class="menu-text">
|
||
<div class="menu-label">Mes signalements</div>
|
||
<div class="menu-sub">12 signalements soumis</div>
|
||
</div>
|
||
<span class="menu-value">12</span>
|
||
<span class="menu-arrow">›</span>
|
||
</div>
|
||
<div style="height:1px;background:var(--neutral-100);margin:0 12px;"></div>
|
||
<div class="menu-item">
|
||
<div class="menu-icon" style="background:#FCE4EC;">📋</div>
|
||
<div class="menu-text">
|
||
<div class="menu-label">Formulaires ODK</div>
|
||
</div>
|
||
<span class="menu-arrow">›</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="height:16px;"></div>
|
||
</div>
|
||
|
||
<!-- Bottom Nav -->
|
||
<div class="bottom-nav">
|
||
<div class="bottom-nav-item">
|
||
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg>
|
||
<span>Accueil</span>
|
||
</div>
|
||
<div class="bottom-nav-item">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg>
|
||
<span>Carte</span>
|
||
</div>
|
||
<div class="bottom-nav-item">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg>
|
||
<span>AI Chat</span>
|
||
</div>
|
||
<div class="bottom-nav-item">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
|
||
<span>Marché</span>
|
||
</div>
|
||
<div class="bottom-nav-item active">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
|
||
<span>Profil</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="position:absolute;bottom:88px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-400);">06 — Profil & Paramètres</div>
|
||
</div>
|
||
</body>
|
||
</html>
|