feature: Problem sorting, solution view raw toggle button
This commit is contained in:
+48
-14
@@ -1,9 +1,11 @@
|
||||
import { route } from 'preact-router'
|
||||
import { useState } from 'preact/hooks'
|
||||
import { isAdministrator, isStudent, Solution as SolutionModel } from '../../shared/model'
|
||||
import { isAdministrator, isStudent, Solution as SolutionModel, SolutionId } from '../../shared/model'
|
||||
import { sortByStringKey } from '../../shared/utils'
|
||||
import { server } from '../api'
|
||||
import { Header } from '../components/Header'
|
||||
import { MarkdownEditor } from '../components/MarkdownEditor'
|
||||
import { Select } from '../components/Select'
|
||||
import { Solution } from '../components/Solution'
|
||||
import { useCurrentUser, useListResource, useResource } from '../hooks'
|
||||
|
||||
@@ -25,6 +27,8 @@ const CreateProblem = ({}) => {
|
||||
)
|
||||
}
|
||||
|
||||
type SortOrder = 'latest' | 'oldest'
|
||||
|
||||
export const AdminPage = ({}) => {
|
||||
const [user] = useCurrentUser(user => {
|
||||
if (!user) {
|
||||
@@ -37,26 +41,56 @@ export const AdminPage = ({}) => {
|
||||
const [solutions, refreshSolutions, setSolutionHeuristic] =
|
||||
useListResource<SolutionModel>(`/api/solutions`)
|
||||
|
||||
const [sortOrder, setSortOrder] = useState<SortOrder>('oldest')
|
||||
|
||||
const sortedSolutions = sortByStringKey(solutions, s => s.createdAt, sortOrder === 'oldest')
|
||||
|
||||
const [trackInteracted, setTrackedInteracted] = useState<Set<SolutionId>>(new Set())
|
||||
|
||||
const hasUntrackedPending =
|
||||
sortedSolutions.filter(s => s.status === 'pending' || trackInteracted.has(s.id)).length > 0
|
||||
|
||||
return (
|
||||
user && (
|
||||
<main class="page-admin">
|
||||
<Header {...{ user }} />
|
||||
<div class="subtitle">Nuovo problema</div>
|
||||
<CreateProblem />
|
||||
<div class="subtitle">Soluzioni ancora da approvare/rifiutare</div>
|
||||
<div class="solution-list">
|
||||
{solutions.map(
|
||||
(s, index) =>
|
||||
s.status === 'pending' && (
|
||||
<Solution
|
||||
adminControls
|
||||
{...s}
|
||||
setSolution={solFn => setSolutionHeuristic(index, solFn)}
|
||||
refreshSolution={refreshSolutions}
|
||||
<div class="subtitle">Soluzioni da correggere</div>
|
||||
{hasUntrackedPending ? (
|
||||
<div class="solution-list">
|
||||
<div class="controls">
|
||||
<div class="sort-order">
|
||||
<Select
|
||||
value={sortOrder}
|
||||
setValue={setSortOrder}
|
||||
options={{
|
||||
latest: 'Prima più recenti',
|
||||
oldest: 'Prima più antichi',
|
||||
}}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{sortedSolutions.map(
|
||||
(s, index) =>
|
||||
(s.status === 'pending' || trackInteracted.has(s.id)) && (
|
||||
<Solution
|
||||
adminControls
|
||||
{...s}
|
||||
setSolution={solFn => {
|
||||
setTrackedInteracted(prev => new Set([...prev, s.id]))
|
||||
setSolutionHeuristic(index, solFn)
|
||||
}}
|
||||
refreshSolution={refreshSolutions}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<em>Nessuna soluzione ancora da correggere</em>
|
||||
</>
|
||||
)}
|
||||
</main>
|
||||
)
|
||||
)
|
||||
|
||||
+28
-4
@@ -1,17 +1,40 @@
|
||||
import { route } from 'preact-router'
|
||||
import { useEffect, useState } from 'preact/hooks'
|
||||
import { Problem as ProblemModel } from '../../shared/model'
|
||||
import { sortByNumericKey, sortByStringKey } from '../../shared/utils'
|
||||
import { Header } from '../components/Header'
|
||||
|
||||
import { Problem } from '../components/Problem'
|
||||
import { Select } from '../components/Select'
|
||||
import { useResource, useCurrentUser } from '../hooks'
|
||||
|
||||
function byTime(p: ProblemModel): string {
|
||||
return p.createdAt
|
||||
}
|
||||
|
||||
function bySolvedProblems(p: ProblemModel & { solutionsCount: number }): number {
|
||||
return p.solutionsCount
|
||||
}
|
||||
|
||||
type SortOrder = 'latest' | 'oldest' | 'top-solved' | 'least-solved'
|
||||
|
||||
const SORT_ORDER: Record<SortOrder, boolean> = {
|
||||
'latest': false,
|
||||
'oldest': true,
|
||||
'top-solved': false,
|
||||
'least-solved': true,
|
||||
}
|
||||
|
||||
export const HomePage = () => {
|
||||
const [user] = useCurrentUser()
|
||||
const [problems] = useResource<ProblemModel[]>('/api/problems', [])
|
||||
const [problems] = useResource<(ProblemModel & { solutionsCount: number })[]>('/api/problems', [])
|
||||
|
||||
console.log(problems)
|
||||
const [sortOrder, setSortOrder] = useState<SortOrder>('oldest')
|
||||
|
||||
const sortedProblems =
|
||||
sortOrder === 'latest' || sortOrder === 'oldest'
|
||||
? sortByStringKey(problems, byTime, SORT_ORDER[sortOrder])
|
||||
: sortByNumericKey(problems, bySolvedProblems, SORT_ORDER[sortOrder])
|
||||
|
||||
return (
|
||||
<main class="page-home">
|
||||
@@ -20,7 +43,8 @@ export const HomePage = () => {
|
||||
<div class="fill-row board-controls">
|
||||
<div class="sort-order">
|
||||
<Select
|
||||
value="oldest"
|
||||
value={sortOrder}
|
||||
setValue={setSortOrder}
|
||||
options={{
|
||||
'latest': 'Prima più recenti',
|
||||
'oldest': 'Prima più antichi',
|
||||
@@ -31,7 +55,7 @@ export const HomePage = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{problems.map(p => (
|
||||
{sortedProblems.map(p => (
|
||||
<Problem {...p} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import { useContext, useState } from 'preact/hooks'
|
||||
import {
|
||||
isAdministrator,
|
||||
Problem as ProblemModel,
|
||||
Solution as SolutionModel,
|
||||
} from '../../shared/model'
|
||||
import { isAdministrator, Problem as ProblemModel, Solution as SolutionModel } from '../../shared/model'
|
||||
import { server } from '../api'
|
||||
import { Header } from '../components/Header'
|
||||
import { MarkdownEditor } from '../components/MarkdownEditor'
|
||||
@@ -37,6 +33,8 @@ export const ProblemPage = ({ id }: RouteProps) => {
|
||||
content: source,
|
||||
})
|
||||
|
||||
setSource('')
|
||||
|
||||
refreshSolutions()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user