From a684bede12afd9912aa8db8810a5e4650d353ab4 Mon Sep 17 00:00:00 2001 From: cursor-agent Date: Wed, 25 Feb 2026 15:22:18 +0000 Subject: [PATCH] =?UTF-8?q?Feature:=20=D1=82=D1=91=D0=BC=D0=BD=D0=B0=D1=8F?= =?UTF-8?q?=20=D1=82=D0=B5=D0=BC=D0=B0,=20=D0=BC=D0=B8=D0=BD=D0=B8=D0=BC?= =?UTF-8?q?=D0=B0=D0=BB=D0=B8=D1=81=D1=82=D0=B8=D1=87=D0=BD=D1=8B=D0=B9=20?= =?UTF-8?q?UI,=20=D1=83=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD=D0=B8=D1=8F=20?= =?UTF-8?q?UX?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- Dockerfile | 1 + HISTORY.md | 14 + app/static/css/theme.css | 431 ++++++++++++++++++ app/templates/base.html | 26 +- app/templates/documents/cash_doc_form.html | 24 +- .../documents/cash_expense_list.html | 69 +-- app/templates/documents/cash_inflow_list.html | 69 +-- .../documents/cash_transfer_list.html | 69 +-- app/templates/documents/confirm_delete.html | 18 +- .../documents/customer_order_list.html | 73 +-- app/templates/documents/order_form.html | 82 ++-- .../documents/supplier_order_form.html | 86 ++-- .../documents/supplier_order_list.html | 73 +-- app/templates/home.html | 6 +- .../references/reference_confirm_delete.html | 18 +- app/templates/references/reference_form.html | 24 +- app/templates/references/reference_list.html | 58 +-- app/templates/registration/login.html | 24 +- 18 files changed, 860 insertions(+), 305 deletions(-) create mode 100644 app/static/css/theme.css diff --git a/Dockerfile b/Dockerfile index c7da1ed..887832f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,6 +16,7 @@ RUN pip install --no-cache-dir -r requirements.txt COPY . . RUN mkdir -p logs app/logs +RUN SECRET_KEY=build python manage.py collectstatic --noinput 2>/dev/null || true EXPOSE 8000 diff --git a/HISTORY.md b/HISTORY.md index 3665483..82548f4 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,19 @@ # История изменений ERP WaterSurf +## 2025-02-25 18:45 UTC – Тёмная тема и обновлённый UI/UX + +**Проблема**: Требовался современный тёмный интерфейс, минималистичный и удобный. + +**Решение**: +- Добавлена кастомная тема в `static/css/theme.css`: тёмный фон (оттенки #0d1117–#21262d), акцент бирюзовый (#2dd4bf), типографика Inter, переменные для цветов и отступов. +- Обновлён базовый шаблон: навбар с выпадающими меню в стиле темы, контейнер контента с ограничением ширины, сообщения (alerts) в стиле темы. +- Все страницы переведены на карточки (ws-card), таблицы (ws-table) с чередованием и hover, кнопки (btn-ws-primary, btn-ws-secondary, btn-ws-danger), формы с группами полей и явными метками. +- Учтены UX: читаемый контраст, фокус на полях ввода, разделители секций в формах, выравнивание чисел в таблицах, пустые состояния. + +**Изменения**: base.html, registration/login.html, home.html, шаблоны references/* и documents/*, новый static/css/theme.css. В Dockerfile добавлен collectstatic при сборке образа. + +--- + ## 2025-02-25 18:15 UTC – Ошибка 500 при создании заказа клиента **Проблема**: При открытии формы создания заказа клиента возникала ошибка 500 (AttributeError: 'NoneType' object has no attribute 'pk'). diff --git a/app/static/css/theme.css b/app/static/css/theme.css new file mode 100644 index 0000000..e0a3fa8 --- /dev/null +++ b/app/static/css/theme.css @@ -0,0 +1,431 @@ +/* ERP WaterSurf — тёмная тема, минималистичный интерфейс */ + +:root { + --ws-bg-page: #0d1117; + --ws-bg-surface: #161b22; + --ws-bg-elevated: #21262d; + --ws-bg-hover: #30363d; + --ws-border: #30363d; + --ws-border-focus: #58a6ff; + --ws-text: #e6edf3; + --ws-text-muted: #8b949e; + --ws-accent: #2dd4bf; + --ws-accent-hover: #5eead4; + --ws-danger: #f87171; + --ws-danger-bg: rgba(248, 113, 113, 0.12); + --ws-success-bg: rgba(45, 212, 191, 0.12); + --ws-radius: 8px; + --ws-radius-sm: 6px; + --ws-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); + --ws-font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; +} + +* { + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; +} + +body { + background: var(--ws-bg-page); + color: var(--ws-text); + font-family: var(--ws-font-sans); + font-size: 15px; + line-height: 1.6; + min-height: 100vh; + -webkit-font-smoothing: antialiased; +} + +/* Навбар */ +.navbar-ws { + background: var(--ws-bg-surface) !important; + border-bottom: 1px solid var(--ws-border); + padding: 0.5rem 0; +} + +.navbar-ws .navbar-brand { + color: var(--ws-text) !important; + font-weight: 600; + font-size: 1.1rem; +} + +.navbar-ws .navbar-brand:hover { + color: var(--ws-accent) !important; +} + +.navbar-ws .nav-link { + color: var(--ws-text-muted) !important; + border-radius: var(--ws-radius-sm); + padding: 0.4rem 0.75rem !important; +} + +.navbar-ws .nav-link:hover { + color: var(--ws-text) !important; + background: var(--ws-bg-hover); +} + +.navbar-ws .dropdown-menu { + background: var(--ws-bg-elevated); + border: 1px solid var(--ws-border); + border-radius: var(--ws-radius); + box-shadow: var(--ws-shadow); + padding: 0.25rem; +} + +.navbar-ws .dropdown-item { + color: var(--ws-text); + border-radius: var(--ws-radius-sm); +} + +.navbar-ws .dropdown-item:hover { + background: var(--ws-bg-hover); + color: var(--ws-text); +} + +.navbar-ws .navbar-text { + color: var(--ws-text-muted); + font-size: 0.9rem; +} + +.navbar-ws .navbar-toggler { + border-color: var(--ws-border); + color: var(--ws-text); +} + +/* Контент */ +.ws-main { + max-width: 1200px; + margin: 0 auto; + padding: 1.5rem 1rem 3rem; +} + +.ws-page-title { + font-size: 1.5rem; + font-weight: 600; + margin-bottom: 1rem; + color: var(--ws-text); +} + +/* Карточки */ +.ws-card { + background: var(--ws-bg-surface); + border: 1px solid var(--ws-border); + border-radius: var(--ws-radius); + padding: 1.25rem; + margin-bottom: 1rem; +} + +.ws-card-header { + display: flex; + align-items: center; + justify-content: space-between; + flex-wrap: wrap; + gap: 0.75rem; + margin-bottom: 1rem; +} + +/* Таблицы */ +.ws-table-wrap { + overflow-x: auto; + border-radius: var(--ws-radius); + border: 1px solid var(--ws-border); +} + +.ws-table { + width: 100%; + border-collapse: collapse; + color: var(--ws-text); +} + +.ws-table th, +.ws-table td { + padding: 0.75rem 1rem; + text-align: left; + border-bottom: 1px solid var(--ws-border); +} + +.ws-table th { + background: var(--ws-bg-elevated); + font-weight: 600; + font-size: 0.85rem; + color: var(--ws-text-muted); + text-transform: none; +} + +.ws-table tbody tr:hover { + background: var(--ws-bg-hover); +} + +.ws-table tbody tr:last-child td { + border-bottom: none; +} + +.ws-table .ws-actions { + white-space: nowrap; +} + +.ws-table .ws-link { + color: var(--ws-accent); + text-decoration: none; + font-size: 0.9rem; +} + +.ws-table .ws-link:hover { + color: var(--ws-accent-hover); + text-decoration: underline; +} + +.ws-table .ws-link-danger { + color: var(--ws-danger); +} + +.ws-table .ws-link-danger:hover { + color: #fca5a5; +} + +/* Кнопки */ +.btn-ws-primary { + background: var(--ws-accent); + color: var(--ws-bg-page); + border: none; + border-radius: var(--ws-radius-sm); + padding: 0.5rem 1rem; + font-weight: 500; + font-size: 0.9rem; +} + +.btn-ws-primary:hover { + background: var(--ws-accent-hover); + color: var(--ws-bg-page); +} + +.btn-ws-secondary { + background: transparent; + color: var(--ws-text-muted); + border: 1px solid var(--ws-border); + border-radius: var(--ws-radius-sm); + padding: 0.5rem 1rem; + font-size: 0.9rem; +} + +.btn-ws-secondary:hover { + background: var(--ws-bg-hover); + color: var(--ws-text); + border-color: var(--ws-border); +} + +.btn-ws-danger { + background: var(--ws-danger-bg); + color: var(--ws-danger); + border: 1px solid var(--ws-danger); + border-radius: var(--ws-radius-sm); + padding: 0.5rem 1rem; + font-size: 0.9rem; +} + +.btn-ws-danger:hover { + background: var(--ws-danger); + color: var(--ws-bg-page); +} + +.ws-btn-group { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + align-items: center; +} + +/* Формы */ +.ws-form-group { + margin-bottom: 1rem; +} + +.ws-form-group label { + display: block; + font-weight: 500; + font-size: 0.9rem; + color: var(--ws-text-muted); + margin-bottom: 0.35rem; +} + +.ws-form-group input, +.ws-form-group select, +.ws-form-group textarea { + width: 100%; + max-width: 400px; + padding: 0.5rem 0.75rem; + background: var(--ws-bg-page); + border: 1px solid var(--ws-border); + border-radius: var(--ws-radius-sm); + color: var(--ws-text); + font-size: 0.95rem; +} + +.ws-form-group input:focus, +.ws-form-group select:focus, +.ws-form-group textarea:focus { + outline: none; + border-color: var(--ws-border-focus); + box-shadow: 0 0 0 2px rgba(88, 166, 255, 0.25); +} + +.ws-form-group input::placeholder, +.ws-form-group textarea::placeholder { + color: var(--ws-text-muted); + opacity: 0.8; +} + +.ws-form-login input, +.ws-form-login input[type="text"], +.ws-form-login input[type="password"] { + width: 100%; + max-width: 100%; + padding: 0.5rem 0.75rem; + background: var(--ws-bg-page); + border: 1px solid var(--ws-border); + border-radius: var(--ws-radius-sm); + color: var(--ws-text); + font-size: 0.95rem; +} + +.ws-form-login input:focus { + outline: none; + border-color: var(--ws-border-focus); + box-shadow: 0 0 0 2px rgba(88, 166, 255, 0.25); +} + +.ws-text-danger { + color: var(--ws-danger); + font-size: 0.85rem; + display: block; + margin-top: 0.25rem; +} + +.ws-form-section { + margin-top: 1.5rem; + padding-top: 1.25rem; + border-top: 1px solid var(--ws-border); +} + +.ws-form-section-title { + font-size: 1rem; + font-weight: 600; + margin-bottom: 0.75rem; + color: var(--ws-text); +} + +/* Сообщения (alerts) */ +.ws-alert { + padding: 0.75rem 1rem; + border-radius: var(--ws-radius-sm); + margin-bottom: 1rem; + border: 1px solid transparent; +} + +.ws-alert-success { + background: var(--ws-success-bg); + color: var(--ws-accent); + border-color: rgba(45, 212, 191, 0.3); +} + +.ws-alert-error, +.ws-alert-danger { + background: var(--ws-danger-bg); + color: var(--ws-danger); + border-color: rgba(248, 113, 113, 0.3); +} + +.ws-alert-warning { + background: rgba(251, 191, 36, 0.12); + color: #fbbf24; + border-color: rgba(251, 191, 36, 0.3); +} + +.ws-alert .btn-close { + filter: invert(1); + opacity: 0.7; +} + +/* Пустое состояние */ +.ws-empty { + text-align: center; + padding: 2rem 1rem; + color: var(--ws-text-muted); + font-size: 0.95rem; +} + +/* Логин */ +.ws-login-card { + max-width: 380px; + margin: 2rem auto; + padding: 2rem; +} + +.ws-login-title { + font-size: 1.5rem; + font-weight: 600; + margin-bottom: 1.5rem; + text-align: center; +} + +/* Главная */ +.ws-hero { + padding: 2rem 0; + text-align: center; +} + +.ws-hero h1 { + font-size: 1.75rem; + font-weight: 600; + margin-bottom: 0.5rem; +} + +.ws-hero p { + color: var(--ws-text-muted); + font-size: 1rem; +} + +/* Подсказка удаления */ +.ws-confirm-text { + color: var(--ws-text-muted); + margin-bottom: 1.25rem; +} + +/* Таблица в форме заказа — инпуты */ +.ws-table input.form-control, +.ws-table select.form-select, +.ws-table input[type="text"], +.ws-table input[type="number"], +.ws-table select { + background: var(--ws-bg-page); + border: 1px solid var(--ws-border); + color: var(--ws-text); + padding: 0.4rem 0.5rem; + font-size: 0.9rem; +} + +.ws-form-card .ws-form-group input, +.ws-form-card .ws-form-group select, +.ws-form-card .ws-form-group textarea { + max-width: 100%; +} + +.ws-table input[type="checkbox"] { + width: 1rem; + height: 1rem; + accent-color: var(--ws-accent); +} + +.ws-table input:focus, +.ws-table select:focus { + border-color: var(--ws-border-focus); + box-shadow: 0 0 0 2px rgba(88, 166, 255, 0.2); +} + +/* Списки документов — выравнивание чисел */ +.ws-table .ws-num { + text-align: right; + font-variant-numeric: tabular-nums; +} diff --git a/app/templates/base.html b/app/templates/base.html index b18521f..1255beb 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -5,22 +5,26 @@ {% block title %}ERP WaterSurf{% endblock %} + + + + {% block extra_css %}{% endblock %} -