diff --git a/src/app/employees/actions.ts b/src/app/employees/actions.ts index 75ac06d..75ac1ff 100644 --- a/src/app/employees/actions.ts +++ b/src/app/employees/actions.ts @@ -1,6 +1,7 @@ 'use server' import { createClient } from '@/utils/supabase/server' +import { createAdminClient } from '@/utils/supabase/admin' import { revalidatePath } from 'next/cache' export async function addEmployee(formData: FormData) { @@ -12,45 +13,62 @@ export async function addEmployee(formData: FormData) { const email = formData.get('email') as string const companyId = formData.get('company_id') as string const roleId = formData.get('role_id') as string + const photo = formData.get('photo') as File - if (!email || !companyId || !roleId) { - return { error: 'E-posta, Şirket ve Rol seçimi zorunludur.' } + if (!firstName || !lastName || !companyId || !roleId) { + return { error: 'Ad, Soyad, Şirket ve Rol seçimi zorunludur.' } } - // Admin creating users manually currently requires an admin API setup or the user registering themselves - // In a robust HRMS, the Superadmin uses the Supabase Admin API to `createUser`. - // For the sake of this prototype, we'll assume the user must register first via valid credentials, - // or we can insert an unauthenticated ghost user into `public.users` (which breaks reference to auth.users if not careful). - // - // Let's implement the standard approach: we check if the user exists in `auth.users` via `public.users` - - let { data: existingUser } = await supabase - .from('users') - .select('id') - .eq('email', email) - .single() + // 2. Handle Photo Upload + let photoUrl = null + if (photo && photo.size > 0) { + const fileExt = photo.name.split('.').pop() + const fileName = `${Math.random()}.${fileExt}` + const filePath = `${fileName}` - if (!existingUser) { - return { error: 'Bu e-posta adresine sahip bir kullanıcı bulunamadı. Kullanıcının önce sisteme kayıt olması gerekmektedir.' } + const { error: uploadError, data } = await supabase.storage + .from('employee-photos') + .upload(filePath, photo) + + if (uploadError) { + console.error('Photo upload error:', uploadError) + } else { + const { data: { publicUrl } } = supabase.storage + .from('employee-photos') + .getPublicUrl(filePath) + photoUrl = publicUrl + } } - // 2. Insert into Employees table + // 3. Insert into Employees table const { error: employeeError } = await supabase .from('employees') .insert([{ - user_id: existingUser.id, + first_name: firstName, + last_name: lastName, + email: email || null, company_id: companyId, role_id: roleId, - department: formData.get('department'), - title: formData.get('title'), - status: formData.get('status') || 'active' + photo_url: photoUrl, + department_id: formData.get('department_id') || null, + section_id: formData.get('section_id') || null, + employment_type_id: formData.get('employment_type_id') || null, + job_title_id: formData.get('job_title_id') || null, + tc_no: formData.get('tc_no'), + birth_date: formData.get('birth_date') || null, + birth_place: formData.get('birth_place'), + gender: formData.get('gender'), + address: formData.get('address'), + phone1: formData.get('phone1'), + phone2: formData.get('phone2'), + has_driving_license: formData.get('has_driving_license') === 'on', + military_status: formData.get('military_status'), + start_date: formData.get('start_date') || null, + leave_date: formData.get('leave_date') || null, + status: 'active' }]) if (employeeError) { - // Catch unique constraint violation - if (employeeError.code === '23505') { - return { error: 'Bu kullanıcı zaten bu şirkete eklenmiş.' } - } return { error: 'Personel eklenirken hata: ' + employeeError.message } } @@ -76,15 +94,52 @@ export async function deleteEmployee(id: string) { export async function updateEmployee(id: string, formData: FormData) { const supabase = await createClient() + const photo = formData.get('photo') as File + + // 1. Handle Photo Upload if new photo provided + let photoUrl = formData.get('existing_photo_url') as string + if (photo && photo.size > 0) { + const fileExt = photo.name.split('.').pop() + const fileName = `${Math.random()}.${fileExt}` + const filePath = `${fileName}` + + const { error: uploadError } = await supabase.storage + .from('employee-photos') + .upload(filePath, photo) + + if (!uploadError) { + const { data: { publicUrl } } = supabase.storage + .from('employee-photos') + .getPublicUrl(filePath) + photoUrl = publicUrl + } + } const { error } = await supabase .from('employees') .update({ + first_name: formData.get('first_name'), + last_name: formData.get('last_name'), + email: formData.get('email'), company_id: formData.get('company_id'), role_id: formData.get('role_id'), - department: formData.get('department'), - title: formData.get('title'), - status: formData.get('status') + photo_url: photoUrl, + department_id: formData.get('department_id') || null, + section_id: formData.get('section_id') || null, + employment_type_id: formData.get('employment_type_id') || null, + job_title_id: formData.get('job_title_id') || null, + tc_no: formData.get('tc_no'), + birth_date: formData.get('birth_date') || null, + birth_place: formData.get('birth_place'), + gender: formData.get('gender'), + address: formData.get('address'), + phone1: formData.get('phone1'), + phone2: formData.get('phone2'), + has_driving_license: formData.get('has_driving_license') === 'on', + military_status: formData.get('military_status'), + start_date: formData.get('start_date') || null, + leave_date: formData.get('leave_date') || null, + status: formData.get('leave_date') ? 'inactive' : formData.get('status') }) .eq('id', id) @@ -95,3 +150,54 @@ export async function updateEmployee(id: string, formData: FormData) { revalidatePath('/employees') return { success: true } } + +export async function createUserForEmployee(formData: FormData) { + const supabaseAdmin = createAdminClient() + const supabase = await createClient() + + const employeeId = formData.get('employee_id') as string + const password = formData.get('password') as string + + if (!employeeId || !password) { + return { error: 'Personel ve şifre zorunludur.' } + } + + // 1. Get employee email + const { data: employee, error: fetchError } = await supabase + .from('employees') + .select('email, first_name, last_name') + .eq('id', employeeId) + .single() + + if (fetchError || !employee || !employee.email) { + return { error: 'Personel bilgisi veya e-posta adresi bulunamadı.' } + } + + // 2. Create user in Auth + const { data: authData, error: authError } = await supabaseAdmin.auth.admin.createUser({ + email: employee.email, + password: password, + email_confirm: true, + user_metadata: { + first_name: employee.first_name, + last_name: employee.last_name + } + }) + + if (authError) { + return { error: 'Kullanıcı oluşturulurken hata (Auth): ' + authError.message } + } + + // 3. Link Auth User to Employee + const { error: updateError } = await supabase + .from('employees') + .update({ user_id: authData.user.id }) + .eq('id', employeeId) + + if (updateError) { + return { error: 'Kullanıcı personele bağlanırken hata: ' + updateError.message } + } + + revalidatePath('/employees') + return { success: true } +} diff --git a/src/app/employees/page.tsx b/src/app/employees/page.tsx index d749c55..a594955 100644 --- a/src/app/employees/page.tsx +++ b/src/app/employees/page.tsx @@ -8,31 +8,24 @@ export default async function EmployeesPage() { const { data: employees } = await supabase .from('employees') .select(` - id, - user_id, - company_id, - role_id, - department, - title, - status, - created_at, + *, companies ( id, name ), users ( id, first_name, last_name, email ), - roles ( id, name, description ) + roles ( id, name, description ), + departments ( id, name ), + sections ( id, name ), + employment_types ( id, name ), + job_titles ( id, name ) `) .order('created_at', { ascending: false }) - // Fetch companies for the modal - const { data: companies } = await supabase - .from('companies') - .select('id, name') - .order('name') - - // Fetch roles for the modal - const { data: roles } = await supabase - .from('roles') - .select('id, name, description') - .order('name') + // Fetch lookups + const { data: companies } = await supabase.from('companies').select('id, name').order('name') + const { data: roles } = await supabase.from('roles').select('id, name, description').order('name') + const { data: departments } = await supabase.from('departments').select('id, name').order('name') + const { data: sections } = await supabase.from('sections').select('id, name, department_id').order('name') + const { data: employmentTypes } = await supabase.from('employment_types').select('id, name').order('name') + const { data: jobTitles } = await supabase.from('job_titles').select('id, name').order('name') return (
- Personel bilgilerini eksiksiz doldurunuz. +
+ Sistem üzerindeki personel bilgilerini detaylı olarak yönetin.