import React, { useMemo, useState } from "react";
import {
ChevronRight,
CalendarDays,
Dumbbell,
Flame,
Home,
LineChart,
PlayCircle,
Search,
Sparkles,
Target,
Trophy,
Plus,
Clock3,
Activity,
BookOpen,
Save,
} from "lucide-react";
import {
ResponsiveContainer,
LineChart as ReLineChart,
Line,
XAxis,
YAxis,
Tooltip,
CartesianGrid,
} from "recharts";
const weeklyPlan = [
{ day: "Maandag", type: "football", title: "Voetbal", accent: "emerald" },
{ day: "Dinsdag", type: "push", title: "Gym • Push", accent: "rose" },
{ day: "Woensdag", type: "football", title: "Voetbal", accent: "emerald" },
{ day: "Donderdag", type: "legs", title: "Gym • Benen", accent: "amber" },
{ day: "Vrijdag", type: "pull", title: "Gym • Pull", accent: "sky" },
{ day: "Zaterdag", type: "football", title: "Wedstrijd", accent: "violet" },
{ day: "Zondag", type: "optional", title: "Optioneel herstel / lichte gym", accent: "slate" },
];
const workoutLibrary = {
football: {
title: "Full Body Light",
subtitle: "Licht, atletisch en slim rondom voetbalbelasting.",
note: "Gebruik dit als een korte onderhouds-workout: technisch strak, weinig spierpijn, en niet tot falen.",
exercises: [
{
name: "Goblet Squat",
sets: "2-3 × 8-10",
reps: "8-10",
video: "https://www.youtube.com/results?search_query=goblet+squat+how+to",
explanation:
"Goede full-body start voor benen en core zonder zware vermoeidheid. Denk aan houding, diepe controle en rustige herhalingen.",
tips: ["Hou je borst trots", "Zak gecontroleerd", "Blijf uit de pijnzone"],
},
{
name: "Push-Up",
sets: "2-3 × 8-15",
reps: "8-15",
video: "https://www.youtube.com/results?search_query=push+up+how+to",
explanation:
"Simpele horizontale duw om borst en triceps bij te houden. Jeff-achtig principe: kwaliteit boven ego, volle range of motion.",
tips: ["Strakke plank positie", "Ellebogen licht schuin", "Rustig zakken"],
},
{
name: "Cable Row / Band Row",
sets: "2-3 × 10-12",
reps: "10-12",
video: "https://www.youtube.com/results?search_query=seated+cable+row+how+to",
explanation:
"Een lichte trekbeweging houdt je rug actief en helpt houding en schouderbalans, zonder je wedstrijdbewegingen te slopen.",
tips: ["Schouderbladen naar achter", "Niet gooien met je romp", "Voel de stretch"],
},
{
name: "Plank",
sets: "2-3 × 30-45 sec",
reps: "30-45 sec",
video: "https://www.youtube.com/results?search_query=plank+how+to",
explanation:
"Core-stabiliteit helpt bij sport, sprinten en contactmomenten. Houd dit kort en strak.",
tips: ["Ribben omlaag", "Bilspieren aanspannen", "Geen doorgezakte onderrug"],
},
],
},
push: {
title: "Push",
subtitle: "Borst, schouders en triceps met focus op progressieve overload.",
note: "Start met compounds, eindig met isolatie. Werk met gecontroleerde uitvoeringen en noteer je gewicht per set.",
exercises: [
{
name: "Barbell Bench Press",
sets: "3-4 × 5-8",
reps: "5-8",
video: "https://www.youtube.com/results?search_query=barbell+bench+press+how+to",
explanation:
"Jeff Nippard-stijl hoofdbeweging voor borstkracht en massa. Stabiele setup, volledige controle en alleen load verhogen als je techniek strak blijft.",
tips: ["Schouderbladen vast", "Bar naar borst met controle", "Explosief omhoog"],
},
{
name: "Incline Dumbbell Press",
sets: "3 × 8-10",
reps: "8-10",
video: "https://www.youtube.com/results?search_query=incline+dumbbell+press+how+to",
explanation:
"Pakt bovenborst en voorste schouderkop goed mee. Houd spanning constant en gebruik een incline die je goed voelt.",
tips: ["Elleboog onder controle", "Diepe stretch", "Geen zwaaien"],
},
{
name: "Seated Shoulder Press",
sets: "3 × 6-10",
reps: "6-10",
video: "https://www.youtube.com/results?search_query=seated+shoulder+press+how+to",
explanation:
"Sterke verticale press voor delts en triceps. Ga niet maximaal forceren; laat de reps technisch netjes blijven.",
tips: ["Core aangespannen", "Ribben laag", "Volledige maar veilige ROM"],
},
{
name: "Lateral Raises",
sets: "3 × 12-20",
reps: "12-20",
video: "https://www.youtube.com/results?search_query=lateral+raise+how+to",
explanation:
"Zijschouders reageren vaak goed op hogere reps en goede spanning. Hier wil je strakke herhalingen, geen ego.",
tips: ["Elleboog iets hoger", "Rustig omlaag", "Voel de zijkant van je schouder"],
},
{
name: "Cable Tricep Pushdown",
sets: "3 × 10-15",
reps: "10-15",
video: "https://www.youtube.com/results?search_query=cable+tricep+pushdown+how+to",
explanation:
"Goede isolatie voor extra tricepsvolume. Fixeer je ellebogen en knijp onderin even hard aan.",
tips: ["Ellebogen stil", "Volledig strekken", "Niet leunen"],
},
],
},
legs: {
title: "Benen",
subtitle: "Sterke benen voor voetbal en spiergroei, maar slim gedoseerd.",
note: "Leg day moet je beter maken, niet slopen. Gebruik kwaliteit, volledige controle en geen slordige reps.",
exercises: [
{
name: "Back Squat",
sets: "3-4 × 4-8",
reps: "4-8",
video: "https://www.youtube.com/results?search_query=back+squat+how+to",
explanation:
"De grote compound voor quads, glutes en core. Jeff-achtig principe: eerst techniek, dan pas gewicht.",
tips: ["Voeten stevig", "Controle in de diepte", "Romp strak"],
},
{
name: "Romanian Deadlift",
sets: "3 × 6-10",
reps: "6-10",
video: "https://www.youtube.com/results?search_query=romanian+deadlift+how+to",
explanation:
"Top voor hamstrings en glutes. Denk aan hip hinge en houd de bar dicht langs je lichaam.",
tips: ["Knieën licht gebogen", "Heupen naar achter", "Niet rond trekken met je onderrug"],
},
{
name: "Leg Press",
sets: "3 × 10-15",
reps: "10-15",
video: "https://www.youtube.com/results?search_query=leg+press+how+to",
explanation:
"Veel quad volume met minder techniekstress dan squat. Perfect als extra hypertrophy-prikkel.",
tips: ["Heupen op de bank", "Volledige controle", "Niet te kort bewegen"],
},
{
name: "Leg Curl",
sets: "3 × 10-15",
reps: "10-15",
video: "https://www.youtube.com/results?search_query=leg+curl+how+to",
explanation:
"Hamstring-isolatie helpt balans en blessurepreventie. Hou de reps strak en gecontroleerd.",
tips: ["Volledige stretch", "Bovenin knijpen", "Geen heupen gooien"],
},
{
name: "Standing Calf Raise",
sets: "3-4 × 12-20",
reps: "12-20",
video: "https://www.youtube.com/results?search_query=standing+calf+raise+how+to",
explanation:
"Kuiten reageren vaak goed op hogere reps en grote stretch. Neem hier je tijd en gebruik volledige range.",
tips: ["Onderin diep", "Bovenin hard aanspannen", "Rustig tempo"],
},
],
},
pull: {
title: "Pull",
subtitle: "Rug, achterste schouders en biceps.",
note: "Combineer een verticale trek met horizontale trek en eindig met rear delts en biceps.",
exercises: [
{
name: "Pull-ups / Lat Pulldown",
sets: "3-4 × 6-10",
reps: "6-10",
video: "https://www.youtube.com/results?search_query=pull+up+how+to+lat+pulldown+how+to",
explanation:
"Sterke vertikale trek voor lats. Kies de variant waarmee je strak en progressief kunt trainen.",
tips: ["Ellebogen naar je heupen", "Volledige stretch", "Niet zwaaien"],
},
{
name: "Barbell Row",
sets: "3 × 6-10",
reps: "6-10",
video: "https://www.youtube.com/results?search_query=barbell+row+how+to",
explanation:
"Sterke horizontale trek voor rugmassa. Houd je torso stabiel en trek consistent.",
tips: ["Hinge vastzetten", "Trek naar onderbuik", "Geen momentum"],
},
{
name: "Seated Cable Row",
sets: "3 × 8-12",
reps: "8-12",
video: "https://www.youtube.com/results?search_query=seated+cable+row+how+to",
explanation:
"Fijne oefening voor constante spanning. Goed voor extra rugvolume met een gecontroleerde uitvoering.",
tips: ["Lang uitrekken", "Middenrug voelen", "Elke rep strak"],
},
{
name: "Face Pull",
sets: "3 × 12-20",
reps: "12-20",
video: "https://www.youtube.com/results?search_query=face+pull+how+to",
explanation:
"Rear delt- en schoudergezondheidsoefening. Licht gewicht, goede lijn en nette reps.",
tips: ["Trek naar ooghoogte", "Ellebogen hoog", "Rustig terug"],
},
{
name: "Dumbbell Curl",
sets: "3 × 8-12",
reps: "8-12",
video: "https://www.youtube.com/results?search_query=dumbbell+bicep+curl+how+to",
explanation:
"Klassieke biceps-builder. Hou de schouders rustig en maak de volledige beweging af.",
tips: ["Ellebogen stil", "Volledige extensie", "Niet gooien"],
},
],
},
optional: {
title: "Herstel / lichte gym",
subtitle: "Alleen doen als je fris bent.",
note: "Deze dag is optioneel. Denk aan mobility, core, licht bovenlichaam of zwakke punten.",
exercises: [
{
name: "Mobility Flow",
sets: "10-15 min",
reps: "-",
video: "https://www.youtube.com/results?search_query=mobility+flow+warm+up",
explanation: "Maak je lichaam los en herstel sneller. Houd het licht en rustig.",
tips: ["Adem rustig", "Werk door de heupen en enkels", "Geen intensiteit"],
},
{
name: "Core Circuit",
sets: "2-3 rondes",
reps: "8-15",
video: "https://www.youtube.com/results?search_query=core+workout+basic",
explanation: "Korte core-sessie voor stabiliteit en sportcontrole. Compact en niet slopend.",
tips: ["Kwaliteit boven volume", "Rustig tempo", "Blijf gecontroleerd"],
},
],
},
};
const tabs = [
{ id: "home", label: "Home", icon: Home },
{ id: "schema", label: "Schema", icon: CalendarDays },
{ id: "progress", label: "Progress", icon: LineChart },
];
const accentMap = {
emerald: "from-emerald-500/20 to-emerald-400/5 border-emerald-400/20",
rose: "from-rose-500/20 to-rose-400/5 border-rose-400/20",
amber: "from-amber-500/20 to-amber-400/5 border-amber-400/20",
sky: "from-sky-500/20 to-sky-400/5 border-sky-400/20",
violet: "from-violet-500/20 to-violet-400/5 border-violet-400/20",
slate: "from-slate-500/20 to-slate-400/5 border-white/10",
};
export default function App() {
const [tab, setTab] = useState("home");
const [selectedDay, setSelectedDay] = useState(weeklyPlan[1]);
const [selectedExercise, setSelectedExercise] = useState("Barbell Bench Press");
const [entries, setEntries] = useState([
{ exercise: "Barbell Bench Press", weight: 70, reps: 8, date: "2026-03-18", day: "Dinsdag" },
{ exercise: "Back Squat", weight: 90, reps: 5, date: "2026-03-19", day: "Donderdag" },
{ exercise: "Pull-ups / Lat Pulldown", weight: 55, reps: 8, date: "2026-03-20", day: "Vrijdag" },
]);
const selectedWorkout = workoutLibrary[selectedDay.type];
const selectedExercises = selectedWorkout.exercises;
const allExerciseNames = useMemo(() => {
const names = [];
Object.values(workoutLibrary).forEach((group) => {
group.exercises.forEach((ex) => names.push(ex.name));
});
return names;
}, []);
const saveLog = (exercise, weight, reps, day) => {
if (!weight || !reps) return;
setEntries((prev) => [
{
exercise,
weight: Number(weight),
reps: Number(reps),
date: new Date().toISOString().slice(0, 10),
day,
},
...prev,
]);
};
const weeklyStats = useMemo(() => {
const totalSets = entries.length;
const avgWeight = totalSets ? Math.round(entries.reduce((sum, e) => sum + e.weight, 0) / totalSets) : 0;
const bestEntry = entries.reduce((best, current) => (current.weight * current.reps > best.weight * best.reps ? current : best), entries[0] || { weight: 0, reps: 0, exercise: "-" });
return { totalSets, avgWeight, bestEntry };
}, [entries]);
const totalVolumeByDate = useMemo(() => {
const grouped = {};
entries.forEach((e) => {
if (!grouped[e.date]) grouped[e.date] = 0;
grouped[e.date] += e.weight * e.reps;
});
return Object.entries(grouped)
.sort(([a], [b]) => a.localeCompare(b))
.map(([date, volume], index) => ({ date, volume, idx: index + 1 }));
}, [entries]);
const selectedExerciseProgress = useMemo(() => {
return entries
.filter((e) => e.exercise === selectedExercise)
.sort((a, b) => a.date.localeCompare(b.date))
.map((e, index) => ({
session: index + 1,
weight: e.weight,
reps: e.reps,
date: e.date,
volume: e.weight * e.reps,
}));
}, [entries, selectedExercise]);
const recentLogs = useMemo(() => entries.slice(0, 8), [entries]);
const dayColorClass = accentMap[selectedDay.accent] || accentMap.slate;
return (
Training dashboard
Voetbal + Gym App
Overzichtelijk schema, duidelijke oefeningsuitleg en progress-tracking in één app.
Jeff Nippard geïnspireerd
{tab === "home" && (
Deze week in één oogopslag
Je week is verdeeld zodat voetbal en kracht elkaar zo min mogelijk in de weg zitten.
Korte uitleg
De app gebruikt een duidelijke weekindeling: voetbaldagen krijgen een lichte full-body sessie, de gymdagen krijgen een echte push / legs / pull-opbouw, en progress wordt gelogd per oefening.
Vandaag / volgende training
Tik op een dag om het detailplan te openen.
{weeklyPlan.map((day) => (
))}
)}
{tab === "schema" && (
Weekschema
Kies een dag en zie direct de oefeningen, uitleg en een veld om je gewicht te loggen.
{weeklyPlan.map((day) => (
))}
{selectedDay.day}
{selectedWorkout.title}
{selectedWorkout.subtitle}
{selectedDay.type === "football" ? : }
{selectedWorkout.note}
{selectedExercises.map((exercise) => (
))}
)}
{tab === "progress" && (
Totale groei
Volume per dag: gewicht × reps, samengevoegd per datum.
Per oefening
Kies een oefening om je progressie per lift te zien.