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.

159 lines
5.4 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 {
const input = event.currentTarget as HTMLInputElement | null
return input?.value ?? (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))}
onChange={(event) => updateField('theme', readInputValue(event))}
inputProps={{ 'data-testid': 'admin-theme-input' }}
fullWidth
/>
<TextField
label="Question"
value={form().text}
onInput={(event) => updateField('text', readInputValue(event))}
onChange={(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))}
onChange={(event) => updateField('answer', readInputValue(event))}
inputProps={{ 'data-testid': 'admin-answer-input' }}
fullWidth
/>
<TextField
label="Indice"
value={form().hint}
onInput={(event) => updateField('hint', readInputValue(event))}
onChange={(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>
)
}