From deca9e1e2c243141df3fa879e5767edb59925d15 Mon Sep 17 00:00:00 2001 From: Ali Nabhan Aboobakuru <Ali3.Aboobakuru@live.uwe.ac.uk> Date: Thu, 10 Oct 2024 00:43:00 +0500 Subject: [PATCH] Final commit: added onboarding, models, and templates --- .../__pycache__/forms.cpython-311.pyc | Bin 3899 -> 8226 bytes .../__pycache__/models.cpython-311.pyc | Bin 3341 -> 4968 bytes .../__pycache__/views.cpython-311.pyc | Bin 7702 -> 9103 bytes postgresTest/PROJECT1/forms.py | 94 +++++++++++-- ...salary_employee_id_card_number_and_more.py | 40 ++++++ ...ee_id_card_number_and_more.cpython-311.pyc | Bin 0 -> 2302 bytes postgresTest/PROJECT1/models.py | 52 +++++-- postgresTest/PROJECT1/templates/base.html | 132 +++++++++++------- postgresTest/PROJECT1/templates/index.html | 48 ++++--- .../PROJECT1/templates/onboard_employee.html | 91 +++++++++++- postgresTest/PROJECT1/views.py | 56 ++++++-- .../__pycache__/settings.cpython-311.pyc | Bin 4125 -> 4146 bytes postgresTest/postgresTest/settings.py | 13 +- 13 files changed, 421 insertions(+), 105 deletions(-) create mode 100644 postgresTest/PROJECT1/migrations/0022_rename_price_job_salary_employee_id_card_number_and_more.py create mode 100644 postgresTest/PROJECT1/migrations/__pycache__/0022_rename_price_job_salary_employee_id_card_number_and_more.cpython-311.pyc diff --git a/postgresTest/PROJECT1/__pycache__/forms.cpython-311.pyc b/postgresTest/PROJECT1/__pycache__/forms.cpython-311.pyc index e43f987ffec4721365fff7387a20d7e579fcc1de..8ec5d4336fe99bbf4023b50e27d5a05d31a20302 100644 GIT binary patch literal 8226 zcmZ3^%ge>Uz`&r`&Xz7F$-wX!#DQT}DC6@J1_p-d3@HpLj5!Rsj8Tk?AU0DDQ!aB9 zGnmbs!;;Gy#mdN#!ji(8!<Ne)#h%L%#gWSy#R-;Y%i+r9j^fVciQ)nC*>iZKc$pa7 z8B#b}7*aS>8MFAHb}=ktW?)#&4C6)dgH>_0Fr;v&GNZ`}faQ2v7*crgm>>vN#n-}+ z!jDIlPzrl6gQmbskj0vew^-Bii*k!K8E*-M7N-_D7o{eaWaj6&<rn2@GT!1#Pc4Zr zElw?p&&^Ls&3Vblz`&r%e2d*VKd&S)x#Sj?b7^r&elAGoEe_Y*f}H%y)KpETTYN#O z>8TZAi8+}mi6!|(xA<Ih6Ekz*e7|In<uJ?wWqj5E2YxC;6k`fQ6cgApj4cc)Ov{)U z7*;buRWU>{r!WUIXtLZA3d+w(bu2E<OwY?r%_{*p8O2<9q&lIPo5~!;lERqI7{!{x z$i$G!mc<S;Ih`SeX%XWZ=4Ffw468w21xsWyMscLD1T$!|{u0NuQO`HEB=HtYQGQOU zCW|K1Emp^r+|0aNykIJ`xTFZ=e@&)aOddg193DXm!6k`lX_`#8*nJc864O(Qssv!c zrT`VuWGdohU|;|fnvA#DlQZ%&lT(ZRG&yf^#K-3)=BCES-{Oh~#Ykxmh|LopUs#%$ z1Cc4>U|?Xl#R`tDTWo2WsW~adMW94>i!C@cCpEd`7JGSSN_uKZ@k)lzApia9bhe5C zMPM<QjB!aV&MwI>hzZNg$w_q1&&f$mPmKw#EG|jSRd7iyOU=nI0EM<fsGGB!d9bdr zfv!;uA`%olLVSG`obyvsV;plb<NXqoG7|IRjf@S<42=y<V+!(%OVW!{i$hY2OJV|o z{JmVALkwfUDNwJV@)ipyFpKyZ7#O%27#NB@7#J8D;P8fkR0rz~A&ChR9c&MHgeLe* zaGm1wfq_+v4}}or|H!~9%KrsKd|+l5=IUSv!6G?Om?|(ZF!*V*6p4X2;vhl-M1X{g zWI-&jDtQo#7e;_ejba-Vr+i@IV&(e4fJuA=iG2YPXtEINL1v;PQBY)oBH{BClqAZ; zkjk6|%N7jaWXhZcOU?`_OexGMEOVIFu%aeZP-0GDTf>ejn$Ea}1FbY+2WKtL7KRkA zRE{iAVgtDWy*%Pf;SOfd<hdn=$m7VRL&z^4P`v3T=jW9a<>%aD1!wV<Ot)B*a}tY- zZ*dpoBqpb3<maTM7OiBw#hO@BQdIm)#x<`bwMZdRp$t?uD5Qdl1%<?vl%mw)V!f4& zx7c%2i;EM}Q#F}yaTKK%mSz^ErrctKq}W?rU`?P5Rg4mfu%h9!14bw=V_;xd4fY*~ zh+;`)&0+(wKp2tnQy8ll7#O11Q<#DoG?{-%WA`yQtAk2Ru&ezvIna|4D29q8LFon* zcSYb-B?aQ5B`vUoAp-*gh*7MKlC*9J$W7q8D4=jfK%s;6hM?jVLA5J_x*NDI3R-or zfgmI$fpq$5a-q8boYA?!G2sTv`nMo#&%A=tk|I!^Dl!7O2jM(4mnnf{K?KMb#l5I5 z<B{oby}~1NLs0YvzkEmO6@K{*d?(5;sD*<Nf5b)ph%5XNH$;>s_+8NUyddIrQN-(t zh}Q*S?+@%OylfvCSa{jKfQSay4?Ik))*l!!i3|MlSNK&vf@Hpc2sAYizk}R|68|9Y zfFks>9$NgnGo;|CKw220SRjS^EpBLKhEadOGREfvD8_>7k939<#zl-#te`B1l#IX` zGlg{y^BOkPOo*nA9h8A_s)H2@3@IFV)xq4ykiwb5oWh08ycEVcEKyvLjQmRg$)k|8 z%yNqbRBPN~Ey&2vONFEj9R>!5D$dCK(jo=F#N5=7B4u!$U!)F78oD4t4Mc$I>R&to zAbkpcrMXF|MMWy0nupyNl7XuvkV^*zXtvf(%CGR#<VH`npc)vGalqLHoQgR^QY%Uz z3D*Q<Fb9aASd^MrBm=S^E#ZRlLy-jo0|UsJ#fwoBu7EfwE16vo1fdSL2O`Q7T&MW& z(7q5Hej%ygf>t32i4<KFDY_z3bVF2SLg<wE9d;MOqc5bDT+l8BA<?pnqGeY^%WjCO zP6)jss=CAdLSX2HguDwn`5+`(a8b12ifF+Nan%W>Q|fkjf{m`Zpi>J%;&m6r>#m5` zec)sj=K8?EidiQm!&@5+3=E*;3<`qJMc{N-!;l3^++e%_SshpeM5HjHrnXwf5>QbD zl44*0R~KtoP}@+oOiT<lOf_iw7#V69LG2vBA}a<4hF|<~G1~Tq_Ax2dmO6%}wJKFX zkm$|>N4G+5X>o}{QmR5Ks6<aqQOL|wD9K1w07ZLZiIsx7wj~Ux>nVg5D3s(Y7@8`i zWTt196e}d=<m8v9rs#p{i=x!@)QTcdx?9P7izhiJH8C$WB|aswB=Ht=dTL1#7Xt&s zO6FTE#i==IV3*zE2dCF~M0EfPE(HaJB2dkJiyLf2JXlSYIC7##k^q&1#h&1FazjAm zih$yE0o6+asteLD3g}%C(Cc8mE2VKmNacn|#s^krX|9h9%+g$6Ktu=s2Mz{Ki4Oi5 ztQR@tu5id*;E=n)FVevSE}Z-{S<w?WIB9}xLT_Q1fzmOE0A;9RZ?Icn&7BWS9H15k zCh?JhgO%$Gi1+{|#MoIyKQLetVAm9ZOvheSUIV8sL|YrR!I8qWh8Z=*fXg~&MCF;n zn8Jdgh8^5+fmg68j47-bYB<1ZKxrJDK2sP|*f7*^f*UC8Eet6fXs+N&;cQ`u;!fde zVTj^M;cj7w;!WXcVTj^O;ca1v;!oiVX3*rn#pj=wl%H6Xl9`tdD%C@(cmwitGLusk zf>I0ei%K+^ia-U~E!LdGq|}@$eoq$#=ft8E1r4{N{Jav)Dn7V?Q(|(qW)-({n1V)7 zYH?|9swPTk3WB}B!0?%m3Dj+bg(jgI0(;X9r5<6!)xgU_)DBE3>^N0{N>s4pQkYUW zaH>MoAWSKoI8`B=#YL1VZk(z>c^T#|o)lgjAwirfWOwo5v=LbqKT)a#aH>KMFF|ao zQiSI4MscSI2Qz4j{1Qe@g^(&&@D^8EW>IkoxFdIqGba(sgjBwua`zTHv^{)_D<!oc zv8V*p-MYn@m7f$}l39|IdW);LB(bOjR6wTQ;!Q~`NsZ4>i%-fdD#^ITmzffuoLH0+ z4=JN>iKXVI7Nw`=C0E9S+UbeOP<zEO#lgkpE#aiZyzI=p^!Us?NI{;NpLdJ50GxZ` zi@>?(7B9?_G*EWA#RKCeB_?OzVoELpw-~Cp+(6z0w;_sDK_wli#ZblRlUQ5=7Odh0 zH&YcHA&vhcYf!sGI4HF^GbJ^zBr`DwCUc9+1s)7loL>1!3L)TNU;%kulc@+)dfs9w zsVqoEWL!v#q)N;c=6wZdH2|?%98(-zwN=SELA<ZviSWLHMt%WkNF*^wQ<JyIALNw) z5CN(|z|~PvAcz|TB7#9g2#5#;5n&)A97IHbh)8hnlLx(m0HrFl)=!ZwNIj_CQ)I`$ zz;KJxC9xzG(ip<o`tf66U~mC-o3}8ccAF(SSU)ha3V~W4P@;qF10RF5)(q7-`aAS4 zM5bOaNCP3M^ovsISESN!NNUUwog=?P?m|TJ1^pBdl1#lQnR-Ps71sXQkar<8<$_Ks z2#Ka$6ivG#nsx)ya@r7gAtdR7b}|Twrd$+FxgweZZ5M%bWnIw81|jjBi{d#~#B**) zX_Dg(xUQgx3kH!OBo%d0D(Z?<)D2mk8KHCHcf?%?jlN(U146Q~7iD9w$j07~)18qz zCx1uYh1lE+CV3zvmw!<%|B77x4K>pRsY~(?<XuRuy<k%ZLTdFF)#|UP)!$GzTTr^B z{y^P@wE7PW40eu8a8kpG=_3P!h7;2lFnL4SaDnL(y90V37#NZmoj~d=oe`vp3rMw! z3rMw!3)2T_K2URzk3e$})V2ZP&jsKroATx$`T!T+#vqFyq-4?pB}h<LRg<|0l*)=+ zK?2;6zJWW44ayI<_`!W+0xdJJnkp%@;t|p~1IxvNk})XZH!$FAoLw;VzaSNGQ7Yhy zR6qy+4GwV}Ei#m*H7FcG`13Nd!?K341m1XIV8{ZQ2CmQ+Ac=wnzy!!1#P~xtSWS^g z2`Jpa@(c_}O)4hTW_%MPxH-=3R|G0is+5C4#l8Zl)Kf@K%*)FMx4vPm?$VOdqEx+= z?1;#@#Q{=Ul9`)Y6b~vxSWEI#5-TBNf&9>+*v$Mq*P^2QB2A_ua2$dxDh3Uwz}nIR zkXS*~I92jkqYa@T1r&Fn=57PS4N=J}qH5PgwJwQjt+2T$YH>x>qJ!%Ox9D7sIlR{; zv@c0$UzE_jBB6VUTlWID?p-1AD?;iQG<+`#`CSq6yTIdjgJ1Fjha|WuJE)=&+`A$@ z8bNhJl@h2ZSIAFO0N2>?UKBJQ3lfV<^or6z*$NsZAWbMyA`FQVP~^fZ{wgJ`v4Wx| z8!2KWWUfePUYF3lB%!+^|DuH56$!fz-W%K!b3NwxUYF6oB%^;(#_)=a;U#Xv3*3gV zi1E27<a<TP_X3aa4Stym95R>@14`eZ95KLM*CNnBU{wI>SR=TBqX20bk=I!*as-ug z&LF}K6qq2N!g`%Wpd^o@Oat2t>dX_>;Y=f`!-<kF20`$H8#>_NPeKiTc#Bg3+7eX& z2Md)VM3Wg(fPt+C%^MUWN6sx-NS=Ya0p1!0yP--4Ywp3Jx&{>WzTn>a4JEZJO2*ff z%r7aKU$6+gs1$TXDd+-+JZ$Ws0#{UCkkG%#VQ_`R-~xxi4Sux?9BSaa<fkcs-Z%t# z;})k|W=<-2K({CgRFrdh<|d{?1)@R8F$P3{YE8(XGpGzM0*x9K<$xqWNwX*)#6lZ2 z1C2Qpfe27@vluiZ3LAfDV1SO2tq9p6e?i3aqKM}e5zhwS8zL$bT(5|ztVp?F<$XcK z=c0(u6%n5X-y6cp6HKoNE3XK-VCi{5*z2OO*A-!}2A><85*?yF@(WZ}<X+&kxyWgA zh0~_N=>v-xXmkUU_{bmz8r^_P7_qR5eqewTd@QU|ATE^PV_}sAaiIhsJ4i8{5MgIk z2aSxN6X1{r`&v`@7F$YIVqSVaq*j!KaP&Y4v?w!4FR`>FLl4vqDlP)$tXslZ<cmOc z!7VoMd|Po5sIv*4fdkLp-4cUqC`#2sj8=h1v>?Or=?tLOy)S5T6*N*&1ezf#0u6A3 zhi<^GL>o5x#bJ}1pHiBWYFAXjz`y_+5G=N3WMKHf%*e=igF)f~D!Rd7b^#ULV9>jO zif%9%UcilRFgRYohHfzMH-O;>4sJ%S4-A+Ds1xxKB>n|NKvc+aGFpFNz$7ln>V5<X ze*qB?1yaI{q8}JAi3zGx^gn{czkmpc3OzSQM)eO2*h$cM?nkiP7chyb4xA<c&EBL? delta 1784 zcmZ4Fuv?CAIWI340|Ntt>84+4-#8}nNie>csBT`*$dJO2!j{7s#mU6r&XB_1!jQs| z%9sUK3R1p|nSo(7Gl&JkQQTlvoGlC~T&c`xay(!;?iPj=9y})SrZA*1<}l<kMlmun zq!_cL@aC}P@<s76GJv)7wJ@ac<I&Ea!Zw+Q(N3J{7Q1tPUP)qd$t^DD(&Cc*+|c6G zBEQM!*u^$4X5?Vxxy9j{Tac4qnVMQ8G<g%#4@REJtC>UXWEdD2isTp=82nbU6p4U1 zq98&HM1X{gq(LmODp?Q<6c9xq0)#(LwqtSR0!xCp$rA-dgG?A07^X9%GDI<^Fhntd z{lM75kiwM8oW%kPG7v@!D3%oFU<OT=TVe=@I~S!UmSpDVx#bt-PCmyf#%MM9DXTe0 z6nhF|FoP!3WGyyXFF#EVbQiONoG1<=Kz4!sRU`r8qWJ>sGZh8~1}O#xhGMnJv)GjD zJJ>+52<#h>yq_j3y734@(aci<*#ROXLFPFzFfcU0;RhxrR=p1ln8XEs`78V?A3-u- z7?^}H6cx!#KE^ILc`>8@W=RfC#`;^Vskw=nIk(tzQ;Ule(^IQBBlAm(6#No%Q$v37 zq~#ao>L%ysl@#UYXfog8F33qtPR+>ANl7ib#Zi=6SejXsnsSRZIVZ8WcqQX4*2I#M zqT(u^fQ<aSR0Y4%+@#c^Tdb}S3w)s#NFW<Jxt3EP2`z=NgZvE+Z*VAs^2IIAkkpD2 z&%A=tl3QG0^B`;vkZ@vAYGM&6%+Zq-D8P#}7#JAjC%@oaqlbuuB6*M%Xu+)p5(5z+ zZN)Z|7xI{iGjOnSeE<=V7zD{`G8PF<KFux(3PN>0|GcF9#G;hUymYtxqTFOqI)q_R z;svokvoKDM=R3^EHTfaG^5h(TQJxgWIc!l}DLlapn!J+>1;pyvZgHh$78RGo=OyN* z-r~$jgffe?85kIDaiyddBo>wArskF0;wmmlEGmglNi0dd#hI0#6kn2Al9O7b%fP@; z#pMPv0~~dlOhpDD@92RDLy#n=PhxQiSgwi}9DoXrDJey%#l^R{Tqf@k<gCBN0x}e; z@fJ%-WkG5cr&oTGLI}tPKTU4*bSnfh8#S7WOhIC1AV+h$B$lLtBMEoZSTis%fLvaD zmVrSAp0pbnZU{(pu-*`iy8uQVY!4>S6gHdeE-W*7rm*zn^TN`Tb%dq-KJc;&bA4c7 z7v}0<2SG>_fg;ZjYy4V*+y)|aKnw*C0ZtJhAx(kFqH>Wzw>UsyP?8CX1mFCW)ErQx zf(xc1P(CaI#eWgl-yltB$?X@1O>TZlX-=wLkv9Va10yKYT2H<!=b)&5fdLD;!NA`D zh99^l$H?o{Gc)RaV8A3U$m)Is34Z|*5CvSEj9ecWFo_AOQ}jQA#J_+Dhzc<VM#&2d o63FNVgUkg~^nrz&(VXi812@QA6k<Z?l=zPz@h>0(O$9i_0VJ)G<p2Nx diff --git a/postgresTest/PROJECT1/__pycache__/models.cpython-311.pyc b/postgresTest/PROJECT1/__pycache__/models.cpython-311.pyc index 2adcd25c545d82e61e2acce51c02a32f5d154f82..2198e6f579183f0d627e8ea744b59016fba39080 100644 GIT binary patch literal 4968 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 UdU8H8@G?q%0TCZi32;dT0IMXT$^ZZW delta 1594 zcmaE%)+@!goR^o2fq{X+d-Ja}OSXx85{x@0s;k#CGB7c?Go-MzFr=`iGH0=Ylz{Lu zW(J1U%pevBN3nxdv9&Oyu&1)3$#H<?I9eD|IPsXk30B3`!jQs^q)LMU%`mPMo?r$| z-j^U-H5qSl6sMMyWagz8PkbvSkqi=qVVK)K-(i^S$e19shGiKe1H)=Yn0yq+WJM-L zc1|XSROT$M$@To=jNBj*Q=Syo7KSL^6t-XnP4-(HuDJy{`IV`uFH;y87*;ag;>t~| zh|fvQOE1X?(PX^ER+^VtSem+d7ppNNBj4nAY{rayla<(2>sc5W7;bSoXCxN6Wv1q& z6!9@IFck5F1i4&u6EkzbqPJL6LF^&{kT|DHVo54Qn5(!Xv8W_IC9x#+7H3v|QhZ5f zNlt2!2*?QxMWP_1gh2#5i~z+;@j?a$h6X5{Je|YL^#YI9MINmyJX#H|Hv|<Yh+Pp> zToHUh(D0(5;T1u{1}~W4MM32&g31kEHv|+Wuw4;QSmAs@z~G{Q!4(062G7Y;x#YRP zR)TCxo+v0f`7+nWdJyL&$U#MF3=9mK%tfHobBjGWBR?}awfGi$N@`kSX-<isCVP<> z$d%$CLIUJZo*;i8*LY_Se@|!E;37~s6-k1`S&H&=Qj6q4>cG~4eW(cHf(Ri728Ln- zxDO{Y^Jqg{1(F22%9rPy83#x?C)l)t%;e$_P3Bvir3E?pi7D|V`L|e;auV~hZ?WW+ z=HzHH6@g4EGGt(2n9M1lH94M_r(O_b2`Gsu6oG9A`LBxGD?dpuKEAl5C_Y}9fq~&O z$fpeqH~58nDlc$IfTP1tlON5S2#*z+g51O9nVXmnjb7%=-1J+VA*mH5kmzPfNi9yk z#p5ZISCX2Z3P~`xSPP0WlT#;u;1!hvIRialbU{7^5i*mN`2xjw<U8E1@W?Mn*&uR( z$Lu1H*%cnM2G_}5d<Kf(zyztpo<FvM@`o)W^W=I)g~{#w{OlayEWruN5|b<V`At(; z*07@G9i9|6a2{a~X3*rg#qOM+SCW`qQUnkEm;95z^4r%NgWPBWBCrN5KU5zqaP>ec z%|Ham$$pxA1cH>cAR|97wMYu2LmEU_f&!X7H?_DpF+KGbuPrD;g=FSJL!B$RC^fMp zH6=c=1e}x5L(~Ce1c*=vrGlo(8hpx1JTjnQm07`bfk*oykM<QF?FQEyJhC7`*^4~# zS9s(nmkT;-gWOvL((0$leTzFKD={xUUoSa7FRchv4Bg^{ilihJu}r=ws1VBvaww~B zeoAUi5hx=Sff8{MD2~9Upt<Z9hfQvNN@-52U6Bt10|O|17Be$4FnnNUWMsU-pl|^d zO^y>%G5f&A$>_=WfdM<&QPxxQ5iIuwOhVO3Oui^&$S5+ISy+2Aldz;>T2IbL1`bBa MFCgLrDgjRR0A=WE@Bjb+ diff --git a/postgresTest/PROJECT1/__pycache__/views.cpython-311.pyc b/postgresTest/PROJECT1/__pycache__/views.cpython-311.pyc index c994f8664d23059ce276573f94aac5f6c7c4e9c5..2a4904c7dfe3350cf6b9330d4cfba15495488931 100644 GIT binary patch delta 4437 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 Xz<@-`F)^BdV1N>nU&v~)fPx1AN?!MX delta 3237 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 diff --git a/postgresTest/PROJECT1/forms.py b/postgresTest/PROJECT1/forms.py index 132bf80d..fc1a406b 100644 --- a/postgresTest/PROJECT1/forms.py +++ b/postgresTest/PROJECT1/forms.py @@ -1,12 +1,12 @@ from django import forms from django.contrib.auth.forms import UserCreationForm from django.contrib.auth import get_user_model -from .models import Contact, CustomUser +from .models import Contact, CustomUser, Employee +from django.core.validators import RegexValidator, EmailValidator import datetime - - +# RoleAssignmentForm for assigning roles class RoleAssignmentForm(forms.ModelForm): class Meta: model = CustomUser @@ -21,12 +21,20 @@ class RoleAssignmentForm(forms.ModelForm): } - +# CustomUserCreationForm for creating users with role and validation class CustomUserCreationForm(UserCreationForm): + email = forms.EmailField( + required=True, + widget=forms.EmailInput(attrs={'class': 'form-control', 'placeholder': 'Email'}), + validators=[EmailValidator(message="Enter a valid email address.")] + ) + class Meta(UserCreationForm.Meta): model = get_user_model() - fields = UserCreationForm.Meta.fields + fields = UserCreationForm.Meta.fields + ('email',) # Ensure email is included in the form + +# ContactForm with custom validation and widgets for collecting contact info class ContactForm(forms.ModelForm): class Meta: model = Contact @@ -38,18 +46,86 @@ class ContactForm(forms.ModelForm): 'message': forms.Textarea(attrs={'placeholder': 'Message', 'required': True, 'class': 'form-control message-box'}), } -from django import forms -from .models import Employee + # Additional validation for phone number to ensure proper format + def clean_phone(self): + phone = self.cleaned_data.get('phone') + phone_validator = RegexValidator( + regex=r'^\+?1?\d{9,15}$', + message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed." + ) + phone_validator(phone) + return phone + +# OnboardingForm with custom widgets and validation for employee onboarding class OnboardingForm(forms.ModelForm): + # Adding file fields for Police Report, ID card images (front and back), and CV + police_report = forms.FileField(required=True, label="Police Report") + id_card_front = forms.ImageField(required=True, label="ID Card (Front)") + id_card_back = forms.ImageField(required=True, label="ID Card (Back)") + cv = forms.FileField(required=True, label="CV (Resume)") + class Meta: model = Employee - fields = ['first_name', 'last_name', 'email', 'department', 'start_date', 'job_title'] + fields = [ + 'first_name', 'last_name', 'email', 'phone', 'address', + 'department', 'job_title', 'start_date', 'date_of_birth', + 'id_card_number', 'emergency_contact_name', 'emergency_contact_phone', + 'banking_information', 'police_report', 'id_card_front', 'id_card_back', 'cv' + ] widgets = { 'first_name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'First Name'}), 'last_name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Last Name'}), 'email': forms.EmailInput(attrs={'class': 'form-control', 'placeholder': 'Email Address'}), + 'phone': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Phone Number'}), + 'address': forms.Textarea(attrs={'class': 'form-control', 'placeholder': 'Residential Address'}), 'department': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Department'}), - 'start_date': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}), 'job_title': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Job Title'}), + 'start_date': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}), + 'date_of_birth': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}), + 'id_card_number': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'ID Card Number'}), + 'emergency_contact_name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Emergency Contact Name'}), + 'emergency_contact_phone': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Emergency Contact Phone'}), + 'banking_information': forms.Textarea(attrs={'class': 'form-control', 'placeholder': 'Banking Information (optional)'}), } + + # Additional validation for email + def clean_email(self): + email = self.cleaned_data.get('email') + email_validator = EmailValidator(message="Enter a valid email address.") + email_validator(email) + return email + + # Additional validation for start date + def clean_start_date(self): + start_date = self.cleaned_data.get('start_date') + if start_date > datetime.date.today(): + raise forms.ValidationError("Start date cannot be in the future.") + return start_date + + # Additional validation for date of birth + def clean_date_of_birth(self): + date_of_birth = self.cleaned_data.get('date_of_birth') + if date_of_birth >= datetime.date.today(): + raise forms.ValidationError("Date of birth must be in the past.") + return date_of_birth + + # Validation for phone number + def clean_phone(self): + phone = self.cleaned_data.get('phone') + phone_validator = RegexValidator( + regex=r'^\+?1?\d{9,15}$', + message="Enter a valid phone number in the format: '+999999999'. Up to 15 digits allowed." + ) + phone_validator(phone) + return phone + + # Validation for emergency contact phone number + def clean_emergency_contact_phone(self): + emergency_contact_phone = self.cleaned_data.get('emergency_contact_phone') + phone_validator = RegexValidator( + regex=r'^\+?1?\d{9,15}$', + message="Enter a valid emergency contact phone number in the format: '+999999999'. Up to 15 digits allowed." + ) + phone_validator(emergency_contact_phone) + return emergency_contact_phone diff --git a/postgresTest/PROJECT1/migrations/0022_rename_price_job_salary_employee_id_card_number_and_more.py b/postgresTest/PROJECT1/migrations/0022_rename_price_job_salary_employee_id_card_number_and_more.py new file mode 100644 index 00000000..f216b97d --- /dev/null +++ b/postgresTest/PROJECT1/migrations/0022_rename_price_job_salary_employee_id_card_number_and_more.py @@ -0,0 +1,40 @@ +# Generated by Django 5.0.6 on 2024-10-09 09:54 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('PROJECT1', '0021_employee_delete_account_remove_cartitem_job_and_more'), + ] + + operations = [ + migrations.RenameField( + model_name='job', + old_name='price', + new_name='salary', + ), + migrations.AddField( + model_name='employee', + name='id_card_number', + field=models.CharField(default=12345, max_length=20, validators=[django.core.validators.RegexValidator(message='Enter a valid ID card number.', regex='^\\d{5,20}$')]), + preserve_default=False, + ), + migrations.AlterField( + model_name='contact', + name='email', + field=models.EmailField(max_length=254, validators=[django.core.validators.EmailValidator()]), + ), + migrations.AlterField( + model_name='contact', + name='phone', + field=models.CharField(max_length=15, validators=[django.core.validators.RegexValidator(message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.", regex='^\\+?1?\\d{9,15}$')]), + ), + migrations.AlterField( + model_name='employee', + name='email', + field=models.EmailField(max_length=254, unique=True, validators=[django.core.validators.EmailValidator()]), + ), + ] diff --git a/postgresTest/PROJECT1/migrations/__pycache__/0022_rename_price_job_salary_employee_id_card_number_and_more.cpython-311.pyc b/postgresTest/PROJECT1/migrations/__pycache__/0022_rename_price_job_salary_employee_id_card_number_and_more.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f9e77b4991a5da18652fabc6ef189bc350d0d0e5 GIT binary patch literal 2302 zcmZ3^%ge>Uz`$@ch%H@&je+4Yhy%l{P{wB$1_p-d3@HpLj5!QZj42E$OgT)s%u&p_ zEKw|s3``8}3@OYl3@I$B%vmr!49l1q7*;bwO<;&(O<@dX&}4lH67bVxy2X{7nO>Aw zl9``Ze2XnNKP5G%I2j}d!+cQ2XE!F0-Kk)EqnJ_{(;1_fnHW-85H_VSr7)+ktYJm9 z5v+y{Y6?RNTM9c9Ln?a~2V8_Bg)@~i3+#K4SQa;k1mOidAQBy?aHVjs;aSGSz_6ML zCYR2*h8NY=6uve5%UBo~R<pp=fZf3h<E03s2!h=K^B+Ts5Dr)H!}K82%NQ6KR>K9- z8P^D-x@e6Es(UbO7X{mn2n8`5wqp+i@e~OxVL+N2*f2vNMG}WAhzkQLR6nDKK{{)c zK#FuQgQm<aPG4B6(`35E5fJ3><?0+_c+1kjz{oH@HMbxqzcMv7J|#6LwInq@F*!NE zG_NGSC^a{~EHyqkv8W`oBsDiaD?cedF)t-PH@_(L7IRj9(k<44qRiyfTWrONIf+G; zn#{Mjz$rRDFEKau7Ds+g3Y3+XS`KBw?7GF5nF2C7B|fh-Hz~C!)6#%};iU)z14EUp zYhFoekwT(ESz=CRih`$$LULkJiULHPUKLkdOiHz>j*&sFiYC)7_T1Fs;>7gSTdYN? z>8TZ(%(vK6QqvMkb4qS;<tA3d=cMMPmt@@H0-Kdsl3!HprpZzSisV}?U{|uHWv1q& z+!81#N-a(;Dgy-qL_2$OeqKppa>*^$)ZE0(oR|L?7#K8}ibNS07>dL|Y-X@AMdBa< z2?hp+TdV~c`FW`?L2*|V6aZpF9j%aCT3n)#l&X*l@>yz%LS~*qNk*zdT7FS(Vu_W4 zy0#?@sOu?&7ATbDD;Sz8q-3UNmJ}-_=H%p;r>5vt@yEqz+Z)=)q*Pn#7@F3qglIB@ zopXz=G%vHTG!^VDKTW|~9P!}Lj*q{^6(66QpHiBW8Xtd)CqBNgG%*L{YY;CbwIDSw zB{eTOGqtz~R9@ZU4oU?{x`6|P!!acV%qjxq=v$o58Hq(;{w=nYti-(Z{97!^`9%;r zZ}A0z0zV8CU!X9)#pRe&k_uJM<q8Tuh*mx@8%bS$K`OK`T*>eml)ZnQakh#HElw>e z29q%^sm0kP`2{gynK?O$&iOexsp+XP!Ii}&sksU+sb#4-`31SDc_j*=Zq9Dz!Mer< zx<)aM#l@NFd0=6W5MLh!=lqn^7{{E<c)!G?jKsWnBVz+ILt{hJn1cM`lJug~;*iwh zk{DQ~h(Q$4F$M-kM)5`9P>Ba8b#NYlq;^EMK~2f<ETUIXSp+JF!2~-414Ho^Mh1ok zIQ+oIz!}8&ftg8!t-<F57Xzn!2iFx2xf|j#H$-J_h{}FoXW``f$iTwM^#w$LRLFo- zNZ$}wydkJ~Lr7_Y+7%(C6{b6aPK2F_zT%sF-M8qHZ_x(^h8o6brVk7Z$xH=I7krC8 zGBEft7BYQ-P#+i=d>M;C(!#||9~l^gi$OBN#Y{J3l|FE?f~;f(S;@-D^?`?hQx0UM z><w{+8-fxygp@&6Dz7L$z;=ZDibL3Shtx|BsTUp6uQ;S%u+O+4lzCAo^NLU=7N?_{ z19f`Rj<h}5SL{Nr+a+JJOa8#Xkjv=E{DFbNlR1X@f?e`Q1_t|B<}YCK0|SFy97s+$ zo*Croc#yboJTo4v6j7YK!vrOiF8Y>S@h!RFQ+h$D?4nTF6`?Y8lXRtp*c!Y*ut*=2 z$3bza$#zQ&lKk~Rsb3FKtQ4t(iU3ZiWJ(e^OM&waIR1<DKt_PgF<@X|_{CuZ$(MFT z#taM$jG)w!#K6Gtftit!@dFzJqud1sSqQqppm6~k`oN~h$o7E&lbFDDML^{vNa72K JKvM$t3jkrJPvigq literal 0 HcmV?d00001 diff --git a/postgresTest/PROJECT1/models.py b/postgresTest/PROJECT1/models.py index e47e624a..bc825fb7 100644 --- a/postgresTest/PROJECT1/models.py +++ b/postgresTest/PROJECT1/models.py @@ -1,19 +1,46 @@ -from django.conf import settings from django.db import models from django.contrib.auth.models import AbstractUser +from django.core.validators import EmailValidator, RegexValidator class Employee(models.Model): first_name = models.CharField(max_length=100) last_name = models.CharField(max_length=100) - email = models.EmailField(unique=True) + email = models.EmailField(unique=True, validators=[EmailValidator()]) + phone = models.CharField( + max_length=15, + validators=[ + RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.") + ] + ) + address = models.TextField() # Residential address department = models.CharField(max_length=100) - start_date = models.DateField() job_title = models.CharField(max_length=100) + start_date = models.DateField() + date_of_birth = models.DateField() + id_card_number = models.CharField( + max_length=20, + validators=[RegexValidator(regex=r'^\d{5,20}$', message='Enter a valid ID card number.')] + ) + emergency_contact_name = models.CharField(max_length=100) + emergency_contact_phone = models.CharField( + max_length=15, + validators=[ + RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Emergency contact phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.") + ] + ) + banking_information = models.TextField(blank=True, null=True) # Optional for salary deposits + + # New file upload fields + police_report = models.FileField(upload_to='documents/police_reports/', blank=True, null=True) + id_card_front = models.ImageField(upload_to='documents/id_cards/', blank=True, null=True) + id_card_back = models.ImageField(upload_to='documents/id_cards/', blank=True, null=True) + cv = models.FileField(upload_to='documents/cv/', blank=True, null=True) def __str__(self): return f"{self.first_name} {self.last_name} - {self.department}" - + + # The CustomUser model class CustomUser(AbstractUser): ROLE_CHOICES = ( @@ -24,22 +51,29 @@ class CustomUser(AbstractUser): ) role = models.CharField(max_length=20, choices=ROLE_CHOICES, default='EMPLOYEE') -# The Job model + +# The Job model (with 'salary' field) class Job(models.Model): name = models.CharField(max_length=100) - img = models.ImageField(upload_to='pics', blank=True, null=True) # Optional if needed + img = models.ImageField(upload_to='pics', blank=True, null=True) desc = models.TextField() - price = models.IntegerField(blank=True, null=True) # Optional if needed + salary = models.IntegerField(blank=True, null=True) form_url = models.URLField(blank=True, null=True) def __str__(self): return self.name + # The Contact model class Contact(models.Model): name = models.CharField(max_length=100) - phone = models.CharField(max_length=15) - email = models.EmailField() + phone = models.CharField( + max_length=15, + validators=[ + RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.") + ] + ) + email = models.EmailField(validators=[EmailValidator()]) message = models.TextField() created_at = models.DateTimeField(auto_now_add=True) diff --git a/postgresTest/PROJECT1/templates/base.html b/postgresTest/PROJECT1/templates/base.html index 5aaeaf25..08784b21 100644 --- a/postgresTest/PROJECT1/templates/base.html +++ b/postgresTest/PROJECT1/templates/base.html @@ -14,7 +14,7 @@ <link rel="icon" href="{% static 'images/fevicon/fevicon.png' %}" type="image/gif" /> <!-- Title --> - <title>{% block title %}HR System{% endblock title %}</title> + <title>{% block title %}HR System Onboarding{% endblock %}</title> <!-- Stylesheets --> <link rel="stylesheet" type="text/css" href="{% static 'css/bootstrap.css' %}" /> @@ -22,7 +22,6 @@ <link href="{% static 'css/font-awesome.min.css' %}" rel="stylesheet" /> <link href="{% static 'css/style.css' %}" rel="stylesheet" /> <link href="{% static 'css/responsive.css' %}" rel="stylesheet" /> - <link href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.10.2/fullcalendar.min.css" rel="stylesheet" /> <style> /* Custom CSS for the toggling effect */ @@ -49,7 +48,9 @@ margin-left: 250px; width: calc(100% - 250px); transition: all 0.3s; - padding-top: 20px; + padding: 20px; + background-color: #f7f7f7; + min-height: 100vh; } .toggled .sidebar-wrapper { @@ -76,6 +77,44 @@ margin-right: 10px; } + /* Onboarding-specific styles */ + .onboarding-header { + font-size: 28px; + font-weight: 700; + color: #333; + text-align: center; + margin-bottom: 20px; + } + + .onboarding-step { + background-color: #fff; + padding: 15px; + border-radius: 8px; + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); + margin-bottom: 20px; + } + + .onboarding-step h4 { + font-size: 22px; + color: #007bff; + } + + .onboarding-step p { + font-size: 16px; + color: #555; + } + + .btn-next { + display: block; + width: 100%; + text-align: center; + background-color: #007bff; + color: white; + padding: 10px; + border-radius: 5px; + margin-top: 20px; + } + /* Custom CSS for the login icon in the top right corner */ .login-icon { position: absolute; @@ -93,7 +132,7 @@ <div class="container-fluid"> <nav class="navbar navbar-expand-lg custom_nav-container"> <a class="navbar-brand" href="{% url 'home' %}"> - <span>HR System</span> + <span>HR Onboarding</span> </a> <!-- Login Icon in the top right corner --> <a href="{% url 'login' %}" class="login-icon"> @@ -111,69 +150,65 @@ <a href="{% url 'dashboard' %}" class="list-group-item list-group-item-action bg-light"> <i class="fa fa-tachometer" aria-hidden="true"></i> Dashboard </a> - <a href="{% url 'redirect_to_current_month' %}" class="list-group-item list-group-item-action bg-light"> - <i class="fa fa-calendar" aria-hidden="true"></i> Calendar - </a> - <a href="{% url 'job' %}" class="list-group-item list-group-item-action bg-light"> - <i class="fa fa-briefcase" aria-hidden="true"></i> Jobs + + <!-- Links specifically for onboarding --> + <a href="{% url 'onboard_employee' %}" class="list-group-item list-group-item-action bg-light"> + <i class="fa fa-user-plus" aria-hidden="true"></i> Onboard Employee </a> - <a href="{% url 'leave' %}" class="list-group-item list-group-item-action bg-light"> - <i class="fa fa-plane" aria-hidden="true"></i> Leave + + <a href="{% url 'employee_list' %}" class="list-group-item list-group-item-action bg-light"> + <i class="fa fa-users" aria-hidden="true"></i> View Employees </a> - - <!-- Add this for admin/HR users --> - {% if request.user.is_staff %} - <a href="{% url 'all_leave_forms' %}" class="list-group-item list-group-item-action bg-light"> - <i class="fa fa-file-alt" aria-hidden="true"></i> All Leave Forms - </a> - {% endif %} - - <a href="{% url 'meeting_list' %}" class="list-group-item list-group-item-action bg-light"> - <i class="fa fa-calendar-check-o" aria-hidden="true"></i> Scheduled Meetings - </a> - + + <!-- Removed the Meetings link --> + <a href="#" class="list-group-item list-group-item-action bg-light"> <i class="fa fa-cogs" aria-hidden="true"></i> Settings </a> + <a href="#" class="list-group-item list-group-item-action bg-light"> <i class="fa fa-file-text" aria-hidden="true"></i> Reports </a> - <a href="{% url 'inventory' %}" class="list-group-item list-group-item-action bg-light"> - <i class="fa fa-archive" aria-hidden="true"></i> Inventory - </a> - <a href="{% url 'employee' %}" class="list-group-item list-group-item-action bg-light"> - <i class="fa fa-user" aria-hidden="true"></i> Employee - </a> </div> -</div> + </div> + - <div class="page-content-wrapper" id="page-content-wrapper"> + <!-- Main content area --> + <div class="page-content-wrapper" id="page-content-wrapper"> <i class="fa fa-bars toggle-icon" id="menu-toggle"></i> <div class="container-fluid"> - {% block content %} - <!-- Your content goes here --> - {% endblock content %} + <div class="onboarding-header"> + <!-- Remove this second block title --> + <h1>Welcome to HR Onboarding</h1> + </div> + + <div class="onboarding-content"> + {% block content %} + <!-- Content such as onboarding steps, forms, etc. will be injected here --> + <div class="onboarding-step"> + <h4>Step 1: Complete Your Profile</h4> + <p>Please provide all the necessary personal information to complete your profile.</p> + </div> + + <div class="onboarding-step"> + <h4>Step 2: Review Company Policies</h4> + <p>Make sure to go through the company policies to understand our code of conduct.</p> + </div> + + <a href="#" class="btn-next">Proceed to the Next Step</a> + {% endblock content %} + </div> </div> - </div> </div> <!-- jQuery --> <script type="text/javascript" src="{% static 'js/jquery-3.4.1.min.js' %}"></script> <!-- popper js --> - <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script> + <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"></script> <!-- bootstrap js --> <script type="text/javascript" src="{% static 'js/bootstrap.js' %}"></script> <!-- custom js --> <script type="text/javascript" src="{% static 'js/custom.js' %}"></script> - <!-- fullcalendar js --> - <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script> - <script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.10.2/fullcalendar.min.js"></script> - <!-- Google Platform API --> -<script src="https://apis.google.com/js/platform.js" async defer></script> - -<!-- Your Custom JS --> -<script type="text/javascript" src="{% static 'js/custom.js' %}"></script> - <script> // Toggle sidebar @@ -181,13 +216,6 @@ e.preventDefault(); $("#sidebar-wrapper").toggleClass("collapsed"); }); - - // Initialize calendar - $(document).ready(function() { - $('#calendar').fullCalendar({ - // Add your calendar options here - }); - }); </script> </body> </html> diff --git a/postgresTest/PROJECT1/templates/index.html b/postgresTest/PROJECT1/templates/index.html index bf52bca9..670681bd 100644 --- a/postgresTest/PROJECT1/templates/index.html +++ b/postgresTest/PROJECT1/templates/index.html @@ -3,7 +3,7 @@ {% load static %} {% block content %} -<!-- Carousel section --> +<!-- Carousel Section (highlighting onboarding-specific content) --> <section class="slider_section"> <div id="customCarousel1" class="carousel slide" data-ride="carousel"> <div class="carousel-inner"> @@ -12,9 +12,9 @@ <div class="carousel-item active"> <img src="{% static 'images/banner1.png' %}" alt="Admin Positions" class="d-block w-100"> <div class="carousel-caption d-none d-md-block"> - <h5 class="text-dark-gray">Admin Positions</h5> - <p class="text-dark-gray">Get a 50% discount on all self-sales.</p> - <a href="{% url 'job' %}" class="btn btn-primary"style="background-color: #333; border-color: #333;">Apply Now</a> + <h5 class="text-dark-gray">Admin Positions Available</h5> + <p class="text-dark-gray">Join the HR admin team and get exclusive career perks.</p> + <a href="#" class="btn btn-primary" style="background-color: #007bff; border-color: #007bff;">Apply Now</a> </div> </div> @@ -22,19 +22,19 @@ <div class="carousel-item"> <img src="{% static 'images/banner2.png' %}" alt="Procurement Officer" class="d-block w-100"> <div class="carousel-caption d-none d-md-block"> - <h5 class="text-dark-gray">First-class Procurement Officer</h5> - <p class="text-dark-gray">Get a 10% pay increase now!</p> - <a href="{% url 'job' %}" class="btn btn-primary"style="background-color: #333; border-color: #333;">Apply Now</a> + <h5 class="text-dark-gray">Procurement Officer Roles</h5> + <p class="text-dark-gray">Looking for experienced procurement officers with leadership potential.</p> + <a href="#" class="btn btn-primary" style="background-color: #007bff; border-color: #007bff;">Apply Now</a> </div> </div> <!-- Slide 3: Product Tester --> <div class="carousel-item"> - <img src="{% static 'images/banne3.png' %}" alt="Product Tester" class="d-block w-100"> + <img src="{% static 'images/banner3.png' %}" alt="Product Tester" class="d-block w-100"> <div class="carousel-caption d-none d-md-block"> - <h5 class="text-dark-gray">Product Tester</h5> - <p class="text-dark-gray">Mentorship positions available.</p> - <a href="{% url 'job' %}" class="btn btn-primary"style="background-color: #333; border-color: #333;">Apply Now</a> + <h5 class="text-dark-gray">Become a Product Tester</h5> + <p class="text-dark-gray">Get hands-on with our latest products as part of the product testing team.</p> + <a href="#" class="btn btn-primary" style="background-color: #007bff; border-color: #007bff;">Apply Now</a> </div> </div> @@ -60,19 +60,20 @@ </section> <!-- End Carousel Section --> -<!-- Soapbox Section --> +<!-- Contact Section (Soapbox Form for Feedback) --> <section class="contact_section layout_padding"> <div class="container"> - <!-- Soapbox Heading --> + <!-- Heading for the Soapbox Form --> <div class="heading_container"> - <h2>Soapbox Us</h2> + <h2>Get in Touch with Us</h2> + <p>We're here to assist you. Drop us your questions or feedback.</p> </div> <!-- Soapbox Form Row --> <div class="row"> <div class="col-md-6"> <div class="form_container"> - <form method="post" action="{% url 'contact' %}"> + <form method="post" action="#"> {% csrf_token %} {% for field in form %} <div class="form-group"> @@ -89,13 +90,28 @@ </div> {% endfor %} <div class="btn_box"> - <button type="submit" class="btn btn-primary" style="background-color: #333; border-color: #333;">SEND</button> + <button type="submit" class="btn btn-primary" style="background-color: #007bff; border-color: #007bff;">Submit</button> </div> </form> </div> </div> + + <!-- Adding a right-side section for onboarding --> + <div class="col-md-6"> + <div class="onboarding-info"> + <h4>How We Can Help</h4> + <p>Our onboarding process is designed to be smooth and efficient, allowing you to get started with minimal hassle.</p> + <ul> + <li>Dedicated HR Support</li> + <li>Step-by-step onboarding guide</li> + <li>24/7 assistance for all inquiries</li> + </ul> + <a href="#" class="btn btn-outline-primary" style="margin-top: 20px;">Learn More</a> + </div> + </div> </div> </div> </section> +<!-- End Contact Section --> {% endblock content %} diff --git a/postgresTest/PROJECT1/templates/onboard_employee.html b/postgresTest/PROJECT1/templates/onboard_employee.html index 1921e8c7..cd7779ce 100644 --- a/postgresTest/PROJECT1/templates/onboard_employee.html +++ b/postgresTest/PROJECT1/templates/onboard_employee.html @@ -9,9 +9,96 @@ Onboard New Employee {% block content %} <h1>Onboard New Employee</h1> -<form method="POST"> +<!-- Make sure to add enctype for file uploads --> +<form method="POST" enctype="multipart/form-data"> {% csrf_token %} - {{ form.as_p }} <!-- This renders all form fields as paragraphs --> + + <div class="form-group"> + {{ form.first_name.label_tag }} + {{ form.first_name }} + </div> + + <div class="form-group"> + {{ form.last_name.label_tag }} + {{ form.last_name }} + </div> + + <div class="form-group"> + {{ form.email.label_tag }} + {{ form.email }} + </div> + + <div class="form-group"> + {{ form.phone.label_tag }} + {{ form.phone }} + </div> + + <div class="form-group"> + {{ form.address.label_tag }} + {{ form.address }} + </div> + + <div class="form-group"> + {{ form.department.label_tag }} + {{ form.department }} + </div> + + <div class="form-group"> + {{ form.job_title.label_tag }} + {{ form.job_title }} + </div> + + <div class="form-group"> + {{ form.start_date.label_tag }} + {{ form.start_date }} + </div> + + <div class="form-group"> + {{ form.date_of_birth.label_tag }} + {{ form.date_of_birth }} + </div> + + <div class="form-group"> + {{ form.id_card_number.label_tag }} + {{ form.id_card_number }} + </div> + + <div class="form-group"> + {{ form.emergency_contact_name.label_tag }} + {{ form.emergency_contact_name }} + </div> + + <div class="form-group"> + {{ form.emergency_contact_phone.label_tag }} + {{ form.emergency_contact_phone }} + </div> + + <div class="form-group"> + {{ form.banking_information.label_tag }} + {{ form.banking_information }} + </div> + + <!-- File uploads for Police Report, ID card images (front and back), and CV --> + <div class="form-group"> + {{ form.police_report.label_tag }} + {{ form.police_report }} + </div> + + <div class="form-group"> + {{ form.id_card_front.label_tag }} + {{ form.id_card_front }} + </div> + + <div class="form-group"> + {{ form.id_card_back.label_tag }} + {{ form.id_card_back }} + </div> + + <div class="form-group"> + {{ form.cv.label_tag }} + {{ form.cv }} + </div> + <button type="submit" class="btn btn-primary">Submit</button> </form> <!-- End of Onboard New Employee Section --> diff --git a/postgresTest/PROJECT1/views.py b/postgresTest/PROJECT1/views.py index 0cbc0ebf..7581dcbc 100644 --- a/postgresTest/PROJECT1/views.py +++ b/postgresTest/PROJECT1/views.py @@ -6,22 +6,36 @@ from .models import Job, CustomUser from .forms import CustomUserCreationForm, ContactForm, RoleAssignmentForm, OnboardingForm from django.contrib.auth.views import LoginView from django.contrib.auth.forms import UserChangeForm +from django.http import HttpResponseForbidden @login_required def dashboard(request): return render(request, 'dashboard.html') + @login_required def onboard_employee(request): - if request.method == 'POST': # This handles the form submission + # Ensure only staff can onboard employees + if not request.user.is_staff: + return HttpResponseForbidden("You don't have permission to onboard employees.") + + if request.method == 'POST': form = OnboardingForm(request.POST) + if form.is_valid(): - form.save() # This saves the form data to the database (Employee model) + employee = form.save() + + # Example: Logging action without exposing sensitive information + print(f"New employee onboarded: {employee.first_name} {employee.last_name}") + messages.success(request, 'Employee has been successfully onboarded.') return redirect('onboarding_success') + else: + messages.error(request, 'Please correct the errors below.') else: - form = OnboardingForm() # This displays an empty form for a GET request + form = OnboardingForm() + return render(request, 'onboard_employee.html', {'form': form}) @@ -32,14 +46,23 @@ def onboarding_success(request): @login_required def edit_role(request, user_id): + # Ensure only staff can edit roles user = get_object_or_404(CustomUser, pk=user_id) + + if not request.user.is_staff: + return HttpResponseForbidden("You don't have permission to edit roles.") + if request.method == 'POST': form = RoleAssignmentForm(request.POST, instance=user) if form.is_valid(): form.save() + messages.success(request, 'Role has been successfully updated.') return redirect('employee_list') # or the appropriate URL name + else: + messages.error(request, 'Please correct the errors below.') else: form = RoleAssignmentForm(instance=user) + return render(request, 'edit_role.html', {'form': form, 'user': user}) @@ -49,6 +72,10 @@ class CustomLoginView(LoginView): @login_required def employee_list(request): + # Staff members can view the employee list + if not request.user.is_staff: + return HttpResponseForbidden("You don't have permission to view this page.") + employees = CustomUser.objects.all().order_by('role') return render(request, 'employee.html', {'employees': employees}) @@ -64,6 +91,7 @@ def profile_edit_view(request): form = UserChangeForm(request.POST, instance=request.user) if form.is_valid(): form.save() + messages.success(request, 'Your profile has been updated.') return redirect('profile') else: form = UserChangeForm(instance=request.user) @@ -79,9 +107,10 @@ def register(request): form = CustomUserCreationForm(request.POST) if form.is_valid(): user = form.save() - username = form.cleaned_data.get('username') - messages.success(request, f'Account created for {username}!') + messages.success(request, f'Account created successfully!') return redirect('custom_login') + else: + messages.error(request, 'Please correct the errors below.') else: form = CustomUserCreationForm() return render(request, 'register.html', {'form': form}) @@ -99,17 +128,22 @@ def delete_account(request): request.user.delete() auth_logout(request) messages.success(request, 'Your account has been successfully deleted.') - return redirect('login') + return redirect('custom_login') def home(request): jobs = Job.objects.all() form = ContactForm() - context = { - 'jobs': jobs, - 'form': form, - } - return render(request, 'index.html', context) + + if request.method == 'POST': + form = ContactForm(request.POST) + if form.is_valid(): + form.save() + messages.success(request, 'Your message has been sent.') + else: + messages.error(request, 'Please correct the errors below.') + + return render(request, 'index.html', {'jobs': jobs, 'form': form}) def jobs(request): diff --git a/postgresTest/postgresTest/__pycache__/settings.cpython-311.pyc b/postgresTest/postgresTest/__pycache__/settings.cpython-311.pyc index 4b06af23f9a702b123867653db896b8bb70f8261..97d8a260ce94ce031ef32511349472b221183146 100644 GIT binary patch delta 113 zcmbQMut|Y$IWI340|Ns?br4(ndf|<H&zTu{H-BSRW)#0AoRXE8m!2P=TvS<5lAm6b zSddX!r8!xUU1YO9>rxgrc?JfCDi1LK9p`su#(>Gsc$)<IgqS`sz=#IE4=S50`4%v; J_%Sdr004#=AgKTV delta 89 zcmdm_Fjs+ZIWI340|Ns?@|;6yOd=cko-;G@Z2rcq%(z*PbvFx}90LPGmB(ZQR*}i) oxI{LKb3JBe^q>5jw@Hv!i0K0ZjA-EdptQM<Zvi8VF9QPu05#|rZU6uP diff --git a/postgresTest/postgresTest/settings.py b/postgresTest/postgresTest/settings.py index fafc284e..a0ec1b63 100644 --- a/postgresTest/postgresTest/settings.py +++ b/postgresTest/postgresTest/settings.py @@ -43,12 +43,13 @@ INSTALLED_APPS = [ "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", - 'PROJECT1.apps.Project1Config', # reg i - 'django.contrib.sites', # Added for allauth - 'allauth', # Added for allauth - 'allauth.account', # Added for allauth - 'allauth.socialaccount', # Added for allauth - 'allauth.socialaccount.providers.google', # Added for Google Sign-In + 'PROJECT1.apps.Project1Config', + 'django.contrib.sites', + 'allauth', + 'allauth.account', + 'allauth.socialaccount', + 'allauth.socialaccount.providers.google', + 'django_cryptography' ] # Authentication backends -- GitLab