feat: Add Time Tracking page with analytics and time distribution charts
continuous-integration/drone/push Build is passing

- Add TimeTrackingPage with pie/bar charts for time spent per label
- Add task_time_logs schema for tracking time entries
- Add /api/analytics/time-distribution endpoint
- Update sidebar navigation with time tracking link
- Update App routing for new pages
- Fix routine blocker and settings card issues
- Add German translations for analytics

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-08 23:50:10 +01:00
parent 877d0c897e
commit 74ffef48d3
12 changed files with 412 additions and 62 deletions
+16 -1
View File
@@ -317,7 +317,6 @@ export type Conversation = typeof conversations.$inferSelect;
export type InsertMessage = z.infer<typeof insertMessageSchema>;
export type Message = typeof messages.$inferSelect;
// Audit Logging
export const auditLogs = pgTable("audit_logs", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
userId: varchar("user_id").references(() => users.id), // Nullable if system action (though usually we track actor)
@@ -336,3 +335,19 @@ export const insertAuditLogSchema = createInsertSchema(auditLogs).omit({
export type InsertAuditLog = z.infer<typeof insertAuditLogSchema>;
export type AuditLog = typeof auditLogs.$inferSelect;
export const taskTimeLogs = pgTable("task_time_logs", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
taskId: varchar("task_id").references(() => tasks.id).notNull(),
userId: varchar("user_id").references(() => users.id).notNull(),
timeSpent: integer("time_spent").notNull(), // in minutes
createdAt: timestamp("created_at").defaultNow(), // WHEN the time was logged
});
export const insertTaskTimeLogSchema = createInsertSchema(taskTimeLogs).omit({
id: true,
createdAt: true,
});
export type InsertTaskTimeLog = z.infer<typeof insertTaskTimeLogSchema>;
export type TaskTimeLog = typeof taskTimeLogs.$inferSelect;