Files
smart-city-digital-twin-mar…/smart-app-city/design/04-marketplace.html
Eric FELIXINE e30ae8ed09 feat(smart-app): implement complete mobile app MVP
- 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
2026-06-01 18:00:35 -04:00

356 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 — 04 Marketplace Beckn/DPI</title>
<link rel="stylesheet" href="shared.css">
<style>
.market-header {
padding: 16px;
background: white;
border-bottom: 1px solid var(--neutral-200);
}
.market-search {
display: flex; align-items: center; gap: 8px;
background: var(--neutral-100);
border-radius: var(--radius-full);
padding: 10px 16px;
font-size: var(--text-sm);
color: var(--neutral-500);
margin-bottom: 12px;
}
.category-tabs {
display: flex; gap: 8px;
overflow-x: auto;
scrollbar-width: none;
}
.category-tabs::-webkit-scrollbar { display: none; }
.cat-tab {
flex-shrink: 0;
padding: 8px 16px;
border-radius: var(--radius-full);
font-size: var(--text-sm);
font-weight: var(--weight-medium);
background: var(--neutral-100);
color: var(--neutral-600);
cursor: pointer;
transition: all 0.2s;
white-space: nowrap;
}
.cat-tab.active {
background: var(--primary-500);
color: white;
}
.market-content {
padding: 16px;
}
.featured-card {
background: linear-gradient(135deg, #1B5E20, #00838F);
border-radius: var(--radius-xl);
padding: 20px;
color: white;
margin-bottom: 16px;
position: relative;
overflow: hidden;
}
.featured-card::after {
content: '';
position: absolute;
width: 150px; height: 150px;
border-radius: 50%;
background: rgba(255,255,255,0.08);
top: -40px; right: -30px;
}
.featured-tag {
display: inline-block;
background: rgba(255,255,255,0.2);
border-radius: var(--radius-full);
padding: 4px 10px;
font-size: 10px;
font-weight: 600;
margin-bottom: 8px;
}
.featured-title {
font-size: var(--text-lg);
font-weight: var(--weight-bold);
margin-bottom: 4px;
}
.featured-desc {
font-size: var(--text-sm);
opacity: 0.8;
margin-bottom: 12px;
}
.product-card {
background: white;
border-radius: var(--radius-lg);
overflow: hidden;
box-shadow: var(--shadow-sm);
border: 1px solid var(--neutral-100);
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
}
.product-card:hover {
transform: translateY(-2px);
box-shadow: var(--shadow-md);
}
.product-img {
height: 120px;
display: flex; align-items: center; justify-content: center;
font-size: 40px;
}
.product-info { padding: 12px; }
.product-name {
font-size: var(--text-sm);
font-weight: var(--weight-semibold);
margin-bottom: 2px;
}
.product-shop {
font-size: var(--text-xs);
color: var(--neutral-500);
margin-bottom: 6px;
}
.product-meta {
display: flex; justify-content: space-between;
align-items: center;
}
.product-price {
font-size: var(--text-md);
font-weight: var(--weight-bold);
color: var(--primary-500);
}
.product-rating {
font-size: var(--text-xs);
color: var(--alert-warning);
}
.product-distance {
font-size: 10px;
color: var(--neutral-400);
}
.service-card {
display: flex; gap: 12px;
background: white;
border-radius: var(--radius-lg);
padding: 14px;
box-shadow: var(--shadow-sm);
border: 1px solid var(--neutral-100);
margin-bottom: 10px;
cursor: pointer;
}
.service-icon {
width: 48px; height: 48px;
border-radius: var(--radius-md);
display: flex; align-items: center; justify-content: center;
font-size: 22px;
flex-shrink: 0;
}
.service-info { flex: 1; }
.service-name {
font-size: var(--text-sm);
font-weight: var(--weight-semibold);
margin-bottom: 2px;
}
.service-desc {
font-size: var(--text-xs);
color: var(--neutral-500);
margin-bottom: 4px;
}
.service-tags {
display: flex; gap: 4px;
}
.service-tag {
font-size: 9px;
padding: 2px 8px;
border-radius: var(--radius-full);
background: var(--ocean-50);
color: var(--ocean-600);
font-weight: 600;
}
/* 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>
<!-- Header -->
<div class="market-header">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;">
<div style="font-size:var(--text-lg);font-weight:700;">Marché Local 🏪</div>
<div style="position:relative;">
<svg class="icon" viewBox="0 0 24 24"><circle cx="9" cy="21" r="1"/><circle cx="20" cy="21" r="1"/><path d="M1 1h4l2.68 13.39a2 2 0 002 1.61h9.72a2 2 0 002-1.61L23 6H6"/></svg>
<div class="badge" style="position:absolute;top:-6px;right:-6px;">2</div>
</div>
</div>
<div class="market-search">
<svg class="icon" viewBox="0 0 24 24"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
Produits, services, commerces...
</div>
<div class="category-tabs">
<div class="cat-tab active">🍎 Alimentaire</div>
<div class="cat-tab">🚌 Transport</div>
<div class="cat-tab">🏥 Santé</div>
<div class="cat-tab">⚡ Énergie</div>
<div class="cat-tab">🎭 Culture</div>
<div class="cat-tab">🔧 Services</div>
</div>
</div>
<!-- Content -->
<div class="content-area" style="background:var(--neutral-50);top:140px;">
<div class="market-content">
<!-- Featured -->
<div class="featured-card">
<div class="featured-tag">⭐ Beckn Protocol</div>
<div class="featured-title">Marché de Sainte-Marie</div>
<div class="featured-desc">Produits locaux · Producteurs martiniquais · Livraison 2h</div>
<div style="display:flex;gap:8px;">
<button class="btn" style="background:white;color:var(--primary-600);padding:8px 16px;font-size:13px;min-height:36px;">Explorer</button>
<button class="btn" style="background:rgba(255,255,255,0.2);color:white;padding:8px 16px;font-size:13px;min-height:36px;">Infos</button>
</div>
</div>
<!-- Section -->
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;">
<div style="font-size:var(--text-md);font-weight:700;">Produits frais 🥭</div>
<div style="font-size:var(--text-sm);color:var(--primary-500);font-weight:500;">Voir tout →</div>
</div>
<!-- Product Grid -->
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:20px;">
<div class="product-card">
<div class="product-img" style="background:linear-gradient(135deg,#FFF3E0,#FFE0B2);">🥭</div>
<div class="product-info">
<div class="product-name">Mangue José</div>
<div class="product-shop">Bourg de Sainte-Marie</div>
<div class="product-meta">
<div class="product-price">4.50€</div>
<div class="product-rating">⭐ 4.8</div>
</div>
<div class="product-distance">📍 2.3 km</div>
</div>
</div>
<div class="product-card">
<div class="product-img" style="background:linear-gradient(135deg,#E8F5E9,#C8E6C9);">🍌</div>
<div class="product-info">
<div class="product-name">Banane Plantain</div>
<div class="product-shop">Habitation Limbé</div>
<div class="product-meta">
<div class="product-price">3.20€</div>
<div class="product-rating">⭐ 4.6</div>
</div>
<div class="product-distance">📍 5.1 km</div>
</div>
</div>
<div class="product-card">
<div class="product-img" style="background:linear-gradient(135deg,#FCE4EC,#F8BBD0);">🍅</div>
<div class="product-info">
<div class="product-name">Tomates locales</div>
<div class="product-shop">Jardin du Lamentin</div>
<div class="product-meta">
<div class="product-price">2.80€</div>
<div class="product-rating">⭐ 4.9</div>
</div>
<div class="product-distance">📍 3.7 km</div>
</div>
</div>
<div class="product-card">
<div class="product-img" style="background:linear-gradient(135deg,#E3F2FD,#BBDEFB);">🐟</div>
<div class="product-info">
<div class="product-name">Poisson frais</div>
<div class="product-shop">Pêcheur du Carbet</div>
<div class="product-meta">
<div class="product-price">12.00€</div>
<div class="product-rating">⭐ 4.7</div>
</div>
<div class="product-distance">📍 8.2 km</div>
</div>
</div>
</div>
<!-- Services Section -->
<div style="font-size:var(--text-md);font-weight:700;margin-bottom:12px;">Services proches 🔧</div>
<div class="service-card">
<div class="service-icon" style="background:#E3F2FD;">🚌</div>
<div class="service-info">
<div class="service-name">Transport collectif — Ligne A1</div>
<div class="service-desc">FDF ↔ Trinité · Toutes les 15 min</div>
<div class="service-tags">
<div class="service-tag">Beckn</div>
<div class="service-tag">DPI</div>
<div class="service-tag">Temps réel</div>
</div>
</div>
</div>
<div class="service-card">
<div class="service-icon" style="background:#E8F5E9;"></div>
<div class="service-info">
<div class="service-name">Borne recharge — Centre-ville</div>
<div class="service-desc">4 bornes disponibles · 22kW AC</div>
<div class="service-tags">
<div class="service-tag">OTN</div>
<div class="service-tag">Paiement mobile</div>
</div>
</div>
</div>
<div class="service-card">
<div class="service-icon" style="background:#FFF3E0;">🏥</div>
<div class="service-info">
<div class="service-name">Pharmacie de garde — FDF</div>
<div class="service-desc">Ouverte 24h/24 · Av. des Caraïbes</div>
<div class="service-tags">
<div class="service-tag">Urgence</div>
<div class="service-tag">1.2 km</div>
</div>
</div>
</div>
<div style="height:16px;"></div>
</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 active">
<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">
<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);">04 — Marketplace Beckn/DPI</div>
</div>
</body>
</html>