From 71c808ed0589a103e59fedc7fc565065b251ad4a Mon Sep 17 00:00:00 2001 From: Dave Date: Sat, 19 Sep 2026 13:27:21 +0200 Subject: [PATCH] =?UTF-8?q?fix(dashboard):=20prevent=20polish/submit=20rac?= =?UTF-8?q?e,=20narrow=20cards=20payload,=20tighten=20form=20validation=20?= =?UTF-8?q?=E2=80=94=20Task=208=20Co-Authored-By:=20Claude=20Haiku=204.5?= =?UTF-8?q?=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../[projectSlug]/dashboard/page.tsx | 2 +- src/components/dashboard/log-work-panel.tsx | 22 +++++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/app/p/[clientSlug]/[projectSlug]/dashboard/page.tsx b/src/app/p/[clientSlug]/[projectSlug]/dashboard/page.tsx index 2c493df..118b59d 100644 --- a/src/app/p/[clientSlug]/[projectSlug]/dashboard/page.tsx +++ b/src/app/p/[clientSlug]/[projectSlug]/dashboard/page.tsx @@ -95,7 +95,7 @@ export default async function DashboardPage({ projectId={board.project.id} clientSlug={clientSlug} projectSlug={projectSlug} - cards={board.cards} + cards={board.cards.map((c) => ({ id: c.id, number: c.number, title: c.title }))} assistantAvailable={await aiConfigured()} /> )} diff --git a/src/components/dashboard/log-work-panel.tsx b/src/components/dashboard/log-work-panel.tsx index 828d843..37ce719 100644 --- a/src/components/dashboard/log-work-panel.tsx +++ b/src/components/dashboard/log-work-panel.tsx @@ -1,10 +1,9 @@ "use client"; -import { useState, useTransition } from "react"; +import { useRef, useState, useTransition } from "react"; import { Plus, Sparkles } from "lucide-react"; import { logWorkAction, polishNoteAction } from "@/app/actions/log-work"; -import type { CardRecord } from "@/lib/pb/types"; /** * The owner's way to put off-repo work onto the dashboard. @@ -23,10 +22,12 @@ export function LogWorkPanel({ projectId: string; clientSlug: string; projectSlug: string; - cards: CardRecord[]; + cards: { id: string; number: number; title: string }[]; assistantAvailable: boolean; }) { const [open, setOpen] = useState(false); + const openRef = useRef(open); + openRef.current = open; const [date, setDate] = useState(() => new Date().toISOString().slice(0, 10)); const [hours, setHours] = useState(""); const [message, setMessage] = useState(""); @@ -54,7 +55,10 @@ export function LogWorkPanel({ function submit(event: React.FormEvent) { event.preventDefault(); const parsedHours = Number(hours); - if (!message.trim() || !Number.isFinite(parsedHours) || parsedHours <= 0) return; + if (!message.trim() || !Number.isFinite(parsedHours) || parsedHours <= 0) { + setError("A message and a positive number of hours are required"); + return; + } setError(null); startTransition(async () => { @@ -86,6 +90,7 @@ export function LogWorkPanel({ setError(null); try { const result = await polishNoteAction({ text: message }); + if (!openRef.current) return; // the panel closed (e.g. via a submit) while this was in flight if (result.ok && result.text) setMessage(result.text); else setError(result.message ?? "Could not polish that note"); } finally { @@ -103,6 +108,7 @@ export function LogWorkPanel({ Date setDate(event.target.value)} className={field} @@ -113,8 +119,9 @@ export function LogWorkPanel({ Hours setHours(event.target.value)} placeholder="3.5" @@ -126,6 +133,7 @@ export function LogWorkPanel({