'use client' import { useMemo, useState } from 'react' import { useTranslations } from 'next-intl' import { WowheadLink } from '@/components/WowheadLink' import { CharacterSelect } from '@/components/CharacterSelect' import { Turnstile } from '@/components/Turnstile' export interface QuestCharacter { name: string classCss: string level: number } export interface QuestOptionClient { key: string classCss: string | null label: string minLevel: number hasData: boolean } interface QuestStatus { quest: number state: 'rewarded' | 'inProgress' | 'none' } function trackerError(t: ReturnType, error?: string, minutes?: number): string { switch (error) { case 'missingFields': return t('quest.errors.missingFields') case 'characterNotOwned': return t('quest.errors.characterNotOwned') case 'characterOnline': return t('quest.errors.characterOnline') case 'wrongClass': return t('quest.errors.wrongClass') case 'levelTooLow': return t('quest.errors.levelTooLow') case 'invalidQuestId': return t('quest.errors.invalidQuestId') case 'invalidOption': case 'noData': return t('quest.errors.noData') case 'cooldown': return t('quest.errors.cooldown', { minutes: minutes ?? 0 }) case 'captcha': return t('quest.errors.captcha') case 'notAuthenticated': return t('quest.errors.notAuthenticated') default: return t('quest.errors.default') } } export function QuestTrackerForm({ characters, options }: { characters: QuestCharacter[]; options: QuestOptionClient[] }) { const t = useTranslations('CharService') const [character, setCharacter] = useState('') const [option, setOption] = useState('') const [questId, setQuestId] = useState('') const [captcha, setCaptcha] = useState('') const [captchaKey, setCaptchaKey] = useState(0) const [busy, setBusy] = useState(false) const [message, setMessage] = useState<{ ok: boolean; text: string } | null>(null) const [result, setResult] = useState<{ label: string; statuses: QuestStatus[] } | null>(null) const selected = characters.find((c) => c.name === character) // Opciones que el personaje elegido puede rastrear (clase + nivel + con datos), // más la búsqueda por misión específica (nivel >= 10). const available = useMemo(() => { if (!selected) return [] as { key: string; label: string }[] const list = options .filter((o) => o.hasData && (o.classCss === null || o.classCss === selected.classCss) && selected.level >= o.minLevel) .map((o) => ({ key: o.key, label: o.label })) if (selected.level >= 10) list.push({ key: 'specific', label: t('quest.specificLabel') }) return list }, [selected, options, t]) function onCharacter(v: string) { setCharacter(v) setOption('') setQuestId('') setResult(null) setMessage(null) } async function handleSubmit(e: React.FormEvent) { e.preventDefault() if (busy || !character || !option) return setBusy(true) setMessage(null) setResult(null) try { const res = await fetch('/api/character/quest', { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'same-origin', body: JSON.stringify({ character, option, questId: option === 'specific' ? Number(questId) : undefined, turnstile: captcha }), }) const data: { success?: boolean; error?: string; minutes?: number; label?: string; statuses?: QuestStatus[] } = await res.json() if (data.success && data.statuses) { setResult({ label: data.label ?? '', statuses: data.statuses }) } else { setMessage({ ok: false, text: trackerError(t, data.error, data.minutes) }) } } catch { setMessage({ ok: false, text: trackerError(t) }) } finally { setBusy(false) setCaptcha('') setCaptchaKey((k) => k + 1) } } if (characters.length === 0) { return (

{t('quest.noCharacters')}
) } const stateText = (s: QuestStatus['state']) => s === 'rewarded' ? { text: t('quest.stateCompleted'), cls: 'green-info2' } : s === 'inProgress' ? { text: t('quest.stateInProgress'), cls: 'yellow-info' } : { text: t('quest.stateNotStarted'), cls: 'third-brown' } return (


{option === 'specific' && ( <> setQuestId(e.target.value)} required />
)}
{message && {message.text}} {result && (

{result.label}

{result.statuses.map((s) => { const st = stateText(s.state) return ( ) })}
{t('quest.questNumber', { quest: s.quest })} {st.text}
)}
) }