import { initializeApp } from "https://www.gstatic.com/firebasejs/10.14.1/firebase-app.js"; import { getAuth, onAuthStateChanged, signOut } from "https://www.gstatic.com/firebasejs/10.14.1/firebase-auth.js"; import { getFirestore, collection, addDoc, updateDoc, doc, onSnapshot, query } from "https://www.gstatic.com/firebasejs/10.14.1/firebase-firestore.js"; import { firebaseConfig } from "./config.js"; // --- INIT --- const app = initializeApp(firebaseConfig); const auth = getAuth(app); const db = getFirestore(app); // --- VARIABLER --- let currentUser = null; let people = []; let focusPersonId = null; let currentScale = 1.0; let modalAction = null; let modalMode = 'new'; let mapInstance = null; // Leaflet map // --- SIKKERHETSSJEKK (Kjøres med en gang) --- onAuthStateChanged(auth, (user) => { if (user) { currentUser = user; startDataListener(); } else { window.location.href = "index.html"; } }); // Logg ut knapp const logoutBtn = document.getElementById('btn-logout'); if (logoutBtn) { logoutBtn.addEventListener('click', () => { signOut(auth).then(() => { window.location.href = "index.html"; }); }); } // --- DATABASE LYTTER --- function startDataListener() { const q = query(collection(db, 'familyMembers')); onSnapshot(q, (snapshot) => { people = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })); if (!focusPersonId && people.length > 0) { const me = people.find(p => p.name && (p.name.toLowerCase().includes('eivind') || p.name.toLowerCase() === 'meg')); focusPersonId = me ? me.id : people[0].id; } // Oppdater alle visninger renderTree(); updateMapMarkers(); renderTimeline(); }); } // --- NAVIGASJON (TABS) --- document.querySelectorAll('.nav-tab').forEach(tab => { tab.addEventListener('click', () => { // 1. Visuell tab state document.querySelectorAll('.nav-tab').forEach(t => t.classList.remove('active')); tab.classList.add('active'); // 2. Skjul/vis seksjoner document.querySelectorAll('.view-section').forEach(s => s.classList.add('hidden')); const targetId = tab.dataset.tab + '-view'; document.getElementById(targetId).classList.remove('hidden'); // 3. Spesialhåndtering if (tab.dataset.tab === 'map') { initMap(); // Sørg for at kartet tegnes riktig når det blir synlig } }); }); // --- TEGNE TREET (RENDERING) --- function renderTree() { const rowParents = document.getElementById('row-parents'); const rowFocus = document.getElementById('row-focus'); const rowChildren = document.getElementById('row-children'); if (!rowParents || !rowFocus || !rowChildren) return; rowParents.innerHTML = ''; rowFocus.innerHTML = ''; rowChildren.innerHTML = ''; if (people.length === 0) { rowFocus.innerHTML = ``; return; } const focusPerson = people.find(p => p.id === focusPersonId); if (!focusPerson) return; // A. Foreldre const father = people.find(p => p.id === focusPerson.fatherId); const mother = people.find(p => p.id === focusPerson.motherId); rowParents.appendChild(createSlot(father, 'Far', 'add-parent-m')); rowParents.appendChild(createSlot(mother, 'Mor', 'add-parent-f')); // B. Partner const partner = people.find(p => p.id === focusPerson.partnerId); if (partner) { const pCard = createCard(partner); pCard.onclick = () => { focusPersonId = partner.id; renderTree(); }; rowFocus.appendChild(pCard); const heart = document.createElement('div'); heart.innerHTML = ''; rowFocus.appendChild(heart); } // C. Fokus Person rowFocus.appendChild(createCard(focusPerson, true)); // D. Barn const children = people.filter(p => p.fatherId === focusPersonId || p.motherId === focusPersonId); children.forEach(child => { const cCard = createCard(child); cCard.onclick = () => { focusPersonId = child.id; renderTree(); }; rowChildren.appendChild(cCard); }); } function createCard(person, isFocus = false) { const el = document.createElement('div'); el.className = `card ${isFocus ? 'focus' : ''} ${person.gender === 'F' ? 'female' : 'male'}`; const year = person.birthDate ? new Date(person.birthDate).getFullYear() : '????'; const dead = person.deathDate ? '✝ ' : ''; el.innerHTML = `
${dead}${year}
${person.location ? ' ' + person.location.split(',')[0] + '' : ''} `; if (isFocus) { const actions = document.createElement('div'); actions.className = 'focus-actions'; const btnChild = document.createElement('button'); btnChild.className = 'btn-mini-add add-child'; btnChild.innerHTML = ''; btnChild.onclick = (e) => { e.stopPropagation(); window.openModal('add-child'); }; actions.appendChild(btnChild); if (!person.partnerId) { const btnPartner = document.createElement('button'); btnPartner.className = 'btn-mini-add add-partner'; btnPartner.innerHTML = ''; btnPartner.onclick = (e) => { e.stopPropagation(); window.openModal('add-partner'); }; actions.appendChild(btnPartner); } el.appendChild(actions); } return el; } function createSlot(person, label, actionType) { const wrapper = document.createElement('div'); wrapper.className = 'slot-container'; wrapper.innerHTML = `${label}`; if (person) { const card = createCard(person); card.onclick = () => { focusPersonId = person.id; renderTree(); }; wrapper.appendChild(card); } else { const btn = document.createElement('div'); btn.className = 'btn-add-slot'; btn.innerHTML = ''; btn.onclick = () => window.openModal(actionType); wrapper.appendChild(btn); } return wrapper; } // --- KART FUNKSJONALITET (Leaflet) --- function initMap() { if (mapInstance) { mapInstance.invalidateSize(); // Viktig når kartet vises etter å ha vært skjult return; } // Startposisjon: Norge (omtrentlig) mapInstance = L.map('map-container').setView([65.0, 13.0], 5); L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', { attribution: '© OpenStreetMap contributors © CARTO', subdomains: 'abcd', maxZoom: 19 }).addTo(mapInstance); updateMapMarkers(); } async function updateMapMarkers() { if (!mapInstance) return; // Fjern gamle markører (enklest å tømme og tegne på nytt for nå) mapInstance.eachLayer((layer) => { if (layer instanceof L.Marker) { mapInstance.removeLayer(layer); } }); for (const p of people) { if (p.location) { // Prøv å finne koordinater. For nå, antar vi at input KAN være "lat,lng" // I en ekte app ville vi brukt en geocoding service her. // For demo: Hvis location inneholder komma og tall, bruk det. // Ellers, randomiser litt rundt Grimstad for demo-formål hvis det står "Grimstad" let lat = 0, lng = 0; if (p.location.includes(',')) { const parts = p.location.split(','); if (!isNaN(parseFloat(parts[0]))) { lat = parseFloat(parts[0]); lng = parseFloat(parts[1]); } } else if (p.location.toLowerCase().includes('grimstad')) { lat = 58.34 + (Math.random() * 0.05 - 0.025); lng = 8.59 + (Math.random() * 0.05 - 0.025); } else if (p.location.toLowerCase().includes('oslo')) { lat = 59.91; lng = 10.75; } if (lat !== 0) { L.marker([lat, lng]) .addTo(mapInstance) .bindPopup(`${p.name}${ev.desc}
` : ''}