Files
marmarislocal/app/[locale]/admin/widget-partners/[id]/WidgetPartnerForm.tsx
T
2026-07-13 14:42:07 +03:00

228 lines
8.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client'
import { useState, useRef } from 'react'
import { useRouter } from '@/i18n/routing'
import { saveWidgetPartnerAction } from '@/app/actions'
import { CheckCircle, XCircle, ArrowLeft, Copy, Code } from 'lucide-react'
import { Link } from '@/i18n/routing'
import { WidgetPartner } from '@prisma/client'
type Neighborhood = {
id: string
slug: string
nameTr: string
}
export default function WidgetPartnerForm({
partner,
neighborhoods,
locale
}: {
partner: WidgetPartner | null
neighborhoods: Neighborhood[]
locale: string
}) {
const router = useRouter()
const [error, setError] = useState<string>('')
const [loading, setLoading] = useState(false)
const [copied, setCopied] = useState(false)
const formRef = useRef<HTMLFormElement>(null)
const isEditing = !!partner
const embedCode = partner
? `<iframe
src="https://marmarislocal.com/tr/widget${partner.neighborhoodSlug ? `?neighborhood=${partner.neighborhoodSlug}` : ''}"
width="100%"
height="600"
style="border:none; border-radius: 12px; box-shadow: 0 4px 12px rgba(0,0,0,0.1);"
title="Marmaris Local Önerileri"
></iframe>`
: ''
const handleCopy = () => {
if (embedCode) {
navigator.clipboard.writeText(embedCode)
setCopied(true)
setTimeout(() => setCopied(false), 2000)
}
}
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
setError('')
setLoading(true)
if (!formRef.current) return
try {
const formData = new FormData(formRef.current)
const result = await saveWidgetPartnerAction(formData)
if (result.error) {
setError(result.error)
} else {
router.push('/admin/widget-partners')
router.refresh()
}
} catch (err: any) {
setError(err.message || 'Bir hata oluştu')
} finally {
setLoading(false)
}
}
return (
<div className="space-y-6 max-w-4xl">
<div className="flex items-center gap-4">
<Link href="/admin/widget-partners" className="p-2 hover:bg-stone/20 rounded-full transition-colors">
<ArrowLeft className="w-5 h-5 text-shutter" />
</Link>
<div>
<h2 className="text-3xl font-heading font-extrabold text-pine lowercase">
{isEditing ? 'widget partneri düzenle' : 'yeni widget partneri'}
</h2>
<p className="text-ink/65 text-xs font-medium mt-1">
Harici web sitesi bilgilerini girin ve embed kodunu alın.
</p>
</div>
</div>
{isEditing && (
<div className="bg-pine/5 border border-pine/10 p-6 rounded-2xl">
<div className="flex items-center justify-between mb-3">
<h3 className="font-heading font-bold text-pine flex items-center gap-2">
<Code className="w-5 h-5 text-turquoise" />
Widget Embed Kodu
</h3>
<button
type="button"
onClick={handleCopy}
className="flex items-center gap-1.5 px-3 py-1.5 bg-white border border-pine/10 rounded-lg text-xs font-bold text-pine hover:border-turquoise hover:text-turquoise transition-colors"
>
{copied ? <CheckCircle className="w-4 h-4 text-green-500" /> : <Copy className="w-4 h-4" />}
{copied ? 'Kopyalandı' : 'Kodu Kopyala'}
</button>
</div>
<p className="text-xs text-ink/70 mb-4">
Aşağıdaki kodu kopyalayarak partnerin web sitesine yerleştirin. Bu kod, sitenizden backlink almayı sağlar.
</p>
<pre className="bg-stone-deep/80 text-paper p-4 rounded-xl text-xs overflow-x-auto font-mono whitespace-pre-wrap">
{embedCode}
</pre>
</div>
)}
<form ref={formRef} onSubmit={handleSubmit} className="bg-paper border border-pine/8 rounded-2xl p-6 shadow-sm space-y-6">
<input type="hidden" name="id" value={partner?.id || 'new'} />
{error && (
<div className="p-4 bg-bougainvillea/10 text-bougainvillea rounded-xl text-sm flex items-start gap-3">
<XCircle className="w-5 h-5 shrink-0" />
<span>{error}</span>
</div>
)}
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="space-y-1.5">
<label htmlFor="name" className="text-xs font-bold text-pine block">Site Adı <span className="text-bougainvillea">*</span></label>
<input
type="text"
id="name"
name="name"
required
defaultValue={partner?.name || ''}
className="w-full bg-stone/30 border border-pine/10 rounded-xl px-4 py-2.5 text-sm focus:outline-none focus:border-turquoise focus:ring-1 focus:ring-turquoise transition-all"
placeholder="Örn: Marmaris Haber"
/>
</div>
<div className="space-y-1.5">
<label htmlFor="url" className="text-xs font-bold text-pine block">Site Linki (URL) <span className="text-bougainvillea">*</span></label>
<input
type="url"
id="url"
name="url"
required
defaultValue={partner?.url || ''}
className="w-full bg-stone/30 border border-pine/10 rounded-xl px-4 py-2.5 text-sm focus:outline-none focus:border-turquoise focus:ring-1 focus:ring-turquoise transition-all"
placeholder="https://marmarishaber.com"
/>
</div>
<div className="space-y-1.5">
<label htmlFor="neighborhoodSlug" className="text-xs font-bold text-pine block">Hangi Bölgenin Widget'ı?</label>
<select
id="neighborhoodSlug"
name="neighborhoodSlug"
defaultValue={partner?.neighborhoodSlug || ''}
className="w-full bg-stone/30 border border-pine/10 rounded-xl px-4 py-2.5 text-sm focus:outline-none focus:border-turquoise focus:ring-1 focus:ring-turquoise transition-all"
>
<option value="">Tüm Marmaris (Karışık)</option>
{neighborhoods.map(n => (
<option key={n.id} value={n.slug}>{n.nameTr}</option>
))}
</select>
<p className="text-[10px] text-shutter mt-1">Eğer seçilirse widget sadece o bölgedeki mekanları gösterir.</p>
</div>
<div className="flex flex-col justify-center pt-6">
<label className="flex items-center gap-3 cursor-pointer group">
<div className="relative">
<input
type="checkbox"
name="isActive"
value="true"
defaultChecked={partner ? partner.isActive : true}
className="peer sr-only"
/>
<div className="w-11 h-6 bg-stone-deep/20 rounded-full peer peer-checked:bg-turquoise transition-colors duration-300"></div>
<div className="absolute top-1 left-1 bg-white w-4 h-4 rounded-full transition-transform duration-300 peer-checked:translate-x-5 shadow-sm"></div>
</div>
<div>
<span className="text-sm font-bold text-pine block group-hover:text-turquoise transition-colors">Aktif Durum</span>
<span className="text-[10px] text-shutter">Bu widget yayında mı?</span>
</div>
</label>
</div>
</div>
<div className="flex justify-between pt-4 border-t border-pine/8">
{isEditing && (
<button
type="button"
disabled={loading}
onClick={async () => {
if (confirm('Bu partneri silmek istediğinize emin misiniz?')) {
setLoading(true)
try {
await import('@/app/actions').then(m => m.deleteWidgetPartnerAction(partner!.id))
router.push('/admin/widget-partners')
router.refresh()
} catch (e: any) {
setError(e.message)
setLoading(false)
}
}
}}
className="text-bougainvillea hover:text-bougainvillea/80 px-4 py-2 text-sm font-bold transition-colors"
>
Sil
</button>
)}
<div className="ml-auto">
<button
type="submit"
disabled={loading}
className="bg-pine text-white px-6 py-2.5 rounded-xl font-bold text-sm hover:bg-turquoise transition-colors disabled:opacity-50 flex items-center gap-2"
>
{loading ? 'Kaydediliyor...' : 'Kaydet'}
{!loading && <CheckCircle className="w-4 h-4" />}
</button>
</div>
</div>
</form>
</div>
)
}