diff --git a/src/components/timer/header-timer.tsx b/src/components/timer/header-timer.tsx
index 558837d..35c80d5 100644
--- a/src/components/timer/header-timer.tsx
+++ b/src/components/timer/header-timer.tsx
@@ -39,6 +39,7 @@ interface FeeItem {
name: string;
description: string | null;
amount: number;
+ pricing_type: "hourly" | "flat";
}
export function HeaderTimer() {
@@ -67,7 +68,7 @@ export function HeaderTimer() {
supabase.from("profiles").select("hourly_rate").eq("id", user.id).maybeSingle(),
supabase
.from("fee_schedule_items")
- .select("id, name, description, amount")
+ .select("id, name, description, amount, pricing_type")
.eq("active", true)
.eq("billable", true)
.eq("category", "time")
@@ -96,6 +97,8 @@ export function HeaderTimer() {
[feeItems, feeItemId],
);
+ const isFlatFee = selectedFee?.pricing_type === "flat";
+
const effectiveRate =
selectedFee?.amount ?? activeCase?.default_hourly_rate ?? profileRate ?? 0;
@@ -111,15 +114,18 @@ export function HeaderTimer() {
if (!user?.id) return toast.error("Not signed in");
if (!timer.caseId) return toast.error("Select a case before saving");
if (!timer.description.trim()) return toast.error("Description required");
- if (elapsedMs < 1000) return toast.error("Timer hasn't recorded any time yet");
+ if (elapsedMs < 1000 && !isFlatFee) return toast.error("Timer hasn't recorded any time yet");
setSaving(true);
- const { hours } = consume();
+ const { hours: tracked } = consume();
+ // For a flat-fee item, store 1 hour at the flat amount so the total = flat amount.
+ const hours = isFlatFee ? 1 : tracked;
+ const rate = isFlatFee ? selectedFee!.amount : effectiveRate;
const { error } = await supabase.from("time_entries").insert({
case_id: timer.caseId,
user_id: user.id,
work_date: new Date().toISOString().slice(0, 10),
hours,
- hourly_rate: effectiveRate,
+ hourly_rate: rate,
description: timer.description.trim(),
billable,
});
@@ -128,9 +134,14 @@ export function HeaderTimer() {
toast.error(error.message);
return;
}
- toast.success(`Saved ${hours.toFixed(1)} hr`, {
- description: `${formatCurrency(hours * effectiveRate)} at ${formatCurrency(effectiveRate)}/hr`,
- });
+ toast.success(
+ isFlatFee ? `Saved flat fee` : `Saved ${hours.toFixed(1)} hr`,
+ {
+ description: isFlatFee
+ ? formatCurrency(rate)
+ : `${formatCurrency(hours * rate)} at ${formatCurrency(rate)}/hr`,
+ },
+ );
setBillable(true);
setFeeItemId("");
setOpen(false);
@@ -247,7 +258,10 @@ export function HeaderTimer() {
{feeItems.map((f) => (
- Time saves rounded up to the nearest 1/10 hour (6 minutes). + {isFlatFee + ? "Flat fee items save at the fixed amount regardless of elapsed time." + : "Time saves rounded up to the nearest 1/10 hour (6 minutes)."}