Files
Uch-Practic/static/profile.html

235 lines
9.1 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Robo Arena — Профиль пилота</title>
<link rel="stylesheet" href="/static/style.css">
</head>
<body class="page-app page-profile">
<nav class="topbar">
<div class="topbar-brand">
<span class="logo-icon">🤖</span>
<span>Robo Arena</span> / РСУ
</div>
<span class="topbar-user" id="topbar-email"></span>
<a class="btn btn-sm active-nav" href="/static/profile.html">Профиль</a>
<a class="btn btn-sm" href="/static/dashboard.html">Арена</a>
<button class="btn btn-sm" id="logout-btn">Выйти</button>
</nav>
<div class="main main--profile">
<div class="profile-layout">
<!-- Боковая панель -->
<aside class="profile-sidebar">
<div class="profile-sidebar-glow"></div>
<div class="profile-avatar" id="profile-avatar">👤</div>
<h2 class="profile-sidebar-name" id="sidebar-name">Пилот</h2>
<p class="profile-sidebar-email" id="sidebar-email"></p>
<div class="profile-status" id="profile-status">
<div class="profile-status-label">Заполненность профиля</div>
<div class="profile-progress-wrap">
<div class="profile-progress-bar" id="progress-bar" style="width:0%"></div>
</div>
<div class="profile-status-text" id="status-text">0 из 4 полей</div>
</div>
<div class="profile-sidebar-hints">
<div class="hint-item">
<span class="hint-icon">🛡</span>
<span>Данные нужны для идентификации пилота на арене</span>
</div>
<div class="hint-item">
<span class="hint-icon">🔒</span>
<span>Информация хранится только в вашем аккаунте</span>
</div>
</div>
</aside>
<!-- Форма -->
<div class="profile-form-card">
<div class="profile-form-header">
<div class="profile-badge">⚔ Профиль пилота</div>
<h2>Данные оператора</h2>
<p class="sub">Заполните личную информацию для участия в системе управления боевыми роботами</p>
</div>
<form id="profile-form" autocomplete="on">
<div class="form-section">
<div class="form-section-title">
<span class="form-section-icon">📋</span>
Личные данные
</div>
<div class="form-field">
<label for="full_name">ФИО</label>
<div class="input-wrap">
<span class="input-icon">👤</span>
<input type="text" id="full_name" placeholder="Иванов Иван Иванович" autocomplete="name">
</div>
</div>
<div class="form-row">
<div class="form-field">
<label for="birth_date">Дата рождения</label>
<div class="input-wrap">
<span class="input-icon">🎂</span>
<input type="date" id="birth_date">
</div>
</div>
<div class="form-field">
<label for="gender">Пол</label>
<div class="input-wrap">
<span class="input-icon"></span>
<select id="gender">
<option value="">— выберите —</option>
<option value="male">Мужской</option>
<option value="female">Женский</option>
<option value="other">Не указан</option>
</select>
</div>
</div>
</div>
</div>
<div class="form-section">
<div class="form-section-title">
<span class="form-section-icon">📞</span>
Контакты
</div>
<div class="form-field">
<label for="phone">Телефон</label>
<div class="input-wrap">
<span class="input-icon">📱</span>
<input type="tel" id="phone" placeholder="+7 (999) 123-45-67" autocomplete="tel">
</div>
<span class="field-hint">Формат: +7 или 8, минимум 7 цифр</span>
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary" id="save-btn">
<span>💾 Сохранить профиль</span>
</button>
<a class="btn btn-ghost btn-back" href="/static/dashboard.html">На арену</a>
</div>
<p class="err-msg" id="error-text"></p>
<p class="ok-msg" id="ok-text"></p>
</form>
</div>
</div>
</div>
<script>
const errEl = document.getElementById("error-text");
const okEl = document.getElementById("ok-text");
const saveBtn = document.getElementById("save-btn");
function updateSidebar(u) {
document.getElementById("topbar-email").textContent = u.email;
document.getElementById("sidebar-email").textContent = u.email;
if (u.full_name) {
document.getElementById("sidebar-name").textContent = u.full_name;
document.getElementById("profile-avatar").textContent = u.full_name.trim()[0].toUpperCase();
}
const fields = [u.full_name, u.birth_date, u.phone, u.gender];
const filled = fields.filter(Boolean).length;
const pct = Math.round((filled / 4) * 100);
document.getElementById("progress-bar").style.width = pct + "%";
document.getElementById("status-text").textContent = `${filled} из 4 полей`;
const statusEl = document.getElementById("profile-status");
if (filled === 4) {
statusEl.classList.add("profile-status--complete");
document.getElementById("status-text").textContent = "Профиль заполнен ✓";
} else {
statusEl.classList.remove("profile-status--complete");
}
}
async function loadMe() {
const res = await fetch("/api/me", { credentials: "include" });
if (!res.ok) { window.location.href = "/static/login.html"; return; }
const u = await res.json();
document.getElementById("full_name").value = u.full_name || "";
document.getElementById("birth_date").value = u.birth_date || "";
document.getElementById("phone").value = u.phone || "";
document.getElementById("gender").value = u.gender || "";
updateSidebar(u);
}
["full_name", "birth_date", "phone", "gender"].forEach(id => {
document.getElementById(id).addEventListener("input", () => {
updateSidebar({
full_name: document.getElementById("full_name").value.trim(),
birth_date: document.getElementById("birth_date").value,
phone: document.getElementById("phone").value.trim(),
gender: document.getElementById("gender").value,
email: document.getElementById("sidebar-email").textContent,
});
});
document.getElementById(id).addEventListener("change", () => {
document.getElementById(id).dispatchEvent(new Event("input"));
});
});
document.getElementById("profile-form").addEventListener("submit", async e => {
e.preventDefault();
errEl.textContent = "";
okEl.textContent = "";
const payload = {
full_name: document.getElementById("full_name").value.trim(),
birth_date: document.getElementById("birth_date").value,
phone: document.getElementById("phone").value.trim(),
gender: document.getElementById("gender").value,
};
saveBtn.disabled = true;
saveBtn.querySelector("span").textContent = "Сохраняем…";
try {
const res = await fetch("/api/me/profile", {
method: "PUT",
headers: { "Content-Type": "application/json" },
credentials: "include",
body: JSON.stringify(payload)
});
const data = await res.json();
if (!res.ok) {
errEl.textContent = data.detail || "Не удалось сохранить профиль";
return;
}
okEl.textContent = "✓ Профиль сохранён! Переход на арену…";
updateSidebar(data);
setTimeout(() => { window.location.href = "/static/dashboard.html"; }, 1400);
} catch {
errEl.textContent = "Не удалось связаться с сервером";
} finally {
saveBtn.disabled = false;
saveBtn.querySelector("span").textContent = "💾 Сохранить профиль";
}
});
document.getElementById("logout-btn").addEventListener("click", async () => {
await fetch("/api/logout", { method: "POST", credentials: "include" });
window.location.href = "/static/index.html";
});
loadMe();
</script>
</body>
</html>