import { useState } from 'react'; import { Stack, Title, Group, Button, Badge, ActionIcon, Modal, Text, TextInput, Paper, Card, Alert, Select, NumberInput, } from '@mantine/core'; import { useDisclosure } from '@mantine/hooks'; import { useTranslation } from 'react-i18next'; import { IconEdit, IconTrash, IconPlus, IconInfoCircle } from '@tabler/icons-react'; import { notify, useErrorHandler, AdvancedTable, useServerTable, type AdvancedColumn } from '@ema-platform/ui'; import { useGetCertificationsQuery } from '../../certification/api/certification-api'; import { useGetQuestionsQuery, useCreateQuestionMutation, useUpdateQuestionMutation, useDeleteQuestionMutation, } from '../api/question-api'; import type { Question, QuestionForm } from '../types/question'; function QuestionForm({ editing, certOptions, isSubmitting, onSubmit, onCancel, }: { editing: Question | null; certOptions: { value: string; label: string }[]; isSubmitting: boolean; onSubmit: (values: { certificationId: string; titleEn: string; titleAm: string; form: string; points: number; days: number; hours: number; minutes: number; }, isEdit: boolean) => void; onCancel: () => void; }) { const { t } = useTranslation(); const [certificationId, setCertificationId] = useState(editing?.certificationId ?? null); const [titleEn, setTitleEn] = useState(editing?.title?.en ?? ''); const [titleAm, setTitleAm] = useState(editing?.title?.am ?? ''); const [form, setForm] = useState(editing?.form ?? null); const [points, setPoints] = useState(editing?.points ?? 0); const [days, setDays] = useState(editing?.time?.days ?? 0); const [hours, setHours] = useState(editing?.time?.hours ?? 0); const [minutes, setMinutes] = useState(editing?.time?.minutes ?? 0); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (!certificationId || !titleEn || !titleAm || !form) { notify.error('Please fill all required fields'); return; } onSubmit({ certificationId, titleEn, titleAm, form, points, days, hours, minutes }, !!editing); }; return (
setPoints(Number(v))} min={0} size="sm" required /> {t('question.form.timeAllowed')} setDays(Number(v))} min={0} size="sm" /> setHours(Number(v))} min={0} size="sm" /> setMinutes(Number(v))} min={0} size="sm" />
); } export function QuestionPage() { const { t, i18n } = useTranslation(); const locale = i18n.language as 'en' | 'am'; const { handleError } = useErrorHandler(); const { data: certRes } = useGetCertificationsQuery(); const { data, isFetching, isError, refetch } = useGetQuestionsQuery(); const { setPageIndex, pageSize, paginate } = useServerTable(); const [createQ, { isLoading: isCreating }] = useCreateQuestionMutation(); const [updateQ, { isLoading: isUpdating }] = useUpdateQuestionMutation(); const [deleteQ] = useDeleteQuestionMutation(); const certifications = certRes?.items ?? []; const questions = data?.items ?? []; const [editing, setEditing] = useState(null); const [showForm, setShowForm] = useState(false); const [deleteTarget, setDeleteTarget] = useState(null); const [deleteOpened, { open: openDelete, close: closeDelete }] = useDisclosure(false); const [certFilter, setCertFilter] = useState(null); const certOptions = certifications.filter((c) => c.isActive).map((c) => ({ value: c.id, label: c.name[locale] })); const filtered = questions.filter((q) => !certFilter || q.certificationId === certFilter); const page = paginate(filtered); const getCertName = (id: string) => certifications.find((c) => c.id === id)?.name?.[locale] ?? '-'; const resetForm = () => { setEditing(null); setShowForm(false); }; const handleSubmit = async (values: { certificationId: string; titleEn: string; titleAm: string; form: string; points: number; days: number; hours: number; minutes: number; }, isEdit: boolean) => { const title = { en: values.titleEn, am: values.titleAm }; const time = { days: values.days, hours: values.hours, minutes: values.minutes }; try { if (isEdit && editing) { await updateQ({ id: editing.id, certificationId: values.certificationId, title, form: values.form as QuestionForm, points: values.points, time }).unwrap(); notify.success(t('question.updated')); } else { await createQ({ certificationId: values.certificationId, title, description: { en: '', am: '' }, form: values.form as QuestionForm, points: values.points, time }).unwrap(); notify.success(t('question.created')); } resetForm(); } catch (e) { handleError(e); } }; const handleDelete = async () => { if (!deleteTarget) return; try { await deleteQ(deleteTarget.id).unwrap(); notify.success(t('question.deleted')); closeDelete(); setDeleteTarget(null); } catch (e) { handleError(e); } }; if (isError) return } color="red" title={t('question.loadError')} />; const columns: AdvancedColumn[] = [ { header: t('question.columns.title'), cell: ({ row }) => {row.original.title[locale]}, }, { header: t('question.columns.certification'), cell: ({ row }) => {getCertName(row.original.certificationId)}, }, { header: t('question.columns.form'), cell: ({ row }) => ( {t(`question.form.${row.original.form === 'ESSAY' ? 'essay' : 'choice'}`)} ), }, { header: t('question.columns.points'), cell: ({ row }) => {row.original.points}, }, { header: t('question.columns.status'), cell: ({ row }) => ( {row.original.isActive ? t('question.status.active') : t('question.status.inactive')} ), }, { header: '', label: t('question.columns.actions', 'Actions'), cell: ({ row }) => ( { setEditing(row.original); setShowForm(true); }}> { setDeleteTarget(row.original); openDelete(); }}> ), }, ]; return ( {t('question.title')} {!showForm && ( )} {showForm && ( )} {t('question.pool')}