full app with server + data.json database
This commit is contained in:
parent
78be3fc67f
commit
cf45d0a038
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
node_modules/
|
||||
.vibe42-run.log
|
||||
.vibe42-run.pid
|
||||
26
data.json
Normal file
26
data.json
Normal file
@ -0,0 +1,26 @@
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"firstName": "Алишер",
|
||||
"lastName": "Нурсултанов",
|
||||
"phone": "+7 (777) 123-45-67",
|
||||
"telegram": "@alisher_ns",
|
||||
"registeredAt": "2026-09-12T10:30:00.000Z"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"firstName": "Динара",
|
||||
"lastName": "Кенжегулова",
|
||||
"phone": "+7 (701) 234-56-78",
|
||||
"telegram": "@dinara_kz",
|
||||
"registeredAt": "2026-09-13T14:15:00.000Z"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"firstName": "Максат",
|
||||
"lastName": "Ибрагимов",
|
||||
"phone": "+7 (778) 345-67-89",
|
||||
"telegram": "@maxat_dev",
|
||||
"registeredAt": "2026-09-13T16:45:00.000Z"
|
||||
}
|
||||
]
|
||||
47
index.html
47
index.html
@ -75,6 +75,14 @@
|
||||
font-size: 48px;
|
||||
margin-bottom: var(--kt-ai-space-3);
|
||||
}
|
||||
.error-message {
|
||||
background: var(--kt-ai-bg-soft);
|
||||
border: 1px solid var(--kt-ai-border);
|
||||
border-radius: var(--kt-ai-radius-xl);
|
||||
padding: var(--kt-ai-space-4);
|
||||
color: var(--kt-ai-fg-muted);
|
||||
margin-top: var(--kt-ai-space-4);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="kt-ai-app" data-kt-data-mode="demo">
|
||||
@ -100,7 +108,7 @@
|
||||
</p>
|
||||
<div class="kt-ai-hero-actions" style="justify-content:center">
|
||||
<a class="kt-ai-btn" data-variant="primary" data-size="lg" href="#register">Зарегистрироваться</a>
|
||||
<a class="kt-ai-btn" data-size="lg" href="#participants">Участники</a>
|
||||
<a class="kt-ai-btn" data-size="lg" href="#about">О хакатоне</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -175,9 +183,10 @@
|
||||
<h3 style="margin-bottom:var(--kt-ai-space-2)">Регистрация успешна!</h3>
|
||||
<p style="color:var(--kt-ai-fg-muted)">Добро пожаловать на Hackathon Open 2026!</p>
|
||||
</div>
|
||||
<div id="errorMessage" class="error-message" style="display:none"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display:flex;flex-direction:column;gap:var(--kt-ai-space-6)">
|
||||
<div id="about" style="display:flex;flex-direction:column;gap:var(--kt-ai-space-6)">
|
||||
<article class="kt-ai-tile">
|
||||
<h3 style="margin-bottom:var(--kt-ai-space-2)">📅 Когда</h3>
|
||||
<p style="color:var(--kt-ai-fg-muted)">15-17 ноября 2026, старт в пятницу 18:00</p>
|
||||
@ -199,8 +208,6 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
<footer class="kt-ai-wrap kt-ai-pagefoot">
|
||||
<span>© 2026 Hackathon Open — Казахтелеком</span>
|
||||
<span class="kt-ai-spacer"></span>
|
||||
@ -209,15 +216,14 @@
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
document.getElementById('registrationForm').addEventListener('submit', function(e) {
|
||||
document.getElementById('registrationForm').addEventListener('submit', async function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const formData = {
|
||||
firstName: document.getElementById('firstName').value.trim(),
|
||||
lastName: document.getElementById('lastName').value.trim(),
|
||||
phone: document.getElementById('phone').value.trim(),
|
||||
telegram: document.getElementById('telegram').value.trim(),
|
||||
registeredAt: new Date().toISOString()
|
||||
telegram: document.getElementById('telegram').value.trim()
|
||||
};
|
||||
|
||||
if (!formData.firstName || !formData.lastName || !formData.phone || !formData.telegram) {
|
||||
@ -228,13 +234,28 @@ document.getElementById('registrationForm').addEventListener('submit', function(
|
||||
return;
|
||||
}
|
||||
|
||||
const submissions = JSON.parse(localStorage.getItem('hackathonSubmissions') || '[]');
|
||||
submissions.push(formData);
|
||||
localStorage.setItem('hackathonSubmissions', JSON.stringify(submissions));
|
||||
const successMsg = document.getElementById('successMessage');
|
||||
const errorMsg = document.getElementById('errorMessage');
|
||||
|
||||
document.getElementById('registrationForm').reset();
|
||||
document.getElementById('registrationForm').style.display = 'none';
|
||||
document.getElementById('successMessage').style.display = 'block';
|
||||
try {
|
||||
const response = await fetch('/api/registrations', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(formData)
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Ошибка сервера: ' + response.status);
|
||||
}
|
||||
|
||||
document.getElementById('registrationForm').reset();
|
||||
document.getElementById('registrationForm').style.display = 'none';
|
||||
successMsg.style.display = 'block';
|
||||
errorMsg.style.display = 'none';
|
||||
} catch (err) {
|
||||
errorMsg.textContent = 'Ошибка: ' + err.message + '. Попробуйте ещё раз.';
|
||||
errorMsg.style.display = 'block';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
10
package-lock.json
generated
Normal file
10
package-lock.json
generated
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "hackathon-registration",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "hackathon-registration"
|
||||
}
|
||||
}
|
||||
}
|
||||
6
package.json
Normal file
6
package.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "hackathon-registration",
|
||||
"private": true,
|
||||
"type": "commonjs",
|
||||
"scripts": { "start": "node server.js" }
|
||||
}
|
||||
65
server.js
Normal file
65
server.js
Normal file
@ -0,0 +1,65 @@
|
||||
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");
|
||||
|
||||
function readItems() {
|
||||
try { return JSON.parse(fs.readFileSync(DATA, "utf8")); } catch (_) { return []; }
|
||||
}
|
||||
function writeItems(items) {
|
||||
fs.writeFileSync(DATA, JSON.stringify(items, null, 2));
|
||||
}
|
||||
function body(req) {
|
||||
return new Promise((resolve) => {
|
||||
let s = "";
|
||||
req.on("data", (c) => (s += c));
|
||||
req.on("end", () => { try { resolve(JSON.parse(s || "{}")); } catch (_) { resolve({}); } });
|
||||
});
|
||||
}
|
||||
|
||||
http.createServer(async (req, res) => {
|
||||
const urlPath = req.url.split("?")[0];
|
||||
|
||||
if (req.method === "GET" && urlPath === "/api/registrations") {
|
||||
res.writeHead(200, { "Content-Type": "application/json" });
|
||||
return res.end(JSON.stringify(readItems()));
|
||||
}
|
||||
|
||||
if (req.method === "POST" && urlPath === "/api/registrations") {
|
||||
const item = await body(req);
|
||||
const items = readItems();
|
||||
const newItem = {
|
||||
id: Date.now(),
|
||||
firstName: item.firstName || "",
|
||||
lastName: item.lastName || "",
|
||||
phone: item.phone || "",
|
||||
telegram: item.telegram || "",
|
||||
registeredAt: new Date().toISOString()
|
||||
};
|
||||
items.push(newItem);
|
||||
writeItems(items);
|
||||
res.writeHead(200, { "Content-Type": "application/json" });
|
||||
return res.end(JSON.stringify({ ok: true, data: newItem }));
|
||||
}
|
||||
|
||||
if (req.method === "GET" && urlPath === "/api/stats") {
|
||||
const items = readItems();
|
||||
const today = new Date().toDateString();
|
||||
const todayCount = items.filter(p => new Date(p.registeredAt).toDateString() === today).length;
|
||||
res.writeHead(200, { "Content-Type": "application/json" });
|
||||
return res.end(JSON.stringify({ total: items.length, today: todayCount }));
|
||||
}
|
||||
|
||||
let file = req.url === "/" ? "/index.html" : urlPath;
|
||||
const full = path.join(__dirname, file);
|
||||
if (full.startsWith(__dirname) && fs.existsSync(full) && fs.statSync(full).isFile()) {
|
||||
const ext = path.extname(full);
|
||||
const type = ext === ".css" ? "text/css" : ext === ".js" ? "application/javascript" : "text/html";
|
||||
res.writeHead(200, { "Content-Type": type + "; charset=utf-8" });
|
||||
return res.end(fs.readFileSync(full));
|
||||
}
|
||||
|
||||
res.writeHead(404); res.end("Not found");
|
||||
}).listen(PORT, () => console.log("Сервер запущен на порту " + PORT));
|
||||
Loading…
Reference in New Issue
Block a user