200 lines
6.6 KiB
HTML
200 lines
6.6 KiB
HTML
{% extends "base.html" %}
|
||
{% block body_class %}page-bg bg-cabinets{% endblock %}
|
||
{% block content %}
|
||
<style>
|
||
body.bg-cabinets {
|
||
background-color: #B3B3DA;
|
||
background-image:
|
||
linear-gradient(rgba(179, 179, 218, 0.75), rgba(179, 179, 218, 0.75)),
|
||
url('{{ url_for("static", filename="bg/bg_zdanie.png", v=1) }}');
|
||
background-size: auto 40vh;
|
||
}
|
||
.row-actions {
|
||
background: #f8f9fa;
|
||
}
|
||
.row-actions__inner {
|
||
max-height: 0;
|
||
opacity: 0;
|
||
transform: translateY(-6px);
|
||
transition: max-height 0.2s ease, opacity 0.2s ease, transform 0.2s ease;
|
||
overflow: hidden;
|
||
padding: 0 0.75rem;
|
||
}
|
||
.row-actions.show .row-actions__inner {
|
||
max-height: 60px;
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
}
|
||
.edit-modal {
|
||
position: fixed;
|
||
inset: 0;
|
||
background: rgba(15, 23, 32, 0.55);
|
||
display: none;
|
||
align-items: center;
|
||
justify-content: center;
|
||
z-index: 1050;
|
||
padding: 1rem;
|
||
}
|
||
.edit-modal.show {
|
||
display: flex;
|
||
}
|
||
.edit-modal__dialog {
|
||
background: #fff;
|
||
border-radius: 0.75rem;
|
||
width: min(720px, 100%);
|
||
max-height: 85vh;
|
||
overflow: auto;
|
||
}
|
||
.edit-modal__header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 0.75rem 1rem;
|
||
border-bottom: 1px solid #e2e2e2;
|
||
}
|
||
.edit-modal__title {
|
||
margin: 0;
|
||
font-size: 1.05rem;
|
||
}
|
||
.edit-modal__footer {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
gap: 0.5rem;
|
||
padding: 0.75rem 1rem;
|
||
border-top: 1px solid #e2e2e2;
|
||
}
|
||
</style>
|
||
<h3>Кабинеты</h3>
|
||
|
||
{% if session.get('role') not in ('admin','storekeeper') %}
|
||
<div class="alert alert-secondary">Режим просмотра: изменения доступны только администратору.</div>
|
||
{% endif %}
|
||
|
||
{% if session.get('role') in ('admin','storekeeper') %}
|
||
<form method="post" action="/cabinets/add" class="row g-2 mb-3">
|
||
<div class="col-md-4">
|
||
<input name="building" class="form-control" placeholder="Здание (например: 1, А, Корпус 2)">
|
||
</div>
|
||
<div class="col-md-4">
|
||
<input name="cabinet" class="form-control" placeholder="Кабинет (например: 101, 2-14)">
|
||
</div>
|
||
<div class="col-md-2 d-grid">
|
||
<button class="btn btn-success">Добавить</button>
|
||
</div>
|
||
</form>
|
||
{% endif %}
|
||
|
||
{% for building, rows in grouped.items() %}
|
||
<h5 class="mt-3 mb-2">Здание: {{ building if building else 'Без здания' }}</h5>
|
||
<table class="table table-striped">
|
||
<tr><th>Кабинет</th></tr>
|
||
{% for row in rows %}
|
||
<tr class="js-cabinet-row"
|
||
data-id="{{ row.id }}"
|
||
data-building="{{ row.building }}"
|
||
data-cabinet="{{ row.cabinet }}">
|
||
<td>{{ row.cabinet }}</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</table>
|
||
{% endfor %}
|
||
|
||
{% if session.get('role') in ('admin','storekeeper') %}
|
||
<div class="edit-modal" id="cabinetEditModal" aria-hidden="true">
|
||
<div class="edit-modal__dialog">
|
||
<div class="edit-modal__header">
|
||
<h4 class="edit-modal__title">Редактирование кабинета</h4>
|
||
<button type="button" class="btn btn-sm btn-outline-secondary" data-modal-close>Закрыть</button>
|
||
</div>
|
||
<form method="post" action="/cabinets/edit" id="cabinetEditForm">
|
||
<input type="hidden" name="id" id="cabinetModalId">
|
||
<div class="row g-2 px-3 py-3">
|
||
<div class="col-md-6">
|
||
<input name="building" id="cabinetModalBuilding" class="form-control" placeholder="Здание">
|
||
</div>
|
||
<div class="col-md-6">
|
||
<input name="cabinet" id="cabinetModalCabinet" class="form-control" placeholder="Кабинет">
|
||
</div>
|
||
</div>
|
||
<div class="edit-modal__footer">
|
||
<button type="button" class="btn btn-outline-secondary" data-modal-close>Отмена</button>
|
||
<button class="btn btn-primary">Сохранить</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
{% endif %}
|
||
|
||
<script>
|
||
(function() {
|
||
const canEdit = {{ 'true' if session.get('role') in ('admin','storekeeper') else 'false' }};
|
||
if (!canEdit) return;
|
||
const rows = document.querySelectorAll('.js-cabinet-row');
|
||
if (!rows.length) return;
|
||
const modal = document.getElementById('cabinetEditModal');
|
||
if (!modal) return;
|
||
|
||
const fields = {
|
||
id: document.getElementById('cabinetModalId'),
|
||
building: document.getElementById('cabinetModalBuilding'),
|
||
cabinet: document.getElementById('cabinetModalCabinet'),
|
||
};
|
||
|
||
function closeModal() {
|
||
modal.classList.remove('show');
|
||
modal.setAttribute('aria-hidden', 'true');
|
||
}
|
||
function openModal() {
|
||
modal.classList.add('show');
|
||
modal.setAttribute('aria-hidden', 'false');
|
||
}
|
||
modal.addEventListener('click', (e) => {
|
||
if (e.target === modal || e.target.hasAttribute('data-modal-close')) {
|
||
closeModal();
|
||
}
|
||
});
|
||
|
||
function fillModalFromRow(row) {
|
||
fields.id.value = row.getAttribute('data-id') || '';
|
||
fields.building.value = row.getAttribute('data-building') || '';
|
||
fields.cabinet.value = row.getAttribute('data-cabinet') || '';
|
||
return true;
|
||
}
|
||
|
||
function showActionRow(row) {
|
||
const existing = row.parentElement.querySelector('.row-actions');
|
||
if (existing) existing.remove();
|
||
const rowId = row.getAttribute('data-id') || '';
|
||
const actionRow = document.createElement('tr');
|
||
actionRow.className = 'row-actions';
|
||
actionRow.innerHTML = `<td colspan="2">
|
||
<div class="row-actions__inner">
|
||
<button type="button" class="btn btn-sm btn-outline-primary js-open-cabinet-modal">Редактировать</button>
|
||
<form method="post" action="/cabinets/delete" class="d-inline ms-2" onsubmit="return confirm('Удалить кабинет?')">
|
||
<input type="hidden" name="id" value="${rowId}">
|
||
<button class="btn btn-sm btn-outline-danger" type="submit">Удалить</button>
|
||
</form>
|
||
</div>
|
||
</td>`;
|
||
row.insertAdjacentElement('afterend', actionRow);
|
||
const btn = actionRow.querySelector('.js-open-cabinet-modal');
|
||
btn.addEventListener('click', () => {
|
||
if (fillModalFromRow(row)) openModal();
|
||
});
|
||
requestAnimationFrame(() => actionRow.classList.add('show'));
|
||
}
|
||
|
||
rows.forEach((row) => {
|
||
row.addEventListener('click', (e) => {
|
||
if (e.target.closest('button, input, select, textarea, a')) return;
|
||
showActionRow(row);
|
||
});
|
||
row.addEventListener('dblclick', (e) => {
|
||
if (e.target.closest('button, input, select, textarea, a')) return;
|
||
if (fillModalFromRow(row)) openModal();
|
||
});
|
||
});
|
||
})();
|
||
</script>
|
||
{% endblock %}
|