);
};
// ============================================
// STRIPE CHECKOUT UTILS
// ============================================
const StripeCheckout = ({ clientSecret }) => {
const stripe = useStripe();
const elements = useElements();
const { upgradeToPro } = useUser();
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');
const handleSubmit = async (event) => {
event.preventDefault();
if (!stripe || !elements) return;
setLoading(true);
const { error: submitError } = await elements.submit();
if (submitError) {
setError(submitError.message);
setLoading(false);
return;
}
// Confirm the payment
const { error } = await stripe.confirmPayment({
elements,
clientSecret,
confirmParams: {
return_url: 'http://localhost:5173', // Redirects here after payment
},
redirect: 'if_required'
});
if (error) {
setError(error.message);
setLoading(false);
} else {
// Payment succeeded
upgradeToPro();
}
};
return (
);
};
// ============================================
// PAYMENT MODAL (Stripe Aware)
// ============================================
const PaymentModal = () => {
const { showPayment, setShowPayment, upgradeToPro } = useUser();
const [clientSecret, setClientSecret] = useState(null);
useEffect(() => {
if (showPayment && SYSTEM_CONFIG.STRIPE_KEY) {
// Fetch fetch client secret from our local node server
console.log("Fetching Payment Intent...");
fetch('http://localhost:4242/create-payment-intent', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
})
.then(res => {
if (!res.ok) throw new Error("Server Error");
return res.json();
})
.then(data => {
console.log("Secret received");
setClientSecret(data.clientSecret);
})
.catch(err => {
console.error("Payment Fetch Error", err);
// Fallback for demo if server is dead
// alert("Server Pagamenti Offline. Controlla che 'node server.js' sia attivo.");
});
}
}, [showPayment]);
if (!showPayment) return null;
return (
setShowPayment(false)} />
UPGRADE SCHOLAR PRO
{stripePromise && clientSecret ? (
) : (
Inizializzazione Stripe Sicuro...
)}
);
};
// ============================================
// TYPEWRITER HOOK
// ============================================
const useTypewriter = (lines, speed = 40, pauseBetween = 500) => {
const [currentLine, setCurrentLine] = useState(0);
const [currentChar, setCurrentChar] = useState(0);
const [displayLines, setDisplayLines] = useState([]);
const [isComplete, setIsComplete] = useState(false);
useEffect(() => {
if (currentLine >= lines.length) { setIsComplete(true); return; }
const line = lines[currentLine];
if (currentChar < line.length) {
const timeout = setTimeout(() => { setDisplayLines((prev) => { const newLines = [...prev]; newLines[currentLine] = line.slice(0, currentChar + 1); return newLines; }); setCurrentChar(currentChar + 1); }, speed);
return () => clearTimeout(timeout);
} else {
const timeout = setTimeout(() => { setCurrentLine(currentLine + 1); setCurrentChar(0); }, pauseBetween);
return () => clearTimeout(timeout);
}
}, [currentLine, currentChar, lines, speed, pauseBetween]);
return { displayLines, isComplete };
};
// ============================================
// HERO UNIT
// ============================================
const HeroUnit = () => {
const { displayLines, isComplete } = useTypewriter([
'> Inizializzazione Neural Uplink...',
'> Ottimizzazione Protocolli di Memoria...',
'> Sistema Pronto.',
], 30, 400);
return (
POTENZIA LA TUA MENTE.
{displayLines.map((line, i) => (
{line}{i === displayLines.length - 1 && !isComplete && █}
))}
{displayLines.length === 0 &&
█}
document.getElementById('simulator')?.scrollIntoView({ behavior: 'smooth' })}
className="group px-10 py-5 bg-gradient-to-r from-[#8b5cf6] to-[#7c3aed] text-white font-bold text-lg rounded-xl hover:scale-105 shadow-[0_0_40px_rgba(139,92,246,0.5)] relative overflow-hidden">
AVVIA
);
};
// ============================================
// VIDEO DATABASE & SIMULATION LOGIC
// ============================================
// ID Verificati & Quiz & Riassunti (Curati da Gemini 2 Flash)
const VIDEO_DATABASE = {
'fisica': {
id: 'Y9EjnBmO2Jw',
title: 'I Principi della Dinamica (Hub Scuola)',
summary: "STUDIO: La dinamica è la parte della fisica che studia come si muovono i corpi per effetto delle forze. \n1. Principio d'Inerzia: Se nessuna forza agisce su un corpo, esso mantiene il suo stato (quiete o moto rettilineo uniforme). \n2. Legge Fondamentale (F=ma): La forza è il prodotto tra massa e accelerazione. \n3. Azione e Reazione: A ogni forza corrisponde una forza uguale e contraria.",
quiz: {
question: "Quale principio afferma che F = m * a?",
options: [{ text: "Primo Principio", correct: false }, { text: "Secondo Principio", correct: true }, { text: "Terzo Principio", correct: false }],
hint: "È la legge fondamentale della dinamica che collega causa ed effetto."
}
},
'napoleone': {
id: '2U_YdZD5kkM',
title: 'Napoleone Bonaparte - Sintesi Completa',
summary: "BIOGRAFIA: Generale e Imperatore francese (1769-1821). \nASCESA: Sfruttò il caos post-rivoluzione. Famoso per le campagne d'Italia e d'Egitto. Autoproclamato Imperatore nel 1804. \nRIFORME: Introdusse il Codice Civile (basi diritto moderno). \nCADUTA: Disastrosa campagna di Russia (1812), sconfitto a Lipsia e Waterloo (1815). Esiliato a Sant'Elena.",
quiz: {
question: "In quale isola morì Napoleone in esilio?",
options: [{ text: "Isola d'Elba", correct: false }, { text: "Sant'Elena", correct: true }, { text: "Corsica", correct: false }],
hint: "Un'isola remota nell'Oceano Atlantico meridionale."
}
},
'storia': {
id: 'd_kS3x0lJ4k',
title: 'La Prima Guerra Mondiale (In 5 minuti)',
summary: "GRANDE GUERRA (1914-1918): Scatenata dall'attentato di Sarajevo. \nSCHIERAMENTI: Triplice Intesa (Francia, UK, Russia, poi Italia/USA) vs Imperi Centrali (Austria, Germania). \nCARATTERISTICHE: Guerra di trincea, logoramento, nuove armi (gas, aerei, carri). \nESITO: Crollo di 4 imperi, nascita di nuovi stati, riassetto dell'Europa con Versailles.",
quiz: {
question: "Quale evento fece scoppiare la guerra?",
options: [{ text: "Invasione della Polonia", correct: false }, { text: "Attentato di Sarajevo", correct: true }, { text: "Presa della Bastiglia", correct: false }],
hint: "L'assassinio dell'Arciduca Francesco Ferdinando."
}
},
'chimica': {
id: '?listType=search&list=Tavola+Periodica+Spiegazione+Semplice',
title: 'La Tavola Periodica degli Elementi',
summary: "STRUTTURA: Organizza gli elementi chimici ordinati per numero atomico (Z). \nGRUPPI E PERIODI: Le colonne (gruppi) hanno proprietà simili; le righe (periodi) indicano il livello energetico. \nCLASSIFICAZIONE: Metalli (sinistra), Non metalli (destra), Gas Nobili (ultima colonna, stabili). Fondamentale per prevedere le reazioni chimiche.",
quiz: {
question: "Come sono ordinati gli elementi nella tavola?",
options: [{ text: "Per data di scoperta", correct: false }, { text: "Per numero atomico crescente", correct: true }, { text: "Alfabeticamente", correct: false }],
hint: "Il numero di protoni nel nucleo decide la posizione."
}
},
'matematica': {
id: '?listType=search&list=Equazioni+Primo+Grado+Spiegazione',
title: 'Equazioni Lineari (Algebra)',
summary: "CONCETTO: Uguaglianza tra due espressioni verificata solo per certi valori (soluzioni). \nRISOLUZIONE: L'obiettivo è isolare la 'x'. \nPRINCIPI: \n1. Sommando/sottraendo la stessa quantità a entrambi i membri, il risultato non cambia. \n2. Moltiplicando/dividendo entrambi i membri per uno stesso numero (diverso da 0), l'equazione resta equivalente.",
quiz: {
question: "Qual è il primo passaggio per risolvere 2x + 5 = 15?",
options: [{ text: "Dividere tutto per 2", correct: false }, { text: "Sottrarre 5 da entrambi i lati", correct: true }, { text: "Moltiplicare per x", correct: false }],
hint: "Devi isolare il termine con la x spostando i numeri."
}
},
'italiano': {
id: 'fESdidM5j7s',
title: 'La Divina Commedia in 10 minuti',
summary: "OPERA: Poema allegorico in terzine incatenate. \nVIAGGIO: Dante attraversa i tre regni ultraterreni. \nINFERNO: Voragine a imbuto, pena del contrappasso. \nPURGATORIO: Montagna dove le anime espiano i peccati. \nPARADISO: Cieli concentrici di pura luce e beatitudine. \nGUIDE: Virgilio (Ragione), Beatrice (Teologia/Grazia).",
quiz: {
question: "Chi guida Dante attraverso l'Inferno?",
options: [{ text: "Beatrice", correct: false }, { text: "Virgilio", correct: true }, { text: "San Pietro", correct: false }],
hint: "Il sommo poeta latino autore dell'Eneide."
}
},
'inglese': {
id: 'M2K-kM2i_tQ',
title: 'Inglese: Basi Fondamentali',
summary: "GRAMMATICA BASE: \n1. Verbo To Be (Essere): I am, You are, He is. \n2. Ordine parole: Subject + Verb + Object (SVO). \n3. Present Simple: Per abitudini e verità generali (Add 's' for he/she/it). \nCONSIGLIO: La pratica dell'ascolto (listening) è cruciale quanto la grammatica.",
quiz: {
question: "Qual è la forma corretta?",
options: [{ text: "He go to school", correct: false }, { text: "He goes to school", correct: true }, { text: "He going to school", correct: false }],
hint: "Terza persona singolare richiede la 's' o 'es'."
}
},
};
const getTopicVideo = (topic) => {
const query = topic.toLowerCase().trim();
const searchKey = Object.keys(VIDEO_DATABASE).find(key => query.includes(key));
if (searchKey) return VIDEO_DATABASE[searchKey];
// FALLBACK INTELLIGENTE: YouTube Search Embed
// Genera una ricerca dinamica se non abbiamo un ID specifico
return {
id: `?listType=search&list=${encodeURIComponent(topic + ' spiegazione scuola')}`,
title: `Ricerca approfondita: ${topic}`,
summary: `Generazione sintesi automatica per: ${topic}. L'argomento richiede un'analisi approfondita delle fonti video correlate. Consulta il video per i dettagli specifici e prendi appunti sui concetti chiave.`,
quiz: {
question: `Qual è il concetto principale riguardo "${topic}"?`,
options: [
{ text: "Concetto A (Vedi Video)", correct: true },
{ text: "Concetto B", correct: false },
{ text: "Concetto C", correct: false }
],
hint: "Guarda i primi 2 minuti del video per la risposta."
}
};
};
const getSimulatedResult = (topic) => {
try {
const video = getTopicVideo(topic);
return {
videoId: video.id,
summary: video.summary || `Riassunto generato per ${topic}.`,
notes: [
`Concetti chiave su: ${topic || 'Argomento'}`,
`Analisi approfondita di: ${video.title}`,
'Sintesi dei punti fondamentali',
'Collegamenti interdisciplinari rilevati'
],
planner: [
{ time: '15:00', task: `Studio Intensivo: ${topic || 'Concetti Base'}`, details: 'Lettura e sottolineatura testo', duration: '45m' },
{ time: '15:45', task: 'Active Recall & Quiz', details: 'Test di autovalutazione', duration: '15m' },
{ time: '16:00', task: 'Analisi Video & Sintesi', details: 'Visione materiale multimediale', duration: '30m' },
],
quiz: Array.isArray(video.quiz) ? video.quiz : [video.quiz] // Normalize to array
};
} catch (e) {
console.error("Error generating simulated result:", e);
return {
videoId: 'Y9EjnBmO2Jw', // Fallback sicuro (Fisica)
summary: "Errore durante il recupero dei dati. Riprova.",
notes: ['Errore generazione note', 'Riprova più tardi'],
planner: [],
quiz: [{ question: 'Errore di sistema', options: [], hint: 'Riprova' }]
};
}
};
// ============================================
// CORE SIMULATOR (CUORE DEL SITO)
// ============================================
const CoreSimulator = () => {
const { protocol, credits, setCredits, setShowPayment, addXP } = useUser();
const [state, setState] = useState('INPUT');
const [query, setQuery] = useState('');
const [progress, setProgress] = useState(0);
const [logs, setLogs] = useState([]);
const [resultData, setResultData] = useState(getSimulatedResult('Introduzione'));
const [isListening, setIsListening] = useState(false);
const [quizAnswer, setQuizAnswer] = useState(null);
const [showXP, setShowXP] = useState(false);
const [apiError, setApiError] = useState(false);
const startListening = () => {
if ('webkitSpeechRecognition' in window || 'SpeechRecognition' in window) {
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
const recognition = new SpeechRecognition();
recognition.lang = 'it-IT';
recognition.onstart = () => setIsListening(true);
recognition.onend = () => setIsListening(false);
recognition.onresult = (event) => { const transcript = event.results[0][0].transcript; setQuery(transcript); setTimeout(() => handleSubmit(null, transcript), 500); };
recognition.start();
} else { alert("Riconoscimento vocale non supportato in questo browser."); }
};
const handleSubmit = async (e, voiceQuery = null) => {
e?.preventDefault();
if (protocol === 'GUEST') { document.getElementById('pricing')?.scrollIntoView({ behavior: 'smooth' }); return; }
if (protocol === 'CORE' && credits <= 0) { setShowPayment(true); return; }
if (protocol === 'CORE') setCredits(p => p - 1);
const effectiveQuery = voiceQuery || query;
if (voiceQuery) setQuery(voiceQuery); // Ensure state is synced
setState('PROCESSING');
setProgress(0);
setLogs([]);
setApiError(false);
};
// AI SIMULATION EFFECT
useEffect(() => {
if (state !== 'PROCESSING') return;
const searchQuery = query;
let isMounted = true;
// Fake Progress Logs
const logMessages = ['[INFO] Scansione 40.000 Fonti Accademiche...', '[INFO] Filtraggio Contenuti a Bassa Densità...', '[INFO] Generazione Mappe Neurali...'];
let logIndex = 0;
const logInt = setInterval(() => {
if (logIndex < logMessages.length) {
setLogs(p => [...p, logMessages[logIndex]]);
logIndex++;
}
// Random system logs
if (Math.random() > 0.7) {
setLogs(prev => [...prev.slice(-4), ` [SYSTEM] ${['Analyzing patterns...', 'Decoding vector space...', 'Retrieving archives...', 'Synthesizing layout...'][Math.floor(Math.random() * 4)]}`]);
}
}, 600);
const progInt = setInterval(() => {
setProgress(p => {
if (p >= 90) return p;
return p + Math.floor(Math.random() * 5);
});
}, 200);
const runSimulation = async () => {
// 1. Check Static Database First (Fast Cache) but allow AI override if key is present
// Actually, we want AI to take over unless it fails.
// But for specific static IDs (Fisica/Dante), users might prefer the "Perfect" curated content?
// Let's Check: User said "Use Gemini for EVERY search". So we prefer AI.
// But we can fallback to static if AI fails or for speed?
// Let's try AI first.
try {
if (!SYSTEM_CONFIG.OPENROUTER_KEY) throw new Error("No API Key");
const response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
method: "POST",
headers: {
"Authorization": `Bearer ${SYSTEM_CONFIG.OPENROUTER_KEY}`,
"Content-Type": "application/json",
"HTTP-Referer": "http://localhost:5176",
"X-Title": "Synapse OS"
},
body: JSON.stringify({
"model": "google/gemini-2.0-flash-001",
"messages": [
{
"role": "system",
"content": "You are Synapse OS, an advanced education interface. Analyze the user topic and return a STRICT JSON object (no markdown). Structure: { \"summary\": \"Comprehensive summary (8-10 sentences).\", \"notes\": [\"Point 1\", \"Point 2\", \"Point 3\"], \"videoSearchQuery\": \"${topic} documentario scuola\", \"quiz\": [ { \"question\": \"Q1?\", \"options\": [{\"text\":\"A\",\"correct\":false}, {\"text\":\"B\",\"correct\":true}, {\"text\":\"C\",\"correct\":false}], \"hint\": \"H1\" }, { \"question\": \"Q2?\", \"options\": [...], \"hint\": \"...\" }, { \"question\": \"Q3?\", \"options\": [...], \"hint\": \"...\" }, { \"question\": \"Q4?\", \"options\": [...], \"hint\": \"...\" }, { \"question\": \"Q5?\", \"options\": [...], \"hint\": \"...\" } ], \"planner\": [{\"time\":\"15:00\",\"task\":\"Deep Work\",\"details\":\"Study concept X and Y\",\"duration\":\"45m\"},{\"time\":\"16:00\",\"task\":\"Review\",\"details\":\"Test knowledge\",\"duration\":\"30m\"}] }. Notes: Quiz MUST have exactly 5 questions. Each question MUST have 3 options. Language: ITALIAN."
},
{
"role": "user",
"content": `Topic: ${searchQuery}`
}
]
})
});
const data = await response.json();
if (!data.choices) throw new Error("Invalid API Response");
// Clean potential markdown code blocks ```json ... ```
let cleanContent = data.choices[0].message.content;
if (cleanContent.startsWith('```')) {
cleanContent = cleanContent.replace(/^```json\s*/, '').replace(/^```\s*/, '').replace(/\s*```$/, '');
}
const aiContent = JSON.parse(cleanContent);
let finalVideoId = `?listType=search&list=${encodeURIComponent(aiContent.videoSearchQuery || searchQuery)}`;
// Try YouTube API if Key is present
if (SYSTEM_CONFIG.YOUTUBE_KEY) {
try {
const ytRes = await fetch(`https://www.googleapis.com/youtube/v3/search?part=snippet&maxResults=1&q=${encodeURIComponent(aiContent.videoSearchQuery || searchQuery)}&type=video&key=${SYSTEM_CONFIG.YOUTUBE_KEY}`);
const ytData = await ytRes.json();
if (ytData.items && ytData.items.length > 0) {
finalVideoId = ytData.items[0].id.videoId;
}
} catch (ytErr) {
console.error("YouTube API Failed:", ytErr);
}
}
if (isMounted) {
setResultData({
videoId: finalVideoId,
summary: aiContent.summary,
notes: aiContent.notes,
planner: aiContent.planner,
quiz: Array.isArray(aiContent.quiz) ? aiContent.quiz : [aiContent.quiz]
});
}
} catch (e) {
console.error("AI GENERATION FAILED:", e);
if (isMounted) {
setLogs(prev => [...prev, " [ERROR] NEURAL LINK SEVERED", " [WARN] SWITCHING TO LOCAL CACHE..."]);
// Fallback to static
setResultData(getSimulatedResult(searchQuery));
}
} finally {
if (isMounted) {
setProgress(100);
setTimeout(() => {
setLogs(prev => [...prev, " [SUCCESS] DATA STREAM ESTABLISHED"]);
setTimeout(() => setState('DASHBOARD'), 500);
}, 500);
}
}
};
runSimulation();
return () => {
isMounted = false;
clearInterval(logInt);
clearInterval(progInt);
};
}, [state, query]);
const [quizIndex, setQuizIndex] = useState(0);
const handleQuizAnswer = (isCorrect) => {
setQuizAnswer(isCorrect ? 'correct' : 'wrong');
if (isCorrect) {
setShowXP(true);
addXP(200); // Add real XP
setTimeout(() => setShowXP(false), 2000);
// Next question delay
setTimeout(() => {
if (resultData?.quiz && quizIndex < resultData.quiz.length - 1) {
setQuizIndex(p => p + 1);
setQuizAnswer(null);
}
}, 1500);
}
};
return (
CORE SIMULATOR
INTERFACCIA ELABORAZIONE NEURALE v2.0
{protocol === 'CORE' &&
CREDITI GIORNALIERI: {credits}
}
{state === 'INPUT' && (
)}
{state === 'PROCESSING' && (
ELABORAZIONE NEURALE...{progress}%
{logs.map((l, i) =>
{l}
)}
)}
{state === 'DASHBOARD' && resultData && (
{/* Planner */}
PLANNER
{resultData.planner?.map((x, i) => (
{x.time}
{x.task}
{x.details &&
"{x.details}"
}
{x.duration}
))}
{/* Summary Card (NEW) */}
RIASSUNTO
{resultData.summary}
INTEL. ARTIFICIALE: 98% PRECISIONE
{/* Video Stream */}
VIDEO STREAM
BIGNAMI NOTES:
{resultData.notes?.map((n, i) => - •{n}
)}
{/* Active Recall (Multi-Step) */}
ACTIVE RECALL ({quizIndex + 1}/{resultData.quiz?.length || 1})
{showXP && +200 XP
}
{resultData.quiz && resultData.quiz[quizIndex] ? (
<>
{resultData.quiz[quizIndex]?.question || "Caricamento..."}
{resultData.quiz[quizIndex]?.options?.map((opt, i) => (
))}
{quizAnswer === 'wrong' && Riprova, concentrati sul video...
}
HINT: {resultData.quiz[quizIndex].hint}
>
) : (
Nessun quiz disponibile.
)}
)
}
);
};
// ============================================
// FEATURE MODULES (Holographic Cards)
// ============================================
const FeatureModules = () => {
const [tilt, setTilt] = useState({ x: 0, y: 0, id: null });
const handleMouseMove = (e, id) => { const rect = e.currentTarget.getBoundingClientRect(); setTilt({ x: (e.clientX - rect.left - rect.width / 2) / 10, y: -(e.clientY - rect.top - rect.height / 2) / 10, id }); };
const features = [
{ id: 1, icon: Clock, title: 'TIME DILATION', subtitle: 'Planner', description: 'Algoritmo che adatta lo studio al tuo ritmo circadiano.', color: '#8b5cf6' },
{ id: 2, icon: Filter, title: 'SIGNAL FILTER', subtitle: 'Video', description: 'Elimina rumore, intro e sponsor dai video educativi.', color: '#06b6d4' },
{ id: 3, icon: Brain, title: 'MEMORY LOCK', subtitle: 'Quiz', description: 'Interrogazioni adattive che rinforzano le sinapsi deboli.', color: '#8b5cf6' },
];
return (
MODULI FEATURE
Componenti Interfaccia Olografica
{features.map((f) => (
handleMouseMove(e, f.id)} onMouseLeave={() => setTilt({ x: 0, y: 0, id: null })}
style={{ transform: tilt.id === f.id ? `rotateX(${tilt.y}deg) rotateY(${tilt.x}deg) scale(1.02)` : 'rotateX(0) rotateY(0) scale(1)', transformStyle: 'preserve-3d', transition: 'transform 0.1s ease-out' }}>
{f.subtitle}
{f.title}
{f.description}
))}
);
};
// ============================================
// PARENTS DASHBOARD
// ============================================
const ParentsDashboard = () => {
const { protocol, userData } = useUser();
const locked = protocol !== 'PRO';
return (
DASHBOARD GENITORI {locked && '[BLOCCATA]'}
{!locked ? (
ATTIVITÀ SETTIMANALE
{userData.hours || 0} ore
+{(userData.hours * 0.5).toFixed(1)}% vs settimana scorsa
PUNTEGGIO FOCUS
{Math.min(10, (userData.xp / 500)).toFixed(1)} / 10
REPORT EMAIL
"Tuo figlio ha completato {userData.hours || 0} ore di studio. Voto attuale: {Math.min(10, (userData.xp / 500)).toFixed(1)}"
RIPARTIZIONE MATERIE
{[{ l: 'Storia', v: 75, c: '#8b5cf6' }, { l: 'Scienze', v: 45, c: '#06b6d4' }, { l: 'Matematica', v: 60, c: '#10b981' }].map((item, i) => (
))}
) : (
VISUALIZZAZIONE DATI CRITTOGRAFATA
)}
);
};
// ============================================
// PRICING SECTION
// ============================================
const PricingSection = () => {
const { upgradeToCore, setShowPayment, protocol } = useUser();
const coreFeatures = ['Neural Engine Base', '5 Ricerche al Giorno', 'Accesso Community', 'Video Streaming Base'];
const proFeatures = [
'Ricerche Illimitate', 'Dashboard Genitori Completa', 'Elaborazione Prioritaria', 'Input Vocale Avanzato',
'Memory Lock Pro', 'Time Dilation Algorithm', 'Signal Filter HD', 'Report Email Settimanali',
'Supporto Prioritario 24/7', 'Nessuna Pubblicità'
];
return (
SCEGLI PROTOCOLLO
{/* Student Core */}
{protocol === 'CORE' && ATTIVO
}
STUDENT CORE
€0
{coreFeatures.map((x, i) => - {x}
)}
{protocol === 'GUEST' ? 'ATTIVA GRATIS' : 'GIÀ ATTIVO'}
{/* Scholar Pro */}
{protocol === 'PRO' ? 'ATTIVO' : 'CONSIGLIATO'}
SCHOLAR PRO
€9.99/mese
{proFeatures.map((x, i) => - {x}
)}
setShowPayment(true)} disabled={protocol === 'PRO'}
className="w-full py-3 bg-[#8b5cf6] text-white font-bold rounded-xl hover:bg-[#7c3aed] disabled:opacity-50">
{protocol === 'PRO' ? 'GIÀ PRO' : 'UPGRADE ORA'}
);
};
// ============================================
// PRO DASHBOARD (Interfaccia Dedicata Pro)
// ============================================
const ProDashboard = () => {
const { userData, setCurrentView } = useUser();
const [activeTab, setActiveTab] = useState('overview');
const [isListening, setIsListening] = useState(false);
const [voiceQuery, setVoiceQuery] = useState('');
const [searchHistory, setSearchHistory] = useState([]);
const [memoryCards, setMemoryCards] = useState([]);
const [flippedCard, setFlippedCard] = useState(null);
const [cardTopic, setCardTopic] = useState('');
const [isGeneratingCards, setIsGeneratingCards] = useState(false);
const generateFlashcards = async () => {
if (!cardTopic.trim()) return;
setIsGeneratingCards(true);
try {
if (!SYSTEM_CONFIG.OPENROUTER_KEY) throw new Error("No Key");
const response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
method: "POST",
headers: {
"Authorization": `Bearer ${SYSTEM_CONFIG.OPENROUTER_KEY}`,
"Content-Type": "application/json",
"HTTP-Referer": "http://localhost:5173",
"X-Title": "Synapse OS"
},
body: JSON.stringify({
"model": "google/gemini-2.0-flash-001",
"messages": [
{
"role": "system",
"content": "You are Synapse OS. Analyze the topic and return a STRICT JSON array of 3 objects: [{ \"id\": 1, \"front\": \"Question?\", \"back\": \"Answer\", \"mastery\": 0 }]. Limit answers to 5 words max. Language: ITALIAN."
},
{ role: 'user', content: `Topic: ${cardTopic}` }
]
})
});
const data = await response.json();
let cleanContent = data.choices[0].message.content.replace(/^```json\s*/, '').replace(/^```\s*/, '').replace(/\s*```$/, '');
const newCards = JSON.parse(cleanContent);
// Add random mastery for simulation
const cardsWithMastery = newCards.map((c, i) => ({ ...c, id: Date.now() + i, mastery: Math.floor(Math.random() * 40) }));
setMemoryCards(cardsWithMastery);
setCardTopic('');
} catch (e) {
console.error("Card Gen Failed", e);
} finally {
setIsGeneratingCards(false);
}
};
const [plannerEvents, setPlannerEvents] = useState([]);
const [videoTopic, setVideoTopic] = useState('');
const [videoSearching, setVideoSearching] = useState(false);
const [currentVideo, setCurrentVideo] = useState({ id: SYSTEM_CONFIG.FALLBACK_VIDEO_ID, title: 'La Rivoluzione Francese - Documentario Completo', topic: 'Rivoluzione Francese' });
const [videoQueue, setVideoQueue] = useState([
{ id: 'dQw4w9WgXcQ', title: 'Fisica Quantistica Semplificata', duration: '15:00' },
{ id: 'dQw4w9WgXcQ', title: 'Fisica Quantistica Semplificata', duration: '15:00' },
{ id: 'jNQXAC9IVRw', title: 'Storia del Rinascimento', duration: '18:00' },
]);
// Support Chat State
const [chatMessages, setChatMessages] = useState([
{ role: 'system', content: 'Synapse Support Agent Online. Come posso aiutarti oggi?' }
]);
const [chatInput, setChatInput] = useState('');
const [isTyping, setIsTyping] = useState(false);
const handleSupportMessage = async () => {
if (!chatInput.trim()) return;
const userMsg = chatInput;
setChatMessages(p => [...p, { role: 'user', content: userMsg }]);
setChatInput('');
setIsTyping(true);
try {
if (!SYSTEM_CONFIG.OPENROUTER_KEY) throw new Error("No Key");
const response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
method: "POST",
headers: {
"Authorization": `Bearer ${SYSTEM_CONFIG.OPENROUTER_KEY}`,
"Content-Type": "application/json",
"HTTP-Referer": "http://localhost:5173",
"X-Title": "Synapse OS"
},
body: JSON.stringify({
"model": "google/gemini-2.0-flash-001",
"messages": [
{
"role": "system",
"content": "You are Synapse Support, a helpful AI assistant for the Synapse OS platform. Answer questions about the app (Time Dilation, Signal Filters, Memory Lock), subscription (Pro is 9.99/mo), or general technical support. Be concise, professional, and use a futuristic tone. Language: ITALIAN."
},
...chatMessages.map(m => ({ role: m.role === 'system' ? 'assistant' : m.role, content: m.content })),
{ role: 'user', content: userMsg }
]
})
});
const data = await response.json();
if (!data.choices) throw new Error("AI Error");
setChatMessages(p => [...p, { role: 'system', content: data.choices[0].message.content }]);
} catch (e) {
setChatMessages(p => [...p, { role: 'system', content: "ERRORE CONNESSIONE: Impossibile contattare il supporto centrale." }]);
} finally {
setIsTyping(false);
}
};
const searchVideo = async () => {
if (!videoTopic.trim()) return;
setVideoSearching(true);
// Fallback function
const useFallback = () => {
const foundVideo = getTopicVideo(videoTopic);
setCurrentVideo({ ...foundVideo, topic: videoTopic });
};
try {
// 1. Ask Gemini for the best search query
if (!SYSTEM_CONFIG.OPENROUTER_KEY) throw new Error("No AI Key");
const response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
method: "POST",
headers: {
"Authorization": `Bearer ${SYSTEM_CONFIG.OPENROUTER_KEY}`,
"Content-Type": "application/json",
"HTTP-Referer": "http://localhost:5173",
"X-Title": "Synapse OS"
},
body: JSON.stringify({
"model": "google/gemini-2.0-flash-001",
"messages": [
{
"role": "system",
"content": "You are Synapse OS. Analyze the topic and return a STRICT JSON: { \"videoSearchQuery\": \"optimized youtube search query for topic\", \"title\": \"Formal Title of the topic\" }. Language: ITALIAN."
},
{ "role": "user", "content": `Topic: ${videoTopic}` }
]
})
});
const data = await response.json();
if (!data.choices) throw new Error("AI Error");
let cleanContent = data.choices[0].message.content.replace(/^```json\s*/, '').replace(/^```\s*/, '').replace(/\s*```$/, '');
const aiContent = JSON.parse(cleanContent);
let finalVideoId = `?listType=search&list=${encodeURIComponent(aiContent.videoSearchQuery)}`;
let finalTitle = aiContent.title;
// 2. Fetch from YouTube API if available
if (SYSTEM_CONFIG.YOUTUBE_KEY) {
try {
const ytRes = await fetch(`https://www.googleapis.com/youtube/v3/search?part=snippet&maxResults=1&q=${encodeURIComponent(aiContent.videoSearchQuery)}&type=video&key=${SYSTEM_CONFIG.YOUTUBE_KEY}`);
const ytData = await ytRes.json();
if (ytData.items && ytData.items.length > 0) {
finalVideoId = ytData.items[0].id.videoId;
finalTitle = ytData.items[0].snippet.title;
}
} catch (e) { console.error("YT API Error", e); }
}
setCurrentVideo({
id: finalVideoId,
title: finalTitle,
topic: videoTopic
});
} catch (error) {
console.error("Search failed, using fallback", error);
useFallback();
} finally {
setVideoSearching(false);
setVideoTopic('');
}
};
const startVoiceCommand = () => {
if ('webkitSpeechRecognition' in window || 'SpeechRecognition' in window) {
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
const recognition = new SpeechRecognition();
recognition.lang = 'it-IT';
recognition.continuous = true;
recognition.onstart = () => setIsListening(true);
recognition.onend = () => setIsListening(false);
recognition.onresult = (event) => {
const transcript = event.results[event.results.length - 1][0].transcript;
setVoiceQuery(transcript);
};
recognition.start();
}
};
const tabs = [
{ id: 'overview', label: 'Panoramica', icon: BarChart2 },
{ id: 'planner', label: 'Time Dilation', icon: Clock },
{ id: 'video', label: 'Signal Filter', icon: Video },
{ id: 'memory', label: 'Memory Lock', icon: Brain },
{ id: 'voice', label: 'Voice Commander', icon: Mic },
{ id: 'reports', label: 'Report', icon: Mail },
{ id: 'support', label: 'Supporto 24/7', icon: HelpCircle },
];
return (
{/* Header */}
SCHOLAR PRO
ID: SYN-{Math.floor(Math.random() * 9000) + 1000}
Benvenuto, {userData.name}
{/* Stats Bar */}
{[
{ label: 'XP Totali', value: userData.xp, color: '#8b5cf6', icon: Sparkles },
{ label: 'Ore Studio', value: `${userData.hours}h`, color: '#06b6d4', icon: Clock },
{ label: 'Streak', value: `${userData.streak} giorni`, color: '#10b981', icon: Zap },
{ label: 'Ricerche', value: '∞', color: '#f59e0b', icon: Search },
].map((stat, i) => (
{stat.value}
{stat.label}
))}
{/* Tabs */}
{tabs.map((tab) => (
))}
{/* Tab Content */}
{/* Overview */}
{activeTab === 'overview' && (
Attività Settimanale
{['Lun', 'Mar', 'Mer', 'Gio', 'Ven', 'Sab', 'Dom'].map((d, i) => {
// Distribute total hours roughly across week for viz
const avgDaily = userData.hours / 7;
const h = Math.min(100, (avgDaily + (Math.random() * avgDaily * 0.5)) * 10);
return (
);
})}
Ricerche Recenti
{searchHistory.length === 0 ?
Nessuna ricerca recente
: searchHistory.map((s, i) => (
{s.query}
{s.results} risultati
))}
)}
{/* Time Dilation Planner */}
{activeTab === 'planner' && (
TIME DILATION ALGORITHM
Adattato al tuo ritmo circadiano
{plannerEvents.length === 0 ?
Nessun evento programmato. Usa il simulatore per generare un piano.
: plannerEvents.map((event, i) => (
{event.type === 'focus' && }
{event.type === 'break' && }
{event.type === 'video' && }
{event.type === 'quiz' && }
{event.task}
{event.time} • {event.duration}
{event.completed &&
}
))}
)}
{/* Signal Filter Video */}
{activeTab === 'video' && (
{/* Search Input */}
SIGNAL FILTER HD
Inserisci un argomento e l'AI troverà il video perfetto per te. Intro, sponsor e contenuti a bassa densità rimossi automaticamente.
{/* Video Player */}
{videoSearching ? (
Analisi Neural in corso...
Filtro contenuti attivo
) : (
<>
FILTRATO
{currentVideo.topic}
{currentVideo.title}
>
)}
{/* Video Queue */}
Coda Suggerita
{Object.entries(VIDEO_DATABASE).slice(0, 4).map(([key, video], i) => (
setCurrentVideo({ ...video, topic: key })}
className="flex items-center gap-3 p-3 bg-slate-800/30 rounded-lg hover:bg-slate-700/30 cursor-pointer transition-all">
{video.title}
))}
)}
{/* Memory Lock Pro */}
{activeTab === 'memory' && (
{memoryCards.map((card) => (
setFlippedCard(flippedCard === card.id ? null : card.id)}
className="relative h-48 cursor-pointer" style={{ perspective: '1000px' }}>
{/* Front */}
{/* Back */}
))}
)}
{/* Voice Commander */}
{activeTab === 'voice' && (
VOICE COMMANDER AVANZATO
{isListening ? 'Ascolto in corso...' : 'Clicca per attivare i comandi vocali'}
{voiceQuery &&
"{voiceQuery}"
}
{['Cerca [argomento]', 'Avvia sessione studio', 'Mostra statistiche'].map((cmd, i) => (
{cmd}
))}
)}
{/* Reports */}
{activeTab === 'reports' && (
REPORT EMAIL SETTIMANALI
Report Settimanale - Synapse OS
Inviato ogni Domenica alle 20:00
📊 Attività: 14.5 ore di Deep Work completate
🎯 Focus Score: 8.5/10 (+12% vs settimana precedente)
📚 Materie: Storia (75%), Scienze (45%), Matematica (60%)
🏆 Voto Simulato: 8.5
)}
{/* Support Chat (AI) */}
{activeTab === 'support' && (
SUPPORTO PRIORITARIO 24/7
{chatMessages.map((msg, i) => (
))}
{isTyping &&
L'agente sta scrivendo...
}
setChatInput(e.target.value)}
onKeyDown={(e) => e.key === 'Enter' && handleSupportMessage()}
placeholder="Scrivi il tuo problema..."
className="flex-1 bg-slate-900 border border-slate-700 rounded-lg px-4 py-2 text-white focus:outline-none focus:border-[#10b981]"
/>
)}
);
};
// ============================================
// SYSTEM FOOTER
// ============================================
const SystemFooter = () => (
);
// ============================================
// MAIN APP
// ============================================
const AppContent = () => {
const { currentView, protocol } = useUser();
// Landing Page (Guest or Core)
if (currentView === 'LANDING' || protocol !== 'PRO') {
return (
);
}
// Pro Dashboard (Fully Unlocked & Real AI)
return (
);
};
function App() {
return (
);
}
export default App;