Autosave: 20260219-214250
BIN
assets/images/banner.png
Normal file
|
After Width: | Height: | Size: 2.5 MiB |
@ -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 = os.getenv("DJANGO_DEBUG", "true").lower() == "true"
|
||||
DEBUG = False
|
||||
|
||||
ALLOWED_HOSTS = [
|
||||
"127.0.0.1",
|
||||
@ -155,6 +155,9 @@ STATICFILES_DIRS = [
|
||||
BASE_DIR / 'node_modules',
|
||||
]
|
||||
|
||||
MEDIA_URL = '/media/'
|
||||
MEDIA_ROOT = BASE_DIR / 'media'
|
||||
|
||||
# Email
|
||||
EMAIL_BACKEND = os.getenv(
|
||||
"EMAIL_BACKEND",
|
||||
|
||||
@ -27,3 +27,4 @@ urlpatterns = [
|
||||
if settings.DEBUG:
|
||||
urlpatterns += static("/assets/", document_root=settings.BASE_DIR / "assets")
|
||||
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
||||
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
# 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),
|
||||
),
|
||||
]
|
||||
@ -5,7 +5,7 @@ import urllib.parse
|
||||
|
||||
class Category(models.Model):
|
||||
name = models.CharField(max_length=100)
|
||||
slug = models.SlugField(unique=True, blank=True)
|
||||
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):
|
||||
@ -22,7 +22,7 @@ class Category(models.Model):
|
||||
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)
|
||||
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")
|
||||
@ -40,7 +40,7 @@ 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)
|
||||
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)
|
||||
|
||||
@ -2,6 +2,16 @@
|
||||
{% load static %}
|
||||
|
||||
{% block content %}
|
||||
<!-- Main Banner -->
|
||||
<div class="container-fluid px-0 mb-4">
|
||||
<div class="position-relative overflow-hidden" style="max-height: 450px;">
|
||||
<img src="{% static 'images/banner.png' %}" alt="Banner Desa Pemagarsari" class="w-100 h-100" style="object-fit: cover; object-position: center;">
|
||||
<div class="position-absolute bottom-0 start-0 w-100 p-4 bg-gradient-dark text-white d-md-none">
|
||||
<h3 class="fw-bold mb-0">Selamat Datang</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hero Section -->
|
||||
<section class="hero-section">
|
||||
<div class="container">
|
||||
@ -31,8 +41,8 @@
|
||||
<div class="col-lg-6 d-none d-lg-block text-center">
|
||||
<div class="position-relative p-4">
|
||||
<div class="bg-emerald rounded-circle position-absolute top-50 start-50 translate-middle opacity-10" style="width: 500px; height: 500px; filter: blur(60px);"></div>
|
||||
<div class="position-relative z-1 shadow-lg rounded-4 overflow-hidden border border-white border-4 transform-hover transition-all">
|
||||
<img src="https://images.unsplash.com/photo-1590632823277-285f21442df1?auto=format&fit=crop&q=80&w=800" alt="Pasar Tradisional Desa" class="img-fluid" style="max-height: 450px; width: 100%; object-fit: cover;">
|
||||
<div class="position-relative z-1 shadow-lg rounded-4 overflow-hidden border border-white border-4 transform-hover transition-all" style="aspect-ratio: 4/3;">
|
||||
<img src="https://images.unsplash.com/photo-1488459716781-31db52582fe9?auto=format&fit=crop&q=90&w=1000" alt="Pasar Tradisional Desa" class="w-100 h-100" style="object-fit: cover; object-position: center;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -121,7 +131,7 @@
|
||||
<!-- Call to Action -->
|
||||
<section class="py-5">
|
||||
<div class="container">
|
||||
<div class="p-5 rounded-4 text-white text-center position-relative overflow-hidden shadow-lg" style="background: linear-gradient(135deg, rgba(6, 78, 59, 0.9) 0%, rgba(16, 185, 129, 0.9) 100%), url('https://images.unsplash.com/photo-1544333346-64e4fe18204b?auto=format&fit=crop&q=80&w=1200'); background-size: cover; background-position: center;">
|
||||
<div class="p-5 rounded-4 text-white text-center position-relative overflow-hidden shadow-lg" style="background: linear-gradient(135deg, rgba(6, 78, 59, 0.85) 0%, rgba(16, 185, 129, 0.75) 100%), url('https://images.unsplash.com/photo-1516253593875-bd7ba052fbc5?auto=format&fit=crop&q=90&w=1200'); background-size: cover; background-position: center;">
|
||||
<div class="position-relative z-1">
|
||||
<h2 class="fw-bold mb-3">Punya Usaha di Desa Pemagarsari?</h2>
|
||||
<p class="mb-4 opacity-75">Daftarkan toko Anda dan mulai jualan online hari ini. Mudah, gratis, dan langsung ke WhatsApp!</p>
|
||||
|
||||
BIN
media/product_images/7cVv0a78syo3XkKZFUGKtRZIx9PcIRI1JDfFekt5_ahMb402.jpg
Executable file
|
After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 2.1 MiB |
BIN
media/product_images/Golden_banana_chips_in_wooden_bowl.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
media/product_images/Jajanan_Pasar_Masakan_Nusantara.png
Normal file
|
After Width: | Height: | Size: 2.0 MiB |
BIN
media/product_images/Laundry_Ibu_Tini_logo_design_1.png
Normal file
|
After Width: | Height: | Size: 307 KiB |
BIN
media/product_images/Masakan_Nusantara_Ibu_Tini.png
Normal file
|
After Width: | Height: | Size: 398 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
BIN
media/shop_logos/Kripik_Pisang_logo_design.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
media/shop_logos/Logo_Masakan_Nusantara_Ibu_Tini.png
Normal file
|
After Width: | Height: | Size: 3.0 MiB |
BIN
product_images/7cVv0a78syo3XkKZFUGKtRZIx9PcIRI1JDfFekt5.jpg
Normal file
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 70 KiB |
BIN
product_images/c1f6b9fe04af42e90ee4053e6112b82edb94a6d7.webp
Normal file
|
After Width: | Height: | Size: 151 KiB |
BIN
shop_logos/7819e47b-9455-4740-bb47-199007a1b8a4.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
shop_logos/7819e47b-9455-4740-bb47-199007a1b8a4_fM25NsS.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
@ -132,6 +132,18 @@ h1, h2, h3, h4, .navbar-brand {
|
||||
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 {
|
||||
@ -169,11 +181,19 @@ h1, h2, h3, h4, .navbar-brand {
|
||||
|
||||
.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 {
|
||||
transform: scale(1.02) translateY(-10px) rotate(1deg);
|
||||
box-shadow: 0 25px 50px -12px rgba(16, 185, 129, 0.25) !important;
|
||||
animation-play-state: paused;
|
||||
transform: scale(1.03) translateY(-5px);
|
||||
box-shadow: 0 30px 60px -12px rgba(16, 185, 129, 0.3) !important;
|
||||
}
|
||||
|
||||
.transition-all {
|
||||
|
||||
@ -1,21 +1,233 @@
|
||||
|
||||
:root {
|
||||
--bg-color-start: #6a11cb;
|
||||
--bg-color-end: #2575fc;
|
||||
--text-color: #ffffff;
|
||||
--card-bg-color: rgba(255, 255, 255, 0.01);
|
||||
--card-border-color: rgba(255, 255, 255, 0.1);
|
||||
--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 {
|
||||
margin: 0;
|
||||
font-family: 'Inter', sans-serif;
|
||||
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;
|
||||
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;
|
||||
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(--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);
|
||||
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(16, 185, 129, 0.3) !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;
|
||||
}
|
||||
}
|
||||
|
||||
BIN
staticfiles/images/banner.png
Normal file
|
After Width: | Height: | Size: 2.5 MiB |