diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index a5ed392..2b46b3b 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 e061640..71f1e42 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 5a69659..969d364 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 2a36fd6..f65526a 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 8c38f3f..3dd187c 100644 --- a/core/admin.py +++ b/core/admin.py @@ -1,3 +1,23 @@ from django.contrib import admin +from .models import Category, Shop, Product -# Register your models here. +@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',)} diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py new file mode 100644 index 0000000..a5767a2 --- /dev/null +++ b/core/migrations/0001_initial.py @@ -0,0 +1,58 @@ +# 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/__pycache__/0001_initial.cpython-311.pyc b/core/migrations/__pycache__/0001_initial.cpython-311.pyc new file mode 100644 index 0000000..20f1236 Binary files /dev/null and b/core/migrations/__pycache__/0001_initial.cpython-311.pyc differ diff --git a/core/models.py b/core/models.py index 71a8362..08bd497 100644 --- a/core/models.py +++ b/core/models.py @@ -1,3 +1,63 @@ from django.db import models +from django.contrib.auth.models import User +from django.utils.text import slugify +import urllib.parse -# Create your models here. +class Category(models.Model): + name = models.CharField(max_length=100) + slug = models.SlugField(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(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(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}" diff --git a/core/templates/base.html b/core/templates/base.html index 1e7e5fb..93e9e3c 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -1,25 +1,97 @@ - + - {% 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 %} +
+ + + + + + 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" }} -

-
-
- -{% 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; + } }