Lasten viikkorahaseuranta Google Sheetsillä — React 19 PWA, asennettava mobiililaitteille.
Esiasennettu sovellus käytettävissä: https://gitpages.morgeweb.com/viikkoraha
- Google-kirjautuminen — OAuth 2.0, jokainen perheenjäsen omalla tunnuksella
- Askareiden hallinta — selaa, valitse ja kirjaa kotityöt yhdellä napautuksella
- Dashboard — avoimet summat, tehtyjen töiden historia, maksukuittaus
- Automaattinen Google Sheets -synkronointi — tiedot suoraan perheen omaan taulukkoon
- Uuden sheetin luonti — "Luo uusi" -nappi generoi valmiin Viikkoraha-taulukon
- PWA — asennettavissa iOS/Android-kotivalikkoon, splash screen, faviconit
- Tumma teema — Tailwind CSS 4, responsiivinen (puhelin → tabletti)
- Täysin staattinen — ei backend-palvelinta, hostattavissa GitHub Pages/Netlify/VPS
| Kerros | Teknologia |
|---|---|
| UI-framework | React 19 |
| Build | Vite 8 |
| Tilanhallinta | Zustand 5 |
| Tyylit | Tailwind CSS 4 |
| Reititys | React Router 7 |
| Autentikointi | Google Identity Services (GIS) / OAuth 2.0 implicit flow |
| Tietovarasto | Google Sheets API v4 |
| Testaus | Vitest + Testing Library |
| PWA | Service Worker, Web Manifest, iOS splash screenit |
Sovellus on full client-side — kaikki API-kutsut menevät suoraan selaimesta Google Cloudiin. Ei Node-backendiä, ei tietokantaa.
- Node.js 18+
- Google Cloud Console -projekti (katso ohjeet alla)
- Google Sheets -taulukko (voi luoda sovelluksessa)
Sovellus tarvitsee Google Cloud -projektin, jossa on aktivoitu kaksi API:a, OAuth 2.0 -asiakastunnus ja API-avain.
- Mene osoitteeseen console.cloud.google.com
- Luo uusi projekti (tai valitse olemassa oleva)
- Anna projektille nimi, esim. "Viikkoraha"
Molemmat API:t on aktivoitava erikseen — Sheets API:n aktivointi ei automaattisesti aktivoi Drive API:a.
| API | Linkki aktivointiin | Käyttötarkoitus |
|---|---|---|
| Google Sheets API | Aktivoi Sheets API | Askareiden luku/kirjoitus, yhteenvedot |
| Google Drive API | Aktivoi Drive API | Käyttäjän omien taulukoiden listaus alasvetovalikkoon |
⚠️ Ilman Drive API:n aktivointia taulukkovalikko ei toimi — näkyviin tulee virhe "Drive API has not been used in project".
- Siirry: APIs & Services → Credentials
- Klikkaa Create Credentials → OAuth client ID
- Valitse Web application
- Täytä:
- Name: Viikkoraha
- Authorised JavaScript origins:
https://petekaik.github.io(oma GitHub Pages -domain) - Klikkaa Create
- Kopioi Client ID talteen (muotoa
XXXXXXXXXXXX-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com)
- APIs & Services → Credentials
- Klikkaa Create Credentials → API key
- Kopioi avain talteen (muotoa
AIzaSy...)
🔒 Suositus: Rajoita API-avain Credentials → API Key → Edit -kohdassa:
- Application restrictions:
HTTP referrers→ lisää*.github.io/*- API restrictions:
Google Sheets APIjaGoogle Drive API
- Avaa Viikkoraha
- ⚙️ → Asetukset
- Syötä Client ID ja API-avain
- Tallenna → Kirjaudu Google-tililläsi
- Valitse taulukko tai luo uusi
💡 Vinkki: Voit esitäyttää Client ID:n ja API-avaimen luomalla
.env-tiedoston:cp .env.example .envja täyttämällä
VITE_GOOGLE_CLIENT_IDjaVITE_GOOGLE_API_KEY. Tällöin sovellus on heti käyttövalmis ilman asetusten syöttämistä. Spreadsheet ID täytetään sovelluksessa.
npm install
cp .env.example .env # valinnainen — VITE_GOOGLE_CLIENT_ID:n voi syöttää sovelluksessa
npm run dev # http://localhost:5173npm test # Vitest (kertasuoritus)
npm run test:watch # Watch-moodiE2E-testit oikealla iPhonella: Katso docs/TESTING.md
npm run build # → dist/
npm run preview # Esikatselu paikallisesti- Avaa sovellus selaimessa
- ⚙️-kuvake → Asetukset
- Syötä Google Client ID (
.apps.googleusercontent.com) - Syötä API-avain (
AIzaSy...) - Syötä Spreadsheet ID — tai klikkaa "Luo uusi" generoidaksesi valmiin taulukon
- Tallenna
- Kirjaudu Google-tililläsi
- Aloita askareiden kirjaus
Sovellus käyttää kolmea välilehteä automaattisesti:
| Välilehti | Sarakkeet | Sisältö |
|---|---|---|
| Chores | A–D | ID, Kuvaus, Arvo (€), Näyttönimi |
| Bookings | A–H | Aikaleima, ChoreID, Kuvaus, Arvo, Viikkonro, Käyttäjä, Status |
| Sums | A–B | Kaavat avoimille ja maksetuille summille |
viikkoraha/
├── index.html # Vite entry point
├── vite.config.js # Vite + Vitest -konfiguraatio
├── package.json # Riippuvuudet ja skriptit
├── .env.example # Pohja ympäristömuuttujille
├── .gitignore
├── docs/ # Dokumentaatio
│ ├── BACKLOG.md # Kehitysjonossa olevat tehtävät
│ ├── CHANGELOG.md # Julkaisut ja muutosloki
│ ├── KNOWN_BUGS.md # Tunnetut bugit ja workaroundit
│ └── TESTING.md # Testausohjeet (yksikkö- ja E2E)
├── tests/ # E2E-testit
│ └── e2e/
│ ├── full_e2e.py # iOS Safari WebDriver -skripti
│ ├── .env.e2e # Paikalliset secretit (gitignored)
│ └── .env.e2e.example
├── public/ # Staattiset assetit
│ ├── sw.js # Service Worker (PWA)
│ ├── site.webmanifest # PWA-manifesti
│ ├── splash/ # iOS-splash screenit (eri resoluutiot)
│ └── favicon.* # Faviconit ja PWA-ikonit
└── src/
├── main.jsx # React entry + reititys
├── index.css # Tailwind + globaalit tyylit
├── test-setup.js # Vitest + Testing Library -konfiguraatio
├── components/ # UI-komponentit
│ ├── AppShell.jsx # Header, navigaatio, asetuspaneeli
│ ├── ChoreList.jsx # Askarelista
│ ├── ChoreButton.jsx # Yksittäinen askarepainike
│ ├── ConfirmDialog.jsx
│ ├── NotificationBar.jsx
│ ├── LoginPrompt.jsx
│ ├── SettingsPanel.jsx
│ ├── SpreadsheetPicker.jsx
│ ├── DashboardSummary.jsx
│ ├── HistoryList.jsx
│ ├── HistoryItem.jsx
│ └── WeeklyChart.jsx # Viikkograafi
├── views/ # Sivunäkymät
│ ├── HomeView.jsx # Päänäkymä
│ ├── DashboardView.jsx
│ ├── ChoreManagerView.jsx # Askareiden hallinta (parent)
│ ├── UsersManagerView.jsx # Perheenjäsenten hallinta (parent)
│ └── SettingsView.jsx
├── stores/ # Zustand-tilat
│ ├── authStore.js # Autentikointitila (token + user + rooli)
│ ├── choresStore.js # Askareiden tila
│ └── settingsStore.js # Asetustila (Client ID, API key yms.)
├── hooks/ # Mukautetut hookit
│ ├── useGoogleAuth.js
│ ├── useGoogleSheets.js
│ └── useUsers.js # Käyttäjähallinta (Users-sheet)
├── utils/
│ ├── sheets-schema.js # Sheets-välilehtimäärittelyt ja oletusdata
│ ├── validation.js
│ ├── displayName.js # Google-profiilin nimen käsittely
│ ├── parseNumber.js # Suomi-lokaalin numerojäsennys
│ ├── settingsSync.js # Settings-sheetin synkronointi
│ └── AppContext.js
└── __tests__/ # Yksikkö- ja komponenttitestit
- Ei offline-tukea — vaatii nettiyhteyden Google Sheets API:a varten
- Ei monen käyttäjän reaaliaikaista synkronointia (Sheets API:n luonne)
- Vaatii Google-tilin kirjautumiseen
MIT — vapaasti jaettavissa ja muokattavissa.
Tekijä: Petteri Kaikkonen