diff --git a/assets/images/banner.png b/assets/images/banner.png deleted file mode 100644 index ffed682..0000000 Binary files a/assets/images/banner.png and /dev/null differ diff --git a/config/__pycache__/settings.cpython-311.pyc b/config/__pycache__/settings.cpython-311.pyc index 181a635..96bce55 100644 Binary files a/config/__pycache__/settings.cpython-311.pyc and b/config/__pycache__/settings.cpython-311.pyc differ diff --git a/config/__pycache__/urls.cpython-311.pyc b/config/__pycache__/urls.cpython-311.pyc index 5264a83..0b85e94 100644 Binary files a/config/__pycache__/urls.cpython-311.pyc and b/config/__pycache__/urls.cpython-311.pyc differ diff --git a/config/settings.py b/config/settings.py index c90f1e1..291d043 100644 --- a/config/settings.py +++ b/config/settings.py @@ -18,7 +18,7 @@ BASE_DIR = Path(__file__).resolve().parent.parent load_dotenv(BASE_DIR.parent / ".env") SECRET_KEY = os.getenv("DJANGO_SECRET_KEY", "change-me") -DEBUG = False +DEBUG = os.getenv("DJANGO_DEBUG", "true").lower() == "true" ALLOWED_HOSTS = [ "127.0.0.1", @@ -155,9 +155,6 @@ STATICFILES_DIRS = [ BASE_DIR / 'node_modules', ] -MEDIA_URL = '/media/' -MEDIA_ROOT = BASE_DIR / 'media' - # Email EMAIL_BACKEND = os.getenv( "EMAIL_BACKEND", @@ -183,6 +180,3 @@ if EMAIL_USE_SSL: # https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' - -LOGIN_REDIRECT_URL = 'dashboard' -LOGOUT_REDIRECT_URL = 'home' diff --git a/config/urls.py b/config/urls.py index 4824951..bcfc074 100644 --- a/config/urls.py +++ b/config/urls.py @@ -24,6 +24,6 @@ urlpatterns = [ path("", include("core.urls")), ] -# Always serve media files in dev environment -urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) -urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) +if settings.DEBUG: + urlpatterns += static("/assets/", document_root=settings.BASE_DIR / "assets") + urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index 2b46b3b..a5ed392 100644 Binary files a/core/__pycache__/admin.cpython-311.pyc and b/core/__pycache__/admin.cpython-311.pyc differ diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index 7aa2434..e061640 100644 Binary files a/core/__pycache__/models.cpython-311.pyc and b/core/__pycache__/models.cpython-311.pyc differ diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc index 969d364..5a69659 100644 Binary files a/core/__pycache__/urls.cpython-311.pyc and b/core/__pycache__/urls.cpython-311.pyc differ diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index f65526a..2a36fd6 100644 Binary files a/core/__pycache__/views.cpython-311.pyc and b/core/__pycache__/views.cpython-311.pyc differ diff --git a/core/admin.py b/core/admin.py index 3dd187c..8c38f3f 100644 --- a/core/admin.py +++ b/core/admin.py @@ -1,23 +1,3 @@ from django.contrib import admin -from .models import Category, Shop, Product -@admin.register(Category) -class CategoryAdmin(admin.ModelAdmin): - list_display = ('name', 'slug') - prepopulated_fields = {'slug': ('name',)} - -@admin.register(Shop) -class ShopAdmin(admin.ModelAdmin): - list_display = ('name', 'owner', 'whatsapp_number', 'created_at') - prepopulated_fields = {'slug': ('name',)} - - def save_model(self, request, obj, form, change): - if not obj.pk: - obj.owner = request.user - super().save_model(request, obj, form, change) - -@admin.register(Product) -class ProductAdmin(admin.ModelAdmin): - list_display = ('name', 'shop', 'category', 'price', 'stock', 'is_active') - list_filter = ('shop', 'category', 'is_active') - prepopulated_fields = {'slug': ('name',)} +# Register your models here. diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py deleted file mode 100644 index a5767a2..0000000 --- a/core/migrations/0001_initial.py +++ /dev/null @@ -1,58 +0,0 @@ -# Generated by Django 5.2.7 on 2026-02-17 04:38 - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.CreateModel( - name='Category', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=100)), - ('slug', models.SlugField(blank=True, unique=True)), - ('icon', models.CharField(default='fa-tag', help_text='FontAwesome icon class (e.g., fa-shopping-basket)', max_length=50)), - ], - options={ - 'verbose_name_plural': 'Categories', - }, - ), - migrations.CreateModel( - name='Shop', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=255)), - ('slug', models.SlugField(blank=True, unique=True)), - ('description', models.TextField(blank=True)), - ('logo', models.FileField(blank=True, null=True, upload_to='shop_logos/')), - ('whatsapp_number', models.CharField(help_text='Format: 628123456789', max_length=20)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='shops', to=settings.AUTH_USER_MODEL)), - ], - ), - migrations.CreateModel( - name='Product', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=255)), - ('slug', models.SlugField(blank=True, unique=True)), - ('description', models.TextField()), - ('price', models.DecimalField(decimal_places=2, max_digits=12)), - ('image', models.FileField(blank=True, null=True, upload_to='product_images/')), - ('stock', models.IntegerField(default=0)), - ('is_active', models.BooleanField(default=True)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('category', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='products', to='core.category')), - ('shop', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='products', to='core.shop')), - ], - ), - ] diff --git a/core/migrations/0002_alter_category_slug_alter_product_slug_and_more.py b/core/migrations/0002_alter_category_slug_alter_product_slug_and_more.py deleted file mode 100644 index 215dfcd..0000000 --- a/core/migrations/0002_alter_category_slug_alter_product_slug_and_more.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 5.2.7 on 2026-02-19 18:20 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='category', - name='slug', - field=models.SlugField(blank=True, max_length=150, unique=True), - ), - migrations.AlterField( - model_name='product', - name='slug', - field=models.SlugField(blank=True, max_length=255, unique=True), - ), - migrations.AlterField( - model_name='shop', - name='slug', - field=models.SlugField(blank=True, max_length=255, unique=True), - ), - ] diff --git a/core/migrations/__pycache__/0001_initial.cpython-311.pyc b/core/migrations/__pycache__/0001_initial.cpython-311.pyc deleted file mode 100644 index 20f1236..0000000 Binary files a/core/migrations/__pycache__/0001_initial.cpython-311.pyc and /dev/null differ diff --git a/core/migrations/__pycache__/0002_alter_category_slug_alter_product_slug_and_more.cpython-311.pyc b/core/migrations/__pycache__/0002_alter_category_slug_alter_product_slug_and_more.cpython-311.pyc deleted file mode 100644 index 48195cf..0000000 Binary files a/core/migrations/__pycache__/0002_alter_category_slug_alter_product_slug_and_more.cpython-311.pyc and /dev/null differ diff --git a/core/models.py b/core/models.py index e149432..71a8362 100644 --- a/core/models.py +++ b/core/models.py @@ -1,63 +1,3 @@ from django.db import models -from django.contrib.auth.models import User -from django.utils.text import slugify -import urllib.parse -class Category(models.Model): - name = models.CharField(max_length=100) - slug = models.SlugField(max_length=150, unique=True, blank=True) - icon = models.CharField(max_length=50, help_text="FontAwesome icon class (e.g., fa-shopping-basket)", default="fa-tag") - - def save(self, *args, **kwargs): - if not self.slug: - self.slug = slugify(self.name) - super().save(*args, **kwargs) - - class Meta: - verbose_name_plural = "Categories" - - def __str__(self): - return str(self.name) - -class Shop(models.Model): - owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='shops') - name = models.CharField(max_length=255) - slug = models.SlugField(max_length=255, unique=True, blank=True) - description = models.TextField(blank=True) - logo = models.FileField(upload_to='shop_logos/', blank=True, null=True) - whatsapp_number = models.CharField(max_length=20, help_text="Format: 628123456789") - created_at = models.DateTimeField(auto_now_add=True) - - def save(self, *args, **kwargs): - if not self.slug: - self.slug = slugify(self.name) - super().save(*args, **kwargs) - - def __str__(self): - return str(self.name) - -class Product(models.Model): - shop = models.ForeignKey(Shop, on_delete=models.CASCADE, related_name='products') - category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, related_name='products') - name = models.CharField(max_length=255) - slug = models.SlugField(max_length=255, unique=True, blank=True) - description = models.TextField() - price = models.DecimalField(max_digits=12, decimal_places=2) - image = models.FileField(upload_to='product_images/', blank=True, null=True) - stock = models.IntegerField(default=0) - is_active = models.BooleanField(default=True) - created_at = models.DateTimeField(auto_now_add=True) - - def save(self, *args, **kwargs): - if not self.slug: - self.slug = slugify(self.name) - super().save(*args, **kwargs) - - def __str__(self): - return str(self.name) - - @property - def whatsapp_link(self): - message = f"Halo {self.shop.name}, saya tertarik dengan produk *{self.name}* seharga Rp {self.price:,.0f}. Apakah masih tersedia?" - encoded_message = urllib.parse.quote(message) - return f"https://wa.me/{self.shop.whatsapp_number}?text={encoded_message}" +# Create your models here. diff --git a/core/templates/base.html b/core/templates/base.html index 07a3095..1e7e5fb 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -1,97 +1,25 @@ - + - - {% block title %}Marketplace UMKM Pemagarsari{% endblock %} - - - - - - - - - - - + {% block title %}Knowledge Base{% endblock %} + {% if project_description %} + + + + {% endif %} + {% if project_image_url %} + + + {% endif %} {% load static %} - - + {% block head %}{% endblock %} - - - -
- {% block content %}{% endblock %} -
- - - - - - + {% block content %}{% endblock %} diff --git a/core/templates/core/auth/login.html b/core/templates/core/auth/login.html deleted file mode 100644 index c3c7576..0000000 --- a/core/templates/core/auth/login.html +++ /dev/null @@ -1,37 +0,0 @@ -{% 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 deleted file mode 100644 index eb1e511..0000000 --- a/core/templates/core/dashboard/index.html +++ /dev/null @@ -1,167 +0,0 @@ -{% 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 deleted file mode 100644 index b235928..0000000 --- a/core/templates/core/dashboard/product_form.html +++ /dev/null @@ -1,74 +0,0 @@ -{% 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 deleted file mode 100644 index 0944365..0000000 --- a/core/templates/core/dashboard/shop_form.html +++ /dev/null @@ -1,54 +0,0 @@ -{% 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 a4f15ac..faec813 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -1,145 +1,145 @@ -{% extends 'base.html' %} -{% load static %} +{% extends "base.html" %} + +{% block title %}{{ project_name }}{% endblock %} + +{% block head %} + + + + +{% endblock %} {% block content %} - -
- + + +{% endblock %} \ No newline at end of file diff --git a/core/templates/core/product_detail.html b/core/templates/core/product_detail.html deleted file mode 100644 index a207791..0000000 --- a/core/templates/core/product_detail.html +++ /dev/null @@ -1,105 +0,0 @@ -{% 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 deleted file mode 100644 index a7b9b5c..0000000 --- a/core/templates/core/shop_detail.html +++ /dev/null @@ -1,83 +0,0 @@ -{% 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 deleted file mode 100644 index 390dba0..0000000 --- a/core/templates/core/shop_list.html +++ /dev/null @@ -1,47 +0,0 @@ -{% 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 35c72d4..6299e3d 100644 --- a/core/urls.py +++ b/core/urls.py @@ -1,26 +1,7 @@ -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 -) +from django.urls import path + +from .views import home 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 1b1c6fd..c9aed12 100644 --- a/core/views.py +++ b/core/views.py @@ -2,174 +2,24 @@ import os import platform from django import get_version as django_version -from django.shortcuts import render, get_object_or_404, redirect -from django.contrib.auth.decorators import login_required +from django.shortcuts import render from django.utils import timezone -from .models import Category, Shop, Product + def home(request): - """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 - + """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() + context = { - "categories": categories, - "featured_products": featured_products, - "query": query, - "selected_category": category_slug, - "current_time": timezone.now(), + "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) - -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/media/product_images/7cVv0a78syo3XkKZFUGKtRZIx9PcIRI1JDfFekt5_ahMb402.jpg b/media/product_images/7cVv0a78syo3XkKZFUGKtRZIx9PcIRI1JDfFekt5_ahMb402.jpg deleted file mode 100755 index fd6e8ae..0000000 Binary files a/media/product_images/7cVv0a78syo3XkKZFUGKtRZIx9PcIRI1JDfFekt5_ahMb402.jpg and /dev/null differ diff --git a/media/product_images/Golden_banana_chips_in_garden_sunshine_1.png b/media/product_images/Golden_banana_chips_in_garden_sunshine_1.png deleted file mode 100755 index 3f0b170..0000000 Binary files a/media/product_images/Golden_banana_chips_in_garden_sunshine_1.png and /dev/null differ diff --git a/media/product_images/Golden_banana_chips_in_wooden_bowl.png b/media/product_images/Golden_banana_chips_in_wooden_bowl.png deleted file mode 100755 index 179c757..0000000 Binary files a/media/product_images/Golden_banana_chips_in_wooden_bowl.png and /dev/null differ diff --git a/media/product_images/Jajanan_Pasar_Masakan_Nusantara.png b/media/product_images/Jajanan_Pasar_Masakan_Nusantara.png deleted file mode 100755 index 664c92e..0000000 Binary files a/media/product_images/Jajanan_Pasar_Masakan_Nusantara.png and /dev/null differ diff --git a/media/product_images/Laundry_Ibu_Tini_logo_design_1.png b/media/product_images/Laundry_Ibu_Tini_logo_design_1.png deleted file mode 100755 index b415c47..0000000 Binary files a/media/product_images/Laundry_Ibu_Tini_logo_design_1.png and /dev/null differ diff --git a/media/product_images/Masakan_Nusantara_Ibu_Tini.png b/media/product_images/Masakan_Nusantara_Ibu_Tini.png deleted file mode 100755 index ff67773..0000000 Binary files a/media/product_images/Masakan_Nusantara_Ibu_Tini.png and /dev/null differ diff --git a/media/shop_logos/7819e47b-9455-4740-bb47-199007a1b8a4_fM25NsS.png b/media/shop_logos/7819e47b-9455-4740-bb47-199007a1b8a4_fM25NsS.png deleted file mode 100755 index 0e68a2f..0000000 Binary files a/media/shop_logos/7819e47b-9455-4740-bb47-199007a1b8a4_fM25NsS.png and /dev/null differ diff --git a/media/shop_logos/Kripik_Pisang_logo_design.png b/media/shop_logos/Kripik_Pisang_logo_design.png deleted file mode 100755 index a016aa4..0000000 Binary files a/media/shop_logos/Kripik_Pisang_logo_design.png and /dev/null differ diff --git a/media/shop_logos/Logo_Masakan_Nusantara_Ibu_Tini.png b/media/shop_logos/Logo_Masakan_Nusantara_Ibu_Tini.png deleted file mode 100755 index cac6374..0000000 Binary files a/media/shop_logos/Logo_Masakan_Nusantara_Ibu_Tini.png and /dev/null differ diff --git a/product_images/7cVv0a78syo3XkKZFUGKtRZIx9PcIRI1JDfFekt5.jpg b/product_images/7cVv0a78syo3XkKZFUGKtRZIx9PcIRI1JDfFekt5.jpg deleted file mode 100644 index c6015d2..0000000 Binary files a/product_images/7cVv0a78syo3XkKZFUGKtRZIx9PcIRI1JDfFekt5.jpg and /dev/null differ diff --git a/product_images/7cVv0a78syo3XkKZFUGKtRZIx9PcIRI1JDfFekt5_ahMb402.jpg b/product_images/7cVv0a78syo3XkKZFUGKtRZIx9PcIRI1JDfFekt5_ahMb402.jpg deleted file mode 100644 index c6015d2..0000000 Binary files a/product_images/7cVv0a78syo3XkKZFUGKtRZIx9PcIRI1JDfFekt5_ahMb402.jpg and /dev/null differ diff --git a/product_images/c1f6b9fe04af42e90ee4053e6112b82edb94a6d7.webp b/product_images/c1f6b9fe04af42e90ee4053e6112b82edb94a6d7.webp deleted file mode 100644 index 76b4850..0000000 Binary files a/product_images/c1f6b9fe04af42e90ee4053e6112b82edb94a6d7.webp and /dev/null differ diff --git a/shop_logos/7819e47b-9455-4740-bb47-199007a1b8a4.png b/shop_logos/7819e47b-9455-4740-bb47-199007a1b8a4.png deleted file mode 100644 index ed6e702..0000000 Binary files a/shop_logos/7819e47b-9455-4740-bb47-199007a1b8a4.png and /dev/null differ diff --git a/shop_logos/7819e47b-9455-4740-bb47-199007a1b8a4_fM25NsS.png b/shop_logos/7819e47b-9455-4740-bb47-199007a1b8a4_fM25NsS.png deleted file mode 100644 index ed6e702..0000000 Binary files a/shop_logos/7819e47b-9455-4740-bb47-199007a1b8a4_fM25NsS.png and /dev/null differ diff --git a/static/css/custom.css b/static/css/custom.css old mode 100755 new mode 100644 index f953d51..925f6ed --- a/static/css/custom.css +++ b/static/css/custom.css @@ -1,330 +1,4 @@ -:root { - --primary-orange: #F97316; /* Orange 500 */ - --dark-orange: #EA580C; /* Orange 600 */ - --primary-blue: #2563EB; /* Blue 600 */ - --dark-blue: #1E40AF; /* Blue 800 */ - --deep-blue: #1E3A8A; /* Blue 900 */ - - /* Compatibility Mapping */ - --emerald-primary: var(--primary-orange); - --emerald-dark: var(--dark-orange); - --forest-deep: var(--deep-blue); - - --amber-warm: #F59E0B; - --glass-bg: rgba(255, 255, 255, 0.9); - --soft-shadow: 0 10px 30px rgba(30, 58, 138, 0.1); -} - +/* Custom styles for the application */ body { - font-family: 'Inter', sans-serif; - background-color: #F0FDF4; /* Hijau Muda */ - color: #1e293b; -} - -h1, h2, h3, h4, .navbar-brand { - font-family: 'Poppins', sans-serif; -} - -/* Orange Styles */ -.text-orange, .text-emerald { - color: var(--primary-orange); -} - -.bg-orange, .bg-emerald { - background-color: var(--primary-orange); -} - -.btn-orange, .btn-emerald { - background-color: var(--primary-orange); - border-color: var(--primary-orange); - color: white; - font-weight: 600; - transition: all 0.3s ease; -} - -.btn-orange:hover, .btn-emerald:hover { - background-color: var(--dark-orange); - border-color: var(--dark-orange); - color: white; - transform: translateY(-2px); - box-shadow: 0 5px 15px rgba(249, 115, 22, 0.4); -} - -.btn-outline-orange, .btn-outline-emerald { - color: var(--primary-orange); - border: 2px solid var(--primary-orange); - font-weight: 600; - transition: all 0.3s ease; -} - -.btn-outline-orange:hover, .btn-outline-emerald:hover { - background-color: var(--primary-orange); - color: white; - transform: translateY(-2px); -} - -/* Blue Styles */ -.text-blue { - color: var(--primary-blue); -} - -.bg-blue { - background-color: var(--primary-blue); -} - -.btn-blue { - background-color: var(--primary-blue); - border-color: var(--primary-blue); - color: white; - font-weight: 600; - transition: all 0.3s ease; -} - -.btn-blue:hover { - background-color: var(--dark-blue); - border-color: var(--dark-blue); - color: white; - transform: translateY(-2px); - box-shadow: 0 5px 15px rgba(37, 99, 235, 0.4); -} - -.navbar { - background: var(--glass-bg); - backdrop-filter: blur(10px); - border-bottom: 1px solid rgba(30, 58, 138, 0.05); - padding: 1rem 0; -} - -.navbar-brand { - font-size: 1.5rem; - color: var(--deep-blue); -} - -.nav-link { - color: var(--deep-blue); - font-weight: 500; -} - -.nav-link:hover { - color: var(--primary-orange); -} - -/* Hero Section */ -.hero-section { - padding: 100px 0; - background: linear-gradient(135deg, #DCFCE7 0%, #F0FDF4 100%); - position: relative; - overflow: hidden; -} - -.hero-section::after { - content: ""; - position: absolute; - top: -10%; - right: -5%; - width: 400px; - height: 400px; - background: radial-gradient(circle, rgba(34, 197, 94, 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(--deep-blue); -} - -/* 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(30, 58, 138, 0.15); -} - -.category-icon { - width: 60px; - height: 60px; - background: #fff7ed; - color: var(--primary-orange); - 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(30, 58, 138, 0.15); -} - -.product-img-wrapper { - height: 220px; - background: #f1f5f9; - display: flex; - align-items: center; - justify-content: center; - overflow: hidden; - position: relative; -} - -.product-img-wrapper img { - transition: transform 0.5s ease; - width: 100%; - height: 100%; - object-fit: cover; -} - -.product-card:hover .product-img-wrapper img { - transform: scale(1.1); -} - -.product-img-wrapper i { - font-size: 4rem; - color: #cbd5e1; -} - -.product-price { - color: var(--primary-orange); - font-weight: 700; - font-size: 1.25rem; -} - -.shop-badge { - background: #eff6ff; - color: var(--primary-blue); - 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); - animation: floating 6s ease-in-out infinite; -} - -@keyframes floating { - 0% { transform: translateY(0px); } - 50% { transform: translateY(-15px); } - 100% { transform: translateY(0px); } -} - -.transform-hover:hover { - animation-play-state: paused; - transform: scale(1.03) translateY(-5px); - box-shadow: 0 30px 60px -12px rgba(249, 115, 22, 0.3) !important; -} - -.transition-all { - transition: all 0.3s ease; -} - -/* Search Box */ -.search-box { - border: 1px solid rgba(30, 58, 138, 0.1); - transition: all 0.3s ease; -} - -.search-box:focus-within { - border-color: var(--primary-orange); - box-shadow: 0 0 0 4px rgba(249, 115, 22, 0.1) !important; -} - -/* Categories Active State */ -.category-card.active { - background: var(--deep-blue); - color: white !important; -} - -.category-card.active .category-icon { - background: rgba(255, 255, 255, 0.1); - color: white; -} - -.category-card.active h6 { - color: white !important; -} - -footer { - background-color: #F0FDF4; - border-top: 1px solid rgba(34, 197, 94, 0.1); -} - -@media (max-width: 768px) { - .hero-title { - font-size: 2.2rem; - text-align: center; - } - .hero-section { - padding: 60px 0; - text-align: center; - } - .banner-wrapper { - height: 200px !important; - } - .category-card { - padding: 1.2rem; - } - .category-icon { - width: 50px; - height: 50px; - font-size: 1.2rem; - margin-bottom: 1rem; - } -} - -/* Utilities */ -.banner-wrapper { - height: 400px; - width: 100%; - position: relative; - overflow: hidden; -} - -.banner-img { - width: 100%; - height: 100%; - object-fit: cover; - object-position: center; -} - -.object-fit-cover { - object-fit: cover; + font-family: system-ui, -apple-system, sans-serif; } diff --git a/static/images/banner.png b/static/images/banner.png deleted file mode 100755 index 2cb6ce7..0000000 Binary files a/static/images/banner.png and /dev/null differ diff --git a/staticfiles/css/custom.css b/staticfiles/css/custom.css index f953d51..108056f 100644 --- a/staticfiles/css/custom.css +++ b/staticfiles/css/custom.css @@ -1,330 +1,21 @@ + :root { - --primary-orange: #F97316; /* Orange 500 */ - --dark-orange: #EA580C; /* Orange 600 */ - --primary-blue: #2563EB; /* Blue 600 */ - --dark-blue: #1E40AF; /* Blue 800 */ - --deep-blue: #1E3A8A; /* Blue 900 */ - - /* Compatibility Mapping */ - --emerald-primary: var(--primary-orange); - --emerald-dark: var(--dark-orange); - --forest-deep: var(--deep-blue); - - --amber-warm: #F59E0B; - --glass-bg: rgba(255, 255, 255, 0.9); - --soft-shadow: 0 10px 30px rgba(30, 58, 138, 0.1); + --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); } - body { + margin: 0; font-family: 'Inter', sans-serif; - background-color: #F0FDF4; /* Hijau Muda */ - color: #1e293b; -} - -h1, h2, h3, h4, .navbar-brand { - font-family: 'Poppins', sans-serif; -} - -/* Orange Styles */ -.text-orange, .text-emerald { - color: var(--primary-orange); -} - -.bg-orange, .bg-emerald { - background-color: var(--primary-orange); -} - -.btn-orange, .btn-emerald { - background-color: var(--primary-orange); - border-color: var(--primary-orange); - color: white; - font-weight: 600; - transition: all 0.3s ease; -} - -.btn-orange:hover, .btn-emerald:hover { - background-color: var(--dark-orange); - border-color: var(--dark-orange); - color: white; - transform: translateY(-2px); - box-shadow: 0 5px 15px rgba(249, 115, 22, 0.4); -} - -.btn-outline-orange, .btn-outline-emerald { - color: var(--primary-orange); - border: 2px solid var(--primary-orange); - font-weight: 600; - transition: all 0.3s ease; -} - -.btn-outline-orange:hover, .btn-outline-emerald:hover { - background-color: var(--primary-orange); - color: white; - transform: translateY(-2px); -} - -/* Blue Styles */ -.text-blue { - color: var(--primary-blue); -} - -.bg-blue { - background-color: var(--primary-blue); -} - -.btn-blue { - background-color: var(--primary-blue); - border-color: var(--primary-blue); - color: white; - font-weight: 600; - transition: all 0.3s ease; -} - -.btn-blue:hover { - background-color: var(--dark-blue); - border-color: var(--dark-blue); - color: white; - transform: translateY(-2px); - box-shadow: 0 5px 15px rgba(37, 99, 235, 0.4); -} - -.navbar { - background: var(--glass-bg); - backdrop-filter: blur(10px); - border-bottom: 1px solid rgba(30, 58, 138, 0.05); - padding: 1rem 0; -} - -.navbar-brand { - font-size: 1.5rem; - color: var(--deep-blue); -} - -.nav-link { - color: var(--deep-blue); - font-weight: 500; -} - -.nav-link:hover { - color: var(--primary-orange); -} - -/* Hero Section */ -.hero-section { - padding: 100px 0; - background: linear-gradient(135deg, #DCFCE7 0%, #F0FDF4 100%); - position: relative; - overflow: hidden; -} - -.hero-section::after { - content: ""; - position: absolute; - top: -10%; - right: -5%; - width: 400px; - height: 400px; - background: radial-gradient(circle, rgba(34, 197, 94, 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(--deep-blue); -} - -/* Cards */ -.category-card { - background: white; - border: none; - border-radius: 20px; - padding: 2rem; + background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end)); + color: var(--text-color); + display: flex; + justify-content: center; + align-items: center; + min-height: 100vh; 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(30, 58, 138, 0.15); -} - -.category-icon { - width: 60px; - height: 60px; - background: #fff7ed; - color: var(--primary-orange); - 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(30, 58, 138, 0.15); -} - -.product-img-wrapper { - height: 220px; - background: #f1f5f9; - display: flex; - align-items: center; - justify-content: center; overflow: hidden; position: relative; } - -.product-img-wrapper img { - transition: transform 0.5s ease; - width: 100%; - height: 100%; - object-fit: cover; -} - -.product-card:hover .product-img-wrapper img { - transform: scale(1.1); -} - -.product-img-wrapper i { - font-size: 4rem; - color: #cbd5e1; -} - -.product-price { - color: var(--primary-orange); - font-weight: 700; - font-size: 1.25rem; -} - -.shop-badge { - background: #eff6ff; - color: var(--primary-blue); - 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); - animation: floating 6s ease-in-out infinite; -} - -@keyframes floating { - 0% { transform: translateY(0px); } - 50% { transform: translateY(-15px); } - 100% { transform: translateY(0px); } -} - -.transform-hover:hover { - animation-play-state: paused; - transform: scale(1.03) translateY(-5px); - box-shadow: 0 30px 60px -12px rgba(249, 115, 22, 0.3) !important; -} - -.transition-all { - transition: all 0.3s ease; -} - -/* Search Box */ -.search-box { - border: 1px solid rgba(30, 58, 138, 0.1); - transition: all 0.3s ease; -} - -.search-box:focus-within { - border-color: var(--primary-orange); - box-shadow: 0 0 0 4px rgba(249, 115, 22, 0.1) !important; -} - -/* Categories Active State */ -.category-card.active { - background: var(--deep-blue); - color: white !important; -} - -.category-card.active .category-icon { - background: rgba(255, 255, 255, 0.1); - color: white; -} - -.category-card.active h6 { - color: white !important; -} - -footer { - background-color: #F0FDF4; - border-top: 1px solid rgba(34, 197, 94, 0.1); -} - -@media (max-width: 768px) { - .hero-title { - font-size: 2.2rem; - text-align: center; - } - .hero-section { - padding: 60px 0; - text-align: center; - } - .banner-wrapper { - height: 200px !important; - } - .category-card { - padding: 1.2rem; - } - .category-icon { - width: 50px; - height: 50px; - font-size: 1.2rem; - margin-bottom: 1rem; - } -} - -/* Utilities */ -.banner-wrapper { - height: 400px; - width: 100%; - position: relative; - overflow: hidden; -} - -.banner-img { - width: 100%; - height: 100%; - object-fit: cover; - object-position: center; -} - -.object-fit-cover { - object-fit: cover; -} diff --git a/staticfiles/images/banner.png b/staticfiles/images/banner.png deleted file mode 100644 index 2cb6ce7..0000000 Binary files a/staticfiles/images/banner.png and /dev/null differ