add date picker

This commit is contained in:
2025-12-10 15:36:47 +01:00
parent 17ab80cac9
commit 1ec15179b7
4 changed files with 106 additions and 16 deletions
@@ -0,0 +1,57 @@
import { useState } from "react";
import { format } from "date-fns";
import { fr } from "date-fns/locale";
import { Calendar } from "react-date-range";
import "react-date-range/dist/styles.css";
// main style file
import "react-date-range/dist/theme/default.css";
import { Control, useController } from "react-hook-form";
// theme css file
interface DateCalendarProps {
control: Control<any>;
name: string;
label?: string;
}
const DateCalendar = ({ control, name, label }: DateCalendarProps) => {
const {
field: { value, onChange },
} = useController({
name,
control,
});
const [open, setOpen] = useState(false);
const handleSelect = (newDate: Date) => {
onChange(newDate);
setOpen(false);
};
return (
<div className="relative w-full">
{label && (
<label className="mb-2 block text-sm font-medium text-gray-900">
{label}
</label>
)}
<input
readOnly
className="w-full rounded-md border border-gray-300 bg-white px-3 py-2 text-sm shadow-sm focus:border-b-blue-300 focus:outline-none focus:ring-1 focus:ring-blue-300"
value={value ? format(value, "dd/MM/yyyy", { locale: fr }) : ""}
onClick={() => setOpen((prev) => !prev)}
placeholder="Sélectionner une date"
/>
{open && (
<div className="absolute z-10 mt-1 translate-x-[-50%] transform bg-white shadow-lg md:translate-x-0">
<Calendar onChange={handleSelect} date={value} locale={fr} />
</div>
)}
</div>
);
};
export default DateCalendar;
+34 -2
View File
@@ -4,7 +4,9 @@ import { zodResolver } from "@hookform/resolvers/zod";
import { FormProvider, useForm } from "react-hook-form"; import { FormProvider, useForm } from "react-hook-form";
import { z } from "zod"; import { z } from "zod";
import Calendar from "@/app/[locale]/(main)/components/Calendar";
import TeamSelection from "@/app/[locale]/(main)/match/components/TeamSelection"; import TeamSelection from "@/app/[locale]/(main)/match/components/TeamSelection";
import { TextField } from "@/components/form/TextField";
import { matchSchema } from "@/schemas"; import { matchSchema } from "@/schemas";
import { Club } from "@/types"; import { Club } from "@/types";
@@ -34,7 +36,7 @@ const MatchForm = ({ clubs }: IProps) => {
// message: t("success"), // message: t("success"),
// }); // });
form.reset(); // form.reset(); // do not reset the form
} catch (err: unknown) { } catch (err: unknown) {
console.log(err); console.log(err);
// //
@@ -54,16 +56,46 @@ const MatchForm = ({ clubs }: IProps) => {
return ( return (
<FormProvider {...form}> <FormProvider {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="w-3/4 space-y-8"> <form onSubmit={form.handleSubmit(onSubmit)} className="w-3/4 space-y-8">
<div className="grid grid-cols-4 items-start gap-6"> <div className="grid grid-cols-6 items-start gap-6">
<div className="col-span-1">
<Calendar name="date" control={form.control} label="Date" />
</div>
<div className="col-span-2">
<TextField
name="competition"
control={form.control}
label="Competition"
required
/>
</div>
<div className="col-span-1">
<TextField
name="ronde"
control={form.control}
label="Ronde"
type="number"
required
/>
</div>
<div className="col-span-2">
<TextField
name="lieu"
control={form.control}
label="Lieu"
required
/>
</div>
<TeamSelection <TeamSelection
clubOptions={clubOptions} clubOptions={clubOptions}
name="team1" name="team1"
label="Team 1" label="Team 1"
className="col-span-3 space-y-4"
/> />
<TeamSelection <TeamSelection
clubOptions={clubOptions} clubOptions={clubOptions}
name="team2" name="team2"
label="Team 2" label="Team 2"
className="col-span-3 space-y-4"
/> />
</div> </div>
<button type="submit">Submit</button> <button type="submit">Submit</button>
@@ -18,6 +18,7 @@ import { fetchClubPlayers } from "@/server/fetchClubPlayers";
interface IProps { interface IProps {
name: string; name: string;
label: string; label: string;
className?: string;
clubOptions: { clubOptions: {
value: string; value: string;
label: string; label: string;
@@ -25,7 +26,7 @@ interface IProps {
}[]; }[];
} }
const TeamSelection = ({ name, label, clubOptions }: IProps) => { const TeamSelection = ({ name, label, clubOptions, className }: IProps) => {
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const { control } = useFormContext(); const { control } = useFormContext();
@@ -81,7 +82,7 @@ const TeamSelection = ({ name, label, clubOptions }: IProps) => {
})) || []; })) || [];
return ( return (
<div className="col-span-2 space-y-4"> <div className={className}>
<label className="mb-2 block text-sm font-medium text-gray-900"> <label className="mb-2 block text-sm font-medium text-gray-900">
{label} {label}
</label> </label>
+12 -12
View File
@@ -60,23 +60,23 @@ export const zoneSchema = z
path: ["features"], path: ["features"],
}); });
// export const fetchClubPlayersSchema = z.array(
// z.object({
// nrFFE: z.string(),
// name: z.string(),
// elo: z.string(),
// elo_rapid: z.string(),
// elo_blitz: z.string(),
// category: z.string(),
// club: z.string(),
// }),
// );
export const fetchClubPlayersSchema = z.object({ export const fetchClubPlayersSchema = z.object({
clubId: z.string(), clubId: z.string(),
}); });
const matchPlayerSchema = z.object({
name: z.string(),
elo: z.string(),
nrFFE: z.string(),
});
export const matchSchema = z.object({ export const matchSchema = z.object({
competition: z.string(),
date: z.string(),
ronde: z.number(),
lieu: z.string(),
team1: z.string(), team1: z.string(),
team2: z.string(), team2: z.string(),
team1_players: z.array(matchPlayerSchema),
team2_players: z.array(matchPlayerSchema),
}); });