Umkn Pemagarsari

This commit is contained in:
Flatlogic Bot 2026-02-21 17:32:21 +00:00
parent 997d4c8ee3
commit a0d7e5a068
22 changed files with 290 additions and 69 deletions

View File

@ -183,4 +183,6 @@ if EMAIL_USE_SSL:
# Default primary key field type
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
LOGIN_REDIRECT_URL = '/admin/'
LOGIN_URL = 'vendor_login'

Binary file not shown.

View File

@ -42,7 +42,7 @@
</li>
</ul>
<div class="d-grid d-lg-block">
<a href="/admin/" class="btn btn-outline-light btn-sm rounded-pill px-3">
<a href="{% url 'vendor_login' %}" class="btn btn-outline-light btn-sm rounded-pill px-3">
<i class="fas fa-user-circle me-1"></i> Admin / Vendor Login
</a>
</div>
@ -54,6 +54,12 @@
{% block content %}{% endblock %}
</main>
<!-- Floating WA Button -->
<a href="https://wa.me/6281385035662" target="_blank" class="wa-floating-btn shadow-lg">
<i class="fab fa-whatsapp"></i>
<span>Chat Admin</span>
</a>
<!-- Footer -->
<footer class="footer mt-auto">
<div class="container">
@ -67,7 +73,7 @@
<ul class="list-unstyled">
<li><a href="{% url 'home' %}" class="footer-link small">Beranda</a></li>
<li><a href="{% url 'product_list' %}" class="footer-link small">Semua Produk</a></li>
<li><a href="/admin/" class="footer-link small">Admin / Vendor</a></li>
<li><a href="{% url 'vendor_login' %}" class="footer-link small">Admin / Vendor</a></li>
</ul>
</div>
<div class="col-lg-2 col-6">
@ -80,12 +86,12 @@
</div>
<div class="col-lg-4 col-md-6">
<h5 class="fw-bold">Kontak Kami</h5>
<p class="small mb-2"><i class="fas fa-map-marker-alt me-2 text-accent"></i> Kantor Desa Pemagarsari, Jawa Barat</p>
<p class="small mb-3"><i class="fas fa-phone me-2 text-accent"></i> +62-21-XXXXXXX</p>
<p class="small mb-2"><i class="fas fa-map-marker-alt me-2 text-accent"></i> Kp.Tajur Rt 04/ Rw 04 Desa Pemagarsari Parung Bogor</p>
<p class="small mb-3"><i class="fas fa-phone me-2 text-accent"></i> +62 813-8503-5662</p>
<div class="d-flex gap-3">
<a href="#" class="text-white fs-5 opacity-75 hover-opacity-100"><i class="fab fa-instagram"></i></a>
<a href="#" class="text-white fs-5 opacity-75 hover-opacity-100"><i class="fab fa-facebook"></i></a>
<a href="#" class="text-white fs-5 opacity-75 hover-opacity-100"><i class="fab fa-whatsapp"></i></a>
<a href="https://wa.me/6281385035662" target="_blank" class="text-white fs-5 opacity-75 hover-opacity-100"><i class="fab fa-whatsapp"></i></a>
</div>
</div>
</div>

View File

@ -2,26 +2,6 @@
{% load static %}
{% block content %}
<!-- Hero Section -->
<header class="hero-section text-center">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-10 col-xl-8">
<h1 class="mb-4">Selamat Datang di Pasar UMKM Desa Pemagarsari</h1>
<p class="lead mb-5 opacity-90 mx-auto max-width-700">Pasar digital untuk produk unggulan lokal dari desa kita sendiri. Berdayakan ekonomi lokal melalui kemudahan transaksi via WhatsApp.</p>
<div class="d-flex flex-column flex-sm-row justify-content-center gap-3 px-4 px-sm-0">
<a href="{% url 'product_list' %}" class="btn btn-accent btn-lg shadow">
<i class="fas fa-shopping-bag me-2"></i> Jelajahi Produk
</a>
<a href="#kategori" class="btn btn-outline-light btn-lg">
<i class="fas fa-list-ul me-2"></i> Lihat Kategori
</a>
</div>
</div>
</div>
</div>
</header>
<!-- Image Banner Section -->
<section class="banner-promo py-5">
<div class="container">
@ -35,6 +15,26 @@
</div>
</section>
<!-- Welcome Section -->
<section class="welcome-section text-center py-5">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-10 col-xl-8">
<h1 class="mb-4 text-primary">Selamat Datang di Pasar UMKM Desa Pemagarsari</h1>
<p class="lead mb-5 mx-auto max-width-700 text-muted">Pasar digital untuk produk unggulan lokal dari desa kita sendiri. Berdayakan ekonomi lokal melalui kemudahan transaksi via WhatsApp.</p>
<div class="d-flex flex-column flex-sm-row justify-content-center gap-3 px-4 px-sm-0">
<a href="{% url 'product_list' %}" class="btn btn-accent btn-lg shadow">
<i class="fas fa-shopping-bag me-2"></i> Jelajahi Produk
</a>
<a href="#kategori" class="btn btn-outline-primary btn-lg">
<i class="fas fa-list-ul me-2"></i> Lihat Kategori
</a>
</div>
</div>
</div>
</div>
</section>
<!-- Categories Section -->
<section id="kategori" class="py-5 bg-white">
<div class="container">
@ -112,9 +112,9 @@
<div class="card h-100">
<div class="position-relative">
{% if product.image %}
<img src="{{ product.image.url }}" class="card-img-top" alt="{{ product.name }}" style="height: 160px; @media(min-width: 768px){height: 200px}; object-fit: cover;">
<img src="{{ product.image.url }}" class="card-img-top product-img-home" alt="{{ product.name }}" >
{% else %}
<div class="bg-secondary-subtle d-flex align-items-center justify-content-center" style="height: 160px; @media(min-width: 768px){height: 200px};">
<div class="bg-secondary-subtle d-flex align-items-center justify-content-center product-img-home" >
<i class="fas fa-image fa-2x text-muted opacity-50"></i>
</div>
{% endif %}
@ -142,7 +142,7 @@
{% for i in "1234" %}
<div class="col-6 col-lg-3">
<div class="card h-100 shadow-sm opacity-50">
<div class="bg-secondary-subtle d-flex align-items-center justify-content-center" style="height: 160px; @media(min-width: 768px){height: 200px};">
<div class="bg-secondary-subtle d-flex align-items-center justify-content-center product-img-home" >
<i class="fas fa-box-open fa-2x text-muted opacity-50"></i>
</div>
<div class="card-body">

View File

@ -0,0 +1,54 @@
{% extends 'base.html' %}
{% load static %}
{% block title %}Login Vendor - {{ project_name|default:"Pasar UMKM Desa Pemagarsari" }}{% endblock %}
{% block content %}
<section class="py-5" style="background-color: #f8f9fa; min-height: 80vh; display: flex; align-items: center;">
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6 col-lg-5">
<div class="card shadow-lg border-0 rounded-4">
<div class="card-body p-5">
<div class="text-center mb-4">
<div class="bg-primary text-white rounded-circle d-inline-flex align-items-center justify-content-center mb-3" style="width: 60px; height: 60px; font-size: 1.5rem;">
<i class="fas fa-store"></i>
</div>
<h2 class="fw-bold mb-1">Login Vendor</h2>
<p class="text-muted">Masuk ke akun vendor Anda untuk kelola produk</p>
</div>
{% if form.errors %}
<div class="alert alert-danger rounded-3 small">
Username atau password yang Anda masukkan salah. Silakan coba lagi.
</div>
{% endif %}
<form method="post" action="{% url 'vendor_login' %}">
{% csrf_token %}
<div class="mb-3">
<label for="id_username" class="form-label fw-bold small">Username</label>
<input type="text" name="username" class="form-control form-control-lg bg-light border-0" id="id_username" placeholder="Masukkan username" required autofocus>
</div>
<div class="mb-4">
<label for="id_password" class="form-label fw-bold small">Password</label>
<input type="password" name="password" class="form-control form-control-lg bg-light border-0" id="id_password" placeholder="Masukkan password" required>
</div>
<button type="submit" class="btn btn-primary w-100 btn-lg rounded-pill fw-bold shadow-sm">
Masuk ke Dashboard
</button>
<input type="hidden" name="next" value="{{ next }}">
</form>
<div class="text-center mt-4">
<p class="small text-muted mb-0">Belum punya akun vendor? <a href="https://wa.me/6281385035662" target="_blank" class="fw-bold text-decoration-none">Hubungi Admin</a></p>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
{% endblock %}

View File

@ -22,7 +22,7 @@
{% if product.image %}
<img src="{{ product.image.url }}" class="img-fluid rounded w-100" alt="{{ product.name }}" style="object-fit: cover; max-height: 500px;">
{% else %}
<div class="bg-secondary-subtle d-flex align-items-center justify-content-center" style="min-height: 300px; height: 100%;">
<div class="bg-secondary-subtle d-flex align-items-center justify-content-center product-img-related" style="min-height: 300px; height: 100%;">
<i class="fas fa-image fa-5x text-muted opacity-50"></i>
</div>
{% endif %}
@ -92,9 +92,9 @@
<div class="card h-100 shadow-sm border-0">
<div class="position-relative">
{% if rel_prod.image %}
<img src="{{ rel_prod.image.url }}" class="card-img-top" alt="{{ rel_prod.name }}" style="height: 120px; @media(min-width: 768px){height: 180px}; object-fit: cover;">
<img src="{{ rel_prod.image.url }}" class="card-img-top product-img-related" alt="{{ rel_prod.name }}" >
{% else %}
<div class="bg-secondary-subtle d-flex align-items-center justify-content-center" style="height: 120px; @media(min-width: 768px){height: 180px};">
<div class="bg-secondary-subtle d-flex align-items-center justify-content-center product-img-related" >
<i class="fas fa-image fa-lg text-muted opacity-50"></i>
</div>
{% endif %}

View File

@ -57,9 +57,9 @@
<div class="card h-100 shadow-sm">
<div class="position-relative">
{% if product.image %}
<img src="{{ product.image.url }}" class="card-img-top" alt="{{ product.name }}" style="height: 150px; @media(min-width: 768px){height: 180px}; object-fit: cover;">
<img src="{{ product.image.url }}" class="card-img-top product-img-list" alt="{{ product.name }}" >
{% else %}
<div class="bg-secondary-subtle d-flex align-items-center justify-content-center" style="height: 150px; @media(min-width: 768px){height: 180px};">
<div class="bg-secondary-subtle d-flex align-items-center justify-content-center product-img-list" >
<i class="fas fa-image fa-2x text-muted opacity-50"></i>
</div>
{% endif %}

View File

@ -9,9 +9,9 @@
<div class="container py-2 text-center px-4 px-md-0">
<div class="mb-4">
{% if vendor.logo %}
<img src="{{ vendor.logo.url }}" class="rounded-circle shadow-sm mb-3" style="width: 100px; height: 100px; @media(min-width: 768px){width: 120px; height: 120px}; object-fit: cover;">
<img src="{{ vendor.logo.url }}" class="rounded-circle shadow-sm mb-3 vendor-logo-img" >
{% else %}
<div class="rounded-circle bg-primary text-white d-flex align-items-center justify-content-center shadow-sm mb-3 mx-auto" style="width: 100px; height: 100px; @media(min-width: 768px){width: 120px; height: 120px};">
<div class="rounded-circle bg-primary text-white d-flex align-items-center justify-content-center shadow-sm mb-3 mx-auto vendor-logo-img" >
<i class="fas fa-store fa-3x"></i>
</div>
{% endif %}
@ -48,9 +48,9 @@
<div class="card h-100 shadow-sm border-0">
<div class="position-relative">
{% if product.image %}
<img src="{{ product.image.url }}" class="card-img-top" alt="{{ product.name }}" style="height: 140px; @media(min-width: 768px){height: 180px}; object-fit: cover;">
<img src="{{ product.image.url }}" class="card-img-top product-img-vendor" alt="{{ product.name }}" >
{% else %}
<div class="bg-secondary-subtle d-flex align-items-center justify-content-center" style="height: 140px; @media(min-width: 768px){height: 180px};">
<div class="bg-secondary-subtle d-flex align-items-center justify-content-center product-img-vendor" >
<i class="fas fa-image fa-2x text-muted opacity-50"></i>
</div>
{% endif %}

View File

@ -1,4 +1,5 @@
from django.urls import path
from django.contrib.auth import views as auth_views
from . import views
urlpatterns = [
@ -7,4 +8,5 @@ urlpatterns = [
path("kategori/<slug:category_slug>/", views.product_list, name="product_list_by_category"),
path("produk/<slug:slug>/", views.product_detail, name="product_detail"),
path("toko/<slug:slug>/", views.vendor_detail, name="vendor_detail"),
]
path("login/", auth_views.LoginView.as_view(template_name="core/login.html", redirect_authenticated_user=True), name="vendor_login"),
]

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 KiB

1
media/products/test.jpg Normal file
View File

@ -0,0 +1 @@
file_content

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

View File

@ -45,33 +45,37 @@ h1, h2, h3, h4, h5, h6 {
font-size: 1.15rem;
}
/* Hero Section - Mobile First */
/* Hero Section - Decorative Slim Header */
.hero-section {
background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
color: white;
padding: 40px 0;
padding: 15px 0;
border-radius: 0 0 20px 20px;
}
.hero-section h1 {
@media (min-width: 768px) {
.hero-section {
padding: 25px 0;
border-radius: 0 0 40px 40px;
}
}
/* Welcome Intro Section */
.welcome-intro h1 {
font-size: 1.75rem;
line-height: 1.2;
}
.hero-section .lead {
.welcome-intro .lead {
font-size: 1rem !important;
margin-bottom: 1.5rem !important;
}
@media (min-width: 768px) {
.hero-section {
padding: 60px 0;
border-radius: 0 0 40px 40px;
.welcome-intro h1 {
font-size: 2.5rem;
}
.hero-section h1 {
font-size: 2.75rem;
}
.hero-section .lead {
.welcome-intro .lead {
font-size: 1.15rem !important;
margin-bottom: 2rem !important;
}
@ -195,6 +199,55 @@ h1, h2, h3, h4, h5, h6 {
color: white;
}
/* Floating WA Button */
.wa-floating-btn {
position: fixed;
bottom: 25px;
right: 25px;
background-color: #25D366;
color: white;
width: 60px;
height: 60px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 30px;
z-index: 1000;
transition: all 0.3s ease;
text-decoration: none;
}
.wa-floating-btn span {
position: absolute;
right: 70px;
background-color: white;
color: #212529;
font-size: 14px;
font-weight: 600;
padding: 5px 15px;
border-radius: 50px;
box-shadow: var(--shadow-md);
white-space: nowrap;
opacity: 0;
transform: translateX(10px);
transition: all 0.3s ease;
pointer-events: none;
}
@media (min-width: 992px) {
.wa-floating-btn:hover {
transform: scale(1.1);
background-color: #128C7E;
color: white;
}
.wa-floating-btn:hover span {
opacity: 1;
transform: translateX(0);
}
}
/* Footer */
.footer {
background-color: var(--primary-dark);
@ -285,9 +338,17 @@ h1, h2, h3, h4, h5, h6 {
/* Banner Section */
.banner-promo {
background-color: #fff;
padding-top: 2rem !important;
padding-bottom: 2rem !important;
background-color: transparent;
padding-top: 0 !important;
margin-top: 20px;
position: relative;
z-index: 10;
}
@media (min-width: 768px) {
.banner-promo {
margin-top: 30px;
}
}
.banner-wrapper {
@ -303,4 +364,21 @@ h1, h2, h3, h4, h5, h6 {
.banner-wrapper img {
border-radius: 15px;
display: block;
}
}
/* Fix invalid inline styles from templates */
.product-img-home { height: 160px; object-fit: cover; width: 100%; }
@media (min-width: 768px) { .product-img-home { height: 200px; } }
.product-img-list { height: 150px; object-fit: cover; width: 100%; }
@media (min-width: 768px) { .product-img-list { height: 180px; } }
.product-img-vendor { height: 140px; object-fit: cover; width: 100%; }
@media (min-width: 768px) { .product-img-vendor { height: 180px; } }
.product-img-related { height: 120px; object-fit: cover; width: 100%; }
@media (min-width: 768px) { .product-img-related { height: 180px; } }
.vendor-logo-img { width: 100px; height: 100px; object-fit: cover; }
@media (min-width: 768px) { .vendor-logo-img { width: 120px; height: 120px; } }

View File

@ -45,33 +45,37 @@ h1, h2, h3, h4, h5, h6 {
font-size: 1.15rem;
}
/* Hero Section - Mobile First */
/* Hero Section - Decorative Slim Header */
.hero-section {
background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
color: white;
padding: 40px 0;
padding: 15px 0;
border-radius: 0 0 20px 20px;
}
.hero-section h1 {
@media (min-width: 768px) {
.hero-section {
padding: 25px 0;
border-radius: 0 0 40px 40px;
}
}
/* Welcome Intro Section */
.welcome-intro h1 {
font-size: 1.75rem;
line-height: 1.2;
}
.hero-section .lead {
.welcome-intro .lead {
font-size: 1rem !important;
margin-bottom: 1.5rem !important;
}
@media (min-width: 768px) {
.hero-section {
padding: 60px 0;
border-radius: 0 0 40px 40px;
.welcome-intro h1 {
font-size: 2.5rem;
}
.hero-section h1 {
font-size: 2.75rem;
}
.hero-section .lead {
.welcome-intro .lead {
font-size: 1.15rem !important;
margin-bottom: 2rem !important;
}
@ -195,6 +199,55 @@ h1, h2, h3, h4, h5, h6 {
color: white;
}
/* Floating WA Button */
.wa-floating-btn {
position: fixed;
bottom: 25px;
right: 25px;
background-color: #25D366;
color: white;
width: 60px;
height: 60px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 30px;
z-index: 1000;
transition: all 0.3s ease;
text-decoration: none;
}
.wa-floating-btn span {
position: absolute;
right: 70px;
background-color: white;
color: #212529;
font-size: 14px;
font-weight: 600;
padding: 5px 15px;
border-radius: 50px;
box-shadow: var(--shadow-md);
white-space: nowrap;
opacity: 0;
transform: translateX(10px);
transition: all 0.3s ease;
pointer-events: none;
}
@media (min-width: 992px) {
.wa-floating-btn:hover {
transform: scale(1.1);
background-color: #128C7E;
color: white;
}
.wa-floating-btn:hover span {
opacity: 1;
transform: translateX(0);
}
}
/* Footer */
.footer {
background-color: var(--primary-dark);
@ -285,9 +338,17 @@ h1, h2, h3, h4, h5, h6 {
/* Banner Section */
.banner-promo {
background-color: #fff;
padding-top: 2rem !important;
padding-bottom: 2rem !important;
background-color: transparent;
padding-top: 0 !important;
margin-top: 20px;
position: relative;
z-index: 10;
}
@media (min-width: 768px) {
.banner-promo {
margin-top: 30px;
}
}
.banner-wrapper {
@ -303,4 +364,21 @@ h1, h2, h3, h4, h5, h6 {
.banner-wrapper img {
border-radius: 15px;
display: block;
}
}
/* Fix invalid inline styles from templates */
.product-img-home { height: 160px; object-fit: cover; width: 100%; }
@media (min-width: 768px) { .product-img-home { height: 200px; } }
.product-img-list { height: 150px; object-fit: cover; width: 100%; }
@media (min-width: 768px) { .product-img-list { height: 180px; } }
.product-img-vendor { height: 140px; object-fit: cover; width: 100%; }
@media (min-width: 768px) { .product-img-vendor { height: 180px; } }
.product-img-related { height: 120px; object-fit: cover; width: 100%; }
@media (min-width: 768px) { .product-img-related { height: 180px; } }
.vendor-logo-img { width: 100px; height: 100px; object-fit: cover; }
@media (min-width: 768px) { .vendor-logo-img { width: 120px; height: 120px; } }