Skip to content

Commit

Permalink
Matush/Semester picker in administration (#323)
Browse files Browse the repository at this point in the history
* change semesterPicker to support admin/opravovanie

* add semesterPicker to administration

* generate type

* Move semester picker into TopGrid

* Rework url for semester administration

* Fix `Spat na semster` button and change title of ProblemAdministration

* fix lint warning

---------

Co-authored-by: Viktória Brezinová <[email protected]>
  • Loading branch information
Matushl and vikibrezinova authored Dec 12, 2023
1 parent 7e98c58 commit 13c9979
Show file tree
Hide file tree
Showing 11 changed files with 73 additions and 56 deletions.
4 changes: 1 addition & 3 deletions src/components/PageLayout/MenuMain/MenuMain.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {CloseButton} from '@/components/CloseButton/CloseButton'
import {Loading} from '@/components/Loading/Loading'
import Menu from '@/svg/menu.svg'
import {MenuItemShort} from '@/types/api/cms'
import {useDataFromURL} from '@/utils/useDataFromURL'
import {useHasPermissions} from '@/utils/useHasPermissions'
import {useSeminarInfo} from '@/utils/useSeminarInfo'

Expand All @@ -19,7 +18,6 @@ import styles from './MenuMain.module.scss'

export const MenuMain: FC = () => {
const {seminar, seminarId} = useSeminarInfo()
const {id} = useDataFromURL()

const {hasPermissions} = useHasPermissions()

Expand Down Expand Up @@ -74,7 +72,7 @@ export const MenuMain: FC = () => {
</Stack>
{hasPermissions && (
<Stack sx={{mt: 4, mx: 2, borderTop: '8px dashed white', pt: 4}}>
<MenuMainItem caption="TODO: Opravovanie" url={`/${seminar}/admin/opravovanie/${id.semesterId}`} />
<MenuMainItem caption="Opravovanie" url={`/${seminar}/admin/opravovanie/`} />
<MenuMainItem caption="Admin" url="/admin" />
</Stack>
)}
Expand Down
18 changes: 14 additions & 4 deletions src/components/PageLayout/TopGrid/TopGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {Stack, Typography} from '@mui/material'
import clsx from 'clsx'
import Link from 'next/link'
import {useRouter} from 'next/router'
import {FC} from 'react'
import {FC, useMemo} from 'react'

import {SemesterPicker} from '@/components/SemesterPicker/SemesterPicker'
import {PageTitleContainer} from '@/utils/PageTitleContainer'
Expand All @@ -15,7 +15,17 @@ export const TopGrid: FC = () => {
const {seminar} = useSeminarInfo()

// z napr. `/matik/zadania(/*)` vytiahne `zadania`
const page = useRouter().pathname.split('/')[2]
const pathname = useRouter().pathname.split('/')

const semesterPickerPage = useMemo(() => {
if (pathname[2] === 'zadania' || pathname[2] === 'vysledky') {
return pathname[2]
}
if (pathname[2] === 'admin' && pathname[3] === 'opravovanie') {
return 'admin/opravovanie'
}
return undefined
}, [pathname])

const {pageTitle} = PageTitleContainer.useContainer()

Expand All @@ -42,9 +52,9 @@ export const TopGrid: FC = () => {
<Typography variant="h1" className={styles.title}>
{pageTitle}
</Typography>
{(page === 'zadania' || page === 'vysledky') && (
{semesterPickerPage && (
<div className={styles.semesterPicker}>
<SemesterPicker page={page} />
<SemesterPicker page={semesterPickerPage} />
</div>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,3 @@


.container {
display: flex;
flex-direction: column;
row-gap: 12px;
}

.rightButton{
display: flex;
justify-content: flex-end;
}

.icon {
color: black;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
export type Styles = {
centerCell: string
container: string
icon: string
iconDisabled: string
input: string
rightButton: string
row: string
table: string
tableBody: string
Expand Down
45 changes: 31 additions & 14 deletions src/components/ProblemAdministration/ProblemAdministration.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import {FormatAlignJustify, Grading} from '@mui/icons-material'
import {Typography} from '@mui/material'
import {Stack, Typography} from '@mui/material'
import {useMutation, useQuery} from '@tanstack/react-query'
import axios from 'axios'
import {useRouter} from 'next/router'
import React, {FC, useCallback, useEffect, useState} from 'react'
import {DropzoneOptions, useDropzone} from 'react-dropzone'

import {ProblemWithSolutions, SolutionAdministration} from '@/types/api/competition'
import {ProblemWithSolutions, SemesterWithProblems, SolutionAdministration} from '@/types/api/competition'
import {PageTitleContainer} from '@/utils/PageTitleContainer'
import {useHasPermissions} from '@/utils/useHasPermissions'

import {Button} from '../Clickable/Button'
Expand All @@ -20,6 +21,7 @@ import styles from './ProblemAdministration.module.scss'
export const ProblemAdministration: FC = () => {
const router = useRouter()
const {params} = router.query
const {setPageTitle} = PageTitleContainer.useContainer()

const problemId = params && params[0]

Expand All @@ -35,6 +37,21 @@ export const ProblemAdministration: FC = () => {
})
const problem = problemData?.data

const semesterId = problem?.series.semester
const {data: semesterData, isLoading: semesterIsLoading} = useQuery({
queryKey: ['competition', 'semester', semesterId],
queryFn: () => axios.get<SemesterWithProblems>(`/api/competition/semester/${semesterId}`),
// router.query.params su v prvom renderi undefined, tak pustime query az so spravnym semesterId
enabled: semesterId !== undefined,
})
const semester = semesterData?.data
const semesterName = semester?.season_code === 0 ? 'zima' : 'leto'
const semesterUrl = `${semester?.year}/${semesterName}`

useEffect(() => {
!!problem && !!semester && setPageTitle(`${problem?.order}. úloha - ${semesterUrl} (${semester?.school_year})`)
}, [problem, semester, semesterUrl, setPageTitle])

const {hasPermissions, permissionsIsLoading} = useHasPermissions()

const [solutions, setSolutions] = useState<SolutionAdministration[]>()
Expand Down Expand Up @@ -91,22 +108,22 @@ export const ProblemAdministration: FC = () => {
},
})

if (permissionsIsLoading || problemIsLoading) return <Loading />
if (permissionsIsLoading || problemIsLoading || semesterIsLoading) return <Loading />
if (!hasPermissions) return <span>Nemáš oprávnenie na zobrazenie tejto stránky.</span>
if (problemId === undefined || !problem)
return <Typography>Nevalidné číslo úlohy (problemId) v URL alebo ju proste nevieme fetchnúť z BE.</Typography>

const handleSavePoints = () => uploadPoints(problemId)

return (
<div className={styles.container}>
<Typography variant="h2">Opravovanie {problem.order}. úlohy</Typography>
<Stack gap={2}>
<Stack direction="row" justifyContent="space-between">
<Typography variant="h2">Opravovanie {problem.order}. úlohy</Typography>

<div className={styles.rightButton}>
<Link variant="button2" href={`/strom/admin/opravovanie/${problem.series.semester}`}>
<Link variant="button2" href={`/strom/admin/opravovanie/${semesterUrl}`}>
Späť na semester
</Link>
</div>
</Stack>

<Latex>{problem.text ?? 'Načítavam...'}</Latex>

Expand All @@ -129,19 +146,19 @@ export const ProblemAdministration: FC = () => {
/>
</div>

<div className={styles.rightButton}>
<Stack alignItems="end">
<Link variant="button2" href={`/api/competition/problem/${problemId}/download-solutions`}>
Stiahnuť riešenia
</Link>
</div>
</Stack>

<FileDropZone
getRootProps={getRootProps}
getInputProps={getInputProps}
text="Vlož opravené riešenia vo formáte zip"
/>

<form className={styles.container}>
<form>
<div className={styles.table}>
<div className={styles.tableHeader}>
<div>Riešiteľ</div>
Expand Down Expand Up @@ -207,12 +224,12 @@ export const ProblemAdministration: FC = () => {
))}
</div>

<div className={styles.rightButton}>
<Stack alignItems="end" mt={1.5}>
<Button variant="button2" onClick={handleSavePoints}>
Uložiť body
</Button>
</div>
</Stack>
</form>
</div>
</Stack>
)
}
4 changes: 2 additions & 2 deletions src/components/PublicationUploader/PublicationUploader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {Link} from '../Clickable/Link'
import {FileUploader} from '../FileUploader/FileUploader'

interface PublicationUploaderProps {
semesterId: string
semesterId: number
order: number
semesterData: SemesterWithProblems
}
Expand All @@ -20,7 +20,7 @@ export const PublicationUploader: FC<PublicationUploaderProps> = ({semesterId, o

const appendFormData = (formData: FormData) => {
formData.append('publication_type', 'Časopisy')
formData.append('event', semesterId)
formData.append('event', semesterId.toString())
formData.append('order', order.toString())
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
.textarea {
width: 100%;
}
}
25 changes: 14 additions & 11 deletions src/components/SemesterAdministration/SemesterAdministration.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import {Stack, Typography} from '@mui/material'
import {useQuery} from '@tanstack/react-query'
import axios from 'axios'
import {useRouter} from 'next/router'
import {FC, useState} from 'react'

import {Button} from '@/components/Clickable/Button'
import {Link} from '@/components/Clickable/Link'
import {SemesterWithProblems} from '@/types/api/generated/competition'
import {formatDateTime} from '@/utils/formatDate'
import {useDataFromURL} from '@/utils/useDataFromURL'
import {useHasPermissions} from '@/utils/useHasPermissions'

import {Loading} from '../Loading/Loading'
Expand All @@ -26,10 +26,10 @@ interface PostalCard {
}

export const SemesterAdministration: FC = () => {
const router = useRouter()
const {params} = router.query

const semesterId = params && params[0]
const {
id: {semesterId},
loading: urlDataLoading,
} = useDataFromURL()

const {hasPermissions, permissionsIsLoading} = useHasPermissions()

Expand Down Expand Up @@ -84,8 +84,14 @@ export const SemesterAdministration: FC = () => {
)
}

if (permissionsIsLoading || semesterIsLoading) return <Loading />
if (!hasPermissions) return <span>Nemáš oprávnenie na zobrazenie tejto stránky.</span>
if (
urlDataLoading.currentSeriesIsLoading ||
urlDataLoading.semesterListIsLoading ||
permissionsIsLoading ||
semesterIsLoading
)
return <Loading />
if (!hasPermissions) return <Typography variant="body1">Nemáš oprávnenie na zobrazenie tejto stránky.</Typography>
if (semesterId === undefined || !semester)
return (
<Typography variant="body1">
Expand All @@ -95,10 +101,7 @@ export const SemesterAdministration: FC = () => {

return (
<>
<Typography variant="h1">
{semester.year}. ročník ({semester.school_year}) - {semester.season_code === 0 ? 'zima' : 'leto'}
</Typography>
<Typography variant="body1">Administrácia semestra pre opravovateľov.</Typography>
<Typography variant="h3">Administrácia semestra pre opravovateľov.</Typography>
{semester.series_set.map((series) => (
<Stack key={series.id} gap={1} mt={5}>
<Typography variant="h2">{series.order}. séria</Typography>
Expand Down
12 changes: 8 additions & 4 deletions src/components/SemesterPicker/SemesterPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export interface SemesterListItem {
series_set: SeriesListItem[]
}

export const SemesterPicker: FC<{page: 'zadania' | 'vysledky'}> = ({page}) => {
export const SemesterPicker: FC<{page: 'zadania' | 'vysledky' | 'admin/opravovanie'}> = ({page}) => {
const {seminar} = useSeminarInfo()
const {setPageTitle} = PageTitleContainer.useContainer()

Expand All @@ -42,15 +42,19 @@ export const SemesterPicker: FC<{page: 'zadania' | 'vysledky'}> = ({page}) => {
let pageTitleToSet = ''
if (semester) {
const semesterTitle = `${semester?.year}. ročník - ${semester?.season_code === 0 ? 'zimný' : 'letný'} semester`
if (displayWholeSemesterOnResults) {
if (page === 'admin/opravovanie') {
pageTitleToSet = `Opravovanie - ${semester?.year}/${semester?.season_code === 0 ? 'zima' : 'leto'} (${
semester?.school_year
})`
} else if (displayWholeSemesterOnResults) {
pageTitleToSet = semesterTitle
} else if (series) {
pageTitleToSet = `${semesterTitle}${series?.order ? ` - ${series?.order}. séria` : ''}`
}
}
setPageTitle(pageTitleToSet)
// `semester` a `series` su nami vytiahnute objekty, tak mozu triggerovat effekt kazdy render. nemalo by vadit
}, [displayWholeSemesterOnResults, semester, series, setPageTitle])
}, [displayWholeSemesterOnResults, semester, series, page, setPageTitle])

const dropdownSemesterList = semesterList.map((semester) => {
return {
Expand Down Expand Up @@ -85,7 +89,7 @@ export const SemesterPicker: FC<{page: 'zadania' | 'vysledky'}> = ({page}) => {

return (
<div className={styles.menu}>
<Dropdown title={'Séria'} options={dropdownSeriesList} />
{page !== 'admin/opravovanie' && <Dropdown title={'Séria'} options={dropdownSeriesList} />}
<Dropdown title={'Semester'} options={dropdownSemesterList} />
</div>
)
Expand Down
2 changes: 1 addition & 1 deletion src/pages/strom/admin/opravit-ulohu/[[...params]].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {PageLayout} from '@/components/PageLayout/PageLayout'
import {ProblemAdministration as ProblemAdministrationComponent} from '@/components/ProblemAdministration/ProblemAdministration'

const ProblemAdministration: NextPage = () => (
<PageLayout contentWidth={2} title="Opravovanie série">
<PageLayout contentWidth={2} title="Opravovanie úlohy">
<ProblemAdministrationComponent />
</PageLayout>
)
Expand Down
2 changes: 1 addition & 1 deletion src/pages/strom/admin/opravovanie/[[...params]].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {PageLayout} from '@/components/PageLayout/PageLayout'
import {SemesterAdministration as SemesterAdministrationComponent} from '@/components/SemesterAdministration/SemesterAdministration'

const SemesterAdmnistration: NextPage = () => (
<PageLayout contentWidth={2} title="Opravovanie série">
<PageLayout contentWidth={2} title="Opravovanie semestra">
<SemesterAdministrationComponent />
</PageLayout>
)
Expand Down

0 comments on commit 13c9979

Please sign in to comment.