Can filter couples
This commit is contained in:
		| @@ -115,6 +115,14 @@ export class Member implements MemberDataApi { | ||||
|       : `${firstName} ${this.last_name ?? ""}`; | ||||
|   } | ||||
|  | ||||
|   get invertedFullName(): string { | ||||
|     const lastName = this.last_name ?? ""; | ||||
|  | ||||
|     return lastName.length === 0 | ||||
|       ? this.last_name ?? "" | ||||
|       : `${lastName} ${this.first_name ?? ""}`; | ||||
|   } | ||||
|  | ||||
|   get hasPhoto(): boolean { | ||||
|     return this.photo_id !== null; | ||||
|   } | ||||
|   | ||||
| @@ -1,11 +1,15 @@ | ||||
| import { Link } from "react-router-dom"; | ||||
| import { RouterLink } from "../widgets/RouterLink"; | ||||
| import { Button } from "@mui/material"; | ||||
|  | ||||
| export function NotFoundRoute(): React.ReactElement { | ||||
|   return ( | ||||
|     <div style={{ textAlign: "center" }}> | ||||
|       <h1>Page non trouvée !</h1> | ||||
|       <p>La page que vous demandez n'a pas été trouvée !</p> | ||||
|       <Link to="/">Retour à l'accueil</Link> | ||||
|       <RouterLink to="/"> | ||||
|         <Button>Retour à l'accueil</Button> | ||||
|       </RouterLink> | ||||
|     </div> | ||||
|   ); | ||||
| } | ||||
|   | ||||
| @@ -1,23 +1,22 @@ | ||||
| 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 { Couple, CoupleApi } from "../../api/CoupleApi"; | ||||
| import { dateTimestamp, fmtDate } from "../../api/MemberApi"; | ||||
| import { ServerApi } from "../../api/ServerApi"; | ||||
| 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"; | ||||
| import { FamilyPageTitle } from "../../widgets/FamilyPageTitle"; | ||||
| import { MemberPhoto } from "../../widgets/MemberPhoto"; | ||||
| import { RouterLink } from "../../widgets/RouterLink"; | ||||
|  | ||||
| export function FamilyCouplesListRoute(): React.ReactElement { | ||||
|   const alert = useAlert(); | ||||
| @@ -83,7 +82,19 @@ export function FamilyCouplesListRoute(): React.ReactElement { | ||||
|             couples={ | ||||
|               filter === "" | ||||
|                 ? family.couples.fullList | ||||
|                 : family.couples.filter((m) => true /* TODO */) | ||||
|                 : family.couples.filter( | ||||
|                     (m) => | ||||
|                       (m.wife && | ||||
|                         family.members | ||||
|                           .get(m.wife)! | ||||
|                           .fullName.toLocaleLowerCase() | ||||
|                           .includes(filter.toLocaleLowerCase())) || | ||||
|                       (m.husband && | ||||
|                         family.members | ||||
|                           .get(m.husband)! | ||||
|                           .fullName.toLocaleLowerCase() | ||||
|                           .includes(filter.toLocaleLowerCase())) === true | ||||
|                   ) | ||||
|             } | ||||
|             onDelete={processDeletion} | ||||
|           /> | ||||
| @@ -100,6 +111,19 @@ function CouplesTable(p: { | ||||
|   const family = useFamily(); | ||||
|   const n = useNavigate(); | ||||
|  | ||||
|   const compareInvertedMembersNames = ( | ||||
|     v1: number | undefined, | ||||
|     v2: number | undefined | ||||
|   ) => { | ||||
|     const n1 = ((v1 && family.members.get(v1)?.invertedFullName) ?? "") || ""; | ||||
|     const n2 = ((v2 && family.members.get(v2)?.invertedFullName) ?? "") || ""; | ||||
|  | ||||
|     return n1?.localeCompare(n2, undefined, { | ||||
|       ignorePunctuation: true, | ||||
|       sensitivity: "base", | ||||
|     }); | ||||
|   }; | ||||
|  | ||||
|   const columns: GridColDef<Couple>[] = [ | ||||
|     { | ||||
|       field: "signed_photo_id", | ||||
| @@ -116,18 +140,26 @@ function CouplesTable(p: { | ||||
|       field: "husband", | ||||
|       headerName: "Époux", | ||||
|       flex: 5, | ||||
|       sortComparator: compareInvertedMembersNames, | ||||
|       renderCell(params) { | ||||
|         return <MemberCell id={params.row.husband} />; | ||||
|       }, | ||||
|     }, | ||||
|  | ||||
|     { | ||||
|       field: "wife", | ||||
|       headerName: "Épouse", | ||||
|       flex: 5, | ||||
|       sortComparator: compareInvertedMembersNames, | ||||
|       renderCell(params) { | ||||
|         return <MemberCell id={params.row.wife} />; | ||||
|       }, | ||||
|     }, | ||||
|  | ||||
|     { | ||||
|       field: "state", | ||||
|       headerName: "État", | ||||
|       width: 50, | ||||
|       flex: 3, | ||||
|       renderCell(params) { | ||||
|         return ServerApi.Config.couples_states.find( | ||||
|           (c) => c.code === params.row.state | ||||
| @@ -200,7 +232,34 @@ function CouplesTable(p: { | ||||
|       columns={columns} | ||||
|       autoPageSize | ||||
|       getRowId={(c) => c.id} | ||||
|       onRowDoubleClick={(p) => n(family.family.coupleURL(p.row))} | ||||
|       onCellDoubleClick={(p) => { | ||||
|         let member; | ||||
|         if (p.field === "wife") member = family.members.get(p.row.wife); | ||||
|         else if (p.field === "husband") | ||||
|           member = family.members.get(p.row.husband); | ||||
|  | ||||
|         if (member) { | ||||
|           n(family.family.memberURL(member)); | ||||
|           return; | ||||
|         } | ||||
|  | ||||
|         n(family.family.coupleURL(p.row)); | ||||
|       }} | ||||
|     /> | ||||
|   ); | ||||
| } | ||||
|  | ||||
| function MemberCell(p: { id?: number }): React.ReactElement { | ||||
|   const family = useFamily(); | ||||
|   if (!p.id) return <></>; | ||||
|  | ||||
|   const member = family.members.get(p.id!)!; | ||||
|  | ||||
|   return ( | ||||
|     <Tooltip title="Double-cliquez ici pour accéder à la fiche du membre"> | ||||
|       <div style={{ display: "flex", alignItems: "center" }}> | ||||
|         <MemberPhoto member={member} width={25} />   {member.fullName} | ||||
|       </div> | ||||
|     </Tooltip> | ||||
|   ); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user