From e17a272296f796b0afc398f1e085ed152a9eed17 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Tue, 17 Feb 2026 13:59:34 +0000 Subject: [PATCH] Autosave: 20260217-135934 --- core/__pycache__/admin.cpython-311.pyc | Bin 212 -> 1971 bytes core/__pycache__/models.cpython-311.pyc | Bin 209 -> 5376 bytes core/__pycache__/urls.cpython-311.pyc | Bin 347 -> 1768 bytes core/__pycache__/views.cpython-311.pyc | Bin 1364 -> 9426 bytes core/admin.py | 22 +- core/migrations/0001_initial.py | 58 ++++ .../__pycache__/0001_initial.cpython-311.pyc | Bin 0 -> 3610 bytes core/models.py | 62 +++- core/templates/base.html | 98 ++++++- core/templates/core/auth/login.html | 37 +++ core/templates/core/dashboard/index.html | 167 +++++++++++ .../core/dashboard/product_form.html | 74 +++++ core/templates/core/dashboard/shop_form.html | 54 ++++ core/templates/core/index.html | 274 +++++++++--------- core/templates/core/product_detail.html | 105 +++++++ core/templates/core/shop_detail.html | 83 ++++++ core/templates/core/shop_list.html | 47 +++ core/urls.py | 25 +- core/views.py | 180 +++++++++++- static/css/custom.css | 215 +++++++++++++- 20 files changed, 1323 insertions(+), 178 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/auth/login.html create mode 100644 core/templates/core/dashboard/index.html create mode 100644 core/templates/core/dashboard/product_form.html create mode 100644 core/templates/core/dashboard/shop_form.html create mode 100644 core/templates/core/product_detail.html create mode 100644 core/templates/core/shop_detail.html create mode 100644 core/templates/core/shop_list.html diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index a5ed392d6714413db63120e4233d2e96cbadb5de..2b46b3b9ee098bd1155caa4b9ba8c7c218541582 100644 GIT binary patch literal 1971 zcma)6&ube;6rR~1(#n=1*Rm7GEvZWq(rp_HTAI*ON{b0?X=4hx?PXc-j_j3J+ReJiZ5ce8{WQC8=9@R~eQ*9O zmBt7(hyUu&tAzZEFImeC1}E=OLUxEpJQ|P&wJ0T?;;DhsP%X8gSz1H4bV?M$Xgym) zn7Rk6_TlL_g?vLi?K$yun3d1I?!lh>@budr{OxBi#4^q?Y9knPz?i=>W8oa5K7!Ez z#=?~u$Gov8#2kNxUYk_vj@R&;ukh5SDvbpvX3HVpklK@#Fp~KndFUl>><-Te17+}X zG7Ezp!iYsZVksWARE)AuEzQ$l4_%fry038)Q;}NJX)vjYAX(<)u=*wCn9W6)YuGj# zZCj4nb^~?|a9p(Qr->5`EXBYVvF-UH3Y-mDi8zbGC<(x4&#w6_@We}Ug5JHpUtI|s ztePw(%{ZyDXUt9FkXP43zA7TeWmPxiteT#EKHA^~Sd)SV12G5C9{!Fhx7$A)zWv_r zXPw#m9qmTH^Gdd4bZkBV^Us$=XOq+@D9f<)P4bLdxinS<40u0IS{f9ohwDwoWqEzY ziG>qIb~9-#!G|%Iv-HSLoCc8>VJ}w)$Qo)IHF~lJ@EhGBEv25>h$yybeW>!5VrTgz z@lfT2oK^NN#^pk5(U#IuTiPC2_lGl})(D)4Vp5f8RceV~oZo=eQWr^t2N2F0!yL1~ z%z+wMP?LGio+eDhQVo~tQmci$A#?7E(_Chp@qALGw=RU++5iD?jNJ{OMWZ=w=w&dG5h<&-GvuZFV+r> z2VLVqC+lgB%{(vRPRPg02onfzA>i(^H1N)4L15b^<#*t#zyN>M_whPTML?B_Zvnui z>~~aobVgl0P1PUv$km`PLZluoLiF!^fkJVro(4s#dpe{kCyRp`?`tpD*PbS@{0%p| z4)looE`tQdp}Q&zzOWrP_ScxH^7mmAZX$eyfMuO3a?#9nY9YJ$yyLPvR~>7OXZosw_gdCO>I^e@R8+x6x2K=q+BOd8%`Uy!QxrPiBNt)&QFrRjF&a)0j#Z+}4(A(0nMhf*13KNM z(>*0mK}Z*2TklTH9i!nC0a>mO=TBxV`2#xBr87N6MPDw$_NU#-?PD~YA|MO+etv$M G)&Bt#%eW8# delta 148 zcmdnYe}yq+IWI340}xFAk)LS~q#uJgFu(+5d=>&SrZc24q%h_%s&fIr#B<{e8UJu+ zOo+*@{D9P~lvYS>1rn^p1EQgu2Og@5M;>|DhjBGhqmfp9=u_T;!b8PNd(Iu(vCWVA zr>ec4Idkv1=l-Ajopb!#SS-px`flS_`r`=4{RIoPBvdn-_aSqO(>RScxGbOIdCdC^ zU)G=Uv%KF3WQCN#@&O~53i-GXIZe31X+gqY4%a$-;ODq+;q_7~!lXhV6@G(Mlu1QE zD*6T~Q436R32_~}PVjCpo7ae8LN0L8Bow|O(X&T@OmjFFo|HTtob$nYT$tnWZI;NhVT+M z!)uWn;p&D&VX0zEPf<;}!KK6{?i!zxV4*QLd|I_gCQldEH5lz7??$ugHN_ygj5Ry; z(B}q=IsHnJxWcrd=H}K9fl%q-*?i7AHBZcZmdJWKpOe#uYMSzXlFTHB95A8{F)Cm#s6Y!CZ7^Zb)(gZ>BO8!1l+Kq;NB>T8&wooL(#yzq$pR4 zs!^@!x=QGD-Xxx6!6;JIc*xNK7?JJ(;s&s1`a{UJ!)x{cDc65%I|uFXcJJ}p?1%a$ zwL!JOcXJTPEzYVf3QC|R^-{B%OmY<047%<&ElS_QJWsd5$HW%0H?&5>Up`}(Wpuk7#+HpxVc?uI(L2gzO}I6*gZdRC=pbz*32KsPc8 zI_8zTu|9y;ifI7FRnm8m8LKK)niz(nz$E*D%O-h}O_HLDGlF-i zC@&lUeSC>LL*DbPiXboSM7h@!?|5-FX?W|Yj&_2#B10!@OaG5C~3Y^WIdOx_%R=yxN1+WXN0TYXcv5s0> z>OPyNS=Bl&A2~F7@X&iBhmRZ`J(ln>%%_OwU|%E^P*2I_=M`1cnr`p^2eyW`6i$WcncO&8paBqbL#Izoo<22p#uf7OIYQ|$c7V7?-$lXzC^7}cnE{e3YQ#)a zy{H$u3YN4RyirHx}i?K1#s3|>Lm5Qb*VJfCt9-bkTQS>9| zdq5iD>o78rAn=>$gEhjJv}5V4Bkj1Yt<0?Eo*uQO$%-`TNR#C=brAbUkgapq&3#Vi zu9a@PGg;|OI-SY#c)f${73)YaQ=#vr{|9EJ>h3Y5MX;d%RiusAhOdGxJFz<0Hti|8Dh%sU!y&}w8{?HN$MX(^yN!-0 zl>LqIix#*O(1dS7U-DM%=0ks5@yWfK2L#-$w8%H>>6bn&*ff5T9PMwvrs;SRnYm;cYdZN@eYgq;J`0((&nuLI-6g+{E-Uo>ggi2sIJ&#u?P(4i` zzNChsPrE`vh32ksrI?3~K8Dr79l^`!hO)#oLAl*H$)zD2*OV&5#2tso%5%_TbvtC} zxw+C?wZm&-#NFfuhk1`a?f!0CW7$@Tqs}#Q8uLq`@B8Gt zLx1WU`eWbF%B4!*VW;o#QhY6b0V6U;K4!-+!1H9l``Y0Po~4#wWvS_Dm>DyGbPRKs zkf3V0;mI>o%EZM_K5@h8YP|j`t4+^hix07dH0A+?7gKzW{Ev_?FraXyb2$k6i5G%^ zYiQ-ubFTE0eBK~x&NJ^3-Bi@Hr9;p*j?F(of&l6TBZz1a1zQXB3*^1hpif{8lDFYC zC%}F*8g#KAy6VK`d%cf7`@QmX#QtK|j_Z}U z?!@)-M|ErcPni2k=N_kX4_JC>0KJHTl|zqJTRK^hPCC*_@F1jqWcS-|k3I>&c+&Zb zbl#E9V@&70j2oXfvb>5$>Uj;g!3oKYXqVMoCZE)%y%4jnT82QK;M0i*X9;rG3`|Hm{7ML2BE z{4(44TX@K?*b( zZ?Wa(r=;c-`)M-W;!Md(%uCPLOGzqX21>4E_zY6>OHV%|KQ~psG^sSNq*On(A~m_R zB)>?%JijQrxF9h(RX;huC{-U~j9x+IFAf_ZyEG@&u80Guoe_wOWr4&8W=2NF8w@fR Ku%RM0pb7xLi8T)Z diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc index 5a69659f6c6e0ae848e54157af197c543a09315f..969d3640ffe4e0bdfc6155bdcb994b2ca942d4e1 100644 GIT binary patch literal 1768 zcmcgsJ#5=X6h6vNKh$q*sj1UCRvaK`gtR^w1`1R$v?!2)qNoR39f%YHtvg7HNl`tL zO`-xtMvoo}G^3`}MLcB8*sUe~C}}8xs78`BMN%i}M+*o&7WdguOonEN9?N8@ zPI9qKo~B75mMPLKDaA4uXpSt#GD|d1%CSs^7RX1j%tcxxAICDwv_vk&GM~`ooeT5a zC-aKW0re!Go~%3)C-7L@XMBi(@47E!K(%ZHeaEIzal{icGd%G}>_CfjG6vYg&vh{u(#!zea=ua6b7-uG-vRH)!l zdt{j&?Z{F^Nkxv+;^Fun76$r|-t#&mvqvMTCD3ncl_*E{W5In)EFhftq^*NzSR1eFaJul;DWy~9Uyo`f#J1n>P z?Jfrr011I8g~LlnUx$_2^UB7v%Er?cuWSUBW>{(dd7Z;<0J|aVPS+Moi3d6PV^wj; FuK^SS+pz!u delta 266 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 - + - {% block title %}Knowledge Base{% endblock %} - {% if project_description %} - - - - {% endif %} - {% if project_image_url %} - - - {% endif %} + + {% block title %}Marketplace UMKM Pemagarsari{% endblock %} + + + + + + + + + + + {% load static %} - + + {% block head %}{% endblock %} - {% block content %}{% endblock %} + + + +
+ {% block content %}{% endblock %} +
+ + +
+
+
UMKM Desa Pemagarsari
+

Membangun ekonomi desa melalui digitalisasi marketplace mandiri.

+ +
+

© 2026 Desa Pemagarsari. Powered by Flatlogic.

+
+
+ + + diff --git a/core/templates/core/auth/login.html b/core/templates/core/auth/login.html new file mode 100644 index 0000000..c7fb9b3 --- /dev/null +++ b/core/templates/core/auth/login.html @@ -0,0 +1,37 @@ +{% extends 'base.html' %} + +{% block title %}Masuk - Marketplace UMKM Pemagarsari{% endblock %} + +{% block content %} +
+
+
+
+
+

Selamat Datang

+

Masuk untuk mengelola toko Anda

+
+ +
+ {% csrf_token %} +
+ + +
+
+ + +
+ +
+ +
+

Belum punya akun?
Silakan hubungi Admin Desa untuk pendaftaran akun Penjual.

+
+
+
+
+
+{% endblock %} diff --git a/core/templates/core/dashboard/index.html b/core/templates/core/dashboard/index.html new file mode 100644 index 0000000..f5bf0ab --- /dev/null +++ b/core/templates/core/dashboard/index.html @@ -0,0 +1,167 @@ +{% extends 'base.html' %} + +{% block title %}Dashboard Penjual - UMKM Pemagarsari{% endblock %} + +{% block content %} +
+
+
+

Dashboard Penjual

+

Kelola toko dan produk Anda di sini.

+
+ +
+ + +
+
+
+
+
+ +
+ Toko Anda +
+

{{ shops.count }}

+
+
+
+
+
+
+ +
+ Total Produk +
+

{{ products.count }}

+
+
+
+ + +
+
+
Toko Saya
+
+
+ + + + + + + + + + {% for shop in shops %} + + + + + + {% empty %} + + + + {% endfor %} + +
TokoWhatsAppAksi
+
+
+ {% if shop.logo %} + + {% else %} +
+ +
+ {% endif %} +
+ {{ shop.name }} +
+
{{ shop.whatsapp_number }} + + Edit + +
+

Anda belum memiliki toko.

+
+
+
+ + +
+
+
Produk Saya
+
+
+ + + + + + + + + + + + + {% for product in products %} + + + + + + + + + {% empty %} + + + + {% endfor %} + +
ProdukTokoKategoriHargaStokAksi
+
+
+ {% if product.image %} + + {% else %} +
+ +
+ {% endif %} +
+ {{ product.name }} +
+
{{ product.shop.name }}{{ product.category.name }}Rp {{ product.price|floatformat:0 }}{{ product.stock }} + +
+

Anda belum menambahkan produk.

+ Tambah Sekarang +
+
+
+
+{% endblock %} diff --git a/core/templates/core/dashboard/product_form.html b/core/templates/core/dashboard/product_form.html new file mode 100644 index 0000000..ff1fe5d --- /dev/null +++ b/core/templates/core/dashboard/product_form.html @@ -0,0 +1,74 @@ +{% extends 'base.html' %} + +{% block title %}{{ title }} - Dashboard{% endblock %} + +{% block content %} +
+
+
+
+
+ + + +

{{ title }}

+
+ +
+ {% csrf_token %} + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + {% if product.image %} +
+ +
+ {% endif %} + + Kosongkan jika tidak ingin mengubah foto. +
+
+ +
+
+
+
+
+
+
+{% endblock %} diff --git a/core/templates/core/dashboard/shop_form.html b/core/templates/core/dashboard/shop_form.html new file mode 100644 index 0000000..fad7e3d --- /dev/null +++ b/core/templates/core/dashboard/shop_form.html @@ -0,0 +1,54 @@ +{% extends 'base.html' %} + +{% block title %}{{ title }} - Dashboard{% endblock %} + +{% block content %} +
+
+
+
+
+ + + +

{{ title }}

+
+ +
+ {% csrf_token %} + +
+
+ + +
+
+ + +
+
+ + + Gunakan format internasional tanpa tanda plus (+). Contoh: 628123456789 +
+
+ + {% if shop.logo %} +
+ +
+ {% endif %} + +
+
+ +
+
+
+
+
+
+
+{% endblock %} diff --git a/core/templates/core/index.html b/core/templates/core/index.html index faec813..c27cdbd 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -1,145 +1,135 @@ -{% extends "base.html" %} - -{% block title %}{{ project_name }}{% endblock %} - -{% block head %} - - - - -{% endblock %} +{% extends 'base.html' %} +{% load static %} {% block content %} -
-
-

Analyzing your requirements and generating your app…

-
- Loading… + +
+
+
+
+ Digitalisasi UMKM Desa +

Majukan Ekonomi Desa Pemagarsari

+

Temukan produk unggulan dari warga desa kami. Pesan langsung via WhatsApp tanpa ribet, dukung produk lokal hari ini.

+ + +
+ +
+ +
+ Jelajahi Produk + {% if query or selected_category %} + Reset Filter + {% endif %} +
+
+
+
+
+
+ Pasar Tradisional Desa +
+
+
+
-

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 + + + +
+
+
+

Kategori Populer

+

Cari produk berdasarkan kategori

+
+
+ + {% for category in categories %} + + {% endfor %} +
+
+
+ + +
+
+
+

Produk Terbaru

+

Produk unggulan dari para pengrajin dan pedagang desa

+
+
+ {% for product in featured_products %} +
+
+
+ {% if product.image %} + {{ product.name }} + {% else %} + + {% endif %} +
+
+
+ {{ product.shop.name }} + {{ product.category.name }} +
+
+ {{ product.name }} +
+
+ Rp {{ product.price|floatformat:0 }} + + Pesan + +
+
+
+
+ {% empty %} +
+
+ +

Belum ada produk untuk ditampilkan.

+ Tambah Produk Pertama +
+
+ {% endfor %} +
+
+
+ + +
+
+
+
+

Punya Usaha di Desa Pemagarsari?

+

Daftarkan toko Anda dan mulai jualan online hari ini. Mudah, gratis, dan langsung ke WhatsApp!

+ +
+
+
+
+{% endblock %} diff --git a/core/templates/core/product_detail.html b/core/templates/core/product_detail.html new file mode 100644 index 0000000..c674a82 --- /dev/null +++ b/core/templates/core/product_detail.html @@ -0,0 +1,105 @@ +{% extends 'base.html' %} +{% load static %} + +{% block title %}{{ product.name }} - UMKM Pemagarsari{% endblock %} + +{% block content %} +
+
+ + +
+
+
+
+ {% if product.image %} + {{ product.name }} + {% else %} + + {% endif %} +
+
+
+
+
+ {{ product.category.name }} +

{{ product.name }}

+
+
+ +
+
+

Dijual oleh

+
{{ product.shop.name }}
+
+
+ +

Rp {{ product.price|floatformat:0 }}

+ +
+
Deskripsi Produk
+

{{ product.description|linebreaks }}

+
+ +
+
+ +
Cara Pemesanan
+
+

Klik tombol di bawah untuk terhubung langsung dengan WhatsApp penjual. Pesan otomatis akan terisi dengan detail produk ini.

+
+ + +
+
+
+
+
+ + +
+
+

Dukung UMKM Lainnya

+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% endblock %} diff --git a/core/templates/core/shop_detail.html b/core/templates/core/shop_detail.html new file mode 100644 index 0000000..f22f1e3 --- /dev/null +++ b/core/templates/core/shop_detail.html @@ -0,0 +1,83 @@ +{% extends 'base.html' %} + +{% block title %}{{ shop.name }} - UMKM Pemagarsari{% endblock %} + +{% block content %} +
+
+ +
+
+ +
+
+
+
+ {% if shop.logo %} + {{ shop.name }} + {% else %} + + {% endif %} +
+
+
+

{{ shop.name }}

+

{{ shop.description }}

+
+
+ + {{ shop.whatsapp_number }} +
+
+ + {{ products.count }} Produk +
+
+
+ +
+
+ + +
+

Produk dari {{ shop.name }}

+
+ +
+ {% for product in products %} +
+
+
+ {% if product.image %} + {{ product.name }} + {% else %} + + {% endif %} +
+
+ {{ product.category.name }} +
+ {{ product.name }} +
+
+ Rp {{ product.price|floatformat:0 }} + + Pesan + +
+
+
+
+ {% empty %} +
+

Toko ini belum menambahkan produk.

+
+ {% endfor %} +
+
+
+{% endblock %} diff --git a/core/templates/core/shop_list.html b/core/templates/core/shop_list.html new file mode 100644 index 0000000..8907d0d --- /dev/null +++ b/core/templates/core/shop_list.html @@ -0,0 +1,47 @@ +{% extends 'base.html' %} + +{% block title %}Daftar Toko UMKM - Pemagarsari{% endblock %} + +{% block content %} +
+
+
+

Para Pelaku UMKM

+

Dukung usaha warga Desa Pemagarsari dengan berbelanja langsung dari toko mereka.

+
+ +
+ {% for shop in shops %} +
+
+
+
+ {% if shop.logo %} + {{ shop.name }} + {% else %} + + {% endif %} +
+
+
+
{{ shop.name }}
+

{{ shop.description|default:"Pelaku UMKM Desa Pemagarsari" }}

+
+ + {{ shop.whatsapp_number }} +
+ Kunjungi Toko +
+
+
+
+
+ {% empty %} +
+

Belum ada toko yang terdaftar.

+
+ {% endfor %} +
+
+
+{% endblock %} diff --git a/core/urls.py b/core/urls.py index 6299e3d..35c72d4 100644 --- a/core/urls.py +++ b/core/urls.py @@ -1,7 +1,26 @@ -from django.urls import path - -from .views import home +from django.urls import path, include +from django.contrib.auth import views as auth_views +from .views import ( + home, product_detail, shop_list, shop_detail, + dashboard, shop_add, shop_edit, + product_add, product_edit, product_delete +) urlpatterns = [ path("", home, name="home"), + path("shops/", shop_list, name="shop_list"), + path("shop//", shop_detail, name="shop_detail"), + path("product//", product_detail, name="product_detail"), + + # Dashboard + path("dashboard/", dashboard, name="dashboard"), + path("dashboard/shop/add/", shop_add, name="shop_add"), + path("dashboard/shop/edit//", shop_edit, name="shop_edit"), + path("dashboard/product/add/", product_add, name="product_add"), + path("dashboard/product/edit//", product_edit, name="product_edit"), + path("dashboard/product/delete//", product_delete, name="product_delete"), + + # Auth + path("login/", auth_views.LoginView.as_view(template_name="core/auth/login.html"), name="login"), + path("logout/", auth_views.LogoutView.as_view(next_page="home"), name="logout"), ] diff --git a/core/views.py b/core/views.py index c9aed12..1b1c6fd 100644 --- a/core/views.py +++ b/core/views.py @@ -2,24 +2,174 @@ import os import platform from django import get_version as django_version -from django.shortcuts import render +from django.shortcuts import render, get_object_or_404, redirect +from django.contrib.auth.decorators import login_required from django.utils import timezone - +from .models import Category, Shop, Product 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() - + """Render the marketplace landing page with search and filter.""" + categories = Category.objects.all() + + # Get query parameters + query = request.GET.get('q', '') + category_slug = request.GET.get('category', '') + + products = Product.objects.filter(is_active=True).order_by('-created_at') + + if query: + products = products.filter(name__icontains=query) + + if category_slug: + products = products.filter(category__slug=category_slug) + + featured_products = products[:12] # Show more products on home + 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", ""), + "categories": categories, + "featured_products": featured_products, + "query": query, + "selected_category": category_slug, + "current_time": timezone.now(), } return render(request, "core/index.html", context) + +def product_detail(request, slug): + """Render the product detail page.""" + product = get_object_or_404(Product, slug=slug, is_active=True) + return render(request, "core/product_detail.html", {"product": product}) + +def shop_list(request): + """Render a list of all shops.""" + shops = Shop.objects.all().order_by('name') + return render(request, "core/shop_list.html", {"shops": shops}) + +def shop_detail(request, slug): + """Render a specific shop's page with its products.""" + shop = get_object_or_404(Shop, slug=slug) + products = Product.objects.filter(shop=shop, is_active=True) + return render(request, "core/shop_detail.html", {"shop": shop, "products": products}) + +@login_required +def dashboard(request): + """Seller dashboard showing their shops and products.""" + shops = Shop.objects.filter(owner=request.user) + products = Product.objects.filter(shop__owner=request.user).order_by('-created_at') + + context = { + "shops": shops, + "products": products, + } + return render(request, "core/dashboard/index.html", context) + +@login_required +def shop_add(request): + """Add a new shop.""" + if request.method == "POST": + name = request.POST.get('name') + description = request.POST.get('description') + whatsapp_number = request.POST.get('whatsapp_number') + logo = request.FILES.get('logo') + + Shop.objects.create( + owner=request.user, + name=name, + description=description, + whatsapp_number=whatsapp_number, + logo=logo + ) + return redirect('dashboard') + + return render(request, "core/dashboard/shop_form.html", { + "title": "Tambah Toko Baru" + }) + +@login_required +def shop_edit(request, pk): + """Edit an existing shop.""" + shop = get_object_or_404(Shop, pk=pk, owner=request.user) + + if request.method == "POST": + shop.name = request.POST.get('name') + shop.description = request.POST.get('description') + shop.whatsapp_number = request.POST.get('whatsapp_number') + if request.FILES.get('logo'): + shop.logo = request.FILES.get('logo') + + shop.save() + return redirect('dashboard') + + return render(request, "core/dashboard/shop_form.html", { + "shop": shop, + "title": "Edit Toko" + }) + +@login_required +def product_add(request): + """Add a new product.""" + shops = Shop.objects.filter(owner=request.user) + categories = Category.objects.all() + + if request.method == "POST": + shop_id = request.POST.get('shop') + category_id = request.POST.get('category') + name = request.POST.get('name') + description = request.POST.get('description') + price = request.POST.get('price') + stock = request.POST.get('stock') + image = request.FILES.get('image') + + shop = get_object_or_404(Shop, id=shop_id, owner=request.user) + category = get_object_or_404(Category, id=category_id) + + Product.objects.create( + shop=shop, + category=category, + name=name, + description=description, + price=price, + stock=stock, + image=image + ) + return redirect('dashboard') + + return render(request, "core/dashboard/product_form.html", { + "shops": shops, + "categories": categories, + "title": "Tambah Produk Baru" + }) + +@login_required +def product_edit(request, pk): + """Edit an existing product.""" + product = get_object_or_404(Product, pk=pk, shop__owner=request.user) + shops = Shop.objects.filter(owner=request.user) + categories = Category.objects.all() + + if request.method == "POST": + product.shop = get_object_or_404(Shop, id=request.POST.get('shop'), owner=request.user) + product.category = get_object_or_404(Category, id=request.POST.get('category')) + product.name = request.POST.get('name') + product.description = request.POST.get('description') + product.price = request.POST.get('price') + product.stock = request.POST.get('stock') + if request.FILES.get('image'): + product.image = request.FILES.get('image') + + product.save() + return redirect('dashboard') + + return render(request, "core/dashboard/product_form.html", { + "product": product, + "shops": shops, + "categories": categories, + "title": "Edit Produk" + }) + +@login_required +def product_delete(request, pk): + """Delete a product.""" + product = get_object_or_404(Product, pk=pk, shop__owner=request.user) + if request.method == "POST": + product.delete() + return redirect('dashboard') diff --git a/static/css/custom.css b/static/css/custom.css index 925f6ed..9d896f8 100644 --- a/static/css/custom.css +++ b/static/css/custom.css @@ -1,4 +1,213 @@ -/* Custom styles for the application */ -body { - font-family: system-ui, -apple-system, sans-serif; +:root { + --emerald-primary: #10B981; + --emerald-dark: #059669; + --forest-deep: #064E3B; + --amber-warm: #F59E0B; + --glass-bg: rgba(255, 255, 255, 0.8); + --soft-shadow: 0 10px 30px rgba(0, 0, 0, 0.05); +} + +body { + font-family: 'Inter', sans-serif; + background-color: #f8fafc; + color: #1e293b; +} + +h1, h2, h3, h4, .navbar-brand { + font-family: 'Poppins', sans-serif; +} + +.text-emerald { + color: var(--emerald-primary); +} + +.bg-emerald { + background-color: var(--emerald-primary); +} + +.btn-emerald { + background-color: var(--emerald-primary); + border-color: var(--emerald-primary); + color: white; + font-weight: 600; + transition: all 0.3s ease; +} + +.btn-emerald:hover { + background-color: var(--emerald-dark); + border-color: var(--emerald-dark); + color: white; + transform: translateY(-2px); + box-shadow: 0 5px 15px rgba(16, 185, 129, 0.4); +} + +.navbar { + background: var(--glass-bg); + backdrop-filter: blur(10px); + border-bottom: 1px solid rgba(0, 0, 0, 0.05); + padding: 1rem 0; +} + +.navbar-brand { + font-size: 1.5rem; + color: var(--forest-deep); +} + +/* Hero Section */ +.hero-section { + padding: 100px 0; + background: linear-gradient(135deg, #ecfdf5 0%, #ffffff 100%); + position: relative; + overflow: hidden; +} + +.hero-section::after { + content: ""; + position: absolute; + top: -10%; + right: -5%; + width: 400px; + height: 400px; + background: radial-gradient(circle, rgba(16, 185, 129, 0.1) 0%, rgba(255, 255, 255, 0) 70%); + z-index: 0; +} + +.hero-title { + font-size: 3.5rem; + font-weight: 800; + line-height: 1.2; + color: var(--forest-deep); +} + +/* Cards */ +.category-card { + background: white; + border: none; + border-radius: 20px; + padding: 2rem; + text-align: center; + transition: all 0.3s ease; + box-shadow: var(--soft-shadow); + text-decoration: none; + display: block; +} + +.category-card:hover { + transform: translateY(-5px); + box-shadow: 0 15px 40px rgba(0, 0, 0, 0.1); +} + +.category-icon { + width: 60px; + height: 60px; + background: #ecfdf5; + color: var(--emerald-primary); + border-radius: 15px; + display: flex; + align-items: center; + justify-content: center; + margin: 0 auto 1.5rem; + font-size: 1.5rem; +} + +.product-card { + background: white; + border: none; + border-radius: 20px; + overflow: hidden; + transition: all 0.3s ease; + box-shadow: var(--soft-shadow); + height: 100%; +} + +.product-card:hover { + transform: translateY(-5px); + box-shadow: 0 15px 40px rgba(0, 0, 0, 0.1); +} + +.product-img-wrapper { + height: 220px; + background: #f1f5f9; + display: flex; + align-items: center; + justify-content: center; + overflow: hidden; +} + +.product-img-wrapper i { + font-size: 4rem; + color: #cbd5e1; +} + +.product-price { + color: var(--emerald-primary); + font-weight: 700; + font-size: 1.25rem; +} + +.shop-badge { + background: #f1f5f9; + color: #64748b; + padding: 4px 12px; + border-radius: 100px; + font-size: 0.75rem; + font-weight: 600; +} + +/* WhatsApp Button */ +.btn-whatsapp { + background-color: #25D366; + color: white; + font-weight: 600; + border-radius: 12px; +} + +.btn-whatsapp:hover { + background-color: #128C7E; + color: white; +} + +.transform-hover { + transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1); +} + +.transform-hover:hover { + transform: scale(1.02) translateY(-10px) rotate(1deg); + box-shadow: 0 25px 50px -12px rgba(16, 185, 129, 0.25) !important; +} + +.transition-all { + transition: all 0.3s ease; +} + +/* Search Box */ +.search-box { + border: 1px solid rgba(0,0,0,0.05); + transition: all 0.3s ease; +} + +.search-box:focus-within { + border-color: var(--emerald-primary); + box-shadow: 0 0 0 4px rgba(16, 185, 129, 0.1) !important; +} + +/* Categories Active State */ +.category-card.active { + background: var(--forest-deep); + color: white !important; +} + +.category-card.active .category-icon { + background: rgba(255, 255, 255, 0.1); + color: white; +} + +.category-card.active h6 { + color: white !important; +} + +@media (max-width: 768px) { + .hero-title { + font-size: 2.5rem; + } }