base.html
_product_form.html
_product_list.html
forms.py
{% load static %}
<!DOCTYPE html>
<html lang="en" class="h-full bg-gray-100">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Premium Dashboard</title>
<script src="https://unpkg.com/htmx.org@1.9.6"></script>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
[x-cloak] { display: none !important; }
</style>
</head>
<body class="h-full font-['Inter']">
<div class="min-h-full">
<!-- Dark Sidebar -->
<aside class="fixed inset-y-0 left-0 z-50 w-64 bg-gray-900 shadow-xl transform transition-transform duration-300 ease-in-out">
<div class="flex items-center justify-center h-16 bg-gray-800">
<span class="text-white text-xl font-bold tracking-wide">Premium Dashboard</span>
</div>
<nav class="mt-6 px-4 space-y-1">
<a hx-get="{% url 'product_create' %}"
hx-target="#main-content"
hx-push-url="true"
class="group flex items-center px-4 py-3 text-gray-300 rounded-lg hover:bg-gray-800 transition-colors duration-200">
<svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"/>
</svg>
Create Product
</a>
<a hx-get="{% url 'product_list' %}"
hx-target="#main-content"
hx-push-url="true"
class="group flex items-center px-4 py-3 text-gray-300 rounded-lg hover:bg-gray-800 transition-colors duration-200">
<svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/>
</svg>
Product List
</a>
</nav>
</aside>
<!-- Main Content -->
<main class="ml-64 pt-4 px-8 bg-gray-100 min-h-screen">
<!-- Top Bar -->
<div class="flex justify-end items-center h-16 mb-8">
<div class="flex items-center space-x-4">
<div class="relative">
<div class="h-10 w-10 rounded-full bg-gradient-to-r from-blue-500 to-purple-500 flex items-center justify-center text-white cursor-pointer">
JD
</div>
</div>
</div>
</div>
<!-- Dynamic Content Area -->
<div id="main-content" class="bg-white rounded-xl shadow-lg p-8">
{% block content %}{% endblock %}
</div>
</main>
</div>
</body>
</html><!-- templates/products/_product_form.html -->
<div class="max-w-2xl mx-auto">
<!-- Form Header -->
<div class="mb-8 text-center">
<h2 class="text-3xl font-bold text-gray-800 mb-2">Create New Product</h2>
<p class="text-gray-500">Add a new product to your inventory</p>
</div>
<form method="POST" hx-post="{% url 'product_create' %}" hx-target="#main-content" class="space-y-6">
{% csrf_token %}
<!-- Name Field -->
<div class="relative z-0">
{{ form.name }}
<label for="{{ form.name.id_for_label }}"
class="absolute left-3 -top-3.5 bg-white px-1 text-gray-600 text-sm transition-all
peer-placeholder-shown:text-base peer-placeholder-shown:text-gray-400
peer-placeholder-shown:top-2 peer-focus:-top-3.5 peer-focus:text-sm peer-focus:text-blue-600">
Product Name
</label>
</div>
<!-- Price Field -->
<div class="relative z-0">
<div class="relative">
<span class="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400">$</span>
{{ form.price }}
<label for="{{ form.price.id_for_label }}"
class="absolute left-8 -top-3.5 bg-white px-1 text-gray-600 text-sm transition-all
peer-placeholder-shown:text-base peer-placeholder-shown:text-gray-400
peer-placeholder-shown:top-2 peer-focus:-top-3.5 peer-focus:text-sm peer-focus:text-blue-600">
Price
</label>
</div>
</div>
<!-- Description Field -->
<div class="relative z-0">
{{ form.description }}
<label for="{{ form.description.id_for_label }}"
class="absolute left-3 -top-3.5 bg-white px-1 text-gray-600 text-sm transition-all
peer-placeholder-shown:text-base peer-placeholder-shown:text-gray-400
peer-placeholder-shown:top-2 peer-focus:-top-3.5 peer-focus:text-sm peer-focus:text-blue-600">
Description
</label>
</div>
<!-- Submit Button -->
<button type="submit"
class="w-full py-3 px-6 bg-gradient-to-r from-blue-600 to-purple-600
text-white font-medium rounded-lg shadow-md hover:shadow-lg
transition-all duration-200 transform hover:scale-[1.02]">
Create Product
</button>
</form>
</div>
<!-- Widget Styling এর জন্য forms.py আপডেট করুন --><div class="overflow-hidden rounded-lg border border-gray-200 shadow-lg">
<div class="px-6 py-4 border-b border-gray-200 bg-gray-50">
<div class="flex items-center justify-between">
<h3 class="text-lg font-semibold text-gray-900">Product Inventory</h3>
<span class="text-sm text-gray-500">{{ products.count }} items</span>
</div>
</div>
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Product</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Price</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Description</th>
<th class="px-6 py-3"></th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
{% for product in products %}
<tr class="hover:bg-gray-50 transition-colors duration-150">
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm font-medium text-gray-900">{{ product.name }}</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">${{ product.price }}</div>
</td>
<td class="px-6 py-4">
<div class="text-sm text-gray-500 max-w-xs truncate">{{ product.description }}</div>
</td>
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<a href="#" class="text-blue-600 hover:text-blue-900 mr-4">Edit</a>
<a href="#" class="text-red-600 hover:text-red-900">Delete</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div># products/forms.py
from django import forms
from .models import Product
class ProductForm(forms.ModelForm):
class Meta:
model = Product
fields = ['name', 'price', 'description']
widgets = {
'name': forms.TextInput(attrs={
'class': 'block w-full px-3 py-2.5 border border-gray-300 rounded-lg peer placeholder-transparent focus:border-blue-500 focus:ring-1 focus:ring-blue-500 outline-none transition-all',
'placeholder': ' ',
}),
'price': forms.NumberInput(attrs={
'class': 'block w-full pl-7 pr-3 py-2.5 border border-gray-300 rounded-lg peer placeholder-transparent focus:border-blue-500 focus:ring-1 focus:ring-blue-500 outline-none transition-all',
'placeholder': ' ',
}),
'description': forms.Textarea(attrs={
'class': 'block w-full px-3 py-2.5 border border-gray-300 rounded-lg peer placeholder-transparent focus:border-blue-500 focus:ring-1 focus:ring-blue-500 outline-none transition-all',
'placeholder': ' ',
'rows': 3,
}),
}