diff --git a/geneit_app/src/App.tsx b/geneit_app/src/App.tsx
index ffffa01..5f76289 100644
--- a/geneit_app/src/App.tsx
+++ b/geneit_app/src/App.tsx
@@ -33,6 +33,7 @@ import {
FamilyCreateCoupleRoute,
FamilyEditCoupleRoute,
} from "./routes/family/FamilyCoupleRoute";
+import { FamilyCouplesListRoute } from "./routes/family/FamilyCouplesListRoute";
interface AuthContext {
signedIn: boolean;
@@ -75,6 +76,7 @@ export function App(): React.ReactElement {
element={}
/>
+ } />
}
diff --git a/geneit_app/src/routes/family/FamilyCouplesListRoute.tsx b/geneit_app/src/routes/family/FamilyCouplesListRoute.tsx
new file mode 100644
index 0000000..ce583bd
--- /dev/null
+++ b/geneit_app/src/routes/family/FamilyCouplesListRoute.tsx
@@ -0,0 +1,206 @@
+import AddIcon from "@mui/icons-material/Add";
+import DeleteIcon from "@mui/icons-material/DeleteOutlined";
+import EditIcon from "@mui/icons-material/Edit";
+import FemaleIcon from "@mui/icons-material/Female";
+import MaleIcon from "@mui/icons-material/Male";
+import VisibilityIcon from "@mui/icons-material/Visibility";
+import { Button, TextField, Tooltip } from "@mui/material";
+import { DataGrid, GridActionsCellItem, GridColDef } from "@mui/x-data-grid";
+import React from "react";
+import { useNavigate } from "react-router-dom";
+import { useAlert } from "../../hooks/context_providers/AlertDialogProvider";
+import { useConfirm } from "../../hooks/context_providers/ConfirmDialogProvider";
+import { useSnackbar } from "../../hooks/context_providers/SnackbarProvider";
+import { useFamily } from "../../widgets/BaseFamilyRoute";
+import { FamilyPageTitle } from "../../widgets/FamilyPageTitle";
+import { RouterLink } from "../../widgets/RouterLink";
+import { Couple, CoupleApi } from "../../api/CoupleApi";
+import { CouplePhoto } from "../../widgets/CouplePhoto";
+import { ServerApi } from "../../api/ServerApi";
+import { dateTimestamp, fmtDate } from "../../api/MemberApi";
+
+export function FamilyCouplesListRoute(): React.ReactElement {
+ const alert = useAlert();
+ const confirm = useConfirm();
+ const snackbar = useSnackbar();
+
+ const family = useFamily();
+
+ const [filter, setFilter] = React.useState("");
+
+ const processDeletion = async (c: Couple) => {
+ try {
+ if (
+ !(await confirm(
+ `Voulez-vous vraiment supprimer cette fiche de couple ?`
+ ))
+ )
+ return;
+
+ await CoupleApi.Delete(c);
+ await family.reloadCouplesList();
+
+ snackbar("La fiche du couple a été supprimée avec succès !");
+ } catch (e) {
+ console.error(e);
+ alert("Echec de la suppression de la fiche ! ");
+ }
+ };
+
+ return (
+ <>
+
+
+
+
+ }>Nouveau
+
+
+
+
+ {family.couples.isEmpty ? (
+
+ Votre famille n'a aucun couple enregistré pour le moment ! Utilisez le
+ bouton situé en haut à droite pour créer le premier !
+
+ ) : (
+ <>
+ setFilter(e.target.value)}
+ style={{ maxWidth: "500px", margin: "10px" }}
+ />
+
+ true /* TODO */)
+ }
+ onDelete={processDeletion}
+ />
+ >
+ )}
+ >
+ );
+}
+
+function CouplesTable(p: {
+ couples: Couple[];
+ onDelete: (m: Couple) => void;
+}): React.ReactElement {
+ const family = useFamily();
+ const n = useNavigate();
+
+ const columns: GridColDef[] = [
+ {
+ field: "signed_photo_id",
+ headerName: "",
+ disableColumnMenu: true,
+ sortable: false,
+ width: 60,
+ renderCell(params) {
+ return ;
+ },
+ },
+
+ {
+ field: "husband",
+ headerName: "Époux",
+ flex: 5,
+ },
+
+ {
+ field: "wife",
+ headerName: "Épouse",
+ flex: 5,
+ },
+
+ {
+ field: "state",
+ headerName: "État",
+ width: 50,
+ renderCell(params) {
+ return ServerApi.Config.couples_states.find(
+ (c) => c.code === params.row.state
+ )?.fr;
+ },
+ },
+ {
+ field: "dateOfWedding",
+ headerName: "Date de mariage",
+ flex: 3,
+ sortComparator(v1, v2) {
+ const d1 = dateTimestamp(v1);
+ const d2 = dateTimestamp(v2);
+ return d1 - d2;
+ },
+ renderCell(params) {
+ return fmtDate(params.row.dateOfWedding);
+ },
+ },
+ {
+ field: "dateOfDivorce",
+ headerName: "Date de divorce",
+ flex: 3,
+ sortComparator(v1, v2) {
+ const d1 = dateTimestamp(v1);
+ const d2 = dateTimestamp(v2);
+ return d1 - d2;
+ },
+ renderCell(params) {
+ return fmtDate(params.row.dateOfDivorce);
+ },
+ },
+ {
+ field: "actions",
+ type: "actions",
+ sortable: false,
+ width: 120,
+ disableColumnMenu: true,
+ getActions(params) {
+ return [
+ }
+ label="Consulter la fiche du couple"
+ className="textPrimary"
+ onClick={() => n(family.family.coupleURL(params.row))}
+ color="inherit"
+ />,
+ }
+ label="Modifier la fiche du couple"
+ className="textPrimary"
+ onClick={() => n(family.family.coupleURL(params.row, true))}
+ color="inherit"
+ />,
+ }
+ label="Supprimer la fiche du couple"
+ onClick={() => p.onDelete(params.row)}
+ color="inherit"
+ />,
+ ];
+ },
+ },
+ ];
+
+ return (
+ c.id}
+ onRowDoubleClick={(p) => n(family.family.coupleURL(p.row))}
+ />
+ );
+}