const http = require("http"); const fs = require("fs"); const path = require("path"); const PORT = process.env.PORT || 3000; const DATA = path.join(__dirname, "data.json"); const EVENT = { name: "Корпоративный ивент 2026", date: "30.10.2026", place: "Алматы, ДК «Жибек жолы»", capacity: 400 }; function db() { try { const d = JSON.parse(fs.readFileSync(DATA, "utf8")); return { event: Object.assign(EVENT, d.event || {}), registrations: Array.isArray(d.registrations) ? d.registrations : [] }; } catch (_) { return { event: EVENT, registrations: [] }; } } function persist(d) { fs.writeFileSync(DATA, JSON.stringify(d, null, 2)); } function readBody(req) { return new Promise((resolve) => { let s = ""; req.on("data", (c) => { s += c; if (s.length > 1e6) req.destroy(); }); req.on("end", () => { try { resolve(JSON.parse(s || "{}")); } catch (_) { resolve(null); } }); }); } function json(res, code, obj) { res.writeHead(code, { "Content-Type": "application/json; charset=utf-8" }); res.end(JSON.stringify(obj)); } const MIME = { ".html": "text/html", ".css": "text/css", ".js": "application/javascript", ".json": "application/json", ".png": "image/png", ".jpg": "image/jpeg", ".svg": "image/svg+xml", ".ico": "image/x-icon", ".woff2": "font/woff2", ".woff": "font/woff", ".ttf": "font/ttf" }; http.createServer(async (req, res) => { const url = req.url.split("?")[0]; if (req.method === "GET" && url === "/api/registrations") { return json(res, 200, db().registrations); } if (req.method === "POST" && url === "/api/registrations") { const body = await readBody(req); if (!body) return json(res, 400, { ok: false, error: "Некорректные данные" }); const name = String(body.name || "").trim().replace(/\s+/g, " "); const email = String(body.email || "").trim().toLowerCase(); const phone = String(body.phone || "").trim(); if (!name || name.length < 3) return json(res, 400, { ok: false, error: "Укажите ФИО" }); if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) return json(res, 400, { ok: false, error: "Введите корректный адрес почты" }); if (phone.replace(/\D/g, "").length < 10) return json(res, 400, { ok: false, error: "Укажите телефон" }); const d = db(); if (d.registrations.some((r) => r.email === email)) { return json(res, 409, { ok: false, error: "Заявка с этой почтой уже есть" }); } const r = { id: Date.now(), name, email, phone, department: String(body.department || "").trim(), position: String(body.position || "").trim(), role: String(body.role || "Сотрудник"), track: String(body.track || "Все сессии"), food: String(body.food || "Обычное"), status: "Заявка", createdAt: new Date().toISOString() }; d.registrations.push(r); persist(d); return json(res, 200, { ok: true, registration: r }); } if (req.method === "PATCH" && /^\/api\/registrations\/\d+$/.test(url)) { const id = Number(url.split("/").pop()); const body = await readBody(req); if (!body) return json(res, 400, { ok: false, error: "Некорректные данные" }); const d = db(); const r = d.registrations.find((x) => x.id === id); if (!r) return json(res, 404, { ok: false, error: "Заявка не найдена" }); if ("status" in body) r.status = String(body.status || "Заявка"); const note = String(body.note == null ? "" : body.note).trim(); r.note = note; persist(d); return json(res, 200, { ok: true, registration: r }); } let file = url === "/" ? "index.html" : url; file = file.replace(/^\/+/, ""); const full = path.normalize(path.join(__dirname, file)); if (!full.startsWith(__dirname)) return json(res, 403, { ok: false, error: "Forbidden" }); if (fs.existsSync(full) && fs.statSync(full).isFile()) { res.writeHead(200, { "Content-Type": (MIME[path.extname(full)] || "application/octet-stream") + "; charset=utf-8" }); return res.end(fs.readFileSync(full)); } return json(res, 404, { ok: false, error: "Not found" }); }).listen(PORT, () => console.log("Сервер на порту " + PORT));