feat: link alla pagina scores e qualche tweak allo stile della tabella scores

pull/1/head
Antonio De Lucreziis 2 years ago
parent 0ad660b33c
commit 19541630fc

@ -22,6 +22,11 @@ export const Header = ({ noLogin }: Props) => {
<a href={prependBaseUrl('/')}>PHC / Problemi</a> <a href={prependBaseUrl('/')}>PHC / Problemi</a>
</div> </div>
<nav> <nav>
<div class="nav-item">
<Link activeClassName="active" href={prependBaseUrl('/scores')}>
Classifica
</Link>
</div>
{user ? ( {user ? (
<> <>
{isAdministrator(user.role) && ( {isAdministrator(user.role) && (

@ -1,5 +1,5 @@
import { useContext, useState } from 'preact/hooks' import { useContext, useState } from 'preact/hooks'
import { Solution as SolutionModel, SolutionStat, User } from '../../shared/model' import { SolutionStat } from '../../shared/model'
import { sortByNumericKey, sortByStringKey } from '../../shared/utils' import { sortByNumericKey, sortByStringKey } from '../../shared/utils'
import { Header } from '../components/Header' import { Header } from '../components/Header'
@ -16,13 +16,13 @@ export const ScoresPage = () => {
type Order = 'ascending' | 'descending' type Order = 'ascending' | 'descending'
type SortStateSpace = [Column, Order] type SortStateSpace = [Column, Order]
const [[sortStateColumn, sortStateOrder], setSortState] = useState<SortStateSpace>(['sent', 'descending']) const [[sortStateColumn, sortStateOrder], setSortState] = useState<SortStateSpace>(['correct', 'descending'])
const transitionColumn: (k: Column) => Partial<Record<Column, Record<Order, (c: Column) => SortStateSpace>>> = k => ({ const transitionColumn: (k: Column) => Partial<Record<Column, Record<Order, (c: Column) => SortStateSpace>>> = k => ({
[k]: { [k]: {
'ascending': (c: Column) => c === k ? [k, 'descending'] : [c, 'ascending'], ascending: (c: Column) => (c === k ? [k, 'descending'] : [c, 'ascending']),
'descending': (c: Column) => c === k ? [k, 'ascending'] : [c, 'ascending'] descending: (c: Column) => (c === k ? [k, 'ascending'] : [c, 'ascending']),
} },
}) })
const transitionMap: Record<Column, Record<Order, (c: Column) => SortStateSpace>> = { const transitionMap: Record<Column, Record<Order, (c: Column) => SortStateSpace>> = {
@ -36,8 +36,12 @@ export const ScoresPage = () => {
if (sortStateColumn === 'student') { if (sortStateColumn === 'student') {
orderedStats = sortByStringKey(Object.entries(stats), ([user, s]) => user, sortStateOrder === 'ascending') orderedStats = sortByStringKey(Object.entries(stats), ([user, s]) => user, sortStateOrder === 'ascending')
} else { } else {
// @ts-ignore orderedStats = sortByNumericKey(
orderedStats = sortByNumericKey(Object.entries(stats), ([user, s]) => s[sortStateColumn + 'SolutionsCount'], sortStateOrder === 'ascending') Object.entries(stats),
// @ts-ignore
([user, s]) => s[sortStateColumn + 'SolutionsCount'],
sortStateOrder === 'ascending'
)
} }
return ( return (
@ -49,20 +53,37 @@ export const ScoresPage = () => {
<div class="cell header"> <div class="cell header">
<span>Studente</span> <span>Studente</span>
<span onClick={() => setSortState(transitionMap[sortStateColumn][sortStateOrder]('student'))}> <span onClick={() => setSortState(transitionMap[sortStateColumn][sortStateOrder]('student'))}>
<span class="material-symbols-outlined icon">{sortStateColumn === 'student' ? (sortStateOrder === 'ascending' ? 'expand_more' : 'expand_less') : 'unfold_more'}</span> <span class="material-symbols-outlined icon">
{sortStateColumn === 'student'
? sortStateOrder === 'ascending'
? 'expand_more'
: 'expand_less'
: 'unfold_more'}
</span>
</span> </span>
</div> </div>
<div class="cell header"> <div class="cell header">
<span>Soluzioni Inviate</span> <span>Soluzioni Inviate</span>
<span onClick={() => setSortState(transitionMap[sortStateColumn][sortStateOrder]('sent'))}> <span onClick={() => setSortState(transitionMap[sortStateColumn][sortStateOrder]('sent'))}>
<span class="material-symbols-outlined icon">{sortStateColumn === 'sent' ? (sortStateOrder === 'ascending' ? 'expand_more' : 'expand_less') : 'unfold_more'}</span> <span class="material-symbols-outlined icon">
{sortStateColumn === 'sent'
? sortStateOrder === 'ascending'
? 'expand_more'
: 'expand_less'
: 'unfold_more'}
</span>
</span> </span>
</div> </div>
<div class="cell header"> <div class="cell header">
<span>Soluzioni Corrette</span> <span>Soluzioni Corrette</span>
<span onClick={() => setSortState(transitionMap[sortStateColumn][sortStateOrder]('correct'))}> <span onClick={() => setSortState(transitionMap[sortStateColumn][sortStateOrder]('correct'))}>
<span class="material-symbols-outlined icon">{sortStateColumn === 'correct' ? (sortStateOrder === 'ascending' ? 'expand_more' : 'expand_less') : 'unfold_more'}</span> <span class="material-symbols-outlined icon">
{sortStateColumn === 'correct'
? sortStateOrder === 'ascending'
? 'expand_more'
: 'expand_less'
: 'unfold_more'}
</span>
</span> </span>
</div> </div>
{orderedStats.map(([user, s]) => ( {orderedStats.map(([user, s]) => (
@ -73,7 +94,7 @@ export const ScoresPage = () => {
</> </>
))} ))}
</div> </div>
</main > </main>
</> </>
) )
} }

@ -223,7 +223,7 @@ p {
margin: 0; margin: 0;
} }
p+p { p + p {
margin-top: 0.5rem; margin-top: 0.5rem;
} }
@ -353,6 +353,7 @@ main.page-scores {
grid-template-columns: auto auto auto; grid-template-columns: auto auto auto;
box-shadow: -2px 4px 6px 1px #00000018, 0 0 4px 0px #00000010; box-shadow: -2px 4px 6px 1px #00000018, 0 0 4px 0px #00000010;
border: 1px solid #ddd;
border-radius: 0.5rem; border-radius: 0.5rem;
background: #ffffff; background: #ffffff;
@ -366,19 +367,17 @@ main.page-scores {
overflow: hidden; overflow: hidden;
position: relative;
.cell { .cell {
text-align: center; padding: 1rem 1rem 1rem 2rem;
padding: 1rem 2rem;
display: flex;
align-items: center;
text-align: center;
gap: 0.5rem; gap: 0.5rem;
border-left: 1px solid #ddd; border-left: 1px solid #ddd;
border-top: 1px solid #ddd; border-top: 1px solid #ddd;
&:nth-child(3n+1) { &:nth-child(3n + 1) {
border-left: none; border-left: none;
} }
@ -392,13 +391,55 @@ main.page-scores {
font-weight: 400; font-weight: 400;
font-size: 22px; font-size: 22px;
background: #fdfdfd; background: #f0f0f0;
padding-right: 1rem; display: flex;
align-items: center;
text-align: center;
justify-content: space-between;
} }
}
&:not(.header) {
user-select: text;
&:nth-child(3n + 1) {
text-align: left;
}
&:nth-child(3n + 2),
&:nth-child(3n + 3) {
text-align: center;
}
&:nth-child(3n + 3) {
&::after {
content: '';
position: absolute;
left: 0;
right: 0;
height: 3rem;
transform: translate(0, -1rem);
pointer-events: none;
background: transparent;
}
&:hover::after {
background: #00000006;
}
}
&:hover {
&:nth-child(3n + 1) + .cell + .cell::after {
background: #00000006;
}
&:nth-child(3n + 2) + .cell::after {
background: #00000006;
}
}
}
}
} }
} }
@ -693,8 +734,7 @@ header {
} }
// On mobile // On mobile
@media screen and (max-width: $device-s-width), @media screen and (max-width: $device-s-width), (pointer: coarse) {
(pointer: coarse) {
main { main {
padding: 2rem 1rem 6rem; padding: 2rem 1rem 6rem;
@ -761,8 +801,7 @@ header {
} }
} }
@media screen and (max-width: $device-m-width), @media screen and (max-width: $device-m-width), (pointer: coarse) {
(pointer: coarse) {
.markdown-editor { .markdown-editor {
grid-template-columns: auto; grid-template-columns: auto;
grid-template-rows: auto auto; grid-template-rows: auto auto;

Loading…
Cancel
Save