feat: add membre

This commit is contained in:
2024-02-28 12:07:24 +01:00
parent 2fd6ef3c2e
commit b0232cd7b7
8 changed files with 310 additions and 47 deletions

View File

@@ -3,6 +3,7 @@ import './AdminRoot.css'
import {LoadingProvider} from "../../hooks/useLoading.jsx";
import {MemberList} from "../MemberList.jsx";
import {MemberPage} from "./member/MemberPage.jsx";
import {NewMemberPage} from "./member/NewMemberPage.jsx";
export function AdminRoot() {
return <>
@@ -13,7 +14,7 @@ export function AdminRoot() {
</>
}
export function getAdminChildren () {
export function getAdminChildren() {
return [
{
path: 'member',
@@ -23,6 +24,10 @@ export function getAdminChildren () {
path: 'member/:id',
element: <MemberPage/>
},
{
path: 'member/new',
element: <NewMemberPage/>
},
{
path: 'b',
element: <div>Admin B</div>

View File

@@ -5,6 +5,27 @@ import imageCompression from "browser-image-compression";
import {BirthDayField, OptionField, TextField} from "../../../components/MemberCustomFiels.jsx";
import {ClubSelect} from "../../../components/ClubSelect.jsx";
export function addPhoto(event, formData, send) {
const imageFile = event.target.url_photo.files[0];
if (imageFile) {
console.log(`originalFile size ${imageFile.size / 1024 / 1024} MB`);
const options = {
maxSizeMB: 1,
maxWidthOrHeight: 1920,
useWebWorker: true,
}
imageCompression(imageFile, options).then(compressedFile => {
console.log(`compressedFile size ${compressedFile.size / 1024 / 1024} MB`); // smaller than maxSizeMB
formData.append("photo_data", compressedFile)
send(formData)
});
} else {
send(formData)
}
}
export function InformationForm({data}) {
const setLoading = useLoadingSwitcher()
const handleSubmit = (event) => {
@@ -25,7 +46,7 @@ export function InformationForm({data}) {
formData.append("grade_arbitrage", event.target.grade_arbitrage?.value);
const send = (formData_) => {
apiAxios.post(`/member/${data.id}`, formData_, {
apiAxios.put(`/member/${data.id}`, formData_, {
headers: {
'Accept': '*/*',
'Content-Type': 'multipart/form-data',
@@ -40,25 +61,7 @@ export function InformationForm({data}) {
setLoading(0)
})
}
const imageFile = event.target.url_photo.files[0];
if (imageFile) {
console.log(`originalFile size ${imageFile.size / 1024 / 1024} MB`);
const options = {
maxSizeMB: 1,
maxWidthOrHeight: 1920,
useWebWorker: true,
}
imageCompression(imageFile, options).then(compressedFile => {
console.log(`compressedFile size ${compressedFile.size / 1024 / 1024} MB`); // smaller than maxSizeMB
formData.append("photo_data", compressedFile)
send(formData)
});
} else {
send(formData)
}
addPhoto(event, formData, send);
}
return <form onSubmit={handleSubmit}>

View File

@@ -0,0 +1,107 @@
import {useNavigate} from "react-router-dom";
import {useLoadingSwitcher} from "../../../hooks/useLoading.jsx";
import {apiAxios} from "../../../utils/Tools.js";
import {toast} from "react-toastify";
import {BirthDayField, OptionField, TextField} from "../../../components/MemberCustomFiels.jsx";
import {ClubSelect} from "../../../components/ClubSelect.jsx";
import {addPhoto} from "./InformationForm.jsx";
export function NewMemberPage() {
const navigate = useNavigate();
return <>
<h2>Page membre</h2>
<button type="button" className="btn btn-link" onClick={() => navigate("/admin/member")}>
&laquo; retour
</button>
<div>
<div className="row">
<Form/>
</div>
</div>
</>
}
function Form() {
const navigate = useNavigate();
const setLoading = useLoadingSwitcher()
const handleSubmit = (event) => {
event.preventDefault();
setLoading(1)
const formData = new FormData();
formData.append("id", -1);
formData.append("lname", event.target.lname?.value);
formData.append("fname", event.target.fname?.value);
formData.append("categorie", event.target.category?.value);
formData.append("club", event.target.club?.value);
formData.append("genre", event.target.genre?.value);
formData.append("country", event.target.country?.value);
formData.append("birth_date", new Date(event.target.birth_date?.value).toUTCString());
formData.append("email", event.target.email?.value);
formData.append("role", event.target.role?.value);
formData.append("grade_arbitrage", event.target.grade_arbitrage?.value);
const send = (formData_) => {
apiAxios.post(`/member`, formData_, {
headers: {
'Accept': '*/*',
'Content-Type': 'multipart/form-data',
}
}).then(data => {
toast.success('Profile crée avec succès 🎉');
navigate(`/admin/member/${data.data}`)
}).catch(e => {
console.log(e.response)
toast.error('Échec de la création du profile 😕 (code: ' + e.response.status + ')');
}).finally(() => {
if (setLoading)
setLoading(0)
})
}
addPhoto(event, formData, send);
}
return <form onSubmit={handleSubmit}>
<div className="card mb-4">
<div className="card-header">Nouveau membre</div>
<div className="card-body">
<TextField name="lname" text="Nom"/>
<TextField name="fname" text="Prénom"/>
<TextField name="email" text="Email" placeholder="name@example.com"
type="email"/>
<OptionField name="genre" text="Genre" values={{NA: 'N/A', H: 'H', F: 'F'}}/>
<OptionField name="country" text="Pays" value={'fr'}
values={{NA: 'Sélectionner...', fr: 'FR', es: 'ES', be: 'BE'}}/>
<BirthDayField/>
<div className="row">
<ClubSelect name="club"/>
</div>
<OptionField name="role" text="Rôle" value={'MEMBRE'}
values={{
MEMBRE: 'Membre',
PRESIDENT: 'Président',
TRESORIER: 'Trésorier',
SECRETAIRE: 'Secrétaire'
}}/>
<OptionField name="grade_arbitrage" text="Grade d'arbitrage" value={'NA'}
values={{NA: 'N/A', ASSESSEUR: 'Assesseur', ARBITRE: 'Arbitre'}}/>
<div className="row">
<div className="input-group mb-3">
<label className="input-group-text" htmlFor="url_photo">Photos
(optionnelle)</label>
<input type="file" className="form-control" id="url_photo" name="url_photo"
accept=".jpg,.jpeg,.gif,.png,.svg"/>
</div>
</div>
<div className="row">
<div className="d-grid gap-2 d-md-flex justify-content-md-end">
<button type="submit" className="btn btn-primary">Créer</button>
</div>
</div>
</div>
</div>
</form>;
}

View File

@@ -3,6 +3,7 @@ import {LoadingProvider} from "../../hooks/useLoading.jsx";
import {MemberPage} from "./member/MemberPage.jsx";
import {useAuth} from "../../hooks/useAuth.jsx";
import {MemberList} from "../MemberList.jsx";
import {NewMemberPage} from "./member/NewMemberPage.jsx";
export function ClubRoot() {
const {userinfo} = useAuth()
@@ -35,6 +36,10 @@ export function getClubChildren() {
path: 'member/:id',
element: <MemberPage/>
},
{
path: 'member/new',
element: <NewMemberPage/>
},
{
path: 'b',
element: <div>Club B</div>

View File

@@ -3,9 +3,8 @@
import {useLoadingSwitcher} from "../../../hooks/useLoading.jsx";
import {apiAxios} from "../../../utils/Tools.js";
import {toast} from "react-toastify";
import imageCompression from "browser-image-compression";
import {BirthDayField, OptionField, TextField} from "../../../components/MemberCustomFiels.jsx";
import {ClubSelect} from "../../../components/ClubSelect.jsx";
import {addPhoto} from "../../admin/member/InformationForm.jsx";
export function InformationForm({data}) {
const setLoading = useLoadingSwitcher()
@@ -25,7 +24,7 @@ export function InformationForm({data}) {
formData.append("role", event.target.role?.value);
const send = (formData_) => {
apiAxios.post(`/member/club/${data.id}`, formData_, {
apiAxios.put(`/member/club/${data.id}`, formData_, {
headers: {
'Accept': '*/*',
'Content-Type': 'multipart/form-data',
@@ -40,23 +39,7 @@ export function InformationForm({data}) {
setLoading(0)
})
}
const imageFile = event.target.url_photo.files[0];
if (imageFile) {
console.log(`originalFile size ${imageFile.size / 1024 / 1024} MB`);
const options = {
maxSizeMB: 1,
maxWidthOrHeight: 1920,
useWebWorker: true,
}
imageCompression(imageFile, options).then(compressedFile => {
console.log(`compressedFile size ${compressedFile.size / 1024 / 1024} MB`); // smaller than maxSizeMB
formData.append("photo_data", compressedFile)
send(formData)
});
} else {
send(formData)
}
addPhoto(event, formData, send);
}
return <form onSubmit={handleSubmit}>
@@ -79,7 +62,7 @@ export function InformationForm({data}) {
PRESIDENT: 'Président',
TRESORIER: 'Trésorier',
SECRETAIRE: 'Secrétaire'
}}/>
}} disabled={true}/>
<OptionField name="grade_arbitrage" text="Grade d'arbitrage" value={data.grade_arbitrage}
values={{NA: 'N/A', ASSESSEUR: 'Assesseur', ARBITRE: 'Arbitre'}} disabled={true}/>
<div className="row">

View File

@@ -0,0 +1,92 @@
import {useNavigate} from "react-router-dom";
import {useLoadingSwitcher} from "../../../hooks/useLoading.jsx";
import {apiAxios} from "../../../utils/Tools.js";
import {toast} from "react-toastify";
import {BirthDayField, OptionField, TextField} from "../../../components/MemberCustomFiels.jsx";
import {ClubSelect} from "../../../components/ClubSelect.jsx";
import {addPhoto} from "../../admin/member/InformationForm.jsx";
export function NewMemberPage() {
const navigate = useNavigate();
return <>
<h2>Page membre</h2>
<button type="button" className="btn btn-link" onClick={() => navigate("/club/member")}>
&laquo; retour
</button>
<div>
<div className="row">
<Form/>
</div>
</div>
</>
}
function Form() {
const navigate = useNavigate();
const setLoading = useLoadingSwitcher()
const handleSubmit = (event) => {
event.preventDefault();
setLoading(1)
const formData = new FormData();
formData.append("id", -1);
formData.append("lname", event.target.lname?.value);
formData.append("fname", event.target.fname?.value);
formData.append("categorie", event.target.category?.value);
formData.append("genre", event.target.genre?.value);
formData.append("country", event.target.country?.value);
formData.append("birth_date", new Date(event.target.birth_date?.value).toUTCString());
formData.append("email", event.target.email?.value);
const send = (formData_) => {
apiAxios.post(`/member/club`, formData_, {
headers: {
'Accept': '*/*',
'Content-Type': 'multipart/form-data',
}
}).then(data => {
toast.success('Profile crée avec succès 🎉');
navigate(`/club/member/${data.data}`)
}).catch(e => {
console.log(e.response)
toast.error('Échec de la création du profile 😕 (code: ' + e.response.status + ')');
}).finally(() => {
if (setLoading)
setLoading(0)
})
}
addPhoto(event, formData, send);
}
return <form onSubmit={handleSubmit}>
<div className="card mb-4">
<div className="card-header">Nouveau membre</div>
<div className="card-body">
<TextField name="lname" text="Nom"/>
<TextField name="fname" text="Prénom"/>
<TextField name="email" text="Email" placeholder="name@example.com"
type="email"/>
<OptionField name="genre" text="Genre" values={{NA: 'N/A', H: 'H', F: 'F'}}/>
<OptionField name="country" text="Pays" value={'fr'}
values={{NA: 'Sélectionner...', fr: 'FR', es: 'ES', be: 'BE'}}/>
<BirthDayField/>
<div className="row">
<div className="input-group mb-3">
<label className="input-group-text" htmlFor="url_photo">Photos
(optionnelle)</label>
<input type="file" className="form-control" id="url_photo" name="url_photo"
accept=".jpg,.jpeg,.gif,.png,.svg"/>
</div>
</div>
<div className="row">
<div className="d-grid gap-2 d-md-flex justify-content-md-end">
<button type="submit" className="btn btn-primary">Créer</button>
</div>
</div>
</div>
</div>
</form>;
}