diff --git a/src/components/ProblemAdministration/ProblemAdministration.tsx b/src/components/ProblemAdministration/ProblemAdministration.tsx index 638e54a0..60a5ba77 100644 --- a/src/components/ProblemAdministration/ProblemAdministration.tsx +++ b/src/components/ProblemAdministration/ProblemAdministration.tsx @@ -9,9 +9,11 @@ import {DropzoneOptions, useDropzone} from 'react-dropzone' import {ProblemWithSolutions, SemesterWithProblems, SolutionAdministration} from '@/types/api/competition' import {PageTitleContainer} from '@/utils/PageTitleContainer' import {useHasPermissions} from '@/utils/useHasPermissions' +import {useNavigationTrap} from '@/utils/useNavigationTrap' import {Button} from '../Clickable/Button' import {Link} from '../Clickable/Link' +import {Dialog} from '../Dialog/Dialog' import {FileDropZone} from '../FileDropZone/FileDropZone' import {FileUploader} from '../FileUploader/FileUploader' import {Latex} from '../Latex/Latex' @@ -25,6 +27,16 @@ export const ProblemAdministration: FC = () => { const problemId = params && params[0] + const [isDirty, setIsDirty] = useState(false) + + const [exitDialogOpen, setExitDialogOpen] = useState(false) + const {continueNavigation} = useNavigationTrap({ + shouldBlockNavigation: isDirty, + onNavigate: () => { + setExitDialogOpen(true) + }, + }) + const { data: problemData, refetch: refetchProblem, @@ -80,6 +92,23 @@ export const ProblemAdministration: FC = () => { // nie je to ale "deep copy" - data[index] je tiez referencia na povodny objekt, treba ho skopirovat data[index] = {...data[index], score: newScore} setSolutions(data) + setIsDirty(true) + } + + const updateSolution = (index: number) => { + // array v javascripte je objekt s referenciou, pre skopirovanie odpojene od originalneho objektu treba vytvorit novy array + const data = [...(solutions ?? [])] + // nie je to ale "deep copy" - data[index] je tiez referencia na povodny objekt, treba ho skopirovat + data[index] = {...data[index], solution: 'uploaded'} + setSolutions(data) + } + + const updateCorrectedSolution = (index: number) => { + // array v javascripte je objekt s referenciou, pre skopirovanie odpojene od originalneho objektu treba vytvorit novy array + const data = [...(solutions ?? [])] + // nie je to ale "deep copy" - data[index] je tiez referencia na povodny objekt, treba ho skopirovat + data[index] = {...data[index], corrected_solution: 'uploaded'} + setSolutions(data) } const {mutate: uploadZipFile, error: uploadZipFileError} = useMutation({ @@ -124,129 +153,155 @@ export const ProblemAdministration: FC = () => { if (problemId === undefined || !problem) return Nevalidné číslo úlohy (problemId) v URL alebo ju proste nevieme fetchnúť z BE. - const handleSavePoints = () => uploadPoints(problemId) + const handleSavePoints = () => { + setIsDirty(false) + uploadPoints(problemId) + } return ( - - - Opravovanie {problem.order}. úlohy - - - Späť na semester - - + <> + + + + + } + /> + + + Opravovanie {problem.order}. úlohy - {problem.text ?? 'Načítavam...'} - -
- - Vzorové riešenie: - - {problem.solution_pdf ? ( - - - - ) : ( -
- -
- )} - -
+ + Späť na semester + +
- - - Stiahnuť riešenia - - + {problem.text ?? 'Načítavam...'} - - {uploadZipFileError && ( - <> - Chyby pri nahrávaní ZIPka: - {uploadZipFileErrors} - - )} - -
-
-
-
Riešiteľ
-
Body
-
Riešenie
-
Opravené
-
- {solutions?.map((solution, index) => ( -
-
- {solution.semester_registration?.profile.first_name} {solution.semester_registration?.profile.last_name} -
-
- updatePoints(index, event.target.value)} - className={styles.input} - /> -
-
- {solution.solution ? ( - - - - ) : ( -
- -
- )} - -
-
- {solution.corrected_solution ? ( - - - - ) : ( -
- -
- )} - -
+
+ + Vzorové riešenie: + + {problem.solution_pdf ? ( + + + + ) : ( +
+
- ))} + )} +
- - + + + Stiahnuť riešenia + - - + + + {uploadZipFileError && ( + <> + Chyby pri nahrávaní ZIPka: + {uploadZipFileErrors} + + )} + +
+
+
+
Riešiteľ
+
Body
+
Riešenie
+
Opravené
+
+ {solutions?.map((solution, index) => ( +
+
+ {solution.semester_registration?.profile.first_name}{' '} + {solution.semester_registration?.profile.last_name} +
+
+ updatePoints(index, event.target.value)} + className={styles.input} + /> +
+
+ {solution.solution ? ( + + + + ) : ( +
+ +
+ )} + updateSolution(index)} + /> +
+
+ {solution.corrected_solution ? ( + + + + ) : ( +
+ +
+ )} + updateCorrectedSolution(index)} + /> +
+
+ ))} +
+ + + + +
+ + ) } diff --git a/src/utils/useNavigationTrap.ts b/src/utils/useNavigationTrap.ts index 0cc1a5ce..8268c5e5 100644 --- a/src/utils/useNavigationTrap.ts +++ b/src/utils/useNavigationTrap.ts @@ -31,7 +31,7 @@ export const useNavigationTrap = ({shouldBlockNavigation, onNavigate}: Navigatio } const pageExit = (e: BeforeUnloadEvent) => { - e.preventDefault() + if (shouldBlockNavigation) e.preventDefault() } router.events.on('routeChangeStart', pageNavigate)