diff --git a/.phase12-state.json b/.phase12-state.json index 4b0d1eb..d170731 100644 --- a/.phase12-state.json +++ b/.phase12-state.json @@ -1,5 +1,8 @@ { "completed_features": [], - "current_feature": "invoicing-stub", - "started_at": "2026-05-23T06:33:48.406343" + "current_feature": "time-rounding-rules", + "started_at": "2026-05-23T06:33:48.406343", + "attempted_features": [ + "invoicing-stub" + ] } \ No newline at end of file diff --git a/GENERATION_LOG.md b/GENERATION_LOG.md index d59bb34..0622fef 100644 --- a/GENERATION_LOG.md +++ b/GENERATION_LOG.md @@ -1459,3 +1459,22 @@ 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 +- `06:35:10` **INFO** Committed feature invoicing-stub +- `06:35:10` **INFO** Pushed: rc=0 + +## Phase-3 Feature: time-rounding-rules (2026-05-23 06:35:10) + +- `06:35:10` **INFO** Description: Settings-Option: Rundung für Time-Entries (5/15/30 min) +- `06:35:10` **INFO** Generating apps/api/src/db/schema.ts (ERWEITERT — füge `roundingMinutes: integer('rounding_minutes').notNull…) +- `06:35:40` **INFO** wrote 3445 chars in 29.4s (attempt 1) +- `06:35:40` **INFO** Generating apps/web/src/pages/Settings.tsx (ERWEITERT — füge Select-Field 'Time-Rounding: keine / 5min / 15min / 3…) +- `06:36:27` **INFO** wrote 5786 chars in 47.5s (attempt 1) +- `06:36:27` **INFO** Running tsc --noEmit on api… +- `06:36:29` **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/api/src/db/schema.ts b/apps/api/src/db/schema.ts index 7cced23..242461e 100644 --- a/apps/api/src/db/schema.ts +++ b/apps/api/src/db/schema.ts @@ -55,6 +55,7 @@ export const appSettings = pgTable("app_settings", { workspaceName: text("workspace_name").notNull().default("EmberClone"), defaultBillable: boolean("default_billable").notNull().default(true), weekStart: integer("week_start").notNull().default(1), + roundingMinutes: integer("rounding_minutes").notNull().default(0), updatedAt: timestamp("updated_at").notNull().defaultNow() }) diff --git a/apps/web/src/pages/Settings.tsx b/apps/web/src/pages/Settings.tsx index c387d8e..92bcd85 100644 --- a/apps/web/src/pages/Settings.tsx +++ b/apps/web/src/pages/Settings.tsx @@ -8,6 +8,7 @@ export default function Settings() { const [workspaceName, setWorkspaceName] = useState(''); const [defaultBillable, setDefaultBillable] = useState(false); const [weekStart, setWeekStart] = useState('Monday'); + const [timeRounding, setTimeRounding] = useState('0'); const { data: settings, isLoading, refetch } = useQuery({ queryKey: ['settings'], @@ -20,7 +21,12 @@ export default function Settings() { }); const updateMutation = useMutation({ - mutationFn: async (data: { workspaceName: string; defaultBillable: boolean; weekStart: string }) => { + mutationFn: async (data: { + workspaceName: string; + defaultBillable: boolean; + weekStart: string; + timeRounding: number + }) => { return api.updateSettings(data); }, onSuccess: async () => { @@ -37,6 +43,7 @@ export default function Settings() { setWorkspaceName(settings.workspaceName || ''); setDefaultBillable(settings.defaultBillable ?? false); setWeekStart(settings.weekStart || 'Monday'); + setTimeRounding((settings.timeRounding ?? 0).toString()); } }, [settings]); @@ -46,6 +53,7 @@ export default function Settings() { workspaceName, defaultBillable, weekStart, + timeRounding: parseInt(timeRounding, 10), }); }; @@ -113,6 +121,21 @@ export default function Settings() { + + {/* Time Rounding */} +
+ + +