feat: Complete Corporate Site Deployment Checkpoint
This commit is contained in:
115
src/app/dashboard/cms/services/service-form.tsx
Normal file
115
src/app/dashboard/cms/services/service-form.tsx
Normal file
@@ -0,0 +1,115 @@
|
||||
'use client'
|
||||
|
||||
import { Service } 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 { ImageUpload } from "@/components/ui/image-upload"
|
||||
import { useState } from "react"
|
||||
import { createService, updateService } from "./actions"
|
||||
import { toast } from "sonner"
|
||||
import { Switch } from "@/components/ui/switch"
|
||||
import { Loader2 } from "lucide-react"
|
||||
|
||||
interface ServiceFormProps {
|
||||
service?: Service
|
||||
afterSave: () => void
|
||||
}
|
||||
|
||||
export function ServiceForm({ service, afterSave }: ServiceFormProps) {
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [title, setTitle] = useState(service?.title || "")
|
||||
const [description, setDescription] = useState(service?.description || "")
|
||||
const [imageUrl, setImageUrl] = useState(service?.image_url || "")
|
||||
const [order, setOrder] = useState(service?.order.toString() || "0")
|
||||
const [isActive, setIsActive] = useState(service?.is_active ?? true)
|
||||
|
||||
const onSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
setLoading(true)
|
||||
|
||||
const formData = new FormData()
|
||||
formData.append('title', title)
|
||||
formData.append('description', description)
|
||||
formData.append('image_url', imageUrl)
|
||||
formData.append('order', order)
|
||||
formData.append('is_active', String(isActive))
|
||||
|
||||
try {
|
||||
const result = service
|
||||
? await updateService(service.id, formData)
|
||||
: await createService(formData)
|
||||
|
||||
if (result.success) {
|
||||
toast.success(service ? "Hizmet güncellendi" : "Hizmet oluşturuldu")
|
||||
afterSave()
|
||||
} else {
|
||||
toast.error(result.error)
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error("Bir hata oluştu")
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={onSubmit} className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<Label>Hizmet Başlığı</Label>
|
||||
<Input
|
||||
value={title}
|
||||
onChange={(e) => setTitle(e.target.value)}
|
||||
placeholder="Örn: Düğün Organizasyonu"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label>Açıklama</Label>
|
||||
<Textarea
|
||||
value={description}
|
||||
onChange={(e) => setDescription(e.target.value)}
|
||||
placeholder="Hizmet detayları..."
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label>Görsel</Label>
|
||||
<ImageUpload
|
||||
value={imageUrl}
|
||||
onChange={setImageUrl}
|
||||
bucketName="public-site"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="space-y-2 flex-1">
|
||||
<Label>Sıralama</Label>
|
||||
<Input
|
||||
type="number"
|
||||
value={order}
|
||||
onChange={(e) => setOrder(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2 flex flex-col pt-6">
|
||||
<div className="flex items-center space-x-2">
|
||||
<Switch
|
||||
checked={isActive}
|
||||
onCheckedChange={setIsActive}
|
||||
/>
|
||||
<Label>Aktif</Label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end pt-4">
|
||||
<Button type="submit" disabled={loading}>
|
||||
{loading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
|
||||
{service ? 'Güncelle' : 'Oluştur'}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user