diff --git a/apps/main/src/components/TopBar.tsx b/apps/main/src/components/TopBar.tsx index d7fa8a5..b644f08 100644 --- a/apps/main/src/components/TopBar.tsx +++ b/apps/main/src/components/TopBar.tsx @@ -354,6 +354,17 @@ export function TopBar() { />
+ + + Événements +
diff --git a/apps/main/src/pages/planning.tsx b/apps/main/src/pages/planning.tsx index 94629f1..0d57a64 100644 --- a/apps/main/src/pages/planning.tsx +++ b/apps/main/src/pages/planning.tsx @@ -11,7 +11,7 @@ import { SelectValue, } from "@xtablo/ui/components/select"; import { TypographyH3, TypographyH4 } from "@xtablo/ui/components/typography"; -import { Download, FolderInputIcon, PlusIcon, RefreshCcw } from "lucide-react"; +import { ClockIcon, Download, EllipsisVerticalIcon, FolderInputIcon, MapPinIcon, PlusIcon, RefreshCcw, SlidersHorizontalIcon } from "lucide-react"; import { useCallback, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { Outlet, useNavigate, useParams, useSearchParams } from "react-router-dom"; @@ -39,6 +39,8 @@ export const PlanningPage = () => { const [isImportModalOpen, setIsImportModalOpen] = useState(false); const [isWebcalModalOpen, setIsWebcalModalOpen] = useState(false); const isReadOnly = useIsReadOnlyUser(); + const currentTab = searchParams.get("tab") ?? "calendar"; + const [eventsSearchQuery, setEventsSearchQuery] = useState(""); // Fetch tablos const { data: tablos, isLoading: tablosLoading } = useTablosList(); @@ -789,6 +791,157 @@ export const PlanningPage = () => { ); + // ── Events card view ────────────────────────────────────────────────────── + const renderEventsView = () => { + const q = eventsSearchQuery.toLowerCase(); + const filtered = tabloEvents.filter( + (e) => + !q || + e.title?.toLowerCase().includes(q) || + e.description?.toLowerCase().includes(q) + ); + + const months = ["JAN", "FÉV", "MAR", "AVR", "MAI", "JUN", "JUL", "AOÛ", "SEP", "OCT", "NOV", "DÉC"]; + + return ( +
+ {/* Header */} +
+

+ {t("planning:events", "Événements")} +

+ +
+ + {/* Search + filter */} +
+
+ + + + setEventsSearchQuery(e.target.value)} + className="w-full pl-12 pr-4 py-3 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-xl focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent text-gray-700 dark:text-gray-200" + /> +
+ +
+ + {/* Event cards grid */} + {tabloEventsLoading ? ( +
+ Loading... +
+ ) : filtered.length === 0 ? ( +
+

Aucun événement trouvé

+

+ {eventsSearchQuery ? "Essayez un autre terme" : "Créez votre premier événement"} +

+
+ ) : ( +
+ {filtered.map((event) => { + const date = event.start_date ? new Date(event.start_date + "T00:00:00") : null; + const monthLabel = date ? months[date.getMonth()] : ""; + const dayLabel = date ? String(date.getDate()).padStart(2, "0") : ""; + const timeLabel = event.start_time + ? `${event.start_time.slice(0, 5)}${event.end_time ? ` – ${event.end_time.slice(0, 5)}` : ""}` + : null; + + return ( +
navigate(`/planning/${event.event_id}?tablo_id=${event.tablo_id}`)} + > + + +
+ {/* Date badge */} +
+
+ + {monthLabel} + + + {dayLabel} + +
+
+ + {/* Title + description */} +
+

+ {event.title} +

+ {event.description && ( +

+ {event.description} +

+ )} +
+
+ + {/* Meta */} +
+ {timeLabel && ( +
+ + {timeLabel} +
+ )} + {event.tablo_name && ( +
+ + {event.tablo_name} +
+ )} +
+
+ ); + })} +
+ )} +
+ ); + }; + + if (currentTab === "events") { + return ( +
+ {renderEventsView()} + +
+ ); + } + return (