Numex yayın: server.js

This commit is contained in:
numex-admin 2026-09-10 08:58:38 +00:00
parent 2249e1d556
commit 868f02de6a

146
server.js Normal file
View File

@ -0,0 +1,146 @@
// server.js — Express backend
// Randevu sistemi: müşteri kaydı + çakışma kontrolü + günlük liste
const express = require('express');
const path = require('path');
const storage = require('./storage');
const app = express();
const PORT = process.env.PORT || 3000;
// Çalışma saatleri (09:00 - 18:00, her saat başı slot)
const OPEN_HOUR = 9;
const CLOSE_HOUR = 18;
const SLOT_MINUTES = 60;
app.use(express.json());
app.use(express.static(path.join(__dirname, 'public')));
// --- Yardımcılar ---
// Tarihi "YYYY-MM-DD" biçimine getirir
function normalizeDate(date) {
return date; // beklenen format zaten "YYYY-MM-DD"
}
// Saati "HH:MM" dakikaya çevirir (çakışma için)
function toMinutes(hhmm) {
const [h, m] = hhmm.split(':').map(Number);
return h * 60 + m;
}
// Belirtilen günde belirtilen zaman aralığına çakışan randevu var mı?
function isConflict(list, date, startMin, durationMin) {
const end = startMin + durationMin;
return list.some(a => {
if (a.date !== date) return false;
const aStart = toMinutes(a.time);
const aEnd = aStart + (a.duration || 0);
// Çakışma: iki aralık birbirine giriyorsa
return startMin < aEnd && end > aStart;
});
}
// Beklenen çalışma saati içinde mi?
function withinHours(startMin) {
return startMin >= OPEN_HOUR * 60 && (startMin + SLOT_MINUTES) <= CLOSE_HOUR * 60;
}
// --- API ---
// Sağlık kontrolü
app.get('/api/health', (req, res) => {
res.json({ ok: true, service: 'randevu-sistemi' });
});
// Boş slotları döndürür (bugünün veya istenen günün)
app.get('/api/slots', (req, res) => {
const date = req.query.date || null;
const list = storage.getAll();
const slots = [];
for (let m = OPEN_HOUR * 60; m < CLOSE_HOUR * 60; m += SLOT_MINUTES) {
const hh = String(Math.floor(m / 60)).padStart(2, '0');
const mm = String(m % 60).padStart(2, '0');
const time = `${hh}:${mm}`;
// Belirli gün verildiyse o günkü çakışmaları, yoksa genel geçmiş/tekrarı kontrol etme
const busy = date ? isConflict(list, date, m, SLOT_MINUTES) : false;
if (!busy) {
slots.push(time);
}
}
// date verilmediyse tüm saat dilimlerini döndür
if (!date) return res.json(slots);
res.json(slots);
});
// Yeni randevu oluştur (çakışma kontrolü ile)
app.post('/api/appointments', (req, res) => {
const { name, phone, date, time, service, notes } = req.body;
// Doğrulama
if (!name || !phone || !date || !time) {
return res.status(400).json({ error: 'Ad, telefon, tarih ve saat zorunludur.' });
}
// Tarih formatı "YYYY-MM-DD", saat "HH:MM"
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
return res.status(400).json({ error: 'Geçersiz tarih formatı. YYYY-MM-DD kullanın.' });
}
if (!/^\d{2}:\d{2}$/.test(time)) {
return res.status(400).json({ error: 'Geçersiz saat formatı. HH:MM kullanın.' });
}
const startMin = toMinutes(time);
if (!withinHours(startMin)) {
return res.status(400).json({
error: `Randevular yalnızca ${String(OPEN_HOUR).padStart(2,'0')}:00 - ${String(CLOSE_HOUR).padStart(2,'0')}:00 arası alınabilir.`
});
}
// Çakışma kontrolü
const list = storage.getAll();
if (isConflict(list, date, startMin, SLOT_MINUTES)) {
return res.status(409).json({ error: 'Bu saat dilimi dolu. Lütfen başka bir saat seçin.' });
}
const record = storage.add({
name,
phone,
date,
time,
service: service || 'Genel',
notes: notes || '',
duration: SLOT_MINUTES,
createdAt: new Date().toISOString()
});
res.status(201).json({ ok: true, appointment: record });
});
// Belirli bir günün randevularını döndürür (admin)
app.get('/api/appointments', (req, res) => {
const date = req.query.date;
let list = storage.getAll();
if (date) {
list = list.filter(a => a.date === date);
}
// Tarihe ve saate göre sırala
list.sort((a, b) => (a.date + a.time).localeCompare(b.date + b.time));
res.json(list);
});
// Belirli bir randevuyu sil (admin)
app.delete('/api/appointments/:id', (req, res) => {
const ok = storage.remove(req.params.id);
if (!ok) {
return res.status(404).json({ error: 'Randevu bulunamadı.' });
}
res.json({ ok: true });
});
// --- Sunucuyu başlat ---
storage.init();
app.listen(PORT, () => {
console.log(`Randevu sistemi çalışıyor: http://localhost:${PORT}`);
});