import React, { useState, useEffect, useRef } from 'react'; import { initializeApp } from 'firebase/app'; import { getAuth, signInAnonymously, onAuthStateChanged, signInWithCustomToken } from 'firebase/auth'; import { getFirestore, doc, setDoc, onSnapshot, collection } from 'firebase/firestore'; // --- CONFIGURATION --- const firebaseConfig = JSON.parse(__firebase_config); const app = initializeApp(firebaseConfig); const auth = getAuth(app); const db = getFirestore(app); const appId = typeof __app_id !== 'undefined' ? __app_id : 'family-hub-default'; // --- ICONS (Inline SVG for reliability) --- const IconClock = () => ; const IconSun = ({ className }) => ; const IconCloud = ({ className }) => ; const IconCalendar = ({ className }) => ; const IconSettings = ({ size = 24 }) => ; const IconSave = () => ; const IconLock = () => ; export default function App() { const [user, setUser] = useState(null); const [view, setView] = useState('display'); const [adminAuth, setAdminAuth] = useState(false); const [password, setPassword] = useState(''); const [currentTime, setCurrentTime] = useState(new Date()); const [settings, setSettings] = useState({ city: 'Stockholm', weatherApiKey: '', greeting: 'Välkomna hem familjen!', photoUrls: [ 'https://images.unsplash.com/photo-1506744038136-46273834b3fb', 'https://images.unsplash.com/photo-1470770841072-f978cf4d019e' ], calendarEvents: [ { id: 1, title: 'Gympa - Elsa', time: '17:30' }, { id: 2, title: 'Middag hos mormor', time: '18:30' } ] }); const [weather, setWeather] = useState(null); const [currentPhotoIndex, setCurrentPhotoIndex] = useState(0); // 1. Firebase Auth useEffect(() => { const initAuth = async () => { try { if (typeof __initial_auth_token !== 'undefined' && __initial_auth_token) { await signInWithCustomToken(auth, __initial_auth_token); } else { await signInAnonymously(auth); } } catch (err) { console.error("Auth error:", err); } }; initAuth(); const unsubscribe = onAuthStateChanged(auth, setUser); return () => unsubscribe(); }, []); // 2. Sync Settings (Fixed Path Segments) useEffect(() => { if (!user) return; // RULE 1: artifacts/{appId}/public/data/{collectionName}/{documentId} const settingsRef = doc(db, 'artifacts', appId, 'public', 'data', 'config', 'settings'); const unsubscribe = onSnapshot(settingsRef, (docSnap) => { if (docSnap.exists()) { setSettings(docSnap.data()); } else { setDoc(settingsRef, settings).catch(e => console.error("Initial set error:", e)); } }, (error) => console.error("Firestore sync error:", error)); return () => unsubscribe(); }, [user]); // 3. Timers useEffect(() => { const timer = setInterval(() => setCurrentTime(new Date()), 1000); const photoTimer = setInterval(() => { setCurrentPhotoIndex((prev) => (prev + 1) % settings.photoUrls.length); }, 15000); return () => { clearInterval(timer); clearInterval(photoTimer); }; }, [settings.photoUrls.length]); // 4. Weather Fetch useEffect(() => { const fetchWeather = async () => { const key = settings.weatherApiKey; if (!key) return; try { const res = await fetch(`https://api.openweathermap.org/data/2.5/weather?q=${settings.city}&units=metric&lang=se&appid=${key}`); const data = await res.json(); if (data.main) setWeather(data); } catch (err) { console.error("Weather fetch error:", err); } }; fetchWeather(); const interval = setInterval(fetchWeather, 600000); return () => clearInterval(interval); }, [settings.city, settings.weatherApiKey]); const saveSettings = async (newSettings) => { if (!user) return; const settingsRef = doc(db, 'artifacts', appId, 'public', 'data', 'config', 'settings'); await setDoc(settingsRef, newSettings); }; // --- VIEWS --- const AdminPanel = () => { const [localSettings, setLocalSettings] = useState({...settings}); const [newPhotoUrl, setNewPhotoUrl] = useState(''); if (!adminAuth) { return (

Admin Inloggning

setPassword(e.target.value)} />
); } return (

Inställningar

Basinformation

setLocalSettings({...localSettings, city: e.target.value})}/>
setLocalSettings({...localSettings, greeting: e.target.value})}/>
setLocalSettings({...localSettings, weatherApiKey: e.target.value})} placeholder="API-nyckel"/>

Bildspel (URLs)

{localSettings.photoUrls.map((url, i) => (
{url}
))}
setNewPhotoUrl(e.target.value)}/>
); }; const DisplayView = () => { const timeStr = currentTime.toLocaleTimeString('sv-SE', { hour: '2-digit', minute: '2-digit' }); const dateStr = currentTime.toLocaleDateString('sv-SE', { weekday: 'long', day: 'numeric', month: 'long' }); return (
{settings.photoUrls.map((url, i) => ( Background { e.target.src = 'https://images.unsplash.com/photo-1506744038136-46273834b3fb'; }}/> ))}

{timeStr}

{dateStr}

{weather && (
{Math.round(weather.main.temp)}° {weather.weather[0].main.includes('Cloud') ? : }

{weather.weather[0].description}

{settings.city}

)}

"{settings.greeting}"

Familjens Schema

{settings.calendarEvents.map(event => (
{event.title} {event.time}
))}
); }; return (
{view === 'admin' ? : }
); }