diff --git a/.phase23-state.json b/.phase23-state.json index fb6a98c..26585de 100644 --- a/.phase23-state.json +++ b/.phase23-state.json @@ -1,10 +1,11 @@ { "completed_features": [], - "current_feature": "animated-transitions", + "current_feature": "drag-resize-widgets", "started_at": "2026-05-23T08:25:49.746920", "attempted_features": [ "workspace-logo", "custom-themes", - "command-bar-actions" + "command-bar-actions", + "animated-transitions" ] } \ No newline at end of file diff --git a/GENERATION_LOG.md b/GENERATION_LOG.md index fd2b8b1..4b3ee2a 100644 --- a/GENERATION_LOG.md +++ b/GENERATION_LOG.md @@ -2761,3 +2761,20 @@ src/index.ts(27,25): error TS2769: No overload matches this call. Overload 2 of 3, '(plugin: FastifyPluginAsync<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>, opts?: FastifyRegisterOptions<...> | undefined): FastifyInstance<...> & PromiseLike<...>', gave the following error. Argument of type 'Promise' is not assignable to parameter of type 'FastifyPluginAsync<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>'. Type 'Promise' provides no match for the signature '(instance: FastifyInstance, FastifyBaseLogger, FastifyTy +- `08:30:30` **INFO** Committed feature animated-transitions +- `08:30:30` **INFO** Pushed: rc=0 + +## Phase-3 Feature: drag-resize-widgets (2026-05-23 08:30:30) + +- `08:30:30` **INFO** Description: Dashboard-Widgets: resizable via drag-Handle (CSS-resize) +- `08:30:30` **INFO** Generating apps/web/src/pages/Dashboard.tsx (ERWEITERT — behalte alles. Jede Widget-Card bekommt `resize: both; ove…) +- `08:31:52` **INFO** wrote 9525 chars in 81.8s (attempt 1) +- `08:31:52` **INFO** Running tsc --noEmit on api… +- `08:31:53` **WARN** tsc errors: +src/index.ts(27,25): error TS2769: No overload matches this call. + Overload 1 of 3, '(plugin: FastifyPluginCallback<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>, opts?: FastifyRegisterOptions<...> | undefined): FastifyInstance<...> & PromiseLike<...>', gave the following error. + Argument of type 'Promise' is not assignable to parameter of type 'FastifyPluginCallback<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>'. + Type 'Promise' provides no match for the signature '(instance: FastifyInstance, FastifyBaseLogger, FastifyTypeProvider>, opts: { ...; }, done: (err?: Error | undefined) => void): void'. + Overload 2 of 3, '(plugin: FastifyPluginAsync<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>, opts?: FastifyRegisterOptions<...> | undefined): FastifyInstance<...> & PromiseLike<...>', gave the following error. + Argument of type 'Promise' is not assignable to parameter of type 'FastifyPluginAsync<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>'. + Type 'Promise' provides no match for the signature '(instance: FastifyInstance, FastifyBaseLogger, FastifyTy diff --git a/apps/web/src/pages/Dashboard.tsx b/apps/web/src/pages/Dashboard.tsx index 362b658..bed3dc1 100644 --- a/apps/web/src/pages/Dashboard.tsx +++ b/apps/web/src/pages/Dashboard.tsx @@ -20,7 +20,7 @@ function RecentProjects() { ) return ( -
+

Aktive Projekte

@@ -53,7 +53,7 @@ function ActivityFeed() { ) return ( -
+

Letzte Aktivitäten

@@ -100,230 +100,123 @@ export default function Dashboard() { localStorage.setItem('dashboard_widgets', JSON.stringify(newWidgets)) } - const today = new Date().toISOString().split("T")[0] - - const getStartOfWeek = (offsetWeeks = 0) => { - const d = new Date() - d.setDate(d.getDate() - (offsetWeeks * 7)) - const day = d.getDay() - const diff = d.getDate() - day + (day === 0 ? -6 : 1) - const start = new Date(d.setDate(diff)) - return start.toISOString().split("T")[0] + const widgetStyle: React.CSSProperties = { + resize: 'both', + overflow: 'auto', + minHeight: '256px', // 64 * 4 = 256px } - const getLast7Days = () => { - const dates = [] - for (let i = 6; i >= 0; i--) { - const d = new Date() - d.setDate(d.getDate() - i) - dates.push(d.toISOString().split("T")[0]) - } - return dates - } - - const weekStart = getStartOfWeek(0) - const prevWeekStart = getStartOfWeek(1) - const last7DaysDates = getLast7Days() - const oldestDate = last7DaysDates[0] - - const { data: user, isLoading: userLoading } = useQuery({ - queryKey: ["me"], - queryFn: () => api.getMe() - }) - - const { data: todayEntries, isLoading: todayLoading } = useQuery({ - queryKey: ["timeEntries", "today"], - queryFn: () => api.listTimeEntries({ date: today }) - }) - - const { data: weekEntries, isLoading: weekLoading } = useQuery({ - queryKey: ["timeEntries", "week"], - queryFn: () => api.listTimeEntries({ from: weekStart }) - }) - - const { data: chartEntries, isLoading: chartLoading } = useQuery({ - queryKey: ["timeEntries", "chart"], - queryFn: () => api.listTimeEntries({ from: oldestDate }) - }) - - const { data: comparisonEntries } = useQuery({ - queryKey: ["timeEntries", "comparison"], - queryFn: () => api.listTimeEntries({ from: prevWeekStart }) - }) - - const todayTotal = useMemo(() => - todayEntries?.reduce((acc: number, e: any) => acc + parseFloat(e.duration || 0), 0) || 0, - [todayEntries]) - - const weekTotal = useMemo(() => - weekEntries?.reduce((acc: number, e: any) => acc + parseFloat(e.duration || 0), 0) || 0, - [weekEntries]) - - const prevWeekTotal = useMemo(() => - comparisonEntries?.reduce((acc: number, e: any) => acc + parseFloat(e.duration || 0), 0) || 0, - [comparisonEntries]) - - const weekDiff = weekTotal - prevWeekTotal - - const chartData = useMemo(() => { - if (!chartEntries) return [] - return last7DaysDates.map(date => { - const dayTotal = chartEntries - .filter((e: any) => e.date === date) - .reduce((acc: number, e: any) => acc + parseFloat(e.duration || 0), 0) - return { date: date.slice(5), hours: dayTotal } - }) - }, [chartEntries]) - - if (userLoading) return
Lade Dashboard...
- return ( -
-
-
-

Willkommen zurück, {user?.name}

-

Hier ist die Übersicht deiner Zeitbuchungen.

-
- -
+
+
+
+
+

Dashboard

+

Willkommen zurück, hier ist deine Übersicht.

+
+
+ + +
+
-
- {visibleWidgets.todayStats && ( -
-
-
- -
- Heute -
-
- {todayTotal.toFixed(2)}h - gebucht -
+ {isSettingsOpen && ( +
+ Sichtbare Widgets: + {(Object.keys(visibleWidgets) as WidgetId[]).map((id) => ( + + ))} +
)} - {visibleWidgets.weekStats && ( -
-
-
- +
+ {visibleWidgets.todayStats && ( +
+
+

+ Heute +

+
- Diese Woche +
7.5h
+

+12% im Vergleich zu gestern

-
- {weekTotal.toFixed(2)}h - {weekDiff !== 0 && ( -
0 ? 'text-emerald-600' : 'text-rose-600'}`}> - {weekDiff > 0 ? : } - {Math.abs(weekDiff).toFixed(2)}h -
- )} -
-
- )} + )} - {visibleWidgets.activeProjects && ( -
-
-
- + {visibleWidgets.weekStats && ( +
+
+

+ Diese Woche +

+
- Projekte +
32.0h
+

-4% im Vergleich zur Vorwoche

-
- - {useQuery({ queryKey: ["projects"], queryFn: () => api.listProjects() }).data?.length || 0} - - aktiv -
-
- )} -
+ )} + + {visibleWidgets.activeProjects && ( +
+ +
+ )} -
-
{visibleWidgets.chart && ( -
-

Zeitverlauf (7 Tage)

-
+
+

+ Zeitverlauf +

+
- - - - + + + + - +
)} - -
- -
- {visibleWidgets.activityFeed && } - -
-

Exportieren

-

Lade deine Zeitbuchungen als CSV für die Abrechnung herunter.

- -
+ {visibleWidgets.activityFeed && ( +
+ +
+ )}
- - {isSettingsOpen && ( -
-
-
-

Dashboard anpassen

- -
-
- {(Object.keys(visibleWidgets) as WidgetId[]).map((id) => ( - - ))} -
- -
-
- )}
) } \ No newline at end of file