♻️(front) update pages and app structure

Update calendar page to use new Scheduler and CalendarContext.
Update styles, error pages, and app wrapper for new components.
Minor updates to Header, Toaster and Feedback components.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Nathan Panchout
2026-01-25 20:35:43 +01:00
parent 48062a9988
commit afb4e35b1d
12 changed files with 44 additions and 76 deletions

View File

@@ -5,7 +5,7 @@ import {
Modal, Modal,
ModalSize, ModalSize,
useModal, useModal,
} from "@openfun/cunningham-react"; } from "@gouvfr-lasuite/cunningham-react";
import React, { useMemo } from "react"; import React, { useMemo } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useConfig } from "../config/ConfigProvider"; import { useConfig } from "../config/ConfigProvider";

View File

@@ -17,7 +17,6 @@ export const HeaderIcon = () => {
}; };
export const HeaderRight = () => { export const HeaderRight = () => {
const { user } = useAuth();
const { isTablet } = useResponsive(); const { isTablet } = useResponsive();
return ( return (

View File

@@ -1,4 +1,4 @@
import { Button } from "@openfun/cunningham-react"; import { Button } from "@gouvfr-lasuite/cunningham-react";
import clsx from "clsx"; import clsx from "clsx";
import { ToastContainer, ToastContentProps, toast } from "react-toastify"; import { ToastContainer, ToastContentProps, toast } from "react-toastify";

View File

@@ -1,7 +1,7 @@
import { login } from "@/features/auth/Auth"; import { login } from "@/features/auth/Auth";
import { getSimpleLayout } from "@/features/layouts/components/simple/SimpleLayout"; import { getSimpleLayout } from "@/features/layouts/components/simple/SimpleLayout";
import { GenericDisclaimer } from "@/features/ui/components/generic-disclaimer/GenericDisclaimer"; import { GenericDisclaimer } from "@/features/ui/components/generic-disclaimer/GenericDisclaimer";
import { Button } from "@openfun/cunningham-react"; import { Button } from "@gouvfr-lasuite/cunningham-react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
export default function UnauthorizedPage() { export default function UnauthorizedPage() {

View File

@@ -1,7 +1,7 @@
import { getSimpleLayout } from "@/features/layouts/components/simple/SimpleLayout"; import { getSimpleLayout } from "@/features/layouts/components/simple/SimpleLayout";
import { GenericDisclaimer } from "@/features/ui/components/generic-disclaimer/GenericDisclaimer"; import { GenericDisclaimer } from "@/features/ui/components/generic-disclaimer/GenericDisclaimer";
import { Icon } from "@gouvfr-lasuite/ui-kit"; import { Icon } from "@gouvfr-lasuite/ui-kit";
import { Button } from "@openfun/cunningham-react"; import { Button } from "@gouvfr-lasuite/cunningham-react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
export default function UnauthorizedPage() { export default function UnauthorizedPage() {

View File

@@ -1,15 +1,12 @@
import { import {
createContext, createContext,
useContext, useContext, useState,
useMemo,
useState,
type ReactElement, type ReactElement,
type ReactNode, type ReactNode
} from "react"; } from "react";
import type { NextPage } from "next"; import type { NextPage } from "next";
import type { AppProps } from "next/app"; import type { AppProps } from "next/app";
import { CunninghamProvider } from "@gouvfr-lasuite/ui-kit"; import { CunninghamProvider } from "@gouvfr-lasuite/ui-kit";
import { ModalProvider } from "@openfun/cunningham-react";
import { import {
MutationCache, MutationCache,
Query, Query,
@@ -34,9 +31,7 @@ import {
removeQuotes, removeQuotes,
useCunninghamTheme, useCunninghamTheme,
} from "@/features/ui/cunningham/useCunninghamTheme"; } from "@/features/ui/cunningham/useCunninghamTheme";
import { ResponsiveDivs } from "@/features/ui/components/responsive/ResponsiveDivs";
import { FeedbackFooterMobile } from "@/features/feedback/Feedback"; import { FeedbackFooterMobile } from "@/features/feedback/Feedback";
import { useRouter } from "next/router";
export type NextPageWithLayout<P = object, IP = P> = NextPage<P, IP> & { export type NextPageWithLayout<P = object, IP = P> = NextPage<P, IP> & {
getLayout?: (page: ReactElement) => ReactNode; getLayout?: (page: ReactElement) => ReactNode;
@@ -119,7 +114,6 @@ const MyAppInner = ({ Component, pageProps }: AppPropsWithLayout) => {
const getLayout = Component.getLayout ?? ((page) => page); const getLayout = Component.getLayout ?? ((page) => page);
const { t, i18n } = useTranslation(); const { t, i18n } = useTranslation();
const { theme } = useAppContext(); const { theme } = useAppContext();
const router = useRouter();
const themeTokens = useCunninghamTheme(); const themeTokens = useCunninghamTheme();
return ( return (
@@ -137,15 +131,14 @@ const MyAppInner = ({ Component, pageProps }: AppPropsWithLayout) => {
currentLocale={capitalizeRegion(i18n.language)} currentLocale={capitalizeRegion(i18n.language)}
theme={theme} theme={theme}
> >
<ModalProvider>
<ConfigProvider> <ConfigProvider>
<AnalyticsProvider> <AnalyticsProvider>
{getLayout(<Component {...pageProps} />)} {getLayout(<Component {...pageProps} />)}
<ResponsiveDivs />
<FeedbackFooterMobile /> <FeedbackFooterMobile />
</AnalyticsProvider> </AnalyticsProvider>
</ConfigProvider> </ConfigProvider>
</ModalProvider>
</CunninghamProvider> </CunninghamProvider>
</QueryClientProvider> </QueryClientProvider>
</> </>

View File

@@ -19,7 +19,7 @@
flex: 1; flex: 1;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow: hidden; // overflow: hidden;
} }
} }

View File

@@ -2,53 +2,42 @@
* Calendar page - Main calendar view with sidebar. * Calendar page - Main calendar view with sidebar.
*/ */
import { useCallback, useState } from "react"; import { useCallback } from "react";
import { MainLayout } from "@gouvfr-lasuite/ui-kit"; import { MainLayout } from "@gouvfr-lasuite/ui-kit";
import Head from "next/head"; import Head from "next/head";
import { useTranslation } from "next-i18next"; import { useTranslation } from "next-i18next";
import { login, useAuth } from "@/features/auth/Auth"; import { login, useAuth } from "@/features/auth/Auth";
import { CalendarView, LeftPanel } from "@/features/calendar/components"; import { LeftPanel } from "@/features/calendar/components";
import { useCreateCalendarModal } from "@/features/calendar/components/CreateCalendarModal";
import { useCreateEventModal } from "@/features/calendar/hooks/useCreateEventModal";
import { useCalendars } from "@/features/calendar/hooks/useCalendars"; import { useCalendars } from "@/features/calendar/hooks/useCalendars";
import { GlobalLayout } from "@/features/layouts/components/global/GlobalLayout"; import { GlobalLayout } from "@/features/layouts/components/global/GlobalLayout";
import { HeaderRight } from "@/features/layouts/components/header/Header"; import { HeaderRight } from "@/features/layouts/components/header/Header";
import { SpinnerPage } from "@/features/ui/components/spinner/SpinnerPage"; import { SpinnerPage } from "@/features/ui/components/spinner/SpinnerPage";
import { Toaster } from "@/features/ui/components/toaster/Toaster"; import { Toaster } from "@/features/ui/components/toaster/Toaster";
import { Scheduler } from "@/features/calendar/components/scheduler/Scheduler";
import { CalendarContextProvider, useCalendarContext } from "@/features/calendar/contexts";
export default function CalendarPage() { export default function CalendarPage() {
const { t } = useTranslation(); const { t } = useTranslation();
const { user } = useAuth(); const { user } = useAuth();
// Calendar state // Use selectedDate from context (the specific day user has clicked/selected)
const [selectedDate, setSelectedDate] = useState(new Date()); // Note: currentDate (for view sync) is used directly by MiniCalendar
const { selectedDate, setSelectedDate } = useCalendarContext();
// Fetch calendars for the sidebar // Fetch calendars for the sidebar
const { data: calendars = [], isLoading: isLoadingCalendars } = useCalendars(); const { data: calendars = [] } = useCalendars();
// Create calendar modal
const createCalendarModal = useCreateCalendarModal();
// Create event modal
const createEventModal = useCreateEventModal({
calendars: calendars || [],
selectedDate
});
// Handlers // Handlers
const handleDateSelect = useCallback((date: Date) => { const handleDateSelect = useCallback((date: Date) => {
setSelectedDate(date); setSelectedDate(date);
}, []); }, [setSelectedDate]);
const handleCreateEvent = useCallback(() => { const handleCreateEvent = useCallback(() => {
createEventModal.open(); console.log("handleCreateEvent");
}, [createEventModal]); }, []);
const handleCreateCalendar = useCallback(() => {
createCalendarModal.open();
}, [createCalendarModal]);
// Redirect to login if not authenticated // Redirect to login if not authenticated
if (!user) { if (!user) {
@@ -67,26 +56,24 @@ export default function CalendarPage() {
<link rel="icon" href="/favicon.png" /> <link rel="icon" href="/favicon.png" />
</Head> </Head>
<div className="calendar-page">
<div className="calendar-page__sidebar"> <div className="calendar-page">
<LeftPanel <div className="calendar-page__sidebar">
calendars={calendars} <LeftPanel
selectedDate={selectedDate} calendars={calendars}
onDateSelect={handleDateSelect} selectedDate={selectedDate}
onCreateEvent={handleCreateEvent} onDateSelect={handleDateSelect}
onCreateCalendar={handleCreateCalendar} onCreateEvent={handleCreateEvent}
/> />
</div>
<div className="calendar-page__main">
<Scheduler />
</div>
</div> </div>
<div className="calendar-page__main">
<CalendarView
selectedDate={selectedDate}
onSelectDate={handleDateSelect}
/>
</div>
</div>
{createCalendarModal.Modal}
{createEventModal.Modal}
<Toaster /> <Toaster />
</> </>
); );
@@ -94,6 +81,7 @@ export default function CalendarPage() {
CalendarPage.getLayout = function getLayout(page: React.ReactElement) { CalendarPage.getLayout = function getLayout(page: React.ReactElement) {
return ( return (
<CalendarContextProvider>
<div className="calendars__calendar"> <div className="calendars__calendar">
<GlobalLayout> <GlobalLayout>
<MainLayout <MainLayout
@@ -111,5 +99,6 @@ CalendarPage.getLayout = function getLayout(page: React.ReactElement) {
</MainLayout> </MainLayout>
</GlobalLayout> </GlobalLayout>
</div> </div>
</CalendarContextProvider>
); );
}; };

View File

@@ -11,7 +11,7 @@ import {
Toaster, Toaster,
ToasterItem, ToasterItem,
} from "@/features/ui/components/toaster/Toaster"; } from "@/features/ui/components/toaster/Toaster";
import { Button } from "@openfun/cunningham-react"; import { Button } from "@gouvfr-lasuite/cunningham-react";
import { useConfig } from "@/features/config/ConfigProvider"; import { useConfig } from "@/features/config/ConfigProvider";
import { LeftPanelMobile } from "@/features/layouts/components/left-panel/LeftPanelMobile"; import { LeftPanelMobile } from "@/features/layouts/components/left-panel/LeftPanelMobile";
import { SESSION_STORAGE_REDIRECT_AFTER_LOGIN_URL } from "@/features/api/fetchApi"; import { SESSION_STORAGE_REDIRECT_AFTER_LOGIN_URL } from "@/features/api/fetchApi";
@@ -77,7 +77,7 @@ export default function HomePage() {
<HomeGutter> <HomeGutter>
<Hero <Hero
logo={<div className="calendars__logo-icon" />} logo={<div className="calendars__logo-icon" />}
/* banner={banner.src} */ banner={banner.src}
title={t("home.title")} title={t("home.title")}
subtitle={t("home.subtitle")} subtitle={t("home.subtitle")}
mainButton={ mainButton={

View File

@@ -663,7 +663,7 @@
--c--components--gaufre--widgetpath: 'https://static.suite.anct.gouv.fr/widgets/lagaufre.js'; --c--components--gaufre--widgetpath: 'https://static.suite.anct.gouv.fr/widgets/lagaufre.js';
--c--components--gaufre--apiurl: 'https://lasuite.numerique.gouv.fr/api/services'; --c--components--gaufre--apiurl: 'https://lasuite.numerique.gouv.fr/api/services';
--c--components--favicon--src: '/assets/favicon.png'; --c--components--favicon--src: '/assets/favicon.png';
--c--components--logo--src: url('/assets/logo_alpha.svg'); --c--components--logo--src: url('/assets/logo_beta.svg');
--c--components--logo-icon--src: url('/assets/logo-icon_beta.svg'); --c--components--logo-icon--src: url('/assets/logo-icon_beta.svg');
} }
.cunningham-theme--dark{ .cunningham-theme--dark{

View File

@@ -4,20 +4,17 @@
@use "./../features/layouts/components/global/GlobalLayout.scss"; @use "./../features/layouts/components/global/GlobalLayout.scss";
@use "./../features/feedback/Feedback.scss"; @use "./../features/feedback/Feedback.scss";
@use "./../features/layouts/components/header/index.scss"; @use "./../features/layouts/components/header/index.scss";
@use "./../features/ui/components/breadcrumbs";
@use "./../features/ui/components/toaster"; @use "./../features/ui/components/toaster";
@use "./../features/ui/components/generic-disclaimer/GenericDisclaimer.scss"; @use "./../features/ui/components/generic-disclaimer/GenericDisclaimer.scss";
@use "./../features/ui/components/info/InfoRow.scss";
@use "./../features/ui/components/responsive";
@use "./../features/ui/components/spinner/SpinnerPage.scss"; @use "./../features/ui/components/spinner/SpinnerPage.scss";
@use "./../features/ui/components/infinite-scroll/InfiniteScroll.scss";
@use "./../features/layouts/components/left-panel/LeftPanelMobile.scss"; @use "./../features/layouts/components/left-panel/LeftPanelMobile.scss";
@use "./../features/calendar/components/MiniCalendar.scss"; @use "./../features/calendar/components/MiniCalendar.scss";
@use "./../features/calendar/components/CalendarList.scss"; @use "./../features/calendar/components/CalendarList.scss";
@use "./../features/calendar/components/LeftPanel.scss"; @use "./../features/calendar/components/LeftPanel.scss";
@use "./../features/calendar/components/CalendarView.scss";
@use "./../features/calendar/components/EventModal.scss"; @use "./../features/calendar/components/EventModal.scss";
@use "./../features/calendar/components/RecurrenceEditor.scss"; @use "./../features/calendar/components/RecurrenceEditor.scss";
@use "./../features/calendar/components/AttendeesInput.scss";
@use "./../features/calendar/components/scheduler/Scheduler.scss";
@use "./../pages/index.scss" as *; @use "./../pages/index.scss" as *;
@use "./../pages/calendar.scss" as *; @use "./../pages/calendar.scss" as *;
html, html,
@@ -77,7 +74,5 @@ body {
.c__datagrid--empty, .c__datagrid--empty,
.c__datagrid thead { .c__datagrid thead {
transition: transition: background-color 0.3s ease, box-shadow 0.3s ease;
background-color 0.3s ease,
box-shadow 0.3s ease;
} }

View File

@@ -1,12 +1,4 @@
import { UseQueryOptions } from "@tanstack/react-query"; import { UseQueryOptions } from "@tanstack/react-query";
export type HookUseQueryOptions2 = {
enabled?: boolean;
}
export type HookUseQueryOptions<T> = Omit<UseQueryOptions<T>, "queryKey" | "queryFn">; export type HookUseQueryOptions<T> = Omit<UseQueryOptions<T>, "queryKey" | "queryFn">;