From 627a193ec27a1e9026147e23c6114638010ac64d Mon Sep 17 00:00:00 2001 From: alexandre Date: Sat, 9 Dec 2023 11:06:39 +0100 Subject: [PATCH 1/3] Add reusable filter container --- app/dossiers/dossier/page.tsx | 6 --- components/FilterContainer.tsx | 64 +++++++++++++++++++++++++++++++ components/ThemeRegistry/theme.ts | 10 +---- 3 files changed, 66 insertions(+), 14 deletions(-) create mode 100644 components/FilterContainer.tsx diff --git a/app/dossiers/dossier/page.tsx b/app/dossiers/dossier/page.tsx index 8afe3f5..57dd19b 100644 --- a/app/dossiers/dossier/page.tsx +++ b/app/dossiers/dossier/page.tsx @@ -10,12 +10,6 @@ import { HeroSection } from "@/components/folders/HeroSection"; import { PreviewTab } from "@/components/folders/PreviewTab"; import { DebateTab } from "@/components/folders/DebateTab"; -interface TabPanelProps { - children?: React.ReactNode; - index: number; - value: number; -} - export default function Dossier() { const [tabNumber, setTabNumber] = React.useState(0); diff --git a/components/FilterContainer.tsx b/components/FilterContainer.tsx new file mode 100644 index 0000000..404ebec --- /dev/null +++ b/components/FilterContainer.tsx @@ -0,0 +1,64 @@ +import * as React from "react"; + +import Accordion from "@mui/material/Accordion"; +import AccordionSummary from "@mui/material/AccordionSummary"; +import AccordionDetails from "@mui/material/AccordionDetails"; +import Typography from "@mui/material/Typography"; +import Stack from "@mui/material/Stack"; + +import TuneIcon from "@mui/icons-material/Tune"; + +import { MinusIcon } from "@/icons/MinusIcon"; +import { useTheme } from "@mui/material/styles"; +import useMediaQuery from "@mui/material/useMediaQuery"; +import { Paper } from "@mui/material"; + +export const FilterContainer = ({ + children, + disableCollapse: disableCollapseProps, +}: React.PropsWithChildren<{ disableCollapse?: boolean }>) => { + const theme = useTheme(); + const isDesktop = useMediaQuery(theme.breakpoints.up("md")); + + const disableCollapse = + disableCollapseProps === undefined ? isDesktop : disableCollapseProps; + + if (disableCollapse) { + return ( + + + + Filter + + + {children} + + + ); + } + return ( + + } + aria-controls="commission-content" + id="commission-header" + > + + Filter + + + + {children} + + + + ); +}; diff --git a/components/ThemeRegistry/theme.ts b/components/ThemeRegistry/theme.ts index 2de40ff..ac82b0a 100644 --- a/components/ThemeRegistry/theme.ts +++ b/components/ThemeRegistry/theme.ts @@ -108,14 +108,8 @@ const theme = createTheme({ styleOverrides: { root: ({ ownerState }) => ({ borderRadius: "4px", - "& .MuiAccordionSummary-root": { - backgroundColor: - ownerState.color === "secondary" ? "#F8F9FA" : "#FFFFFF", - }, - "& .MuiCollapse-root": { - backgroundColor: - ownerState.color === "secondary" ? "#F8F9FA" : "#FFFFFF", - }, + backgroundColor: + ownerState.color === "secondary" ? "#F8F9FA" : "#FFFFFF", "&:before": { display: "none", }, From 407932029c7c53280735addd2a038ebe8df5bf7e Mon Sep 17 00:00:00 2001 From: alexandre Date: Sat, 9 Dec 2023 15:06:09 +0100 Subject: [PATCH 2/3] Start dossier home page --- app/dossiers/page.tsx | 42 +++- components/const.ts | 15 ++ components/folderHomePage/DossierList.tsx | 230 ++++++++++++++++++++++ components/folderHomePage/Filter.tsx | 39 ++++ 4 files changed, 323 insertions(+), 3 deletions(-) create mode 100644 components/folderHomePage/DossierList.tsx create mode 100644 components/folderHomePage/Filter.tsx diff --git a/app/dossiers/page.tsx b/app/dossiers/page.tsx index 5bb3282..0146758 100644 --- a/app/dossiers/page.tsx +++ b/app/dossiers/page.tsx @@ -1,6 +1,42 @@ -import Link from "next/link"; +"use client"; + +import React from "react"; +import Container from "@mui/material/Container"; +import Stack from "@mui/material/Stack"; + +import { FilterContainer } from "@/components/FilterContainer"; + +import { DossierFilterState, Filter } from "@/components/folderHomePage/Filter"; +import DossierList from "@/components/folderHomePage/DossierList"; export default function Dossiers() { - // TODO: match old website url ":id/dossiers/:id" - return Lien vers un dossier; + const [filterState, setFilterState] = React.useState({ + theme: "", + }); + + return ( + + + + + + + + + + + ); } diff --git a/components/const.ts b/components/const.ts index 5276d5c..227dac5 100644 --- a/components/const.ts +++ b/components/const.ts @@ -67,3 +67,18 @@ export const partis: Record = { fullName: "Députés Non Inscrit", }, }; + +export type ThemeKeys = + | "Environement" + | "Transport" + | "Défense" + | "Agriculture" + | "Economie"; + +export const THEMES: ThemeKeys[] = [ + "Environement", + "Transport", + "Défense", + "Agriculture", + "Economie", +]; diff --git a/components/folderHomePage/DossierList.tsx b/components/folderHomePage/DossierList.tsx new file mode 100644 index 0000000..71ae5eb --- /dev/null +++ b/components/folderHomePage/DossierList.tsx @@ -0,0 +1,230 @@ +import * as React from "react"; +import { Divider, Stack } from "@mui/material"; +import Typography from "@mui/material/Typography"; +import Link from "next/link"; +import { DossierFilterState } from "./Filter"; +import { ThemeKeys } from "../const"; +import LabelChip from "../LabelChip"; + +type DossierType = { + date: string; + id: string | number; + title: string; + theme: ThemeKeys; +}; +type MonthDossier = { date: string; dossiers: DossierType[] }; + +const dossiers: DossierType[] = [ + { + date: "2024-11-01", + id: 0, + title: `Souhaits de bienvenue à une députée nouvellement élue`, + theme: "Transport", + }, + { + date: "2024-11-01", + id: 1, + title: `Écoles nationales d'architecture`, + theme: "Transport", + }, + { + date: "2024-11-01", + id: 2, + title: `Orientation et programmation du ministère de la justice 2023-2027 `, + theme: "Transport", + }, + { + date: "2024-11-01", + id: 3, + title: `Interdiction de l'écriture dite inclusive`, + theme: "Transport", + }, + { + date: "2024-11-01", + id: 4, + title: `Crise de l'hôpital public`, + theme: "Transport", + }, + { + date: "2024-11-01", + id: 5, + title: `Avenant au protocole d'accord france-luxembourg `, + theme: "Transport", + }, + { + date: "2024-11-01", + id: 6, + title: `Débat sur la dette`, + theme: "Transport", + }, + { + date: "2024-11-01", + id: 7, + title: `Convocation du parlement en session extraordinaire`, + theme: "Transport", + }, + { + date: "2024-11-01", + id: 8, + title: `Modernisation et responsabilité du corps judiciaire `, + theme: "Transport", + }, + { + date: "2024-11-01", + id: 9, + title: `Questions orales sans débat (1082 interventions, 3 commentaires)`, + theme: "Transport", + }, + { + date: "2024-11-01", + id: 10, + title: `Orientation et programmation du ministère de la justice 2023-2027 - modernisation et responsabilité du corps judiciaire`, + theme: "Transport", + }, + { + date: "2024-11-01", + id: 11, + title: `Hommage à léon gautier`, + theme: "Transport", + }, + { + date: "2024-11-01", + id: 12, + title: `Lutte contre les arnaques et les dérives des influenceurs sur les réseaux sociaux`, + theme: "Transport", + }, + + { + date: "2024-10-01", + id: 13, + title: `Accompagnement des élus locaux dans la lutte contre l'artificialisation des sols`, + theme: "Transport", + }, + { + date: "2024-10-01", + id: 14, + title: `Hommage au professeur tué à arras `, + theme: "Transport", + }, + { + date: "2024-10-01", + id: 15, + title: `Explosion dans le 5e arrondissement`, + theme: "Transport", + }, + { + date: "2024-10-01", + id: 16, + title: `Discussion d'une proposition de loi`, + theme: "Transport", + }, + { + date: "2024-10-01", + id: 17, + title: `Lutte contre l'inflation concernant les produits de grande consommation `, + theme: "Transport", + }, + { + date: "2024-10-01", + id: 18, + title: `Soutien à israel face au terrorisme`, + theme: "Transport", + }, + { + date: "2024-10-01", + id: 19, + title: `Solution à deux États et condamnation de l'institutionnalisation par l'État d'israel d'un régime d'apartheid`, + theme: "Transport", + }, + { + date: "2024-10-01", + id: 20, + title: `Sécuriser et réguler l'espace numérique `, + theme: "Transport", + }, + { + date: "2024-10-01", + id: 21, + title: `Ouverture de la session ordinaire`, + theme: "Transport", + }, + { + date: "2024-10-01", + id: 22, + title: `Inscrire le groupe militaire privé wagner sur la liste des organisations terroristes`, + theme: "Transport", + }, +]; + +const dossierMensuels = dossiers + .sort((a, b) => (a.date < b.date ? 1 : -1)) + .reduce((acc, val) => { + if ( + acc.length === 0 || + acc[acc.length - 1].date.slice(0, 7) !== val.date.slice(0, 7) + ) { + return [...acc, { date: `${val.date.slice(0, 7)}-01`, dossiers: [val] }]; + } + return [ + ...acc.slice(0, acc.length - 1), + { + ...acc[acc.length - 1], + dossiers: [...acc[acc.length - 1].dossiers, val], + }, + ]; + }, [] as MonthDossier[]); + +type DossierListProps = { + filterState: DossierFilterState; + setFilterState: React.Dispatch>; +}; + +export default function DossierList(props: DossierListProps) { + return ( +
+ + {dossierMensuels.map(({ date, dossiers }) => ( + + + {new Date(date).toLocaleDateString("fr-FR", { + year: "numeric", + month: "long", + })} + + + + {dossiers.map(({ id, title, theme }) => ( + + + {title} + + + + + ))} + + + ))} + +
+ ); +} diff --git a/components/folderHomePage/Filter.tsx b/components/folderHomePage/Filter.tsx new file mode 100644 index 0000000..d795064 --- /dev/null +++ b/components/folderHomePage/Filter.tsx @@ -0,0 +1,39 @@ +import MenuItem from "@mui/material/MenuItem"; +import TextField from "@mui/material/TextField"; +import { THEMES } from "../const"; + +export type DossierFilterState = { + theme: string; +}; + +type FilterProps = { + filterState: DossierFilterState; + setFilterState: React.Dispatch>; +}; + +export const Filter = (props: FilterProps) => { + const { filterState, setFilterState } = props; + + return ( + { + setFilterState((prev) => ({ + ...prev, + theme: event.target.value, + })); + }} + variant="outlined" + > + - + {THEMES.map((theme) => ( + + {theme} + + ))} + + ); +}; From e0bff174f854363333a1cebde7546c756a2a7e56 Mon Sep 17 00:00:00 2001 From: alexandre Date: Mon, 11 Dec 2023 18:06:49 +0100 Subject: [PATCH 3/3] use nextjs state management --- app/dossiers/page.tsx | 17 ++-- components/folderHomePage/DossierList.tsx | 107 ++++++++++++---------- components/folderHomePage/Filter.tsx | 21 ++--- components/folderHomePage/useFilter.tsx | 44 +++++++++ 4 files changed, 120 insertions(+), 69 deletions(-) create mode 100644 components/folderHomePage/useFilter.tsx diff --git a/app/dossiers/page.tsx b/app/dossiers/page.tsx index 0146758..b984c19 100644 --- a/app/dossiers/page.tsx +++ b/app/dossiers/page.tsx @@ -6,13 +6,13 @@ import Stack from "@mui/material/Stack"; import { FilterContainer } from "@/components/FilterContainer"; -import { DossierFilterState, Filter } from "@/components/folderHomePage/Filter"; +import { Filter } from "@/components/folderHomePage/Filter"; import DossierList from "@/components/folderHomePage/DossierList"; -export default function Dossiers() { - const [filterState, setFilterState] = React.useState({ - theme: "", - }); +export default function Dossiers(props: { + searchParams: { theme?: string; search?: string }; +}) { + const { searchParams } = props; return ( - + - + ); diff --git a/components/folderHomePage/DossierList.tsx b/components/folderHomePage/DossierList.tsx index 71ae5eb..85593f1 100644 --- a/components/folderHomePage/DossierList.tsx +++ b/components/folderHomePage/DossierList.tsx @@ -2,7 +2,6 @@ import * as React from "react"; import { Divider, Stack } from "@mui/material"; import Typography from "@mui/material/Typography"; import Link from "next/link"; -import { DossierFilterState } from "./Filter"; import { ThemeKeys } from "../const"; import LabelChip from "../LabelChip"; @@ -18,141 +17,146 @@ const dossiers: DossierType[] = [ { date: "2024-11-01", id: 0, - title: `Souhaits de bienvenue à une députée nouvellement élue`, - theme: "Transport", + title: "Souhaits de bienvenue à une députée nouvellement élue", + theme: "Environement", }, { date: "2024-11-01", id: 1, - title: `Écoles nationales d'architecture`, + title: "Écoles nationales d'architecture", theme: "Transport", }, { date: "2024-11-01", id: 2, - title: `Orientation et programmation du ministère de la justice 2023-2027 `, - theme: "Transport", + title: "Orientation et programmation du ministère de la justice 2023-2027 ", + theme: "Défense", }, { date: "2024-11-01", id: 3, - title: `Interdiction de l'écriture dite inclusive`, - theme: "Transport", + title: "Interdiction de l'écriture dite inclusive", + theme: "Agriculture", }, { date: "2024-11-01", id: 4, - title: `Crise de l'hôpital public`, - theme: "Transport", + title: "Crise de l'hôpital public", + theme: "Economie", }, { date: "2024-11-01", id: 5, - title: `Avenant au protocole d'accord france-luxembourg `, - theme: "Transport", + title: "Avenant au protocole d'accord france-luxembourg ", + theme: "Environement", }, { date: "2024-11-01", id: 6, - title: `Débat sur la dette`, + title: "Débat sur la dette", theme: "Transport", }, { date: "2024-11-01", id: 7, - title: `Convocation du parlement en session extraordinaire`, - theme: "Transport", + title: "Convocation du parlement en session extraordinaire", + theme: "Défense", }, { date: "2024-11-01", id: 8, - title: `Modernisation et responsabilité du corps judiciaire `, - theme: "Transport", + title: "Modernisation et responsabilité du corps judiciaire ", + theme: "Agriculture", }, { date: "2024-11-01", id: 9, - title: `Questions orales sans débat (1082 interventions, 3 commentaires)`, - theme: "Transport", + title: "Questions orales sans débat (1082 interventions, 3 commentaires)", + theme: "Economie", }, { date: "2024-11-01", id: 10, - title: `Orientation et programmation du ministère de la justice 2023-2027 - modernisation et responsabilité du corps judiciaire`, - theme: "Transport", + title: + "Orientation et programmation du ministère de la justice 2023-2027 - modernisation et responsabilité du corps judiciaire", + theme: "Environement", }, { date: "2024-11-01", id: 11, - title: `Hommage à léon gautier`, + title: "Hommage à léon gautier", theme: "Transport", }, { date: "2024-11-01", id: 12, - title: `Lutte contre les arnaques et les dérives des influenceurs sur les réseaux sociaux`, - theme: "Transport", + title: + "Lutte contre les arnaques et les dérives des influenceurs sur les réseaux sociaux", + theme: "Défense", }, - { date: "2024-10-01", id: 13, - title: `Accompagnement des élus locaux dans la lutte contre l'artificialisation des sols`, - theme: "Transport", + title: + "Accompagnement des élus locaux dans la lutte contre l'artificialisation des sols", + theme: "Agriculture", }, { date: "2024-10-01", id: 14, - title: `Hommage au professeur tué à arras `, - theme: "Transport", + title: "Hommage au professeur tué à arras ", + theme: "Economie", }, { date: "2024-10-01", id: 15, - title: `Explosion dans le 5e arrondissement`, - theme: "Transport", + title: "Explosion dans le 5e arrondissement", + theme: "Environement", }, { date: "2024-10-01", id: 16, - title: `Discussion d'une proposition de loi`, + title: "Discussion d'une proposition de loi", theme: "Transport", }, { date: "2024-10-01", id: 17, - title: `Lutte contre l'inflation concernant les produits de grande consommation `, - theme: "Transport", + title: + "Lutte contre l'inflation concernant les produits de grande consommation ", + theme: "Défense", }, { date: "2024-10-01", id: 18, - title: `Soutien à israel face au terrorisme`, - theme: "Transport", + title: "Soutien à israel face au terrorisme", + theme: "Agriculture", }, { date: "2024-10-01", id: 19, - title: `Solution à deux États et condamnation de l'institutionnalisation par l'État d'israel d'un régime d'apartheid`, - theme: "Transport", + title: + "Solution à deux États et condamnation de l'institutionnalisation par l'État d'israel d'un régime d'apartheid", + theme: "Economie", }, { date: "2024-10-01", id: 20, - title: `Sécuriser et réguler l'espace numérique `, - theme: "Transport", + title: "Sécuriser et réguler l'espace numérique ", + theme: "Environement", }, { date: "2024-10-01", id: 21, - title: `Ouverture de la session ordinaire`, + title: "Ouverture de la session ordinaire", theme: "Transport", }, { date: "2024-10-01", id: 22, - title: `Inscrire le groupe militaire privé wagner sur la liste des organisations terroristes`, - theme: "Transport", + title: + "Inscrire le groupe militaire privé wagner sur la liste des organisations terroristes", + theme: "Défense", }, ]; @@ -175,15 +179,26 @@ const dossierMensuels = dossiers }, [] as MonthDossier[]); type DossierListProps = { - filterState: DossierFilterState; - setFilterState: React.Dispatch>; + theme: string; + search: string; }; export default function DossierList(props: DossierListProps) { + const { theme, search } = props; + + const dossierMensuelsFiltered = dossierMensuels + .map((month) => { + return { + ...month, + dossiers: month.dossiers.filter((dossier) => dossier.theme === theme), + }; + }) + .filter((month) => month.dossiers.length > 0); + return (
- {dossierMensuels.map(({ date, dossiers }) => ( + {dossierMensuelsFiltered.map(({ date, dossiers }) => ( >; + theme: string; }; export const Filter = (props: FilterProps) => { - const { filterState, setFilterState } = props; + const { theme } = props; + + const { handleThemes } = useFilterState(); return ( { - setFilterState((prev) => ({ - ...prev, - theme: event.target.value, - })); + handleThemes(event.target.value); }} variant="outlined" > diff --git a/components/folderHomePage/useFilter.tsx b/components/folderHomePage/useFilter.tsx new file mode 100644 index 0000000..901b7eb --- /dev/null +++ b/components/folderHomePage/useFilter.tsx @@ -0,0 +1,44 @@ +"use client"; + +import { usePathname, useRouter } from "next/navigation"; +import { useTransition } from "react"; +import { ThemeKeys } from "../const"; + +export type DossierFilterState = { + theme: ThemeKeys | ""; + search: string; +}; + +export function useFilterState() { + const { replace } = useRouter(); + const pathname = usePathname(); + const [isPending, startTransition] = useTransition(); + + function handleSearch(term: string) { + const params = new URLSearchParams(window.location.search); + if (term) { + params.set("q", term); + } else { + params.delete("q"); + } + + startTransition(() => { + replace(`${pathname}?${params.toString()}`); + }); + } + + function handleThemes(theme: string) { + const params = new URLSearchParams(window.location.search); + if (theme === "") { + params.delete("theme"); + } else { + params.set("theme", theme); + } + + startTransition(() => { + replace(`${pathname}?${params.toString()}`); + }); + } + + return { isPending, handleSearch, handleThemes }; +}