/
axe
/
pet2
Обзор
Документация
Войти
/
axe
/
pet2
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
public/render.js
156 строк
6 KB
gusen
initial commit
09 июн 2026, 22:01
09 июн 2026, 22:01
7bf5434
Код
Авторство
О чём код?
import { login, logout, fetchMe } from './auth.js'; import { fetchCases, createCase, updateCase, deleteCase } from './cases.js'; export const renderLogin = (app) => { app.innerHTML = ` <div class="login defaultContainer"> <h1>Авторизация</h1> <p>Пожалуйста, введите вашу почту для входа</p> <input id="email" type="email" placeholder="example@mail.ru"> <button id="loginBtn">Войти</button> </div> `; document.getElementById('loginBtn').addEventListener('click', async () => { const email = document.getElementById('email').value; if (!email) return alert('Введите email'); const userData = await login(email); if (userData) { await renderApp(app); } }); }; export const renderApp = async (app) => { const token = localStorage.getItem('token'); if (!token) { renderLogin(app); return; } let currentUser; try { currentUser = await fetchMe(); } catch { renderLogin(app); return; } const cases = await fetchCases(); const isAdmin = currentUser.role === 'admin'; const getStatusClass = (status) => { switch (status) { case 'на рассмотрении': return 'status-review'; case 'в процессе': return 'status-progress'; case 'в ожидании': return 'status-waiting'; case 'завершён': return 'status-done'; default: return ''; } }; const escapeHtml = (str) => { if (!str) return ''; return str.replace(/[&<>]/g, (m) => { if (m === '&') return '&'; if (m === '<') return '<'; if (m === '>') return '>'; return m; }); }; app.innerHTML = ` <div class="app-container"> <div class="header"> <h1>Case Tracker</h1> <div class="user-info"> 👋 ${escapeHtml(currentUser.name)} (${isAdmin ? 'Админ' : 'Исполнитель'}) <button id="logoutBtn" class="logout-btn">Выйти</button> </div> </div> <div class="create-case"> <h3>Новый кейс</h3> <input type="text" id="newTitle" placeholder="Название"> <textarea id="newDesc" placeholder="Описание" rows="2"></textarea> <button id="createBtn">Создать</button> </div> <div id="casesList" class="cases-grid"></div> </div> `; document.getElementById('logoutBtn').addEventListener('click', () => { logout(); renderLogin(app); }); document.getElementById('createBtn').addEventListener('click', async () => { const title = document.getElementById('newTitle').value; const description = document.getElementById('newDesc').value; if (title && description) { await createCase(title, description); await renderApp(app); } else { alert('Заполните название и описание'); } }); const casesList = document.getElementById('casesList'); if (cases.length === 0) { casesList.innerHTML = '<div class="card">Нет кейсов</div>'; return; } casesList.innerHTML = cases.map(c => { const canEdit = isAdmin || c.authorId === currentUser.id; const canDelete = isAdmin; return ` <div class="card case-item" data-id="${c.id}"> <div class="flex-between"> <h3>${escapeHtml(c.title)}</h3> <span class="case-status ${getStatusClass(c.status)}">${c.status}</span> </div> <p class="text-sm">${escapeHtml(c.description || '')}</p> <p class="text-sm"><strong>Автор:</strong> ${escapeHtml(c.author?.name || 'Неизвестно')}</p> <p class="text-sm"><strong>Комментарий:</strong> ${c.comment ? escapeHtml(c.comment) : 'отсутствует'}</p> <div> <label>Статус:</label> <select id="status-${c.id}" ${!canEdit ? 'disabled' : ''}> <option value="на рассмотрении" ${c.status === 'на рассмотрении' ? 'selected' : ''}>На рассмотрении</option> <option value="в процессе" ${c.status === 'в процессе' ? 'selected' : ''}>В процессе</option> <option value="в ожидании" ${c.status === 'в ожидании' ? 'selected' : ''}>В ожидании</option> ${isAdmin ? `<option value="завершён" ${c.status === 'завершён' ? 'selected' : ''}>Завершён</option>` : ''} </select> </div> <div> <label>Новый комментарий:</label> <textarea id="comment-${c.id}" rows="2" ${!canEdit ? 'disabled' : ''}></textarea> </div> <div class="mt-2"> ${canEdit ? `<button class="update-btn" data-id="${c.id}">Сохранить изменения</button>` : ''} ${canDelete ? `<button class="delete-btn" data-id="${c.id}">Удалить кейс</button>` : ''} </div> </div> `; }).join(''); document.querySelectorAll('.update-btn').forEach(btn => { btn.addEventListener('click', async (e) => { const id = parseInt(btn.dataset.id); const statusSelect = document.getElementById(`status-${id}`); const commentTextarea = document.getElementById(`comment-${id}`); const newStatus = statusSelect.value; const newComment = commentTextarea.value; await updateCase(id, newStatus, newComment); await renderApp(app); }); }); document.querySelectorAll('.delete-btn').forEach(btn => { btn.addEventListener('click', async (e) => { const id = parseInt(btn.dataset.id); await deleteCase(id); await renderApp(app); }); }); };