Can download / delete member photo

This commit is contained in:
Pierre HUBERT 2023-08-10 13:53:23 +02:00
parent 1cf79e621f
commit 39c7163290
4 changed files with 67 additions and 14 deletions

View File

@ -199,6 +199,16 @@ export class MemberApi {
}); });
} }
/**
* Remove the photo of a member
*/
static async RemoveMemberPhoto(m: Member): Promise<void> {
await APIClient.exec({
uri: `/family/${m.family_id}/member/${m.id}/photo`,
method: "DELETE",
});
}
/** /**
* Delete a family member * Delete a family member
*/ */

View File

@ -4,6 +4,7 @@ import EditIcon from "@mui/icons-material/Edit";
import SaveIcon from "@mui/icons-material/Save"; import SaveIcon from "@mui/icons-material/Save";
import { Button, Grid, Stack } from "@mui/material"; import { Button, Grid, Stack } from "@mui/material";
import React from "react"; import React from "react";
import FileDownloadIcon from "@mui/icons-material/FileDownload";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import { Member, MemberApi } from "../../api/MemberApi"; import { Member, MemberApi } from "../../api/MemberApi";
import { ServerApi } from "../../api/ServerApi"; import { ServerApi } from "../../api/ServerApi";
@ -21,6 +22,7 @@ import { PropEdit } from "../../widgets/forms/PropEdit";
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 { MemberPhoto } from "../../widgets/MemberPhoto"; import { MemberPhoto } from "../../widgets/MemberPhoto";
import { RouterLink } from "../../widgets/RouterLink";
/** /**
* Create a new member route * Create a new member route
@ -238,6 +240,20 @@ export function MemberPage(p: {
p.onForceReload?.(); p.onForceReload?.();
}; };
const deletePhoto = async () => {
try {
if (!(await confirm("Voulez-vous supprimer cette photo ?"))) return;
await MemberApi.RemoveMemberPhoto(member);
snackbar("La photo du membre a été supprimée avec succès !");
p.onForceReload?.();
} catch (e) {
console.error(e);
alert("Échec de la suppresion de la photo !");
}
};
return ( return (
<div style={{ maxWidth: "2000px", margin: "auto" }}> <div style={{ maxWidth: "2000px", margin: "auto" }}>
<ConfirmLeaveWithoutSaveDialog <ConfirmLeaveWithoutSaveDialog
@ -410,11 +426,6 @@ export function MemberPage(p: {
</PropertiesBox> </PropertiesBox>
</Grid> </Grid>
{/* Contact */}
<Grid item sm={12} md={6}>
<PropertiesBox title="Contact">TODO</PropertiesBox>
</Grid>
{/* Photo */} {/* Photo */}
<Grid item sm={12} md={6}> <Grid item sm={12} md={6}>
<PropertiesBox title="Photo"> <PropertiesBox title="Photo">
@ -429,19 +440,40 @@ export function MemberPage(p: {
) : ( ) : (
<> <>
<UploadPhotoButton <UploadPhotoButton
label={ label={member.hasPhoto ? "Remplacer" : "Ajouter"}
member.hasPhoto
? "Remplacer la photo"
: "Ajouter une photo"
}
onPhotoSelected={uploadNewPhoto} onPhotoSelected={uploadNewPhoto}
/> />{" "}
{member.hasPhoto && (
<RouterLink to={member.photoURL} target="_blank">
<Button
variant="outlined"
startIcon={<FileDownloadIcon />}
>
Télécharger
</Button>
</RouterLink>
)}{" "}
{member.hasPhoto && (
<Button
variant="outlined"
startIcon={<DeleteIcon />}
color="error"
onClick={deletePhoto}
>
Supprimer
</Button>
)}
</> </>
)}{" "} )}{" "}
</div> </div>
</PropertiesBox> </PropertiesBox>
</Grid> </Grid>
{/* Contact */}
<Grid item sm={12} md={6}>
<PropertiesBox title="Contact">TODO</PropertiesBox>
</Grid>
{/* Bio */} {/* Bio */}
<Grid item sm={12} md={6}> <Grid item sm={12} md={6}>
<PropertiesBox title="Biographie">TODO</PropertiesBox> <PropertiesBox title="Biographie">TODO</PropertiesBox>

View File

@ -2,10 +2,14 @@ import { PropsWithChildren } from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
export function RouterLink( export function RouterLink(
p: PropsWithChildren<{ to: string }> p: PropsWithChildren<{ to: string; target?: React.HTMLAttributeAnchorTarget }>
): React.ReactElement { ): React.ReactElement {
return ( return (
<Link to={p.to} style={{ color: "inherit", textDecoration: "inherit" }}> <Link
to={p.to}
target={p.target}
style={{ color: "inherit", textDecoration: "inherit" }}
>
{p.children} {p.children}
</Link> </Link>
); );

View File

@ -6,6 +6,7 @@ import { ImageCropperDialog } from "../../dialogs/ImageCropperDialog";
import { useAlert } from "../../hooks/context_providers/AlertDialogProvider"; import { useAlert } from "../../hooks/context_providers/AlertDialogProvider";
import { Area } from "react-easy-crop"; import { Area } from "react-easy-crop";
import getCroppedImg from "../../utils/crop_image"; import getCroppedImg from "../../utils/crop_image";
import UploadIcon from "@mui/icons-material/Upload";
export function UploadPhotoButton(p: { export function UploadPhotoButton(p: {
label: string; label: string;
@ -82,7 +83,13 @@ export function UploadPhotoButton(p: {
return ( return (
<> <>
{/* Upload button */} {/* Upload button */}
<Button onClick={uploadPhoto}>{p.label}</Button> <Button
onClick={uploadPhoto}
variant="outlined"
startIcon={<UploadIcon />}
>
{p.label}
</Button>
{/* Crop image dialog */} {/* Crop image dialog */}
{imageURL && ( {imageURL && (