diff --git a/src/app/settings/actions.ts b/src/app/settings/actions.ts new file mode 100644 index 0000000..7a08610 --- /dev/null +++ b/src/app/settings/actions.ts @@ -0,0 +1,47 @@ +'use server'; + +import { createClient } from '@/utils/supabase/server'; +import { revalidatePath } from 'next/cache'; + +export async function upsertLookup(table: string, data: any) { + const supabase = await createClient(); + + const { id, ...rest } = data; + + let result; + if (id) { + result = await supabase + .from(table) + .update(rest) + .eq('id', id); + } else { + result = await supabase + .from(table) + .insert([rest]); + } + + if (result.error) { + return { error: result.error.message }; + } + + revalidatePath('/settings'); + revalidatePath('/employees'); + return { success: true }; +} + +export async function deleteLookup(table: string, id: string) { + const supabase = await createClient(); + + const { error } = await supabase + .from(table) + .delete() + .eq('id', id); + + if (error) { + return { error: error.message }; + } + + revalidatePath('/settings'); + revalidatePath('/employees'); + return { success: true }; +} diff --git a/src/app/settings/page.tsx b/src/app/settings/page.tsx new file mode 100644 index 0000000..3e8186a --- /dev/null +++ b/src/app/settings/page.tsx @@ -0,0 +1,67 @@ +import { createClient } from '@/utils/supabase/server'; +import LookupManager from '@/components/settings/LookupManager'; +import SectionManager from '@/components/settings/SectionManager'; +import { Cog6ToothIcon } from '@heroicons/react/24/outline'; + +export default async function SettingsPage() { + const supabase = await createClient(); + + // Fetch all lookup data + const [ + { data: departments }, + { data: sections }, + { data: employmentTypes }, + { data: jobTitles } + ] = await Promise.all([ + supabase.from('departments').select('*').order('name'), + supabase.from('sections').select('*').order('name'), + supabase.from('employment_types').select('*').order('name'), + supabase.from('job_titles').select('*').order('name') + ]); + + return ( +
+ {/* Header */} +
+
+
+

+ + Sistem Ayarları +

+

+ Personel kartı veri tanımlamaları ve konfigürasyon +

+
+
+ + {/* Grid Layout for Managers */} +
+ + + + + + + + + +
+
+ ); +} diff --git a/src/components/settings/LookupManager.tsx b/src/components/settings/LookupManager.tsx new file mode 100644 index 0000000..8336fad --- /dev/null +++ b/src/components/settings/LookupManager.tsx @@ -0,0 +1,137 @@ +'use client'; + +import { useState } from 'react'; +import { PlusIcon, PencilSquareIcon, TrashIcon, XMarkIcon } from '@heroicons/react/24/outline'; +import { upsertLookup, deleteLookup } from '@/app/settings/actions'; + +interface LookupManagerProps { + title: string; + table: string; + items: any[]; +} + +export default function LookupManager({ title, table, items }: LookupManagerProps) { + const [isModalOpen, setIsModalOpen] = useState(false); + const [editingItem, setEditingItem] = useState(null); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + const openModal = (item?: any) => { + setEditingItem(item || null); + setIsModalOpen(true); + setError(null); + }; + + const handleSave = async (e: React.FormEvent) => { + e.preventDefault(); + setLoading(true); + setError(null); + + const formData = new FormData(e.currentTarget); + const name = formData.get('name') as string; + + const data = { + id: editingItem?.id, + name + }; + + const result = await upsertLookup(table, data); + if (result.error) { + setError(result.error); + } else { + setIsModalOpen(false); + } + setLoading(false); + }; + + const handleDelete = async (id: string) => { + if (confirm('Bu öğeyi silmek istediğinize emin misiniz?')) { + const result = await deleteLookup(table, id); + if (result.error) { + alert(result.error); + } + } + }; + + return ( +
+
+

{title}

+ +
+ +
+ {items.map((item) => ( +
+ {item.name} +
+ + +
+
+ ))} + {items.length === 0 && ( +
+ Henüz kayıt bulunamadı. +
+ )} +
+ + {isModalOpen && ( +
+
+
+

+ {editingItem ? 'DÜZENLE' : 'YENİ EKLE'} +

+ +
+
+ {error && ( +
+ {error} +
+ )} +
+ + +
+ +
+
+
+ )} +
+ ); +} diff --git a/src/components/settings/SectionManager.tsx b/src/components/settings/SectionManager.tsx new file mode 100644 index 0000000..b4cb54d --- /dev/null +++ b/src/components/settings/SectionManager.tsx @@ -0,0 +1,165 @@ +'use client'; + +import { useState } from 'react'; +import { PlusIcon, PencilSquareIcon, TrashIcon, XMarkIcon, BuildingOfficeIcon } from '@heroicons/react/24/outline'; +import { upsertLookup, deleteLookup } from '@/app/settings/actions'; + +interface SectionManagerProps { + sections: any[]; + departments: any[]; +} + +export default function SectionManager({ sections, departments }: SectionManagerProps) { + const [isModalOpen, setIsModalOpen] = useState(false); + const [editingItem, setEditingItem] = useState(null); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + const openModal = (item?: any) => { + setEditingItem(item || null); + setIsModalOpen(true); + setError(null); + }; + + const handleSave = async (e: React.FormEvent) => { + e.preventDefault(); + setLoading(true); + setError(null); + + const formData = new FormData(e.currentTarget); + const name = formData.get('name') as string; + const department_id = formData.get('department_id') as string; + + const data = { + id: editingItem?.id, + name, + department_id + }; + + const result = await upsertLookup('sections', data); + if (result.error) { + setError(result.error); + } else { + setIsModalOpen(false); + } + setLoading(false); + }; + + const handleDelete = async (id: string) => { + if (confirm('Bu bölümü silmek istediğinize emin misiniz?')) { + const result = await deleteLookup('sections', id); + if (result.error) { + alert(result.error); + } + } + }; + + const getDeptName = (id: string) => { + return departments.find(d => d.id === id)?.name || 'Bilinmiyor'; + }; + + return ( +
+
+

Bölümler

+ +
+ +
+ {sections.map((item) => ( +
+
+

{item.name}

+
+ +

{getDeptName(item.department_id)}

+
+
+
+ + +
+
+ ))} + {sections.length === 0 && ( +
+ Henüz kayıt bulunamadı. +
+ )} +
+ + {isModalOpen && ( +
+
+
+

+ {editingItem ? 'DÜZENLE' : 'YENİ EKLE'} +

+ +
+
+ {error && ( +
+ {error} +
+ )} + +
+ + +
+ +
+ + +
+ + +
+
+
+ )} +
+ ); +}