diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index a5ed392..7913631 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..4563f36 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..a19c8e4 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..0b9d9db 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..2fbf728 100644 --- a/core/admin.py +++ b/core/admin.py @@ -1,3 +1,14 @@ from django.contrib import admin +from .models import Category, Product -# Register your models here. +@admin.register(Category) +class CategoryAdmin(admin.ModelAdmin): + list_display = ('name', 'slug') + prepopulated_fields = {'slug': ('name',)} + +@admin.register(Product) +class ProductAdmin(admin.ModelAdmin): + list_display = ('name', 'category', 'price', 'stock', 'is_active') + list_filter = ('category', 'is_active') + search_fields = ('name', 'description') + prepopulated_fields = {'slug': ('name',)} \ No newline at end of file diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py new file mode 100644 index 0000000..cb1e883 --- /dev/null +++ b/core/migrations/0001_initial.py @@ -0,0 +1,43 @@ +# Generated by Django 5.2.7 on 2026-01-22 19:11 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + 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)), + ('description', models.TextField(blank=True)), + ('image_url', models.URLField(blank=True, help_text='Placeholder image URL')), + ], + options={ + 'verbose_name_plural': 'Categories', + }, + ), + migrations.CreateModel( + name='Product', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200)), + ('slug', models.SlugField(blank=True, unique=True)), + ('description', models.TextField()), + ('price', models.DecimalField(decimal_places=2, max_digits=10)), + ('stock', models.PositiveIntegerField(default=0)), + ('image_url', models.URLField(blank=True, help_text='Placeholder image URL')), + ('is_active', models.BooleanField(default=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='products', to='core.category')), + ], + ), + ] 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..5de0a98 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..5195e91 100644 --- a/core/models.py +++ b/core/models.py @@ -1,3 +1,38 @@ from django.db import models +from django.utils.text import slugify -# Create your models here. +class Category(models.Model): + name = models.CharField(max_length=100) + slug = models.SlugField(unique=True, blank=True) + description = models.TextField(blank=True) + image_url = models.URLField(blank=True, help_text="Placeholder image URL") + + def save(self, *args, **kwargs): + if not self.slug: + self.slug = slugify(self.name) + super().save(*args, **kwargs) + + def __str__(self): + return self.name + + class Meta: + verbose_name_plural = "Categories" + +class Product(models.Model): + category = models.ForeignKey(Category, related_name='products', on_delete=models.CASCADE) + name = models.CharField(max_length=200) + slug = models.SlugField(unique=True, blank=True) + description = models.TextField() + price = models.DecimalField(max_digits=10, decimal_places=2) + stock = models.PositiveIntegerField(default=0) + image_url = models.URLField(blank=True, help_text="Placeholder image URL") + 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 self.name \ No newline at end of file diff --git a/core/templates/base.html b/core/templates/base.html index 1e7e5fb..c27fce9 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -1,25 +1,103 @@ +{% load static %} - - - {% block title %}Knowledge Base{% endblock %} - {% if project_description %} - - - - {% endif %} - {% if project_image_url %} - - - {% endif %} - {% load static %} - - {% block head %}{% endblock %} + + + {% block title %}GiftShop Polska - Authentic Polish Gifts{% endblock %} + + {% if project_description %} + + + + {% endif %} + {% if project_image_url %} + + + {% endif %} + + + + + + + + + + + + + + + + {% block head %}{% endblock %} - - {% block content %}{% endblock %} - - + + +
+ {% block content %}{% endblock %} +
+ + + + + + + \ No newline at end of file diff --git a/core/templates/core/blog.html b/core/templates/core/blog.html new file mode 100644 index 0000000..d9fcddf --- /dev/null +++ b/core/templates/core/blog.html @@ -0,0 +1,35 @@ +{% extends 'base.html' %} + +{% block title %}Blog - GiftShop Polska{% endblock %} + +{% block content %} +
+
+

Gift Shop Blog

+
+
+
+
+
+ Traditions +

The Magic of Polish Beeswax Candles

+

Discover why natural candles are a staple in every Polish home during winter.

+ Read More → +
+
+
+
+
+
+
+ Gifting Tips +

How to Build the Perfect Gift Box

+

A step-by-step guide to choosing items that tell a story.

+ Read More → +
+
+
+
+
+
+{% endblock %} diff --git a/core/templates/core/cart.html b/core/templates/core/cart.html new file mode 100644 index 0000000..161e5ed --- /dev/null +++ b/core/templates/core/cart.html @@ -0,0 +1,40 @@ +{% extends 'base.html' %} + +{% block title %}Your Cart - GiftShop Polska{% endblock %} + +{% block content %} +
+
+

Shopping Cart

+
+
+
+ +

Your cart is empty

+

Looks like you haven't added anything to your cart yet.

+ Start Shopping +
+
+
+
+

Summary

+
+ Subtotal + 0,00 zł +
+
+ Delivery + Calculated at next step +
+
+
+ Total + 0,00 zł +
+ +
+
+
+
+
+{% endblock %} diff --git a/core/templates/core/catalog.html b/core/templates/core/catalog.html new file mode 100644 index 0000000..bfa2c81 --- /dev/null +++ b/core/templates/core/catalog.html @@ -0,0 +1,95 @@ +{% extends 'base.html' %} +{% load static %} + +{% block title %}Catalog - GiftShop Polska{% endblock %} + +{% block content %} +
+
+ + +
+ +
+
+
Categories
+
+ + All Products + + {% for category in categories %} + + {{ category.name }} + + {% endfor %} +
+
+
+ + +
+
+

{% if selected_category %}{{ selected_category.name }}{% else %}All Products{% endif %}

+

{{ products.count }} items found

+
+ +
+ {% for product in products %} +
+
+
+ {{ product.name }} + +
+
+

{{ product.category.name }}

+
{{ product.name }}
+

{{ product.price }} PLN

+
+
+
+ {% empty %} +
+
🥀
+

No products found

+

Try selecting a different category or check back later.

+
+ {% endfor %} +
+
+
+
+
+ + +{% endblock %} diff --git a/core/templates/core/constructor.html b/core/templates/core/constructor.html new file mode 100644 index 0000000..8fdf219 --- /dev/null +++ b/core/templates/core/constructor.html @@ -0,0 +1,17 @@ +{% extends 'base.html' %} + +{% block title %}Gift Box Constructor - GiftShop Polska{% endblock %} + +{% block content %} +
+
+

Box Constructor

+

Build your perfect gift box. Choose items, add a card, and we'll pack it with love.

+
+

Coming Soon

+

Our interactive gift box builder is currently under development.

+ Browse Items +
+
+
+{% endblock %} diff --git a/core/templates/core/favorites.html b/core/templates/core/favorites.html new file mode 100644 index 0000000..f8923aa --- /dev/null +++ b/core/templates/core/favorites.html @@ -0,0 +1,17 @@ +{% extends 'base.html' %} + +{% block title %}Favorites - GiftShop Polska{% endblock %} + +{% block content %} +
+
+

Your Favorites

+
+ +

No favorites yet

+

Save your favorite items here to find them easily later.

+ Browse Products +
+
+
+{% endblock %} diff --git a/core/templates/core/index.html b/core/templates/core/index.html index faec813..eb5215f 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -1,145 +1,106 @@ -{% 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… + +
+
+
+
+

Thoughtful Gifts,
Authentically Polish

+

Create a personalized gift box filled with handpicked candles, books, postcards, and stationary. We deliver the warmth of Poland to your doorstep.

+ +
+
+
+
+ Gift Box +
+
+
-

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" }} -

-
-
- + + + +
+
+
+

The Little Wonders

+

Explore our curated collections

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

No categories available yet. Please add some in the Admin panel.

+
+ {% endfor %} +
+
+
+ + +
+
+
+
+

Staff Favorites

+

Our most loved items this month

+
+ View All → +
+
+ {% for product in featured_products %} +
+
+ {{ product.name }} +
+ {{ product.category.name }} +
{{ product.name }}
+

{{ product.price }} PLN

+ View Details +
+
+
+ {% endfor %} +
+
+
+ + +
+
+
+
+
+

The Gift Box Constructor

+

Can't decide? Build your own box! Pick the items, choose a card, and we'll pack it beautifully with a handwritten note.

+ Start Building +
+
+ Box Packing +
+
+
+
+
{% endblock %} \ No newline at end of file diff --git a/core/templates/core/product_detail.html b/core/templates/core/product_detail.html new file mode 100644 index 0000000..94dbf9a --- /dev/null +++ b/core/templates/core/product_detail.html @@ -0,0 +1,63 @@ +{% extends 'base.html' %} +{% load static %} + +{% block title %}{{ product.name }} - GiftShop Polska{% endblock %} + +{% block content %} +
+
+ + +
+
+ {{ product.name }} +
+
+
+ {{ product.category.name }} +

{{ product.name }}

+

{{ product.price }} PLN

+ +
+
Description
+

{{ product.description }}

+
+ +
+
+ + + +
+ +
+ +
+
+ 🚚 +
+
Delivery to Poland
+

Ships within 1-2 business days

+
+
+
+ 🎁 +
+
Gift Wrap Included
+

Every item is packed with care

+
+
+
+
+
+
+
+
+{% endblock %} diff --git a/core/urls.py b/core/urls.py index 6299e3d..345b1b5 100644 --- a/core/urls.py +++ b/core/urls.py @@ -1,7 +1,12 @@ from django.urls import path - -from .views import home +from .views import home, catalog, product_detail, constructor, cart, favorites, blog urlpatterns = [ path("", home, name="home"), + path("catalog/", catalog, name="catalog"), + path("product//", product_detail, name="product_detail"), + path("constructor/", constructor, name="constructor"), + path("cart/", cart, name="cart"), + path("favorites/", favorites, name="favorites"), + path("blog/", blog, name="blog"), ] diff --git a/core/views.py b/core/views.py index c9aed12..b8c68d2 100644 --- a/core/views.py +++ b/core/views.py @@ -1,25 +1,55 @@ -import os -import platform - -from django import get_version as django_version -from django.shortcuts import render -from django.utils import timezone - +from django.shortcuts import render, get_object_or_404 +from .models import Category, 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() - + """Landing page with featured categories and products.""" + categories = Category.objects.all()[:4] + featured_products = Product.objects.filter(is_active=True)[:6] 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, + "project_name": "GiftShop Polska", } return render(request, "core/index.html", context) + +def catalog(request): + """Product catalog with category filtering.""" + category_slug = request.GET.get('category') + categories = Category.objects.all() + products = Product.objects.filter(is_active=True) + + selected_category = None + if category_slug: + selected_category = get_object_or_404(Category, slug=category_slug) + products = products.filter(category=selected_category) + + context = { + "categories": categories, + "products": products, + "selected_category": selected_category, + } + return render(request, "core/catalog.html", context) + +def product_detail(request, slug): + """Individual product detail page.""" + product = get_object_or_404(Product, slug=slug, is_active=True) + context = { + "product": product, + } + return render(request, "core/product_detail.html", context) + +def constructor(request): + """Gift box constructor page.""" + return render(request, "core/constructor.html", {"title": "Box Constructor"}) + +def cart(request): + """Shopping cart page.""" + return render(request, "core/cart.html", {"title": "Your Cart"}) + +def favorites(request): + """Favorites/Wishlist page.""" + return render(request, "core/favorites.html", {"title": "Your Favorites"}) + +def blog(request): + """Blog index page.""" + return render(request, "core/blog.html", {"title": "Gift Shop Blog"}) \ No newline at end of file diff --git a/static/css/custom.css b/static/css/custom.css index 925f6ed..049107c 100644 --- a/static/css/custom.css +++ b/static/css/custom.css @@ -1,4 +1,90 @@ -/* Custom styles for the application */ -body { - font-family: system-ui, -apple-system, sans-serif; +:root { + --primary-color: #D2765E; /* Warm Terracotta */ + --accent-color: #A8B196; /* Soft Sage */ + --bg-color: #FCF8F3; /* Cream */ + --text-color: #2C2C2C; /* Deep Charcoal */ + --font-heading: 'Playfair Display', serif; + --font-body: 'Inter', sans-serif; } + +body { + font-family: var(--font-body); + background-color: var(--bg-color); + color: var(--text-color); + margin: 0; + padding: 0; +} + +h1, h2, h3, h4, h5, h6 { + font-family: var(--font-heading); + font-weight: 700; +} + +.navbar { + background-color: #fff; + border-bottom: 1px solid rgba(0,0,0,0.05); + padding: 1rem 0; +} + +.navbar-brand { + font-family: var(--font-heading); + font-size: 1.5rem; + color: var(--primary-color) !important; +} + +.nav-link { + font-weight: 500; + color: var(--text-color) !important; + margin: 0 10px; +} + +.nav-link:hover { + color: var(--primary-color) !important; +} + +.btn-primary { + background-color: var(--primary-color); + border-color: var(--primary-color); + padding: 10px 25px; + font-weight: 600; + border-radius: 50px; + color: white; +} + +.btn-primary:hover { + background-color: #bc654e; + border-color: #bc654e; + color: white; +} + +.btn-outline-primary { + color: var(--primary-color); + border-color: var(--primary-color); + border-radius: 50px; +} + +.btn-outline-primary:hover { + background-color: var(--primary-color); + border-color: var(--primary-color); +} + +.footer { + background-color: #fff; + padding: 4rem 0 2rem; + margin-top: 5rem; + border-top: 1px solid rgba(0,0,0,0.05); +} + +.hover-lift { + transition: transform 0.3s ease, box-shadow 0.3s ease; +} + +.hover-lift:hover { + transform: translateY(-10px); + box-shadow: 0 1rem 3rem rgba(0,0,0,.1) !important; +} + +.card { + border-radius: 1rem; + overflow: hidden; +} \ No newline at end of file diff --git a/staticfiles/css/custom.css b/staticfiles/css/custom.css index 108056f..049107c 100644 --- a/staticfiles/css/custom.css +++ b/staticfiles/css/custom.css @@ -1,21 +1,90 @@ - :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); + --primary-color: #D2765E; /* Warm Terracotta */ + --accent-color: #A8B196; /* Soft Sage */ + --bg-color: #FCF8F3; /* Cream */ + --text-color: #2C2C2C; /* Deep Charcoal */ + --font-heading: 'Playfair Display', serif; + --font-body: 'Inter', sans-serif; } + body { - margin: 0; - font-family: 'Inter', sans-serif; - background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end)); + font-family: var(--font-body); + background-color: var(--bg-color); color: var(--text-color); - display: flex; - justify-content: center; - align-items: center; - min-height: 100vh; - text-align: center; - overflow: hidden; - position: relative; + margin: 0; + padding: 0; } + +h1, h2, h3, h4, h5, h6 { + font-family: var(--font-heading); + font-weight: 700; +} + +.navbar { + background-color: #fff; + border-bottom: 1px solid rgba(0,0,0,0.05); + padding: 1rem 0; +} + +.navbar-brand { + font-family: var(--font-heading); + font-size: 1.5rem; + color: var(--primary-color) !important; +} + +.nav-link { + font-weight: 500; + color: var(--text-color) !important; + margin: 0 10px; +} + +.nav-link:hover { + color: var(--primary-color) !important; +} + +.btn-primary { + background-color: var(--primary-color); + border-color: var(--primary-color); + padding: 10px 25px; + font-weight: 600; + border-radius: 50px; + color: white; +} + +.btn-primary:hover { + background-color: #bc654e; + border-color: #bc654e; + color: white; +} + +.btn-outline-primary { + color: var(--primary-color); + border-color: var(--primary-color); + border-radius: 50px; +} + +.btn-outline-primary:hover { + background-color: var(--primary-color); + border-color: var(--primary-color); +} + +.footer { + background-color: #fff; + padding: 4rem 0 2rem; + margin-top: 5rem; + border-top: 1px solid rgba(0,0,0,0.05); +} + +.hover-lift { + transition: transform 0.3s ease, box-shadow 0.3s ease; +} + +.hover-lift:hover { + transform: translateY(-10px); + box-shadow: 0 1rem 3rem rgba(0,0,0,.1) !important; +} + +.card { + border-radius: 1rem; + overflow: hidden; +} \ No newline at end of file