feat: add ordering for member page

This commit is contained in:
2025-11-17 21:48:24 +01:00
parent c7f56881cd
commit 9457c5749a
4 changed files with 150 additions and 16 deletions

View File

@@ -13,6 +13,7 @@ import * as XLSX from "xlsx-js-style";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {faEuroSign} from "@fortawesome/free-solid-svg-icons";
export function MemberList({source}) {
const {hash} = useLocation();
const navigate = useNavigate();
@@ -26,14 +27,19 @@ export function MemberList({source}) {
const [stateFilter, setStateFilter] = useState(4)
const [lastSearch, setLastSearch] = useState("");
const [paymentFilter, setPaymentFilter] = useState(2);
const [order, setOrder] = useState("");
const setLoading = useLoadingSwitcher()
const {data, error, refresh} = useFetch(`/member/find/${source}?page=${page}&licenceRequest=${stateFilter}&payment=${paymentFilter}`, setLoading, 1)
const {
data,
error,
refresh
} = useFetch(`/member/find/${source}?page=${page}&licenceRequest=${stateFilter}&payment=${paymentFilter}&order=${order}`, setLoading, 1)
useEffect(() => {
refresh(`/member/find/${source}?page=${page}&search=${lastSearch}&club=${clubFilter}&licenceRequest=${stateFilter}&payment=${paymentFilter}`);
}, [hash, clubFilter, stateFilter, lastSearch, paymentFilter]);
refresh(`/member/find/${source}?page=${page}&search=${lastSearch}&club=${clubFilter}&licenceRequest=${stateFilter}&payment=${paymentFilter}&order=${order}`);
}, [hash, clubFilter, stateFilter, lastSearch, paymentFilter, order]);
useEffect(() => {
if (!data)
@@ -79,6 +85,10 @@ export function MemberList({source}) {
setLastSearch(search);
}
const onOrderChange = (newOrder) => {
setOrder(newOrder.join(","));
}
return <>
<div>
<div className="row">
@@ -102,6 +112,14 @@ export function MemberList({source}) {
<button className="btn btn-primary" onClick={() => navigate("pay")} style={{marginTop: "0.5rem"}}>Paiement des
licences</button>}
</div>
<div className="card mb-4">
<div className="card-header">Trie</div>
<div className="card-body">
<OrderBar onOrderChange={onOrderChange} source={source}/>
</div>
</div>
<div className="card mb-4">
<div className="card-header">Filtre</div>
<div className="card-body">
@@ -371,7 +389,7 @@ function MakeRow({member, showLicenceState, navigate, source}) {
const rowContent = <>
<div className="row">
<span className="col-auto">{(member.licence_number ? String(member.licence_number).padStart(5, '0') : "-------") + " "}
{(showLicenceState && member.licence != null && member.licence.pay)? <FontAwesomeIcon icon={faEuroSign}/> : <>&nbsp;&nbsp;</>}</span>
{(showLicenceState && member.licence != null && member.licence.pay) ? <FontAwesomeIcon icon={faEuroSign}/> : <>&nbsp;&nbsp;</>}</span>
<div className="ms-2 col-auto">
<div className="fw-bold">{member.fname} {member.lname}</div>
</div>
@@ -394,9 +412,92 @@ function MakeRow({member, showLicenceState, navigate, source}) {
}
}
function OrderBar({onOrderChange, source}) {
const [orderCriteria, setOrderCriteria] = useState(['']);
const handleChange = (index, value) => {
const newCriteria = [...orderCriteria];
newCriteria[index] = value;
// Si le dernier critère est rempli, on en ajoute un nouveau
if (index === orderCriteria.length - 1 && value !== '') {
newCriteria.push('');
}
// Si un critère (sauf le premier) est réinitialisé, on le supprime
else if (value === '' && (index !== 0 || orderCriteria.length > 1)) {
newCriteria.splice(index, 1);
}
setOrderCriteria(newCriteria);
onOrderChange(newCriteria.filter(c => c !== ''));
};
// Liste de toutes les options possibles
const allOptions = [
{value: 'lname n', label: 'Nom ↓', base: 'lname'},
{value: 'lname i', label: 'Nom ↑', base: 'lname'},
{value: 'fname n', label: 'Prénom ↓', base: 'fname'},
{value: 'fname i', label: 'Prénom ↑', base: 'fname'},
{value: 'categorie n', label: 'Catégorie ↓', base: 'categorie'},
{value: 'categorie i', label: 'Catégorie ↑', base: 'categorie'},
{value: 'licence n', label: 'Licence ↓', base: 'licence'},
{value: 'licence i', label: 'Licence ↑', base: 'licence'},
];
if (source === "admin") {
allOptions.push(
{value: 'club.name n', label: 'Club ↓', base: 'club.name'},
{value: 'club.name i', label: 'Club ↑', base: 'club.name'},
);
}
return (
<div className="mb-3">
{orderCriteria.map((criteria, index) => {
// Récupère les bases des critères déjà sélectionnés (sauf le courant)
const usedBases = orderCriteria
.filter((c, i) => c !== '' && i !== index)
.map(c => allOptions.find(o => o.value === c)?.base);
// Filtre les options disponibles
const availableOptions = allOptions.filter(option =>
!usedBases.includes(option.base) || option.value === criteria
);
return (
<select
key={index}
className="form-select mb-2"
value={criteria}
onChange={(e) => handleChange(index, e.target.value)}
>
<option value="">----</option>
{availableOptions.map((option) => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</select>
);
})}
</div>
);
}
let allClub = []
function FiltreBar({showLicenceState, setShowLicenceState, data, clubFilter, setClubFilter, source, stateFilter, setStateFilter, paymentFilter, setPaymentFilter}) {
function FiltreBar({
showLicenceState,
setShowLicenceState,
data,
clubFilter,
setClubFilter,
source,
stateFilter,
setStateFilter,
paymentFilter,
setPaymentFilter
}) {
useEffect(() => {
if (!data)
return;