From 54b4b9fad2f4debcbf7aa1c34512f85439af4fb1 Mon Sep 17 00:00:00 2001 From: Kevin Ressegaire <176156975+earzalien@users.noreply.github.com> Date: Wed, 25 Feb 2026 16:13:52 +0100 Subject: [PATCH 1/8] refactor(trip-ui): enhance accessibility and unify trip components --- client/src/components/TripInfos.tsx | 52 +++--- client/src/pages/TripCard.tsx | 68 ++++---- client/src/pages/TripInvitation.tsx | 90 +++++----- client/src/pages/styles/NavTabs.css | 2 +- client/src/pages/styles/TripCard.css | 84 +++++---- client/src/pages/styles/TripInfos.css | 63 ++----- client/src/pages/styles/TripInvitation.css | 190 +++++++++++---------- 7 files changed, 278 insertions(+), 271 deletions(-) diff --git a/client/src/components/TripInfos.tsx b/client/src/components/TripInfos.tsx index 7407fc6..40968f3 100644 --- a/client/src/components/TripInfos.tsx +++ b/client/src/components/TripInfos.tsx @@ -1,9 +1,9 @@ +import { useState } from "react"; import TripCard from "../pages/TripCard"; import TripInvitation from "../pages/TripInvitation"; import type { TheTrip } from "../types/tripType"; import Modal from "./Modal"; import "../pages/styles/TripInfos.css"; -import { useState } from "react"; type TripInfosProps = { trip: TheTrip | null; @@ -11,15 +11,12 @@ type TripInfosProps = { function TripInfos({ trip }: TripInfosProps) { if (!trip) return null; + const tripId = trip.id; const [isInviteModalOpen, setIsInviteModalOpen] = useState(false); - const openInviteModal = () => { - setIsInviteModalOpen(true); - }; + const openInviteModal = () => setIsInviteModalOpen(true); + const closeInviteModal = () => setIsInviteModalOpen(false); - const closeInviteModal = () => { - setIsInviteModalOpen(false); - }; return ( <>
- {/*
*/} -
-
- {trip && ( + +
+
+
- )} -
+ +
+ - {trip && ( - - )} + ); } + export default TripInfos; diff --git a/client/src/pages/TripCard.tsx b/client/src/pages/TripCard.tsx index 396a8a7..c78393b 100644 --- a/client/src/pages/TripCard.tsx +++ b/client/src/pages/TripCard.tsx @@ -4,13 +4,25 @@ type TripCardProps = { title?: string; city: string; country: string; - startAt: string; - endAt: string; - participants: number | undefined; - role?: "organizer" | "participant"; + startAt?: string | null; + endAt?: string | null; + participants?: number | null; + role?: "organizer" | "participant" | string | null; onInvite?: () => void; }; +function formatDate(dateString?: string | null) { + if (!dateString) return ""; + const date = new Date(dateString); + if (Number.isNaN(date.getTime())) return dateString; + + return new Intl.DateTimeFormat("fr-FR", { + day: "2-digit", + month: "short", + year: "numeric", + }).format(date); +} + function TripCard({ title, city, @@ -18,25 +30,14 @@ function TripCard({ startAt, endAt, participants, - role, onInvite, }: TripCardProps) { - const formatDate = (dateString: string) => { - if (!dateString) return ""; - const date = new Date(dateString); - if (Number.isNaN(date.getTime())) return dateString; - - return new Intl.DateTimeFormat("fr-FR", { - day: "2-digit", - month: "long", - year: "numeric", - }).format(date); - }; - return ( - <> -
-

{title}

+
+
+

+ {title ?? `${city}, ${country}`} +

{onInvite && (
+ +
+ 📍 {city}, {country} +
+ +
+
+ 📅 {formatDate(startAt)} - {formatDate(endAt)} +
+ +
+ 👥 {participants ?? 0} participant + {participants && participants > 1 ? "s" : ""} +
+
+
-

- {city}, {country} -

-

- {formatDate(startAt)} - {formatDate(endAt)} -

-

{participants} participant(s)

-

{role}

-
- ); } diff --git a/client/src/pages/TripInvitation.tsx b/client/src/pages/TripInvitation.tsx index 4953d77..91eb18a 100644 --- a/client/src/pages/TripInvitation.tsx +++ b/client/src/pages/TripInvitation.tsx @@ -2,7 +2,6 @@ import { useState } from "react"; import { useParams } from "react-router"; import { ToastContainer, toast } from "react-toastify"; -import "./styles/Invitation.css"; import "./styles/TripInvitation.css"; type InvitationForm = { @@ -30,6 +29,15 @@ function TripInvitation({ participants, onClose, }: TripInvitationProps) { + const { id } = useParams<{ id: string }>(); + + const [invitationForm, setInvitationForm] = useState({ + email: "", + message: "", + }); + + const [loading, setLoading] = useState(false); + const formatDate = (dateString: string) => { if (!dateString) return ""; const date = new Date(dateString); @@ -41,14 +49,6 @@ function TripInvitation({ year: "numeric", }).format(date); }; - const { id } = useParams<{ id: string }>(); - - const [invitationForm, setInvitationForm] = useState({ - email: "", - message: "", - }); - - const [loading, setLoading] = useState(false); const updateInvitationForm = ( e: React.ChangeEvent, @@ -101,7 +101,6 @@ function TripInvitation({ } await copyToClipboard(data.invitationLink); - setInvitationForm({ email: "", message: "" }); } catch { toast.error("Erreur lors de l'envoi de l'invitation"); @@ -111,38 +110,50 @@ function TripInvitation({ }; return ( - <> -
{}} - > - - -
+
{ + if (e.key === "Escape" && onClose) { + onClose(e as unknown as React.MouseEvent); + } + }} + aria-modal="true" + > + + +
+

- + Inviter un participant

-

Invitez une personne à rejoindre ce voyage par email

-
+ Invitez une personne à rejoindre ce voyage par email + -
+
-
+

{title}

-

- {city}, {country} -

-

- {formatDate(startAt)} - {formatDate(endAt)} -

-

{participants} participant(s)

-
+ +
+ 📍 {city}, {country} +
+ +
+
+ 📅 {formatDate(startAt)} - {formatDate(endAt)} +
+ +
+ 👥 {participants ?? 0} participant + {participants && participants > 1 ? "s" : ""} +
+
+
-