mirror of
https://github.com/TheRealOwenRees/echecsfrance.git
synced 2026-07-23 12:36:57 +00:00
add date picker
This commit is contained in:
@@ -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;
|
||||||
@@ -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
@@ -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),
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user