// 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 }) => (
);
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 */}
{/* Map area */}
{/* FABs */}
{/* 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 }) => (
);
const InfoRow = ({ label, value }) => (
{label}
{value}
);
const CommentCard = ({ avatar, bg, 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 });