2 Commits

Author SHA1 Message Date
Cursor Agent a12060f5ff Remove status change hint text from invoice form
Co-authored-by: soconnor0919 <soconnor0919@gmail.com>
2025-07-17 12:54:50 +00:00
Cursor Agent 117ba0832a Add client-side validation and improve error handling in invoice form
Co-authored-by: soconnor0919 <soconnor0919@gmail.com>
2025-07-17 12:43:44 +00:00
2 changed files with 22 additions and 7 deletions
+21 -7
View File
@@ -498,6 +498,25 @@ function InvoiceForm({ invoiceId }: InvoiceFormProps) {
e.preventDefault(); e.preventDefault();
setLoading(true); setLoading(true);
// Client-side validation
if (!formData.clientId) {
toast.error("Please select a client");
setLoading(false);
return;
}
if (formData.items.length === 0) {
toast.error("Please add at least one invoice item");
setLoading(false);
return;
}
if (formData.items.some(item => !item.description.trim())) {
toast.error("Please provide descriptions for all items");
setLoading(false);
return;
}
try { try {
if (invoiceId && hasOnlyStatusChanged) { if (invoiceId && hasOnlyStatusChanged) {
// Use dedicated status update mutation for status-only changes // Use dedicated status update mutation for status-only changes
@@ -526,7 +545,6 @@ function InvoiceForm({ invoiceId }: InvoiceFormProps) {
description: item.description, description: item.description,
hours: item.hours, hours: item.hours,
rate: item.rate, rate: item.rate,
amount: item.hours * item.rate,
})), })),
}; };
@@ -540,7 +558,8 @@ function InvoiceForm({ invoiceId }: InvoiceFormProps) {
} }
} catch (error) { } catch (error) {
console.error("Error saving invoice:", error); console.error("Error saving invoice:", error);
toast.error("Failed to save invoice. Check console for details."); const errorMessage = error instanceof Error ? error.message : "Unknown error";
toast.error(`Failed to save invoice: ${errorMessage}`);
} finally { } finally {
setLoading(false); setLoading(false);
} }
@@ -642,11 +661,6 @@ function InvoiceForm({ invoiceId }: InvoiceFormProps) {
))} ))}
</SelectContent> </SelectContent>
</Select> </Select>
{invoiceId && hasOnlyStatusChanged && (
<div className="mt-1 text-xs text-blue-600 dark:text-blue-400">
Only status will be updated
</div>
)}
</div> </div>
</div> </div>
+1
View File
@@ -30,6 +30,7 @@ const createInvoiceSchema = z.object({
const updateInvoiceSchema = createInvoiceSchema.partial().extend({ const updateInvoiceSchema = createInvoiceSchema.partial().extend({
id: z.string(), id: z.string(),
clientId: z.string().min(1, "Client is required"), // Keep clientId required for updates
}); });
const updateStatusSchema = z.object({ const updateStatusSchema = z.object({