Show children on member page
This commit is contained in:
parent
a062f27b0b
commit
44f54934cc
@ -191,6 +191,10 @@ export class MembersList {
|
|||||||
get(id: number): Member | undefined {
|
get(id: number): Member | undefined {
|
||||||
return this.map.get(id);
|
return this.map.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
children(id: number): Member[] {
|
||||||
|
return this.list.filter((m) => m.mother === id || m.father === id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MemberApi {
|
export class MemberApi {
|
||||||
|
@ -26,6 +26,7 @@ import { PropEdit } from "../../widgets/forms/PropEdit";
|
|||||||
import { PropSelect } from "../../widgets/forms/SelectInput";
|
import { PropSelect } from "../../widgets/forms/SelectInput";
|
||||||
import { SexSelection } from "../../widgets/forms/SexSelection";
|
import { SexSelection } from "../../widgets/forms/SexSelection";
|
||||||
import { UploadPhotoButton } from "../../widgets/forms/UploadPhotoButton";
|
import { UploadPhotoButton } from "../../widgets/forms/UploadPhotoButton";
|
||||||
|
import { MemberItem } from "../../widgets/MemberItem";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new member route
|
* Create a new member route
|
||||||
@ -126,6 +127,7 @@ export function FamilyMemberRoute(): React.ReactElement {
|
|||||||
build={() => (
|
build={() => (
|
||||||
<MemberPage
|
<MemberPage
|
||||||
member={member!}
|
member={member!}
|
||||||
|
children={family.members.children(member!.id)}
|
||||||
creating={false}
|
creating={false}
|
||||||
editing={false}
|
editing={false}
|
||||||
onRequestDelete={deleteMember}
|
onRequestDelete={deleteMember}
|
||||||
@ -144,13 +146,14 @@ export function FamilyMemberRoute(): React.ReactElement {
|
|||||||
*/
|
*/
|
||||||
export function FamilyEditMemberRoute(): React.ReactElement {
|
export function FamilyEditMemberRoute(): React.ReactElement {
|
||||||
const n = useNavigate();
|
const n = useNavigate();
|
||||||
|
const { memberId } = useParams();
|
||||||
|
|
||||||
const alert = useAlert();
|
const alert = useAlert();
|
||||||
const snackbar = useSnackbar();
|
const snackbar = useSnackbar();
|
||||||
|
|
||||||
const [shouldQuit, setShouldQuit] = React.useState(false);
|
const [shouldQuit, setShouldQuit] = React.useState(false);
|
||||||
|
|
||||||
const family = useFamily();
|
const family = useFamily();
|
||||||
const { memberId } = useParams();
|
|
||||||
|
|
||||||
const [member, setMember] = React.useState<Member>();
|
const [member, setMember] = React.useState<Member>();
|
||||||
const load = async () => {
|
const load = async () => {
|
||||||
@ -202,6 +205,7 @@ export function MemberPage(p: {
|
|||||||
editing: boolean;
|
editing: boolean;
|
||||||
creating: boolean;
|
creating: boolean;
|
||||||
shouldAllowLeaving?: boolean;
|
shouldAllowLeaving?: boolean;
|
||||||
|
children?: Member[];
|
||||||
onCancel?: () => void;
|
onCancel?: () => void;
|
||||||
onSave?: (m: Member) => void;
|
onSave?: (m: Member) => void;
|
||||||
onRequestEdit?: () => void;
|
onRequestEdit?: () => void;
|
||||||
@ -211,6 +215,8 @@ export function MemberPage(p: {
|
|||||||
const confirm = useConfirm();
|
const confirm = useConfirm();
|
||||||
const snackbar = useSnackbar();
|
const snackbar = useSnackbar();
|
||||||
|
|
||||||
|
const family = useFamily();
|
||||||
|
|
||||||
const [changed, setChanged] = React.useState(false);
|
const [changed, setChanged] = React.useState(false);
|
||||||
const [member, setMember] = React.useState(
|
const [member, setMember] = React.useState(
|
||||||
new Member(structuredClone(p.member))
|
new Member(structuredClone(p.member))
|
||||||
@ -604,9 +610,24 @@ export function MemberPage(p: {
|
|||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
{/* Children */}
|
{/* Children */}
|
||||||
|
{p.children && (
|
||||||
<Grid item sm={12} md={6}>
|
<Grid item sm={12} md={6}>
|
||||||
<PropertiesBox title="Enfants">TODO</PropertiesBox>
|
<PropertiesBox title="Enfants">
|
||||||
|
{p.children.length === 0 ? (
|
||||||
|
<>Aucun enfant</>
|
||||||
|
) : (
|
||||||
|
p.children.map((c) => (
|
||||||
|
<RouterLink
|
||||||
|
key={c.id}
|
||||||
|
to={family.family.URL(`member/${c.id}`)}
|
||||||
|
>
|
||||||
|
<MemberItem member={c} />
|
||||||
|
</RouterLink>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</PropertiesBox>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
45
geneit_app/src/widgets/MemberItem.tsx
Normal file
45
geneit_app/src/widgets/MemberItem.tsx
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { mdiCross } from "@mdi/js";
|
||||||
|
import {
|
||||||
|
ListItemAvatar,
|
||||||
|
ListItemButton,
|
||||||
|
ListItemSecondaryAction,
|
||||||
|
ListItemText,
|
||||||
|
} from "@mui/material";
|
||||||
|
import { Member, fmtDate } from "../api/MemberApi";
|
||||||
|
import { MemberPhoto } from "./MemberPhoto";
|
||||||
|
import Icon from "@mdi/react";
|
||||||
|
import FemaleIcon from "@mui/icons-material/Female";
|
||||||
|
import MaleIcon from "@mui/icons-material/Male";
|
||||||
|
|
||||||
|
export function MemberItem(p: {
|
||||||
|
member?: Member;
|
||||||
|
onClick?: () => void;
|
||||||
|
secondary?: React.ReactElement;
|
||||||
|
}): React.ReactElement {
|
||||||
|
return (
|
||||||
|
<ListItemButton onClick={p.onClick}>
|
||||||
|
<ListItemAvatar>
|
||||||
|
<MemberPhoto member={p.member!} />
|
||||||
|
</ListItemAvatar>
|
||||||
|
<ListItemText
|
||||||
|
primary={
|
||||||
|
<>
|
||||||
|
{p.member?.fullName}{" "}
|
||||||
|
{p.member?.sex === "F" ? (
|
||||||
|
<FemaleIcon fontSize="small" htmlColor="pink" />
|
||||||
|
) : (
|
||||||
|
<MaleIcon fontSize="small" htmlColor="lightBlue" />
|
||||||
|
)}{" "}
|
||||||
|
{p.member?.dead && <Icon path={mdiCross} size={"1rem"} />}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
secondary={`${fmtDate(p.member?.dateOfBirth)} - ${fmtDate(
|
||||||
|
p.member?.dateOfDeath
|
||||||
|
)}`}
|
||||||
|
/>
|
||||||
|
{p.secondary && (
|
||||||
|
<ListItemSecondaryAction>{p.secondary}</ListItemSecondaryAction>
|
||||||
|
)}
|
||||||
|
</ListItemButton>
|
||||||
|
);
|
||||||
|
}
|
@ -1,21 +1,10 @@
|
|||||||
import { mdiCross } from "@mdi/js";
|
|
||||||
import Icon from "@mdi/react";
|
|
||||||
import ClearIcon from "@mui/icons-material/Clear";
|
import ClearIcon from "@mui/icons-material/Clear";
|
||||||
import {
|
import { Autocomplete, IconButton, TextField, Typography } from "@mui/material";
|
||||||
Autocomplete,
|
|
||||||
IconButton,
|
|
||||||
ListItemAvatar,
|
|
||||||
ListItemButton,
|
|
||||||
ListItemSecondaryAction,
|
|
||||||
ListItemText,
|
|
||||||
TextField,
|
|
||||||
Typography,
|
|
||||||
} from "@mui/material";
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { Member, fmtDate } from "../../api/MemberApi";
|
import { Member } from "../../api/MemberApi";
|
||||||
import { useFamily } from "../BaseFamilyRoute";
|
import { useFamily } from "../BaseFamilyRoute";
|
||||||
import { MemberPhoto } from "../MemberPhoto";
|
import { MemberItem } from "../MemberItem";
|
||||||
|
|
||||||
export function MemberInput(p: {
|
export function MemberInput(p: {
|
||||||
editable: boolean;
|
editable: boolean;
|
||||||
@ -92,31 +81,3 @@ export function MemberInput(p: {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function MemberItem(p: {
|
|
||||||
member?: Member;
|
|
||||||
onClick?: () => void;
|
|
||||||
secondary?: React.ReactElement;
|
|
||||||
}): React.ReactElement {
|
|
||||||
return (
|
|
||||||
<ListItemButton onClick={p.onClick}>
|
|
||||||
<ListItemAvatar>
|
|
||||||
<MemberPhoto member={p.member!} />
|
|
||||||
</ListItemAvatar>
|
|
||||||
<ListItemText
|
|
||||||
primary={
|
|
||||||
<>
|
|
||||||
{p.member?.fullName}{" "}
|
|
||||||
{p.member?.dead && <Icon path={mdiCross} size={"1rem"} />}
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
secondary={`${fmtDate(p.member?.dateOfBirth)} - ${fmtDate(
|
|
||||||
p.member?.dateOfDeath
|
|
||||||
)}`}
|
|
||||||
/>
|
|
||||||
{p.secondary && (
|
|
||||||
<ListItemSecondaryAction>{p.secondary}</ListItemSecondaryAction>
|
|
||||||
)}
|
|
||||||
</ListItemButton>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user