Files
marmarislocal/app/[locale]/admin/collections/[id]/CollectionForm.tsx
T

190 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 } from 'react'
import { useRouter } from 'next/navigation'
import { createOrUpdateCollectionAction } from '@/app/actions'
import { Link } from '@/i18n/routing'
import { ArrowLeft, Save } from 'lucide-react'
interface Option {
value: string
label: string
}
interface FormProps {
collection: any | null
allListings: Option[]
}
export default function CollectionForm({ collection, allListings }: FormProps) {
const router = useRouter()
const [activeTab, setActiveTab] = useState<'tr' | 'en' | 'ru'>('tr')
const [loading, setLoading] = useState(false)
const [error, setError] = useState('')
const [success, setSuccess] = useState(false)
// Track selected listing IDs
const [selectedListingIds, setSelectedListingIds] = useState<string[]>(
collection?.listingIds || []
)
const toggleListing = (id: string) => {
setSelectedListingIds(prev =>
prev.includes(id) ? prev.filter(p => p !== id) : [...prev, id]
)
}
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
setLoading(true)
setError('')
setSuccess(false)
const formData = new FormData(e.currentTarget)
if (collection) {
formData.append('id', collection.id)
}
// Append array of listing IDs manually since standard FormData doesn't handle arrays easily
selectedListingIds.forEach(id => {
formData.append('listingIds', id)
})
try {
const res = await createOrUpdateCollectionAction(formData)
if (res.error) {
setError(res.error)
} else {
setSuccess(true)
setTimeout(() => {
router.push('/admin/collections')
router.refresh()
}, 1500)
}
} catch (err) {
setError('İşlem sırasında bir hata oluştu.')
} finally {
setLoading(false)
}
}
return (
<form onSubmit={handleSubmit} className="space-y-6">
{error && (
<div className="bg-bougainvillea/10 border border-bougainvillea/25 text-bougainvillea p-4 rounded-xl text-xs font-semibold">
{error}
</div>
)}
{success && (
<div className="bg-turquoise/10 border border-turquoise/25 text-turquoise p-4 rounded-xl text-xs font-bold">
Koleksiyon başarıyla kaydedildi! Yönlendiriliyorsunuz...
</div>
)}
<div className="border-b border-pine/8">
<div className="flex gap-2">
{(['tr', 'en', 'ru'] as const).map((lang) => {
const label = lang === 'tr' ? '🇹🇷 Türkçe' : lang === 'en' ? '🇬🇧 English' : '🇷🇺 Русский'
const isTabActive = activeTab === lang
return (
<button
key={lang}
type="button"
onClick={() => setActiveTab(lang)}
className={`py-3 px-4 font-heading font-bold text-xs border-b-2 transition lowercase ${
isTabActive
? 'border-turquoise text-turquoise'
: 'border-transparent text-shutter hover:text-pine'
}`}
>
{label}
</button>
)
})}
</div>
</div>
<div className="space-y-4">
{activeTab === 'tr' && (
<div className="space-y-4">
<div className="space-y-1.5">
<label className="block text-xs font-mono uppercase tracking-wider text-shutter">Başlık (TR) *</label>
<input type="text" name="titleTr" required defaultValue={collection?.titleTr || ''} className="w-full bg-stone border border-pine/10 rounded-xl px-4 py-3 text-sm focus:ring-1 focus:ring-turquoise outline-none text-ink" placeholder="Örn: En İyi Kahvaltı Mekanları" />
</div>
<div className="space-y-1.5">
<label className="block text-xs font-mono uppercase tracking-wider text-shutter">Açıklama (TR) *</label>
<textarea name="descriptionTr" required rows={4} defaultValue={collection?.descriptionTr || ''} className="w-full bg-stone border border-pine/10 rounded-xl px-4 py-3 text-sm focus:ring-1 focus:ring-turquoise outline-none text-ink" placeholder="Türkçe açıklama..." />
</div>
</div>
)}
{activeTab === 'en' && (
<div className="space-y-4">
<div className="space-y-1.5">
<label className="block text-xs font-mono uppercase tracking-wider text-shutter">Başlık (EN) *</label>
<input type="text" name="titleEn" required defaultValue={collection?.titleEn || ''} className="w-full bg-stone border border-pine/10 rounded-xl px-4 py-3 text-sm focus:ring-1 focus:ring-turquoise outline-none text-ink" placeholder="e.g. Best Breakfast Spots" />
</div>
<div className="space-y-1.5">
<label className="block text-xs font-mono uppercase tracking-wider text-shutter">Açıklama (EN) *</label>
<textarea name="descriptionEn" required rows={4} defaultValue={collection?.descriptionEn || ''} className="w-full bg-stone border border-pine/10 rounded-xl px-4 py-3 text-sm focus:ring-1 focus:ring-turquoise outline-none text-ink" placeholder="English description..." />
</div>
</div>
)}
{activeTab === 'ru' && (
<div className="space-y-4">
<div className="space-y-1.5">
<label className="block text-xs font-mono uppercase tracking-wider text-shutter">Başlık (RU) *</label>
<input type="text" name="titleRu" required defaultValue={collection?.titleRu || ''} className="w-full bg-stone border border-pine/10 rounded-xl px-4 py-3 text-sm focus:ring-1 focus:ring-turquoise outline-none text-ink" placeholder="e.g. Лучшие места для завтрака" />
</div>
<div className="space-y-1.5">
<label className="block text-xs font-mono uppercase tracking-wider text-shutter">Açıklama (RU) *</label>
<textarea name="descriptionRu" required rows={4} defaultValue={collection?.descriptionRu || ''} className="w-full bg-stone border border-pine/10 rounded-xl px-4 py-3 text-sm focus:ring-1 focus:ring-turquoise outline-none text-ink" placeholder="Russian description..." />
</div>
</div>
)}
</div>
<hr className="border-dashed border-pine/8" />
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div className="space-y-1.5">
<label className="block text-xs font-mono uppercase tracking-wider text-shutter">URL Slug *</label>
<input type="text" name="slug" required defaultValue={collection?.slug || ''} className="w-full bg-stone border border-pine/10 rounded-xl px-4 py-3 text-sm focus:ring-1 focus:ring-turquoise outline-none text-ink font-mono" placeholder="en-iyi-kahvalti" />
</div>
<div className="space-y-1.5">
<label className="block text-xs font-mono uppercase tracking-wider text-shutter">Kapak Görseli URL</label>
<input type="url" name="coverImageUrl" defaultValue={collection?.coverImage || ''} className="w-full bg-stone border border-pine/10 rounded-xl px-4 py-3 text-sm focus:ring-1 focus:ring-turquoise outline-none text-ink" placeholder="https://..." />
</div>
</div>
<div className="space-y-1.5">
<label className="block text-xs font-mono uppercase tracking-wider text-shutter">Koleksiyon Mekanları (Seçiniz)</label>
<div className="bg-stone border border-pine/10 rounded-xl p-4 max-h-60 overflow-y-auto space-y-2">
{allListings.map(listing => (
<label key={listing.value} className="flex items-center gap-2 cursor-pointer hover:bg-stone-deep/20 p-2 rounded-lg transition">
<input
type="checkbox"
checked={selectedListingIds.includes(listing.value)}
onChange={() => toggleListing(listing.value)}
className="rounded border-pine/20 text-turquoise focus:ring-turquoise"
/>
<span className="text-sm font-medium text-ink">{listing.label}</span>
</label>
))}
</div>
</div>
<div className="flex items-center justify-between pt-4">
<Link href="/admin/collections" className="text-xs font-bold text-shutter hover:text-pine transition inline-flex items-center gap-1">
<ArrowLeft className="w-3.5 h-3.5" />
İptal ve Geri Dön
</Link>
<button disabled={loading} type="submit" className="bg-turquoise hover:bg-turquoise/90 text-paper px-6 py-3 rounded-xl font-bold text-sm transition-colors shadow-sm inline-flex items-center gap-2 disabled:opacity-50">
<Save className="w-4 h-4" />
{loading ? 'Kaydediliyor...' : 'Kaydet'}
</button>
</div>
</form>
)
}