177 lines
4.7 KiB
TypeScript
177 lines
4.7 KiB
TypeScript
import Database from 'better-sqlite3';
|
|
import bcrypt from 'bcryptjs';
|
|
|
|
async function setupDatabase() {
|
|
const db = new Database('sqlite.db');
|
|
|
|
// Enable foreign keys
|
|
db.pragma('foreign_keys = ON');
|
|
|
|
// Create tables
|
|
db.exec(`
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id TEXT PRIMARY KEY,
|
|
email TEXT NOT NULL UNIQUE,
|
|
name TEXT NOT NULL,
|
|
surname TEXT NOT NULL,
|
|
password TEXT NOT NULL,
|
|
role TEXT NOT NULL DEFAULT 'user' CHECK (role IN ('user', 'admin')),
|
|
created_at INTEGER NOT NULL,
|
|
updated_at INTEGER NOT NULL
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS courts (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
is_active INTEGER NOT NULL DEFAULT 1,
|
|
created_at INTEGER NOT NULL,
|
|
updated_at INTEGER NOT NULL
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS settings (
|
|
id TEXT PRIMARY KEY,
|
|
key TEXT NOT NULL UNIQUE,
|
|
value TEXT NOT NULL,
|
|
description TEXT,
|
|
created_at INTEGER NOT NULL,
|
|
updated_at INTEGER NOT NULL
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS time_slots (
|
|
id TEXT PRIMARY KEY,
|
|
start_time TEXT NOT NULL,
|
|
end_time TEXT NOT NULL,
|
|
is_active INTEGER NOT NULL DEFAULT 1,
|
|
created_at INTEGER NOT NULL,
|
|
updated_at INTEGER NOT NULL
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS bookings (
|
|
id TEXT PRIMARY KEY,
|
|
user_id TEXT NOT NULL,
|
|
court_id TEXT NOT NULL,
|
|
date TEXT NOT NULL,
|
|
time_slot_id TEXT NOT NULL,
|
|
status TEXT NOT NULL DEFAULT 'confirmed' CHECK (status IN ('confirmed', 'cancelled', 'pending')),
|
|
created_at INTEGER NOT NULL,
|
|
updated_at INTEGER NOT NULL,
|
|
FOREIGN KEY (user_id) REFERENCES users(id),
|
|
FOREIGN KEY (court_id) REFERENCES courts(id),
|
|
FOREIGN KEY (time_slot_id) REFERENCES time_slots(id)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS announcements (
|
|
id TEXT PRIMARY KEY,
|
|
title TEXT NOT NULL,
|
|
content TEXT NOT NULL,
|
|
is_active INTEGER NOT NULL DEFAULT 1,
|
|
created_at INTEGER NOT NULL,
|
|
updated_at INTEGER NOT NULL
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS activity_logs (
|
|
id TEXT PRIMARY KEY,
|
|
user_id TEXT NOT NULL,
|
|
action TEXT NOT NULL,
|
|
details TEXT,
|
|
created_at INTEGER NOT NULL,
|
|
FOREIGN KEY (user_id) REFERENCES users(id)
|
|
);
|
|
`);
|
|
|
|
console.log('Tables created successfully!');
|
|
|
|
// Insert default admin user
|
|
const now = Date.now();
|
|
const adminPassword = await bcrypt.hash('admin123', 10);
|
|
|
|
try {
|
|
const stmt = db.prepare(`
|
|
INSERT OR IGNORE INTO users (id, email, name, surname, password, role, created_at, updated_at)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
`);
|
|
|
|
stmt.run(
|
|
'admin-' + crypto.randomUUID(),
|
|
'admin@ttbooking.com',
|
|
'Admin',
|
|
'User',
|
|
adminPassword,
|
|
'admin',
|
|
now,
|
|
now
|
|
);
|
|
|
|
console.log('Admin user created: admin@ttbooking.com / admin123');
|
|
} catch (error) {
|
|
console.log('Admin user might already exist');
|
|
}
|
|
|
|
// Insert default courts
|
|
try {
|
|
const courtStmt = db.prepare(`
|
|
INSERT OR IGNORE INTO courts (id, name, is_active, created_at, updated_at)
|
|
VALUES (?, ?, ?, ?, ?)
|
|
`);
|
|
|
|
courtStmt.run('court-1', 'Court 1', 1, now, now);
|
|
courtStmt.run('court-2', 'Court 2', 1, now, now);
|
|
|
|
console.log('Default courts created');
|
|
} catch (error) {
|
|
console.log('Courts might already exist');
|
|
}
|
|
|
|
// Insert time slots
|
|
try {
|
|
const timeSlotStmt = db.prepare(`
|
|
INSERT OR IGNORE INTO time_slots (id, start_time, end_time, is_active, created_at, updated_at)
|
|
VALUES (?, ?, ?, ?, ?, ?)
|
|
`);
|
|
|
|
const timeSlots = [
|
|
['09:00', '10:00'],
|
|
['10:00', '11:00'],
|
|
['11:00', '12:00'],
|
|
['12:00', '13:00'],
|
|
['13:00', '14:00'],
|
|
['14:00', '15:00'],
|
|
['15:00', '16:00'],
|
|
['16:00', '17:00'],
|
|
['17:00', '18:00'],
|
|
['18:00', '19:00'],
|
|
['19:00', '20:00'],
|
|
['20:00', '21:00'],
|
|
];
|
|
|
|
timeSlots.forEach(([start, end], index) => {
|
|
timeSlotStmt.run(`slot-${index + 1}`, start, end, 1, now, now);
|
|
});
|
|
|
|
console.log('Time slots created');
|
|
} catch (error) {
|
|
console.log('Time slots might already exist');
|
|
}
|
|
|
|
// Insert default settings
|
|
try {
|
|
const settingsStmt = db.prepare(`
|
|
INSERT OR IGNORE INTO settings (id, key, value, description, created_at, updated_at)
|
|
VALUES (?, ?, ?, ?, ?, ?)
|
|
`);
|
|
|
|
settingsStmt.run('setting-1', 'booking_advance_days', '7', 'Days in advance users can book', now, now);
|
|
settingsStmt.run('setting-2', 'max_bookings_per_user', '3', 'Maximum bookings per user per week', now, now);
|
|
settingsStmt.run('setting-3', 'booking_duration', '60', 'Booking duration in minutes', now, now);
|
|
|
|
console.log('Default settings created');
|
|
} catch (error) {
|
|
console.log('Settings might already exist');
|
|
}
|
|
|
|
db.close();
|
|
console.log('Database setup completed!');
|
|
}
|
|
|
|
setupDatabase().catch(console.error);
|