Visual redesign: indigo accent palette, lucide icons per section, lighter/softer cards and dark mode
Deploy App / deploy (push) Successful in 2m59s

This commit is contained in:
2026-07-10 22:19:10 +02:00
parent e9dacc2026
commit 2e65bb3a2d
13 changed files with 197 additions and 114 deletions
+30 -23
View File
@@ -1,6 +1,7 @@
"use client";
import { useCallback, useEffect, useState } from "react";
import { LogOut, PiggyBank, Plus, Settings, X } from "lucide-react";
import { PhaseCard } from "@/components/PhaseCard";
import { TransitionPanel } from "@/components/TransitionPanel";
import { Dashboard } from "@/components/Dashboard";
@@ -91,15 +92,17 @@ export function AppShell({ initialHousehold }: { initialHousehold: HouseholdInpu
return (
<div className="mx-auto flex w-full max-w-5xl flex-1 flex-col gap-6 px-4 py-8">
<header className="flex items-center justify-between">
<h1 className="text-xl font-semibold text-zinc-900 dark:text-zinc-50">
<h1 className="flex items-center gap-2 text-xl font-semibold text-zinc-900 dark:text-zinc-50">
<PiggyBank className="h-6 w-6 text-indigo-600 dark:text-indigo-400" />
Financial Planning Tool
</h1>
<div className="flex items-center gap-2">
<button
type="button"
onClick={() => setShowSettings((v) => !v)}
className="rounded-md border border-zinc-300 px-3 py-1.5 text-xs font-medium text-zinc-700 hover:bg-zinc-50 dark:border-zinc-600 dark:text-zinc-200 dark:hover:bg-zinc-800"
className="flex items-center gap-1.5 rounded-lg border border-zinc-300 bg-white px-3 py-1.5 text-xs font-medium text-zinc-700 shadow-sm hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-200 dark:hover:bg-zinc-700"
>
<Settings className="h-3.5 w-3.5" />
Grundprofil
</button>
<button
@@ -108,8 +111,9 @@ export function AppShell({ initialHousehold }: { initialHousehold: HouseholdInpu
await api.post("/api/auth/logout");
window.location.href = "/login";
}}
className="rounded-md border border-zinc-300 px-3 py-1.5 text-xs font-medium text-zinc-700 hover:bg-zinc-50 dark:border-zinc-600 dark:text-zinc-200 dark:hover:bg-zinc-800"
className="flex items-center gap-1.5 rounded-lg border border-zinc-300 bg-white px-3 py-1.5 text-xs font-medium text-zinc-700 shadow-sm hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-200 dark:hover:bg-zinc-700"
>
<LogOut className="h-3.5 w-3.5" />
Abmelden
</button>
</div>
@@ -124,15 +128,15 @@ export function AppShell({ initialHousehold }: { initialHousehold: HouseholdInpu
)}
{/* Tab-Leiste */}
<div className="flex flex-wrap items-center gap-2 border-b border-zinc-200 pb-2 dark:border-zinc-700">
<div className="flex flex-wrap items-center gap-2 border-b border-zinc-200 pb-2 dark:border-zinc-800">
{plans.map((p) => (
<div key={p.id} className="flex items-center">
<button
type="button"
onClick={() => setSelectedPlanId(p.id)}
className={`rounded-t-md px-3 py-1.5 text-sm font-medium ${
className={`rounded-t-lg px-3 py-1.5 text-sm font-medium transition-colors ${
selectedPlanId === p.id
? "bg-zinc-900 text-white dark:bg-zinc-100 dark:text-zinc-900"
? "bg-indigo-600 text-white shadow-sm dark:bg-indigo-500"
: "text-zinc-600 hover:bg-zinc-100 dark:text-zinc-300 dark:hover:bg-zinc-800"
}`}
>
@@ -142,10 +146,10 @@ export function AppShell({ initialHousehold }: { initialHousehold: HouseholdInpu
<button
type="button"
onClick={() => handleDeletePlan(p.id)}
className="ml-1 text-xs text-zinc-400 hover:text-red-600"
className="ml-1 text-zinc-400 hover:text-red-600"
aria-label="Plan loeschen"
>
<X className="h-3.5 w-3.5" />
</button>
)}
</div>
@@ -154,9 +158,10 @@ export function AppShell({ initialHousehold }: { initialHousehold: HouseholdInpu
<button
type="button"
onClick={() => setShowNewPlan((v) => !v)}
className="rounded-md px-2 py-1.5 text-sm text-zinc-500 hover:bg-zinc-100 dark:hover:bg-zinc-800"
className="flex items-center gap-1 rounded-lg px-2 py-1.5 text-sm text-indigo-600 hover:bg-indigo-50 dark:text-indigo-400 dark:hover:bg-indigo-500/10"
>
+ Plan
<Plus className="h-3.5 w-3.5" />
Plan
</button>
{showNewPlan && (
<NewPlanPopover
@@ -174,9 +179,10 @@ export function AppShell({ initialHousehold }: { initialHousehold: HouseholdInpu
<button
type="button"
onClick={() => setShowScenario((v) => !v)}
className="rounded-md px-2 py-1.5 text-sm text-zinc-500 hover:bg-zinc-100 dark:hover:bg-zinc-800"
className="flex items-center gap-1 rounded-lg px-2 py-1.5 text-sm text-indigo-600 hover:bg-indigo-50 dark:text-indigo-400 dark:hover:bg-indigo-500/10"
>
+ Szenario
<Plus className="h-3.5 w-3.5" />
Szenario
</button>
{showScenario && (
<ScenarioPopover
@@ -235,9 +241,10 @@ export function AppShell({ initialHousehold }: { initialHousehold: HouseholdInpu
<button
type="button"
onClick={handleAddPhase}
className="self-start rounded-md border border-zinc-300 px-3 py-2 text-sm font-medium text-zinc-700 hover:bg-zinc-50 dark:border-zinc-600 dark:text-zinc-200 dark:hover:bg-zinc-800"
className="flex items-center gap-1.5 self-start rounded-lg border border-dashed border-indigo-300 bg-indigo-50/50 px-3 py-2 text-sm font-medium text-indigo-700 hover:bg-indigo-50 dark:border-indigo-500/30 dark:bg-indigo-500/10 dark:text-indigo-300 dark:hover:bg-indigo-500/20"
>
+ Phase hinzufuegen
<Plus className="h-4 w-4" />
Phase hinzufuegen
</button>
{detail.plan.phases.length > 0 && (
@@ -252,9 +259,9 @@ export function AppShell({ initialHousehold }: { initialHousehold: HouseholdInpu
function NewPlanPopover({ onCreate, onClose }: { onCreate: (name: string) => void; onClose: () => void }) {
const [name, setName] = useState("Basisplan");
return (
<div className="absolute left-0 top-10 z-10 w-64 rounded-md border border-zinc-200 bg-white p-3 shadow-lg dark:border-zinc-700 dark:bg-zinc-900">
<div className="absolute left-0 top-10 z-10 w-64 rounded-lg border border-zinc-200 bg-white p-3 shadow-lg dark:border-zinc-700 dark:bg-zinc-800">
<input
className="mb-2 w-full rounded-md border border-zinc-300 px-2 py-1 text-sm dark:border-zinc-600 dark:bg-zinc-800"
className="mb-2 w-full rounded-lg border border-zinc-300 px-2 py-1 text-sm focus:border-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/20 dark:border-zinc-600 dark:bg-zinc-900"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Name des Plans"
@@ -263,11 +270,11 @@ function NewPlanPopover({ onCreate, onClose }: { onCreate: (name: string) => voi
<button
type="button"
onClick={() => onCreate(name)}
className="rounded-md bg-zinc-900 px-2 py-1 text-xs text-white dark:bg-zinc-100 dark:text-zinc-900"
className="rounded-lg bg-indigo-600 px-2 py-1 text-xs font-medium text-white hover:bg-indigo-500 dark:bg-indigo-500 dark:hover:bg-indigo-400"
>
Erstellen
</button>
<button type="button" onClick={onClose} className="text-xs text-zinc-500">
<button type="button" onClick={onClose} className="text-xs text-zinc-500 hover:text-zinc-700 dark:hover:text-zinc-300">
Abbrechen
</button>
</div>
@@ -287,16 +294,16 @@ function ScenarioPopover({
const [name, setName] = useState("Neues Szenario");
const [branchFromPhaseId, setBranchFromPhaseId] = useState(phases[phases.length - 1]?.id ?? "");
return (
<div className="absolute left-0 top-10 z-10 w-72 rounded-md border border-zinc-200 bg-white p-3 shadow-lg dark:border-zinc-700 dark:bg-zinc-900">
<div className="absolute left-0 top-10 z-10 w-72 rounded-lg border border-zinc-200 bg-white p-3 shadow-lg dark:border-zinc-700 dark:bg-zinc-800">
<input
className="mb-2 w-full rounded-md border border-zinc-300 px-2 py-1 text-sm dark:border-zinc-600 dark:bg-zinc-800"
className="mb-2 w-full rounded-lg border border-zinc-300 px-2 py-1 text-sm focus:border-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/20 dark:border-zinc-600 dark:bg-zinc-900"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Name des Szenarios"
/>
<label className="mb-1 block text-xs text-zinc-500">Verzweigen ab Phase</label>
<select
className="mb-2 w-full rounded-md border border-zinc-300 px-2 py-1 text-sm dark:border-zinc-600 dark:bg-zinc-800"
className="mb-2 w-full rounded-lg border border-zinc-300 px-2 py-1 text-sm focus:border-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/20 dark:border-zinc-600 dark:bg-zinc-900"
value={branchFromPhaseId}
onChange={(e) => setBranchFromPhaseId(e.target.value)}
>
@@ -310,11 +317,11 @@ function ScenarioPopover({
<button
type="button"
onClick={() => onCreate(name, branchFromPhaseId)}
className="rounded-md bg-zinc-900 px-2 py-1 text-xs text-white dark:bg-zinc-100 dark:text-zinc-900"
className="rounded-lg bg-indigo-600 px-2 py-1 text-xs font-medium text-white hover:bg-indigo-500 dark:bg-indigo-500 dark:hover:bg-indigo-400"
>
Erstellen
</button>
<button type="button" onClick={onClose} className="text-xs text-zinc-500">
<button type="button" onClick={onClose} className="text-xs text-zinc-500 hover:text-zinc-700 dark:hover:text-zinc-300">
Abbrechen
</button>
</div>