521 lines
18 KiB
HTML
521 lines
18 KiB
HTML
{% extends "base.html" %}
|
||
|
||
{% block title %}Добавление поставщика{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="container">
|
||
<div class="row justify-content-center">
|
||
<div class="col-md-8">
|
||
<!-- Хлебные крошки -->
|
||
<nav aria-label="breadcrumb" class="mb-3">
|
||
<ol class="breadcrumb">
|
||
<li class="breadcrumb-item"><a href="{{ url_for('index') }}">Поставщики</a></li>
|
||
<li class="breadcrumb-item active">Добавление поставщика</li>
|
||
</ol>
|
||
</nav>
|
||
|
||
<div class="form-card">
|
||
<div class="form-card-header">
|
||
<h2 class="form-card-title">
|
||
<i class="fas fa-truck"></i> Добавление нового поставщика
|
||
</h2>
|
||
</div>
|
||
|
||
<div class="form-card-body">
|
||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||
{% if messages %}
|
||
{% for category, message in messages %}
|
||
<div class="alert alert-{{ 'danger' if category == 'error' else 'success' }} alert-dismissible fade show">
|
||
<i class="fas fa-{{ 'exclamation-circle' if category == 'error' else 'check-circle' }} me-2"></i>
|
||
{{ message }}
|
||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||
</div>
|
||
{% endfor %}
|
||
{% endif %}
|
||
{% endwith %}
|
||
|
||
<form method="POST" id="supplierForm">
|
||
<div class="row">
|
||
<!-- Левая колонка - Основная информация -->
|
||
<div class="col-md-6">
|
||
<h5 class="section-title">
|
||
<i class="fas fa-info-circle"></i> Основная информация
|
||
</h5>
|
||
|
||
<div class="form-group">
|
||
<label for="name" class="form-label">
|
||
<i class="fas fa-building"></i>
|
||
Название компании
|
||
</label>
|
||
<input type="text" class="form-control" id="name" name="name"
|
||
required maxlength="255" placeholder="ООО 'СтройМатериалы'"
|
||
onkeypress="return blockNumbers(event)" onpaste="return blockNumbersPaste(event)">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="director" class="form-label">
|
||
<i class="fas fa-user-tie"></i>
|
||
Директор (ФИО)
|
||
</label>
|
||
<input type="text" class="form-control" id="director" name="director"
|
||
maxlength="255" placeholder="Петров Петр Петрович"
|
||
onkeypress="return blockNumbers(event)" onpaste="return blockNumbersPaste(event)">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="contractor_type_id" class="form-label">
|
||
<i class="fas fa-tag"></i>
|
||
Тип поставщика
|
||
</label>
|
||
<select class="form-select" id="contractor_type_id" name="contractor_type_id" required>
|
||
<option value="" selected disabled>Выберите тип поставщика</option>
|
||
{% for type in contractor_types %}
|
||
<option value="{{ type.id }}">{{ type.type_name }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="rating" class="form-label">
|
||
<i class="fas fa-star"></i>
|
||
Рейтинг надежности
|
||
</label>
|
||
<input type="number" class="form-control" id="rating" name="rating"
|
||
min="0" max="5" step="0.1" value="5.0">
|
||
<div class="form-text">От 0 до 5 (чем выше, тем надежнее)</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Правая колонка - Контактные данные -->
|
||
<div class="col-md-6">
|
||
<h5 class="section-title">
|
||
<i class="fas fa-address-card"></i> Контактные данные
|
||
</h5>
|
||
|
||
<div class="form-group">
|
||
<label for="email" class="form-label">
|
||
<i class="fas fa-envelope"></i>
|
||
Email
|
||
</label>
|
||
<input type="email" class="form-control" id="email" name="email"
|
||
required maxlength="255" placeholder="info@stroymaterial.ru">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="phone" class="form-label">
|
||
<i class="fas fa-phone"></i>
|
||
Телефон
|
||
</label>
|
||
<input type="tel" class="form-control" id="phone" name="phone"
|
||
maxlength="50" placeholder="+7 (495) 123-45-67"
|
||
onkeypress="return allowPhoneNumbers(event)">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="inn" class="form-label">
|
||
<i class="fas fa-id-card"></i>
|
||
ИНН
|
||
</label>
|
||
<input type="text" class="form-control" id="inn" name="inn"
|
||
maxlength="12" placeholder="1234567890"
|
||
onkeypress="return allowOnlyNumbers(event)" onpaste="return allowNumbersPaste(event)">
|
||
<div class="form-text">10 или 12 цифр</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Адрес на всю ширину -->
|
||
<div class="col-12">
|
||
<div class="form-group">
|
||
<label for="address" class="form-label">
|
||
<i class="fas fa-map-marker-alt"></i>
|
||
Юридический адрес
|
||
</label>
|
||
<textarea class="form-control" id="address" name="address"
|
||
rows="2" maxlength="500" placeholder="г. Москва, ул. Строителей, д. 1"></textarea>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Кнопки -->
|
||
<div class="form-actions">
|
||
<a href="{{ url_for('index') }}" class="btn btn-outline">
|
||
<i class="fas fa-times"></i> Отмена
|
||
</a>
|
||
<button type="submit" class="btn btn-primary">
|
||
<i class="fas fa-save"></i> Добавить поставщика
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<style>
|
||
/* ===== ОСНОВНЫЕ ПЕРЕМЕННЫЕ ===== */
|
||
:root {
|
||
--antique-white: #FAEBD7;
|
||
--light-brown: #DEB887;
|
||
--brown: #A0522D;
|
||
--dark-brown: #8B4513;
|
||
}
|
||
|
||
/* ===== ХЛЕБНЫЕ КРОШКИ ===== */
|
||
.breadcrumb {
|
||
background: none;
|
||
padding: 0;
|
||
}
|
||
|
||
.breadcrumb-item a {
|
||
color: var(--brown);
|
||
text-decoration: none;
|
||
font-family: 'Verdana', sans-serif;
|
||
}
|
||
|
||
.breadcrumb-item a:hover {
|
||
text-decoration: underline;
|
||
}
|
||
|
||
.breadcrumb-item.active {
|
||
color: #6c757d;
|
||
font-family: 'Verdana', sans-serif;
|
||
}
|
||
|
||
.breadcrumb-item + .breadcrumb-item::before {
|
||
color: var(--light-brown);
|
||
}
|
||
|
||
/* ===== КАРТОЧКА ФОРМЫ ===== */
|
||
.form-card {
|
||
background: white;
|
||
border: 1px solid var(--light-brown);
|
||
border-radius: 16px;
|
||
box-shadow: 0 4px 20px rgba(160, 82, 45, 0.1);
|
||
overflow: hidden;
|
||
}
|
||
|
||
.form-card-header {
|
||
background: linear-gradient(135deg, var(--brown) 0%, var(--dark-brown) 100%);
|
||
padding: 20px 25px;
|
||
color: white;
|
||
}
|
||
|
||
.form-card-title {
|
||
font-size: 1.4rem;
|
||
font-weight: 600;
|
||
font-family: 'Verdana', sans-serif;
|
||
margin: 0;
|
||
}
|
||
|
||
.form-card-title i {
|
||
margin-right: 10px;
|
||
color: white;
|
||
}
|
||
|
||
.form-card-body {
|
||
padding: 25px;
|
||
}
|
||
|
||
/* ===== ЗАГОЛОВКИ СЕКЦИЙ ===== */
|
||
.section-title {
|
||
color: var(--brown);
|
||
font-size: 1.1rem;
|
||
font-weight: 600;
|
||
margin-bottom: 20px;
|
||
padding-bottom: 10px;
|
||
border-bottom: 2px solid var(--light-brown);
|
||
font-family: 'Verdana', sans-serif;
|
||
}
|
||
|
||
.section-title i {
|
||
color: var(--brown);
|
||
margin-right: 8px;
|
||
}
|
||
|
||
/* ===== ЭЛЕМЕНТЫ ФОРМЫ ===== */
|
||
.form-group {
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.form-label {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
color: var(--brown);
|
||
font-weight: 600;
|
||
font-size: 0.95rem;
|
||
margin-bottom: 6px;
|
||
font-family: 'Verdana', sans-serif;
|
||
}
|
||
|
||
.form-label i {
|
||
color: var(--brown);
|
||
font-size: 1rem;
|
||
}
|
||
|
||
.form-control, .form-select {
|
||
width: 100%;
|
||
height: 42px;
|
||
padding: 0 12px;
|
||
border: 2px solid var(--light-brown);
|
||
border-radius: 10px;
|
||
font-size: 0.95rem;
|
||
font-family: 'Verdana', sans-serif;
|
||
transition: all 0.2s ease;
|
||
background: white;
|
||
}
|
||
|
||
.form-control:focus, .form-select:focus {
|
||
outline: none;
|
||
border-color: var(--brown);
|
||
box-shadow: 0 0 0 3px rgba(160, 82, 45, 0.1);
|
||
}
|
||
|
||
.form-control:hover, .form-select:hover {
|
||
border-color: var(--brown);
|
||
}
|
||
|
||
textarea.form-control {
|
||
height: auto;
|
||
padding: 10px 12px;
|
||
resize: vertical;
|
||
}
|
||
|
||
.form-text {
|
||
font-size: 0.8rem;
|
||
color: #6c757d;
|
||
margin-top: 4px;
|
||
font-family: 'Verdana', sans-serif;
|
||
}
|
||
|
||
/* ===== КНОПКИ ===== */
|
||
.form-actions {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
margin-top: 25px;
|
||
padding-top: 20px;
|
||
border-top: 2px solid var(--light-brown);
|
||
}
|
||
|
||
.btn {
|
||
padding: 10px 25px;
|
||
border-radius: 10px;
|
||
font-size: 0.95rem;
|
||
font-weight: 500;
|
||
font-family: 'Verdana', sans-serif;
|
||
transition: all 0.2s ease;
|
||
border: none;
|
||
cursor: pointer;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
text-decoration: none;
|
||
}
|
||
|
||
.btn-primary {
|
||
background: var(--brown);
|
||
color: white;
|
||
}
|
||
|
||
.btn-primary:hover {
|
||
background: var(--dark-brown);
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 4px 12px rgba(160, 82, 45, 0.3);
|
||
}
|
||
|
||
.btn-outline {
|
||
background: white;
|
||
border: 2px solid var(--light-brown);
|
||
color: var(--brown);
|
||
}
|
||
|
||
.btn-outline:hover {
|
||
background: var(--antique-white);
|
||
border-color: var(--brown);
|
||
transform: translateY(-2px);
|
||
}
|
||
|
||
/* ===== АЛЕРТЫ ===== */
|
||
.alert {
|
||
border-radius: 10px;
|
||
border: 1px solid var(--light-brown);
|
||
font-family: 'Verdana', sans-serif;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.alert-success {
|
||
background: var(--antique-white);
|
||
color: var(--brown);
|
||
border-left: 4px solid #28a745;
|
||
}
|
||
|
||
.alert-danger {
|
||
background: var(--antique-white);
|
||
color: #721c24;
|
||
border-left: 4px solid #dc3545;
|
||
}
|
||
|
||
/* ===== ИКОНКИ ===== */
|
||
i {
|
||
color: var(--brown);
|
||
}
|
||
|
||
.btn-primary i, .btn-outline i {
|
||
color: inherit;
|
||
}
|
||
|
||
/* ===== АДАПТИВНОСТЬ ===== */
|
||
@media (max-width: 768px) {
|
||
.form-card-body {
|
||
padding: 20px;
|
||
}
|
||
|
||
.form-actions {
|
||
flex-direction: column-reverse;
|
||
gap: 10px;
|
||
}
|
||
|
||
.form-actions .btn {
|
||
width: 100%;
|
||
justify-content: center;
|
||
}
|
||
|
||
.col-md-6 {
|
||
width: 100%;
|
||
}
|
||
|
||
.section-title {
|
||
margin-top: 15px;
|
||
}
|
||
|
||
.section-title:first-of-type {
|
||
margin-top: 0;
|
||
}
|
||
}
|
||
</style>
|
||
|
||
{% block scripts %}
|
||
<script>
|
||
// Запрет на ввод цифр в текстовые поля
|
||
function blockNumbers(event) {
|
||
const key = event.key;
|
||
if (key === ' ' || key === 'Backspace' || key === 'Delete' || key === 'Tab' ||
|
||
key === 'Enter' || key === 'ArrowLeft' || key === 'ArrowRight' ||
|
||
key === 'ArrowUp' || key === 'ArrowDown' || key === 'Home' || key === 'End') {
|
||
return true;
|
||
}
|
||
|
||
if (key >= '0' && key <= '9') {
|
||
event.preventDefault();
|
||
alert('Цифры запрещены в этом поле');
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
function blockNumbersPaste(event) {
|
||
event.preventDefault();
|
||
const pastedText = (event.clipboardData || window.clipboardData).getData('text');
|
||
const cleanedText = pastedText.replace(/[0-9]/g, '');
|
||
|
||
const input = event.target;
|
||
const start = input.selectionStart;
|
||
const end = input.selectionEnd;
|
||
const currentValue = input.value;
|
||
const newValue = currentValue.substring(0, start) + cleanedText + currentValue.substring(end);
|
||
input.value = newValue;
|
||
|
||
if (pastedText.match(/[0-9]/)) {
|
||
alert('Цифры были удалены из вставленного текста');
|
||
}
|
||
}
|
||
|
||
// Только цифры для ИНН
|
||
function allowOnlyNumbers(event) {
|
||
const key = event.key;
|
||
if (key === 'Backspace' || key === 'Delete' || key === 'Tab' ||
|
||
key === 'Enter' || key === 'ArrowLeft' || key === 'ArrowRight' ||
|
||
key === 'ArrowUp' || key === 'ArrowDown' || key === 'Home' || key === 'End') {
|
||
return true;
|
||
}
|
||
|
||
if (key >= '0' && key <= '9') {
|
||
return true;
|
||
}
|
||
|
||
event.preventDefault();
|
||
return false;
|
||
}
|
||
|
||
function allowNumbersPaste(event) {
|
||
event.preventDefault();
|
||
const pastedText = (event.clipboardData || window.clipboardData).getData('text');
|
||
const cleanedText = pastedText.replace(/[^0-9]/g, '');
|
||
|
||
const input = event.target;
|
||
const start = input.selectionStart;
|
||
const end = input.selectionEnd;
|
||
const currentValue = input.value;
|
||
const newValue = currentValue.substring(0, start) + cleanedText + currentValue.substring(end);
|
||
input.value = newValue;
|
||
}
|
||
|
||
// Для телефона
|
||
function allowPhoneNumbers(event) {
|
||
const key = event.key;
|
||
const allowedKeys = ['+', '-', '(', ')', ' '];
|
||
|
||
if (key === 'Backspace' || key === 'Delete' || key === 'Tab' ||
|
||
key === 'Enter' || key === 'ArrowLeft' || key === 'ArrowRight' ||
|
||
key === 'ArrowUp' || key === 'ArrowDown' || key === 'Home' || key === 'End') {
|
||
return true;
|
||
}
|
||
|
||
if (allowedKeys.includes(key)) {
|
||
return true;
|
||
}
|
||
|
||
if (key >= '0' && key <= '9') {
|
||
return true;
|
||
}
|
||
|
||
event.preventDefault();
|
||
return false;
|
||
}
|
||
|
||
// Валидация формы
|
||
document.getElementById('supplierForm').addEventListener('submit', function(e) {
|
||
const inn = document.getElementById('inn').value;
|
||
const name = document.getElementById('name').value;
|
||
|
||
if (name.match(/[0-9]/)) {
|
||
e.preventDefault();
|
||
alert('Название компании не должно содержать цифры');
|
||
return false;
|
||
}
|
||
|
||
if (inn && !/^\d{10,12}$/.test(inn)) {
|
||
e.preventDefault();
|
||
alert('ИНН должен содержать 10 или 12 цифр');
|
||
return false;
|
||
}
|
||
|
||
const rating = parseFloat(document.getElementById('rating').value);
|
||
if (rating < 0 || rating > 5) {
|
||
e.preventDefault();
|
||
alert('Рейтинг должен быть от 0 до 5');
|
||
return false;
|
||
}
|
||
|
||
const email = document.getElementById('email').value;
|
||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||
if (!emailRegex.test(email)) {
|
||
e.preventDefault();
|
||
alert('Введите корректный email адрес');
|
||
return false;
|
||
}
|
||
});
|
||
</script>
|
||
{% endblock %}
|
||
{% endblock %} |