You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
154 lines
5.0 KiB
TypeScript
154 lines
5.0 KiB
TypeScript
import { For, createSignal, type JSX } from 'solid-js'
|
|
|
|
import Box from '@suid/material/Box'
|
|
import Button from '@suid/material/Button'
|
|
import Card from '@suid/material/Card'
|
|
import CardContent from '@suid/material/CardContent'
|
|
import MenuItem from '@suid/material/MenuItem'
|
|
import Stack from '@suid/material/Stack'
|
|
import TextField from '@suid/material/TextField'
|
|
import Typography from '@suid/material/Typography'
|
|
|
|
import {
|
|
createAdminQuestion,
|
|
deleteAdminQuestion,
|
|
listAdminQuestions,
|
|
type AdminQuestion,
|
|
type CreateQuestionInput,
|
|
} from '../services/adminQuestions'
|
|
|
|
type FormState = CreateQuestionInput
|
|
|
|
const defaultState: FormState = {
|
|
theme: 'Général',
|
|
text: '',
|
|
answer: '',
|
|
hint: '',
|
|
difficulty: 'medium',
|
|
}
|
|
|
|
function readInputValue(event: Event): string {
|
|
return (event.target as HTMLInputElement).value
|
|
}
|
|
|
|
export default function AdminQuestionsRoute(): JSX.Element {
|
|
const [items, setItems] = createSignal<AdminQuestion[]>(listAdminQuestions())
|
|
const [form, setForm] = createSignal<FormState>(defaultState)
|
|
const [error, setError] = createSignal<string | null>(null)
|
|
|
|
const updateField = (key: keyof FormState, value: string): void => {
|
|
setForm((prev) => ({ ...prev, [key]: value }) as FormState)
|
|
}
|
|
|
|
const submit = (): void => {
|
|
const current = form()
|
|
if (!current.theme.trim() || !current.text.trim() || !current.answer.trim()) {
|
|
setError('Theme, question et réponse sont requis.')
|
|
return
|
|
}
|
|
|
|
createAdminQuestion(current)
|
|
setItems(listAdminQuestions())
|
|
setForm(defaultState)
|
|
setError(null)
|
|
}
|
|
|
|
const remove = (id: string): void => {
|
|
deleteAdminQuestion(id)
|
|
setItems(listAdminQuestions())
|
|
}
|
|
|
|
return (
|
|
<Box>
|
|
<Stack spacing={2}>
|
|
<Typography variant="h4" sx={{ fontWeight: 800 }}>
|
|
Admin - Questions
|
|
</Typography>
|
|
|
|
<Card variant="outlined" sx={{ bgcolor: '#111827', borderColor: '#1f2937' }}>
|
|
<CardContent>
|
|
<Stack spacing={2}>
|
|
<Typography variant="h6">Créer une question</Typography>
|
|
{error() && <Typography color="error">{error()}</Typography>}
|
|
|
|
<TextField
|
|
label="Theme"
|
|
value={form().theme}
|
|
onInput={(event) => updateField('theme', readInputValue(event))}
|
|
inputProps={{ 'data-testid': 'admin-theme-input' }}
|
|
fullWidth
|
|
/>
|
|
|
|
<TextField
|
|
label="Question"
|
|
value={form().text}
|
|
onInput={(event) => updateField('text', readInputValue(event))}
|
|
inputProps={{ 'data-testid': 'admin-question-input' }}
|
|
fullWidth
|
|
/>
|
|
|
|
<TextField
|
|
label="Réponse"
|
|
value={form().answer}
|
|
onInput={(event) => updateField('answer', readInputValue(event))}
|
|
inputProps={{ 'data-testid': 'admin-answer-input' }}
|
|
fullWidth
|
|
/>
|
|
|
|
<TextField
|
|
label="Indice"
|
|
value={form().hint}
|
|
onInput={(event) => updateField('hint', readInputValue(event))}
|
|
inputProps={{ 'data-testid': 'admin-hint-input' }}
|
|
fullWidth
|
|
/>
|
|
|
|
<TextField
|
|
select
|
|
label="Difficulté"
|
|
value={form().difficulty}
|
|
onChange={(event) => updateField('difficulty', readInputValue(event))}
|
|
inputProps={{ 'data-testid': 'admin-difficulty-select' }}
|
|
fullWidth
|
|
>
|
|
<MenuItem value="easy">easy</MenuItem>
|
|
<MenuItem value="medium">medium</MenuItem>
|
|
<MenuItem value="hard">hard</MenuItem>
|
|
</TextField>
|
|
|
|
<Button variant="contained" onClick={submit} data-testid="admin-create-question">
|
|
Ajouter la question
|
|
</Button>
|
|
</Stack>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card variant="outlined" sx={{ bgcolor: '#111827', borderColor: '#1f2937' }}>
|
|
<CardContent>
|
|
<Stack spacing={1}>
|
|
<Typography variant="h6">Questions existantes</Typography>
|
|
<For each={items()}>
|
|
{(item) => (
|
|
<Stack spacing={1} sx={{ border: '1px solid #1f2937', p: 1.5, borderRadius: 1 }}>
|
|
<Typography sx={{ fontWeight: 700 }}>{item.text}</Typography>
|
|
<Typography sx={{ opacity: 0.8 }}>Theme: {item.theme}</Typography>
|
|
<Typography sx={{ opacity: 0.8 }}>Réponse: {item.answer}</Typography>
|
|
<Button
|
|
variant="outlined"
|
|
color="error"
|
|
onClick={() => remove(item.id)}
|
|
data-testid={`admin-delete-${item.id}`}
|
|
>
|
|
Supprimer
|
|
</Button>
|
|
</Stack>
|
|
)}
|
|
</For>
|
|
</Stack>
|
|
</CardContent>
|
|
</Card>
|
|
</Stack>
|
|
</Box>
|
|
)
|
|
}
|