diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index cd6f855..fc33bde 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 9aa598b..a7b496d 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 1f807fa..b4c1f9d 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 6867ddf..b689a39 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..e4a053d 100644 --- a/core/admin.py +++ b/core/admin.py @@ -1,3 +1,8 @@ from django.contrib import admin +from .models import Product -# Register your models here. +@admin.register(Product) +class ProductAdmin(admin.ModelAdmin): + list_display = ('name', 'category', 'sku', 'price', 'stock', 'minimum_stock_level') + search_fields = ('name', 'sku') + list_filter = ('category',) \ 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..52bc3cd --- /dev/null +++ b/core/migrations/0001_initial.py @@ -0,0 +1,26 @@ +# Generated by Django 5.2.7 on 2026-01-18 11:36 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + 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)), + ('category', models.CharField(blank=True, max_length=100, null=True)), + ('sku', models.CharField(max_length=100, unique=True)), + ('price', models.DecimalField(decimal_places=2, max_digits=10)), + ('stock', models.PositiveIntegerField()), + ('minimum_stock_level', models.PositiveIntegerField(default=10)), + ], + ), + ] 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..6864246 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..661aceb 100644 --- a/core/models.py +++ b/core/models.py @@ -1,3 +1,16 @@ from django.db import models +from django.urls import reverse -# Create your models here. +class Product(models.Model): + name = models.CharField(max_length=200) + category = models.CharField(max_length=100, blank=True, null=True) + sku = models.CharField(max_length=100, unique=True) + price = models.DecimalField(max_digits=10, decimal_places=2) + stock = models.PositiveIntegerField() + minimum_stock_level = models.PositiveIntegerField(default=10) + + def __str__(self): + return self.name + + def is_below_minimum_stock(self): + return self.stock < self.minimum_stock_level diff --git a/core/templates/base.html b/core/templates/base.html index 1e7e5fb..2eb01fe 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -3,7 +3,8 @@ - {% block title %}Knowledge Base{% endblock %} + {% block title %}Thai Shop Inventory{% endblock %} + {% if project_description %} @@ -13,13 +14,46 @@ {% endif %} + + + + + + + {% load static %} - + {% block head %}{% endblock %} - {% block content %}{% endblock %} + + +
+ {% block content %}{% endblock %} +
+ + - + \ No newline at end of file diff --git a/core/templates/core/index.html b/core/templates/core/index.html index faec813..97a65a6 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -1,145 +1,57 @@ {% extends "base.html" %} -{% block title %}{{ project_name }}{% endblock %} - -{% block head %} - - - - -{% endblock %} +{% block title %}Dashboard - Thai Shop Inventory{% endblock %} {% block content %} -
-
-

Analyzing your requirements and generating your app…

-
- Loading… +
+

Product Dashboard

+ Add Product +
+ +
+
+
All Products
+
+ + + + + + + + + + + + + + {% for product in products %} + + + + + + + + + + {% empty %} + + + + {% endfor %} + +
SKUNameCategoryPriceStockStatusActions
{{ product.sku }}{{ product.name }}{{ product.category }}฿{{ product.price|floatformat:2 }}{{ product.stock }} + {% if product.is_below_minimum_stock %} + Low Stock + {% else %} + In Stock + {% endif %} + + Edit + Delete +
No products found.
+
-

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 + +{% endblock %} diff --git a/core/templates/core/product_confirm_delete.html b/core/templates/core/product_confirm_delete.html new file mode 100644 index 0000000..c1f2f88 --- /dev/null +++ b/core/templates/core/product_confirm_delete.html @@ -0,0 +1,17 @@ +{% extends "base.html" %} + +{% block title %}Confirm Delete - Thai Shop Inventory{% endblock %} + +{% block content %} +

Confirm Delete

+ + + +
+ {% csrf_token %} + + Cancel +
+{% endblock %} diff --git a/core/templates/core/product_form.html b/core/templates/core/product_form.html new file mode 100644 index 0000000..e1661ae --- /dev/null +++ b/core/templates/core/product_form.html @@ -0,0 +1,18 @@ +{% extends "base.html" %} + +{% block title %}{% if object %}Edit{% else %}Add{% endif %} Product - Thai Shop Inventory{% endblock %} + +{% block content %} +

{% if object %}Edit{% else %}Add{% endif %} Product

+ +
+
+
+ {% csrf_token %} + {{ form.as_p }} + + Cancel +
+
+
+{% endblock %} diff --git a/core/templates/core/product_list.html b/core/templates/core/product_list.html new file mode 100644 index 0000000..9bb5fc0 --- /dev/null +++ b/core/templates/core/product_list.html @@ -0,0 +1,81 @@ +{% extends "base.html" %} + +{% block title %}Products - Thai Shop Inventory{% endblock %} + +{% block content %} +
+

Products

+ Add Product +
+ +
+
+
Filter & Search
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+ +
+
+
Product List
+
+ + + + + + + + + + + + + + {% for product in products %} + + + + + + + + + + {% empty %} + + + + {% endfor %} + +
SKUNameCategoryPriceStockStatusActions
{{ product.sku }}{{ product.name }}{{ product.category }}฿{{ product.price|floatformat:2 }}{{ product.stock }} + {% if product.stock <= product.minimum_stock_level %} + Low Stock + {% else %} + In Stock + {% endif %} + + Edit + Delete +
No products found.
+
+
+
+{% endblock %} diff --git a/core/urls.py b/core/urls.py index 6299e3d..8749ca6 100644 --- a/core/urls.py +++ b/core/urls.py @@ -1,7 +1,18 @@ from django.urls import path +from .views import ( + DashboardView, + ProductListView, + ProductCreateView, + ProductUpdateView, + ProductDeleteView, +) -from .views import home +app_name = 'core' urlpatterns = [ - path("", home, name="home"), -] + path("", DashboardView.as_view(), name="dashboard"), + path("products/", ProductListView.as_view(), name="product-list"), + path("products/add/", ProductCreateView.as_view(), name="product-add"), + path("products//edit/", ProductUpdateView.as_view(), name="product-edit"), + path("products//delete/", ProductDeleteView.as_view(), name="product-delete"), +] \ No newline at end of file diff --git a/core/views.py b/core/views.py index c9aed12..2c53856 100644 --- a/core/views.py +++ b/core/views.py @@ -1,25 +1,52 @@ -import os -import platform +from django.shortcuts import render, redirect, get_object_or_404 +from django.urls import reverse_lazy +from django.views.generic import ListView, CreateView, UpdateView, DeleteView +from .models import Product -from django import get_version as django_version -from django.shortcuts import render -from django.utils import timezone +class DashboardView(ListView): + model = Product + template_name = 'core/index.html' + context_object_name = 'products' +class ProductListView(ListView): + model = Product + template_name = 'core/product_list.html' + context_object_name = 'products' -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() + def get_queryset(self): + queryset = super().get_queryset() + name = self.request.GET.get('name') + category = self.request.GET.get('category') - 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", ""), - } - return render(request, "core/index.html", context) + if name: + queryset = queryset.filter(name__icontains=name) + + if category: + queryset = queryset.filter(category__iexact=category) + + return queryset + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['categories'] = Product.objects.values_list('category', flat=True).distinct() + return context + +class ProductCreateView(CreateView): + model = Product + template_name = 'core/product_form.html' + fields = ['name', 'category', 'sku', 'price', 'stock', 'minimum_stock_level'] + success_url = reverse_lazy('core:product-list') + +class ProductUpdateView(UpdateView): + model = Product + template_name = 'core/product_form.html' + fields = ['name', 'category', 'sku', 'price', 'stock', 'minimum_stock_level'] + success_url = reverse_lazy('core:product-list') + +class ProductDeleteView(DeleteView): + model = Product + template_name = 'core/product_confirm_delete.html' + success_url = reverse_lazy('core:product-list') + +# The home view is now the product list view. +home = DashboardView.as_view() \ No newline at end of file diff --git a/static/css/custom.css b/static/css/custom.css index 925f6ed..a3eb3be 100644 --- a/static/css/custom.css +++ b/static/css/custom.css @@ -1,4 +1,54 @@ -/* Custom styles for the application */ -body { - font-family: system-ui, -apple-system, sans-serif; +:root { + --primary-color: #4F46E5; + --secondary-color: #10B981; + --accent-color: #F59E0B; + --bg-color: #F3F4F6; + --text-color: #111827; + --font-family-headings: 'Poppins', sans-serif; + --font-family-body: 'Inter', sans-serif; } + +body { + background-color: var(--bg-color); + color: var(--text-color); + font-family: var(--font-family-body); +} + +h1, h2, h3, h4, h5, h6 { + font-family: var(--font-family-headings); +} + +.bg-primary { + background-color: var(--primary-color) !important; +} + +.btn-primary { + background-color: var(--primary-color); + border-color: var(--primary-color); +} + +.btn-primary:hover { + opacity: 0.9; + background-color: var(--primary-color); + border-color: var(--primary-color); +} + +.btn-secondary { + background-color: var(--secondary-color); + border-color: var(--secondary-color); +} + +.btn-secondary:hover { + opacity: 0.9; + background-color: var(--secondary-color); + border-color: var(--secondary-color); +} + +.text-accent { + color: var(--accent-color); +} + +.table { + --bs-table-bg: #fff; + --bs-table-striped-bg: #f9f9f9; +} \ No newline at end of file diff --git a/staticfiles/css/custom.css b/staticfiles/css/custom.css index 108056f..a3eb3be 100644 --- a/staticfiles/css/custom.css +++ b/staticfiles/css/custom.css @@ -1,21 +1,54 @@ - :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: #4F46E5; + --secondary-color: #10B981; + --accent-color: #F59E0B; + --bg-color: #F3F4F6; + --text-color: #111827; + --font-family-headings: 'Poppins', sans-serif; + --font-family-body: 'Inter', sans-serif; } + body { - margin: 0; - font-family: 'Inter', sans-serif; - background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end)); + 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; + font-family: var(--font-family-body); } + +h1, h2, h3, h4, h5, h6 { + font-family: var(--font-family-headings); +} + +.bg-primary { + background-color: var(--primary-color) !important; +} + +.btn-primary { + background-color: var(--primary-color); + border-color: var(--primary-color); +} + +.btn-primary:hover { + opacity: 0.9; + background-color: var(--primary-color); + border-color: var(--primary-color); +} + +.btn-secondary { + background-color: var(--secondary-color); + border-color: var(--secondary-color); +} + +.btn-secondary:hover { + opacity: 0.9; + background-color: var(--secondary-color); + border-color: var(--secondary-color); +} + +.text-accent { + color: var(--accent-color); +} + +.table { + --bs-table-bg: #fff; + --bs-table-striped-bg: #f9f9f9; +} \ No newline at end of file