Add database integration, auth API, admin/user portals, and deploy-db.sh
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
import { db } from './db';
|
||||
import bcrypt from 'bcryptjs';
|
||||
|
||||
export async function initSchema() {
|
||||
await db.query(`
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id SERIAL PRIMARY KEY,
|
||||
username VARCHAR(50) UNIQUE NOT NULL,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
role VARCHAR(20) NOT NULL CHECK (role IN ('admin', 'user')),
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
`);
|
||||
|
||||
await db.query(`
|
||||
CREATE TABLE IF NOT EXISTS images (
|
||||
id SERIAL PRIMARY KEY,
|
||||
filename VARCHAR(255) NOT NULL,
|
||||
data TEXT NOT NULL,
|
||||
uploaded_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
`);
|
||||
|
||||
await db.query(`
|
||||
CREATE TABLE IF NOT EXISTS reservations (
|
||||
id SERIAL PRIMARY KEY,
|
||||
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
|
||||
date DATE NOT NULL,
|
||||
time TIME NOT NULL,
|
||||
guests INTEGER NOT NULL,
|
||||
table_name VARCHAR(100) NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
`);
|
||||
|
||||
await db.query(`
|
||||
CREATE TABLE IF NOT EXISTS coupons (
|
||||
id SERIAL PRIMARY KEY,
|
||||
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
|
||||
code VARCHAR(50) NOT NULL,
|
||||
discount VARCHAR(255) NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
`);
|
||||
|
||||
await db.query(`
|
||||
CREATE TABLE IF NOT EXISTS offers (
|
||||
id SERIAL PRIMARY KEY,
|
||||
title VARCHAR(255) NOT NULL,
|
||||
description TEXT NOT NULL,
|
||||
active BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
`);
|
||||
|
||||
await db.query(`
|
||||
CREATE TABLE IF NOT EXISTS benefits (
|
||||
id SERIAL PRIMARY KEY,
|
||||
text VARCHAR(500) NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
`);
|
||||
|
||||
await db.query(`
|
||||
CREATE TABLE IF NOT EXISTS config (
|
||||
key VARCHAR(100) PRIMARY KEY,
|
||||
value TEXT NOT NULL
|
||||
);
|
||||
`);
|
||||
}
|
||||
|
||||
export async function seed() {
|
||||
const { rows: adminRows } = await db.query(`SELECT id FROM users WHERE username = 'admin'`);
|
||||
if (adminRows.length === 0) {
|
||||
const adminHash = bcrypt.hashSync('admin', 10);
|
||||
const userHash = bcrypt.hashSync('user', 10);
|
||||
|
||||
await db.query(
|
||||
`INSERT INTO users (username, password_hash, role) VALUES ($1, $2, $3), ($4, $5, $6)`,
|
||||
['admin', adminHash, 'admin', 'user', userHash, 'user']
|
||||
);
|
||||
}
|
||||
|
||||
const { rows: offerRows } = await db.query(`SELECT id FROM offers`);
|
||||
if (offerRows.length === 0) {
|
||||
await db.query(
|
||||
`INSERT INTO offers (title, description) VALUES
|
||||
($1, $2), ($3, $4)`,
|
||||
[
|
||||
'Summer Wine Weekend', 'Complimentary wine tasting with every two-night stay.',
|
||||
'Sunset Dinner', 'Three-course menu on the terrace every Friday.',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
const { rows: benefitRows } = await db.query(`SELECT id FROM benefits`);
|
||||
if (benefitRows.length === 0) {
|
||||
await db.query(
|
||||
`INSERT INTO benefits (text) VALUES
|
||||
($1), ($2), ($3), ($4)`,
|
||||
[
|
||||
'Priority booking for peak weekends',
|
||||
'Late checkout on availability',
|
||||
'Free welcome cocktail',
|
||||
'Member-only events and tastings',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
const { rows: configRows } = await db.query(`SELECT key FROM config WHERE key = 'wifi_password'`);
|
||||
if (configRows.length === 0) {
|
||||
await db.query(
|
||||
`INSERT INTO config (key, value) VALUES ($1, $2)`,
|
||||
['wifi_password', 'LaHuascaGuest2026']
|
||||
);
|
||||
}
|
||||
|
||||
const { rows: userResRows } = await db.query(`SELECT id FROM reservations WHERE user_id = (SELECT id FROM users WHERE username = 'user')`);
|
||||
if (userResRows.length === 0) {
|
||||
await db.query(
|
||||
`INSERT INTO reservations (user_id, date, time, guests, table_name)
|
||||
SELECT id, $2, $3, $4, $5 FROM users WHERE username = $1`,
|
||||
['user', '2026-07-12', '19:00', 4, 'Terrace 3']
|
||||
);
|
||||
await db.query(
|
||||
`INSERT INTO reservations (user_id, date, time, guests, table_name)
|
||||
SELECT id, $2, $3, $4, $5 FROM users WHERE username = $1`,
|
||||
['user', '2026-07-25', '20:30', 2, 'Barrel 7']
|
||||
);
|
||||
}
|
||||
|
||||
const { rows: userCouponRows } = await db.query(`SELECT id FROM coupons WHERE user_id = (SELECT id FROM users WHERE username = 'user')`);
|
||||
if (userCouponRows.length === 0) {
|
||||
await db.query(
|
||||
`INSERT INTO coupons (user_id, code, discount)
|
||||
SELECT id, $2, $3 FROM users WHERE username = $1`,
|
||||
['user', 'WELCOME20', '20% off your next stay']
|
||||
);
|
||||
await db.query(
|
||||
`INSERT INTO coupons (user_id, code, discount)
|
||||
SELECT id, $2, $3 FROM users WHERE username = $1`,
|
||||
['user', 'COFFEE5', '$5 off any coffee tasting']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function resetDatabase() {
|
||||
await db.query('DROP TABLE IF EXISTS config, benefits, offers, coupons, reservations, images, users CASCADE');
|
||||
await initSchema();
|
||||
await seed();
|
||||
}
|
||||
Reference in New Issue
Block a user