Files
kovakemlak-crm/src/components/investors/investor-form-sheet.tsx
T
egecankomur 4ef0482732 feat: all core modules — properties, customers, searches, matches, presentations, activities, investors + public sunum page
- Server actions: property/customer/search/presentation/activity/investor CRUD
- Matching engine: matchPropertyToSearches + syncMatchesForSearch on search save
- UI: form sheets + table clients for all modules
- Public /sunum/[token] page (no auth) with property card grid + expiry check
- All pages force-dynamic for auth guard compatibility
2026-05-05 12:03:48 +03:00

110 lines
3.9 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 { useActionState, useEffect } from "react";
import { Loader2 } from "lucide-react";
import { toast } from "sonner";
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 {
Sheet,
SheetContent,
SheetFooter,
SheetHeader,
SheetTitle,
} from "@/components/ui/sheet";
import { createInvestorAction, updateInvestorAction } from "@/lib/appwrite/investor-actions";
import type { Investor } from "@/lib/appwrite/schema";
type ActionState = { ok: boolean; error?: string; fieldErrors?: Record<string, string[]> };
const INITIAL: ActionState = { ok: false };
interface InvestorFormSheetProps {
open: boolean;
onOpenChange: (v: boolean) => void;
investor?: Investor | null;
onSuccess?: () => void;
}
export function InvestorFormSheet({ open, onOpenChange, investor, onSuccess }: InvestorFormSheetProps) {
const action = investor
? updateInvestorAction.bind(null, investor.$id)
: createInvestorAction;
const [state, formAction, isPending] = useActionState(action, INITIAL);
useEffect(() => {
if (state.ok) {
toast.success(investor ? "Yatırımcı güncellendi." : "Yatırımcı oluşturuldu.");
onSuccess?.();
onOpenChange(false);
} else if (state.error) {
toast.error(state.error);
}
}, [state]);
const fe = state.fieldErrors ?? {};
return (
<Sheet open={open} onOpenChange={onOpenChange}>
<SheetContent className="sm:max-w-md">
<SheetHeader>
<SheetTitle>{investor ? "Yatırımcıyı Düzenle" : "Yeni Yatırımcı"}</SheetTitle>
</SheetHeader>
<form action={formAction} className="mt-4 space-y-4 pb-6">
<div className="grid gap-1.5">
<Label htmlFor="name">Ad Soyad *</Label>
<Input id="name" name="name" defaultValue={investor?.name} placeholder="Mehmet Demir" />
{fe.name && <p className="text-destructive text-xs">{fe.name[0]}</p>}
</div>
<div className="grid gap-1.5">
<Label htmlFor="email">Email *</Label>
<Input id="email" name="email" type="email" defaultValue={investor?.email} placeholder="mehmet@example.com" />
{fe.email && <p className="text-destructive text-xs">{fe.email[0]}</p>}
</div>
<div className="grid gap-1.5">
<Label htmlFor="phone">Telefon</Label>
<Input id="phone" name="phone" type="tel" defaultValue={investor?.phone ?? ""} placeholder="+90 555 123 45 67" />
</div>
<div className="grid grid-cols-2 gap-3">
<div className="grid gap-1.5">
<Label htmlFor="budget">Bütçe</Label>
<Input id="budget" name="budget" type="number" min="0" defaultValue={investor?.budget ?? ""} placeholder="5000000" />
</div>
<div className="grid gap-1.5">
<Label>Para birimi</Label>
<select
name="currency"
defaultValue={investor?.currency ?? "TRY"}
className="border-input bg-background h-9 rounded-md border px-3 text-sm"
>
<option value="TRY">TRY</option>
<option value="USD">USD</option>
<option value="EUR">EUR</option>
</select>
</div>
</div>
<div className="grid gap-1.5">
<Label htmlFor="notes">Notlar</Label>
<Textarea id="notes" name="notes" rows={3} defaultValue={investor?.notes ?? ""} placeholder="Yatırım tercihleri..." />
</div>
<SheetFooter>
<Button type="submit" disabled={isPending} className="w-full">
{isPending && <Loader2 className="mr-2 size-4 animate-spin" />}
{investor ? "Güncelle" : "Oluştur"}
</Button>
</SheetFooter>
</form>
</SheetContent>
</Sheet>
);
}