import React, { useState, useEffect } from 'react'; import { Home, Briefcase, User, Volume2, ZoomIn, ZoomOut, Eye, ArrowRight, ArrowLeft, Monitor, ChefHat, Scissors, Package, Palette, Folder, Wifi, CloudRain, Play, TreePine, BookOpen, Flower, Wrench, Search, Microscope, Coffee, Calculator, IdCard, Award, Frown, Meh, Smile, LayoutGrid, ShoppingCart, Circle, Star, Pen, Cookie, Power, Music, Footprints, Droplets, CheckCircle, LogOut, Shirt, Store } from 'lucide-react'; // --- KOMPONEN JAM (Diasingkan supaya tidak mengganggu aplikasi utama) --- const HeaderClock = () => { const [currentTime, setCurrentTime] = useState(''); useEffect(() => { const timer = setInterval(() => { const now = new Date(); setCurrentTime(now.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' })); }, 1000); return () => clearInterval(timer); }, []); return {currentTime || '11:11 AM'}; }; export default function App() { // State Management const [currentView, setCurrentView] = useState('home'); const [isHighContrast, setIsHighContrast] = useState(false); const [zoomLevel, setZoomLevel] = useState(0); const [malayVoice, setMalayVoice] = useState(null); const [selectedCareer, setSelectedCareer] = useState(null); // --- PROFIL MURID --- const [isProfileComplete, setIsProfileComplete] = useState(false); const [userProfile, setUserProfile] = useState({ name: '', age: '', gender: '' }); const [quizResult, setQuizResult] = useState(null); // --- KUIZ STATE --- const [quizPhase, setQuizPhase] = useState('intro'); const [quizIndex, setQuizIndex] = useState(0); const [quizAnswers, setQuizAnswers] = useState([]); // Load Voices useEffect(() => { const loadVoices = () => { const voices = window.speechSynthesis.getVoices(); const preferredVoice = voices.find(voice => voice.lang === 'ms-MY' || voice.lang === 'ms_MY') || voices.find(voice => voice.lang.includes('ms')) || voices.find(voice => voice.lang.includes('id-ID')); if (preferredVoice) setMalayVoice(preferredVoice); }; loadVoices(); if ('speechSynthesis' in window) window.speechSynthesis.onvoiceschanged = loadVoices; }, []); const speakText = (text) => { if ('speechSynthesis' in window) { window.speechSynthesis.cancel(); const cleanText = text.replace(/[*_#✨📋🏢🛠️]/g, ''); const utterance = new SpeechSynthesisUtterance(cleanText); utterance.lang = 'ms-MY'; if (malayVoice) utterance.voice = malayVoice; utterance.rate = 0.9; window.speechSynthesis.speak(utterance); } else { console.warn("Fungsi bacaan suara tidak disokong pelayar anda."); } }; const SpeakButton = ({ text, className = "" }) => ( ); const getSizes = (level) => { const map = { '-2': { base: 'text-sm', card: 'text-base', quiz: 'text-lg', main: 'text-xl' }, '-1': { base: 'text-base', card: 'text-lg', quiz: 'text-xl', main: 'text-2xl' }, '0': { base: 'text-lg', card: 'text-xl', quiz: 'text-2xl', main: 'text-3xl' }, '1': { base: 'text-xl', card: 'text-2xl', quiz: 'text-3xl', main: 'text-4xl' }, '2': { base: 'text-2xl', card: 'text-3xl', quiz: 'text-4xl', main: 'text-5xl' } }; return map[level]; }; const { base: textSize, card: cardTitleSize, quiz: quizTextSize, main: headingSize } = getSizes(zoomLevel); const retroShadow = 'shadow-[6px_6px_0px_0px_rgba(0,0,0,1)]'; const retroShadowHover = 'hover:shadow-[2px_2px_0px_0px_rgba(0,0,0,1)] hover:translate-y-[4px] hover:translate-x-[4px] transition-all cursor-pointer'; const retroBorder = 'border-4 border-black'; const navigateTo = (view) => { setCurrentView(view); setSelectedCareer(null); window.scrollTo(0, 0); }; // --- DATA KERJAYA (14 SENARAI) --- const careers = [ { id: 1, title: 'Pembantu Bakeri', icon: , desc: 'Menyediakan bahan masakan, mengadun dan membakar roti.', category: 'R (Realistik)', color: 'bg-green-300', details: { tasks: ['Menguli tepung dengan tangan.', 'Menyapu jem pada roti.', 'Menyusun roti di dalam dulang.'], env: 'Dapur yang berbau wangi.', tools: ['Ketuhar', 'Dulang', 'Sarung Tangan'] } }, { id: 2, title: 'Pembantu Landskap', icon: , desc: 'Menanam, menyiram dan menjaga tumbuh-tumbuhan taman.', category: 'R (Realistik)', color: 'bg-emerald-300', details: { tasks: ['Menyiram pokok bunga.', 'Menyapu daun kering.', 'Menanam benih baru.'], env: 'Taman dan luar rumah.', tools: ['Penyapu', 'Paip Air', 'Kereta Sorong'] } }, { id: 3, title: 'Pembantu Dobi', icon: , desc: 'Membasuh, mengering dan melipat pakaian dengan kemas.', category: 'R (Realistik)', color: 'bg-teal-300', details: { tasks: ['Memasukkan baju ke dalam mesin.', 'Melipat baju dengan lurus.', 'Menyusun baju ikut bakul.'], env: 'Kedai dobi, bau sabun.', tools: ['Mesin Basuh', 'Bakul', 'Penyangkut'] } }, { id: 4, title: 'Pembantu Mekanik', icon: , desc: 'Membantu membaiki kenderaan dan menyusun peralatan bengkel.', category: 'R (Realistik)', color: 'bg-slate-300', details: { tasks: ['Menyusun spanar di rak.', 'Mengelap cermin kereta.', 'Menyapu lantai bengkel.'], env: 'Bengkel kereta, bising sedikit.', tools: ['Spanar', 'Kain Lap', 'Troli'] } }, { id: 5, title: 'Pembantu Makmal', icon: , desc: 'Mencuci kelalang, menyusun radas dan menjaga kebersihan.', category: 'I (Investigatif)', color: 'bg-blue-400', details: { tasks: ['Membasuh tabung uji.', 'Menyusun radas sains.', 'Mengelap meja makmal.'], env: 'Makmal sains yang bersih.', tools: ['Berus Cuci', 'Kain Lap', 'Rak Tabung Uji'] } }, { id: 6, title: 'Penyemak Kualiti', icon: , desc: 'Memerhati dan memastikan barang kilang tiada kerosakan.', category: 'I (Investigatif)', color: 'bg-indigo-300', details: { tasks: ['Mengasingkan barang yang calar.', 'Menyusun barang yang elok.', 'Melihat label dengan teliti.'], env: 'Kilang atau meja kerja.', tools: ['Bakul Asing', 'Sarung Tangan', 'Kanta Pembesar'] } }, { id: 7, title: 'Pembantu Kedai Bunga', icon: , desc: 'Menyusun dan menjaga keindahan bunga segar di kedai.', category: 'A (Artistik)', color: 'bg-pink-300', details: { tasks: ['Memotong daun lebih.', 'Menyusun bunga dalam pasu.', 'Mengikat reben cantik.'], env: 'Kedai bunga, sejuk dan wangi.', tools: ['Gunting', 'Reben', 'Pasu'] } }, { id: 8, title: 'Pembuat Kraf Tangan', icon: , desc: 'Menggunting dan menghasilkan pelbagai barangan seni kraf.', category: 'A (Artistik)', color: 'bg-yellow-300', details: { tasks: ['Menggunting kertas warna.', 'Menampal gam pada kraf.', 'Mewarnakan hasil seni.'], env: 'Bilik kraf yang ceria.', tools: ['Gunting', 'Gam', 'Warna'] } }, { id: 9, title: 'Pembantu Cafe', icon: , desc: 'Menyambut tetamu, mengambil pesanan dan menghidang makanan.', category: 'S (Sosial)', color: 'bg-orange-300', details: { tasks: ['Mengelap meja makan.', 'Menghantar minuman kepada pelanggan.', 'Menyusun kerusi dengan lurus.'], env: 'Kedai makan, ramai orang.', tools: ['Kain Lap', 'Dulang', 'Buku Menu'] } }, { id: 10, title: 'Usahawan', icon: , desc: 'Membuka perniagaan sendiri dan menjual produk kepada pelanggan.', category: 'E (Enterprising)', color: 'bg-red-300', details: { tasks: ['Senyum dan sapa orang.', 'Menyusun barang niaga.', 'Berikan beg plastik kepada pembeli.'], env: 'Kedai atau pasar.', tools: ['Barang Niaga', 'Kalkulator', 'Beg Plastik'] } }, { id: 11, title: 'Jurutunai', icon: , desc: 'Mengira bil, menerima bayaran dan memastikan pelanggan gembira.', category: 'E (Enterprising)', color: 'bg-cyan-300', details: { tasks: ['Scan barang (bunyi tit!).', 'Menekan butang mesin duit.', 'Memberi resit kepada pelanggan.'], env: 'Pasar raya, kaunter bayaran.', tools: ['Mesin Tunai', 'Scanner', 'Duit Baki'] } }, { id: 12, title: 'Pembantu Stor', icon: , desc: 'Menyusun barang, mengangkat kotak dan merekod jumlah stok.', category: 'C (Konvensional)', color: 'bg-amber-300', details: { tasks: ['Mengangkat kotak kecil.', 'Menyusun kotak di rak lurus.', 'Mengira jumlah kotak.'], env: 'Gudang atau stor besar.', tools: ['Troli Barang', 'Kotak', 'Papan Klip'] } }, { id: 13, title: 'Pembantu Perpustakaan', icon: , desc: 'Menyusun buku di rak dan merekod pinjaman bahan bacaan.', category: 'C (Konvensional)', color: 'bg-blue-300', details: { tasks: ['Menyusun buku mengikut warna/nombor.', 'Menolak troli buku.', 'Memastikan meja sentiasa kemas.'], env: 'Perpustakaan, senyap dan tenang.', tools: ['Troli Buku', 'Rak Buku', 'Cap Tarikh'] } }, { id: 14, title: 'Kerani Data', icon: , desc: 'Menaip dan memasukkan maklumat ke dalam komputer dengan teliti.', category: 'C (Konvensional)', color: 'bg-purple-300', details: { tasks: ['Menaip huruf di komputer.', 'Menekan tetikus (mouse).', 'Menyalin maklumat dari kertas.'], env: 'Pejabat, meja komputer.', tools: ['Papan Kekunci', 'Komputer', 'Fail Kertas'] } }, ]; const quizQuestions = [ { id: 1, code: 'R1', text: "Adakah kamu suka menyusun blok jadi tinggi?", icon: , color: "bg-emerald-300", category: "R (Realistik)" }, { id: 2, code: 'R2', text: "Adakah kamu suka menolak kereta mainan / troli?", icon: , color: "bg-green-300", category: "R (Realistik)" }, { id: 3, code: 'I1', text: "Adakah kamu suka asingkan butang ikut warna?", icon: , color: "bg-indigo-300", category: "I (Investigatif)" }, { id: 4, code: 'I2', text: "Adakah kamu suka cari benda tersembunyi dalam pasir?", icon: , color: "bg-blue-400", category: "I (Investigatif)" }, { id: 5, code: 'A1', text: "Adakah kamu suka mewarna gambar?", icon: , color: "bg-pink-300", category: "A (Artistik)" }, { id: 6, code: 'A2', text: "Adakah kamu suka lekatkan pelekat (sticker)?", icon: , color: "bg-yellow-300", category: "A (Artistik)" }, { id: 7, code: 'S1', text: "Adakah kamu suka hulur pensel kepada kawan?", icon: , color: "bg-red-300", category: "S (Sosial)" }, { id: 8, code: 'S2', text: "Adakah kamu suka bagi makanan ringan kat kawan?", icon: , color: "bg-orange-300", category: "S (Sosial)" }, { id: 9, code: 'E1', text: "Adakah kamu suka tekan suis lampu untuk cikgu?", icon: , color: "bg-teal-300", category: "E (Enterprising)" }, { id: 10, code: 'E2', text: "Adakah kamu suka pilih lagu untuk kelas dengar?", icon: , color: "bg-cyan-300", category: "E (Enterprising)" }, { id: 11, code: 'C1', text: "Adakah kamu suka susun kasut di rak lurus-lurus?", icon: , color: "bg-purple-300", category: "C (Konvensional)" }, { id: 12, code: 'C2', text: "Adakah kamu suka lap meja lepas makan?", icon: , color: "bg-blue-300", category: "C (Konvensional)" }, ]; // --- GOOGLE SHEETS SKELETON --- const SCRIPT_URL = "URL_ANDA_DI_SINI"; const saveToGoogleSheets = async (profile, resultData) => { if (SCRIPT_URL === "URL_ANDA_DI_SINI") return; try { const payload = { timestamp: new Date().toLocaleString('ms-MY'), name: profile.name, age: profile.age, gender: profile.gender, dominant1: resultData.riasec[0] || '-', dominant2: resultData.riasec[1] || '-', scoreR: resultData.scores['R (Realistik)'], scoreI: resultData.scores['I (Investigatif)'], scoreA: resultData.scores['A (Artistik)'], scoreS: resultData.scores['S (Sosial)'], scoreE: resultData.scores['E (Enterprising)'], scoreC: resultData.scores['C (Konvensional)'] }; await fetch(SCRIPT_URL, { method: 'POST', mode: 'no-cors', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); } catch (error) { console.error(error); } }; // --- QUIZ LOGIC --- const handleQuizAnswer = (score) => { const newAnswers = [...quizAnswers, { questionId: quizQuestions[quizIndex].id, score }]; setQuizAnswers(newAnswers); if (quizIndex < quizQuestions.length - 1) { setQuizIndex(quizIndex + 1); } else { const scores = { 'R (Realistik)': 0, 'I (Investigatif)': 0, 'A (Artistik)': 0, 'S (Sosial)': 0, 'E (Enterprising)': 0, 'C (Konvensional)': 0 }; newAnswers.forEach(ans => { const cat = quizQuestions.find(q => q.id === ans.questionId).category; scores[cat] += ans.score; }); const sortedCats = Object.entries(scores).sort((a, b) => b[1] - a[1]); const dominantCats = [sortedCats[0][0], sortedCats[1][0]]; const recommended = careers.filter(c => dominantCats.includes(c.category)); const finalResultData = { riasec: dominantCats, scores: scores, careers: recommended }; setQuizResult(finalResultData); setQuizPhase('result'); saveToGoogleSheets(userProfile, finalResultData); } }; const startQuiz = () => { setQuizPhase('questions'); }; const resetQuiz = () => { setQuizIndex(0); setQuizAnswers([]); setQuizPhase('intro'); }; const handleNewStudent = () => { setIsProfileComplete(false); setUserProfile({ name: '', age: '', gender: '' }); setQuizResult(null); resetQuiz(); setCurrentView('home'); setSelectedCareer(null); window.scrollTo(0, 0); }; // --- VIEWS --- const OnboardingView = () => { const [tempName, setTempName] = useState(userProfile.name); const [tempAge, setTempAge] = useState(userProfile.age); const [tempGender, setTempGender] = useState(userProfile.gender); const handleSaveProfile = () => { setUserProfile({ name: tempName.trim() || 'Kawan', age: tempAge || '-', gender: tempGender || '-' }); setIsProfileComplete(true); navigateTo('home'); }; return (

Isi Biodata Diri

Maklumat ini akan disimpan dalam Profil Saya.

setTempName(e.target.value)} className={`w-full p-4 rounded-xl border-4 border-black font-bold outline-none focus:bg-pink-50 ${retroShadowHover} ${textSize}`} />
setTempAge(e.target.value)} className={`w-full p-4 rounded-xl border-4 border-black font-bold outline-none focus:bg-pink-50 ${retroShadowHover} ${textSize}`} />
setTempGender('Lelaki')} className={`flex-1 p-4 rounded-xl border-4 border-black font-black uppercase text-center transition-all ${tempGender === 'Lelaki' ? 'bg-blue-400 text-white shadow-[inset_4px_4px_0px_0px_rgba(0,0,0,0.3)]' : 'bg-slate-100 hover:bg-slate-200'} ${textSize}`}>Lelaki
setTempGender('Perempuan')} className={`flex-1 p-4 rounded-xl border-4 border-black font-black uppercase text-center transition-all ${tempGender === 'Perempuan' ? 'bg-pink-400 text-white shadow-[inset_4px_4px_0px_0px_rgba(0,0,0,0.3)]' : 'bg-slate-100 hover:bg-slate-200'} ${textSize}`}>Perempuan
Simpan & Masuk
); }; const HomeView = () => (

Selamat Datang, {userProfile.name}!

Pilih folder untuk bermula

{ setQuizPhase('intro'); navigateTo('quiz'); }} className="flex flex-col items-center group cursor-pointer">
Kuiz Kerjaya
navigateTo('gallery')} className="flex flex-col items-center group cursor-pointer">
Senarai Kerja
navigateTo('profile')} className="flex flex-col items-center group cursor-pointer">
Profil Saya
); const QuizView = () => { return (
{quizPhase === 'intro' && (

Sedia Untuk Mula?

Terdapat 12 soalan. Pilih Skor 1, 2, atau 3 untuk setiap soalan.

Mula Kuiz
)} {quizPhase === 'questions' && ( <>
Soalan {quizIndex + 1} / {quizQuestions.length}
{quizQuestions[quizIndex].icon}

{quizQuestions[quizIndex].text}

handleQuizAnswer(1)} className={`flex-1 flex flex-col items-center gap-3 p-5 rounded-xl border-4 border-black bg-red-400 text-white relative ${retroShadowHover}`}>
TIDAK SUKA (1)
handleQuizAnswer(2)} className={`flex-1 flex flex-col items-center gap-3 p-5 rounded-xl border-4 border-black bg-yellow-400 text-black relative ${retroShadowHover}`}>
BIASA SAHAJA (2)
handleQuizAnswer(3)} className={`flex-1 flex flex-col items-center gap-3 p-5 rounded-xl border-4 border-black bg-green-400 text-white relative ${retroShadowHover}`}>
SANGAT SUKA (3)
)} {quizPhase === 'result' && (

Tahniah, {userProfile.name}!

Dua Profil Paling Dominan Anda:

{quizResult.riasec.map(cat => (
{cat.split(' ')[0]} {cat.substring(4)}
Skor: {quizResult.scores[cat]} / 6
))}
)}
); }; const CareerDetailView = ({ career }) => (
{React.cloneElement(career.icon, { size: 64 })}

{career.title}

Kategori: {career.category}

{career.desc}

📋 Tugas Harian:

    {career.details.tasks.map(task => (
  • {task}
  • ))}

🏢 Persekitaran

{career.details.env}

🛠️ Peralatan Utama

{career.details.tools.join(', ')}

Info Pekerjaan

info pekerjaan by MAISARA QISTINA BINTI AZROL NIZAM IPG-Pelajar

); const GalleryView = () => { if (selectedCareer) return ; return (

Senarai Kerjaya

{careers.map((career) => (
{career.icon}

{career.title}

{career.category}

{career.desc}

setSelectedCareer(career)} className={`flex-grow py-3 rounded-xl font-black uppercase bg-pink-300 border-4 border-black flex items-center justify-center gap-2 ${retroShadowHover} cursor-pointer text-sm md:text-base`} > Butiran Penuh
))}
); }; const ProfileView = () => (

Profil Saya

{userProfile.name}

Umur: {userProfile.age} Tahun
Jantina: {userProfile.gender}

Rekod Kerjaya

{!quizResult ? (

Anda belum mengambil Kuiz Kerjaya.

) : (

Dua Profil Paling Dominan:

{quizResult.riasec.map(cat => (
{cat.split(' ')[0]} {cat.substring(4)}
Skor: {quizResult.scores[cat]}
))}

Kerjaya Pilihan Anda:

{quizResult.careers.map(career => (
{career.icon}

{career.title}

{career.category}
))}
)}
); return (
CareerVerse
{!isProfileComplete ? ( ) : ( <> {currentView === 'home' && } {currentView === 'quiz' && } {currentView === 'gallery' && } {currentView === 'profile' && } )}
{zoomLevel > 0 ? `+${zoomLevel}` : zoomLevel}
); }