Skip to content

Commit f0d77c0

Browse files
committed
feat: Refactor competitions list and details components
- Enhanced CompetitionsList component with memoization and improved performance. - Added detailed status and actions templates for better user interaction. - Introduced CompetitionDetailsHeader and CompetitionStatisticsPanel components for better separation of concerns. - Implemented GroupsTable and ParticipantsTable components to display associated groups and participants. - Created CompetitionHeader and PuzzleGrid components for player competition page, improving layout and user experience. - Added PuzzleCard component to represent individual puzzles with unlocking logic and difficulty indicators. - Improved data fetching logic in CompetitionPage for better error handling and loading states.
1 parent 7b5bce3 commit f0d77c0

12 files changed

Lines changed: 945 additions & 525 deletions

src/app/admin/pages/competitions/CompetitionsPage.tsx

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useState, useEffect, useRef } from "react";
1+
import { useState, useEffect, useRef, useCallback } from "react";
22
import { useTranslation } from "react-i18next";
33

44
import { Toast } from "primereact/toast";
@@ -17,6 +17,15 @@ import { Competition } from "@/models";
1717

1818
import "./CompetitionsPage.css";
1919

20+
/**
21+
* CompetitionsPage - Admin page that manages competitions
22+
*
23+
* This component handles:
24+
* - Listing all competitions
25+
* - Creating new competitions
26+
* - Editing existing competitions
27+
* - Viewing competition details
28+
*/
2029
export default function CompetitionsPage() {
2130
const { t } = useTranslation(["common", "staffTabs"]);
2231
const toast = useRef<Toast>(null);
@@ -27,14 +36,18 @@ export default function CompetitionsPage() {
2736
useState<Competition | null>(null);
2837
const [loading, setLoading] = useState<boolean>(true);
2938

30-
// Dialog visibility states - refactored to match Roles.tsx pattern
39+
// Dialog visibility states
3140
const [editDialogVisible, setEditDialogVisible] = useState<boolean>(false);
3241
const [createDialogVisible, setCreateDialogVisible] =
3342
useState<boolean>(false);
3443
const [detailsDialogVisible, setDetailsDialogVisible] =
3544
useState<boolean>(false);
3645

37-
const fetchCompetitionsData = async () => {
46+
/**
47+
* Fetches all competitions from the API
48+
* Memoized with useCallback to prevent unnecessary re-renders
49+
*/
50+
const fetchCompetitionsData = useCallback(async () => {
3851
try {
3952
setLoading(true);
4053
const fetchedCompetitions = await ServiceManager.competitions.fetchAll();
@@ -45,13 +58,16 @@ export default function CompetitionsPage() {
4558
} finally {
4659
setLoading(false);
4760
}
48-
};
61+
}, [t]);
4962

63+
// Load competitions on component mount
5064
useEffect(() => {
5165
fetchCompetitionsData();
52-
// eslint-disable-next-line react-hooks/exhaustive-deps
53-
}, []);
66+
}, [fetchCompetitionsData]);
5467

68+
/**
69+
* Display a toast notification
70+
*/
5571
const showToast = (
5672
severity: "success" | "info" | "warn" | "error",
5773
detail: string
@@ -64,7 +80,7 @@ export default function CompetitionsPage() {
6480
});
6581
};
6682

67-
// Open dialog handlers - refactored to match Roles.tsx pattern
83+
// Dialog handlers
6884
const openCreateDialog = () => {
6985
setSelectedCompetition(null);
7086
setCreateDialogVisible(true);
@@ -80,13 +96,20 @@ export default function CompetitionsPage() {
8096
setDetailsDialogVisible(true);
8197
};
8298

99+
/**
100+
* Handle successful form submission (create/edit)
101+
* Refreshes the competitions list automatically
102+
*/
83103
const handleFormSubmitSuccess = () => {
84104
// Close all dialog forms
85105
setCreateDialogVisible(false);
86106
setEditDialogVisible(false);
87107
fetchCompetitionsData();
88108
};
89109

110+
/**
111+
* Renders the appropriate content based on loading state and data availability
112+
*/
90113
const renderContent = () => {
91114
if (loading) {
92115
return (
@@ -151,7 +174,7 @@ export default function CompetitionsPage() {
151174
{/* Main content */}
152175
{renderContent()}
153176

154-
{/* Competition Create Form Dialog */}
177+
{/* Competition Create Form Dialog - Only render when visible */}
155178
{createDialogVisible && (
156179
<CompetitionForm
157180
visible={createDialogVisible}
@@ -162,7 +185,7 @@ export default function CompetitionsPage() {
162185
/>
163186
)}
164187

165-
{/* Competition Edit Form Dialog */}
188+
{/* Competition Edit Form Dialog - Only render when visible and has selected competition */}
166189
{editDialogVisible && selectedCompetition && (
167190
<CompetitionForm
168191
visible={editDialogVisible}
@@ -173,7 +196,7 @@ export default function CompetitionsPage() {
173196
/>
174197
)}
175198

176-
{/* Competition Details Dialog */}
199+
{/* Competition Details Dialog - Only render when visible and has selected competition */}
177200
{detailsDialogVisible && selectedCompetition && (
178201
<CompetitionDetails
179202
visible={detailsDialogVisible}

0 commit comments

Comments
 (0)