From 407554791773e559b4eece23b84a37c99c2bd24c Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Fri, 6 Feb 2026 13:44:48 +0000 Subject: [PATCH] DN WH1.0.1 --- .../context_processors.cpython-311.pyc | Bin 1295 -> 1314 bytes core/__pycache__/forms.cpython-311.pyc | Bin 8395 -> 8788 bytes core/__pycache__/models.cpython-311.pyc | Bin 11113 -> 12758 bytes core/context_processors.py | 3 +- core/forms.py | 11 +- ...t_color_appsetting_font_family_and_more.py | 33 +++ .../0006_alter_appsetting_theme_color.py | 18 ++ ...tting_font_family_and_more.cpython-311.pyc | Bin 0 -> 1900 bytes ...ter_appsetting_theme_color.cpython-311.pyc | Bin 0 -> 1142 bytes core/models.py | 53 ++++- core/templates/base.html | 199 +++++++++++------- core/templates/core/settings.html | 76 +++++-- 12 files changed, 291 insertions(+), 102 deletions(-) create mode 100644 core/migrations/0005_appsetting_font_color_appsetting_font_family_and_more.py create mode 100644 core/migrations/0006_alter_appsetting_theme_color.py create mode 100644 core/migrations/__pycache__/0005_appsetting_font_color_appsetting_font_family_and_more.cpython-311.pyc create mode 100644 core/migrations/__pycache__/0006_alter_appsetting_theme_color.cpython-311.pyc diff --git a/core/__pycache__/context_processors.cpython-311.pyc b/core/__pycache__/context_processors.cpython-311.pyc index 0d9097d822cb4b4ce88bca0b65d51e2b49ef6114..67d9f7cebc3ad5f0f7072fced63aabf3cf71f3b8 100644 GIT binary patch delta 203 zcmeC@TExY>oR^o20SFpzv}P`t$eYW>4dgHb@#nCKEw7ns7$@g5W-@Y2zR9=}NH#MC z^YSDX6vP*&mXu`Xr5A6$%EZLTr2tgV3dF?=CO>2@V7?)tFgcJ#$y1n%hwTFcgkWX+ z3{=3N$yy`^q>5yK#4Wbm{FKz3;vyE1hysvU$xx&SV#@=GUmP|->C&83yCRjzdsxh6 Mgc*T`VG>{+0M(u__y7O^ delta 182 zcmZ3))z8JdoR^o20SHnrw`Mv`;vHZyLGhr#{3Wk*|ur7t#P>C$-E?u1+Is*)uws>b6 z0%|ZOCPZJ9yC!Hzd{mN+(ewr1HpVwiEC~;Fo_yW6Zrqs2llM%i-E=`>r}OpPd(XLZ z&Y5#hf0;PC5%|XM=NS4~D}1cAUHl=?#`muIQIwl=4lrj}lgWN<1xqnfhlC4G*u zmwo1nno^}?M$cf&x0Fen(vqCg^bL!%2c-qSp(*O3j3rx}XpZi13w6_S;>^0SNzHJo z-%xcmX<9DZVxPq&1#@Ffjf=Hp&mp0cFc+a#4sQJdll;WZC8@1Pfl4VZ47%R>CKQYxe4-<>&GofDdqtJAOvWo z5LrA7@+%Z^k;9!Zs5lH&hPweh00*EKAObD}s=|TL@eoBby^RC~ghP(qx5Y|o@Qa{T zWqAeW08Qk*nn|~D>E)2&xJI&w_Rb#UmCZs2zGZtAldG+G$z0 zgYw>xO|=x#f7j0p!?4U%603jEe@@ZF;DG>m6$W|9HBl;@SZ?4#D~no4Jjf$~Xu-ig zsD9d97Qh1Pa+-lEf1ou)|T zouy3Hq{k9!-C{MRbYO4O(WY-!)3ufM>#~_#!91C5?hru>-vw1JrkX0I5y|O@=&-}I zJXn1~a1|LOA+)&duCz`z1s-K{UkERt zt*0^pkF&eLJ0RIL47=fb0LT!Q0Uip=na-qDoQ3fcAPQIpECQg9fDUzH9Ynt*C3V>_ zlB%vtl8Ep}bk?BVzJVFXwo^Ko0q*6dL$9BtQ75~tZ(OsR2h@OF(RM{xPWZ>N({3A8 u^_yeQXey&*b@dwlgmkqfE?+>j)jo^Q=I=|7Vg5;Fu{-ymO+Zel&3^!=E2|>_ delta 1638 zcmb7^O-vg{6vsVgz1ZuR&lqD0#^xh*D+-jhQfVp@NFX5*Cc>d1r0L4o8`#$D!t7dA zI1~+2sfrZsrI$)QMrsd5NhGqTo+?GTkdG6+^t~}@r~^Xv+CR_C zzBluKZ{Eyqu(!)ho5&#K2Ep~RrCrds^}>Ob9{XWs{A zlze5zrv|s{hZYwzy5kt;+^EGDdd77ps|MhgievDO)ESB5l%B+`FYL4$hOZI%!7$Ht*La2V;OYJ^HT2;yyp$zd>LXuEH zNDk{JdLwF~QehS0wKQzNIj_)F4 z3;*2?td#P^SJEtdsQ2WIUeI%n7fu%!W_3PhE*72rH{vKx(+S6`9v-B6fYu{)z+m-` z>H$=J+TExgeXV@Xpy9fomulU)x~M<)lRxDxtsW|mMW%Oq#KMR1g%>)Rb@Wmg`xccV zs_GP)zY8~OfBN8nN*bXB31TnaqMq;=aeuB$_?t=g_Tejdc;C)hro*j5(iTbW=P`J8 zxGzHI1jGB794|m`v{9yj`8bS6yTZGUA*@7u*f89Q##svPMO)Z8_$%7VPJrAn5HG9l zNt%H$=uS6$#!BTq>E4TNGM0f`@mNY^({JQUC-gj;E{D$<1!F!roON>Zya67?Q>v(( zX?*D^XLU#CS#vIHj;a+xtrz6_Qqkago?md=n_B$rG7L3O)zdNb8(Z0x474rX z4>Qyf^-Ih0PYATr{4ybk@FdeRb-qOXS;7fIj_@ggZWyvbwIsod>?q9Xg@UH3jDLxv zHuL%Fe8)>l=gEz5(cMU#*~#uaq>>YZ;#v`fAZnb-!jmW#u^Ymv>?Ya{ezaiaiv@j< je*<@tm%0^(xAN<_K6OKTO5-nHy=-*fPrbn;Dz|?CnL|nI diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index 8b0ae5eb590e0fe00b6423ac7b18b601f0e37ee6..e699863f29d84a44f9d3532b1b3a5b7387fb5dc0 100644 GIT binary patch delta 4819 zcma)9Z%iD=72mzTaB#pK9EJer1v{9FV+R91AaU#%0yf6{iSH6S)X`_l{PfgR+ETINz^J*(&S52wOB$G+O}!FRrwGJ%aN+)L)7-g`6i_PzI;89smDZ^??^`29W(o{#^2QAzK7yF%kX` zh-Aj}jU{DK6Z+J=jN(~6pG?ZSZu$o@G7(itI7Vby1C>Y7Bqg0S%THxzL{%8ilbnh} zJXs=YY1#D0@|rFi!Wip zaR#)r?#HGSLpIC$Rdnk#b|P+2xQ8@DCT0bD32h@;NhVqZ6yEV{E~jX^8C+`!ZG%LS zHA$U8wdYiJGHYbb3i~azv58UR8_8;hE)yaeW=)~pB^pB8fGVd&%>W~_YFrg(QldhH zdlfwgZCIutfvH4YSCSF>q~l>eL_c-3%vM9f$PR=MfaM;@h>A+Q&^CRiMWTs9T+WCK zE`o-ZH#wD6Al#&;FyiwLY*jG(6SAi0!XSA0Ih(+{t3&GS?&>kC?3qv_+;4~(G2+As zsY-fw%COugG29UcDZ?dPYhib%(OJuX3}2Zn$xSJGhU~(H%8!XNq7YLgc~T@vp#9AU zsf%>JaT4G%YypzPrn=-oGQZ+|l7E8#CFlxIfj-cGf_voVR1&|jETJSzM@{dpb}1^S zBxoFHpX}{90F7v8G@8Oj>R_+jK8Y&1qqh?q(JuIQY^2z;;ALSY=p!jbfUWFKj(s)3 zO@R0T795r{EgM#uF(qf@L^7*p3CLW!tfnjv>*_l0Mgskwvtzc@Hk*>qn>Fi<*?&`t z@w#ysV2)e$aCOZqJA{?mo%mbRv{K))5(=+YmIQsP9Kf@l)gV_@`-1sH^X1*kx7_x| z(6!3wa%FU>Bzgm8;JzW!5WepmYMjD;zEh;zrH)hzg4fw4b@ui`L+m+tFx8FWoSaN` zbU~x5d-mYLDC&B<#Lmec)b*sqRFbs9LSzrZZ2)$>1hNm>R?v=3nurpR&PV|9%%&}& zD^|DTJa-^qYeN)hgRhAmaR#c$UQp>+KlU>8d1q7TZj|A9HOH+~RzLsbQb{9er|&zz ze}HkVdRiuvSzS(OB4j$J=3)CZN}wm)({Q*~@4D2w9Bg@G^4)z)_f0G*`K93W zwczw}aC&ZdCD>9>-o7+`dMQPgg8H?fz8us+8EC##yBuhKW6 zcVeYx_ocz*n%!?XmJU5-|E_Y}kYn5duY@CmuaM@r&T&WK^(E`fjeO?zuR470?o|%p zx|8!%TsUJ3>Y%-yihkg}hi|72&+Gew5DU{k3cH^$EE;k;OOyo%+g91u8@EdDmGyH( z$>|EIrDeYT;Vu}lz*{b?4-&;tt``{Trh+#V8UpE!^%9#|Dyf4K`!v{1pY}F%Y^)K2 z^~l!RoG+Hc2S9t0{>9t!a8aH4Hq{v`CDMlz#Sr=dtTIW~li;|aWHqvFQH-KJ!T=pF zdB(>U!EW-!K!{#1`FH0S8eo*-rhgc!QamS&%S4AcZ$V8xfaQ(Ls+MJD?b3Ed!x1b!%qBiNC;;;V?Ch3+UhgThU<%wi*g;z3k0D2h+{ zx5S6~%Nh=_0C`18B5+CBJ~+5OK^UhGmi^wtRya%fhWf?Z%m2flOM?bZOwX{G)AK5s zvb*j+xG1PZS?k3N$N_o8?m5SkIytx2?#rGhDzwQ%0A?Ah!9Ef1Jp_Ypm1bl~Nh%r~ z?5F9ED|Q~j{fUGD;$}%~`2IVF;r6oNwC@0(yrw*wm+eBrq!9GZ^29_VFKVQbeqB-T zsX=*&HdRJyv#51xc~!OV897^ZwsQLaW^QE7twQD=#i47N^H+VqchSFA?dJESK;y}f5wTo+m&IVd}gU$z{z|DUKF1G#veJsr=8dOL& z3AaABpIdGtYl!O2|F#_m2*3 z+@#l;W%&lPL{`$;uslOX={wc!p6BrE&(bfdCps9(@Qy>!bMhmEZ`z1cs6cpV@u`~k zc)PAri+9()z|Y!DD<93mi{93cZ zcCk?R3nM#Qmn)l>N}Ac>8l_*<`FFnxns4FrJg8ry;rf=kqWshr=ZBuD4~N)3 z_iL~vxE$jrxlEs{kM=TJyS1zVl=&IzevYv1-iPiGgo}$`)$?n4cy*C)_<#>z1hM5= zqoW3$II|>=;g}%(tTEJxBsGI;v4_(`64ks&ba8IouiP2X{mq($LG z9Dyp0{-unhlJ0t?ruWw}oycVPO**#P>^t&j8X z(9YJq0{e7!O3$IHIAPfDrcbpt@gLGxT92%yAh@S(`xLCen2+h1JuS0EDX1%^3>a8} z_^G3#v7`O*p|R0K{K4^o*!EdrA;YYYXAoGDKE@W(&Z;U3QNoykyQiHW?k=!k^m8Ho zz6<+4!ATJo7rWYyujS?w`b;ExlwC@2!(+Ro?E~|RjX8`8_PO}4!&fDTGFd6F%7@9n ppo@1gU7`Pt?B92o?^@-y!ll}m8n2`L%XMX+V=;DHkayv%{{w;?cG3U< delta 3254 zcma)8U2Ggz6`t|_|0hoEUB^znjvXf($99@lb}FJ0+qL6l8`oqvC9xoz$Me|Tz5K{Vpidw0H2gEsd*7j!W z1a`Hb=bm%!opaB3zI**{@!oUsAI4%~2|s84a$P%``bFH3xseFTf9IDH-C@;p$NPpy zl78&re~Naj`c(g&z#A<%#-IC{3$#eg^Spn3toqd8Ct`vk#=8*{!l>|_h`aK-buJ{L zL^5Q{O7^#5yxvWecqDM#sB6%#Qz-ZYK!2&qTs92-NcTs zU0w@zeJJs@*a&|zbn-E=%8rW+E|?Z87)ps1%6bJ9y(&QpCqX-c<2}i21$N?NoWB|B z8x)>24relP=)}L!MX-wii!C{!iA4pbG^VStgYOAHdpJq1G(k7P#?nA_7eK|eevfc< z<9j#J&9_G`%3gjfdQ?vF8`0MX0~oOqn^8(iI;+@h!33?^0-`Lmm%I~tnpsPrl`Rb- z{Oj9>rd!cml^ri_4j#dQs83q#3@ERaZ4>TF%R_~NWkaDroBnXKX3J~A6r`|brw%o3 z_E8KJOf+vRO^(M9I(R<5`+P&e!dn##dMJK~U^jvjQJGc5P1u@gh#a@9U54TbTKT*2 zFZ#txGPlnqcm2R-90YsajDp zm<5M$T=h61(hKCsP7IBSN# zu=kPtz*?~LZnE!2l)jA(*V)u?PW1H5@qA%o`q|?XlR0suZ7S3WPnp291tZIrA;b6W zJm}Z(6)?)r?VKB>1H}oJ!NlIQmw`3}O9W|xCK-&8jbMN6{hhy&-Bui{Rl9Dg~BiOtS0(oq+1x1G(*-sH%L0F08wK7{@WEL$>0FONU z8bH?roS}nqmc*Zto!Gp1S;453E-={oAc(sOt#f}4XIiw9xMSW)^sEJY#ECG%&vwW9 zE~Dom=fHJzD?||gUUxj(a1OLL)3Re~ESo=ls*pcBJGlirU&4jJBoGp>@Q=Gko)qV) z&oFHi!6ou76A(>XQbM@`!KvDOTCP)axmN0VOI|Ia+40xKd>jXP5ecVhj<}c-E?wh_ zU0fV~#4B+-tN{gO{g1BRFLX3{Jq}uqjYsR(F^q6hY}YPsjc&7@=D)c)X;mq9sJjQ#bMC_ zUMIpXl{Hu{sCW{A7gvU_5PX&3KKV}X>5+jyzh|Jn#?SWLKC~J7ZOX~3D$7>Jv!P=g zqD`Bhw>;=h3prow&&U_~Py2I1&LjNr-p&Wh`8H1b0(Q%8rJ+-r1?);zw1UuBnNt5I zf#A1-PmbU1b642kBHs-H${K8fbNr*d!$+EW=0);+hu~F$G(nT9Z<39G)e8F->n(J% z_IBnSdEgeB@l+GyB`Why)W*BP!rKh5dP_`m`{^?O<3Q&T@sG`CXhDj0{BEbfOEd^) z@yei!r7mN~_gPXdE`L@`;JpW4lwaZBKQNFMTc;iYlIndV(m2WAKd?)_#e;*Nu2XPj zaNmO|coXM*LkRZnU_8}8L#k1*{6B+Tt6NbZ>O&O3c>=-6YxLBE;B0HCN5NjEW0ZU% zZ=q!`Y5D(=a#fN75+F)fYd;v8t`kw^{}>(_%g~ym1foAg4k9lKZzA;H!6PM8t?2A2 q_$_*6{8@{f9UM9km7n-P`Xs#6{&Lqp$^Ox%v#a*IgRQcciuGTRSJTk| diff --git a/core/context_processors.py b/core/context_processors.py index 0d1599d..265d612 100644 --- a/core/context_processors.py +++ b/core/context_processors.py @@ -17,7 +17,8 @@ def project_context(request): "project_address": settings.app_address, "project_phone": settings.app_phone, "project_email": settings.app_email, + "app_settings": settings, # Passing the whole object for easier access to new fields "project_image_url": os.getenv("PROJECT_IMAGE_URL", ""), # Used for cache-busting static assets "deployment_timestamp": int(time.time()), - } \ No newline at end of file + } diff --git a/core/forms.py b/core/forms.py index cd5e243..e32b761 100644 --- a/core/forms.py +++ b/core/forms.py @@ -4,13 +4,20 @@ from .models import Supplier, Faktur, Medicine, Batch, StockTransaction, Categor class AppSettingForm(forms.ModelForm): class Meta: model = AppSetting - fields = ['app_name', 'app_description', 'app_address', 'app_phone', 'app_email'] + fields = [ + 'app_name', 'app_description', 'app_address', 'app_phone', 'app_email', + 'theme_color', 'font_family', 'font_color', 'sidebar_theme' + ] widgets = { 'app_name': forms.TextInput(attrs={'class': 'form-control'}), 'app_description': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}), 'app_address': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}), 'app_phone': forms.TextInput(attrs={'class': 'form-control'}), 'app_email': forms.EmailInput(attrs={'class': 'form-control'}), + 'theme_color': forms.Select(attrs={'class': 'form-select'}), + 'font_family': forms.Select(attrs={'class': 'form-select'}), + 'font_color': forms.TextInput(attrs={'class': 'form-control', 'type': 'color'}), + 'sidebar_theme': forms.Select(attrs={'class': 'form-select'}), } class CategoryForm(forms.ModelForm): @@ -116,4 +123,4 @@ class StockOutForm(forms.Form): except (ValueError, TypeError): pass elif self.initial.get('medicine'): - self.fields['batch'].queryset = Batch.objects.filter(medicine_id=self.initial.get('medicine'), quantity__gt=0) + self.fields['batch'].queryset = Batch.objects.filter(medicine_id=self.initial.get('medicine'), quantity__gt=0) \ No newline at end of file diff --git a/core/migrations/0005_appsetting_font_color_appsetting_font_family_and_more.py b/core/migrations/0005_appsetting_font_color_appsetting_font_family_and_more.py new file mode 100644 index 0000000..43006a2 --- /dev/null +++ b/core/migrations/0005_appsetting_font_color_appsetting_font_family_and_more.py @@ -0,0 +1,33 @@ +# Generated by Django 5.2.7 on 2026-02-06 12:04 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0004_appsetting'), + ] + + operations = [ + migrations.AddField( + model_name='appsetting', + name='font_color', + field=models.CharField(default='#2d3748', max_length=7, verbose_name='Warna Font Utama'), + ), + migrations.AddField( + model_name='appsetting', + name='font_family', + field=models.CharField(choices=[('Inter', 'Inter (Modern)'), ('Poppins', 'Poppins (Friendly)'), ('Roboto', 'Roboto (Clean)'), ('Montserrat', 'Montserrat (Elegant)'), ('Playfair Display', 'Playfair (Classic)')], default='Inter', max_length=50, verbose_name='Jenis Font'), + ), + migrations.AddField( + model_name='appsetting', + name='sidebar_theme', + field=models.CharField(choices=[('light', 'Light'), ('dark', 'Dark'), ('glass', 'Glassmorphism')], default='glass', max_length=20, verbose_name='Gaya Sidebar'), + ), + migrations.AddField( + model_name='appsetting', + name='theme_color', + field=models.CharField(choices=[('primary', 'Ocean Blue'), ('success', 'Emerald Green'), ('indigo', 'Royal Purple'), ('orange', 'Sunset Orange'), ('dark', 'Midnight Dark'), ('secondary', 'Minimalist Gray')], default='primary', max_length=20, verbose_name='Warna Tema'), + ), + ] diff --git a/core/migrations/0006_alter_appsetting_theme_color.py b/core/migrations/0006_alter_appsetting_theme_color.py new file mode 100644 index 0000000..3addede --- /dev/null +++ b/core/migrations/0006_alter_appsetting_theme_color.py @@ -0,0 +1,18 @@ +# Generated by Django 5.2.7 on 2026-02-06 12:17 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0005_appsetting_font_color_appsetting_font_family_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='appsetting', + name='theme_color', + field=models.CharField(choices=[('primary', 'Ocean Blue'), ('success', 'Emerald Green'), ('indigo', 'Royal Purple'), ('orange', 'Sunset Orange'), ('dark', 'Midnight Dark'), ('secondary', 'Minimalist Gray'), ('white', 'Clean White')], default='primary', max_length=20, verbose_name='Warna Tema'), + ), + ] diff --git a/core/migrations/__pycache__/0005_appsetting_font_color_appsetting_font_family_and_more.cpython-311.pyc b/core/migrations/__pycache__/0005_appsetting_font_color_appsetting_font_family_and_more.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0303de97e031886585c698f8e6a45516d2fa1967 GIT binary patch literal 1900 zcmb7E&2Jk;6rcU@+TPgta8e3tsg|@tu|RQDiU6rXq92K<;xsgT#RyiDoryik?#wc~ zru70<4j^&tjXQ?|A_x8i{)8aq5N(f~a&wfNdg9I6Za$1!F>Ak%dGmhn&6_v#Yq@MA z7=P~l$e!d7`bQ~)0eUtLuLJuT5kxc}1zJN3^oFh>9W5ZD|A2@=wGE@c7Ci>(k7ruL zAm$3H=Ju7js;73qni9uM@F=wcL8u>j15d@vedX|mrb1HG&3k{q$N^QTkTE}YhfP>QEfnuyrHXk>(xNO^nou?gFOe{Z}HYitN>9Iz%x zg-rf$tf?WabAa^{V4Z&vR?}=0$jeapSJGmAP;n@~=?O{GvAMaqYc3AMh{iGF&D1_A zuL~Z#p74cC@|UlYx8Aw-?!GEx}v&9m!&?5O#JsAUgc|H$RfVwcP|l*P5LGkHdo95{8p#saq-tO} z3M4H@jLtW6avEiWh*2pP6m6v#_}wLb+U zDJ|d*c2;_*=|~3KJE*D!?)gx%0LxBd-}PYg&JDj!)pXSMAiF3j-wvq6K5-T#r5r34 z>x^)fztc~<7*S7f*hwcD zt1}Kc_$-Pc3hu~ho)dPcPNd}5Du4e zk3nJ8Ymyc|AY@*3ja0WWE#7Qlndzx5LfBaLru>c$!HAv)wU!8It-aRfal1wzP_G>e zS-UUfW)xzN*3>E$*vRx5~(d)aF>EGV_YhvdkZ>K{3u8`dd>E_L% zeSm-*DRRc`(!i~Y(3@WwXK2e1YU(@Vp<;D&)dV)#Fb^_%l+owoI|KZkH-i4}{zCv+ z)R%N%U+SBRP5Qcm^mPU4>(7TgmGT!^$|oo_xSIOb_+GI^^Ybj_)hy*zQ{lrV&XnY} za}{grj{0P6Q2iyijYYBn%`0ZfTGlpMv-HkqRxQic&Vlr_aJ|=i?@M*3;mA<*DUhzA jX&RiFR^34}!@sU|L9@DOm^`v~$FCeH!_j|Ov$+2Pd1(R> literal 0 HcmV?d00001 diff --git a/core/migrations/__pycache__/0006_alter_appsetting_theme_color.cpython-311.pyc b/core/migrations/__pycache__/0006_alter_appsetting_theme_color.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..046352383beef07ac379f97bf69757c00216d1d5 GIT binary patch literal 1142 zcmZuv&rj4q6rTRr?zXT|k;Ic^1vPGBST1@n#6(dsM!*P4vX^G)yxr~6&aBf`*u6-M zCLXzQ_kc0-ub6n?K|2f_@{+QuMh8?A3AUfp2kBB>Vk6iqsnrdgfY~01!lRjrSnZ-pRHI3l`B`HH zX0hT30`1Qw*{kJgOuf!abHk8_P15GH<^n`@;-qh689hY`G5yY|2n{Gq!*!4sp zDQ9k|a-Gw(bSQ2?2>rxr5w|aPq#sh*?Kuk`P+oZ$B%s1k;&~87z4GG_ zBn?<)RswKjET1#KDSE>%MVAJZ7m4fyD#H?z@+S1kiwQ@Om4)0z!emsg_R4cU<9@Rh zS015@VLJj(aOAqZ3v)h45rH4Ycns|#TUcxPG4zIJ0wro$IdTXKw?B%|bC#*(w6X*t zt(s}kYY894rbPw~nglU6m9D!1@Mhdfhu?x+5fQkYhEO$-Q%%mj)Ksyw(C{H(^Hn=7 zxp~}mQ^&>Hu_OSrhh6tgLIbr{c?>$h8F0^sNUD34Iu8Pr_eAX?Rew`^rbYXH>WB{3 zFTY=3$sv;Dc&XMBA=HwUgvUt@*1=0+A!}y85WFF*rlw(#jZRda>94W{QYsA`krXD#y5H*i|vRNB%h?rz6 zdD-$(^<`gE%ks4oXdRcP`?bF>Z=kE;7rjQv3{BJUSG4L6a_jt?S;Lx@k@K+W>|VTn MpopXYu=%;a0g9eNkN^Mx literal 0 HcmV?d00001 diff --git a/core/models.py b/core/models.py index b0e3a39..7ab7a00 100644 --- a/core/models.py +++ b/core/models.py @@ -2,12 +2,62 @@ from django.db import models from django.utils import timezone class AppSetting(models.Model): + THEME_CHOICES = [ + ('primary', 'Ocean Blue'), + ('success', 'Emerald Green'), + ('indigo', 'Royal Purple'), + ('orange', 'Sunset Orange'), + ('dark', 'Midnight Dark'), + ('secondary', 'Minimalist Gray'), + ('white', 'Clean White'), + ] + + FONT_CHOICES = [ + ('Inter', 'Inter (Modern)'), + ('Poppins', 'Poppins (Friendly)'), + ('Roboto', 'Roboto (Clean)'), + ('Montserrat', 'Montserrat (Elegant)'), + ('Playfair Display', 'Playfair (Classic)'), + ] + app_name = models.CharField(max_length=100, default="DN-WRS", verbose_name="Nama Aplikasi") app_description = models.TextField(blank=True, verbose_name="Deskripsi Aplikasi") app_address = models.TextField(blank=True, verbose_name="Alamat") app_phone = models.CharField(max_length=20, blank=True, verbose_name="Nomor Telepon") app_email = models.EmailField(blank=True, verbose_name="Email") + # Theme Management + theme_color = models.CharField(max_length=20, choices=THEME_CHOICES, default='primary', verbose_name="Warna Tema") + font_family = models.CharField(max_length=50, choices=FONT_CHOICES, default='Inter', verbose_name="Jenis Font") + font_color = models.CharField(max_length=7, default="#2d3748", verbose_name="Warna Font Utama") + sidebar_theme = models.CharField(max_length=20, choices=[('light', 'Light'), ('dark', 'Dark'), ('glass', 'Glassmorphism')], default='glass', verbose_name="Gaya Sidebar") + + @property + def theme_hex(self): + colors = { + 'primary': '#0d6efd', + 'success': '#10b981', + 'indigo': '#6366f1', + 'orange': '#f59e0b', + 'dark': '#1e293b', + 'secondary': '#64748b', + 'white': '#ffffff', + } + return colors.get(self.theme_color, '#0d6efd') + + @property + def theme_gradient_end(self): + colors = { + 'primary': '#00d2ff', + 'success': '#34d399', + 'indigo': '#a855f7', + 'orange': '#fbbf24', + 'dark': '#475569', + 'secondary': '#94a3b8', + 'white': '#f8fafc', + } + return colors.get(self.theme_color, '#00d2ff') + def __str__(self): return self.app_name @@ -15,6 +65,7 @@ class AppSetting(models.Model): verbose_name = "Pengaturan Aplikasi" verbose_name_plural = "Pengaturan Aplikasi" +# ... rest of the file stays same class Category(models.Model): name = models.CharField(max_length=100, verbose_name="Nama Kategori") description = models.TextField(blank=True, verbose_name="Deskripsi") @@ -145,4 +196,4 @@ class StockTransaction(models.Model): class Meta: verbose_name_plural = "Transaksi Stok" - verbose_name = "Transaksi Stok" \ No newline at end of file + verbose_name = "Transaksi Stok" diff --git a/core/templates/base.html b/core/templates/base.html index 12a5b04..535ad96 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -7,10 +7,22 @@ {{ project_name|default:"DN-WRS" }} - + + - + {% if app_settings.font_family == 'Poppins' %} + + {% elif app_settings.font_family == 'Roboto' %} + + {% elif app_settings.font_family == 'Montserrat' %} + + {% elif app_settings.font_family == 'Playfair Display' %} + + {% else %} + + {% endif %} + @@ -20,19 +32,38 @@ - {% block extra_head %}{% endblock %} + {% block extra_css %}{% endblock %} {% if user.is_authenticated %} - + {% endif %} -
- +
+ {% if user.is_authenticated %}
-
- + +
+ {% endif %} -
- {% if messages %} +
+ {% if user.is_authenticated and messages %} {% for message in messages %} - {% else %} -
- {% block login_content %}{% block content_no_auth %}{% endblock %}{% endblock %} -
- {% endif %}