diff --git a/TODO.md b/TODO.md index 31211b8..cd31feb 100644 --- a/TODO.md +++ b/TODO.md @@ -1,5 +1,52 @@ # Gravl - Feature Roadmap +## đš Design Overhaul - Fitness App Feel + +**MĂ„l:** En professionell, atletisk kĂ€nsla - inte en hobby-app med emojis. + +### FĂ€rgpalett +- [ ] PrimĂ€r: Mörk bakgrund (#0a0a0f eller liknande) +- [ ] Accent: Energisk orange/röd (#ff6b35) eller electric blue (#00d4ff) +- [ ] Text: Ljus pĂ„ mörk (#ffffff, #a1a1aa för sekundĂ€r) +- [ ] Gradienter: Subtila, inte rainbow + +### Typografi +- [ ] Rubrik: Bold, kondenserad sans-serif (Inter, Oswald, eller liknande) +- [ ] Body: Clean sans-serif +- [ ] Siffror/stats: Monospace eller tabular för alignment + +### Ikoner & Grafik +- [ ] **Bort med ALLA emojis** - ersĂ€tt med: + - SVG-ikoner (Lucide, Heroicons, eller custom) + - Stiliserade fitness-silhuetter för workout-typer + - Abstrakta former/linjer istĂ€llet för cartoonish grafik +- [ ] Coach-avatar: Stiliserad silhuett eller initialer, inte emoji +- [ ] Workout-ikoner: Dumbbell, barbell, kettlebell som rena linjeikoner + +### UI-komponenter +- [ ] Kort: Subtila skuggor, mjuka kanter, inte "bubbliga" +- [ ] Knappar: Solid eller outlined, inte gradient-rainbow +- [ ] Progress bars: Tunna, eleganta +- [ ] Kalender: Minimalistisk, fĂ€rgkodade dots/bars + +### Bilder +- [ ] Hero-bilder: Högkvalitativa trĂ€ningsbilder (Unsplash fitness) +- [ ] Bakgrunder: Mörka texturer eller subtila patterns +- [ ] Inga clip-art eller cartoon-style + +### Animation +- [ ] Subtila micro-interactions +- [ ] Smooth transitions (300ms ease) +- [ ] Loading states: Skeleton screens, inte spinners med emojis + +### Inspirations-appar +- Nike Training Club +- FITBOD +- Strong +- Hevy + +--- + ## đ Onboarding & Signup - [ ] Registrering/inloggning (email + lösenord) - [ ] Onboarding-wizard med steg-för-steg guide diff --git a/frontend/src/components/Icons.jsx b/frontend/src/components/Icons.jsx new file mode 100644 index 0000000..bfcbb40 --- /dev/null +++ b/frontend/src/components/Icons.jsx @@ -0,0 +1,276 @@ +// Clean SVG icons for the Gravl app +// Replaces emojis with professional vector icons + +export const Icons = { + // Navigation & UI + home: ( + + ), + chart: ( + + ), + user: ( + + ), + logout: ( + + ), + arrowLeft: ( + + ), + arrowRight: ( + + ), + chevronLeft: ( + + ), + chevronRight: ( + + ), + chevronDown: ( + + ), + plus: ( + + ), + check: ( + + ), + + // Workout types + dumbbell: ( + + ), + arm: ( + + ), + leg: ( + + ), + back: ( + + ), + chest: ( + + ), + shoulder: ( + + ), + core: ( + + ), + fullBody: ( + + ), + + // Activity & rest + walking: ( + + ), + yoga: ( + + ), + swimming: ( + + ), + cycling: ( + + ), + sleep: ( + + ), + + // Stats & metrics + fire: ( + + ), + calendar: ( + + ), + target: ( + + ), + trophy: ( + + ), + + // Coach avatar (silhouette) + coach: ( + + ), + + // Brand + gravl: ( + + ), +} + +// Icon component wrapper +export function Icon({ name, size = 24, className = '', style = {} }) { + const icon = Icons[name] + if (!icon) return null + + return ( + + {icon} + + ) +} + +// Helper to get workout icon name based on workout name +export function getWorkoutIconName(name) { + const lower = name.toLowerCase() + if (lower.includes('push') || lower.includes('bröst') || lower.includes('chest')) return 'chest' + if (lower.includes('pull') || lower.includes('rygg') || lower.includes('back')) return 'back' + if (lower.includes('ben') || lower.includes('leg') || lower.includes('lower')) return 'leg' + if (lower.includes('axlar') || lower.includes('shoulder')) return 'shoulder' + if (lower.includes('arm')) return 'arm' + if (lower.includes('core') || lower.includes('mage')) return 'core' + if (lower.includes('helkropp') || lower.includes('full')) return 'fullBody' + if (lower.includes('överkropp') || lower.includes('upper')) return 'chest' + if (lower.includes('underkropp')) return 'leg' + return 'dumbbell' +} + +// Helper to get activity icon name +export function getActivityIconName(activity) { + const lower = activity.toLowerCase() + if (lower.includes('promenad') || lower.includes('walk')) return 'walking' + if (lower.includes('yoga') || lower.includes('stretch')) return 'yoga' + if (lower.includes('sim') || lower.includes('swim')) return 'swimming' + if (lower.includes('cyk') || lower.includes('bike')) return 'cycling' + return 'walking' +} + +export default Icon diff --git a/frontend/src/pages/Dashboard.jsx b/frontend/src/pages/Dashboard.jsx index ea40a13..ee18d3e 100644 --- a/frontend/src/pages/Dashboard.jsx +++ b/frontend/src/pages/Dashboard.jsx @@ -1,5 +1,6 @@ import { useState, useEffect } from 'react' import { useAuth } from '../context/AuthContext' +import { Icon, getActivityIconName } from '../components/Icons' const API_URL = '/api' @@ -7,13 +8,13 @@ const API_URL = '/api' const getCoachGreeting = (user, todayWorkout) => { const hour = new Date().getHours() const name = user?.name?.split(' ')[0] || 'du' - + if (todayWorkout) { // There's a workout today if (hour < 10) { - return `Godmorgon ${name}! Idag kör vi ${todayWorkout.name.toLowerCase()}. Redo? đȘ` + return `Godmorgon ${name}! Idag kör vi ${todayWorkout.name.toLowerCase()}. Redo?` } else if (hour < 14) { - return `${todayWorkout.name} stĂ„r pĂ„ schemat idag. Dags att köra! đïž` + return `${todayWorkout.name} stĂ„r pĂ„ schemat idag. Dags att köra!` } else if (hour < 18) { return `Eftermiddagspass? ${todayWorkout.name} vĂ€ntar pĂ„ dig.` } else { @@ -22,23 +23,23 @@ const getCoachGreeting = (user, todayWorkout) => { } else { // Rest day if (hour < 10) { - return `Godmorgon ${name}! Vilodag idag â perfekt för Ă„terhĂ€mtning. đ§` + return `Godmorgon ${name}! Vilodag idag â perfekt för Ă„terhĂ€mtning.` } else if (hour < 14) { - return `Ingen trĂ€ning schemalagd. Ta en promenad eller stretcha lite? đ¶` + return `Ingen trĂ€ning schemalagd. Ta en promenad eller stretcha lite?` } else if (hour < 18) { - return `Vila Ă€r ocksĂ„ trĂ€ning! LĂ€tt rörelse eller mobilitet idag? đ§` + return `Vila Ă€r ocksĂ„ trĂ€ning! LĂ€tt rörelse eller mobilitet idag?` } else { - return `Lugn kvĂ€ll ${name}. Ladda batterierna till nĂ€sta pass! đŽ` + return `Lugn kvĂ€ll ${name}. Ladda batterierna till nĂ€sta pass!` } } } // Rest day tips const restDayTips = [ - { icon: 'đ¶', text: '30 min promenad' }, - { icon: 'đ§', text: 'Yoga/stretching' }, - { icon: 'đ', text: 'Simning' }, - { icon: 'đŽ', text: 'LĂ€tt cykling' }, + { iconName: 'walking', text: 'Promenad' }, + { iconName: 'yoga', text: 'Stretching' }, + { iconName: 'swimming', text: 'Simning' }, + { iconName: 'cycling', text: 'Cykling' }, ] // Get weekday names @@ -89,12 +90,12 @@ function Dashboard({ onStartWorkout, onNavigate }) {
{getCoachGreeting(user, todayWorkout)}