From 9e1355a137980861ae01019edd477fd780e921f5 Mon Sep 17 00:00:00 2001 From: kovakmedya Date: Fri, 1 May 2026 02:52:09 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20services=20=E2=80=94=20preset=20names,?= =?UTF-8?q?=20currency,=20multi-assignee=20(MCP:=20assigneeIds+currency=20?= =?UTF-8?q?columns)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/service-form-sheet.tsx | 184 ++++++++++++++++-- .../services/components/services-client.tsx | 35 +++- .../(dashboard)/services/components/types.ts | 4 + src/app/(dashboard)/services/page.tsx | 11 +- src/lib/appwrite/schema.ts | 2 + src/lib/appwrite/service-actions.ts | 2 + src/lib/format.ts | 9 + src/lib/validation/services.ts | 2 + 8 files changed, 224 insertions(+), 25 deletions(-) diff --git a/src/app/(dashboard)/services/components/service-form-sheet.tsx b/src/app/(dashboard)/services/components/service-form-sheet.tsx index dab67de..de5b963 100644 --- a/src/app/(dashboard)/services/components/service-form-sheet.tsx +++ b/src/app/(dashboard)/services/components/service-form-sheet.tsx @@ -1,12 +1,19 @@ "use client"; -import { useActionState, useEffect } from "react"; -import { Loader2, Save } from "lucide-react"; +import { useActionState, useEffect, useState } from "react"; +import { Check, ChevronDown, Loader2, Save, Users } from "lucide-react"; import { toast } from "sonner"; +import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; +import { Checkbox } from "@/components/ui/checkbox"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; import { Select, SelectContent, @@ -24,12 +31,32 @@ import { } from "@/components/ui/sheet"; import { Switch } from "@/components/ui/switch"; import { Textarea } from "@/components/ui/textarea"; +import { cn } from "@/lib/utils"; import { createServiceAction, updateServiceAction, } from "@/lib/appwrite/service-actions"; import { initialServiceState } from "@/lib/appwrite/service-types"; -import type { CustomerOption, ServiceRow } from "./types"; +import type { CustomerOption, MemberOption, ServiceRow } from "./types"; + +const PRESET_SERVICES = [ + "Web sitesi tasarımı", + "Web sitesi bakımı", + "SEO optimizasyonu", + "Sosyal medya yönetimi", + "Domain kayıt / yenileme", + "Hosting hizmeti", + "Kurumsal e-posta", + "Grafik tasarım", + "Logo tasarımı", + "Google Ads yönetimi", + "Meta Ads yönetimi", + "Yazılım geliştirme", + "Mobil uygulama", + "Teknik destek", + "Muhasebe danışmanlığı", + "Eğitim / danışmanlık", +]; type Props = { open: boolean; @@ -37,6 +64,7 @@ type Props = { service?: ServiceRow | null; customers: CustomerOption[]; defaultCustomerId?: string; + members: MemberOption[]; }; export function ServiceFormSheet({ @@ -45,11 +73,24 @@ export function ServiceFormSheet({ service, customers, defaultCustomerId, + members, }: Props) { const isEdit = Boolean(service); const action = isEdit ? updateServiceAction : createServiceAction; const [state, formAction, isPending] = useActionState(action, initialServiceState); + const [name, setName] = useState(service?.name ?? ""); + const [assigneeIds, setAssigneeIds] = useState(service?.assigneeIds ?? []); + const [assigneeOpen, setAssigneeOpen] = useState(false); + + // Reset local state when sheet opens with a different service + useEffect(() => { + if (open) { + setName(service?.name ?? ""); + setAssigneeIds(service?.assigneeIds ?? []); + } + }, [open, service]); + useEffect(() => { if (state.ok) { toast.success(isEdit ? "Hizmet güncellendi." : "Hizmet eklendi."); @@ -60,6 +101,12 @@ export function ServiceFormSheet({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [state]); + const toggleAssignee = (id: string) => { + setAssigneeIds((prev) => + prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id], + ); + }; + return ( @@ -74,8 +121,13 @@ export function ServiceFormSheet({
{isEdit && service && } + {/* Assignee hidden inputs — one per selected member */} + {assigneeIds.map((id) => ( + + ))} -
+
+ {/* Müşteri */}
setName(e.target.value)} + placeholder="Hizmet adını yazın veya yukarıdan seçin" required /> {state.fieldErrors?.name && ( @@ -113,6 +185,7 @@ export function ServiceFormSheet({ )}
+ {/* Açıklama */}