Can create a member

This commit is contained in:
Pierre HUBERT 2023-08-08 14:30:08 +02:00
parent d07dfd6596
commit c6d0ff187c
2 changed files with 129 additions and 17 deletions

View File

@ -1,3 +1,5 @@
import { APIClient } from "./ApiClient";
export type Sex = "M" | "F";
export interface MemberApi {
@ -85,4 +87,30 @@ export class Member implements MemberApi {
this.death_day = m.death_day;
this.note = m.note;
}
/**
* Create an empty member object
*/
static New(family_id: number): Member {
return new Member({
id: 0,
dead: false,
family_id: family_id,
});
}
}
export class MemberApi {
/**
* Create a new member
*/
static async Create(m: Member): Promise<Member> {
const res = await APIClient.exec({
uri: `/family/${m.family_id}/member/create`,
method: "POST",
jsonData: m,
});
return new Member(res.data);
}
}

View File

@ -1,23 +1,49 @@
import ClearIcon from "@mui/icons-material/Clear";
import SaveIcon from "@mui/icons-material/Save";
import { Button, Grid, Stack } from "@mui/material";
import React from "react";
import { Member } from "../../api/MemberApi";
import { useFamily } from "../../widgets/BaseFamilyRoute";
import { Grid, Typography } from "@mui/material";
import { PropertiesBox } from "../../widgets/PropertiesBox";
import { PropEdit } from "../../widgets/PropEdit";
import { useNavigate } from "react-router-dom";
import { Member, MemberApi } from "../../api/MemberApi";
import { ServerApi } from "../../api/ServerApi";
import { useAlert } from "../../context_providers/AlertDialogProvider";
import { useConfirm } from "../../context_providers/ConfirmDialogProvider";
import { useFamily } from "../../widgets/BaseFamilyRoute";
import { FamilyPageTitle } from "../../widgets/FamilyPageTitle";
import { PropEdit } from "../../widgets/PropEdit";
import { PropertiesBox } from "../../widgets/PropertiesBox";
import { SexSelection } from "../../widgets/SexSelection";
/**
* Create a new member route
*/
export function FamilyCreateMemberRoute(): React.ReactElement {
const alert = useAlert();
const n = useNavigate();
const family = useFamily();
const member = new Member({
id: 0,
dead: false,
family_id: family.family.family_id,
});
return <MemberPage member={member} creating={true} forceEdit={true} />;
const create = async (m: Member) => {
try {
const r = await MemberApi.Create(m);
// TODO : trigger update
n(family.family.URL(`member/${r.id}`));
} catch (e) {
console.error(e);
alert("Echec de la création de la personne !");
}
};
return (
<MemberPage
member={Member.New(family.family.family_id)}
creating={true}
editing={true}
onCancel={() => n(family.family.URL("members"))}
onSave={create}
/>
);
}
/**
@ -29,21 +55,79 @@ export function FamilyMemberRoute(): React.ReactElement {
export function MemberPage(p: {
member: Member;
forceEdit: boolean;
editing: boolean;
creating: boolean;
onCancel: () => void;
onSave: (m: Member) => void;
onRequestEdit?: () => void;
}): React.ReactElement {
const confirm = useConfirm();
// TODO : add confirmation when leaving page https://dev.to/bangash1996/detecting-user-leaving-page-with-react-router-dom-v602-33ni
const [editing, setEditing] = React.useState(p.forceEdit);
const [changed, setChanged] = React.useState(false);
const [member, setMember] = React.useState(structuredClone(p.member));
const updatedMember = () => {
// TODO : add confirmation
setChanged(true);
setMember(structuredClone(member));
};
const save = () => {
p.onSave(member);
};
const cancel = async () => {
if (
!(await confirm(
"Voulez-vous vraiment retirer les modifications apportées ? Celles-ci seront perdues !"
))
)
return;
p.onCancel();
};
return (
<div style={{ maxWidth: "2000px", margin: "auto" }}>
<Typography variant="h3">Fiche de membre</Typography>
<div
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
}}
>
<FamilyPageTitle
title={
(p.creating ? "Création" : "Édition") + " d'une fiche de membre"
}
/>
<Stack direction="row" spacing={1}>
{/* Save button */}
{p.editing && (
<Button
variant="contained"
startIcon={<SaveIcon />}
onClick={save}
size="large"
>
Enregistrer
</Button>
)}
{/* Cancel button */}
{p.editing && (
<Button
variant="outlined"
startIcon={<ClearIcon />}
onClick={cancel}
size="small"
>
Annuler les modifications
</Button>
)}
</Stack>
</div>
<Grid container spacing={2}>
<Grid item sm={12} md={6}>
<PropertiesBox title="Informations générales">
@ -59,7 +143,7 @@ export function MemberPage(p: {
{/* First name */}
<PropEdit
label="Prénom"
editable={editing}
editable={p.editing}
value={member.first_name}
onValueChange={(v) => {
member.first_name = v;
@ -71,7 +155,7 @@ export function MemberPage(p: {
{/* Last name */}
<PropEdit
label="Nom"
editable={editing}
editable={p.editing}
value={member.last_name}
onValueChange={(v) => {
member.last_name = v;
@ -81,7 +165,7 @@ export function MemberPage(p: {
/>
<PropEdit
label="Nom de naissance"
editable={editing}
editable={p.editing}
value={member.birth_last_name}
onValueChange={(v) => {
member.birth_last_name = v;