From b354412cb88b2acba8496424bb4a1f3ac4742c60 Mon Sep 17 00:00:00 2001 From: Kenan KARAER Date: Wed, 18 Mar 2026 00:08:39 +0300 Subject: [PATCH] =?UTF-8?q?Personel=20Sayfas=C4=B1=20ve=20Uygulama=20renk?= =?UTF-8?q?=20de=C4=9Fi=C5=9Fiklikleri?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/favicon.png | Bin 0 -> 13995 bytes public/logo.png | Bin 0 -> 21759 bytes src/app/companies/page.tsx | 58 ++--- src/app/employees/actions.ts | 34 ++- src/app/employees/page.tsx | 182 ++------------- src/app/favicon.ico | Bin 25931 -> 0 bytes src/app/layout.tsx | 6 +- src/app/leave-requests/actions.ts | 2 +- src/app/leave-requests/page.tsx | 72 +++--- src/app/login/page.tsx | 91 ++++---- src/app/page.tsx | 113 ++++++---- src/components/employees/EmployeeModal.tsx | 175 +++++++++++++++ src/components/employees/EmployeeTable.tsx | 211 ++++++++++++++++++ src/components/layout/Header.tsx | 5 +- src/components/layout/Sidebar.tsx | 60 ++--- .../20240317000001_user_sync_trigger.sql | 19 ++ .../20240317000002_leave_balances.sql | 40 ++++ .../migrations/20240317000003_tighten_rls.sql | 41 ++++ .../20240317000004_fix_rls_recursion.sql | 76 +++++++ 19 files changed, 836 insertions(+), 349 deletions(-) create mode 100644 public/favicon.png create mode 100644 public/logo.png delete mode 100644 src/app/favicon.ico create mode 100644 src/components/employees/EmployeeModal.tsx create mode 100644 src/components/employees/EmployeeTable.tsx create mode 100644 supabase/migrations/20240317000001_user_sync_trigger.sql create mode 100644 supabase/migrations/20240317000002_leave_balances.sql create mode 100644 supabase/migrations/20240317000003_tighten_rls.sql create mode 100644 supabase/migrations/20240317000004_fix_rls_recursion.sql diff --git a/public/favicon.png b/public/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..672cf13b8dbf24c36a19f237ab2dfc28c8d4cbba GIT binary patch literal 13995 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 E+~BD< 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%0A05URfm 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�qSr|s;~*68|R(#N!A z83gA->lyrjH0hw=0L!=g7^5o|fXaclt(FfZJ@Xxwd2jLXgq6A8^*OoiFM^&W-_oqB zQ`ataB|7W%d@p1`^4+U@j&65%mW{DK*@0!IG%(56$2NpBPx3J8aOvbdkl2xMT-+yg z52QYFsaVY&y4IkY`jBa03OFWQd#r%PlCfv$1wfqGWP!z2%IY6C%AtR5UzNoTnrCY^ zqeJa*<(Q9^7v~`br2{180n#?{51)%q1_6>E)kkh`>UhC?DV+e`hO?|!?}(f7Ij3!b zj}bT%M@k0?Abh?m=j`)cuQ26^@B*~$bpDv9*);`8R?VKO2WAps+p&roE zL5Ghol5vBkYVB=R^p7DYaEm2TcyQk`QWAA?@E)!oZm)nYssjigL=$ z-*?t`Y(2vFw8afe1W4d2qNU+QT5cxB(rbSuV)wE3T#TGsFkHH zs)5BouUQ&htvZwlraVUeN+J<|Yk%!CuPO-@#q7@NHKS@fGa9BUuEr-Ey1rSvV8Rzz zR+X}F{VY^UuTxjUV?>YS)BFD2GT7x;EVhuCjUx`HGF^9%rd)>G5WMYR>Nu z8&6aXRvLqELI&#g`FD__`Jo7HVo5lTBcX0f4u)eYA$PP;hU4jbXd_HMVDaIh`|lTB zJn}UBJGjxj_}e^-zlspAaU{u}4_(2CPe?P+) zL()b?eby7IUePLI*xP~}O*xg+ePO3I#%Ut6(hefu+|x{jo(8r-zwvA`A420VjL{h}Fa!uSQ{IwER-poWt>`d(-B4^@mV}wHuhiyimnLos zoSxc$WGssvUMnfAyfRK}+#Tp>yJ4whuqF&Tkh54oqQyt>OL?O^CSO<=6STyPCFI)y zQ;SlS8US4VlJnkEk=rK(`9239ltkeL@1W9{8rx)Uw2(gUtYMqTDBa&0#%WO9Kc+Yx zK2Zp_M=J^yBR0OF4Ob|W@no(kP)#z(-f%gl4Zo31Z3wNpI;yf=JE)~Tu`lcG3k!{KqBD{|=$DrB#sx z^bR8x4j+o(q4khLrx6fEQEL;;MF{b0Un3yD%6Nd4M`TjXE>oAXAp~$T62l~(9eEZO zsf{YFEO7uCExVp{dx7S+q2?Fgu&_-aXZ!ZVkt>Wptet1n0)7MmUu|`8dzG%8J5&!6FgE7`thK^RH1tS;2W%)oL7!2KnJyr1`r*8EPfOPgG%d*O0wSgR#Whn7@RKilyqh+J+CM8dXrEA zU%kE*L>F!Te%xrwm8a@_r<%G@8?Nb3d;@(z?zH6jXbPU$z+mP`*w8YAHXGFko%T0Q zBmW{kPU!d1xy|JL)LGlic2mWU5&b!pAW^EA8Tm~C&h|*@voLj&Z&E9}WmElcH4moD z@D#dYnO_JaBzqT@eY@lPM2KEAE~1Un#*c*8XT9ET(kOqdchw~+wwm8A3Gg|cj&f7n zrX7qoG$PcaP#o-RC23N+%cy6`QFtF&+gpO!rAKn@-nRiXEY+ZLan8)|K5F6n53#c9 z@JHU^rd8H`@YWd8Xf0`^GHcx0MWuy0&_$E`f@VMT6=>!xFORt4`M5af^5WNSvZlSf|JQXVM%pOn0qtR4BQ}T4K!i+(lu=P3?FA zn*~F?u?ru0Z;RL02;cA2HY?zIilW8uejRga5aUu6a~;cXTa+ULl?b20Npy&Kr!Zfa z?Z~U?HIOe*TGL@T((Oh`C>*7|P>)uRqOe&;9aee1=-Qilo$8Vw1IY0>pc+K>8Uu2OFD&;E4vboekR5zp%xBFNRP?o@bIV1PsU^({$Nd@rDAc(ns(T;Em!`N zQ|tpuhw?{0Uzg^(2;=rau={jn1v%D6=jea3#t~r#zNj;C@~GA@{?E%kGTgN4)W6`e zt`)vP!D5b=99Kd=MQA_aC#$D&dCIKUCyZRq77Sz-ukDm|lFC`&YaR<2P9QUJ)!b_( zZamRhR|t|*wU&*UH2;j}C#pz+Ahu;`pexq%{PMP>qmAe2WSi>uhub}7iq~ypA@TW| ziV+%tS$sD$pOdgL=1sLdLl4vXxbtRLatlbBiimnD0q}fUz4V>o-cQ1+ovuU2kyRt0 zxE=wOj+8WY)ISK(U0itS0_?n~)vwAiS=YOB)})*X5+K>o{>~@M-FVeel#JRrXs+^r z>p)<0!V7mIwvq%0u{Hc%GUA@*dDB)Oyd2q279rvq4QP+^sX4^?_%Z){K4($^3TiB< zIsz!g!kslP&+>4#?9of-D~XD+6mb3Cp7Hz%V?6jRvZX9p-#Mw%i<~C9Vl3KGLjw1H0+`zNZRL(d%ltmyHrUpP0%)aO5=Z86CpDG35NG& zB(0${FE@bTs+1uH>E1U0wi#?EDp-CJK6Xv9-%)nblhAidCpT5)GiC8Jy!9;*FJ(Cd z@by$~l>7a`QalycY*13Sm38juqt_KiZbvyyw&RBP4}q}X3YMHm72>o=bVn1U$K}$57Md>QcbU2-EEkwc7F*E( z)Lm=7l*@e8`w>CNWY?xh&6)FfvSN~MhotHiQTVqvsBo1f8^5=k!hBjqU`?SEB)HRB z8V6I&hNmzC2Om7Vf0v3i-RPxEfhbg#j1EON!YsCDT2n?lUouy2NVMSMYg7)5u6JC? z1;Xog@~1gJhF(9l4b(=TgOr@K77DA9?EamH^}(8wZRD^?g;tQmHf5!0PQNl^!HXVh~h1gd^Nk7B|st) zTYR1QPU%j!Y^_*YG1GB^G|dP73fb6H*;m#v?u|?i*PO$&f+-GC!K6~q-WiqtizGPr^^5MyQxB&`;U+*sW-N51xgx;I52a z^Y7uks*_PAnm#Z;LP) zIkc_#hBkTLI)=yX!4G87+L3a&fx{tRngs|%{_+0*1t@Z!>CgxzdVS>AqaYQ+=`oQg z+|$Iog12Fk=R@0`?9G?Rz09nztlV62BQXMFu+A4o)F{z(=QwzI1i4d&55h$Iz!t$Z z1P>M?O@47qwK@QoGu8J{^vV+BKfsqYv0nNH+#ifB2dk|%+M642;QD5-)dRcKv!XvY ziZi(iBMcWF=kMhihA*}L(ffh%BN8pdY2_}0R1t!=E@W|PPFx=8nJ~jrJ&4NVeNL{> z9H@TIXU#&;>6{&mWcmIP3gqRVO-zLxa{}mS+xR=@cV|e$Av=|l&iZ>HZ;t$$frPEL z^9{g9GvuG{&50904H`=3s0&j`kjXVH$|dMY&Hf4T`%2S6i~UfIcX>PSiE16GjDsq#}qtb+p>K3@JEA8>bX!N@vjlibQYqJ zLC}18VBz46Mr^b@y+}9&JfTvoI}_cSK5mLsx1DO$Yt>h?bfcUQ(D!R7v`}|qhBDOLa`HB#Bk|MFMi#{UYF@+k-7x~eN(Y>yMZoFMIGcX)5f>Bg zZpNLfC2QL~z|r@l%0MPD7nSp=FT=lZW!9Ud5q0u#uj?4g3Px)K)W}I_C)=wIe4LBi zUh3fGHt>~CZ%EbDtN>7%jht0+`{6RlV5;3t5VKmjuc8=-i+4Hn0h=Uhm|74lCD`U} z^ZF4+W4Y?36l8sA%fzP56dfWO;00S`dIWr#v4J(fNG|FYtuRizmUo=2me;n=*#i*Y z(=p-8*?nhuoT8!!{p9ko7yw|mqn{~yJjz&2%S0yKl7chA2dN8;KN6WHg{F#6wFS(c zE@2yoMS0x4uoSxpZvUV*aw<2xUe@ocVe^rQT8*GB=d7iEA!xIp$@QiQ-Sre&;?{-b zI99xdB`7#h>Pjj-Iq9x#^6XRfE9tC3W@a@0!~fUAnFm7Ey>Wby-C*o%k(T!rgRGJ4 zvV_XMjU_vSvJ(cAH(3g=B?>LJ>|s6O{5vd&P@1S)bIRz?mg!@&w1{- z_uTV*Kcb%p_6@BU^u}ze8rh{?6BWI`{Tg@@$ z;nls>P*5VwC2V>>eZF$*j!D|9Th6m#nWW6 z6*AI)_WaDK#OR}3R5Z%P)8ULa95YC5v|e}sXXP@+gGeO7vZ;`tc?jjdUeK#d5GXNw z*nxBR)!=pKlP;+=7&-Wiv2c6j zU{LS&pYA7QV98c%y>K&1 zIOLaxDr=x!oqnOMjY)Gl(&B~2p$Lu_#f2ppk*&_ehOG}bOxt`b_Q&(}V*4F>Y4cL8 zz&MDy=W36c5nY^hgNLT18yMV|T&3=5=CN=;T@boenecpyn$4gd_PpmM#W4ZFFPGc< z(r0u2^&{(qTc<8jh6`vaw$b00i^a1DkKOF#EHUV(Z)@{nE`xYoD-v-dIK0Jxi}WaZ z$IYE0@VMUMoD&=J+;jT-eLn1wWAg0FVOZQ0{bQke&IwqB(N@#}AdRINr=MLhM+zTw zlF4Pw>U7Ok`-3gh-os@1_8tP8?H4(=uT86Gfo#|G@=rNlY4y&89l}Cn+DNzJPo?DuSI*y3d8O-L z;Jm5vB!e_!SRXD&{Ys4Z>qabczb@;sgKvD0P*1YdTcU-pfOYo5!+9wciRwiIfuBqb z*Y~9yX<5uYJr)ze~)!oQySZ|5lI`hh29VW4b|@T_Xkxs_g@woROl(1vCzDx^Tf z17xR$3eWtV*%sq*n&>ao-iSo-zxW_F>6rA7z+uBbuVsc>NSo7JmykLB3f&3&yi_;% zFt%paFta@KIug^CmndrhO<j9w3 zi)UpzdSUPneHOryO{1{ap3DoFtvRfCRTZYOLV z4GdwiWaq$`IEGrYQv_g_IJA*MZ!gs)BW9e?4mS<0pST7$?u)98Kw_Hri9rn=>5fd zZK!}IzsN+V=<{2V;RF(6J3-fAHxxT!Vfj++P^BLe!5_)1GLzv@5q=Qy-vc&I#s_@h z!4=Wjl~AwYBK^O#GPgJ1?TK?aGn0kd+Iiw;Df!{)t_6RX=<^kv#teOfA^B zC>@IEGYmH@q%6{-Yc*(O6zXT8%0vR^qrK7t`cDG#{}!~__38Nd7t-!sQ{WKW`u6UV z{8F3#yL`zgVsF@CnpU6;@mj2Klo(E>|G=vDN?o3tElMWqAqX{SlkzWh_7%0UP}{ff zCRGvPooz6Dy`5miNv0?R5EjinrLP4v_`!o_PI8Ob>}kJP?iFpA568K4@xrLH%VHn@ zuEA$ytHgfIX$nD2uiPr5VJk|S@x(rAS_RQLnY< zw27ym7!5ytqd6KUyJ<@!^_Bq+OozJ(x-4eX436+gsgn_nI*JjI4pr|%*!H*GPpn+b z5v8}&+rEhX($$WQs(RPA;ccTusQu5m8{yEEe zsqGyvC~rSw!zj(Kx&h?n8A0DdO2v3Pp|Y-9hyzMqxHbv!2`q5I$-ui3$Vr*dhLJ{7 z&EF^mXXb>H1~@I&{Kd#WB0@%?yiQ(v5=-Zi_NmTcjJFkIKFV!Nj5os7`*R~`mc$Yk zsE|IDhmncaqU3w>i5y6D+L2e_aG?h4etB6418JIDUKcf(TflEL6DZyWvP641N+78^ zd{IWtDjt$9ldGrDBpcOFP_9V-)+{Tw0H#oy=WgU!9xdOeNnh9>Zrj$ehnL?&_#)9O zknFuMhlNgIu&`@N9sX{mvpGyVDpA&}6(!QUmIm(G#7Ha*kK~UgTs1E;zg%@-@g{Qm z0^i5Jg^iZ1&S9o`)j==9%_gR#I!2FZseSiS#PA~;CY^Z-&xGcPMYZzvIu3(_3x{qa zyimvr#YHDKlSkv-<9h~HqT zrX&lhYtfwQ6_C%UZQJVjwV$9m3sR8(Bx1m6eTdwiR7}^zq1c=+q+aIQ9!p@J@N_l# z*+z4v;GI8RdPdZ=LA6;6qbfXPE#lEmEft|0#T3&LH7)cpEf5Dt+Msmd0yo-LpD}{8 zFKX%R%T8O4t9e`8zg3ky(`_8Ev3PUHGuNo1MVOW#D|lx)4oMN%5UiXW>&g%@bEuCy zB@NbnFR=7XnISU+O6$ddQI0d)L--@nEEW+iP9Ixex18Y#2ap)KPFmP!95YT+tV(EK^`lApeT8v?!?>aDQ* z8+r50SYM%mhkd@oP~2;Lahu^74|gA8=h?xtC8pVGuD4j+;q7S-mK%V#E>Y010UBrO8_S$S<&O8Kr$86v!AMiCCBQ25E01&Yxr>_)L%)ALs&B&vugkq|MRQN z;qH1n_Mv~HoI4!b-)II_S7_xQaSwpLG8b5;fJ{HXxIpC_i+}~^y@rn~K&Wj8tnpHU z2}WWP%m)_=p80jsi#>ILy0faWj|PJ92R@2ug=tSjvoW1Y335!;cnv>k7OP)SG1FHz z*Lmr?ZT3E(j-r1P9#Uj-GWKy68W|<`4#KMgSN)prDuLBMHUC(Xc0P0glt z@mr2Dy;wPk$yEMmpnHyEY6EC|+?W?5Xo=~5OI!skh#h$?;pKBCpFR1^jWh2rW{&J6&;oCxvN?cA z1QcKU(s<=pkCY=rS_#7=VY+i=bECj{;&ELiyb59chRSp}r`zf{qQVd?HuLAErg&T; zX7R>sT0i}M=q*4H7RI&PA%icOMf?t`$~z>4HIQn{h|f6M4hjzi@EceECoY+Cd-`Nv zoz;cuF}Hv0rAG@ld^q0`0SLhd=H3m)0l9ET#aX)b{^3FNyt?JW18^iGac*Wjo2}G> zGVcw&f8dI|4 z57xE;(en$@vCg`ebkWBM1`xIa$PNZbgHfUNMkt@1%GTUe^J&PqLl!^YNnr58 zpUCFlNA<1%Ki2>jg@~JNXt%#rrxhuUDX}&o47Hvw3IJAsQiM0<#r&sJJPlygs%?W! z=--5%j2M9=ijX}Xi`S5P(OqrxV9O&$2~ad$?U=*s|9P^bDH#zZqHEfBe%#$f>ZDFg zt`)U)mkMxpX4EsV5dZtA=-bR;zuQx2v}&_|b+LvUCE8JrTt2x2#5Ed;&4;XqdP^pk zJ@2AIPA&#jR%9ZYfWuAjS+iZGP!BvT<(Ll1x9j=)g24$(?DjRTO%Qt=q@d*3@ z6r1Gwqi#EIWxFq0Y#bn+PeKcX)qlo_X#~(hiZ!GGyz%a(J8Qqejv)IDKEO?IVZUyw zcwG(IN}CWwkN@4A*i9JS6p*k;<=RX;TfOwWS35{)y!lqG`blpf+EM^{WvI7m&^~1o zxd}6@jWQHISt39n_-$UYQje>j5>b@FX4JUsiJYu1z0sRH<#Yqj6c3 z$)8&612Nj8TK02Gjl3<41+>$ugU#uhIRzhn_xOwzI^%dDZnXv3e0{wTzdWs$!?|M` zv!dfD8T{L`UYz%_Xrm*ew>`LiRd*!5- -
+
-

- - Şirket Yönetimi -

-

- Sisteme kayıtlı şirketlerin listesi ve yeni şirket ekleme alanı. -

+
+
+
+

Şirket Yönetimi

+

+ Sisteme kayıtlı şirketlerin listesi ve yeni şirket ekleme alanı. +

+
+
@@ -34,26 +36,32 @@ export default async function CompaniesPage() { Yeni Şirket Ekle
-

Çalışanları atayabilmek için öncelikle şirket kaydı açmalısınız.

+

Personelleri atayabilmek için öncelikle şirket kaydı açmalısınız.

-
+ { + 'use server'; + await addCompany(formData); + }} + className="mt-5 space-y-4" + >
- +
@@ -62,13 +70,13 @@ export default async function CompaniesPage() { {/* Company List */}
- - +
+ - - - + {companies?.map((company) => ( - - + - - diff --git a/src/app/employees/actions.ts b/src/app/employees/actions.ts index 90577d6..75ac06d 100644 --- a/src/app/employees/actions.ts +++ b/src/app/employees/actions.ts @@ -11,9 +11,10 @@ export async function addEmployee(formData: FormData) { const lastName = formData.get('last_name') as string const email = formData.get('email') as string const companyId = formData.get('company_id') as string + const roleId = formData.get('role_id') as string - if (!email || !companyId) { - return { error: 'E-posta ve Şirket seçimi zorunludur.' } + if (!email || !companyId || !roleId) { + return { error: 'E-posta, Şirket ve Rol seçimi zorunludur.' } } // Admin creating users manually currently requires an admin API setup or the user registering themselves @@ -39,9 +40,10 @@ export async function addEmployee(formData: FormData) { .insert([{ user_id: existingUser.id, company_id: companyId, + role_id: roleId, department: formData.get('department'), title: formData.get('title'), - status: 'active' + status: formData.get('status') || 'active' }]) if (employeeError) { @@ -49,7 +51,7 @@ export async function addEmployee(formData: FormData) { if (employeeError.code === '23505') { return { error: 'Bu kullanıcı zaten bu şirkete eklenmiş.' } } - return { error: 'Çalışan eklenirken hata: ' + employeeError.message } + return { error: 'Personel eklenirken hata: ' + employeeError.message } } revalidatePath('/employees') @@ -65,7 +67,29 @@ export async function deleteEmployee(id: string) { .eq('id', id) if (error) { - return { error: 'Çalışan silinirken hata oluştu: ' + error.message } + return { error: 'Personel silinirken hata oluştu: ' + error.message } + } + + revalidatePath('/employees') + return { success: true } +} + +export async function updateEmployee(id: string, formData: FormData) { + const supabase = await createClient() + + const { error } = await supabase + .from('employees') + .update({ + company_id: formData.get('company_id'), + role_id: formData.get('role_id'), + department: formData.get('department'), + title: formData.get('title'), + status: formData.get('status') + }) + .eq('id', id) + + if (error) { + return { error: 'Personel güncellenirken hata oluştu: ' + error.message } } revalidatePath('/employees') diff --git a/src/app/employees/page.tsx b/src/app/employees/page.tsx index 4a8ba7d..d749c55 100644 --- a/src/app/employees/page.tsx +++ b/src/app/employees/page.tsx @@ -1,6 +1,5 @@ import { createClient } from '@/utils/supabase/server' -import { addEmployee, deleteEmployee } from './actions' -import { UsersIcon, TrashIcon } from '@heroicons/react/24/outline' +import EmployeeTable from '@/components/employees/EmployeeTable' export default async function EmployeesPage() { const supabase = await createClient() @@ -10,180 +9,39 @@ export default async function EmployeesPage() { .from('employees') .select(` id, + user_id, + company_id, + role_id, department, title, status, created_at, - companies ( name ), - users ( first_name, last_name, email ), - roles ( name, description ) + companies ( id, name ), + users ( id, first_name, last_name, email ), + roles ( id, name, description ) `) .order('created_at', { ascending: false }) - // Fetch companies for the dropdown + // 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') + return (
-
-
-

- - Çalışan Yönetimi -

-

- Sisteme kayıtlı çalışanları görüntüleyin ve yeni çalışanları şirketlere atayın. -

-
-
- -
- - {/* Add Employee Form */} -
-
-

- Yeni Çalışan Ata -

-
-

Sisteme daha önce kayıt olmuş (şifre oluşturmuş) kullanıcıları şirketlere atayın.

-
- -
-
- - -
- -
- - -
- -
- - -
- -
- - -
- - - -
-
- - {/* Employee List */} -
-
-
+ Şirket Adı + Kayıt Tarihi @@ -76,13 +84,13 @@ export default async function CompaniesPage() {
+
{company.name} + {new Date(company.created_at).toLocaleDateString('tr-TR')} @@ -90,7 +98,7 @@ export default async function CompaniesPage() { 'use server'; await deleteCompany(company.id) }}> - @@ -99,7 +107,7 @@ export default async function CompaniesPage() { ))} {(!companies || companies.length === 0) && (
+ Henüz kayıtlı şirket bulunmamaktadır.
- - - - - - - - - - - {employees?.map((emp) => ( - - - - - - - - ))} - {(!employees || employees.length === 0) && ( - - - - )} - -
- Kişi - - Şirket - - Departman / Ünvan - - Durum - - İşlemler -
-
- {emp.users?.first_name} {emp.users?.last_name} -
-
{emp.users?.email}
-
-
{emp.companies?.name}
-
-
{emp.department || '-'}
-
{emp.title || '-'}
-
- - {emp.status === 'active' ? 'Aktif' : 'Pasif'} - - -
{ - 'use server'; - await deleteEmployee(emp.id) - }}> - -
-
- Sisteme kayıtlı çalışan bulunmamaktadır. -
-
-
- -
+ ) } + diff --git a/src/app/favicon.ico b/src/app/favicon.ico deleted file mode 100644 index 718d6fea4835ec2d246af9800eddb7ffb276240c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25931 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 LrJugUA?W`A8`#=m diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 939bbf6..65b75e3 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -16,10 +16,14 @@ const geistMono = Geist_Mono({ }); export const metadata: Metadata = { - title: "HRMS Yönetim Sistemi", + title: "Abisena | Personel Takip Sistemi", description: "Şirket içi insan kaynakları yönetim paneli", + icons: { + icon: "/favicon.png", + }, }; + export default async function RootLayout({ children, }: Readonly<{ diff --git a/src/app/leave-requests/actions.ts b/src/app/leave-requests/actions.ts index eaf5cfb..10fa477 100644 --- a/src/app/leave-requests/actions.ts +++ b/src/app/leave-requests/actions.ts @@ -27,7 +27,7 @@ export async function submitLeaveRequest(formData: FormData) { .single() if (empError || !employeeData) { - return { error: 'Seçili şirket için çalışan kaydınız bulunamadı.' } + return { error: 'Seçili şirket için personel kaydınız bulunamadı.' } } const { error } = await supabase diff --git a/src/app/leave-requests/page.tsx b/src/app/leave-requests/page.tsx index 6231d83..633e71d 100644 --- a/src/app/leave-requests/page.tsx +++ b/src/app/leave-requests/page.tsx @@ -53,17 +53,19 @@ export default async function LeaveRequestsPage() { return (
-
+
-

- - İzin Talepleri -

-

- {isAdminOrManager - ? 'Tüm çalışanların izin taleplerini görüntüleyin ve onaylayın.' - : 'Kendi izin taleplerinizi oluşturun ve durumlarını takip edin.'} -

+
+
+
+

İzin Talepleri

+

+ {isAdminOrManager + ? 'Tüm personellerin izin taleplerini görüntüleyin ve onaylayın.' + : 'Kendi izin taleplerinizi oluşturun ve durumlarını takip edin.'} +

+
+
@@ -86,7 +88,7 @@ export default async function LeaveRequestsPage() { id="company_id" name="company_id" required - className="mt-2 block w-full rounded-md border-0 py-1.5 pl-3 pr-10 text-gray-900 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-blue-600 sm:text-sm sm:leading-6 dark:bg-zinc-800 dark:text-white dark:ring-zinc-700" + className="mt-2 block w-full rounded-xl border-0 py-2.5 pl-3 pr-10 text-slate-900 ring-1 ring-inset ring-slate-200 dark:ring-zinc-700 dark:bg-zinc-800 dark:text-white focus:ring-2 focus:ring-indigo-500 sm:text-sm outline-none" > {userCompanies?.filter((c: any) => c.companies).map((c: any) => ( @@ -123,7 +125,7 @@ export default async function LeaveRequestsPage() { id="reason" rows={3} required - className="mt-2 block w-full rounded-md border-0 py-1.5 px-3 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 dark:ring-zinc-700 dark:bg-zinc-800 dark:text-white sm:text-sm sm:leading-6" + className="mt-2 block w-full rounded-xl border-0 py-2.5 px-3 text-slate-900 shadow-sm ring-1 ring-inset ring-slate-200 dark:ring-zinc-700 dark:bg-zinc-800 dark:text-white placeholder:text-slate-400 focus:ring-2 focus:ring-inset focus:ring-indigo-500 sm:text-sm outline-none" />
@@ -134,7 +136,7 @@ export default async function LeaveRequestsPage() { const { submitLeaveRequest } = await import('./actions'); await submitLeaveRequest(formData); }} - className="inline-flex w-full items-center justify-center rounded-md bg-blue-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-blue-500" + className="inline-flex w-full items-center justify-center rounded-2xl bg-indigo-600 px-3 py-3 text-sm font-bold text-white shadow-sm shadow-indigo-200 dark:shadow-none hover:bg-indigo-700 transition-all active:scale-95" > Talep Oluştur @@ -151,18 +153,18 @@ export default async function LeaveRequestsPage() {
- + - - - - {isAdminOrManager && ( @@ -172,30 +174,32 @@ export default async function LeaveRequestsPage() { )} - + {requests?.map((req: any) => { - const employeeInfo = req.employees?.users || {}; + const employeeData = Array.isArray(req.employees) ? req.employees[0] : req.employees; + const userData = Array.isArray(employeeData?.users) ? employeeData.users[0] : employeeData?.users; + const companyData = Array.isArray(employeeData?.companies) ? employeeData.companies[0] : employeeData?.companies; return ( - + - - - diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index e5b4346..ca86658 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -6,77 +6,68 @@ export default function LoginPage({ searchParams: { error?: string } }) { return ( -
-
+
+
-

- HRMS Sistemine Giriş +

+ Abisena Giriş

-

- Lütfen e-posta ve şifrenizle giriş yapın. +

+ Personel Takip Sistemine Giriş Yapın

-
+ {searchParams?.error && ( -
+
E-posta adresi veya şifre hatalı.
)} -
+
-
- -
+
-
-
- -
-
- -
-
- -
- + Şifre + +
- + +
) diff --git a/src/app/page.tsx b/src/app/page.tsx index ae23c51..42973bb 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -11,18 +11,26 @@ export default async function Home() { redirect('/login') } - // Fetch the extended user metadata from our 'users' table - const { data: dbUser } = await supabase + // Deep debug: Fetch users and employees separately + const { data: dbUser, error: dbUserError } = await supabase .from('users') - .select('*, roles(name, description)') + .select('*') .eq('id', user.id) .single() - const roleData: any = dbUser?.roles - const role = Array.isArray(roleData) ? roleData[0] : roleData + const { data: dbEmployees, error: dbEmpError } = await supabase + .from('employees') + .select('*, roles(*)') + .eq('user_id', user.id) + + const userData = dbUser + const role = dbEmployees?.[0]?.roles || null + const displayName = userData?.first_name + ? `${userData.first_name}${userData.last_name ? ' ' + userData.last_name : ''}` + : user.email?.split('@')[0] const stats = [ - { name: 'Toplam Çalışan', stat: '0', icon: UsersIcon, change: '12%', changeType: 'increase' }, + { name: 'Toplam Personel', stat: '0', icon: UsersIcon, change: '12%', changeType: 'increase' }, { name: 'Bekleyen İzinler', stat: '0', icon: CalendarDaysIcon, change: '3', changeType: 'increase' }, { name: 'Aktif Şirketler', stat: '1', icon: BuildingOfficeIcon, change: '0%', changeType: 'none' }, ] @@ -30,75 +38,92 @@ export default async function Home() { return (
- {/* Welcome Section - Premium Header */} -
-
-

- Hoş Geldiniz, {dbUser?.first_name || user.email?.split('@')[0]} 👋 -

-

- IK Yönetim Sistemine tekrar hoş geldiniz. Bugün {role?.name || 'Kullanıcı'} yetkileriyle sisteme bağlısınız. -

+ {/* Welcome Section - Modern & Clean */} +
+
+
+

+ Hoş Geldiniz, {displayName} 👋 +

+

+ IK Yönetim Sistemine tekrar hoş geldiniz. Bugün sisteme + + {role?.name || 'Kullanıcı'} + + yetkileriyle bağlısınız. +

+
+
+ {[1,2,3,4].map(i => ( +
+ ))} +
+12
+
- {/* Decorative backdrop blobs */} -
-
+ + {/* Corporate decorative element */} +
+
- {/* Stats Grid */} -
+ {/* Stats Grid - abisena.tr Style */} +
{stats.map((item) => (
-
-
-
+ {/* Subtle progress bar */} +
+
- {/* Subtle background icon for premium feel */} -
))}
{/* Profile & Quick Actions section */}
-
-

-
+
+

+
Sistem Bilgileri

-
    -
  • - E-posta - {user.email} +
      +
    • + E-posta Adresi + {user.email}
    • -
    • - Hesap Tipi - -
      +
    • + Hesap Yetkisi + {role?.description || 'Standart Erişim'}
    • - Son Giriş - {new Date().toLocaleDateString('tr-TR')} + Sistem Tarihi + {new Date().toLocaleDateString('tr-TR', { day: 'numeric', month: 'long', year: 'numeric' })}
+ + +

); } diff --git a/src/components/employees/EmployeeModal.tsx b/src/components/employees/EmployeeModal.tsx new file mode 100644 index 0000000..909659b --- /dev/null +++ b/src/components/employees/EmployeeModal.tsx @@ -0,0 +1,175 @@ +'use client'; + +import { useState, useEffect } from 'react'; +import { XMarkIcon } from '@heroicons/react/24/outline'; +import { addEmployee, updateEmployee } from '@/app/employees/actions'; + +interface EmployeeModalProps { + isOpen: boolean; + onClose: () => void; + companies: any[]; + roles: any[]; + editingEmployee?: any; +} + +export default function EmployeeModal({ isOpen, onClose, companies, roles, editingEmployee }: EmployeeModalProps) { + const [error, setError] = useState(null); + const [loading, setLoading] = useState(false); + + if (!isOpen) return null; + + async function handleSubmit(formData: FormData) { + setLoading(true); + setError(null); + + try { + let result; + if (editingEmployee) { + result = await updateEmployee(editingEmployee.id, formData); + } else { + result = await addEmployee(formData); + } + + if (result.error) { + setError(result.error); + } else { + onClose(); + } + } catch (err) { + setError('Bir hata oluştu, lütfen tekrar deneyin.'); + } finally { + setLoading(false); + } + } + + return ( +
+
+ + {/* Header */} +
+
+

+ {editingEmployee ? 'Personel Düzenle' : 'Yeni Personel Ekle'} +

+

+ Personel bilgilerini eksiksiz doldurunuz. +

+
+ +
+ + {/* Body */} +
+ {error && ( +
+ {error} +
+ )} + +
+ {!editingEmployee && ( +
+ + +
+ )} + +
+
+ + +
+ +
+ + +
+
+ +
+
+ + +
+ +
+ + +
+
+ +
+ + +
+
+ +
+ + +
+ +
+
+ ); +} diff --git a/src/components/employees/EmployeeTable.tsx b/src/components/employees/EmployeeTable.tsx new file mode 100644 index 0000000..8bd117d --- /dev/null +++ b/src/components/employees/EmployeeTable.tsx @@ -0,0 +1,211 @@ +'use client'; + +import { useState } from 'react'; +import { + UsersIcon, + TrashIcon, + PencilSquareIcon, + PlusIcon, + MagnifyingGlassIcon +} from '@heroicons/react/24/outline'; +import { deleteEmployee } from '@/app/employees/actions'; +import EmployeeModal from '@/components/employees/EmployeeModal'; + +interface EmployeeTableProps { + initialEmployees: any[]; + companies: any[]; + roles: any[]; +} + +export default function EmployeeTable({ initialEmployees, companies, roles }: EmployeeTableProps) { + const [employees, setEmployees] = useState(initialEmployees); + const [searchTerm, setSearchTerm] = useState(''); + const [statusFilter, setStatusFilter] = useState('all'); + const [isModalOpen, setIsModalOpen] = useState(false); + const [editingEmployee, setEditingEmployee] = useState(null); + + const filteredEmployees = employees.filter(emp => { + const userData = Array.isArray(emp.users) ? emp.users[0] : emp.users; + const fullName = `${userData?.first_name || ''} ${userData?.last_name || ''}`.toLowerCase(); + const email = (userData?.email || '').toLowerCase(); + const matchesSearch = fullName.includes(searchTerm.toLowerCase()) || email.includes(searchTerm.toLowerCase()); + const matchesStatus = statusFilter === 'all' || emp.status === statusFilter; + return matchesSearch && matchesStatus; + }); + + const handleEdit = (emp: any) => { + setEditingEmployee(emp); + setIsModalOpen(true); + }; + + const handleAdd = () => { + setEditingEmployee(null); + setIsModalOpen(true); + }; + + const handleDelete = async (id: string) => { + if (confirm('Bu personeli silmek istediğinize emin misiniz?')) { + const result = await deleteEmployee(id); + if (result.error) { + alert(result.error); + } + } + }; + + return ( +
+ {/* Header with Add Button */} +
+
+
+
+
+

Personeller

+

+ Şirketinizdeki tüm personel kayıtlarını yönetin +

+
+
+
+ +
+ + {/* Filter & Search Bar */} +
+
+ + setSearchTerm(e.target.value)} + placeholder="İsim veya e-posta ile ara..." + className="w-full pl-12 pr-4 py-3 bg-slate-50 border-none rounded-2xl text-sm font-medium focus:ring-2 focus:ring-[#CE0515] transition-all outline-none placeholder:text-slate-400" + /> +
+
+ + + +
+
+ + {/* Table Section */} +
+
+
- Çalışan + + Personel + Tarih Aralığı + Gerekçe + Durum
-
- {employeeInfo?.first_name} {employeeInfo?.last_name} +
+ {userData?.first_name} {userData?.last_name}
-
{req.employees?.companies?.name}
+
{companyData?.name}
+
{new Date(req.start_date).toLocaleDateString('tr-TR')}
{new Date(req.end_date).toLocaleDateString('tr-TR')}
+ {req.reason} - {req.status === 'approved' ? 'Onaylandı' : req.status === 'rejected' ? 'Reddedildi' : 'Bekliyor'} @@ -209,7 +213,7 @@ export default async function LeaveRequestsPage() { 'use server'; await updateLeaveStatus(req.id, 'approved') }} - className="text-green-600 hover:text-green-900 dark:text-green-500 dark:hover:text-green-400 bg-green-50 hover:bg-green-100 dark:bg-green-500/10 p-2 rounded-lg transition-colors" title="Onayla"> + className="text-emerald-600 hover:text-emerald-900 dark:text-emerald-500 dark:hover:text-emerald-400 p-2 rounded-xl hover:bg-emerald-50 dark:hover:bg-emerald-500/10 transition-all" title="Onayla"> @@ -228,7 +232,7 @@ export default async function LeaveRequestsPage() { )})} {(!requests || requests.length === 0) && (
+ Henüz bir izin talebi bulunmamaktadır.
+ + + + + + + + + + + {filteredEmployees.map((emp) => { + const userData = Array.isArray(emp.users) ? emp.users[0] : emp.users; + const companyData = Array.isArray(emp.companies) ? emp.companies[0] : emp.companies; + const roleData = Array.isArray(emp.roles) ? emp.roles[0] : emp.roles; + + return ( + + + + + + + + ); + })} + {filteredEmployees.length === 0 && ( + + + + )} + +
PersonelŞirket / RolDepartman / ÜnvanDurum + İşlemler +
+
+
+ {userData?.first_name?.[0]}{userData?.last_name?.[0]} +
+
+

+ {userData?.first_name} {userData?.last_name} +

+

{userData?.email}

+
+
+
+

{companyData?.name}

+

{roleData?.description}

+
+

{emp.department || '-'}

+

{emp.title || '-'}

+
+ + + {emp.status === 'active' ? 'Aktif' : 'Pasif'} + + +
+ + +
+
+ +

Herhangi bir personel kaydı bulunamadı.

+
+
+
+ + {/* Modal */} + setIsModalOpen(false)} + companies={companies} + roles={roles} + editingEmployee={editingEmployee} + /> +
+ ); +} diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx index c068de4..c0f741f 100644 --- a/src/components/layout/Header.tsx +++ b/src/components/layout/Header.tsx @@ -11,9 +11,12 @@ export function Header({ user }: { user?: { email?: string; first_name?: string
Profil -
+
{user?.first_name?.[0]?.toUpperCase() || user?.email?.[0]?.toUpperCase() || 'U'}
+ + + {user?.first_name || user?.email?.split('@')[0] || 'Kullanıcı'} diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx index 4cbdb08..cde7809 100644 --- a/src/components/layout/Sidebar.tsx +++ b/src/components/layout/Sidebar.tsx @@ -2,6 +2,7 @@ import { useState } from 'react' import Link from 'next/link' +import Image from 'next/image' import { usePathname } from 'next/navigation' import { HomeIcon, @@ -16,7 +17,7 @@ import { const navigation = [ { name: 'Dashboard', href: '/', icon: HomeIcon }, - { name: 'Çalışanlar', href: '/employees', icon: UsersIcon }, + { name: 'Personeller', href: '/employees', icon: UsersIcon }, { name: 'İzinler', href: '/leave-requests', icon: CalendarDaysIcon }, { name: 'Şirketler', href: '/companies', icon: BuildingOfficeIcon }, { name: 'Ayarlar', href: '/settings', icon: Cog6ToothIcon }, @@ -29,16 +30,18 @@ export function Sidebar() { return ( <> {/* Mobile sidebar trigger */} -
+
-
- HRMS +
+ Abisena Logo +
+ Personel
Sistemi
@@ -59,11 +62,11 @@ export function Sidebar() {
{/* Mobile Sidebar Content */} -
-
-
- - HRMS +
+
+
+ Abisena Logo + TAKİP SİSTEMİ