feat(04-03): project workspace + timer analytics + settings page

- /admin/projects/[id]: full workspace with 7 tabs (Fasi, Pagamenti,
  Documenti, Note, Commenti, Preventivo, Timer)
- TimerTab: TimerCell + ProfitabilityCard with €/h real, ideal cost, delta
- ProfitabilityCard: hours worked, €/h real vs target, profit/loss delta
- /admin/impostazioni: target_hourly_rate setting (default 50€/h)
- actions.ts: resolveEntity() helper — actions now work transparently
  with both clientId and projectId (same tab components reused)
- quote-actions.ts: same resolveEntity pattern for addQuoteItem,
  removeQuoteItem, updateAcceptedTotal
- timer-actions.ts: revalidate /admin/projects and /admin/projects/[id]

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-22 11:05:31 +02:00
parent ef05d647fe
commit 1d9fa10961
7 changed files with 442 additions and 108 deletions
+3
View File
@@ -32,6 +32,8 @@ export async function startTimer(projectId: string): Promise<{ entryId: string }
const id = nanoid();
await db.insert(time_entries).values({ id, project_id: projectId });
revalidatePath("/admin");
revalidatePath("/admin/projects");
revalidatePath(`/admin/projects/${projectId}`);
return { entryId: id };
}
@@ -64,4 +66,5 @@ export async function stopTimer(entryId: string): Promise<void> {
.where(eq(time_entries.id, entryId));
revalidatePath("/admin");
revalidatePath("/admin/projects");
}