From 7267515a87f0599ceb76ab67549930d256fe4d41 Mon Sep 17 00:00:00 2001 From: elpatron Date: Tue, 13 Jan 2026 09:48:54 +0100 Subject: [PATCH] feat: add recent plans history to homepage --- app/[lang]/dashboard/[planId]/page.tsx | 2 + app/[lang]/page.tsx | 3 + components/plan-tracker.tsx | 35 ++++++++++++ components/recent-plans.tsx | 76 ++++++++++++++++++++++++++ dictionaries/de.json | 7 ++- dictionaries/en.json | 7 ++- 6 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 components/plan-tracker.tsx create mode 100644 components/recent-plans.tsx diff --git a/app/[lang]/dashboard/[planId]/page.tsx b/app/[lang]/dashboard/[planId]/page.tsx index 6cb2f98..7e0511b 100644 --- a/app/[lang]/dashboard/[planId]/page.tsx +++ b/app/[lang]/dashboard/[planId]/page.tsx @@ -8,6 +8,7 @@ import { Button } from "@/components/ui/button" import { PlanLoginForm } from "@/components/plan-login-form" import { PlanDashboard } from "./_components/plan-dashboard" import { getDictionary } from "@/get-dictionary" +import { PlanTracker } from "@/components/plan-tracker" export default async function DashboardPage({ params @@ -39,6 +40,7 @@ export default async function DashboardPage({ return (
+
+ + {dict.home.createPlan} diff --git a/components/plan-tracker.tsx b/components/plan-tracker.tsx new file mode 100644 index 0000000..8315038 --- /dev/null +++ b/components/plan-tracker.tsx @@ -0,0 +1,35 @@ +"use client" + +import { useEffect } from "react" + +export function PlanTracker({ planId, title }: { planId: string, title: string }) { + useEffect(() => { + const stored = localStorage.getItem("csp_recent_plans") + let plans: { id: string, title: string, lastVisited: number }[] = [] + + if (stored) { + try { + plans = JSON.parse(stored) + } catch (e) { + console.error(e) + } + } + + // Remove existing entry for this plan + plans = plans.filter(p => p.id !== planId) + + // Add to top + plans.unshift({ + id: planId, + title: title, + lastVisited: Date.now() + }) + + // Keep max 5 + plans = plans.slice(0, 5) + + localStorage.setItem("csp_recent_plans", JSON.stringify(plans)) + }, [planId, title]) + + return null +} diff --git a/components/recent-plans.tsx b/components/recent-plans.tsx new file mode 100644 index 0000000..56a926d --- /dev/null +++ b/components/recent-plans.tsx @@ -0,0 +1,76 @@ +"use client" + +import { useEffect, useState } from "react" +import Link from "next/link" +import { History, ChevronRight, X } from "lucide-react" +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" +import { Button } from "@/components/ui/button" + +type RecentPlan = { + id: string + title: string + lastVisited: number +} + +export function RecentPlans({ lang, dict }: { lang: string, dict: { title: string, noPlans: string, clear: string } }) { + const [plans, setPlans] = useState([]) + const [mounted, setMounted] = useState(false) + + useEffect(() => { + setMounted(true) + const stored = localStorage.getItem("csp_recent_plans") + if (stored) { + try { + const parsed = JSON.parse(stored) + setPlans(parsed.sort((a: RecentPlan, b: RecentPlan) => b.lastVisited - a.lastVisited)) + } catch (e) { + console.error("Failed to parse recent plans", e) + } + } + }, []) + + const removePlan = (id: string, e: React.MouseEvent) => { + e.preventDefault() + e.stopPropagation() + const newPlans = plans.filter(p => p.id !== id) + setPlans(newPlans) + localStorage.setItem("csp_recent_plans", JSON.stringify(newPlans)) + } + + if (!mounted || plans.length === 0) return null + + return ( + + + + + {dict.title} + + + + {plans.map((plan) => ( + +
+ {plan.title} +
+
+ + +
+ + ))} +
+
+ ) +} diff --git a/dictionaries/de.json b/dictionaries/de.json index dd4150c..6307b45 100644 --- a/dictionaries/de.json +++ b/dictionaries/de.json @@ -3,7 +3,12 @@ "title": "Katzen-Sitting-Planer", "description": "Koordiniere die Pflege deiner Vierbeiner, während du weg bist.", "createPlan": "Neuen Plan erstellen", - "createPlanDesc": "Gib deinem Plan einen Namen, wähle deine Reisedaten und setze ein Gruppen-Passwort." + "createPlanDesc": "Gib deinem Plan einen Namen, wähle deine Reisedaten und setze ein Gruppen-Passwort.", + "recentPlans": { + "title": "Zuletzt besuchte Pläne", + "noPlans": "Keine Pläne", + "clear": "Leeren" + } }, "createPlanForm": { "title": "Titel des Plans", diff --git a/dictionaries/en.json b/dictionaries/en.json index 4302083..79c8999 100644 --- a/dictionaries/en.json +++ b/dictionaries/en.json @@ -3,7 +3,12 @@ "title": "Cat Sitting Planner", "description": "Coordinate care for your furry friends while you're away.", "createPlan": "Create a New Plan", - "createPlanDesc": "Give your plan a title, select your travel dates and set a group password." + "createPlanDesc": "Give your plan a title, select your travel dates and set a group password.", + "recentPlans": { + "title": "Recently Visited Plans", + "noPlans": "No recent plans", + "clear": "Clear" + } }, "createPlanForm": { "title": "Plan Title",