feat: add shared validation for chainage and coordinates
This commit is contained in:
@@ -182,16 +182,16 @@ export function SegmentDialog({
|
||||
<div className="grid gap-4 md:grid-cols-2">
|
||||
<FormField
|
||||
id="segment-start-km"
|
||||
label="Start (km)"
|
||||
label="Start Chainage"
|
||||
required
|
||||
error={getError('chainage_start_km')}
|
||||
>
|
||||
<Input
|
||||
id="segment-start-km"
|
||||
type="number"
|
||||
step="any"
|
||||
step="1"
|
||||
min="0"
|
||||
placeholder="0.0"
|
||||
placeholder="Enter start chainage"
|
||||
aria-invalid={!!getError('chainage_start_km')}
|
||||
{...register('chainage_start_km')}
|
||||
/>
|
||||
@@ -199,16 +199,16 @@ export function SegmentDialog({
|
||||
|
||||
<FormField
|
||||
id="segment-end-km"
|
||||
label="End (km)"
|
||||
label="End Chainage"
|
||||
required
|
||||
error={getError('chainage_end_km')}
|
||||
>
|
||||
<Input
|
||||
id="segment-end-km"
|
||||
type="number"
|
||||
step="any"
|
||||
step="1"
|
||||
min="0"
|
||||
placeholder="1.0"
|
||||
placeholder="Enter end chainage"
|
||||
aria-invalid={!!getError('chainage_end_km')}
|
||||
{...register('chainage_end_km')}
|
||||
/>
|
||||
@@ -312,7 +312,9 @@ export function SegmentDialog({
|
||||
Cancel
|
||||
</Button>
|
||||
<Button type="submit" disabled={isSaving || !canSubmit}>
|
||||
{isSaving ? <Loader2 className="mr-2 size-4 animate-spin" /> : null}
|
||||
{isSaving ? (
|
||||
<Loader2 className="mr-2 size-4 animate-spin" />
|
||||
) : null}
|
||||
{segmentId ? 'Update Segment' : 'Create Segment'}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
@@ -7,49 +7,32 @@ import { useForm, useWatch } from 'react-hook-form';
|
||||
import { toast } from 'sonner';
|
||||
import { z } from 'zod';
|
||||
|
||||
import {
|
||||
requiredIntegerNumber,
|
||||
requiredLatitude,
|
||||
requiredLongitude,
|
||||
validateChainageRange,
|
||||
} from '@/lib/validation/numberField';
|
||||
import { chainageService } from '@/services/api';
|
||||
import type { Chainage, ChainageCreate, ChainageUpdate } from '@/types';
|
||||
|
||||
import { segmentKeys } from '../queries/segmentKeys';
|
||||
|
||||
const requiredNumber = (message: string) =>
|
||||
z
|
||||
.string()
|
||||
.trim()
|
||||
.min(1, message)
|
||||
.refine((value) => Number.isFinite(Number(value)), {
|
||||
message: 'Enter a valid number',
|
||||
});
|
||||
|
||||
const latitude = requiredNumber('Latitude is required').refine(
|
||||
(value) => {
|
||||
const numberValue = Number(value);
|
||||
return numberValue >= -90 && numberValue <= 90;
|
||||
},
|
||||
{ message: 'Latitude must be between -90 and 90' },
|
||||
);
|
||||
|
||||
const longitude = requiredNumber('Longitude is required').refine(
|
||||
(value) => {
|
||||
const numberValue = Number(value);
|
||||
return numberValue >= -180 && numberValue <= 180;
|
||||
},
|
||||
{ message: 'Longitude must be between -180 and 180' },
|
||||
);
|
||||
|
||||
const segmentFormSchema = z.object({
|
||||
id: z.string().optional(),
|
||||
project_id: z.string().trim().min(1, 'Project is required'),
|
||||
package_id: z.string().trim().min(1, 'Package is required'),
|
||||
segment_name: z.string().trim().min(1, 'Segment name is required'),
|
||||
chainage_start_km: requiredNumber('Start km is required'),
|
||||
chainage_end_km: requiredNumber('End km is required'),
|
||||
start_lat: latitude,
|
||||
start_lng: longitude,
|
||||
end_lat: latitude,
|
||||
end_lng: longitude,
|
||||
direction: z.enum(['UP', 'DOWN']),
|
||||
});
|
||||
const segmentFormSchema = z
|
||||
.object({
|
||||
id: z.string().optional(),
|
||||
project_id: z.string().trim().min(1, 'Project is required'),
|
||||
package_id: z.string().trim().min(1, 'Package is required'),
|
||||
segment_name: z.string().trim().min(1, 'Segment name is required'),
|
||||
chainage_start_km: requiredIntegerNumber('Start km is required'),
|
||||
chainage_end_km: requiredIntegerNumber('End km is required'),
|
||||
start_lat: requiredLatitude,
|
||||
start_lng: requiredLongitude,
|
||||
end_lat: requiredLatitude,
|
||||
end_lng: requiredLongitude,
|
||||
direction: z.enum(['UP', 'DOWN']),
|
||||
})
|
||||
.superRefine(validateChainageRange);
|
||||
|
||||
export type SegmentFormValues = z.infer<typeof segmentFormSchema>;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user