Skip to content

Commit

Permalink
Enhance dates fields
Browse files Browse the repository at this point in the history
  • Loading branch information
abarghoud committed Jan 8, 2025
1 parent 9fd1b3f commit 22d091e
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 45 deletions.
13 changes: 10 additions & 3 deletions apps/client/src/app/components/form/EventForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Card, CardContent, CardHeader, CardTitle } from '@pps-easy/ui/card';
import { Button } from '@pps-easy/ui/button';
import { EventFormInputField, EventFormSelectField } from './EventFormFields';
import { FormValues } from '../../schema/event-form-schema';
import { addMonths, format } from 'date-fns';

interface EventFormProps {
formMethods: UseFormReturn<FormValues>;
Expand All @@ -16,6 +17,10 @@ export const EventForm: FC<EventFormProps> = ({
isSubmitting,
onSubmit
}) => {
const today = new Date();
const minRaceDate = format(today, 'yyyy-MM-dd');
const maxRaceDate = format(addMonths(today, 3), 'yyyy-MM-dd');

return (
<FormProvider {...formMethods}>
<Card className="w-full max-w-4xl mx-auto min-h-[595px] flex flex-col p-6 bg-card rounded-lg shadow-2xl border-2 border-border overflow-auto">
Expand All @@ -27,15 +32,17 @@ export const EventForm: FC<EventFormProps> = ({
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<EventFormInputField
control={formMethods.control}
isDateField
type='date'
label="Date de naissance"
name="birthday"
placeholder="JJ/MM/AAAA"
/>
<EventFormInputField
control={formMethods.control}
isDateField
label="Date de l'événement"
type='date'
label="Date de la course"
max={maxRaceDate}
min={minRaceDate}
name="eventDate"
placeholder="JJ/MM/AAAA"
/>
Expand Down
24 changes: 11 additions & 13 deletions apps/client/src/app/components/form/EventFormFields.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { FC } from 'react';
import { FC, HTMLInputTypeAttribute, InputHTMLAttributes } from 'react';
import { Control, ControllerRenderProps } from 'react-hook-form';
import { FormField, FormItem, FormLabel, FormControl, FormMessage } from '@pps-easy/ui/form';
import { Input } from '@pps-easy/ui/input';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@pps-easy/ui/select';
import { formatDate } from '../../utils/validators';
import { FormValues } from '../../schema/event-form-schema';

interface InputFieldProps {
control: Control<FormValues>;
isDateField?: boolean;
type?: HTMLInputTypeAttribute;
label: string;
max?: InputHTMLAttributes<HTMLInputElement>['max'];
min?: InputHTMLAttributes<HTMLInputElement>['min'];
name: keyof FormValues;
placeholder: string;
}
Expand All @@ -22,12 +23,12 @@ interface SelectFieldProps {
placeholder: string;
}

const DATE_FIELD_MAX_LENGTH = 10;

export const EventFormInputField: FC<InputFieldProps> = ({
control,
isDateField = false,
type = 'text',
label,
max,
min,
name,
placeholder,
}) => (
Expand All @@ -39,15 +40,12 @@ export const EventFormInputField: FC<InputFieldProps> = ({
<FormLabel className="text-sm font-medium text-foreground">{label}</FormLabel>
<FormControl>
<Input
className="py-2 px-3 border border-border rounded-md focus:outline-none focus:ring focus:ring-primary transition duration-150 ease-in-out"
placeholder={placeholder}
type={type}
max={max}
min={min}
{...field}
value={field.value || ""}
onChange={(event) => {
const newValue = event.target.value;
field.onChange(isDateField ? formatDate(newValue) : newValue);
}}
maxLength={isDateField ? DATE_FIELD_MAX_LENGTH : undefined}
className="py-2 px-3 border border-border rounded-md focus:outline-none focus:ring focus:ring-primary transition duration-150 ease-in-out"
/>
</FormControl>
<FormMessage className="text-red-500 text-xs mt-1" />
Expand Down
21 changes: 10 additions & 11 deletions apps/client/src/app/schema/event-form-schema.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import * as z from 'zod';
import { isValidEventDate, isValidEmail } from '../utils/validators';
import { isValidEmail } from '../utils/validators';
import { addMonths, isAfter, isBefore, startOfDay } from 'date-fns';

export const eventFormSchema = z.object({
birthday: z.string().refine(
(value) => isValidEventDate(value) &&
new Date(value.split("/").reverse().join("-")) <= new Date() &&
new Date(value.split("/").reverse().join("-")) >= new Date("1900-01-01"),
{ message: "Veuillez entrer une date de naissance valide au format JJ/MM/AAAA." }
),
eventDate: z.string().refine(
(value) => isValidEventDate(value) && new Date(value.split("/").reverse().join("-")) >= new Date(),
{ message: "Veuillez entrer une date d'événement valide au format JJ/MM/AAAA jusqu'à 3 mois à venir." }
),
birthday: z.string().min(1, 'La date de naissance est requise'),
eventDate: z.string().min(1, "La date de la course est requise").refine((date) => {
const selectedDate = startOfDay(new Date(date));
const today = startOfDay(new Date());
const threeMonthsFromNow = startOfDay(addMonths(today, 3));

return !isAfter(selectedDate, threeMonthsFromNow) && !isBefore(selectedDate, today);
}, 'La date de la course doit être dans les 3 mois à venir'),
email: z.string().refine(isValidEmail, {
message: "Veuillez entrer une adresse email valide.",
}),
Expand Down
5 changes: 2 additions & 3 deletions apps/client/src/app/service/event-form-service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { IEventFormService } from './event-form-service.requirements';
import { IPPSCertificateApiService } from '../api/pps-certificate-service.requirements';
import { FormValues } from '../schema/event-form-schema';
import { formatToISODate } from '../utils/validators';

export class EventFormService implements IEventFormService {
private api: IPPSCertificateApiService;
Expand Down Expand Up @@ -45,9 +44,9 @@ export class EventFormService implements IEventFormService {

private transformFormValuesToRequestPayload(values: FormValues) {
return {
birthday: formatToISODate(values.birthday),
birthday: values.birthday,
email: values.email,
event_date: formatToISODate(values.eventDate),
event_date: values.eventDate,
firstname: values.firstname,
gender: values.gender === 'homme' ? 'male' : 'female',
lastname: values.lastname,
Expand Down
15 changes: 0 additions & 15 deletions apps/client/src/app/utils/validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,4 @@ export const isValidEventDate = (dateString: string): boolean => {
return false;
};


export const isValidEmail = (email: string): boolean => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);

export const formatToISODate = (dateString: string): string => {
const [day, month, year] = dateString.split("/");
return `${year}-${month}-${day}`;
};

export const formatDate = (value: string): string => {
const cleaned = value.replace(/\D/g, "");

if (cleaned.length === 0) return "";
if (cleaned.length <= 2) return cleaned;
if (cleaned.length <= 4) return `${cleaned.slice(0, 2)}/${cleaned.slice(2)}`;
return `${cleaned.slice(0, 2)}/${cleaned.slice(2, 4)}/${cleaned.slice(4, 8)}`;
};

0 comments on commit 22d091e

Please sign in to comment.