domovoy_bot/web/templates/phones.html
Admin 97c3e5864d 🎨 refactor: Единая навигация — ВСЕ 14 страниц используют base.html
БЫЛО: Каждая из 14 страниц имела своё собственное вшитое меню
      с разным набором кнопок (от 4 до 10 пунктов)

СТАЛО: Все 14 страниц наследуют base.html с единым меню из 14 пунктов
       в 4 разделах: Пользователи / Коммуникации / Контент / Система

Убрано 1949 строк дублирующегося кода, добавлено 1323 строки чистого контента.
Экономия: -626 строк (32% сокращение).

Переписанные страницы:
- dashboard.html, users.html, verification.html
- phones.html, polls.html, events.html
- schedules.html, ads.html, scheduled_posts.html, export.html

Результат: На ЛЮБОЙ странице пользователь видит ВСЕ 14 пунктов меню.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-04-12 18:52:58 +04:00

187 lines
8.1 KiB
HTML

{% extends "base.html" %}
{% block title %}Телефоны и службы - Домовой Бот{% endblock %}
{% block nav_phones %}active{% endblock %}
{% block extra_style %}
.service-image-preview { max-width: 200px; max-height: 200px; object-fit: contain; }
{% endblock %}
{% block content %}
<h2 class="mb-4"><i class="bi bi-telephone"></i> Телефоны и службы</h2>
<!-- Добавить службу -->
<div class="card mb-4">
<div class="card-header bg-primary text-white">
<h5 class="mb-0"><i class="bi bi-plus-lg"></i> Добавить службу</h5>
</div>
<div class="card-body">
<form id="addServiceForm" class="row g-3">
<div class="col-md-3">
<input type="text" class="form-control" id="serviceName" placeholder="Название" required>
</div>
<div class="col-md-2">
<input type="text" class="form-control" id="servicePhone" placeholder="Телефон" required>
</div>
<div class="col-md-2">
<select class="form-select" id="serviceCategory">
<option value="emergency">🚨 Экстренные</option>
<option value="utility">🔧 ЖКХ</option>
<option value="masters">👷 Мастера</option>
<option value="police">👮 Полиция</option>
<option value="other">📋 Другое</option>
</select>
</div>
<div class="col-md-3">
<input type="text" class="form-control" id="serviceDesc" placeholder="Описание">
</div>
<div class="col-md-2">
<button type="submit" class="btn btn-primary w-100">Добавить</button>
</div>
</form>
</div>
</div>
<!-- Загрузить картинку -->
<div class="card mb-4">
<div class="card-header bg-success text-white">
<h5 class="mb-0"><i class="bi bi-image"></i> Загрузить картинку для службы</h5>
</div>
<div class="card-body">
<form id="uploadImageForm" class="row g-3" enctype="multipart/form-data">
<div class="col-md-3">
<select class="form-select" id="imageCategory" required>
<option value="emergency">🚨 Экстренные</option>
<option value="utility">🔧 ЖКХ</option>
<option value="masters">👷 Мастера</option>
<option value="police">👮 Полиция</option>
<option value="other">📋 Другое</option>
</select>
</div>
<div class="col-md-4">
<input type="file" class="form-control" id="imageFile" accept="image/*" required>
<small class="text-muted">JPG, PNG до 5MB</small>
</div>
<div class="col-md-2">
<button type="submit" class="btn btn-success w-100">Загрузить</button>
</div>
</form>
<div id="uploadResult" class="mt-3"></div>
</div>
</div>
<!-- Список служб -->
<div class="card">
<div class="card-body">
<h5>Существующие службы:</h5>
<table class="table table-hover">
<thead>
<tr>
<th>Категория</th>
<th>Название</th>
<th>Телефон</th>
<th>Описание</th>
<th>Картинка</th>
<th>Действия</th>
</tr>
</thead>
<tbody>
{% for service in services %}
<tr>
<td>
{% if service.category == 'emergency' %}
<span class="badge bg-danger">🚨 Экстренные</span>
{% elif service.category == 'utility' %}
<span class="badge bg-info">🔧 ЖКХ</span>
{% elif service.category == 'masters' %}
<span class="badge bg-success">👷 Мастера</span>
{% elif service.category == 'police' %}
<span class="badge bg-warning text-dark">👮 Полиция</span>
{% else %}
<span class="badge bg-secondary">Другое</span>
{% endif %}
</td>
<td>{{ service.name }}</td>
<td><a href="tel:{{ service.phone }}">{{ service.phone }}</a></td>
<td>{{ service.description or '—' }}</td>
<td>
{% if service.image_path %}
<img src="/static/service_images/{{ service.image_path.split('/')[-1] }}"
class="service-image-preview" alt="Картинка">
<br><small class="text-muted"></small>
{% else %}
<span class="text-muted">❌ Нет</span>
{% endif %}
</td>
<td>
<button class="btn btn-sm btn-danger" onclick="deleteService({{ service.service_id }})">
<i class="bi bi-trash"></i>
</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% if not services %}
<p class="text-center text-muted">Служб нет</p>
{% endif %}
</div>
</div>
{% endblock %}
{% block extra_script %}
<script>
// Добавление службы
document.getElementById('addServiceForm').addEventListener('submit', async (e) => {
e.preventDefault();
const data = {
name: document.getElementById('serviceName').value,
phone: document.getElementById('servicePhone').value,
category: document.getElementById('serviceCategory').value,
description: document.getElementById('serviceDesc').value
};
const r = await fetch('/api/service/add', {
method: 'POST', headers: {'Content-Type': 'application/json'},
body: JSON.stringify(data)
});
const result = await r.json();
if (result.success) { alert('✅ Служба добавлена'); location.reload(); }
else { alert('❌ Ошибка: ' + (result.error || 'Неизвестная')); }
});
// Загрузка картинки
document.getElementById('uploadImageForm').addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData();
formData.append('category', document.getElementById('imageCategory').value);
formData.append('file', document.getElementById('imageFile').files[0]);
const resultDiv = document.getElementById('uploadResult');
resultDiv.innerHTML = '<div class="alert alert-info">Загрузка...</div>';
try {
const r = await fetch('/api/service/upload_image', {
method: 'POST',
body: formData
});
const result = await r.json();
if (result.success) {
resultDiv.innerHTML = `<div class="alert alert-success">✅ ${result.message}<br>Файл: ${result.file_path}</div>`;
} else {
resultDiv.innerHTML = `<div class="alert alert-danger">❌ Ошибка: ${result.error}</div>`;
}
} catch (err) {
resultDiv.innerHTML = `<div class="alert alert-danger">❌ Ошибка: ${err.message}</div>`;
}
});
async function deleteService(id) {
if (!confirm('Удалить службу?')) return;
const r = await fetch(`/api/service/${id}/delete`, { method: 'POST' });
const result = await r.json();
if (result.success) { alert('✅ Удалено'); location.reload(); }
}
</script>
{% endblock %}