/
opt
/
canhelp
/
apps
/
web
/
src
/
app
/
support
/
/opt/canhelp/apps/web/src/app/support
mkdir
upload
Name
Size
Mode
Actions
page.tsx
8650
0644
edit
dl
rm
Edit:
/opt/canhelp/apps/web/src/app/support/page.tsx
(8650B)
'use client' import { useState } from 'react' import Link from 'next/link' import { useLocale } from '@/context/locale' import { CAPTCHA_ENABLED, TurnstileWidget } from '@/components/Turnstile' import { sendPublicSupportMessage } from '@/lib/api' const SUPPORT_EMAIL = 'info@canhelp.gr' const CONTENT = { el: { title: 'Υποστήριξη CanHelp', intro: 'Αν χρειάζεστε βοήθεια με την εφαρμογή, στείλτε μας email ή χρησιμοποιήστε τη φόρμα επικοινωνίας μέσα στην εφαρμογή.', points: [ 'Περιγράψτε σύντομα το πρόβλημα και, αν γίνεται, επισυνάψτε στιγμιότυπο οθόνης.', 'Αν το ζήτημα αφορά σύνδεση, αναφέρετε τη συσκευή και την έκδοση της εφαρμογής.', 'Απαντάμε συνήθως μέσα σε 1-2 εργάσιμες ημέρες.', ], }, en: { title: 'CanHelp Support', intro: 'If you need help with the app, email us or use the in-app contact form.', points: [ 'Briefly describe the issue and attach a screenshot if possible.', 'If it is a login problem, include your device and app version.', 'We usually reply within 1-2 business days.', ], }, ru: { title: 'Поддержка CanHelp', intro: 'Если вам нужна помощь с приложением, напишите нам на email или используйте форму связи в приложении.', points: [ 'Кратко опишите проблему и, если возможно, приложите скриншот.', 'Если проблема со входом, укажите устройство и версию приложения.', 'Обычно мы отвечаем в течение 1-2 рабочих дней.', ], }, uk: { title: 'Підтримка CanHelp', intro: 'Якщо вам потрібна допомога з додатком, напишіть нам на email або скористайтеся формою зв’язку в додатку.', points: [ 'Коротко опишіть проблему та, якщо можливо, додайте скріншот.', 'Якщо проблема зі входом, вкажіть пристрій і версію додатка.', 'Зазвичай ми відповідаємо протягом 1-2 робочих днів.', ], }, } as const export default function SupportPage() { const { locale, t } = useLocale() const content = CONTENT[locale as keyof typeof CONTENT] ?? CONTENT.en const [name, setName] = useState('') const [email, setEmail] = useState('') const [subject, setSubject] = useState('') const [body, setBody] = useState('') const [captchaToken, setCaptchaToken] = useState(CAPTCHA_ENABLED ? '' : 'dev') const [loading, setLoading] = useState(false) const [sent, setSent] = useState(false) const [error, setError] = useState('') async function handleSubmit(e: React.FormEvent) { e.preventDefault() setError('') setLoading(true) try { await sendPublicSupportMessage({ name: name.trim(), email: email.trim(), subject: subject.trim(), body: body.trim(), captchaToken, }) setSent(true) } catch (err: any) { if ((err?.message || '').toLowerCase().includes('captcha')) { setError('Security check failed. Please try again.') setCaptchaToken('') } else { setError('Failed to send message. Please try again.') } } finally { setLoading(false) } } return ( <main className="py-12 px-4 sm:px-6"> <div className="max-w-3xl mx-auto bg-white rounded-2xl shadow-sm border border-gray-100 px-6 sm:px-10 py-10"> <div className="mb-6"> <Link href="/" className="text-sm text-green-600 hover:underline"> ← {t('nav.home')} </Link> </div> <h1 className="text-3xl font-extrabold text-gray-900 mb-3">{content.title}</h1> <p className="text-gray-600 leading-relaxed">{content.intro}</p> <div className="mt-8 space-y-3"> {content.points.map((point) => ( <div key={point} className="flex gap-3 items-start rounded-xl border border-gray-100 bg-gray-50 px-4 py-3 text-sm text-gray-700"> <span className="mt-0.5 h-2 w-2 rounded-full bg-green-500 shrink-0" /> <span>{point}</span> </div> ))} </div> <div className="mt-8 flex flex-col sm:flex-row gap-3 sm:items-center"> <a href={`mailto:${SUPPORT_EMAIL}`} className="inline-flex items-center justify-center rounded-xl bg-green-600 px-5 py-3 text-sm font-medium text-white hover:bg-green-700 transition" > {SUPPORT_EMAIL} </a> <span className="text-sm text-gray-500">{t('nav.privacy')}</span> </div> <form onSubmit={handleSubmit} className="mt-10 space-y-4 rounded-2xl border border-gray-100 bg-gray-50 p-5 sm:p-6"> <div> <h2 className="text-xl font-semibold text-gray-900 mb-1">Send a message to support</h2> <p className="text-sm text-gray-500">We will forward it directly to the admin team.</p> </div> <div className="grid gap-4 sm:grid-cols-2"> <div> <label className="block text-sm font-medium text-gray-700 mb-1">Name</label> <input value={name} onChange={(e) => setName(e.target.value)} required minLength={2} maxLength={100} className="w-full rounded-xl border border-gray-300 bg-white px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-green-500" placeholder="Your name" /> </div> <div> <label className="block text-sm font-medium text-gray-700 mb-1">Email</label> <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} required maxLength={200} className="w-full rounded-xl border border-gray-300 bg-white px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-green-500" placeholder="name@example.com" /> </div> </div> <div> <label className="block text-sm font-medium text-gray-700 mb-1">Subject</label> <input value={subject} onChange={(e) => setSubject(e.target.value)} required minLength={3} maxLength={200} className="w-full rounded-xl border border-gray-300 bg-white px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-green-500" placeholder="What do you need help with?" /> </div> <div> <label className="block text-sm font-medium text-gray-700 mb-1">Message</label> <textarea value={body} onChange={(e) => setBody(e.target.value)} required minLength={10} maxLength={5000} rows={6} className="w-full rounded-xl border border-gray-300 bg-white px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-green-500 resize-none" placeholder="Describe the problem in detail" /> </div> <div> <TurnstileWidget onSuccess={setCaptchaToken} onError={() => setCaptchaToken('')} onExpire={() => setCaptchaToken('')} /> </div> {error && <p className="text-sm text-red-600">{error}</p>} {sent ? ( <div className="rounded-xl border border-green-200 bg-green-50 px-4 py-3 text-sm text-green-800"> Your message has been sent. </div> ) : ( <button type="submit" disabled={loading || (CAPTCHA_ENABLED && !captchaToken)} className="inline-flex w-full items-center justify-center rounded-xl bg-green-600 px-5 py-3 text-sm font-medium text-white hover:bg-green-700 disabled:opacity-50" > {loading ? 'Sending...' : 'Send message'} </button> )} </form> </div> </main> ) }
Save
cmd:
run