web sitesi yönetimi
This commit is contained in:
128
components/dashboard/content-form.tsx
Normal file
128
components/dashboard/content-form.tsx
Normal file
@@ -0,0 +1,128 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from "react"
|
||||
import { SiteContent } from "@/types/cms"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Label } from "@/components/ui/label"
|
||||
import { Textarea } from "@/components/ui/textarea"
|
||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card"
|
||||
import { ImageUpload } from "@/components/ui/image-upload" // Ensure this exists or adapt
|
||||
import { updateSiteContent } from "@/app/(dashboard)/dashboard/cms/content/actions"
|
||||
import { toast } from "sonner"
|
||||
import { Save, Loader2 } from "lucide-react"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
interface ContentFormProps {
|
||||
initialContent: SiteContent[]
|
||||
}
|
||||
|
||||
const SECTIONS = [
|
||||
{ id: 'general', label: 'Genel Ayarlar' },
|
||||
{ id: 'home', label: 'Anasayfa' },
|
||||
{ id: 'contact', label: 'İletişim' },
|
||||
]
|
||||
|
||||
export function ContentForm({ initialContent }: ContentFormProps) {
|
||||
const [contents, setContents] = useState<SiteContent[]>(initialContent)
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [activeSection, setActiveSection] = useState('general')
|
||||
|
||||
const handleChange = (key: string, value: string) => {
|
||||
setContents(prev => prev.map(item =>
|
||||
item.key === key ? { ...item, value } : item
|
||||
))
|
||||
}
|
||||
|
||||
const onSubmit = async () => {
|
||||
setLoading(true)
|
||||
try {
|
||||
const result = await updateSiteContent(contents)
|
||||
if (result.success) {
|
||||
toast.success("İçerikler başarıyla güncellendi")
|
||||
} else {
|
||||
toast.error(result.error)
|
||||
}
|
||||
} catch {
|
||||
toast.error("Bir hata oluştu")
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
const filteredContent = contents.filter(item => item.section === activeSection)
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{/* Custom Tabs */}
|
||||
<div className="flex space-x-1 rounded-lg bg-muted p-1 overflow-x-auto">
|
||||
{SECTIONS.map((section) => (
|
||||
<button
|
||||
key={section.id}
|
||||
onClick={() => setActiveSection(section.id)}
|
||||
className={cn(
|
||||
"flex-1 justify-center whitespace-nowrap rounded-md px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
||||
activeSection === section.id
|
||||
? "bg-background text-foreground shadow-sm"
|
||||
: "text-muted-foreground hover:bg-background/50 hover:text-foreground"
|
||||
)}
|
||||
>
|
||||
{section.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>{SECTIONS.find(s => s.id === activeSection)?.label}</CardTitle>
|
||||
<CardDescription>
|
||||
Bu bölümdeki içerikleri aşağıdan düzenleyebilirsiniz.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-6">
|
||||
{filteredContent.length === 0 && (
|
||||
<p className="text-sm text-muted-foreground">Bu bölümde henüz ayar bulunmuyor.</p>
|
||||
)}
|
||||
{filteredContent.map((item) => (
|
||||
<div key={item.key} className="space-y-2">
|
||||
<Label className="capitalize">
|
||||
{item.key.replace(/_/g, ' ').replace(activeSection, '').trim() || item.key}
|
||||
</Label>
|
||||
|
||||
{item.type === 'image_url' ? (
|
||||
<ImageUpload
|
||||
value={item.value}
|
||||
onChange={(url) => handleChange(item.key, url)}
|
||||
onRemove={() => handleChange(item.key, '')}
|
||||
/>
|
||||
) : item.type === 'long_text' || item.type === 'html' || item.key.includes('address') ? (
|
||||
<Textarea
|
||||
value={item.value}
|
||||
onChange={(e) => handleChange(item.key, e.target.value)}
|
||||
rows={4}
|
||||
/>
|
||||
) : (
|
||||
<Input
|
||||
value={item.value}
|
||||
onChange={(e) => handleChange(item.key, e.target.value)}
|
||||
/>
|
||||
)}
|
||||
{item.key.includes('map_embed') && (
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
Google Maps'den alınan <iframe> kodunu buraya yapıştırın.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<div className="flex justify-end sticky bottom-6 z-10">
|
||||
<Button onClick={onSubmit} disabled={loading} size="lg" className="shadow-lg">
|
||||
{loading ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : <Save className="mr-2 h-4 w-4" />}
|
||||
Değişiklikleri Kaydet
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user