Enhance FormFieldWrapper with blur validation and toasts

Adds validation on blur mode to FormFieldWrapper, introduces animated validation states, and implements standardized form submission toasts via a new formToasts helper; updates ParkForm and RideForm to use the new toast system and to propagate error state with scroll-to-error support.
This commit is contained in:
gpt-engineer-app[bot]
2025-11-11 23:43:01 +00:00
parent 7d085a0702
commit 92e93bfc9d
5 changed files with 150 additions and 24 deletions

View File

@@ -17,6 +17,7 @@ import { FlexibleDateInput, type DatePrecision } from '@/components/ui/flexible-
import { SlugField } from '@/components/ui/slug-field';
import { toast } from '@/hooks/use-toast';
import { handleError } from '@/lib/errorHandler';
import { formToasts } from '@/lib/formToasts';
import { MapPin, Save, X, Plus, AlertCircle, Info } from 'lucide-react';
import { toDateOnly, parseDateOnly, toDateWithPrecision } from '@/lib/dateUtils';
import { Badge } from '@/components/ui/badge';
@@ -294,7 +295,16 @@ export function ParkForm({ onSubmit, onCancel, initialData, isEditing = false }:
await onSubmit(submissionData);
// Parent component handles success feedback
// Show success toast
if (isModerator()) {
formToasts.success.moderatorApproval('Park', data.name);
} else if (isEditing) {
formToasts.success.update('Park', data.name);
} else {
formToasts.success.create('Park', data.name);
}
// Parent component handles modal closing/navigation
} catch (error: unknown) {
const errorMessage = getErrorMessage(error);
handleError(error, {
@@ -308,6 +318,9 @@ export function ParkForm({ onSubmit, onCancel, initialData, isEditing = false }:
}
});
// Show error toast
formToasts.error.generic(errorMessage);
// Re-throw so parent can handle modal closing
throw error;
} finally {

View File

@@ -24,6 +24,7 @@ import { Checkbox } from '@/components/ui/checkbox';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
import { toast } from '@/hooks/use-toast';
import { handleError } from '@/lib/errorHandler';
import { formToasts } from '@/lib/formToasts';
import { Plus, Zap, Save, X, Building2, AlertCircle, Info, HelpCircle } from 'lucide-react';
import { toDateOnly, parseDateOnly, toDateWithPrecision } from '@/lib/dateUtils';
import { useUnitPreferences } from '@/hooks/useUnitPreferences';
@@ -360,14 +361,14 @@ export function RideForm({ onSubmit, onCancel, initialData, isEditing = false }:
// Pass clean data to parent with extended fields
await onSubmit(metricData);
toast({
title: isEditing ? "Ride Updated" : "Submission Sent",
description: isEditing
? "The ride information has been updated successfully."
: tempNewManufacturer
? "Ride, manufacturer, and model submitted for review"
: "Ride submitted for review"
});
// Show success toast
if (isModerator()) {
formToasts.success.moderatorApproval('Ride', data.name);
} else if (isEditing) {
formToasts.success.update('Ride', data.name);
} else {
formToasts.success.create('Ride', data.name);
}
} catch (error: unknown) {
handleError(error, {
action: isEditing ? 'Update Ride' : 'Create Ride',
@@ -378,6 +379,9 @@ export function RideForm({ onSubmit, onCancel, initialData, isEditing = false }:
}
});
// Show error toast
formToasts.error.generic(getErrorMessage(error));
// Re-throw so parent can handle modal closing
throw error;
} finally {