From 1c815a62fb2b932668b4e903b35fd66667cebeac Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sun, 18 Jan 2026 11:58:06 +0000 Subject: [PATCH] with product --- core/__pycache__/admin.cpython-311.pyc | Bin 212 -> 751 bytes core/__pycache__/models.cpython-311.pyc | Bin 209 -> 1431 bytes core/__pycache__/urls.cpython-311.pyc | Bin 347 -> 1075 bytes core/__pycache__/views.cpython-311.pyc | Bin 1364 -> 3478 bytes core/admin.py | 7 +- core/migrations/0001_initial.py | 26 +++ .../__pycache__/0001_initial.cpython-311.pyc | Bin 0 -> 1416 bytes core/models.py | 15 +- core/templates/base.html | 42 +++- core/templates/core/index.html | 192 +++++------------- .../core/product_confirm_delete.html | 17 ++ core/templates/core/product_form.html | 18 ++ core/templates/core/product_list.html | 81 ++++++++ core/urls.py | 17 +- core/views.py | 69 +++++-- static/css/custom.css | 56 ++++- staticfiles/css/custom.css | 65 ++++-- 17 files changed, 416 insertions(+), 189 deletions(-) create mode 100644 core/migrations/0001_initial.py create mode 100644 core/migrations/__pycache__/0001_initial.cpython-311.pyc create mode 100644 core/templates/core/product_confirm_delete.html create mode 100644 core/templates/core/product_form.html create mode 100644 core/templates/core/product_list.html diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index cd6f855b12f4883b1ba9de01c54245c53aacd714..fc33bde1289d744c49cd7ab796f13c6888539bbf 100644 GIT binary patch literal 751 zcmZWmKX21O6o2Q7V-pgPnid5rpi(Cf)Ds&*Vq$<+NDN3`POk5ox;e-0*{02wp&y`I zC)Oa;&%s`#4$)1On7XA3Qzzazaiyy7?%ut>zjycE&rYWWNI!ndxJLl~8l|S@QkZ8b zoB;<;BqSst1h~biv=SOn0u~5z(5RCHogmIRo&{O(5qRSSxQ$VEZJkhz!Ly(VUgxy} zL6bMXg6CWti$}B_@+2N!8${HcFDm6_R77|2DAd*FFHkuH0RiC5F3#l|`!jqf`y@ER2L7rAqi!leV&vaxkZ2W+eGb zWaGPa)%`a9JYC%!Z%Kv*Wip*$)+mk_#y znU98om0e^M2HZ7-wBY)f&;YC=BgcdV#2#j5ukp$MfP01rY6uuLL=h3`;|W;kisu5H z0y7^CWhz6$GM2l_6qmxMS>3`psK10c+^Lx5ltw--;!<~JDrY9k$@<6h&S74T3Q(gw zxr&Qjb&9Qq%P&x47HfcWcozCImlhv0A4hgL_!D-5_NcD)%%sHI4-W^hMuECc;{mmT?jisOZF_6T);aZbT8lqcRsAv4t$r?qGsfUQH?w!b`<)o z_S9#s;0VsE**+t+{Nh)SPST=j1|c)eQ+=p;br{fKyMSwGqrN`>@+2e48%;a{8yQwv(l`zx1`Zw8m~jc*oGwl4iN1%%cN~)g3}HTi|}lwnDP+vy)T`T2ZQP=Qo;Vq{*p+ znyK<;BkTNqO;g5SLea<&~to(%$at z)y{FESKr=$hksv)^?FaQCwjg8Q(vug?j~yGwf*k9Sl#HU8;QEne$>~hoqD2G-`;y~ z#oA_1+f200_78n+nTMBqnvrM*_?7incazHc`(|9(>Q%Oq%2q7jypjdw_7xgKK~UDY zI}N!YE@Q_iq%-)?^7j2z+|0XK9{LfZ0pmJTYMgm8=Os?^EdPy`=y0_&SrZc24q%h_%F;NA^_k4A8`Nx diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc index 1f807fae1897c89361c99c5e868a26d00799b73f..b4c1f9d7d00bc41592f712e39129b0288753c6f0 100644 GIT binary patch literal 1075 zcmbu7y=&V*6u?jNNw%XXPC{|0TPPUSU|L5*ForaV33Z@^wiJp>BPc=f9kCP15+}K7 zHD%1$t^YyV(heOvcI$eA8-mtO*$mk-_0AumN$sg8>G8gP@9Ey%CtaTbeBJ-$bQ&@M zzlAYg*^zRwDgp2jAb=zXxRNDF0Lduj$ZpC?xzK{HVkxd_sczaz^BA-;GQbj2xJ(_4 ztAJBp?(4WVKxKoyg2^Mw!ZJ6Pa1gs8bnzA~VOC^i(Eyli63S z88rVAlo!s$2Fp?ceLHNQ^I?LrlIRUPXzzJ8L9aUaD9ODb9_qEir=1`iI2J~Z#{}CU zzUFHB=%%ZI9X!f{Esx*?Bv~|WAX;~A7e`rt*d#Ec*^ydtc*97)3fKslkv0x;D_XjW zt#!KLs(-j)V$=!$Dk041_P=Rp@Ka_qH!e4HJTGgBh7RoRzPH>XPC&#JNR+pH3;|KN zPE;Y%LS%#xS18HYzP~GWk)-WlS0pDIr};=jOuE4raKW>{6oJJvj6@vv*z-tJ9vZSIV?^lSmLsuk|gO2+@;swzN|`eAN;SF z2eXUEnZ62?>~Z5{k?O^hH%u?ay1{hg^CJptF|09IJA)Y>zeDqt4<5@`;=IZ7=Jzgz zTQS^XaBCR9M++;o@PHLo;zE@bsz07lxE;f72Db+ZG+U&`IyI`ySdWc5GwMHiiDnF& q3^qp@1})WTsm4n6xU|VioAk+R3U^|-!{AO|Q*-jMCLVH&59kk+%o_3l delta 255 zcmdnYahs`rIWI340}vcY|CNyiq#uJgFu)3Be6|5HrZc24q%h_%7Ws=T@>f{oKQJ@#Gc|C7U=a_{H~>Y{H-G>D diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index 6867ddf286a519cf1754ac97038f9f1e4605fbf2..b689a39ad2d757e2dcb3ed1ba8957ab17c7e0105 100644 GIT binary patch literal 3478 zcmcIm&2JM&6rc63z3VSFi2)O)n9ii#ei3elqU&?Emrd$c1WNc>!lB|&^}Sg;@kfC6(An9yv+vEv zn|Z(a&HNOPM+l@HzuCDzLxlW+Kg|?u6juI*!d+q!OR|Y08Ilt)0*-9R66ylB;slML zD9d)pQ4Q7649y7}VJBilK(AOqJL<%Ym_!2PV`7DF5lf}&eVLF2c>QF=g-runxXZRd z*dkzyQmvz%E^INd#c8<1)+1~iz^2nkhpm^!=lhzYw|?)#&%&z0NLW2zl63DA)TCt| zVl;12#x+K*9HUu}_l{G~EL@s|vRPo}@Y};_iN_edN|{SdJ2P`Vt#Iwroa>#>(Q7<% zoY9O&{qk2+)@u0#wW+UvBH>sPS3hS3tC;n&tKL8XZJ1WJg1Ad4F(iu^0V*4cB^g00 zV1z6gJXU!8M8=)CRLC$32bzy_}s*kyMrlcj^gv8&*tJ1}*fZGbjH03L~(0x`S#)MJU+ll6^zX3x~O z?ye|FKeJ@BN!v;VK#OT*7{u2vSgSG_lPvj`W~id1KuIf;X~_t~8V0%E2thM^Gn<98 zjg>QPh^kmjro$N7W^8a&L^i%FyFvTCbeDK7)^?1|w^*>LpW5r(kV<5-IU_QOJ&QE2 zG)t{tOS%tzF0A%@Bk-SE2Rd5Ir2yMplIEL?&^i<;1%8n`>Psd0CH3WBl&<;`uJ$Nb z5I0=Q0^kfL-N#-I@s-KtT~PHj&8C^7)0wQ74)LH{oPu2$!@YQ=NZECldR%1` z%C5)dk58WCGT3-%EN6R^L1Yz|+GAX6R%Y8^Qfxa29yZOaopD{$baBEdNV9AUnqLPo zv#kRX1Fd8BKn?d6h`(mZqr{fmhwdC&O7t%#`m2d_Es-v3bv^M-siyB-(swQDyXHTt z>icT?zOqtJB=3yW61)7`KS!#Gp;}_7tUZqE%R~ylUr+A5d-J=Szj|{wtI3gCa-@9f zaWsLZ52c3fp@z0&wd66d>B+J#_C*^gaXwLaR}fqX%D_utIk^fSE0`lC>7MkhbR*!k z0PfW=v=AHs+l5u=t`DMiu$KasG6Ei!0sxE9s0hnBh`cfejKd?1_~)q0Hbbp+h^64e zdoU199s*v?_=KhU-0bq`)r<{r5Sx~37Hr*I9>AlpH?ei-^0f>bce&c=fxQJ<7bm+G z|NZbclUgtSt-~US+|NJ&2I_r#zu$Aa|4x6cZ*Qe<81m2O{cl-)lTor6ww5}(l)A8(x=>ABtfelN)wx(z+g{fIj88D;@7m{Jhz|sBKyDBVE+Ti{-Y1VFAoS( z4z(?pgK3zE3fxj;wg9ic7J^;ym|`g2fOlmGL^BM4BmdyTK*YbOh&=mIy>G|d z{>sjGs(nMXzMW$Ar5J+_L;LTlk#TULHRYH+BTw zMzU#%*KzzsF#xZNv+Ii2L5SB2gM>{-(;In@HJQne7Y5vk0`uT*Aqm2!Xe`y-0c?!^FDz?y2gi+wlo`=MB&GlJAT&={07g!UKK`*$PaZT)tD|l7w znCNqD#J><8VW*+81h0Dz(US=s~i(k13j zJw@%aHB)4h1Vq#=<|dw^_Su?gK#_)*Nw@eR@)Wht)=aVPN}}O9HD&CxTVPGlqMr?W YjA)yd)NPCEwyL_LrtX+k@DcF(2a?Mx8UO$Q literal 1364 zcmZ`(&1)M+6ra_{dS%J>I!@|TuH%hUh$T{~CE!96oTjQ1oHkCdQ%ZHHPf-Q6#oP5Eq{V!1Q7#*Ku^61OfEk4%~~s}guETzy!YnKoA>c! z|CpMZL_mL+PRlpL2>m0JfI>sz+l$SscSs^=|k4VB6wxYJ2mwh>6 zP1s6a0Xh0B%Et_88>QrbMYzqB#N#E*3Oks3CUHQODRvA@K~k7$;|6iCE(zZu#bJlk z(8(RJK1WUTVt6pV9fEo^GQIeJgpqaJXHRNMhV;}glZK3tBN^en5Q~o7QAND#(>piA zMx+^HvEUS;@pC3}9#TaPq;a2SxGAxj;0&RP639l>kPjiNqhJ8&1AY_l`WecBvKL`< zK_mp-GGfihA=Gg+ss)BI*;w21yRNY^)~upqm`+Labc(T~)l62_EK-D_XmFxoXUC+( zv9ZH61GA!Od6`C{=(;tt(Wqy1VsquT>;5P-9=l@|nMF#b-iU4DnzqgA7Upvgw;tSE z&pj%9yS|;<+IaYA=m{Nfc9(G8LP76tKq2MQk+Efgahls~zxB^Y15iq2p ze1hU%s@P+67IZo#*hj*3LMINxyUY_2H9@DJWy{3I+3Mq}!>U=li}flaG+QI|spl4T zob~hDF>%eyxOE;8-gFVJ3n+TO18bo->ila}J65%hy4+QlU#ly}>PkmVchz)jqo<`_ z{(P+6Xlpn2)BEXH3$5?^ljojY`z`Y<)5;BG^zo;?`Q?6crISo|lj(kPxtsi=lf2$d zUhiF8=v}zfU%GryZ>QE?g*r>Q?ozJ5xODJS`|4MJebZUI)m^+bn2pWI0|cyf_w9L< zIJbYby>RVisS{uA##h^s)e}e(07x&wM(2TX`E06G0Q9V<>X{|ul?i3g0?%(HPYlgf z1`zb;;Me{qqL;+gPk@~&H*I26ExbmrfGYk1-V{EkF{MC?3pR(-?TR|_ct_tu zu~Ml>kJ^ba@YBQ#Sk9)t25!UzjG>IhAtBQ`|=iRcN!;x7mXh;Rsdr=thj*}`fD zaBv4zLSyc%h%DC8T9)EyreQOwV`8G)>TIL`mz)_FYXVP6P*cFDDPo}+XrX3ML?m=5 z%{O2X2Vf<97+I_cSinIX>Px*KlmT-(_C*}_kp&lq_a|1!H>}5a1xOKJeR=B@> zIc`g6CU6dj&$H;WIpe!5ylt7-RUIa3c$0}w*DFDmP+Z59Rf{MN!7Sdjw2opO%WZPZ zqBgNKMb~~NEOA7vJ<}$#p>zlfaycGAnH2%9RCy`u#ArDOETTe`mT4W2F?R-7Xiry+ zwv`48cDcIF0(RT2h|?9xHMAElVIjz>k})T5%=v;wNnxTwCA!?z6_wc2ELdx4j?F^0 zW2$X-v!fYW$L+|z2_+m69qI{Vvah(h14&Xmt+cNZ9ovmcl0{^{epzNQS%&U&bpm=q zmS4Dv&d&r^7=k)*YL>vHOAJg5RU@{=JDSDoK26Vf-&(x6SYl0UeG3F`@*FH$KTxcx znpmIKKee*krVUY#$WsIOAu~+O?2_5b@F%)}aOlG~wF9$5YVMwEIBt!+Bq{{AYCoA) z+wKApHPy68?Z20(wz9JFK%SL+zk6))m%|rau|I-1Sv+r3OD9hzK_M%hd_Rex=x4vi zyvV1cOz~~z7R}v#b>!vlz77s<)22)fi{|WM&h~OPO*^AZjutAX%U+>!zC#PE!@{ap zSf%N&Mww4&se1a{D^<_e-|P$=TG}0!cD>RrP5(H`EYp1XRPyrW^ZJ`0&2J3z8(w~c zrZ-2KJS|pF?|8-P>mLSR&|+g)YgEt{9Soh|1G@#X^_)sxg=6$^9U#EYA zQ^G#yFdth5?L*}8v^l=EYGCp&g#8@EBp?XFL_$J^qVo0MM9K=%1YH-eVqW_8JMMV@ IKVCoYzh{Ddp#T5? literal 0 HcmV?d00001 diff --git a/core/models.py b/core/models.py index 71a8362..661aceb 100644 --- a/core/models.py +++ b/core/models.py @@ -1,3 +1,16 @@ from django.db import models +from django.urls import reverse -# Create your models here. +class Product(models.Model): + name = models.CharField(max_length=200) + category = models.CharField(max_length=100, blank=True, null=True) + sku = models.CharField(max_length=100, unique=True) + price = models.DecimalField(max_digits=10, decimal_places=2) + stock = models.PositiveIntegerField() + minimum_stock_level = models.PositiveIntegerField(default=10) + + def __str__(self): + return self.name + + def is_below_minimum_stock(self): + return self.stock < self.minimum_stock_level diff --git a/core/templates/base.html b/core/templates/base.html index 1e7e5fb..2eb01fe 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -3,7 +3,8 @@ - {% block title %}Knowledge Base{% endblock %} + {% block title %}Thai Shop Inventory{% endblock %} + {% if project_description %} @@ -13,13 +14,46 @@ {% endif %} + + + + + + + {% load static %} - + {% block head %}{% endblock %} - {% block content %}{% endblock %} + + +
+ {% block content %}{% endblock %} +
+ + - + \ No newline at end of file diff --git a/core/templates/core/index.html b/core/templates/core/index.html index faec813..97a65a6 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -1,145 +1,57 @@ {% extends "base.html" %} -{% block title %}{{ project_name }}{% endblock %} - -{% block head %} - - - - -{% endblock %} +{% block title %}Dashboard - Thai Shop Inventory{% endblock %} {% block content %} -
-
-

Analyzing your requirements and generating your app…

-
- Loading… +
+

Product Dashboard

+ Add Product +
+ +
+
+
All Products
+
+ + + + + + + + + + + + + + {% for product in products %} + + + + + + + + + + {% empty %} + + + + {% endfor %} + +
SKUNameCategoryPriceStockStatusActions
{{ product.sku }}{{ product.name }}{{ product.category }}฿{{ product.price|floatformat:2 }}{{ product.stock }} + {% if product.is_below_minimum_stock %} + Low Stock + {% else %} + In Stock + {% endif %} + + Edit + Delete +
No products found.
+
-

AppWizzy AI is collecting your requirements and applying the first changes.

-

This page will refresh automatically as the plan is implemented.

-

- Runtime: Django {{ django_version }} · Python {{ python_version }} - — UTC {{ current_time|date:"Y-m-d H:i:s" }} -

-
-
-
- Page updated: {{ current_time|date:"Y-m-d H:i:s" }} (UTC) -
-{% endblock %} \ No newline at end of file + +{% endblock %} diff --git a/core/templates/core/product_confirm_delete.html b/core/templates/core/product_confirm_delete.html new file mode 100644 index 0000000..c1f2f88 --- /dev/null +++ b/core/templates/core/product_confirm_delete.html @@ -0,0 +1,17 @@ +{% extends "base.html" %} + +{% block title %}Confirm Delete - Thai Shop Inventory{% endblock %} + +{% block content %} +

Confirm Delete

+ + + +
+ {% csrf_token %} + + Cancel +
+{% endblock %} diff --git a/core/templates/core/product_form.html b/core/templates/core/product_form.html new file mode 100644 index 0000000..e1661ae --- /dev/null +++ b/core/templates/core/product_form.html @@ -0,0 +1,18 @@ +{% extends "base.html" %} + +{% block title %}{% if object %}Edit{% else %}Add{% endif %} Product - Thai Shop Inventory{% endblock %} + +{% block content %} +

{% if object %}Edit{% else %}Add{% endif %} Product

+ +
+
+
+ {% csrf_token %} + {{ form.as_p }} + + Cancel +
+
+
+{% endblock %} diff --git a/core/templates/core/product_list.html b/core/templates/core/product_list.html new file mode 100644 index 0000000..9bb5fc0 --- /dev/null +++ b/core/templates/core/product_list.html @@ -0,0 +1,81 @@ +{% extends "base.html" %} + +{% block title %}Products - Thai Shop Inventory{% endblock %} + +{% block content %} +
+

Products

+ Add Product +
+ +
+
+
Filter & Search
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+ +
+
+
Product List
+
+ + + + + + + + + + + + + + {% for product in products %} + + + + + + + + + + {% empty %} + + + + {% endfor %} + +
SKUNameCategoryPriceStockStatusActions
{{ product.sku }}{{ product.name }}{{ product.category }}฿{{ product.price|floatformat:2 }}{{ product.stock }} + {% if product.stock <= product.minimum_stock_level %} + Low Stock + {% else %} + In Stock + {% endif %} + + Edit + Delete +
No products found.
+
+
+
+{% endblock %} diff --git a/core/urls.py b/core/urls.py index 6299e3d..8749ca6 100644 --- a/core/urls.py +++ b/core/urls.py @@ -1,7 +1,18 @@ from django.urls import path +from .views import ( + DashboardView, + ProductListView, + ProductCreateView, + ProductUpdateView, + ProductDeleteView, +) -from .views import home +app_name = 'core' urlpatterns = [ - path("", home, name="home"), -] + path("", DashboardView.as_view(), name="dashboard"), + path("products/", ProductListView.as_view(), name="product-list"), + path("products/add/", ProductCreateView.as_view(), name="product-add"), + path("products//edit/", ProductUpdateView.as_view(), name="product-edit"), + path("products//delete/", ProductDeleteView.as_view(), name="product-delete"), +] \ No newline at end of file diff --git a/core/views.py b/core/views.py index c9aed12..2c53856 100644 --- a/core/views.py +++ b/core/views.py @@ -1,25 +1,52 @@ -import os -import platform +from django.shortcuts import render, redirect, get_object_or_404 +from django.urls import reverse_lazy +from django.views.generic import ListView, CreateView, UpdateView, DeleteView +from .models import Product -from django import get_version as django_version -from django.shortcuts import render -from django.utils import timezone +class DashboardView(ListView): + model = Product + template_name = 'core/index.html' + context_object_name = 'products' +class ProductListView(ListView): + model = Product + template_name = 'core/product_list.html' + context_object_name = 'products' -def home(request): - """Render the landing screen with loader and environment details.""" - host_name = request.get_host().lower() - agent_brand = "AppWizzy" if host_name == "appwizzy.com" else "Flatlogic" - now = timezone.now() + def get_queryset(self): + queryset = super().get_queryset() + name = self.request.GET.get('name') + category = self.request.GET.get('category') - context = { - "project_name": "New Style", - "agent_brand": agent_brand, - "django_version": django_version(), - "python_version": platform.python_version(), - "current_time": now, - "host_name": host_name, - "project_description": os.getenv("PROJECT_DESCRIPTION", ""), - "project_image_url": os.getenv("PROJECT_IMAGE_URL", ""), - } - return render(request, "core/index.html", context) + if name: + queryset = queryset.filter(name__icontains=name) + + if category: + queryset = queryset.filter(category__iexact=category) + + return queryset + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['categories'] = Product.objects.values_list('category', flat=True).distinct() + return context + +class ProductCreateView(CreateView): + model = Product + template_name = 'core/product_form.html' + fields = ['name', 'category', 'sku', 'price', 'stock', 'minimum_stock_level'] + success_url = reverse_lazy('core:product-list') + +class ProductUpdateView(UpdateView): + model = Product + template_name = 'core/product_form.html' + fields = ['name', 'category', 'sku', 'price', 'stock', 'minimum_stock_level'] + success_url = reverse_lazy('core:product-list') + +class ProductDeleteView(DeleteView): + model = Product + template_name = 'core/product_confirm_delete.html' + success_url = reverse_lazy('core:product-list') + +# The home view is now the product list view. +home = DashboardView.as_view() \ No newline at end of file diff --git a/static/css/custom.css b/static/css/custom.css index 925f6ed..a3eb3be 100644 --- a/static/css/custom.css +++ b/static/css/custom.css @@ -1,4 +1,54 @@ -/* Custom styles for the application */ -body { - font-family: system-ui, -apple-system, sans-serif; +:root { + --primary-color: #4F46E5; + --secondary-color: #10B981; + --accent-color: #F59E0B; + --bg-color: #F3F4F6; + --text-color: #111827; + --font-family-headings: 'Poppins', sans-serif; + --font-family-body: 'Inter', sans-serif; } + +body { + background-color: var(--bg-color); + color: var(--text-color); + font-family: var(--font-family-body); +} + +h1, h2, h3, h4, h5, h6 { + font-family: var(--font-family-headings); +} + +.bg-primary { + background-color: var(--primary-color) !important; +} + +.btn-primary { + background-color: var(--primary-color); + border-color: var(--primary-color); +} + +.btn-primary:hover { + opacity: 0.9; + background-color: var(--primary-color); + border-color: var(--primary-color); +} + +.btn-secondary { + background-color: var(--secondary-color); + border-color: var(--secondary-color); +} + +.btn-secondary:hover { + opacity: 0.9; + background-color: var(--secondary-color); + border-color: var(--secondary-color); +} + +.text-accent { + color: var(--accent-color); +} + +.table { + --bs-table-bg: #fff; + --bs-table-striped-bg: #f9f9f9; +} \ No newline at end of file diff --git a/staticfiles/css/custom.css b/staticfiles/css/custom.css index 108056f..a3eb3be 100644 --- a/staticfiles/css/custom.css +++ b/staticfiles/css/custom.css @@ -1,21 +1,54 @@ - :root { - --bg-color-start: #6a11cb; - --bg-color-end: #2575fc; - --text-color: #ffffff; - --card-bg-color: rgba(255, 255, 255, 0.01); - --card-border-color: rgba(255, 255, 255, 0.1); + --primary-color: #4F46E5; + --secondary-color: #10B981; + --accent-color: #F59E0B; + --bg-color: #F3F4F6; + --text-color: #111827; + --font-family-headings: 'Poppins', sans-serif; + --font-family-body: 'Inter', sans-serif; } + body { - margin: 0; - font-family: 'Inter', sans-serif; - background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end)); + background-color: var(--bg-color); color: var(--text-color); - display: flex; - justify-content: center; - align-items: center; - min-height: 100vh; - text-align: center; - overflow: hidden; - position: relative; + font-family: var(--font-family-body); } + +h1, h2, h3, h4, h5, h6 { + font-family: var(--font-family-headings); +} + +.bg-primary { + background-color: var(--primary-color) !important; +} + +.btn-primary { + background-color: var(--primary-color); + border-color: var(--primary-color); +} + +.btn-primary:hover { + opacity: 0.9; + background-color: var(--primary-color); + border-color: var(--primary-color); +} + +.btn-secondary { + background-color: var(--secondary-color); + border-color: var(--secondary-color); +} + +.btn-secondary:hover { + opacity: 0.9; + background-color: var(--secondary-color); + border-color: var(--secondary-color); +} + +.text-accent { + color: var(--accent-color); +} + +.table { + --bs-table-bg: #fff; + --bs-table-striped-bg: #f9f9f9; +} \ No newline at end of file