diff --git a/src/app/dashboard/calendar/page.tsx b/src/app/dashboard/calendar/page.tsx index fee7964..154781c 100644 --- a/src/app/dashboard/calendar/page.tsx +++ b/src/app/dashboard/calendar/page.tsx @@ -25,16 +25,19 @@ export default async function CalendarPage() { .order('name') // Transform data for calendar - const events = reservations?.map(res => ({ - id: res.id, - title: `${res.customers?.full_name || 'Müşteri'} ${res.customers?.phone ? `(${res.customers.phone})` : ''}`, - start: new Date(res.start_time), - end: new Date(res.end_time), - resource: res, - })) || [] + const events = reservations?.map(res => { + const customer = Array.isArray(res.customers) ? res.customers[0] : res.customers + return { + id: res.id, + title: `${customer?.full_name || 'Müşteri'} ${customer?.phone ? `(${customer.phone})` : ''}`, + start: new Date(res.start_time), + end: new Date(res.end_time), + resource: res, + } + }) || [] return ( -
+
) diff --git a/src/app/dashboard/expenses/categories/category-manager.tsx b/src/app/dashboard/expenses/categories/category-manager.tsx new file mode 100644 index 0000000..784bb32 --- /dev/null +++ b/src/app/dashboard/expenses/categories/category-manager.tsx @@ -0,0 +1,127 @@ +'use client' + +import { useState } from "react" +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Label } from "@/components/ui/label" +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table" +import { Trash2 } from "lucide-react" +import { createClient } from "@/lib/supabase/client" +import { toast } from "sonner" +import { useRouter } from "next/navigation" + +export function CategoryManager({ initialCategories }: { initialCategories: any[] }) { + const [categories, setCategories] = useState(initialCategories) + const [newCategory, setNewCategory] = useState("") + const [loading, setLoading] = useState(false) + const router = useRouter() + const supabase = createClient() + + const handleAdd = async (e: React.FormEvent) => { + e.preventDefault() + if (!newCategory.trim()) return + + setLoading(true) + const { data, error } = await supabase + .from('expense_categories') + .insert({ name: newCategory }) + .select() + .single() + + if (error) { + toast.error("Kategori eklenirken hata oluştu") + console.error(error) + } else { + setCategories([data, ...categories]) + setNewCategory("") + toast.success("Kategori eklendi") + router.refresh() + } + setLoading(false) + } + + const handleDelete = async (id: string) => { + if (!confirm("Bu kategoriyi silmek istediğinize emin misiniz?")) return + + const { error } = await supabase + .from('expense_categories') + .delete() + .eq('id', id) + + if (error) { + toast.error("Silinirken hata oluştu. Bu kategoriye bağlı harcamalar olabilir.") + console.error(error) + } else { + setCategories(categories.filter(c => c.id !== id)) + toast.success("Kategori silindi") + router.refresh() + } + } + + return ( +
+
+
+

Yeni Kategori Ekle

+
+
+ + setNewCategory(e.target.value)} + /> +
+ +
+
+
+ +
+ + + + Kategori Adı + + + + + {categories.length === 0 ? ( + + + Kategori bulunamadı. + + + ) : ( + categories.map((category) => ( + + {category.name} + + + + + )) + )} + +
+
+
+ ) +} diff --git a/src/app/dashboard/expenses/categories/page.tsx b/src/app/dashboard/expenses/categories/page.tsx new file mode 100644 index 0000000..75ad60a --- /dev/null +++ b/src/app/dashboard/expenses/categories/page.tsx @@ -0,0 +1,31 @@ +import { createClient } from "@/lib/supabase/server" +import { CategoryManager } from "./category-manager" +import { Button } from "@/components/ui/button" +import { ArrowLeft } from "lucide-react" +import Link from "next/link" + +export default async function CategoriesPage() { + const supabase = await createClient() + const { data: categories } = await supabase + .from('expense_categories') + .select('*') + .order('created_at', { ascending: false }) + + return ( +
+
+ + + +
+

Gider Kategorileri

+

Giderlerinizi gruplandırmak için kategoriler oluşturun.

+
+
+ + +
+ ) +} diff --git a/src/app/dashboard/expenses/new/expense-form.tsx b/src/app/dashboard/expenses/new/expense-form.tsx new file mode 100644 index 0000000..e84abfa --- /dev/null +++ b/src/app/dashboard/expenses/new/expense-form.tsx @@ -0,0 +1,114 @@ +'use client' + +import { useState } from "react" +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 { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select" +import { createClient } from "@/lib/supabase/client" +import { toast } from "sonner" +import { useRouter } from "next/navigation" +import { format } from "date-fns" + +export function ExpenseForm({ categories }: { categories: any[] }) { + const [loading, setLoading] = useState(false) + const router = useRouter() + const supabase = createClient() + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault() + setLoading(true) + + const formData = new FormData(e.currentTarget) + const amount = formData.get("amount") + const categoryId = formData.get("category_id") + const description = formData.get("description") + const date = formData.get("date") + + const { error } = await supabase + .from('expenses') + .insert({ + amount: parseFloat(amount as string), + category_id: categoryId === "general" || !categoryId ? null : categoryId, + description, + date: new Date(date as string).toISOString(), + }) + + if (error) { + toast.error("Gider eklenirken hata oluştu") + console.error(error) + } else { + toast.success("Gider kaydedildi") + router.push("/dashboard/expenses") + router.refresh() + } + setLoading(false) + } + + return ( +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +