// ===== SCREENS: Buddy, Checklist, Logger, PoliceTips =====
// ---------- SOS Buddy ----------
function BuddyScreen({ t, go }) {
const [selected, setSelected] = useState(buddy_contacts[0].id);
const [active, setActive] = useState(false);
const [secs, setSecs] = useState(0);
useEffect(() => {
if (!active) return;
const id = setInterval(() => setSecs(s => s + 1), 1000);
return () => clearInterval(id);
}, [active]);
const fmt = (s) => `${String(Math.floor(s / 60)).padStart(2, '0')}:${String(s % 60).padStart(2, '0')}`;
const buddy = buddy_contacts.find(b => b.id === selected);
return (
{active ? '● Live Trip Sharing' : 'Trip Inactive'}
{fmt(secs)}
{active ? `${buddy.name} can see your live location` : 'Start a trip to share your location with a buddy'}
{ if (active) { setActive(false); setSecs(0); } else setActive(true); }}>
{active ? 'End Trip' : 'Start Live Trip'}
Choose Your SOS Buddy
{buddy_contacts.map(b => {
const sel = selected === b.id;
return (
setSelected(b.id)} style={{ border: `1.5px solid ${sel ? t.mid : t.border}`, cursor: 'pointer' }}>
{b.avatar}
{b.name}
{b.phone} · {b.relation}
{sel && }
);
})}
);
}
// ---------- Pre-Trip Checklist ----------
function ChecklistScreen({ t, go }) {
const allKeys = checklist_items.flatMap(c => c.items.map((_, i) => `${c.id}-${i}`));
const [checked, setChecked] = useState({});
const [open, setOpen] = useState(checklist_items[0].id);
const doneCount = Object.values(checked).filter(Boolean).length;
const pct = Math.round((doneCount / allKeys.length) * 100);
const toggle = (k) => setChecked(c => ({ ...c, [k]: !c[k] }));
return (
{pct}%
{pct === 100 ? 'Ready to roll! 🚗' : 'Pre-Trip Inspection'}
{doneCount} of {allKeys.length} checks complete across {checklist_items.length} categories.
{checklist_items.map(cat => {
const isOpen = open === cat.id;
const catKeys = cat.items.map((_, i) => `${cat.id}-${i}`);
const catDone = catKeys.filter(k => checked[k]).length;
return (
{cat.items.map((it, i) => {
const k = `${cat.id}-${i}`;
const on = !!checked[k];
return (
);
})}
);
})}
);
}
// ---------- Evidence Logger ----------
function LoggerScreen({ t, go }) {
const [type, setType] = useState('Collision');
const [note, setNote] = useState('');
const [log, setLog] = useState([
{ id: 1, type: 'Near-miss', note: 'Motorcycle swerved without signal', loc: '14.5995° N, 120.9842° E', time: 'Today 08:42' },
{ id: 2, type: 'Pothole', note: 'Deep pothole damaged front tire', loc: '14.6760° N, 121.0437° E', time: 'Yesterday 17:20' },
]);
const types = ['Collision', 'Near-miss', 'Pothole', 'Hazard', 'Violation'];
const submit = () => {
if (!note.trim()) return;
const now = new Date();
setLog(l => [{ id: Date.now(), type, note: note.trim(), loc: `${(14.55 + Math.random() * 0.2).toFixed(4)}° N, ${(120.98 + Math.random() * 0.1).toFixed(4)}° E`, time: `Now ${String(now.getHours()).padStart(2,'0')}:${String(now.getMinutes()).padStart(2,'0')}` }, ...l]);
setNote('');
};
return (
GPS locked · 14.5995° N, 120.9842° E
INCIDENT TYPE
{types.map(ty =>
setType(ty)} color={t.accent}>{ty})}
Log History
{log.map(e => (
{e.type}
{e.time}
{e.note}
{e.loc}
))}
);
}
// ---------- Know Your Rights ----------
function PoliceTipsScreen({ t, go }) {
const [tab, setTab] = useState(0);
return (
{['Dealing with Enforcers', 'How to Contest'].map((label, i) => (
))}
{tab === 0 ? (
{police_tips.map(p => (
))}
) : (
{contest_steps.map((s, i) => (
))}
)}
🚫 Report a Corrupt Enforcer
Bribery is punishable under RA 3019. Report misconduct to:
{corrupt_contacts.map(c => (
))}
);
}
Object.assign(window, { BuddyScreen, ChecklistScreen, LoggerScreen, PoliceTipsScreen });