| Mode | Name | Last commit | Updated | Size |
|---|---|---|---|---|
| FORTIS-app.html | Initial commit — FORTIS träningsapp HTML-prototyp (Fas 1 + Fas 2) | 4 months ago | 109.59 KB | |
| FORTIS_HANDOFF.md | Add RN app: nutrition, measurements, weight graph, profile editing, cus… | 4 months ago | 7.58 KB | |
| README.md | Add RN app: nutrition, measurements, weight graph, profile editing, cus… | 4 months ago | 13.7 KB | |
| Träningsapp_Planering.md | Add RN app: nutrition, measurements, weight graph, profile editing, cus… | 4 months ago | 13.37 KB | |
| fortis | Add RN app: nutrition, measurements, weight graph, profile editing, cus… | 4 months ago |
FORTIS — Tränings- och hälsoapp
Personlig träningsapp byggd i React Native + Expo. Spårning av träning, kost, vikt och progress med 5 teman och offline-stöd.
Innehåll
- Kom igång
- Funktioner
- Skärmar
- Övningsbibliotek
- Kostdatabas
- Tema-system
- Achievements
- Datalagring
- Datamodeller
- Arkitektur
- Roadmap
- Tech stack
Kom igång
cd fortis
npx expo start
- iOS Simulator: tryck
ii terminalen - Android Emulator: tryck
ai terminalen - Fysisk enhet: skanna QR-koden med Expo Go
All data sparas lokalt med AsyncStorage — ingen server krävs.
Funktioner
Implementerat i React Native-appen
| Funktion | Status | Detaljer |
|---|---|---|
| Splash screen | ✅ | Animerad SVG-ring + progress-bar, 2.8 sek → fade |
| Onboarding | ✅ | 5-stegs wizard, Mifflin-St Jeor TDEE, takt-val, kan hoppas över |
| Route guard | ✅ | Redirect till onboarding om ingen profil, tillbaka vid profil |
| Dashboard | ✅ | SVG-kaloriering, makrobars, vattendroppar, dagens pass, streak |
| Träningsschema | ✅ | Veckostrip mån–sön, pass per dag, starta pass |
| Aktiv träning | ✅ | Sets/reps/vikt, vilotimer per övning, passtimer, spara till logg |
| Övningsbibliotek | ✅ | 75 övningar, utrustningschips, filtermodal (muskelgrupp + svårighet), sök |
| Egna övningar | ✅ | Skapa/ta bort egna övningar, EGET-badge, persist i fortis_custom_exercises |
| Kostlogg | ✅ | 30 livsmedel, sök per måltid, gram-input, live makrobars |
| Egna livsmedel | ✅ | Skapa/ta bort egna livsmedel, EGET-badge, persist i fortis_custom_foods |
| Mätningar | ✅ | Logga vikt, midja, fettprocent — persist i fortis_measurements |
| Viktgraf | ✅ | SVG-linjegraf senaste 7 mätningarna med y-axel + datumrubriker |
| Profil-redigering | ✅ | Redigera vikt, mål, takt, aktivitetsnivå — live makropreview |
| Achievements | ✅ | 10 achievements, grid i profil med låsta/upplåsta |
| Tema-system | ✅ | 5 teman, väljs i Profil, persist i fortis_theme |
| 5 teman | ✅ | Fortis, Dark, Midnight, Forest, Stone |
Ej implementerat ännu
| Funktion | Fas | Blockerat av |
|---|---|---|
| Barcodeläsare | 4 | Expo Camera |
| Open Food Facts API | 4 | Native network + barcode |
| Push-notifikationer | 4 | Expo Notifications |
| Progressionsgraf per övning | — | Träningslogg saknar aggregering per övning i RN |
| Export av data (JSON) | — | Inte prioriterat ännu |
Skärmar
🏠 Hem (Dashboard)
Daglig översikt på ett ögonkast:
- Kaloriering — SVG-cirkel med kcal loggat / mål
- Makrobars — Protein / Kolhydrater / Fett med procentfyllning
- Vattenspårning — visuella droppar, +250 ml snabbknapp, dagsmål 2 500 ml
- Dagens pass — namn + antal övningar, länk till aktiv träning
- Streak-pill — antal dagar i rad med loggat pass
📅 Schema
- Veckostrip måndag–söndag, aktiv dag markerad
- Pass per dag med övningar listade
- Starta pass direkt → aktiv träningsvy
Aktiv träning
- Varje övning med sets × reps × vikt, editerbara live
- ✓-knapp per set → startar vilotimer (tid från övningens
restSec) - Passtimer (MM:SS) i headern
- Avsluta → sparar till träningslogg
📚 Övningsbibliotek
Filtreringssystem — hybrid-UX:
- Nivå 1: Horisontellt scrollbara utrustningschips (alltid synliga)
- Nivå 2: Filtermodal — muskelgrupp + svårighet, badge visar antal aktiva
- Fritextsök i realtid
Detaljvy: steg-för-steg instruktioner, sekundära muskler
Egna övningar: "+ Ny övning"-FAB, EGET-badge, 🗑 ta bort i detaljvy
🍎 Kost
- Summarykortet — kcal loggat / mål, live makroboxar
- Måltidssektioner: Frukost / Lunch / Middag / Mellanmål
- "+ Lägg till" per måltid → sök-modal med alla livsmedel
- Egna livsmedel — "Skapa eget livsmedel" i sök-modalen, formulär för namn + makron per 100g
- EGET-badge + 🗑-knapp på egna i listan
- ✕ på loggad post tar bort direkt
👤 Profil
- Statistik — pass totalt · streak · kcal/dag
- Progress — "Logga"-knapp öppnar mätningsmodal (vikt, midja, fettprocent)
- SVG-linjegraf över senaste 7 viktmätningarna
- Lista på 4 senaste mätningarna
- Profil-data — "Redigera"-knapp: vikt, målvikt, mål, takt, aktivitetsnivå + live makropreview
- Tema-väljare — 5 färgswatches
- Achievements — 10 achievements, låsta i 40% opacity
- Återställ all data
Övningsbibliotek
75 övningar från wger.de + egna.
Fördelning per muskelgrupp
| Muskelgrupp | Antal |
|---|---|
| Ben | 18 |
| Rygg | 11 |
| Core | 11 |
| Bröst | 10 |
| Armar | 9 |
| Axlar | 8 |
| Kondition | 7 |
| Helkropp | 1 |
Övningsstruktur
{
id: 'exercise_id',
name: 'Exercise Name',
muscle: 'Ben', // primär muskelgrupp
secondary: 'Rumpa, Core', // sekundära (sträng)
equip: 'Kroppsvikt', // måste matcha EQUIP_CHIPS
icon: '🦵',
diff: 'Nybörjare', // Nybörjare | Medel | Avancerad
type: 'Styrka', // Styrka | Kondition | Rörlighet
isTimer: false, // true = tidsbaserad (plank, löpband etc.)
instructions: ['Steg 1', 'Steg 2', ...]
}
wger.de API för fler övningar:
GET https://wger.de/api/v2/exerciseinfo/{id}/?format=json
Kostdatabas
30 vanliga livsmedel, alla med makrovärden per 100g. Egna livsmedel läggs till direkt i appen.
| Kategori | Livsmedel |
|---|---|
| Kött & fisk | Kycklingfilé, Nötfärs, Lax, Tonfisk, Ägg, Räkor |
| Mejeri | Mjölk, Grekisk yoghurt, Keso, Ost, Kvarg |
| Spannmål | Havregryn, Ris, Pasta, Vitt bröd, Rågbröd, Tortilla |
| Grönsaker | Broccoli, Spenat, Potatis, Sötpotatis |
| Frukt | Banan, Äpple, Blåbär |
| Nötter & övrigt | Mandlar, Jordnötssmör, Olivolja, Avokado, Proteinpulver, Kidneybönor |
Eget livsmedel-schema:
{ id: 'cf123', name: 'Hemmagjord granola', cal: 420, prot: 9, carbs: 58, fat: 16, isCustom: true }
Tema-system
5 inbyggda teman, väljs i Profil-fliken.
| Tema | Bakgrund | Accent | Karaktär |
|---|---|---|---|
| Fortis | Varm off-white #F2F1ED | Orange #E85D26 | Standard, varm |
| Dark | Kol #121212 | Orange #E85D26 | Mörkt läge |
| Midnight | Navy #0D1117 | Blå #5B8BFF | GitHub-mörkt |
| Forest | Naturgrön #F0F4F0 | Grön #2D9E5F | Lugnt, naturligt |
| Stone | Cool grå #F5F5F4 | Indigo #6366F1 | Modernt, minimalt |
Tema-systemet är frikopplat:
src/constants/theme.ts ← THEMES-objekt + Theme-interface
src/store/useThemeStore.ts ← Zustand: themeId, setTheme(), persist
src/hooks/useTheme.ts ← hook: returnerar aktiva temavärden
Inga färgvärden hårdkodas i komponenter. Nya teman läggs enbart till i theme.ts.
Achievements
10 achievements som låses upp baserat på träningshistorik.
| Achievement | Ikon | Villkor |
|---|---|---|
| Första steget | 🏆 | Slutför 1 pass |
| På rulle | 🔥 | 3 dagars streak |
| Veckovinnare | 🔥🔥 | 7 dagars streak |
| Hängiven | 💪 | 5 pass totalt |
| Maskin | ⚡ | 10 pass totalt |
| Elit | 👑 | 20 pass totalt |
| Morgonfågel | 🌅 | Tränat innan kl 08:00 |
| Maraton | 🏅 | 60+ min i ett pass |
| Helkropp | 🎯 | Tränat 5+ muskelgrupper |
| Personbästa | 📈 | Sätt ett personligt rekord |
Datalagring
Storage-nycklar
| Nyckel | Typ | Innehåll |
|---|---|---|
fortis_profile | Profile | Profildata inkl. makromål |
fortis_workouts | WorkoutSchedule[] | Schemalagda pass |
fortis_workoutlog | WorkoutLogEntry[] | Genomförda pass |
fortis_foodlog | FoodLogEntry[] | Loggad mat per dag |
fortis_water_YYYY-MM-DD | number | Vattenintag i ml |
fortis_measurements | MeasurementEntry[] | Vikt, midja, fettprocent |
fortis_custom_foods | FoodItem[] | Egna livsmedel |
fortis_custom_exercises | Exercise[] | Egna övningar |
fortis_theme | string | Aktivt tema-ID |
Datamodeller
interface Profile {
id: string
name: string
gender: 'male' | 'female' | 'other'
age: number
heightCm: number
weightKg: number
goalWeightKg: number
goal: 'lose' | 'maintain' | 'gain'
pace: 'slow' | 'moderate' | 'fast'
activityLevel: 'sedentary' | 'light' | 'moderate' | 'very_active'
macroGoals: MacroGoals
createdAt: string
updatedAt: string
}
interface MacroGoals {
calories: number
proteinG: number
carbsG: number
fatG: number
}
interface Exercise {
id: string
name: string
muscle: string
secondary?: string
equip: string
icon: string
diff: 'Nybörjare' | 'Medel' | 'Avancerad'
type: 'Styrka' | 'Kondition' | 'Rörlighet'
isTimer?: boolean
instructions: string[]
wgerId?: number
isCustom?: boolean
}
interface WorkoutSchedule {
id: string
name: string
day: number // 0=mån … 6=sön
exercises: ScheduledExercise[]
}
interface ScheduledExercise {
exerciseId: string
sets: number
reps?: number
durationSec?: number
weight?: number
restSec: number
}
interface WorkoutLogEntry {
id: string
workoutId: string
date: string
startedAt: string
endedAt?: string
durationMin: number
exercises: LoggedSet[][]
completedManually: boolean
}
interface LoggedSet {
reps?: number
weight?: number
durationSec?: number
done: boolean
}
interface FoodItem {
id: string
name: string
cal: number
prot: number
carbs: number
fat: number
isCustom?: boolean
}
interface FoodLogEntry {
id: string
date: string
meal: 'breakfast' | 'lunch' | 'dinner' | 'snack'
foodId: string
foodName: string
amountG: number
cal: number
prot: number
carbs: number
fat: number
}
interface MeasurementEntry {
id: string
date: string
weightKg?: number
waistCm?: number
bodyFatPct?: number
notes?: string
}
interface WaterLogEntry {
id: string
date: string
totalMl: number
}
Arkitektur
fortis/
├── app/
│ ├── _layout.tsx # Root layout, store-laddning, route guard
│ ├── (tabs)/
│ │ ├── _layout.tsx # Tab bar med 5 flikar (Lucide-ikoner)
│ │ ├── index.tsx # Dashboard
│ │ ├── schedule.tsx # Träningsschema
│ │ ├── library.tsx # Övningsbibliotek
│ │ ├── nutrition.tsx # Kostlogg
│ │ └── profile.tsx # Profil & progress
│ ├── onboarding/
│ │ └── index.tsx # Splash-animation + 5-stegs wizard
│ └── workout/
│ └── [id].tsx # Aktiv träningsvy (fullscreen modal)
│
└── src/
├── constants/
│ ├── types.ts # Alla TypeScript-gränssnitt
│ ├── exercises.ts # 75 övningar
│ ├── foods.ts # 30 livsmedel
│ └── theme.ts # 5 teman + Theme-interface
├── store/
│ ├── useProfileStore.ts # Zustand: profile, macroGoals, hasLoaded
│ ├── useWorkoutStore.ts # Zustand: workouts, workoutLog, calcStreak()
│ ├── useNutritionStore.ts # Zustand: foodLog, waterToday, customFoods
│ ├── useMeasurementsStore.ts # Zustand: measurements
│ └── useThemeStore.ts # Zustand: themeId, persist
├── hooks/
│ └── useTheme.ts # Returnerar aktiva temavärden
└── lib/
├── storage.ts # AsyncStorage wrapper + STORAGE_KEYS
└── macroCalc.ts # calcTDEE(), calcMacros(), PACE_LABELS
Roadmap
| Fas | Innehåll | Status |
|---|---|---|
| Fas 1 | Splash, Onboarding, Dashboard, Schema, Aktiv träning, Bibliotek | ✅ Klar |
| Fas 2 | Progressionsgraf, Achievements/streaks, Utbyggt bibliotek (75 övningar) | ✅ Klar |
| Fas 3 | Kostlogg, Makrospårning, Matdatabas, Vattenlogg, Egna livsmedel | ✅ Klar |
| Fas 4 | Profil-redigering, Viktgraf, Mätningar, Egna livsmedel | ✅ Klar |
| Fas 5 | React Native + Expo migration, AsyncStorage, offline-stöd | ✅ Klar |
| Fas 6 | Barcodeläsare, Open Food Facts API, Push-notifikationer | 🔜 |
Närmast kvar
- [ ] Barcodeläsare (Expo Camera) — ersätter sökning med skanning
- [ ] Open Food Facts API-integration
- [ ] Push-notifikationer (pass-påminnelse, vattenintag, invägningsdag)
- [ ] Progressionsgraf per övning i RN
- [ ] Export av all data till JSON
Tech stack
| Komponent | Val |
|---|---|
| Framework | React Native + Expo SDK 54 |
| Routing | Expo Router v6 (file-based) |
| State | Zustand |
| Persistens | @react-native-async-storage/async-storage |
| Charts | react-native-svg (hand-byggda SVG-grafer) |
| Animationer | React Native Animated API |
| Icons | lucide-react-native |
| Barcode | — (ej implementerat, kräver Expo Camera) |
| Notiser | — (ej implementerat, kräver Expo Notifications) |
Kaloriformel
TDEE beräknas med Mifflin-St Jeor:
Män: BMR = 10×vikt + 6.25×längd − 5×ålder + 5
Kvinnor: BMR = 10×vikt + 6.25×längd − 5×ålder − 161
TDEE = BMR × aktivitetsmultiplikator
sedentary: × 1.2
light: × 1.375
moderate: × 1.55
very_active: × 1.725
Takt-justering:
lose:
slow: TDEE − 250 kcal (~0,25 kg/vecka)
moderate: TDEE − 500 kcal (~0,5 kg/vecka)
fast: TDEE − 750 kcal (~0,75 kg/vecka)
gain:
slow: TDEE + 200 kcal (lean bulk, ~0,2 kg/vecka)
moderate: TDEE + 350 kcal (~0,35 kg/vecka)
fast: TDEE + 500 kcal (~0,5 kg/vecka)
maintain: TDEE (ingen justering)
Minimum: 1 200 kcal/dag
Senast uppdaterad: 2026-05-01