404 lines
17 KiB
HTML
404 lines
17 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="ru">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
|
<title>Редактор комитетов</title>
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:opsz,wght@14..32,300;400;500;600;700&display=swap" rel="stylesheet">
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
|
|
<style>
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
body { font-family: 'Inter', sans-serif; background: #f8fafc; color: #0f172a; line-height: 1.5; padding: 2rem 1rem; }
|
|
.container { max-width: 1200px; margin: 0 auto; }
|
|
|
|
.header { text-align: center; margin-bottom: 2rem; }
|
|
.header h1 { font-size: 2rem; font-weight: 700; background: linear-gradient(135deg, #1e3a5f, #0f2b40); -webkit-background-clip: text; background-clip: text; color: transparent; }
|
|
.header p { color: #475569; margin-top: 0.5rem; }
|
|
|
|
.back-link {
|
|
display: inline-block;
|
|
margin-bottom: 1.5rem;
|
|
color: #1e3a5f;
|
|
text-decoration: none;
|
|
font-weight: 500;
|
|
}
|
|
.back-link:hover { text-decoration: underline; }
|
|
|
|
.committee-selector {
|
|
background: white;
|
|
border-radius: 16px;
|
|
padding: 1rem;
|
|
margin-bottom: 1.5rem;
|
|
border: 1px solid #eef2f6;
|
|
display: flex;
|
|
gap: 1rem;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
}
|
|
.committee-selector select {
|
|
flex: 2;
|
|
min-width: 250px;
|
|
padding: 10px 14px;
|
|
border-radius: 12px;
|
|
border: 1px solid #cbd5e1;
|
|
font-family: 'Inter', sans-serif;
|
|
font-size: 0.9rem;
|
|
}
|
|
.committee-selector button {
|
|
background: #1e3a5f;
|
|
color: white;
|
|
border: none;
|
|
padding: 10px 20px;
|
|
border-radius: 12px;
|
|
cursor: pointer;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.editor-form {
|
|
background: white;
|
|
border-radius: 24px;
|
|
padding: 1.5rem;
|
|
border: 1px solid #eef2f6;
|
|
}
|
|
.form-section {
|
|
margin-bottom: 2rem;
|
|
padding-bottom: 1rem;
|
|
border-bottom: 1px solid #eef2f6;
|
|
}
|
|
.section-title {
|
|
font-weight: 700;
|
|
font-size: 1rem;
|
|
color: #1e3a5f;
|
|
margin-bottom: 1rem;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
.form-group {
|
|
margin-bottom: 1rem;
|
|
}
|
|
.form-group label {
|
|
display: block;
|
|
font-weight: 600;
|
|
font-size: 0.8rem;
|
|
color: #475569;
|
|
margin-bottom: 0.3rem;
|
|
}
|
|
.form-group input, .form-group textarea, .form-group select {
|
|
width: 100%;
|
|
padding: 10px 12px;
|
|
border-radius: 10px;
|
|
border: 1px solid #cbd5e1;
|
|
font-family: 'Inter', sans-serif;
|
|
font-size: 0.85rem;
|
|
}
|
|
.form-group textarea {
|
|
min-height: 100px;
|
|
resize: vertical;
|
|
}
|
|
.form-row {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 1rem;
|
|
}
|
|
.form-3col {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr 1fr;
|
|
gap: 1rem;
|
|
}
|
|
.status-select {
|
|
width: auto;
|
|
display: inline-block;
|
|
}
|
|
.save-btn {
|
|
background: #10b981;
|
|
color: white;
|
|
border: none;
|
|
padding: 12px 24px;
|
|
border-radius: 12px;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
margin-top: 1rem;
|
|
font-size: 1rem;
|
|
}
|
|
.save-btn:hover { background: #059669; }
|
|
|
|
.toast {
|
|
position: fixed;
|
|
bottom: 30px;
|
|
right: 30px;
|
|
background: #15803d;
|
|
color: white;
|
|
padding: 12px 20px;
|
|
border-radius: 50px;
|
|
z-index: 1000;
|
|
display: none;
|
|
}
|
|
.toast.error { background: #dc2626; }
|
|
|
|
@media (max-width: 700px) {
|
|
.form-row, .form-3col { grid-template-columns: 1fr; }
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<a href="/committees.html" class="back-link"><i class="fas fa-arrow-left"></i> Назад к списку комитетов</a>
|
|
|
|
<div class="header">
|
|
<h1><i class="fas fa-edit"></i> Редактор комитетов</h1>
|
|
<p>Редактирование информации о руководителях и кандидатах комитетов</p>
|
|
</div>
|
|
|
|
<div class="committee-selector">
|
|
<select id="committeeSelect">
|
|
<option value="">-- Выберите комитет --</option>
|
|
</select>
|
|
<button id="loadCommitteeBtn"><i class="fas fa-folder-open"></i> Загрузить</button>
|
|
</div>
|
|
|
|
<div id="editorContainer" style="display: none;">
|
|
<form id="editorForm" class="editor-form">
|
|
<div class="form-section">
|
|
<div class="section-title"><i class="fas fa-info-circle"></i> Информация о комитете</div>
|
|
<div class="form-group">
|
|
<label>Название комитета</label>
|
|
<input type="text" id="committeeName" readonly style="background:#f1f5f9;">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Описание деятельности</label>
|
|
<textarea id="committeeDescription" readonly style="background:#f1f5f9;"></textarea>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-section">
|
|
<div class="section-title"><i class="fas fa-user-tie"></i> Текущий руководитель</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>ФИО руководителя</label>
|
|
<input type="text" id="leaderName" placeholder="Иванов Иван Иванович">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Должность / Регалии</label>
|
|
<input type="text" id="leaderTitle" placeholder="Председатель комитета">
|
|
</div>
|
|
</div>
|
|
<div class="form-3col">
|
|
<div class="form-group">
|
|
<label>Email</label>
|
|
<input type="email" id="leaderEmail" placeholder="email@example.com">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Телефон</label>
|
|
<input type="text" id="leaderPhone" placeholder="+7 (xxx) xxx-xx-xx">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Telegram</label>
|
|
<input type="text" id="leaderTelegram" placeholder="@username">
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>Статус активности</label>
|
|
<select id="leaderStatus" class="status-select">
|
|
<option value="active">Активен</option>
|
|
<option value="medium">Средняя активность</option>
|
|
<option value="inactive">Не активен</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Дополнительная информация</label>
|
|
<input type="text" id="leaderAdditional" placeholder="Член правления, эксперт и т.д.">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-section">
|
|
<div class="section-title"><i class="fas fa-user-plus"></i> Кандидат на должность руководителя</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>ФИО кандидата</label>
|
|
<input type="text" id="candidateName" placeholder="Петров Петр Петрович">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Должность / Регалии</label>
|
|
<input type="text" id="candidateTitle" placeholder="Заместитель председателя">
|
|
</div>
|
|
</div>
|
|
<div class="form-3col">
|
|
<div class="form-group">
|
|
<label>Email</label>
|
|
<input type="email" id="candidateEmail" placeholder="email@example.com">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Телефон</label>
|
|
<input type="text" id="candidatePhone" placeholder="+7 (xxx) xxx-xx-xx">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Telegram</label>
|
|
<input type="text" id="candidateTelegram" placeholder="@username">
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>Статус кандидата</label>
|
|
<select id="candidateStatus" class="status-select">
|
|
<option value="candidate">Кандидат</option>
|
|
<option value="active">Активен</option>
|
|
<option value="medium">Средняя активность</option>
|
|
<option value="inactive">Не активен</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Дополнительная информация</label>
|
|
<input type="text" id="candidateAdditional" placeholder="Опыт работы, достижения">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<button type="submit" class="save-btn"><i class="fas fa-save"></i> Сохранить изменения</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="toast" class="toast">✅ Данные сохранены</div>
|
|
|
|
<script>
|
|
let committeesData = [];
|
|
let currentCommitteeIndex = -1;
|
|
let currentFile = 'opora_committees.json';
|
|
|
|
function showToast(msg, isError = false) {
|
|
const toast = document.getElementById('toast');
|
|
toast.textContent = msg;
|
|
toast.className = isError ? 'toast error' : 'toast';
|
|
toast.style.display = 'block';
|
|
setTimeout(() => { toast.style.display = 'none'; }, 2500);
|
|
}
|
|
|
|
async function loadCommittees() {
|
|
try {
|
|
const response = await fetch(`/committees/${currentFile}`);
|
|
if (response.ok) {
|
|
committeesData = await response.json();
|
|
populateSelect();
|
|
showToast('Комитеты загружены');
|
|
} else {
|
|
showToast('Ошибка загрузки файла комитетов', true);
|
|
}
|
|
} catch (error) {
|
|
showToast('Ошибка загрузки: ' + error.message, true);
|
|
}
|
|
}
|
|
|
|
function populateSelect() {
|
|
const select = document.getElementById('committeeSelect');
|
|
select.innerHTML = '<option value="">-- Выберите комитет --</option>';
|
|
committeesData.forEach((committee, idx) => {
|
|
const option = document.createElement('option');
|
|
option.value = idx;
|
|
option.textContent = committee.name;
|
|
select.appendChild(option);
|
|
});
|
|
}
|
|
|
|
function loadCommitteeToForm(index) {
|
|
const committee = committeesData[index];
|
|
if (!committee) return;
|
|
|
|
currentCommitteeIndex = index;
|
|
|
|
document.getElementById('committeeName').value = committee.name;
|
|
document.getElementById('committeeDescription').value = committee.description;
|
|
|
|
// Текущий руководитель
|
|
document.getElementById('leaderName').value = committee.current_leader?.name || '';
|
|
document.getElementById('leaderTitle').value = committee.current_leader?.title || '';
|
|
document.getElementById('leaderEmail').value = committee.current_leader?.contacts?.email || '';
|
|
document.getElementById('leaderPhone').value = committee.current_leader?.contacts?.phone || '';
|
|
document.getElementById('leaderTelegram').value = committee.current_leader?.contacts?.telegram || '';
|
|
document.getElementById('leaderStatus').value = committee.current_leader?.status || 'active';
|
|
document.getElementById('leaderAdditional').value = committee.current_leader?.additional_info || '';
|
|
|
|
// Кандидат
|
|
document.getElementById('candidateName').value = committee.candidate_for_leader?.name || '';
|
|
document.getElementById('candidateTitle').value = committee.candidate_for_leader?.title || '';
|
|
document.getElementById('candidateEmail').value = committee.candidate_for_leader?.contacts?.email || '';
|
|
document.getElementById('candidatePhone').value = committee.candidate_for_leader?.contacts?.phone || '';
|
|
document.getElementById('candidateTelegram').value = committee.candidate_for_leader?.contacts?.telegram || '';
|
|
document.getElementById('candidateStatus').value = committee.candidate_for_leader?.status || 'candidate';
|
|
document.getElementById('candidateAdditional').value = committee.candidate_for_leader?.additional_info || '';
|
|
|
|
document.getElementById('editorContainer').style.display = 'block';
|
|
}
|
|
|
|
function saveCommittee() {
|
|
const committee = committeesData[currentCommitteeIndex];
|
|
if (!committee) return;
|
|
|
|
// Сохраняем данные текущего руководителя
|
|
committee.current_leader = {
|
|
name: document.getElementById('leaderName').value,
|
|
contacts: {
|
|
email: document.getElementById('leaderEmail').value,
|
|
phone: document.getElementById('leaderPhone').value,
|
|
telegram: document.getElementById('leaderTelegram').value
|
|
},
|
|
title: document.getElementById('leaderTitle').value,
|
|
status: document.getElementById('leaderStatus').value,
|
|
additional_info: document.getElementById('leaderAdditional').value
|
|
};
|
|
|
|
// Сохраняем данные кандидата
|
|
committee.candidate_for_leader = {
|
|
name: document.getElementById('candidateName').value,
|
|
contacts: {
|
|
email: document.getElementById('candidateEmail').value,
|
|
phone: document.getElementById('candidatePhone').value,
|
|
telegram: document.getElementById('candidateTelegram').value
|
|
},
|
|
title: document.getElementById('candidateTitle').value,
|
|
status: document.getElementById('candidateStatus').value,
|
|
additional_info: document.getElementById('candidateAdditional').value
|
|
};
|
|
|
|
saveToServer();
|
|
}
|
|
|
|
async function saveToServer() {
|
|
try {
|
|
const response = await fetch(`/save_committees/${currentFile}`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(committeesData)
|
|
});
|
|
const result = await response.json();
|
|
if (result.success) {
|
|
showToast('✅ Данные сохранены');
|
|
} else {
|
|
showToast('❌ Ошибка сохранения: ' + result.message, true);
|
|
}
|
|
} catch (error) {
|
|
showToast('❌ Ошибка соединения: ' + error.message, true);
|
|
}
|
|
}
|
|
|
|
document.getElementById('loadCommitteeBtn').addEventListener('click', () => {
|
|
const idx = document.getElementById('committeeSelect').value;
|
|
if (idx !== '') {
|
|
loadCommitteeToForm(parseInt(idx));
|
|
} else {
|
|
showToast('Выберите комитет', true);
|
|
}
|
|
});
|
|
|
|
document.getElementById('editorForm').addEventListener('submit', (e) => {
|
|
e.preventDefault();
|
|
saveCommittee();
|
|
});
|
|
|
|
// Загрузка данных
|
|
loadCommittees();
|
|
</script>
|
|
</body>
|
|
</html> |