Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Matush/Semester picker in administration #323

Merged
merged 7 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading