feat(water-log): cycle 4 — Tuxedo mobile worker Time tab + unified PIN

The mobile `/water` worker experience (Tuxedo-only, matching the
existing water flow) now exposes a "Time" tab alongside "Headgates"
so irrigators can clock in/out from the same phone they use for
water entries — no second PIN.

- MobileWaterApp: new `activeTab` state, sticky TabBar rendered only
  after PIN, screen='time' case embeds <TimeTrackingFieldClient>
  with hardcoded Tuxedo brand constants.
- handlePinSubmit best-effort calls `verifyTimeTrackingPin` after
  the water PIN succeeds, so the Time tab never re-prompts a worker
  who is also set up in `time_tracking_workers`.
- handleLogout clears BOTH `wl_session` and `time_tracking_session`
  cookies in independent try/catch blocks.
- Tab switching to Time drops in-flight water flow state; switching
  back to Headgates restores the list without reload.
- i18n: added `tab.{headgates,time,logout}` strings (en + es); lifted
  Tuxedo brand display constants into @/lib/water-log/brand so the
  standalone /tuxedo/time-clock page and the embedded Time tab share
  one source of truth.
This commit is contained in:
Nora
2026-07-03 18:26:32 -06:00
parent 0599bdc331
commit dfd6b63888
5 changed files with 218 additions and 23 deletions
+10 -1
View File
@@ -11,4 +11,13 @@
* `TUXEDO_BRAND_ID` with `effectiveBrandId` from `getAdminUser()` —
* which is the standard pattern used throughout the rest of the app.
*/
export const TUXEDO_BRAND_ID = "64294306-5f42-463d-a5e8-2ad6c81a96de";
export const TUXEDO_BRAND_ID = "64294306-5f42-463d-a5e8-2ad6c81a96de";
/** Display surfaces (Cycle 4) — single source of truth for the
* Tuxedo worker experience so the standalone `/tuxedo/time-clock`
* page and the embedded Time tab inside `/water` stay in sync.
* Bump these together when the brand refreshes its accent/logo. */
export const TUXEDO_BRAND_NAME = "Tuxedo Corn";
export const TUXEDO_BRAND_ACCENT = "green";
/** `null` until the Tuxedo brand gets a logo asset uploaded. */
export const TUXEDO_BRAND_LOGO_URL: string | null = null;
+17
View File
@@ -138,6 +138,13 @@ export type Labels = {
minutesAgo: (n: number) => string;
hoursAgo: (n: number) => string;
};
/** Tuxedo worker post-PIN shell (Cycle 4) — names for the two
* top tabs and the inline logout affordance. */
tab: {
headgates: string;
time: string;
logout: string;
};
};
export const LABELS: Record<Lang, Labels> = {
@@ -231,6 +238,11 @@ export const LABELS: Record<Lang, Labels> = {
minutesAgo: (n) => `${n}m ago`,
hoursAgo: (n) => `${n}h ago`,
},
tab: {
headgates: "Headgates",
time: "Time",
logout: "Log out",
},
},
es: {
common: {
@@ -323,6 +335,11 @@ export const LABELS: Record<Lang, Labels> = {
minutesAgo: (n) => `hace ${n}m`,
hoursAgo: (n) => `hace ${n}h`,
},
tab: {
headgates: "Compuertas",
time: "Tiempo",
logout: "Salir",
},
},
};