otkryt-dannyy-proekt-i-dorab/index.html

197 lines
6.9 KiB
HTML
Raw 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>Дашборд</title>
<style>
:root{--ink:#0F1218;--cyan:#00E5FF;--cyan-50:#E8FCFF;--white:#fff;--gray-500:#5B6573;--gray-100:#F2F4F7;--success:#10B981;--warning:#F59E0B;--danger:#EF4444}
*{box-sizing:border-box;margin:0;padding:0}
body{font:15px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Inter,system-ui,sans-serif;color:var(--ink);background:#f8f9fa}
.container{max-width:1400px;margin:0 auto;padding:24px}
.header{background:var(--ink);color:var(--white);padding:20px 24px;margin-bottom:24px}
.header h1{font-size:24px;font-weight:700}
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:20px;margin-bottom:32px}
.stat-card{background:var(--white);border-radius:12px;padding:24px;box-shadow:0 2px 8px rgba(0,0,0,0.08)}
.stat-label{font-size:14px;color:var(--gray-500);margin-bottom:8px}
.stat-value{font-size:32px;font-weight:700;color:var(--ink)}
.stat-card.primary .stat-value{color:var(--cyan)}
.stat-card.success .stat-value{color:var(--success)}
.stat-card.warning .stat-value{color:var(--warning)}
.main-grid{display:grid;grid-template-columns:1fr 400px;gap:24px}
.panel{background:var(--white);border-radius:12px;padding:24px;box-shadow:0 2px 8px rgba(0,0,0,0.08)}
.panel h2{font-size:18px;font-weight:700;margin-bottom:20px}
.table{width:100%;border-collapse:collapse}
.table th,.table td{padding:12px;text-align:left;border-bottom:1px solid var(--gray-100)}
.table th{font-size:13px;font-weight:600;color:var(--gray-500);text-transform:uppercase}
.table tr:hover{background:var(--gray-100)}
.badge{display:inline-block;padding:4px 12px;border-radius:20px;font-size:12px;font-weight:600}
.badge-active{background:#DCFCE7;color:#166534}
.badge-completed{background:var(--cyan-50);color:#006999}
.form-group{margin-bottom:16px}
.form-group label{display:block;font-size:14px;font-weight:600;margin-bottom:8px;color:var(--gray-500)}
.form-group input,.form-group select{width:100%;padding:12px;border:1px solid var(--gray-100);border-radius:8px;font-size:15px;font-family:inherit}
.form-group input:focus,.form-group select:focus{outline:none;border-color:var(--cyan)}
.btn{display:inline-block;background:var(--cyan);color:var(--ink);padding:12px 24px;border-radius:8px;font-weight:700;text-decoration:none;cursor:pointer;border:none;font-size:15px;width:100%}
.btn:hover{opacity:0.9}
.btn-sm{padding:6px 12px;font-size:13px;width:auto}
.btn-danger{background:var(--danger);color:var(--white)}
.actions{display:flex;gap:8px}
.empty{text-align:center;padding:40px;color:var(--gray-500)}
@media(max-width:900px){.main-grid{grid-template-columns:1fr}}
@media(max-width:640px){.stats{grid-template-columns:1fr}.container{padding:16px}}
</style>
</head>
<body>
<div class="header">
<div class="container">
<h1>📊 Панель управления</h1>
</div>
</div>
<div class="container">
<div class="stats">
<div class="stat-card primary">
<div class="stat-label">Всего</div>
<div class="stat-value" id="stat-total">0</div>
</div>
<div class="stat-card warning">
<div class="stat-label">В работе</div>
<div class="stat-value" id="stat-active">0</div>
</div>
<div class="stat-card success">
<div class="stat-label">Завершено</div>
<div class="stat-value" id="stat-completed">0</div>
</div>
</div>
<div class="main-grid">
<div class="panel">
<h2>📋 Заказы</h2>
<table class="table">
<thead>
<tr><th>ID</th><th>Название</th><th>Клиент</th><th>Сумма</th><th>Статус</th><th>Дата</th><th>Действия</th></tr>
</thead>
<tbody id="table-body"></tbody>
</table>
<div id="empty" class="empty" style="display:none">Нет записей</div>
</div>
<div class="panel">
<h2>➕ Добавить</h2>
<form id="form">
<div class="form-group">
<label>Название</label>
<input type="text" name="title" placeholder="Например: Заказ #001" required>
</div>
<div class="form-group">
<label>Клиент</label>
<input type="text" name="client" placeholder="ФИО клиента" required>
</div>
<div class="form-group">
<label>Сумма (₸)</label>
<input type="number" name="amount" placeholder="0" required>
</div>
<div class="form-group">
<label>Статус</label>
<select name="status">
<option value="active">В работе</option>
<option value="completed">Завершено</option>
</select>
</div>
<button type="submit" class="btn">Добавить</button>
</form>
</div>
</div>
</div>
<script>
let editingId = null;
async function load() {
const res = await fetch("/api/data");
const data = await res.json();
document.getElementById("stat-total").textContent = data.stats.total;
document.getElementById("stat-active").textContent = data.stats.active;
document.getElementById("stat-completed").textContent = data.stats.completed;
const tbody = document.getElementById("table-body");
const empty = document.getElementById("empty");
if (data.items.length === 0) {
tbody.innerHTML = "";
empty.style.display = "block";
} else {
empty.style.display = "none";
tbody.innerHTML = data.items.map(item => `
<tr>
<td>${item.id}</td>
<td>${item.title}</td>
<td>${item.client}</td>
<td>${item.amount.toLocaleString()}</td>
<td><span class="badge badge-${item.status}">${item.status === "active" ? "В работе" : "Завершено"}</span></td>
<td>${item.createdAt}</td>
<td class="actions">
<button class="btn btn-sm" onclick="editItem(${item.id})">✏️</button>
<button class="btn btn-sm btn-danger" onclick="deleteItem(${item.id})">🗑️</button>
</td>
</tr>
`).join("");
}
}
document.getElementById("form").addEventListener("submit", async (e) => {
e.preventDefault();
const form = e.target;
const data = {
title: form.title.value,
client: form.client.value,
amount: parseInt(form.amount.value),
status: form.status.value
};
const url = editingId ? `/api/data/${editingId}` : "/api/data";
const method = editingId ? "PUT" : "POST";
await fetch(url, {
method,
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data)
});
form.reset();
editingId = null;
form.querySelector("button").textContent = "Добавить";
load();
});
async function editItem(id) {
const res = await fetch("/api/data");
const data = await res.json();
const item = data.items.find(i => i.id === id);
if (!item) return;
const form = document.getElementById("form");
form.title.value = item.title;
form.client.value = item.client;
form.amount.value = item.amount;
form.status.value = item.status;
editingId = id;
form.querySelector("button").textContent = "Сохранить";
}
async function deleteItem(id) {
if (!confirm("Удалить эту запись?")) return;
await fetch(`/api/data/${id}`, { method: "DELETE" });
load();
}
load();
</script>
</body>
</html>