223 lines
10 KiB
HTML
223 lines
10 KiB
HTML
{% extends "base.html" %}
|
||
|
||
{% block title %}Добавление товара{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="container">
|
||
<div class="row justify-content-center">
|
||
<div class="col-md-8">
|
||
<div class="card">
|
||
<div class="card-header" style="background: linear-gradient(135deg, var(--steel-blue) 0%, var(--light-steel-blue) 100%); color: white;">
|
||
<h2 class="card-title mb-0">
|
||
<i class="fas fa-box"></i> Добавление товара
|
||
</h2>
|
||
</div>
|
||
<div class="card-body">
|
||
<form method="POST" id="productForm">
|
||
<div class="row">
|
||
<div class="col-md-6 mb-3">
|
||
<label for="product_name" class="form-label">Наименование</label>
|
||
<input type="text" class="form-control" id="product_name" name="product_name" required maxlength="255"
|
||
onkeypress="return isLetterKey(event)"
|
||
oninput="this.value = this.value.replace(/[^а-яА-ЯёЁa-zA-Z\s]/g, '')">
|
||
<small class="form-text text-muted">Только буквы</small>
|
||
</div>
|
||
|
||
<div class="col-md-6 mb-3">
|
||
<label for="article" class="form-label">Артикул</label>
|
||
<input type="text" class="form-control" id="article" name="article" readonly
|
||
value="{{ '%07d'|format(range(1, 10000000)|random) }}">
|
||
<small class="form-text text-muted">Генерируется автоматически</small>
|
||
</div>
|
||
|
||
<div class="col-md-6 mb-3">
|
||
<label for="category_id" class="form-label">Категория</label>
|
||
<select class="form-select" id="category_id" name="category_id" required>
|
||
<option value="">Выберите категорию</option>
|
||
{% for category in categories %}
|
||
<option value="{{ category.id }}">{{ category.category_name }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
</div>
|
||
|
||
<div class="col-md-6 mb-3">
|
||
<label for="material_id" class="form-label">Материал</label>
|
||
<select class="form-select" id="material_id" name="material_id">
|
||
<option value="">Не выбран</option>
|
||
{% for material in materials %}
|
||
<option value="{{ material.id }}">{{ material.material_name }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
</div>
|
||
|
||
<div class="col-12 mb-3">
|
||
<label for="description" class="form-label">Описание</label>
|
||
<textarea class="form-control" id="description" name="description" rows="3" maxlength="500"></textarea>
|
||
</div>
|
||
|
||
<div class="col-md-6 mb-3">
|
||
<label for="production_time_days" class="form-label">Время изготовления (дней)</label>
|
||
<input type="number" class="form-control" id="production_time_days" name="production_time_days"
|
||
min="1" value="1" required onkeypress="return isNumberKey(event)">
|
||
<small class="form-text text-muted">Сколько дней нужно на производство</small>
|
||
</div>
|
||
|
||
<div class="col-md-6 mb-3">
|
||
<label for="min_price" class="form-label">Цена</label>
|
||
<input type="number" class="form-control" id="min_price" name="min_price"
|
||
min="0" step="0.01" required value="0.00" onkeypress="return isNumberKey(event)">
|
||
</div>
|
||
|
||
<div class="col-md-6 mb-3">
|
||
<label for="quantity_in_stock" class="form-label">Количество на складе</label>
|
||
<input type="number" class="form-control" id="quantity_in_stock" name="quantity_in_stock"
|
||
min="0" value="0" onkeypress="return isNumberKey(event)">
|
||
</div>
|
||
</div>
|
||
|
||
<div class="row mt-4">
|
||
<div class="col-12">
|
||
<div class="d-flex justify-content-between">
|
||
<a href="{{ url_for('catalog') }}" class="btn btn-secondary">
|
||
<i class="fas fa-arrow-left"></i> Назад в каталог
|
||
</a>
|
||
<button type="submit" class="btn btn-primary">
|
||
<i class="fas fa-save"></i> Сохранить
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
// Функция для проверки ввода только цифр
|
||
function isNumberKey(evt) {
|
||
var charCode = (evt.which) ? evt.which : evt.keyCode;
|
||
if (charCode > 31 && (charCode < 48 || charCode > 57)) {
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
// Функция для проверки ввода только букв
|
||
function isLetterKey(evt) {
|
||
var charCode = (evt.which) ? evt.which : evt.keyCode;
|
||
// Разрешаем буквы, пробел, backspace, delete, tab, enter
|
||
if (charCode == 32 || charCode == 8 || charCode == 46 || charCode == 9 || charCode == 13) {
|
||
return true;
|
||
}
|
||
// Русские и английские буквы
|
||
if ((charCode >= 65 && charCode <= 90) || (charCode >= 97 && charCode <= 122) ||
|
||
(charCode >= 1040 && charCode <= 1103)) {
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
document.getElementById('productForm').addEventListener('submit', function(e) {
|
||
const price = parseFloat(document.getElementById('min_price').value);
|
||
if (price <= 0) {
|
||
e.preventDefault();
|
||
alert('Цена должна быть больше 0');
|
||
return false;
|
||
}
|
||
|
||
const prodDays = parseInt(document.getElementById('production_time_days').value);
|
||
if (prodDays < 1) {
|
||
e.preventDefault();
|
||
alert('Время изготовления должно быть не менее 1 дня');
|
||
return false;
|
||
}
|
||
|
||
// Проверяем наименование на наличие цифр
|
||
const productName = document.getElementById('product_name').value;
|
||
if (/\d/.test(productName)) {
|
||
e.preventDefault();
|
||
alert('Наименование не должно содержать цифры');
|
||
return false;
|
||
}
|
||
});
|
||
|
||
// Очищаем поле наименования от цифр при вводе
|
||
document.getElementById('product_name').addEventListener('input', function() {
|
||
this.value = this.value.replace(/[0-9]/g, '');
|
||
});
|
||
</script>
|
||
|
||
<style>
|
||
.card {
|
||
border: 1px solid var(--light-steel-blue);
|
||
border-radius: 15px;
|
||
box-shadow: 0 4px 10px rgba(70, 130, 180, 0.1);
|
||
}
|
||
|
||
.form-label {
|
||
color: var(--steel-blue);
|
||
font-weight: 500;
|
||
font-family: 'Franklin Gothic', 'Arial Narrow', Arial, sans-serif;
|
||
}
|
||
|
||
.form-control, .form-select {
|
||
border: 2px solid var(--light-steel-blue);
|
||
border-radius: 8px;
|
||
padding: 10px 15px;
|
||
font-family: 'Franklin Gothic', 'Arial Narrow', Arial, sans-serif;
|
||
}
|
||
|
||
.form-control:focus, .form-select:focus {
|
||
border-color: var(--steel-blue);
|
||
box-shadow: 0 0 0 0.2rem rgba(70, 130, 180, 0.25);
|
||
outline: none;
|
||
}
|
||
|
||
.btn-primary {
|
||
background: linear-gradient(135deg, var(--steel-blue) 0%, #3a6d99 100%);
|
||
border: none;
|
||
border-radius: 8px;
|
||
padding: 10px 20px;
|
||
font-family: 'Franklin Gothic', 'Arial Narrow', Arial, sans-serif;
|
||
}
|
||
|
||
.btn-primary:hover {
|
||
background: linear-gradient(135deg, #3a6d99 0%, var(--steel-blue) 100%);
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 4px 10px rgba(70, 130, 180, 0.3);
|
||
}
|
||
|
||
.btn-secondary {
|
||
background: linear-gradient(135deg, var(--light-steel-blue) 0%, #9fb6d4 100%);
|
||
border: none;
|
||
border-radius: 8px;
|
||
padding: 10px 20px;
|
||
color: #2c3e50;
|
||
font-family: 'Franklin Gothic', 'Arial Narrow', Arial, sans-serif;
|
||
}
|
||
|
||
.btn-secondary:hover {
|
||
background: linear-gradient(135deg, #9fb6d4 0%, var(--light-steel-blue) 100%);
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 4px 10px rgba(176, 196, 222, 0.3);
|
||
}
|
||
|
||
.form-text {
|
||
font-family: 'Franklin Gothic', 'Arial Narrow', Arial, sans-serif;
|
||
color: #6c757d;
|
||
}
|
||
|
||
textarea.form-control {
|
||
resize: vertical;
|
||
min-height: 80px;
|
||
}
|
||
|
||
/* Стиль для readonly поля */
|
||
#article[readonly] {
|
||
background-color: #f8f9fa;
|
||
cursor: not-allowed;
|
||
}
|
||
</style>
|
||
{% endblock %} |