Idag lagras inpasseringsdata hårdkodat i BASE_DATA-objektet i
index.html och data.html. Det fungerar bra,
men för att uppdatera siffrorna måste Kent redigera koden och publicera via
GitHub – varje gång.
BASE_DATA behålls alltid i koden som reserv, ifall Firebase inte går att nå.
Alla 8 steg är genomförda och systemet är i produktion på GitHub Pages. Föreningsmedlemmar loggar in direkt på data.html och uppdaterar siffror utan att Kent behöver göra något. Nya användare bjuds in via "✉ Bjud in"-knappen i nedre vänstra hörnet av data.html – administratören anger namn, e-post och tillfälligt lösenord, och ett färdigt välkomstbrev genereras att kopiera och skicka.
Aktiva användare (2026-05-15):
•
lundgren.kent@gmail.com – administratör•
bjorn.syren1@gmail.com – Björn Syren, inbjuden 2026-05-15
Firebase är Googles backend-plattform, men den innehåller faktiskt två helt skilda databasprodukter. Det är lätt att blanda ihop dem – de heter nästan likadant och lever i samma Firebase-projekt. Här är skillnaden:
| Egenskap | ☁️ Firestore | ⚡ Realtime Database |
|---|---|---|
| Hur data lagras | Dokument i samlingar (som mappar med JSON-filer) | Ett enda stort JSON-träd (som ett JavaScript-objekt) |
| Struktur | Hierarkisk: samlingar → dokument → fält | Platt träd: nod/nod/nod → värde |
| Passar bäst för | Komplex data, relationer, avancerade sökfrågor | Enkel tabelldata, realtidssynk, enkla strukturer |
| Realtidsuppdatering | Ja, men kräver lite mer kod | Ja, inbyggt och mycket enkelt |
| SDK-exempel | firebase.firestore() |
getDatabase(app) + ref() |
| Används i projektet | Bjerred-skylt (trivselregler, röster) | Quiz 16B (resultat, namn, poäng) |
Titta på hur BASE_DATA ser ut i koden:
BASE_DATA[2026]['Medlemmar – armband'][3] = 90.Det är exakt samma struktur som ett JSON-träd:
data/2026/Medlemmar – armband/3 = 90.Realtime Database är ett JSON-träd. Vi kan kopiera BASE_DATA rakt in utan att ändra strukturen. Firestore hade krävt att vi omstrukturerar data till dokument och samlingar – onödigt jobb.
Vi använder det befintliga Firebase-projektet "skylt" (skylt-e0c45), som redan är kopplat till Bjerreds Saltsjöbad via appen "Bjerreds-skylt". Inpasseringsdata sparas under en egen nod i databasen så att den inte krockar med annan data i projektet.
https://console.firebase.google.com/project/skylt-e0c45
ℹ️ Länken är inte hemlig – den kräver att du är inloggad med rätt Google-konto för att visa något. Den långa URL som Firebase Console ibland genererar (med
web:ZmU3... i slutet) är bara
App-ID:t kodat och behövs inte – den kortare versionen ovan fungerar
lika bra och är enklare att läsa.
Nedanför visas firebaseConfig för projektet.
Notera att koden är anpassad för CDN-laddning (direkt i HTML utan
byggverktyg), inte npm-versionen som visas i Firebase Console.
// ============================================================ // FIREBASE-KONFIGURATION – projekt "skylt" (skylt-e0c45) // Används för Bjerreds-skylt-appen (Web App) // // OBS: Konfigurationen nedan är för CDN-varianten (ES-moduler // från gstatic.com), inte npm-versionen. Det är det format // som fungerar direkt i en HTML-fil utan byggverktyg. // // databaseURL saknas ännu – läggs till när Realtime Database // har aktiverats i Firebase Console (se steg 3 nedan). // ============================================================ import { initializeApp, getApps } from 'https://www.gstatic.com/firebasejs/11.0.0/firebase-app.js'; import { getDatabase, ref, set, onValue } from 'https://www.gstatic.com/firebasejs/11.0.0/firebase-database.js'; const firebaseConfig = { apiKey: "AIzaSyBbAX6EFxbW1VIcSYQ3Zqbr3v733sGMYD8", authDomain: "skylt-e0c45.firebaseapp.com", projectId: "skylt-e0c45", storageBucket: "skylt-e0c45.firebasestorage.app", messagingSenderId: "653653642598", appId: "1:653653642598:web:29e332c87fed1cd9f34ca7", // databaseURL – tillagd efter att Realtime Database aktiverades (steg 3 klart): databaseURL: "https://skylt-e0c45-default-rtdb.europe-west1.firebasedatabase.app" };
databas.html (den här sidan) är ett levande arbetsdokument – en loggbok över vad vi gör, varför vi gör det, och hur långt vi har kommit. databaseURL:en finns här för att anslutningstest-knappen ska kunna testa om Firebase svarar. Den här sidan påverkar inte produktionsdatan.
data.html är produktionsfilen – den som besökare använder för att se och (när Firebase är klart) uppdatera inpasseringssiffror. Firebase-koden läggs in i data.html i steg 7, inte förrän allt är testat och klart.
SDK = Software Development Kit
Ett SDK (uttalas "es-dee-kay") är ett färdigt verktygslåda
av kod som ett företag paketerar och ger bort till utvecklare, så att
de slipper uppfinna hjulet på nytt. I stället för att skriva all kommunikation
med Firebase-servrar från grunden laddar vi in Googles SDK – och sedan
räcker det att anropa enkla funktioner som set() och
onValue().
Nej – SDK:er finns för i princip allt inom modern mjukvaruutveckling. Några exempel på vad SDK:er används till:
- Databaser och molntjänster – Firebase, AWS, Azure (det vi använder här)
- Betalningar – Stripe SDK, Klarna SDK, Swish
- Kartor – Google Maps SDK, Mapbox
- Inloggning – BankID SDK, Google Sign-In
- Mobilappar – Android SDK, iOS SDK (hela plattformen)
- AI-tjänster – OpenAI SDK, Anthropic SDK
- Statistik – Google Analytics SDK
Firebase JS SDK – versioner
Google släpper kontinuerligt nya versioner av Firebase JavaScript SDK. Varje version kan innehålla buggfixar, prestandaförbättringar, nya funktioner – och ibland ändringar som kan bryta befintlig kod (breaking changes). Versionen anges i CDN-länken:
// Versionen styr vilken kod som laddas från Googles servrar: import { initializeApp } from 'https://www.gstatic.com/firebasejs/11.0.0/firebase-app.js';
| Version | Status | Används i projektet | Notering |
|---|---|---|---|
| v10.7.0 | Äldre | Bjerred-skylt (Firestore, compat-läge) | Äldre compat-API – fortfarande vanlig |
| v11.0.0 | ✅ Stabil – används nu | data.html + databas.html (Realtime DB) | ES-moduler, vältestad, rekommenderas |
| v12.13.0 | 🆕 Senaste (maj 2026) | – | Nyast men mindre beprövad i produktion |
data.html (firebase-app, firebase-database, firebase-auth)
och tre ställen i databas.html.
Firebase Realtime Database lagrar data som ett JSON-träd.
Vi speglar strukturen i BASE_DATA-objektet rakt av,
men lägger allt under noden bjerred-inpasseringar/
för att inte krocka med annan data i projektet.
| Sökväg i Firebase | Innehåll | Exempel |
|---|---|---|
bjerred-inpasseringar/data |
Rotnod för all inpasseringsdata | – |
.../data/2026 |
Årsdata, ett objekt per år | – |
.../data/2026/Medlemmar – armband |
Kategori, ett objekt per kategori | – |
.../data/2026/Medlemmar – armband/3 |
Månadsindex (0 = jan, 3 = apr) | 90 |
bjerred-inpasseringar/senast-uppdaterad |
Datum för senaste ändring | "2026-05-15" |
{
"rules": {
"bjerred-inpasseringar": {
".read": "true",
".write": "auth != null"
}
}
}
I vardagligt tal används orden ibland som synonymer, och i det här projektet betyder de i praktiken samma sak:
Backend är den del av ett system som användaren inte ser – servern, databasen, logiken som körs bakom kulisserna. Motsatsen är frontend, det vill säga det som visas i webbläsaren (HTML, CSS, JavaScript).
Databas är den specifika del av backend där data lagras permanent. En backend kan innehålla mycket mer (beräkningar, autentisering, e-post osv.), men för det här projektet är det databasen som är det viktiga.
Firebase är en backend som en tjänst (BaaS – Backend as a Service): Google sköter servern och infrastrukturen, vi sköter bara vår data och våra regler. Det är därför Firebase är ett bra val för ett litet projekt som det här – vi slipper sätta upp en egen server.
Kort sagt: när vi säger "koppla data.html till en backend" menar vi "lagra inpasseringssiffrorna i Firebase-databasen istället för bara lokalt i webbläsaren".
-
✅
Steg 1 – Firebase-projekt valt Använder befintliga projektet "skylt" (skylt-e0c45) med appen "Bjerreds-skylt". Inget nytt projekt behövs.
-
✅
Steg 2 – firebaseConfig hämtad Konfigurationen är kopierad från Firebase Console och dokumenterad ovan i det här dokumentet.
-
✅
Steg 3 – Aktivera Realtime Database i Firebase Console Klart! Realtime Database är aktiverad i projektet "skylt" (europe-west1). Databasen är tom men redo att ta emot data.
databaseURL:https://skylt-e0c45-default-rtdb.europe-west1.firebasedatabase.app
Obs: URL:en slutar på/:nulli Firebase Console – det betyder bara att databasen är tom. Det är korrekt. -
✅
Steg 4 – Säkerhetsregler publicerade Klart! Reglerna är publicerade i Firebase Console. Noden
bjerred-inpasseringarkan läsas av alla, men bara skriva av inloggade användare (auth != null). De gamla testlägesreglerna (med utgångsdatum 2026-06-14) är borttagna. -
✅
Steg 5 – Firebase Authentication aktiverad Klart! Inloggningsmetoden E-post/lösenord är aktiverad. Användarkonto skapat:
lundgren.kent@gmail.com(2026-05-15). Det är det kontot som används för att logga in och få skriva i databasen. -
✅
Steg 6 – Engångsmigration klar (2026-05-15) All historisk data är uppskriven till Firebase Realtime Database. 11 kategorier skrivna, 0 fel. Data finns under
bjerred-inpasseringar/data/i Firebase Console. Migrationen kördes inloggad somlundgren.kent@gmail.com. -
✅
Steg 7 – data.html omskriven för Firebase (2026-05-15) Hela JavaScript-blocket skrevs om med
<script type="module">och Firebase SDK v11.0.0 (ES-moduler via CDN).
•onValue()prenumererar påbjerred-inpasseringar/data– tabellen uppdateras live.
•set()sparar cellredigering direkt till Firebase.
•BASE_DATArenderas omedelbart vid sidladdning som fallback.
• Inloggningsmodal visas automatiskt vid cellklick om ej inloggad.
• Grön/röd statusdot i headern visar om Firebase är uppkopplad.
• CSP-metatag tillåter Firebase WebSocket från GitHub Pages.
•tolkFirebaseSnapshot()hanterar kategorier med snedstreck (nästlad sökväg i Firebase). -
✅
Steg 8 – Testat och publicerat på GitHub Pages (2026-05-15) Pusha direkt till
mainvia Cursor – säkerhetskopior (index copy.html,data copy.html) fungerade som skyddsnät i stället för separat branch.
Bekräftat på live-URL: data.html:
• Tabellen laddas från Firebase ✓
• Live-synk bekräftad: ändring i Chrome syntes direkt i Firefox ✓
• Inloggning och utloggning fungerar frånkentlundgren.github.io✓
Tillägg efter steg 8: "Bjud in"-knapp (✉ Bjud in) lagd till i nedre vänstra hörnet av data.html. Knappen öppnar en modal där administratören fyller i namn, e-post och tillfälligt lösenord – ett färdigt välkomstbrev genereras automatiskt och kan kopieras med ett klick. Inbjudan skickad till Björn Syren (bjorn.syren1@gmail.com) 2026-05-15.
Skriptet behöver Firebase SDK för att kunna skriva till databasen. Firebase SDK är inläst på den här sidan (databas.html) – det lade vi in tidigare. data.html har ingen Firebase-kod än (det kommer i steg 7). Därför kör vi migrationen härifrån.
Är BASE_DATA samma i data.html och databas.html?
BASE_DATA finns i
data.html och inpasseringar/index.html
– de är identiska och hålls alltid synkade. Den här sidan (databas.html)
har ingen BASE_DATA. Därför är all historisk data inbakad direkt i
skriptet nedan – en kopia av BASE_DATA från data.html.
Så här gör du:
- Se till att du är på sidan databas.html i webbläsaren
- Tryck F12 för att öppna utvecklarverktyget
- Klicka på fliken Console
- Kopiera hela skriptet nedan och klistra in det i konsolen
- Tryck Enter
- Vänta på bekräftelsemeddelandena – hela BASE_DATA skrivs till Firebase
// ============================================================ // ENGÅNGSMIGRATION – BASE_DATA → Firebase Realtime Database // ============================================================ // Kör detta skript EN GÅNG i konsolen (F12) på databas.html. // Skriptet använder Firebase SDK som redan är inläst på sidan. // // Data skrivs till: bjerred-inpasseringar/data/{år}/{kategori}/{månadsindex} // ============================================================ (async () => { // ============================================================ // STEG 0 – Logga in med ditt Firebase-konto // Skriptet måste autentisera sig innan det kan skriva, // eftersom säkerhetsreglerna kräver auth != null. // Fyll i ditt lösenord på raden nedan innan du kör skriptet. // ============================================================ const EPOST = 'lundgren.kent@gmail.com'; const LÖSENORD = 'FYLL_IN_DITT_LÖSENORD_HÄR'; // ← ändra detta const { getAuth, signInWithEmailAndPassword } = await import('https://www.gstatic.com/firebasejs/11.0.0/firebase-auth.js'); const auth = getAuth(); try { await signInWithEmailAndPassword(auth, EPOST, LÖSENORD); console.log('✅ Inloggad som', EPOST); } catch (e) { console.error('❌ Inloggning misslyckades:', e.message); return; // avbryt om inloggningen misslyckas } // ---- BASE_DATA – identisk kopia från data.html och index.html ---- const BASE_DATA = { /* ---- 2024 -------------------------------------------------- */ 2024: { 'Restaurangen': [754,696,772,656,841, 654,696,678,725,607,795,620], 'SMS-biljetter': [557,458,484,331,265, 184,143,197,240,484,593,827], 'Medlemmar – armband': [2949,2788,3096,2251,3388,3130,3581,3362,4210,3146,3299,3255] }, /* ---- 2025 – 0-värden mars–juli = ombyggnad av bastun ------- */ 2025: { 'Restaurangen/badbiljetter': [737,764, 0, 0, 0, 0, 344, 891, 991, 667, 794, 621], 'SMS/Swish-biljett': [801,619, 0, 0, 0, 0, 4, 140, 285, 726,1052,1373], 'Medlemmar – armband': [3231,2555, 0, 0, 0, 0,1524,2134,2339,1552,1400,1000], 'Medlemmar – Wonder': [ 0, 0, 0, 0, 0, 0, 120,1359,1729,1993,2443,2513] }, /* ---- 2026 – null = saknas (ännu ej rapporterat) ------------ */ 2026: { 'Restaurangen/badbiljetter': [643, 665, 600,null,null,null,null,null,null,null,null,null], 'SMS/Swish-biljetter': [1114, 751,1006, 913,null,null,null,null,null,null,null,null], 'Medlemmar – armband': [ 492, 119, 95, 90,null,null,null,null,null,null,null,null], 'Medlemmar – Wonder': [2627,2445,3663,3293,null,null,null,null,null,null,null,null] } }; // ---- Hämta Firebase-instansen som redan är initierad på sidan ---- const { getDatabase, ref, set } = await import('https://www.gstatic.com/firebasejs/11.0.0/firebase-database.js'); const db = getDatabase(); let ok = 0; let fel = 0; // ---- Skriv år för år, kategori för kategori till Firebase -------- for (const [år, kategorier] of Object.entries(BASE_DATA)) { for (const [kategori, månader] of Object.entries(kategorier)) { // Bygg ett objekt {0: val, 1: val, ...} – null-värden inkluderas const månadsObj = {}; månader.forEach((v, i) => { månadsObj[i] = v ?? 'null'; }); try { await set( ref(db, `bjerred-inpasseringar/data/${år}/${kategori}`), månadsObj ); console.log(`✅ ${år} / ${kategori}`); ok++; } catch (e) { console.error(`❌ ${år} / ${kategori}: ${e.message}`); fel++; } } } // ---- Spara tidsstämpel för migrationen --------------------------- await set(ref(db, 'bjerred-inpasseringar/senast-uppdaterad'), new Date().toLocaleDateString('sv-SE')); console.log(`\n✅ Migration klar! ${ok} kategorier skrivna, ${fel} fel.`); if (fel > 0) console.warn('Kontrollera felen ovan och kör om vid behov.'); })();
Knappen nedan försöker ansluta till Firebase och skriva ett
testmeddelande under noden bjerred-inpasseringar/anslutningstest.
Testet fungerar inte förrän Realtime Database är aktiverad
och databaseURL är inlagd.
databaseURL är inlagd
och säkerhetsreglerna är i produktion (read=true, write=auth!=null).
Tidigare försökte det här testet skriva ett testmeddelande till Firebase. Det gav felet
PERMISSION_DENIED – och det är korrekt beteende:
säkerhetsreglerna kräver numera inloggning för all skrivning, och anslutningstest-knappen
är inte inloggad.Testet är nu uppdaterat och gör istället en läsning av riktig produktionsdata (
bjerred-inpasseringar/senast-uppdaterad).
Läsning är öppen för alla – det bekräftar att Firebase är nådd och svarar.
Vill du testa skrivning loggar du in i data.html
och redigerar en cell.
Kent har arbetat med Firebase i två olika projekt som använder olika Firebase-tekniker. Det är viktigt att förstå skillnaden inför arbetet med inpasseringsdata.
| Projekt | Teknik | SDK | Passar för |
|---|---|---|---|
|
Bjerred-skylt
skylt-e0c45 |
Firestore Dokumentdatabas |
v10.7.0 compat script-taggar |
Komplex data, avancerade queries, röster och förslag |
|
Quiz 16B
borgholm-registration |
Realtime Database JSON-träd |
v11.0.0 ES-moduler import-satser |
Enkel tabelldata, realtidssynk, passar BASE_DATA-strukturen |
Vad lagras? Trivselregler för bastun, med möjlighet att rösta (👍/👎) och föreslå ändringar av enskilda regler. Varje regel är ett eget objekt med svenska och engelska texter, ett röstningsresultat och en lista med användarförslag.
Var Firestore ett bra val här?
- Varje regel är ett dokument med flera fält (textSv, textEn, votes.up, votes.down, suggestions). Det passar Firestores dokumentstruktur perfekt.
- Röstning och förslag är oberoende av varandra – Firestore hanterar det bra med subcollections.
- Firestore har inbyggt stöd för att lyssna på ändringar i enskilda dokument (t.ex. bara regel nr 3), vilket är effektivt när man bara vill uppdatera en reglad i taget.
- Compat-SDK v10.7.0 (script-taggar) är enkel att komma igång med – rätt nivå för ett lärande-projekt.
Kort sagt: Data med relationer (regel → röster → förslag) = Firestore. Det är precis det Bjerred-skylt har.
Vad lagras? Quizresultat – varje deltagare skickar in sitt namn, sin poäng och ett svårighetsbetyg (1–10). Allt sparas i en enkel lista som sedan kan visas för alla.
Var Realtime Database ett bra val här?
- Quizresultat är en enkel lista av poster (namn + poäng + betyg + datum). Det är ett platt JSON-träd – exakt vad Realtime Database är optimerat för.
- Med
push()läggs varje ny post till med ett unikt nyckel-ID automatiskt. Enkelt och felfritt. onValue()lyssnar i realtid – om en ny person skickar in sitt resultat syns det direkt för alla utan att sidan behöver laddas om.- Modern ES-modul-SDK (v11.0.0) med
import-satser är det senaste och mest underhållna alternativet.
Kort sagt: Enkel lista med poster som skapas och läses i realtid = Realtime Database. Perfekt match.
borgholm-registration
– ett namn som inte har med quiz att göra. Det funkar tekniskt,
men om man bygger om det idag skulle man skapa ett nytt
Firebase-projekt med ett tydligare namn. Återigen: inte fel,
bara lite otydligt i efterhand.
Båda tidigare val var välmotiverade och tekniskt korrekta. Det visar att du redan har en god intuition för när man väljer vad. För inpasseringsdata är valet lika tydligt:
BASE_DATA[år][kategori][månadsindex] är ett
JSON-träd → Realtime Database.
Samma teknik som i quiz-projektet, fast nu i projektet "skylt"
(skylt-e0c45) istället för borgholm-registration.
Länk till datatabellen som ska få Firebase-koppling: 📊 data.html
I samband med att en ny datakategori (Engångsbadare – Wondr)
lades till i data.html uppstod en förvirring som ledde till en
viktig insikt om hur systemet verkligen fungerar.
Det finns två separata lagringsplatser för inpasseringsdata. De synkroniseras inte automatiskt med varandra.
| Lagring | Vad är det? | Hur uppdateras det? | Grön prick? |
|---|---|---|---|
| BASE_DATA |
JavaScript-konstant hårdkodad direkt i HTML-filerna
(data.html, index.html).
Det är vanlig kod – inte browser-localStorage
och inte Firebase.
|
Redigera filen i Cursor → commit → push | ❌ Nej (orange) |
| Firebase | Realtidsdatabas online. Alla sidor med grön prick läser härifrån. Firebase-data har alltid företräde över BASE_DATA. |
Öppna data.html → logga in →
klicka en cell → skriv värdet → tryck Enter.
Ändringen syns direkt för alla.
|
✅ Ja |
🔶 Vad händer när en ny kategori läggs till i BASE_DATA?
När en ny rad läggs till i koden (t.ex. 'Engångsbadare – Wondr')
syns värden direkt i tabellen – men de kommer från BASE_DATA, inte Firebase.
Indikatorn i sidhuvudet visar då
● orange: Lokal fallbackdata
tills data aktivt sparas till Firebase.
✅ Hur sparar man data till Firebase?
Metod 1 – Manuell cell-klick (alltid tillgänglig):
- Öppna
data.htmloch logga in - Klicka på en cell i den nya kategorins rad
- Skriv in värdet i rutan som dyker upp
- Tryck Enter – värdet sparas direkt i Firebase
- Upprepa för varje månad
Metod 2 – Synkroniseringsknapp (tillagd 2026-06-03):
När man är inloggad i data.html visas en grön knapp
📥 Synka till Firebase i sidhuvudet.
Den läser igenom hela BASE_DATA, jämför med vad Firebase redan har,
och skickar enbart de värden som saknas.
Befintliga Firebase-värden skrivs aldrig över.
Perfekt för att initiera en ny kategori med ett klick.
Att värden visas i tabellen på
data.html betyder
inte att de är sparade i Firebase. De kan komma från BASE_DATA.
Kontrollera alltid indikatorn i sidhuvudet:
grön prick = Firebase, orange prick = lokal fallback.
📊 Konkret exempel – Engångsbadare Wondr, 3 juni 2026
Kategorin lades till i BASE_DATA med värden jan=17, feb=13, mar=38,
apr=31, maj=173. Trots att tabellen visade dessa siffror var de
inte i Firebase. Indikatorn visade orange.
Problemet löstes när ett värde (1 173 som testvalue) skrevs in manuellt
via cell-klick i data.html – då bytte indikatorn till
grön och engangsintraden.html uppdaterades direkt.
Dokumenterat: 2026-06-03
Strax efter att kategori-synken fungerade (se lärdomen ovan) uppstod ett
nytt problem: Jan–apr försvann ur tabellen för Engångsbadare – Wondr
direkt efter att maj sparats i Firebase. Det såg ut som att siffror gick
förlorade, men egentligen var det en bugg i hur loadData()
blandade ihop Firebase och BASE_DATA.
loadData() ersatte hela månadsarryen för en kategori med
Firebase-arrayen. Men Firebase-arrayen innehöll bara maj (ett verkligt värde)
och null för jan–apr. Dessa null skrev över BASE_DATA:s jan–apr-värden.
Hur det såg ut före fixen
// GAMMAL kod – ersätter hela arrayen med Firebase
for (const [kategori, månader] of Object.entries(kategorier)) {
data[year][kategori] = månader; // null-värden från Firebase skriver över BASE_DATA
}
Hur det fungerar efter fixen (2026-06-03)
// NY kod – merge på månads-nivå
for (const [kategori, månader] of Object.entries(kategorier)) {
if (!data[year][kategori]) {
// Kategorin saknas i BASE_DATA – använd Firebase-arrayen direkt
data[year][kategori] = månader;
} else {
// Kategorin finns i BASE_DATA – slå ihop månad för månad
for (let m = 0; m < 12; m++) {
if (månader[m] !== null) {
data[year][kategori][m] = månader[m]; // Firebase vinner
}
// månader[m] === null: behåll BASE_DATA (gör ingenting)
}
}
}
Konkret exempel – januari till maj
| Källa | Jan | Feb | Mar | Apr | Maj |
|---|---|---|---|---|---|
| BASE_DATA | 17 | 13 | 38 | 31 | 173 |
| Firebase (bara maj sparad) | null | null | null | null | 1173 |
| Resultat efter fix | 17 | 13 | 38 | 31 | 1173 |
Firebase-värdet 1173 används för maj. BASE_DATA 173 används ej för maj. Jan–apr hämtas från BASE_DATA eftersom Firebase har null för dem.
Dokumenterat och fixat: 2026-06-03