628 lines
14 KiB
TypeScript
628 lines
14 KiB
TypeScript
import express, { Request, Response } from 'express';
|
|
import { client } from '../app';
|
|
import { isLoggedInAPI } from '../util/guard';
|
|
import { logger } from '../util/logger';
|
|
|
|
export const scheduleRoutes = express.Router();
|
|
|
|
scheduleRoutes.get('/', isLoggedInAPI, getEventSchedule);
|
|
scheduleRoutes.post('/activity', isLoggedInAPI, postEventSchedule);
|
|
scheduleRoutes.put('/description/edit', isLoggedInAPI, editDescription);
|
|
scheduleRoutes.put('/remark/edit', isLoggedInAPI, editRemark);
|
|
scheduleRoutes.put('/timeName/edit', isLoggedInAPI, editTimeName);
|
|
scheduleRoutes.post('/item', isLoggedInAPI, postItem);
|
|
scheduleRoutes.delete('/timeBlock/', isLoggedInAPI, deleteTimeBlock);
|
|
|
|
// select * from time_blocks where start_time
|
|
// between '2022-10-12T10:00:00' and '2022-10-12T12:00:00'
|
|
// or end_time between '2022-10-12T10:00:00' and '2022-10-12T12:00:00';
|
|
|
|
// Date <- Birthday , no need to do comparison , Time is not useful
|
|
// Time <- only if it is not a moment, but a periodic time. "Every day 3pm"
|
|
// Datetime <- everything else
|
|
|
|
async function postItem(req: Request, res: Response) {
|
|
try {
|
|
logger.debug('Before reading DB');
|
|
const creator = req.query['is-creator'];
|
|
const timeBlockId = req.query['id'];
|
|
const itemList = req.body;
|
|
const eventId = req.query['event-id'];
|
|
|
|
const event = (
|
|
await client.query(
|
|
`
|
|
SELECT start_datetime, end_datetime, deleted FROM events
|
|
WHERE id = $1
|
|
`,
|
|
[eventId]
|
|
)
|
|
).rows[0];
|
|
|
|
const isDeleted = event.deleted;
|
|
const eventStartTimeInMin = event.start_datetime.getTime();
|
|
const eventEndTimeInMin = event.end_datetime.getTime();
|
|
const now = new Date().getTime();
|
|
|
|
let isProcessing = true;
|
|
|
|
if (eventStartTimeInMin < now && eventEndTimeInMin < now) {
|
|
isProcessing = false;
|
|
//event is finished
|
|
}
|
|
if (isDeleted) {
|
|
isProcessing = false;
|
|
//event was deleted by creator
|
|
}
|
|
|
|
if (creator === '1' && isProcessing) {
|
|
// delete existing list
|
|
await client.query(
|
|
`
|
|
DELETE FROM time_block_item
|
|
WHERE time_block_item.time_block_id = $1
|
|
`,
|
|
[timeBlockId]
|
|
);
|
|
|
|
itemList.forEach(async (item: any) => {
|
|
await client.query(
|
|
`
|
|
INSERT INTO time_block_item (time_block_id, item_id, created_at, updated_at)
|
|
VALUES ($1, $2, $3, $4)
|
|
`,
|
|
[timeBlockId, `${item}`, 'now()', 'now()']
|
|
);
|
|
});
|
|
|
|
res.json({
|
|
status: true,
|
|
msg: 'Items Added'
|
|
});
|
|
} else {
|
|
res.status(400).json({
|
|
msg: '[EER001]: Unauthorized Request'
|
|
});
|
|
}
|
|
} catch (e) {
|
|
logger.error(e);
|
|
res.status(500).json({
|
|
msg: '[ITM003]: Failed to Add Show Item'
|
|
});
|
|
}
|
|
}
|
|
|
|
async function editTimeName(req: Request, res: Response) {
|
|
try {
|
|
logger.debug('Before reading DB');
|
|
const eventId = req.query['event-id'];
|
|
const creator = req.query['is-creator'];
|
|
const timeBlockId = parseInt(req.query['id'] as string);
|
|
const date = req.query.date;
|
|
const title = req.body.title;
|
|
const startTime = req.body.editStartTime;
|
|
const endTime = req.body.editEndTime;
|
|
const color = req.body.editColor;
|
|
|
|
const event = (
|
|
await client.query(
|
|
`
|
|
SELECT start_datetime, end_datetime, deleted FROM events
|
|
WHERE id = $1
|
|
`,
|
|
[eventId]
|
|
)
|
|
).rows[0];
|
|
|
|
const isDeleted = event.deleted;
|
|
const eventStartTimeInMin = event.start_datetime.getTime();
|
|
const eventEndTimeInMin = event.end_datetime.getTime();
|
|
const now = new Date().getTime();
|
|
|
|
let isProcessing = true;
|
|
|
|
if (eventStartTimeInMin < now && eventEndTimeInMin < now) {
|
|
isProcessing = false;
|
|
//event is finished
|
|
}
|
|
if (isDeleted) {
|
|
isProcessing = false;
|
|
//event was deleted by creator
|
|
}
|
|
|
|
if (creator === '1' && isProcessing) {
|
|
//check time collision with existing time-blocks
|
|
//bug: correct end time = 00:00 problem
|
|
|
|
const existingActivities = (
|
|
await client.query(
|
|
`
|
|
SELECT start_time, end_time, id FROM time_blocks
|
|
WHERE event_id = $1
|
|
AND date = $2
|
|
AND id != $3
|
|
ORDER BY start_time ASC;
|
|
`,
|
|
[eventId, date, timeBlockId]
|
|
)
|
|
).rows;
|
|
|
|
let reject = false;
|
|
|
|
const newStartTimeInMin = toMin(req.body.editStartTime);
|
|
const newEndTimeInMin = toMin(req.body.editEndTime);
|
|
|
|
existingActivities.forEach((activity) => {
|
|
const startTimeInMin = toMin(activity.start_time);
|
|
const endTimeInMin = toMin(activity.end_time);
|
|
|
|
if (newStartTimeInMin > startTimeInMin && newStartTimeInMin < endTimeInMin) {
|
|
reject = true;
|
|
console.log('1');
|
|
}
|
|
if (newEndTimeInMin > startTimeInMin && newEndTimeInMin < endTimeInMin) {
|
|
reject = true;
|
|
console.log('2');
|
|
}
|
|
if (newStartTimeInMin <= startTimeInMin && newEndTimeInMin >= endTimeInMin) {
|
|
reject = true;
|
|
console.log('3');
|
|
}
|
|
});
|
|
|
|
//writing update to DB
|
|
if (reject) {
|
|
res.status(400).json({
|
|
msg: '[EER002]: Activity Start Time or End Time Overlapped with Existing Activity'
|
|
});
|
|
} else {
|
|
await client.query(
|
|
`
|
|
UPDATE time_blocks
|
|
SET title = $1,
|
|
start_time = $2,
|
|
end_time = $3,
|
|
color = $4,
|
|
updated_at = $5
|
|
WHERE event_id = $6
|
|
AND id = $7
|
|
AND date = $8
|
|
`,
|
|
[title, startTime, endTime, color, 'now()', eventId, timeBlockId, date]
|
|
);
|
|
|
|
res.json({
|
|
status: true,
|
|
msg: 'Edit success'
|
|
});
|
|
}
|
|
} else {
|
|
res.json({
|
|
status: false,
|
|
msg: '[EER001]: Unauthorized Request'
|
|
});
|
|
}
|
|
} catch (e) {
|
|
logger.error(e);
|
|
res.status(500).json({
|
|
msg: '[TBE002]: Failed to Edit Time & Name'
|
|
});
|
|
}
|
|
}
|
|
|
|
async function editRemark(req: Request, res: Response) {
|
|
try {
|
|
logger.debug('Before reading DB');
|
|
const eventId = req.query['event-id'];
|
|
const creator = req.query['is-creator'];
|
|
const timeBlockId = req.query['id'];
|
|
const date = req.query.date;
|
|
const remark = req.body.remark;
|
|
|
|
const event = (
|
|
await client.query(
|
|
`
|
|
SELECT start_datetime, end_datetime, deleted FROM events
|
|
WHERE id = $1
|
|
`,
|
|
[eventId]
|
|
)
|
|
).rows[0];
|
|
|
|
const isDeleted = event.deleted;
|
|
const eventStartTimeInMin = event.start_datetime.getTime();
|
|
const eventEndTimeInMin = event.end_datetime.getTime();
|
|
const now = new Date().getTime();
|
|
|
|
let isProcessing = true;
|
|
|
|
if (eventStartTimeInMin < now && eventEndTimeInMin < now) {
|
|
isProcessing = false;
|
|
//event is finished
|
|
}
|
|
if (isDeleted) {
|
|
isProcessing = false;
|
|
//event was deleted by creator
|
|
}
|
|
|
|
if (creator === '1' && isProcessing) {
|
|
await client.query(
|
|
`
|
|
UPDATE time_blocks
|
|
SET remark = $1,
|
|
updated_at = $2
|
|
WHERE event_id = $3
|
|
AND id = $4
|
|
AND date = $5
|
|
`,
|
|
[remark, 'now()', eventId, timeBlockId, date]
|
|
);
|
|
res.json({
|
|
status: true,
|
|
msg: 'Edit success'
|
|
});
|
|
} else {
|
|
res.json({
|
|
status: false,
|
|
msg: '[EER001]: Unauthorized Request'
|
|
});
|
|
}
|
|
} catch (e) {
|
|
logger.error(e);
|
|
res.status(500).json({
|
|
msg: '[TBE001]: Failed to Edit Remark'
|
|
});
|
|
}
|
|
}
|
|
|
|
async function editDescription(req: Request, res: Response) {
|
|
try {
|
|
logger.debug('Before reading DB');
|
|
const eventId = req.query['event-id'];
|
|
const creator = req.query['is-creator'];
|
|
const timeBlockId = req.query['id'];
|
|
const date = req.query.date;
|
|
const description = req.body.description;
|
|
|
|
const event = (
|
|
await client.query(
|
|
`
|
|
SELECT start_datetime, end_datetime, deleted FROM events
|
|
WHERE id = $1
|
|
`,
|
|
[eventId]
|
|
)
|
|
).rows[0];
|
|
|
|
const isDeleted = event.deleted;
|
|
const eventStartTimeInMin = event.start_datetime.getTime();
|
|
const eventEndTimeInMin = event.end_datetime.getTime();
|
|
const now = new Date().getTime();
|
|
|
|
let isProcessing = true;
|
|
|
|
if (eventStartTimeInMin < now && eventEndTimeInMin < now) {
|
|
isProcessing = false;
|
|
//event is finished
|
|
}
|
|
if (isDeleted) {
|
|
isProcessing = false;
|
|
//event was deleted by creator
|
|
}
|
|
|
|
if (creator === '1' && isProcessing) {
|
|
await client.query(
|
|
`
|
|
UPDATE time_blocks
|
|
SET description = $1,
|
|
updated_at = $2
|
|
WHERE event_id = $3
|
|
AND id = $4
|
|
AND date = $5
|
|
`,
|
|
[description, 'now()', eventId, timeBlockId, date]
|
|
);
|
|
res.json({
|
|
status: true,
|
|
msg: 'Edit success'
|
|
});
|
|
} else {
|
|
res.json({
|
|
status: false,
|
|
msg: '[EER001]: Unauthorized Request'
|
|
});
|
|
}
|
|
} catch (e) {
|
|
logger.error(e);
|
|
res.status(500).json({
|
|
msg: '[TBE003]: Failed to Edit Description'
|
|
});
|
|
}
|
|
}
|
|
|
|
async function deleteTimeBlock(req: Request, res: Response) {
|
|
try {
|
|
logger.debug('Before reading DB');
|
|
const eventId = req.query['event-id'];
|
|
const creator = req.query['is-creator'];
|
|
const timeBlockId = req.query['id'];
|
|
const date = req.query.date;
|
|
|
|
const event = (
|
|
await client.query(
|
|
`
|
|
SELECT start_datetime, end_datetime, deleted FROM events
|
|
WHERE id = $1
|
|
`,
|
|
[eventId]
|
|
)
|
|
).rows[0];
|
|
|
|
const isDeleted = event.deleted;
|
|
const eventStartTimeInMin = event.start_datetime.getTime();
|
|
const eventEndTimeInMin = event.end_datetime.getTime();
|
|
const now = new Date().getTime();
|
|
|
|
let isProcessing = true;
|
|
|
|
if (eventStartTimeInMin < now && eventEndTimeInMin < now) {
|
|
isProcessing = false;
|
|
//event is finished
|
|
}
|
|
if (isDeleted) {
|
|
isProcessing = false;
|
|
//event was deleted by creator
|
|
}
|
|
|
|
if (creator === '1' && isProcessing) {
|
|
await client.query(
|
|
`
|
|
DELETE FROM time_block_item
|
|
WHERE time_block_id = $1
|
|
`,
|
|
|
|
[timeBlockId]
|
|
);
|
|
|
|
await client.query(
|
|
`
|
|
DELETE FROM time_blocks
|
|
WHERE id = $1
|
|
AND event_id = $2
|
|
AND date = $3
|
|
`,
|
|
|
|
[timeBlockId, eventId, date]
|
|
);
|
|
res.json({
|
|
status: true,
|
|
msg: 'Delete success'
|
|
});
|
|
} else {
|
|
res.status(400).json({
|
|
status: false,
|
|
msg: '[EER001]: Unauthorized Request'
|
|
});
|
|
}
|
|
} catch (e) {
|
|
logger.error(e);
|
|
res.status(500).json({
|
|
msg: '[TBD001]: Failed to Delete Time Block'
|
|
});
|
|
}
|
|
}
|
|
|
|
async function getEventSchedule(req: Request, res: Response) {
|
|
try {
|
|
logger.debug('Before reading DB');
|
|
const eventId = req.query['event-id'];
|
|
const creator = req.query['is-creator'];
|
|
let date = req.query.date;
|
|
|
|
let event;
|
|
if (creator === '1') {
|
|
event = (
|
|
await client.query(
|
|
`
|
|
SELECT * FROM events
|
|
WHERE events.id = $1
|
|
AND events.creator_id = $2
|
|
|
|
`,
|
|
[eventId, req.session.user]
|
|
)
|
|
).rows[0];
|
|
} else {
|
|
event = (
|
|
await client.query(
|
|
`
|
|
SELECT * FROM events
|
|
INNER JOIN participants ON participants.event_id = events.id
|
|
WHERE events.id = $1
|
|
AND participants.user_id = $2;
|
|
`,
|
|
[eventId, req.session.user]
|
|
)
|
|
).rows[0];
|
|
}
|
|
|
|
if (event.start_datetime) {
|
|
if (date === 'null' || 'undefined') {
|
|
const option = {
|
|
hour12: false,
|
|
year: 'numeric',
|
|
month: '2-digit',
|
|
day: '2-digit'
|
|
};
|
|
let placeholder = event.start_datetime.toLocaleString('en-GB', option).split('/');
|
|
date = `${placeholder[2]}${placeholder[1]}${placeholder[0]}`;
|
|
}
|
|
|
|
const activitiesArr = (
|
|
await client.query(
|
|
`
|
|
SELECT * FROM time_blocks
|
|
WHERE event_id = $1
|
|
AND date = $2
|
|
|
|
`,
|
|
[eventId, date]
|
|
)
|
|
).rows;
|
|
|
|
const itemList = (
|
|
await client.query(
|
|
`
|
|
SELECT * FROM items
|
|
WHERE items.event_id = $1
|
|
`,
|
|
[eventId]
|
|
)
|
|
).rows;
|
|
|
|
const savedItemList = (
|
|
await client.query(
|
|
`
|
|
SELECT * FROM items
|
|
JOIN time_block_item ON items.id = time_block_item.item_id
|
|
JOIN time_blocks ON time_block_item.time_block_id = time_blocks.id
|
|
WHERE time_blocks.event_id = $1
|
|
AND time_blocks.date = $2
|
|
`,
|
|
[eventId, date]
|
|
)
|
|
).rows;
|
|
|
|
res.json({
|
|
status: true,
|
|
detail: event,
|
|
activities: activitiesArr,
|
|
items: itemList,
|
|
savedItems: savedItemList
|
|
});
|
|
} else {
|
|
res.json({ status: false });
|
|
}
|
|
} catch (e) {
|
|
logger.error(e);
|
|
res.status(500).json({
|
|
msg: '[ETS001]: Failed to get Event Schedule'
|
|
});
|
|
}
|
|
}
|
|
|
|
function toMin(timeInput: String) {
|
|
const hourInMin = parseInt(timeInput.slice(0, 2)) * 60;
|
|
const min = parseInt(timeInput.slice(3, 5));
|
|
return hourInMin + min;
|
|
}
|
|
|
|
async function postEventSchedule(req: Request, res: Response) {
|
|
try {
|
|
logger.debug('Before reading DB');
|
|
const eventId = req.query['event-id'];
|
|
const creator = req.query['is-creator'];
|
|
const date = req.query.date;
|
|
|
|
const event = (
|
|
await client.query(
|
|
`
|
|
SELECT start_datetime, end_datetime, deleted FROM events
|
|
WHERE id = $1
|
|
`,
|
|
[eventId]
|
|
)
|
|
).rows[0];
|
|
|
|
const isDeleted = event.deleted;
|
|
const eventStartTimeInMin = event.start_datetime.getTime();
|
|
const eventEndTimeInMin = event.end_datetime.getTime();
|
|
const now = new Date().getTime();
|
|
|
|
let isProcessing = true;
|
|
|
|
if (eventStartTimeInMin < now && eventEndTimeInMin < now) {
|
|
isProcessing = false;
|
|
//event is finished
|
|
}
|
|
if (isDeleted) {
|
|
isProcessing = false;
|
|
//event was deleted by creator
|
|
}
|
|
|
|
if (creator === '1' && isProcessing) {
|
|
//check if start time and end time collided with existing activities
|
|
|
|
const existingActivities = (
|
|
await client.query(
|
|
`
|
|
SELECT start_time, end_time FROM time_blocks
|
|
WHERE event_id = $1
|
|
AND date = $2
|
|
ORDER BY start_time ASC;
|
|
`,
|
|
[eventId, date]
|
|
)
|
|
).rows;
|
|
|
|
let reject = false;
|
|
|
|
existingActivities.forEach((activity) => {
|
|
const startTimeInMin = toMin(activity.start_time);
|
|
const endTimeInMin = toMin(activity.end_time);
|
|
|
|
const newStartTimeInMin = toMin(req.body.startTime);
|
|
const newEndTimeInMin = toMin(req.body.endTime);
|
|
|
|
if (newStartTimeInMin > startTimeInMin && newStartTimeInMin < endTimeInMin) {
|
|
reject = true;
|
|
} else if (newEndTimeInMin > startTimeInMin && newEndTimeInMin < endTimeInMin) {
|
|
reject = true;
|
|
}
|
|
});
|
|
|
|
//writing request to DB
|
|
if (reject) {
|
|
res.status(400).json({
|
|
msg: '[EER002]: Activity Start Time or End Time Overlapped with Existing Activity'
|
|
});
|
|
} else {
|
|
await client.query(
|
|
`
|
|
INSERT INTO time_blocks
|
|
(title, description, event_id, user_id, start_time,
|
|
end_time, remark, date, color, created_at, updated_at)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)`,
|
|
[
|
|
req.body.title,
|
|
req.body.description,
|
|
eventId,
|
|
req.session.user,
|
|
req.body.startTime,
|
|
req.body.endTime,
|
|
req.body.remark,
|
|
date,
|
|
req.body.color,
|
|
'now()',
|
|
'now()'
|
|
]
|
|
);
|
|
|
|
res.json({
|
|
status: true,
|
|
msg: 'save success'
|
|
});
|
|
}
|
|
} else {
|
|
res.status(400).json({
|
|
msg: '[EER001]: Unauthorized Request'
|
|
});
|
|
}
|
|
} catch (e) {
|
|
logger.error(e);
|
|
res.status(500).json({
|
|
msg: '[ETS002]: Failed to Post Event Schedule'
|
|
});
|
|
}
|
|
}
|