Added Repository

This commit is contained in:
2026-01-30 14:02:35 +03:30
parent 8917e625a5
commit dbc8f70b4a
53 changed files with 7758 additions and 2 deletions

View File

@@ -0,0 +1,131 @@
{% extends "base.html" %}
{% block styles %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/add_product.css') }}">
{% endblock %}
{% block scripts %}
<script src="{{ url_for('static', filename='js/add_product.js') }}" defer></script>
{% endblock %}
{% block content %}
<div class="admin-container">
<h2>Add New Product</h2>
<form method="POST" enctype="multipart/form-data" class="product-form">
<div class="form-grid">
<div class="form-section">
<h3>Basic Information</h3>
<div class="form-group">
<label for="name">Product Name *</label>
<input type="text" id="name" name="name" required class="form-control">
</div>
<div class="form-group">
<label for="sku">SKU (Stock Keeping Unit)</label>
<input type="text" id="sku" name="sku" class="form-control" placeholder="e.g., TSHIRT-RED-M">
</div>
<div class="form-group">
<label for="description">Description</label>
<textarea id="description" name="description" class="form-control" rows="4"></textarea>
</div>
<div class="form-row">
<div class="form-group">
<label for="price">Price ($) *</label>
<input type="number" step="0.01" id="price" name="price" required class="form-control">
</div>
<div class="form-group">
<label for="stock">Stock Quantity *</label>
<input type="number" id="stock" name="stock" value="0" min="0" required class="form-control">
</div>
</div>
</div>
<div class="form-section">
<h3>Product Details</h3>
<div class="form-group">
<label for="category_id">Category *</label>
<select id="category_id" name="category_id" class="form-control">
<option value="">-- Select Category --</option>
{% for c in categories %}
<option value="{{ c.id }}">{{ c.name }}</option>
{% endfor %}
</select>
</div>
<div class="form-row">
<div class="form-group">
<label for="material">Material</label>
<input type="text" id="material" name="material" class="form-control" placeholder="e.g., Cotton, Polyester">
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="size">Size</label>
<select id="size" name="size" class="form-control">
<option value="">-- Select Size --</option>
{% for size in sizes %}
<option value="{{ size }}">{{ size }}</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="color">Color</label>
<input type="text" id="color" name="color" class="form-control" placeholder="e.g., Red, Blue">
</div>
</div>
<div class="form-group">
<label for="company">Brand/Company</label>
<input type="text" id="company" name="company" class="form-control" placeholder="e.g., Nike, Adidas">
</div>
<div class="form-row">
<div class="form-group">
<label for="weight">Weight (kg)</label>
<input type="number" step="0.01" id="weight" name="weight" class="form-control" placeholder="0.5">
</div>
<div class="form-group">
<label for="dimensions">Dimensions</label>
<input type="text" id="dimensions" name="dimensions" class="form-control" placeholder="10x5x3 cm">
</div>
</div>
</div>
<div class="form-section">
<h3>Product Images</h3>
<div class="form-group">
<label>Upload Images *</label>
<div class="image-upload-area" id="image-upload-area">
<div class="upload-prompt">
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
<polyline points="17 8 12 3 7 8"></polyline>
<line x1="12" y1="3" x2="12" y2="15"></line>
</svg>
<p>Click or drag images here</p>
<p class="upload-hint">First image will be primary</p>
</div>
<input type="file" name="images[]" multiple accept="image/*" class="image-input" id="image-input">
</div>
<div class="image-preview" id="image-preview"></div>
</div>
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">Save Product</button>
<a href="{{ url_for('admin.dashboard') }}" class="btn btn-secondary">Cancel</a>
</div>
</form>
</div>
{% endblock %}

View File

@@ -0,0 +1,72 @@
{% extends "base.html" %}
{% block styles %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/categories.css') }}">
{% endblock %}
{% block content %}
<div class="admin-container">
<h2>Manage Categories</h2>
<div class="card mb-4">
<div class="card-header">
<h3>Add New Category</h3>
</div>
<div class="card-body">
<form method="POST" action="{{ url_for('admin.add_category') }}" class="row g-3">
<div class="col-md-8">
<input type="text" name="name" class="form-control" placeholder="Category name" required>
</div>
<div class="col-md-4">
<button type="submit" class="btn btn-primary w-100">Add Category</button>
</div>
</form>
</div>
</div>
<div class="card">
<div class="card-header">
<h3>All Categories ({{ categories|length }})</h3>
</div>
<div class="card-body">
{% if categories %}
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Products</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for category in categories %}
<tr>
<td>{{ category.id }}</td>
<td>{{ category.name }}</td>
<td>{{ category.products|length }}</td>
<td>
{% if category.products|length == 0 %}
<form method="POST" action="{{ url_for('admin.delete_category', id=category.id) }}"
style="display: inline;" onsubmit="return confirm('Delete category {{ category.name }}?')">
<button type="submit" class="btn btn-sm btn-danger">Delete</button>
</form>
{% else %}
<button class="btn btn-sm btn-secondary" disabled title="Cannot delete category with products">
Delete
</button>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="alert alert-info">No categories found.</div>
{% endif %}
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,54 @@
{% extends "base.html" %}
{% block styles %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/dashboard.css') }}">
{% endblock %}
{% block content %}
<h2>Admin Dashboard</h2>
<a href="{{ url_for('admin.add_product') }}" class="btn btn-success">Add New Product</a>
<table class="admin-table">
<thead>
<tr>
<th>Image</th>
<th>ID</th>
<th>Name</th>
<th>Description</th>
<th>Price</th>
<th>Stock</th>
<th>Category</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for p in products %}
<tr>
<td>
<img src="{{ p.get_image_url() }}" alt="{{ p.name }}" style="width: 60px; height: 60px; object-fit: cover;">
</td>
<td>{{ p.id }}</td>
<td>{{ p.name }}</td>
<td>{{ p.description[:50] }}{% if p.description|length > 50 %}...{% endif %}</td>
<td>${{ "%.2f"|format(p.price) }}</td>
<td>
{% if p.stock > 10 %}
<span class="stock-high">{{ p.stock }}</span>
{% elif p.stock > 0 %}
<span class="stock-low">{{ p.stock }}</span>
{% else %}
<span class="stock-out">Out of Stock</span>
{% endif %}
</td>
<td>{{ p.category.name if p.category else 'N/A' }}</td>
<td class="actions">
<a href="{{ url_for('admin.edit_product', id=p.id) }}" class="btn btn-sm btn-primary">Edit</a>
<form method="POST" action="{{ url_for('admin.delete_product', id=p.id) }}" style="display:inline;"
onsubmit="return confirm('Delete this product?')">
<button type="submit" class="btn btn-sm btn-danger">Delete</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

View File

@@ -0,0 +1,169 @@
{% extends "base.html" %}
{% block styles %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/edit_product.css') }}">
{% endblock %}
{% block scripts %}
<script src="{{ url_for('static', filename='js/edit_product.js') }}" defer></script>
{% endblock %}
{% block content %}
<div class="admin-container">
<h2>Edit Product: {{ product.name }}</h2>
<form method="POST" enctype="multipart/form-data" class="product-form" id="product-form">
<div class="form-grid">
<div class="form-section">
<h3>Basic Information</h3>
<div class="form-group">
<label for="name">Product Name *</label>
<input type="text" id="name" name="name" value="{{ product.name }}" required class="form-control">
</div>
<div class="form-group">
<label for="sku">SKU (Stock Keeping Unit)</label>
<input type="text" id="sku" name="sku" value="{{ product.sku or '' }}" class="form-control"
placeholder="e.g., TSHIRT-RED-M">
</div>
<div class="form-group">
<label for="description">Description</label>
<textarea id="description" name="description" class="form-control"
rows="4">{{ product.description or '' }}</textarea>
</div>
<div class="form-row">
<div class="form-group">
<label for="price">Price ($) *</label>
<input type="number" step="0.01" id="price" name="price" value="{{ product.price }}" required
class="form-control" min="0.01">
</div>
<div class="form-group">
<label for="stock">Stock Quantity *</label>
<input type="number" id="stock" name="stock" value="{{ product.stock }}" min="0" required
class="form-control">
</div>
</div>
</div>
<div class="form-section">
<h3>Product Details</h3>
<div class="form-group">
<label for="category_id">Category *</label>
<select id="category_id" name="category_id" class="form-control" required>
<option value="">-- Select Category --</option>
{% for c in categories %}
<option value="{{ c.id }}" {% if product.category_id==c.id %}selected{% endif %}>
{{ c.name }}
</option>
{% endfor %}
</select>
</div>
<div class="form-row">
<div class="form-group">
<label for="material">Material</label>
<input type="text" id="material" name="material" value="{{ product.material or '' }}" class="form-control"
placeholder="e.g., Cotton, Polyester, Denim">
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="size">Size</label>
<select id="size" name="size" class="form-control">
<option value="">-- Select Size --</option>
{% for size in sizes %}
<option value="{{ size }}" {% if product.size==size %}selected{% endif %}>
{{ size }}
</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="color">Color</label>
<input type="text" id="color" name="color" value="{{ product.color or '' }}" class="form-control"
placeholder="e.g., Red, Blue, Black">
</div>
</div>
<div class="form-group">
<label for="company">Brand/Company</label>
<input type="text" id="company" name="company" value="{{ product.company or '' }}" class="form-control"
placeholder="e.g., Nike, Adidas, Levi's">
</div>
<div class="form-row">
<div class="form-group">
<label for="weight">Weight (kg)</label>
<input type="number" step="0.01" id="weight" name="weight" value="{{ product.weight or '' }}"
class="form-control" placeholder="0.5" min="0">
</div>
<div class="form-group">
<label for="dimensions">Dimensions</label>
<input type="text" id="dimensions" name="dimensions" value="{{ product.dimensions or '' }}"
class="form-control" placeholder="10x5x3 cm">
</div>
</div>
</div>
<div class="form-section">
<h3>Current Images</h3>
<div class="current-images">
{% if product.images %}
<div class="image-grid">
{% for image in product.images %}
<div class="image-item" data-id="{{ image.id }}">
<img src="/static/uploads/products/{{ image.filename }}" alt="Product Image {{ loop.index }}">
<div class="image-actions">
<label class="primary-checkbox">
<input type="radio" name="primary_image" value="{{ image.id }}" {% if image.is_primary %}checked{%
endif %}>
Primary
</label>
<button type="button" class="btn-delete-image" onclick="deleteImage('{{ image.id }}')">
Delete
</button>
</div>
</div>
{% endfor %}
</div>
{% else %}
<p class="no-images">No images uploaded yet.</p>
{% endif %}
</div>
<h3 style="margin-top: 30px;">Add New Images</h3>
<div class="form-group">
<div class="image-upload-area" id="image-upload-area">
<div class="upload-prompt">
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
<polyline points="17 8 12 3 7 8"></polyline>
<line x1="12" y1="3" x2="12" y2="15"></line>
</svg>
<p>Click or drag images here</p>
</div>
<input type="file" name="images[]" multiple accept="image/*" class="image-input" id="image-input">
</div>
<div class="image-preview" id="image-preview"></div>
</div>
</div>
</div>
<input type="hidden" name="deleted_images" id="deleted-images" value="">
<div class="form-actions">
<button type="submit" class="btn btn-primary">Update Product</button>
<a href="{{ url_for('admin.dashboard') }}" class="btn btn-secondary">Cancel</a>
</div>
</form>
</div>
{% endblock %}