Skip to content

Commit

Permalink
[draft] Récupérer les débat de l'assemblée (#44)
Browse files Browse the repository at this point in the history
* [draft] Récupérer les débat de l'assemblée

* WIP

* Ajoute l'identité des interlocuteurs

* fixes
  • Loading branch information
alexfauquette authored Jun 1, 2024
1 parent 00a1a86 commit 5f0a19e
Show file tree
Hide file tree
Showing 11 changed files with 487 additions and 119 deletions.
2 changes: 1 addition & 1 deletion app/[legislature]/dossier/[id]/[tab]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export default async function Page({

switch (params.tab) {
case "debat":
return <DebateTab />;
return <DebateTab actesLegislatifs={dossier.acts} />;

case "amendement":
if (!amendements) {
Expand Down
3 changes: 3 additions & 0 deletions components/folders/AdditionalInfoCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ export const AdditionalInfoCard = ({
{coSignatairesIds
?.slice(0, fullCosignataires ? coSignatairesIds.length : 3)
?.map((id) => {
if (!acteurs[id]) {
return null;
}
const { prenom, nom, slug, deputeGroupeParlementaireUid } =
acteurs[id];

Expand Down
95 changes: 95 additions & 0 deletions components/folders/DebatTab/ParoleItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import * as React from "react";

import Typography from "@mui/material/Typography";
import TimelineItem from "@mui/lab/TimelineItem";
import TimelineSeparator from "@mui/lab/TimelineSeparator";
import TimelineConnector from "@mui/lab/TimelineConnector";
import TimelineContent from "@mui/lab/TimelineContent";
import Stack from "@mui/material/Stack";
import Avatar from "@mui/material/Avatar";
import Box from "@mui/material/Box";
import CircleDiv from "@/icons/CircleDiv";

interface ParoleItemProps {
acteurRef: string | null;
prenom: string | null;
nom: string | null;
group_color: string | null;
group_libelle: string | null;
group_libelle_short: string | null;
roleDebat: string | null;
acteur_slug: string | null;
texte: string | null;
}
export default function ParoleItem(props: ParoleItemProps) {
const {
prenom,
nom,
acteur_slug,
group_color,
group_libelle,
group_libelle_short,
roleDebat,
texte,
} = props;

return (
<TimelineItem>
<TimelineSeparator sx={{ minWidth: 50 }}>
<Box
sx={{
width: 44,
height: 44,
my: 1,
mx: "auto",
borderColor: "grey.400",
borderWidth: 2,
borderRadius: "50%",
display: "flex",
justifyContent: "center",
alignItems: "center",
overflow: "hidden",
}}
>
<Avatar
sx={{ height: 40, width: 40 }}
alt={`${prenom ?? ""} ${nom ?? ""}`}
src={`https://www.nosdeputes.fr/depute/photo/${acteur_slug}/${52}`}
>
{prenom?.[0]?.toUpperCase()}
{nom?.[0]?.toUpperCase()}
</Avatar>
</Box>

<TimelineConnector />
</TimelineSeparator>
<TimelineContent>
<Stack direction="column" spacing={1}>
<div>
<Typography variant="body1" fontWeight="bold">
{prenom ?? ""} {nom ?? ""}
</Typography>
{group_libelle && (
<Box
sx={{
display: "flex",
alignItems: "center",
}}
>
{group_color && <CircleDiv color={group_color} />}{" "}
<Typography sx={{ ml: 1 }} variant="body2" fontWeight="light">
{group_libelle} ({group_libelle_short})
</Typography>
</Box>
)}
{roleDebat && <Typography>{roleDebat}</Typography>}
</div>
<Typography
variant="caption"
dangerouslySetInnerHTML={{ __html: texte || "TEXT_NOT_FOUND" }}
></Typography>
</Stack>
</TimelineContent>
</TimelineItem>
);
}
67 changes: 67 additions & 0 deletions components/folders/DebatTab/SectionItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import * as React from "react";

import Typography from "@mui/material/Typography";
import TimelineItem from "@mui/lab/TimelineItem";
import TimelineSeparator from "@mui/lab/TimelineSeparator";
import TimelineConnector from "@mui/lab/TimelineConnector";
import TimelineContent from "@mui/lab/TimelineContent";
import Stack from "@mui/material/Stack";
import Box from "@mui/material/Box";

function TimelineDot() {
return (
<Box
sx={(theme) => ({
mx: "auto",
borderWidth: 2,
borderColor: theme.palette.grey[400],
width: 40,
height: 40,
borderRadius: "50%",
display: "flex",
justifyContent: "center",
alignItems: "center",
})}
>
<Box
sx={{
bgcolor: "black",
width: 8,
height: 8,
borderRadius: "50%",
}}
/>
</Box>
);
}

interface ParoleItemProps {
title: string | null;
subtitle?: string | null;
}

export default function SectionItem(props: ParoleItemProps) {
const { title, subtitle } = props;

return (
<TimelineItem sx={{ minHeight: 100 }}>
<TimelineSeparator sx={{ minWidth: 50 }}>
<TimelineConnector />
<TimelineDot />
<TimelineConnector />
</TimelineSeparator>
<TimelineContent sx={{ my: "auto" }}>
<Stack direction="column" spacing={1}>
<Typography variant="body1" fontWeight="bold">
{title}
</Typography>
{subtitle && (
<Typography variant="caption" fontWeight="light">
{subtitle}
</Typography>
)}
</Stack>
</TimelineContent>
</TimelineItem>
);
}
8 changes: 7 additions & 1 deletion components/folders/DebateFilterBar.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"use client";
import React from "react";

import Box from "@mui/material/Box";
Expand All @@ -11,7 +12,12 @@ import Typography from "@mui/material/Typography";
import { ArrowLeftIcon } from "@/icons/ArrowLeftIcon";
import { ArrowRightIcon } from "@/icons/ArrowRightIcon";

export const DebateFilterBar = () => {
type DebateFilterBarProps = {
debatIndex: number;
setDebatIndex: (newVal: number) => void;
debats: any;
};
export const DebateFilterBar = (props: DebateFilterBarProps) => {
const [placeholderValue, setPlaceholderValue] = React.useState("1");

return (
Expand Down
66 changes: 66 additions & 0 deletions components/folders/DebatePage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"use client";

import * as React from "react";

import Container from "@mui/material/Container";
import Stack from "@mui/material/Stack";

import { DebateFilterBar } from "./DebateFilterBar";
import { DebateSummary } from "./DebateSummary";
import { DebateTranscript } from "./DebateTranscript";
import { Agenda } from "@/repository/types";

interface DebatePageProps {
paragraphs: any[];
debats: (Agenda & { ptIndex: number })[];
}
export function DebatePage(props: DebatePageProps) {
const { paragraphs, debats } = props;

console.log({ paragraphs });

const [debatIndex, setDebatIndex] = React.useState(0);

console.log("dfskljghldkj");
console.log(
paragraphs.filter(
(p) =>
p.debatRefUid === debats[debatIndex].compteRenduRef &&
Number.parseInt(p.valeurPtsOdj) === debats[debatIndex].ptIndex
)
);

return (
<>
<DebateFilterBar
debatIndex={debatIndex}
setDebatIndex={setDebatIndex}
debats={debats}
/>
<Container
sx={{
pt: 3,
display: "flex",
flexDirection: {
xs: "column",
md: "row",
},
gap: 5,
}}
>
<Stack flex={2}>
<DebateSummary />
</Stack>
<Stack spacing={3} flex={5} alignItems="flex-start">
<DebateTranscript
paragraphs={paragraphs.filter(
(p) =>
p.debatRefUid === debats[debatIndex].compteRenduRef &&
Number.parseInt(p.valeurPtsOdj) === debats[debatIndex].ptIndex
)}
/>
</Stack>
</Container>
</>
);
}
2 changes: 2 additions & 0 deletions components/folders/DebateSummary.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"use client"

import React from "react";

import Accordion from "@mui/material/Accordion";
Expand Down
96 changes: 62 additions & 34 deletions components/folders/DebateTab.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,64 @@
"use client";

import React from "react";
import { ActeLegislatif } from "@/repository/types";
import { getAgendas, getParagraphs, getPtsOdj } from "@/repository/database";
import { DebatePage } from "./DebatePage";

const CODE_ACTS_AVEC_DEBAT = [
"AN1-DEBATS-SEANCE",
"AN2-DEBATS-SEANCE",
"AN21-DEBATS-SEANCE",
"AN3-DEBATS-SEANCE",
"ANLDEF-DEBATS-SEANCE",
"ANLUNI-DEBATS-SEANCE",
"ANNLEC-DEBATS-SEANCE",
"CMP-DEBATS-AN-SEANCE",
"CMP-DEBATS-SN-SEANCE",
];

interface DebatTableProps {
actesLegislatifs: ActeLegislatif[];
}

export async function DebateTab(props: DebatTableProps) {
const { actesLegislatifs } = props;

const seen = new Set();
const reunionsIds = actesLegislatifs
.filter((act) => CODE_ACTS_AVEC_DEBAT.includes(act.codeActe))
.map((act) => act.reunionRefUid)
.filter((id) => !!id)
.filter((id) => {
// Remove duplicates
if (seen.has(id)) {
return false;
}
seen.add(id);
return true;
});

const agendas = await getAgendas(reunionsIds);
const ptOdj = await getPtsOdj(reunionsIds);
ptOdj.sort((a, b) => (a.uid < b.uid ? -1 : 1));

const debats = agendas
.map((agenda) => {
const act = actesLegislatifs.find((a) => a.reunionRefUid === agenda.uid);
if (!act) {
return {};
}

return {
...agenda,
ptIndex:
ptOdj
.filter((pt) => pt.agendaRefUid === agenda.uid)
.findIndex((pt) => pt.uid === act.odjRefUid) + 1,
};
})
.filter((x) => x.compteRenduRef && x.ptIndex)
.sort((a, b) => (a.timestampDebut < b.timestampDebut ? -1 : 1));

const paragraphs = await getParagraphs(debats.map((x) => x.compteRenduRef));

import Container from "@mui/material/Container";
import Stack from "@mui/material/Stack";

import { DebateFilterBar } from "./DebateFilterBar";
import { DebateSummary } from "./DebateSummary";
import { DebateTranscript } from "./DebateTranscript";

export const DebateTab = () => {
return (
<>
<DebateFilterBar />
<Container
sx={{
pt: 3,
display: "flex",
flexDirection: {
xs: "column",
md: "row",
},
gap: 5,
}}
>
<Stack flex={2}>
<DebateSummary />
</Stack>
<Stack spacing={3} flex={5} alignItems="flex-start">
<DebateTranscript />
</Stack>
</Container>
</>
);
};
return <DebatePage debats={debats} paragraphs={paragraphs} />;
}
Loading

0 comments on commit 5f0a19e

Please sign in to comment.