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 */}
);
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)} />
))}
);
}