upcoming events dynamic
This commit is contained in:
parent
b42f8a9e69
commit
ead2eef1b5
13
.env.example
13
.env.example
@ -1,13 +0,0 @@
|
|||||||
# Database Configuration
|
|
||||||
DB_HOST=82.25.95.117
|
|
||||||
DB_USER=user_tamilculturewaterloo
|
|
||||||
DB_PASSWORD=Metatron@2025
|
|
||||||
DB_NAME=user_tamilculturewaterloo
|
|
||||||
|
|
||||||
# Server Configuration
|
|
||||||
PORT=3006
|
|
||||||
|
|
||||||
DB_CONNECTION_LIMIT=20
|
|
||||||
DB_ACQUIRE_TIMEOUT=60000
|
|
||||||
DB_TIMEOUT=60000
|
|
||||||
DB_IDLE_TIMEOUT=300000
|
|
||||||
392
server.js
392
server.js
@ -157,6 +157,120 @@ async function ensureEventImagesSortOrderColumn() {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function ensureUpcomingEventsTable() {
|
||||||
|
try {
|
||||||
|
await pool.execute(`
|
||||||
|
CREATE TABLE IF NOT EXISTS upcoming_events (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
title VARCHAR(255),
|
||||||
|
eventtitle VARCHAR(255),
|
||||||
|
slug VARCHAR(255),
|
||||||
|
date VARCHAR(255),
|
||||||
|
eventdate VARCHAR(255),
|
||||||
|
time VARCHAR(255),
|
||||||
|
location VARCHAR(255),
|
||||||
|
image TEXT,
|
||||||
|
eventimageurl TEXT,
|
||||||
|
link TEXT,
|
||||||
|
btn_text VARCHAR(255) DEFAULT 'Details Coming Soon',
|
||||||
|
btnText VARCHAR(255) DEFAULT 'Details Coming Soon',
|
||||||
|
description TEXT,
|
||||||
|
eventdescription TEXT,
|
||||||
|
admission VARCHAR(255),
|
||||||
|
sort_order INT DEFAULT 0,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
)
|
||||||
|
`);
|
||||||
|
|
||||||
|
const [columns] = await pool.execute("SHOW COLUMNS FROM upcoming_events");
|
||||||
|
const colNames = columns.map(col => col.Field);
|
||||||
|
|
||||||
|
if (colNames.includes('year')) {
|
||||||
|
try {
|
||||||
|
await pool.execute("ALTER TABLE upcoming_events MODIFY COLUMN year INT NULL DEFAULT 2026");
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('Could not modify year column:', err.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const columnsToAdd = [
|
||||||
|
{ name: 'title', type: 'VARCHAR(255)' },
|
||||||
|
{ name: 'date', type: 'VARCHAR(255)' },
|
||||||
|
{ name: 'image', type: 'TEXT' },
|
||||||
|
{ name: 'description', type: 'TEXT' },
|
||||||
|
{ name: 'btn_text', type: "VARCHAR(255) DEFAULT 'Details Coming Soon'" },
|
||||||
|
{ name: 'admission', type: 'VARCHAR(255)' },
|
||||||
|
{ name: 'sort_order', type: 'INT DEFAULT 0' }
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const col of columnsToAdd) {
|
||||||
|
if (!colNames.includes(col.name)) {
|
||||||
|
await pool.execute(`ALTER TABLE upcoming_events ADD COLUMN ${col.name} ${col.type}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('✅ Verified upcoming_events table');
|
||||||
|
|
||||||
|
const [existing] = await pool.execute(
|
||||||
|
'SELECT id FROM upcoming_events WHERE title = ? OR eventtitle = ?',
|
||||||
|
['KW Multicultural Festival', 'KW Multicultural Festival']
|
||||||
|
);
|
||||||
|
|
||||||
|
if (existing.length === 0) {
|
||||||
|
const hasYearCol = colNames.includes('year');
|
||||||
|
if (hasYearCol) {
|
||||||
|
await pool.execute(
|
||||||
|
`INSERT INTO upcoming_events (year, title, eventtitle, slug, date, eventdate, time, location, image, eventimageurl, link, btn_text, btnText, description, eventdescription)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||||
|
[
|
||||||
|
2026,
|
||||||
|
'KW Multicultural Festival',
|
||||||
|
'KW Multicultural Festival',
|
||||||
|
'kw-multicultural-festival-2026',
|
||||||
|
'Jun 20, 2026 and Jun 21, 2026',
|
||||||
|
'Jun 20, 2026 and Jun 21, 2026',
|
||||||
|
'Details will be announced',
|
||||||
|
'Victoria Park, Kitchener',
|
||||||
|
'/assets/img/event/upcoming-event/multicultural-festival.webp',
|
||||||
|
'/assets/img/event/upcoming-event/multicultural-festival.webp',
|
||||||
|
'/upcoming-event/kw-multicultural-festival-2026',
|
||||||
|
'Details Coming Soon',
|
||||||
|
'Details Coming Soon',
|
||||||
|
'KW Multicultural Festival will take place on Jun 20-21, 2026 at Victoria Park, Kitchener. More details will be updated soon.',
|
||||||
|
'KW Multicultural Festival will take place on Jun 20-21, 2026 at Victoria Park, Kitchener. More details will be updated soon.'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
await pool.execute(
|
||||||
|
`INSERT INTO upcoming_events (title, eventtitle, slug, date, eventdate, time, location, image, eventimageurl, link, btn_text, btnText, description, eventdescription)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||||
|
[
|
||||||
|
'KW Multicultural Festival',
|
||||||
|
'KW Multicultural Festival',
|
||||||
|
'kw-multicultural-festival-2026',
|
||||||
|
'Jun 20, 2026 and Jun 21, 2026',
|
||||||
|
'Jun 20, 2026 and Jun 21, 2026',
|
||||||
|
'Details will be announced',
|
||||||
|
'Victoria Park, Kitchener',
|
||||||
|
'/assets/img/event/upcoming-event/multicultural-festival.webp',
|
||||||
|
'/assets/img/event/upcoming-event/multicultural-festival.webp',
|
||||||
|
'/upcoming-event/kw-multicultural-festival-2026',
|
||||||
|
'Details Coming Soon',
|
||||||
|
'Details Coming Soon',
|
||||||
|
'KW Multicultural Festival will take place on Jun 20-21, 2026 at Victoria Park, Kitchener. More details will be updated soon.',
|
||||||
|
'KW Multicultural Festival will take place on Jun 20-21, 2026 at Victoria Park, Kitchener. More details will be updated soon.'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
console.log('✅ Seeded initial upcoming event: KW Multicultural Festival');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Failed to ensure upcoming_events table:', error.message);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Test database connection on startup
|
// Test database connection on startup
|
||||||
async function testDatabaseConnection() {
|
async function testDatabaseConnection() {
|
||||||
try {
|
try {
|
||||||
@ -166,6 +280,7 @@ async function testDatabaseConnection() {
|
|||||||
connection.release();
|
connection.release();
|
||||||
await ensureAdminUsersTable();
|
await ensureAdminUsersTable();
|
||||||
await ensureEventImagesSortOrderColumn();
|
await ensureEventImagesSortOrderColumn();
|
||||||
|
await ensureUpcomingEventsTable();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ Database connection failed:', error.message);
|
console.error('❌ Database connection failed:', error.message);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
@ -548,6 +663,253 @@ app.delete('/api/events/:id', async (req, res) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ===============================
|
||||||
|
// UPCOMING EVENTS CRUD ROUTES
|
||||||
|
// ===============================
|
||||||
|
|
||||||
|
// Helper function to slugify string
|
||||||
|
function slugify(text) {
|
||||||
|
if (!text) return '';
|
||||||
|
return text
|
||||||
|
.toString()
|
||||||
|
.toLowerCase()
|
||||||
|
.trim()
|
||||||
|
.replace(/\s+/g, '-') // Replace spaces with -
|
||||||
|
.replace(/[^\w\-]+/g, '') // Remove all non-word chars
|
||||||
|
.replace(/\-\-+/g, '-'); // Replace multiple - with single -
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET all upcoming events
|
||||||
|
app.get('/api/upcoming-events', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const [rows] = await pool.execute('SELECT * FROM upcoming_events ORDER BY sort_order ASC, id DESC');
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
data: rows
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching upcoming events:', error);
|
||||||
|
res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
message: 'Error fetching upcoming events',
|
||||||
|
error: error.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// GET single upcoming event by ID
|
||||||
|
app.get('/api/upcoming-events/:id', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const [rows] = await pool.execute('SELECT * FROM upcoming_events WHERE id = ?', [req.params.id]);
|
||||||
|
if (rows.length === 0) {
|
||||||
|
return res.status(404).json({
|
||||||
|
success: false,
|
||||||
|
message: 'Upcoming event not found'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
data: rows[0]
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching upcoming event:', error);
|
||||||
|
res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
message: 'Error fetching upcoming event',
|
||||||
|
error: error.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// GET single upcoming event by slug or ID
|
||||||
|
app.get('/api/upcoming-events/slug/:slug', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const rawSlug = req.params.slug ? req.params.slug.trim() : '';
|
||||||
|
const cleanedSlug = slugify(rawSlug);
|
||||||
|
|
||||||
|
// 1. First priority: exact slug or ID match
|
||||||
|
let [rows] = await pool.execute(
|
||||||
|
'SELECT * FROM upcoming_events WHERE slug = ? OR slug = ? OR id = ?',
|
||||||
|
[rawSlug, cleanedSlug, rawSlug]
|
||||||
|
);
|
||||||
|
|
||||||
|
// 2. Second priority: title slug match fallback
|
||||||
|
if (rows.length === 0 && cleanedSlug) {
|
||||||
|
[rows] = await pool.execute(
|
||||||
|
'SELECT * FROM upcoming_events WHERE LOWER(REPLACE(title, " ", "-")) = ? OR LOWER(REPLACE(eventtitle, " ", "-")) = ?',
|
||||||
|
[cleanedSlug, cleanedSlug]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rows.length === 0) {
|
||||||
|
return res.status(404).json({
|
||||||
|
success: false,
|
||||||
|
message: 'Upcoming event not found'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
data: rows[0]
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching upcoming event by slug:', error);
|
||||||
|
res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
message: 'Error fetching upcoming event',
|
||||||
|
error: error.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// POST create new upcoming event
|
||||||
|
app.post('/api/upcoming-events', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { title, eventtitle, slug, date, eventdate, time, location, venue, image, image_url, eventimageurl, link, btn_text, btnText, description, desc, eventdescription, admission } = req.body;
|
||||||
|
|
||||||
|
const inputTitle = title || eventtitle;
|
||||||
|
if (!inputTitle || String(inputTitle).trim() === '') {
|
||||||
|
return res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
message: 'Event title is required'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const finalTitle = String(inputTitle).trim();
|
||||||
|
const generatedSlug = slugify(finalTitle);
|
||||||
|
const finalSlug = (slug && String(slug).trim()) ? slugify(String(slug).trim()) : generatedSlug;
|
||||||
|
const finalLocation = location || venue || '';
|
||||||
|
const finalImage = image || image_url || eventimageurl || '';
|
||||||
|
const finalBtnText = btn_text || btnText || 'Details Coming Soon';
|
||||||
|
const finalDesc = description || desc || eventdescription || '';
|
||||||
|
const finalLink = (link && String(link).trim() && !String(link).startsWith('/upcoming-event/'))
|
||||||
|
? String(link).trim()
|
||||||
|
: `/upcoming-event/${finalSlug}`;
|
||||||
|
const finalDate = date || eventdate || '';
|
||||||
|
const finalTime = time || '';
|
||||||
|
const finalAdmission = admission || null;
|
||||||
|
|
||||||
|
const [result] = await pool.execute(
|
||||||
|
`INSERT INTO upcoming_events (title, eventtitle, slug, date, eventdate, time, location, image, eventimageurl, link, btn_text, btnText, description, eventdescription, admission)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||||
|
[finalTitle, finalTitle, finalSlug, finalDate, finalDate, finalTime, finalLocation, finalImage, finalImage, finalLink, finalBtnText, finalBtnText, finalDesc, finalDesc, finalAdmission]
|
||||||
|
);
|
||||||
|
|
||||||
|
res.status(201).json({
|
||||||
|
success: true,
|
||||||
|
message: 'Upcoming event created successfully',
|
||||||
|
data: {
|
||||||
|
id: result.insertId,
|
||||||
|
title: finalTitle,
|
||||||
|
slug: finalSlug,
|
||||||
|
link: finalLink
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error creating upcoming event:', error);
|
||||||
|
res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
message: 'Error creating upcoming event',
|
||||||
|
error: error.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// PUT update upcoming event (supports full or partial updates)
|
||||||
|
app.put('/api/upcoming-events/:id', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const eventId = req.params.id;
|
||||||
|
|
||||||
|
// Fetch existing record
|
||||||
|
const [rows] = await pool.execute('SELECT * FROM upcoming_events WHERE id = ?', [eventId]);
|
||||||
|
if (rows.length === 0) {
|
||||||
|
return res.status(404).json({
|
||||||
|
success: false,
|
||||||
|
message: 'Upcoming event not found'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const existing = rows[0];
|
||||||
|
const { title, eventtitle, slug, date, eventdate, time, location, venue, image, image_url, eventimageurl, link, btn_text, btnText, description, desc, eventdescription, admission, sort_order } = req.body || {};
|
||||||
|
|
||||||
|
const inputTitle = title || eventtitle || existing.title || existing.eventtitle;
|
||||||
|
if (!inputTitle || String(inputTitle).trim() === '') {
|
||||||
|
return res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
message: 'Event title is required'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const finalTitle = String(inputTitle).trim();
|
||||||
|
const generatedSlug = slugify(finalTitle);
|
||||||
|
|
||||||
|
let finalSlug = generatedSlug;
|
||||||
|
if (slug && String(slug).trim()) {
|
||||||
|
const userSlug = slugify(String(slug).trim());
|
||||||
|
const oldTitleSlug = slugify(existing.title || existing.eventtitle || '');
|
||||||
|
if (userSlug !== oldTitleSlug) {
|
||||||
|
finalSlug = userSlug;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const finalLocation = location !== undefined ? location : (venue !== undefined ? venue : (existing.location || ''));
|
||||||
|
const finalImage = image !== undefined ? image : (image_url !== undefined ? image_url : (eventimageurl !== undefined ? eventimageurl : (existing.image || existing.eventimageurl || '')));
|
||||||
|
const finalBtnText = btn_text !== undefined ? btn_text : (btnText !== undefined ? btnText : (existing.btn_text || existing.btnText || 'Details Coming Soon'));
|
||||||
|
const finalDesc = description !== undefined ? description : (desc !== undefined ? desc : (eventdescription !== undefined ? eventdescription : (existing.description || existing.eventdescription || '')));
|
||||||
|
const finalLink = (link && String(link).trim() && !String(link).startsWith('/upcoming-event/'))
|
||||||
|
? String(link).trim()
|
||||||
|
: `/upcoming-event/${finalSlug}`;
|
||||||
|
const finalDate = date !== undefined ? date : (eventdate !== undefined ? eventdate : (existing.date || existing.eventdate || ''));
|
||||||
|
const finalTime = time !== undefined ? time : (existing.time || '');
|
||||||
|
const finalAdmission = admission !== undefined ? admission : existing.admission;
|
||||||
|
const finalSortOrder = sort_order !== undefined ? Number(sort_order) : (existing.sort_order || 0);
|
||||||
|
|
||||||
|
await pool.execute(
|
||||||
|
`UPDATE upcoming_events
|
||||||
|
SET title = ?, eventtitle = ?, slug = ?, date = ?, eventdate = ?, time = ?, location = ?, image = ?, eventimageurl = ?, link = ?, btn_text = ?, btnText = ?, description = ?, eventdescription = ?, admission = ?, sort_order = ?
|
||||||
|
WHERE id = ?`,
|
||||||
|
[finalTitle, finalTitle, finalSlug, finalDate, finalDate, finalTime, finalLocation, finalImage, finalImage, finalLink, finalBtnText, finalBtnText, finalDesc, finalDesc, finalAdmission, finalSortOrder, eventId]
|
||||||
|
);
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
message: 'Upcoming event updated successfully'
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error updating upcoming event:', error);
|
||||||
|
res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
message: 'Error updating upcoming event',
|
||||||
|
error: error.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// DELETE upcoming event
|
||||||
|
app.delete('/api/upcoming-events/:id', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const [result] = await pool.execute('DELETE FROM upcoming_events WHERE id = ?', [req.params.id]);
|
||||||
|
|
||||||
|
if (result.affectedRows === 0) {
|
||||||
|
return res.status(404).json({
|
||||||
|
success: false,
|
||||||
|
message: 'Upcoming event not found'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
message: 'Upcoming event deleted successfully'
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error deleting upcoming event:', error);
|
||||||
|
res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
message: 'Error deleting upcoming event',
|
||||||
|
error: error.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// ===============================
|
// ===============================
|
||||||
// EVENT_IMAGES CRUD ROUTES
|
// EVENT_IMAGES CRUD ROUTES
|
||||||
// ===============================
|
// ===============================
|
||||||
@ -579,9 +941,9 @@ app.get('/api/event-images', async (req, res) => {
|
|||||||
app.get('/api/event-images/event/:eventId', async (req, res) => {
|
app.get('/api/event-images/event/:eventId', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const [rows] = await pool.execute(
|
const [rows] = await pool.execute(
|
||||||
'SELECT * FROM event_images WHERE eventid = ? ORDER BY sort_order ASC, id ASC',
|
'SELECT * FROM event_images WHERE eventid = ? ORDER BY sort_order ASC, id ASC',
|
||||||
[req.params.eventId]
|
[req.params.eventId]
|
||||||
);
|
);
|
||||||
res.json({
|
res.json({
|
||||||
success: true,
|
success: true,
|
||||||
data: rows
|
data: rows
|
||||||
@ -664,7 +1026,7 @@ app.post('/api/event-images', async (req, res) => {
|
|||||||
// Bulk reorder images
|
// Bulk reorder images
|
||||||
app.put('/api/event-images/reorder', async (req, res) => {
|
app.put('/api/event-images/reorder', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
console.log("Request body:", req.body);
|
console.log("Request body:", req.body);
|
||||||
const { images } = req.body; // Array of { id, sort_order }
|
const { images } = req.body; // Array of { id, sort_order }
|
||||||
console.log(`Reorder request received for ${images?.length} images`);
|
console.log(`Reorder request received for ${images?.length} images`);
|
||||||
|
|
||||||
@ -700,18 +1062,18 @@ app.put('/api/event-images/reorder', async (req, res) => {
|
|||||||
connection.release();
|
connection.release();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("===== REORDER ERROR =====");
|
console.error("===== REORDER ERROR =====");
|
||||||
console.error(error);
|
console.error(error);
|
||||||
console.error("Message:", error.message);
|
console.error("Message:", error.message);
|
||||||
console.error("Code:", error.code);
|
console.error("Code:", error.code);
|
||||||
console.error("=========================");
|
console.error("=========================");
|
||||||
|
|
||||||
res.status(500).json({
|
res.status(500).json({
|
||||||
success: false,
|
success: false,
|
||||||
message: error.message,
|
message: error.message,
|
||||||
code: error.code
|
code: error.code
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post('/api/event-images/bulk', async (req, res) => {
|
app.post('/api/event-images/bulk', async (req, res) => {
|
||||||
|
|||||||
20
setup-db.js
20
setup-db.js
@ -52,6 +52,26 @@ async function setup() {
|
|||||||
`);
|
`);
|
||||||
console.log('Verified event_images table exists.');
|
console.log('Verified event_images table exists.');
|
||||||
|
|
||||||
|
// Create upcoming_events table
|
||||||
|
await pool.execute(`
|
||||||
|
CREATE TABLE IF NOT EXISTS upcoming_events (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
title VARCHAR(255) NOT NULL,
|
||||||
|
slug VARCHAR(255),
|
||||||
|
date VARCHAR(255),
|
||||||
|
time VARCHAR(255),
|
||||||
|
location VARCHAR(255),
|
||||||
|
image TEXT,
|
||||||
|
link TEXT,
|
||||||
|
btn_text VARCHAR(255) DEFAULT 'Details Coming Soon',
|
||||||
|
description TEXT,
|
||||||
|
admission VARCHAR(255),
|
||||||
|
sort_order INT DEFAULT 0,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
)
|
||||||
|
`);
|
||||||
|
console.log('Verified upcoming_events table exists.');
|
||||||
|
|
||||||
// Check if admin user exists
|
// Check if admin user exists
|
||||||
const [rows] = await pool.execute('SELECT * FROM admin_users WHERE email = ?', ['admin@example.com']);
|
const [rows] = await pool.execute('SELECT * FROM admin_users WHERE email = ?', ['admin@example.com']);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user