import React, { useState, useEffect } from 'react'; import { Shield, Users, Volume2, AlertTriangle, Briefcase, Plus, Search, Megaphone, Banknote, Siren, X, CheckCircle, Radio, Fingerprint, Activity, Gavel, FileText, QrCode, Lock, Skull } from 'lucide-react'; // --- SYSTEM NOTYFIKACJI --- const Toast = ({ message, type, onClose }) => { useEffect(() => { const timer = setTimeout(() => { onClose(); }, 3000); return () => clearTimeout(timer); }, [onClose]); const bgColor = type === 'success' ? 'bg-green-500' : type === 'error' ? 'bg-red-500' : type === 'warning' ? 'bg-yellow-500' : 'bg-blue-500'; return (
{type === 'success' && } {type === 'error' && } {type === 'warning' && } {message}
); }; export default function App() { const [activeTab, setActiveTab] = useState('kody'); const [toasts, setToasts] = useState([]); // Stan miasta const [budget, setBudget] = useState(150000); // System Kodów const [activeCode, setActiveCode] = useState('ZIELONY'); // ZIELONY, ZOLTY, CZERWONY const [presidentInDanger, setPresidentInDanger] = useState(false); // KOD CZARNY const [announcementText, setAnnouncementText] = useState(''); // Baza Obywateli const [citizens, setCitizens] = useState([ { id: '001', name: 'Jan Kowalski', role: 'Policjant', money: 2500, status: 'Czysty' }, { id: '002', name: 'Anna Nowak', role: 'Lekarz', money: 4200, status: 'Czysty' }, { id: '003', name: 'Piotr Wiśniewski', role: 'Bezrobotny', money: 150, status: 'Poszukiwany' }, ]); const addToast = (message, type = 'info') => { const id = Math.random().toString(36).substr(2, 9); setToasts((prev) => [...prev, { id, message, type }]); }; const removeToast = (id) => { setToasts((prev) => prev.filter((t) => t.id !== id)); }; // --- SYSTEM MÓWIĄCY (TEXT TO SPEECH) --- const speakAnnouncement = (text) => { if ('speechSynthesis' in window) { window.speechSynthesis.cancel(); // Przerwij poprzednie mówienie const msg = new SpeechSynthesisUtterance(text); msg.lang = 'pl-PL'; msg.rate = 0.9; // Troszkę wolniej, żeby brzmiało groźniej/wyraźniej msg.pitch = 0.8; window.speechSynthesis.speak(msg); addToast('Wysłano komunikat głosowy!', 'success'); } else { addToast('Twoja przeglądarka nie obsługuje czytania na głos.', 'error'); } }; const handleCodeChange = (code) => { setActiveCode(code); let speechText = ""; switch(code) { case 'ZIELONY': speechText = "Uwaga obywatele. Ogłaszam kod zielony. Powtarzam, kod zielony. Sytuacja jest w pełni bezpieczna. Można normalnie poruszać się po mieście i wrócić do swoich obowiązków."; break; case 'ZOLTY': speechText = "Uwaga! Ogłaszam kod żółty. Sytuacja jest niebezpieczna. Zachowajcie wzmożoną czujność, ale nie ma jeszcze potrzeby ucieczki do bunkra. Oczekujcie na dalsze polecenia służb."; break; case 'CZERWONY': speechText = "ALARM! ALARM! Ogłaszam kod czerwony! To nie jest ćwiczenie! Ekstremalne zagrożenie dla miasta! Natychmiastowa ewakuacja do bunkra! Bunkier został otwarty! Prezydent biegnie do strefy bezpiecznej!"; break; default: break; } speakAnnouncement(speechText); }; const toggleBlackCode = () => { const newState = !presidentInDanger; setPresidentInDanger(newState); if (newState) { speakAnnouncement("KOD CZARNY! KOD CZARNY! Prezydent jest w bezpośrednim niebezpieczeństwie! Wszystkie jednostki policji natychmiast do ochrony VIP-a! Użycie siły dozwolone!"); } else { speakAnnouncement("Odwołuję kod czarny. Prezydent jest bezpieczny. Służby mogą wrócić do standardowych patroli."); } }; const customAnnouncement = () => { if (announcementText.trim()) { speakAnnouncement(`Komunikat od Prezydenta: ${announcementText}`); setAnnouncementText(''); } }; // --- RENDEROWANIE INTERFEJSU --- const renderTopBar = () => (

M.I.A.S.T.O - SYSTEM PREZYDENCKI

STAN MIASTA: KOD {activeCode}

{presidentInDanger && (
KOD CZARNY - VIP W NIEBEZPIECZEŃSTWIE
)}

BUDŻET MIASTA

{budget.toLocaleString()} PLN

); const renderCodePanel = () => (

System Ostrzegania i Głośników

{/* KOD ZIELONY */} {/* KOD ZÓŁTY */} {/* KOD CZERWONY */}
{/* KOD CZARNY - DODATEK */}

MODYFIKATORY SPECJALNE

{/* Ręczne Komunikaty */}

Własny Komunikat Głosowy

setAnnouncementText(e.target.value)} placeholder="Wpisz co ma powiedzieć głośnik..." className="flex-1 bg-gray-900 border border-gray-600 rounded-lg p-3 text-white focus:outline-none focus:border-purple-500" onKeyPress={(e) => e.key === 'Enter' && customAnnouncement()} />
); const renderCitizensPanel = () => (

Rejestr eDowodów

{citizens.map(citizen => (

{citizen.name}

{citizen.role} ID: #{citizen.id}

Konto w banku

{citizen.money} PLN

{citizen.status}
))}
); return (
{renderTopBar()}
{/* Pasek boczny nawigacji */}
{/* Główna zawartość */}
{activeTab === 'kody' && renderCodePanel()} {activeTab === 'obywatele' && renderCitizensPanel()}
{/* Kontenery Toastów */} {toasts.map((toast, index) => (
removeToast(toast.id)} />
))}
); }