// LuzAlerts — Screens 1–4: Onboarding, Map, List, Detail /* ── FAKE MAP SVG (Google Maps dark style) ── */ const MAP_TOKENS = { bg: '#1b2336', block: '#1f2942', blockAlt: '#1c2640', park: '#22432d', parkLabel: '#5e8a6f', water: '#102842', // Road tiers tertStroke: '#2a3550', secCasing: '#2f3c5a', secFill: '#3e4d6e', priCasing: '#3b4b6c', priFill: '#5a6b94', hwyCasing: '#5a4a2a', hwyFill: '#c8a559', // Labels labelMajor: '#aebbd2', labelMinor: '#7a8aa8', }; const DarkMap = ({ h = 340, markerSelected = null }) => { const W = 393; const T = MAP_TOKENS; const hRoads = [ { y: 36, name: 'Av. Aviadores del Chaco', tier: 'pri', off: 16 }, { y: 76, name: 'Mcal. Estigarribia', tier: 'sec', off: 22 }, { y: 132, name: 'Av. Mcal. López', tier: 'hwy', off: 18 }, { y: 174, name: 'Brasilia', tier: 'sec', off: 60 }, { y: 214, name: 'Av. España', tier: 'pri', off: 28 }, { y: 254, name: 'Cnel. Bogado', tier: 'sec', off: 50 }, { y: 296, name: 'Av. Eusebio Ayala', tier: 'pri', off: 18 }, ].filter(r => r.y > -10 && r.y < h + 10); const vRoads = [ { x: 58, name: 'Sajonia', tier: 'sec', off: 22 }, { x: 128, name: 'Cruz del Chaco', tier: 'pri', off: 26 }, { x: 208, name: 'Madame Lynch', tier: 'pri', off: 24 }, { x: 276, name: 'San Martín', tier: 'sec', off: 28 }, { x: 344, name: 'Las Heras', tier: 'sec', off: 22 }, ]; // road widths per tier (casing, fill) const W_ROAD = { tert: [0, 1.5], sec: [4.5, 3], pri: [9, 7], hwy: [11, 8.5] }; const COLOR = { tert: { c: T.tertStroke, f: T.tertStroke }, sec: { c: T.secCasing, f: T.secFill }, pri: { c: T.priCasing, f: T.priFill }, hwy: { c: T.hwyCasing, f: T.hwyFill }, }; const hRoadLine = (r, useFill) => ( ); const vRoadLine = (r, useFill) => ( ); const tertY = [56, 96, 154, 194, 234, 274].filter(y => y > 0 && y < h); const tertX = [28, 92, 166, 244, 308, 376]; return ( {/* Base */} {/* Block tinting — subtle alternating fills between major roads */} {/* Park (Parque de la Salud area) */} Parque{'\u00A0'}Caballero {/* Tertiary grid (alleys / minor streets) */} {tertY.map((y, i) => )} {tertX.map((x, i) => )} {/* Road casings (darker outline below fills) */} {hRoads.map((r, i) => {hRoadLine(r, false)})} {vRoads.map((r, i) => {vRoadLine(r, false)})} {/* Road fills (lighter center) */} {hRoads.map((r, i) => {hRoadLine(r, true)})} {vRoads.map((r, i) => {vRoadLine(r, true)})} {/* Road labels */} {hRoads.map((r, i) => { const isMajor = r.tier === 'pri' || r.tier === 'hwy'; return ( {r.name} ); })} {vRoads.map((r, i) => { const isMajor = r.tier === 'pri'; const cx = r.x + 3, cy = r.off + 60; return ( {r.name} ); })} {/* User location — blue dot */} {/* Markers — programado (amber) */} {/* Markers — activo (red) */} {/* Markers — resuelto (green) */} {/* Marker — crowdsource (violet) */} ); }; const MapPin = ({ cx, cy, color, pulse = false, selected = false, crowd = false }) => { // cy = tip of pin. body sits above. const W = 20, H = 26, R = 5; const top = cy - H - 14; // top of rectangle return ( {pulse && ( )} {/* Badge body */} {/* Triangle tail */} {/* ! bar */} {/* ! dot */} {crowd && ( 👥 )} ); }; const MiniMap = ({ color = '#EF4444' }) => { const T = MAP_TOKENS; const W = 361, H = 160; return (
{/* Block tints around the focus point */} {/* Tertiary streets */} {[30, 120].map((y, i) => )} {[80, 280].map((x, i) => )} {/* Primary horizontal — Av. Mcal. López */} {/* Primary vertical — Cruz del Chaco */} {/* Labels */} Av. Mcal. López Cruz del Chaco Av. España {/* Halo + pin at intersection */}
Abrir en Mapa
); }; /* ── SCREEN 1: Onboarding ── */ const ONBOARDING_TOTAL = 4; const OnboardingDots = ({ active }) => (
{Array.from({ length: ONBOARDING_TOTAL }).map((_, i) => (
))}
); const OnboardingSlide = ({ slide }) => { const slides = [ { icon: IZap, color: '#F59E0B', title: 'Cortes de luz\nen tiempo real', body: 'Datos oficiales de la ANDE actualizados cada hora, más reportes de usuarios de toda Paraguay.', cta: 'Siguiente', dot: 0 }, { icon: IPin, color: '#EF4444', title: 'Tu zona,\nsiempre actualizada', body: 'El mapa muestra cortes planificados y activos cerca de vos. Si hay un corte, podés reportarlo en un toque.', cta: 'Siguiente', dot: 1 }, { icon: IBell, color: '#0A84FF', title: 'Avisamos cuando\nhay un corte', body: 'Activá las notificaciones y la ubicación para recibir alertas cuando haya un corte a menos de 5 km.', cta: 'Activar y empezar', dot: 3 }, ]; const s = slides[slide]; const Icon = s.icon; return (
{/* Icon circle */}
{/* Title */}
{s.title}
{/* Body */}
{s.body}
{/* CTA */}
{s.cta}
Saltar
); }; /* ── SCREEN 1b: Onboarding — leyenda de colores ── */ const LegendPin = ({ color, pulse = false, crowd = false }) => ( {pulse && ( <> )} {/* Pin body */} {/* ! glyph */} {crowd && ( 3 )} ); const LegendRow = ({ color, pulse, crowd, label, term, body }) => (
{label} {term}
{body}
); const OnboardingLegend = () => (
{/* Heading */}
Conocé los marcadores
Cada color en el mapa indica el estado del corte.
{/* Legend list */}
{/* CTA */}
Siguiente
Saltar
); /* ── SCREEN 2: Mapa ── */ const ScreenMap = ({ showSheet = false }) => ( {/* Top app bar */}
LuzAlerts
{/* Map area */}
{/* FABs */}
Sin luz
{/* Bottom sheet */} {showSheet && (
Hace 23 min
Av. Eusebio Ayala y Cruz del Chaco
Mburucuyá, Asunción
Estimado: 18:00 – 22:00
Ver detalles
)}
); /* ── SCREEN 3: Lista ── */ const OutageCard = ({ status, title, subtitle, time, reports, comments, noTime }) => (
{time}
{title}
{subtitle}
{!noTime && <>18:00 – 22:00}
{reports && {reports} reportes } {comments && 💬 {comments}}
); const ScreenList = () => ( }/> {/* Filter chips */}
{[ { label: 'Todos', active: true }, { label: 'Programados' }, { label: 'Activos' }, { label: 'Resueltos' }, { label: '📍 Cerca tuyo' }, ].map(c => (
{c.label}
))}
{/* Cards */}
); /* ── SCREEN 4: Detalle ── */ const InfoCard = ({ icon: Icon, iconColor, title, children }) => (
{title}
{children}
); const InfoRow = ({ label, value }) => (
{label} {value}
); const CommentCard = ({ avatar, bg, name, time, text }) => (
{avatar}
{name} {time}
{text}
); const ScreenDetail = ({ crowdsource = false }) => ( } right={} />
{/* Header */}
Av. Eusebio Ayala c/ Cruz del Chaco
Mburucuyá, Asunción, Capital
{crowdsource ? : } {crowdsource ? 'Reportado por vecinos' : 'Fuente: ANDE'}
{/* Mini map */} {/* Info cards */}
{!crowdsource && ( )}
Mburucuyá, Asunción
Mburucuyá, Madame Lynch, San Cristóbal
4 vecinos confirmaron este corte en los últimos 30 minutos.
{/* Comments */}
Comentarios (4)
{/* Input */}
Compartí lo que está pasando…
); Object.assign(window, { OnboardingSlide, OnboardingLegend, ScreenMap, ScreenList, ScreenDetail, DarkMap, MiniMap });