import React, { useState, useEffect } from 'react' import { useNavigate, useParams } from 'react-router-dom' import { useTranslation } from 'react-i18next' import { Box, Heading, Button, Input, Textarea, VStack, HStack, Text, Field, Tabs, } from '@chakra-ui/react' import ReactMarkdown from 'react-markdown' import { useGetTaskQuery, useCreateTaskMutation, useUpdateTaskMutation, } from '../../__data__/api/api' import { URLs } from '../../__data__/urls' import { LoadingSpinner } from '../../components/LoadingSpinner' import { ErrorAlert } from '../../components/ErrorAlert' import { toaster } from '../../components/ui/toaster' export const TaskFormPage: React.FC = () => { const { id } = useParams<{ id: string }>() const navigate = useNavigate() const isEdit = !!id const { t } = useTranslation() const { data: task, isLoading: isLoadingTask, error: loadError } = useGetTaskQuery(id!, { skip: !id, }) const [createTask, { isLoading: isCreating }] = useCreateTaskMutation() const [updateTask, { isLoading: isUpdating }] = useUpdateTaskMutation() const [title, setTitle] = useState('') const [description, setDescription] = useState('') const [hiddenInstructions, setHiddenInstructions] = useState('') const [showDescPreview, setShowDescPreview] = useState(false) useEffect(() => { if (task) { setTitle(task.title) setDescription(task.description) setHiddenInstructions(task.hiddenInstructions || '') } }, [task]) const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() if (!title.trim() || !description.trim()) { toaster.create({ title: t('challenge.admin.common.validation.error'), description: t('challenge.admin.tasks.validation.fill.required.fields'), type: 'error', }) return } try { if (isEdit && id) { await updateTask({ id, data: { title: title.trim(), description: description.trim(), hiddenInstructions: hiddenInstructions.trim() || undefined, }, }).unwrap() toaster.create({ title: t('challenge.admin.common.success'), description: t('challenge.admin.tasks.updated'), type: 'success', }) } else { await createTask({ title: title.trim(), description: description.trim(), hiddenInstructions: hiddenInstructions.trim() || undefined, }).unwrap() toaster.create({ title: t('challenge.admin.common.success'), description: t('challenge.admin.tasks.created'), type: 'success', }) } navigate(URLs.tasks) } catch (err: unknown) { const errorMessage = (err && typeof err === 'object' && 'data' in err && err.data && typeof err.data === 'object' && 'error' in err.data && err.data.error && typeof err.data.error === 'object' && 'message' in err.data.error && typeof err.data.error.message === 'string') ? err.data.error.message : t('challenge.admin.tasks.save.error') toaster.create({ title: t('challenge.admin.common.error'), description: errorMessage, type: 'error', }) } } if (isEdit && isLoadingTask) { return } if (isEdit && loadError) { return } const isLoading = isCreating || isUpdating return ( {isEdit ? t('challenge.admin.tasks.edit.title') : t('challenge.admin.tasks.create.title')} {/* Title */} {t('challenge.admin.tasks.field.title')} setTitle(e.target.value)} placeholder={t('challenge.admin.tasks.field.title.placeholder')} maxLength={255} disabled={isLoading} /> {t('challenge.admin.tasks.field.title.helper')} {/* Description with Markdown */} {t('challenge.admin.tasks.field.description')} setShowDescPreview(e.value === 'preview')} > {t('challenge.admin.tasks.tab.editor')} {t('challenge.admin.tasks.tab.preview')}