improve: descending activityId order
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
// src/components/ClubList.tsx
|
||||||
import React, { useState, useEffect, useMemo, useCallback } from 'react';
|
import React, { useState, useEffect, useMemo, useCallback } from 'react';
|
||||||
import Fuse from 'fuse.js';
|
import Fuse from 'fuse.js';
|
||||||
import type { ClubBasic, ClubDetail, CategoryCount, AcademicYearCount } from '@types';
|
import type { ClubBasic, ClubDetail, CategoryCount, AcademicYearCount } from '@types';
|
||||||
@@ -32,6 +33,15 @@ const ClubList: React.FC = () => {
|
|||||||
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
|
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
|
||||||
const [selectedClubForModal, setSelectedClubForModal] = useState<ClubDetail | null>(null);
|
const [selectedClubForModal, setSelectedClubForModal] = useState<ClubDetail | null>(null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper that sorts clubs by ID in descending order (high → low).
|
||||||
|
* `id` could be either a string or number, so we cast to number for comparison.
|
||||||
|
*/
|
||||||
|
const sortClubsDesc = useCallback(
|
||||||
|
(clubs: ClubBasic[]) => [...clubs].sort((a, b) => Number(b.id) - Number(a.id)),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
const fuse = useMemo(() => {
|
const fuse = useMemo(() => {
|
||||||
if (!allClubsData.length) return null;
|
if (!allClubsData.length) return null;
|
||||||
return new Fuse(allClubsData, {
|
return new Fuse(allClubsData, {
|
||||||
@@ -70,7 +80,10 @@ const ClubList: React.FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let clubs;
|
let clubs;
|
||||||
if (selectedCategory || selectedAcademicYear || (gradeNumber && gradeNumber >= 1 && gradeNumber <= 12)) {
|
if (
|
||||||
|
selectedCategory || selectedAcademicYear ||
|
||||||
|
(gradeNumber && gradeNumber >= 1 && gradeNumber <= 12)
|
||||||
|
) {
|
||||||
clubs = await filterClubs({
|
clubs = await filterClubs({
|
||||||
category: selectedCategory || undefined,
|
category: selectedCategory || undefined,
|
||||||
academicYear: selectedAcademicYear || undefined,
|
academicYear: selectedAcademicYear || undefined,
|
||||||
@@ -79,7 +92,8 @@ const ClubList: React.FC = () => {
|
|||||||
} else {
|
} else {
|
||||||
clubs = await listAllClubs();
|
clubs = await listAllClubs();
|
||||||
}
|
}
|
||||||
setAllClubsData(clubs);
|
// Sort clubs from high ID → low ID before saving to state
|
||||||
|
setAllClubsData(sortClubsDesc(clubs));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Failed to fetch clubs:', err);
|
console.error('Failed to fetch clubs:', err);
|
||||||
setError('Could not load clubs. Please try refreshing.');
|
setError('Could not load clubs. Please try refreshing.');
|
||||||
@@ -87,7 +101,7 @@ const ClubList: React.FC = () => {
|
|||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
}, [selectedCategory, selectedAcademicYear, selectedGrade]);
|
}, [selectedCategory, selectedAcademicYear, selectedGrade, sortClubsDesc]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchFilteredClubsFromAPI();
|
fetchFilteredClubsFromAPI();
|
||||||
@@ -98,18 +112,19 @@ const ClubList: React.FC = () => {
|
|||||||
setDisplayedClubs([]);
|
setDisplayedClubs([]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fuse) {
|
if (!fuse) {
|
||||||
setDisplayedClubs(allClubsData);
|
setDisplayedClubs(sortClubsDesc(allClubsData));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (searchTerm.trim() === '') {
|
if (searchTerm.trim() === '') {
|
||||||
setDisplayedClubs(allClubsData);
|
setDisplayedClubs(sortClubsDesc(allClubsData));
|
||||||
} else {
|
} else {
|
||||||
const results = fuse.search(searchTerm);
|
const results = fuse.search(searchTerm).map(result => result.item);
|
||||||
setDisplayedClubs(results.map(result => result.item));
|
setDisplayedClubs(sortClubsDesc(results));
|
||||||
}
|
}
|
||||||
}, [searchTerm, allClubsData, fuse]);
|
}, [searchTerm, allClubsData, fuse, sortClubsDesc]);
|
||||||
|
|
||||||
const debouncedSetSearchTerm = useMemo(() => debounce(setSearchTerm, 300), []);
|
const debouncedSetSearchTerm = useMemo(() => debounce(setSearchTerm, 300), []);
|
||||||
|
|
||||||
@@ -128,8 +143,8 @@ const ClubList: React.FC = () => {
|
|||||||
setSelectedClubForModal(null);
|
setSelectedClubForModal(null);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
if (isLoading && !allClubsData.length && !Object.keys(availableCategories).length)
|
||||||
if (isLoading && !allClubsData.length && !Object.keys(availableCategories).length) return <p className="loading-message">Loading clubs and filters...</p>;
|
return <p className="loading-message">Loading clubs and filters...</p>;
|
||||||
if (error) return <p className="error-message">{error}</p>;
|
if (error) return <p className="error-message">{error}</p>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user