♻️(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:
@@ -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";
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ export const HeaderIcon = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const HeaderRight = () => {
|
export const HeaderRight = () => {
|
||||||
const { user } = useAuth();
|
|
||||||
const { isTablet } = useResponsive();
|
const { isTablet } = useResponsive();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -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";
|
||||||
|
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: hidden;
|
// overflow: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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={
|
||||||
|
|||||||
@@ -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{
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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">;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user