diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml
new file mode 100644
index 0000000..47d1803
--- /dev/null
+++ b/.github/workflows/develop.yml
@@ -0,0 +1,73 @@
+name: Deploy to Railway
+
+on:
+ push:
+ branches:
+ - develop
+ paths-ignore:
+ - 'README.md'
+
+env:
+ AZURE_WEBAPP_NAME: bookify
+ NODE_VERSION: '20.x'
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout Source
+ uses: actions/checkout@v3
+
+ - name: Setup Node.js version
+ uses: actions/setup-node@v4
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+ cache: 'npm'
+
+ - name: Create .env file
+ run: |
+ echo "SQLITE_DB=${{ secrets.SQLITE_DB }}" >> .env
+ echo "TYPEORM_CLI=${{ secrets.TYPEORM_CLI }}" >> .env
+ echo "APP_PORT=${{ secrets.APP_PORT }}" >> .env
+ echo "NODE_ENV=${{ secrets.NODE_ENV }}" >> .env
+ echo "OAUTH_CLIENT_SECRET=${{ secrets.OAUTH_CLIENT_SECRET }}" >> .env
+ echo "OAUTH_CLIENT_ID=${{ secrets.OAUTH_CLIENT_ID }}" >> .env
+ echo "OAUTH_REDIRECT_URL=${{ secrets.OAUTH_REDIRECT_URL }}" >> .env
+ echo "JWT_SECRET=${{ secrets.JWT_SECRET }}" >> .env
+ echo "${{ secrets.ROOMS }}" > ./src/config/rooms.ts
+
+ - name: Install Dependencies
+ run: npm install
+
+ - name: Run database migrations
+ run: npm run migration:run
+
+ - name: Build project
+ run: npm run build
+
+ - name: Upload artifact for deployment job
+ uses: actions/upload-artifact@v4
+ with:
+ name: node-app
+ path: .
+
+ deploy:
+ runs-on: ubuntu-latest
+ needs: build
+ environment:
+ name: 'production'
+ url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}
+
+ steps:
+ - name: Download artifact from build job
+ uses: actions/download-artifact@v4
+ with:
+ name: node-app
+
+ - name: Install Railway
+ run: npm i -g @railway/cli
+
+ - name: Deploy
+ run: railway up --service bookify
+ env:
+ RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 5bb83d4..b1d9d63 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -37,13 +37,14 @@ jobs:
echo "${{ secrets.ROOMS }}" > ./src/config/rooms.ts
- name: Install Dependencies
- run: |
- npm install
- npm run build --if-present
+ run: npm install
- name: Run database migrations
run: npm run migration:run
+ - name: Build project
+ run: npm run build
+
- name: Upload artifact for deployment job
uses: actions/upload-artifact@v4
with:
diff --git a/client/script.js b/client/script.js
index 3209204..b6931d3 100644
--- a/client/script.js
+++ b/client/script.js
@@ -4,7 +4,7 @@ let floor = 1;
const CLIENT_ID = '1043931677993-j15eelb1golb8544ehi2meeru35q3fo4.apps.googleusercontent.com';
const REDIRECT_URI = window.location.origin;
-const BACKEND_ENDPOINT = 'http://localhost:3000';
+const BACKEND_ENDPOINT = REDIRECT_URI;
async function openPage(pageName, elmnt) {
var i, tabcontent, tablinks;
@@ -119,12 +119,17 @@ async function bookRoom() {
const startTimeSelect = document.getElementById('startTime');
const startTime = startTimeSelect.value;
+ const date = new Date(Date.now()).toISOString().split('T')[0];
+ const formattedStartTime = convertToRFC3339(date, startTime);
+
+ console.log('formattedStartTime', formattedStartTime);
+
const duration = document.getElementById('duration').textContent;
const seats = document.getElementById('seat_text').textContent;
const floor = document.getElementById('floor_text').textContent;
const res = await makeRequest('/room', 'POST', {
- startTime,
+ startTime: formattedStartTime,
duration: parseInt(duration),
seats: parseInt(seats),
floor: parseInt(floor),
@@ -135,7 +140,7 @@ async function bookRoom() {
return;
}
- createRoomAlert(res.room, res.start, res.end, res.summary, 'info');
+ createRoomAlert(res.room, convertToLocaleTime(res.start), convertToLocaleTime(res.end), res.summary, 'info');
}
async function makeRequest(path, method, body) {
@@ -340,7 +345,7 @@ const populateEvents = async () => {
- ${event.start} - ${event.end}
+ ${convertToLocaleTime(event.start)} - ${convertToLocaleTime(event.end)}
@@ -381,3 +386,30 @@ async function removeEvent(id) {
eventElement.remove();
}
}
+
+function convertToRFC3339(dateString, timeString, timeZoneOffset = '+06:00') {
+ const date = new Date(`${dateString} ${timeString}`);
+
+ const [offsetSign, offsetHours, offsetMinutes] = timeZoneOffset.match(/([+-])(\d{2}):(\d{2})/).slice(1);
+
+ const offsetInMinutes = (parseInt(offsetHours) * 60 + parseInt(offsetMinutes)) * (offsetSign === '+' ? 1 : -1);
+ date.setMinutes(date.getMinutes() + offsetInMinutes);
+
+ const isoString = date.toISOString();
+ const [isoDate, isoTime] = isoString.split('T');
+
+ // Return the formatted date and time in RFC 3339 format
+ return `${isoDate}T${isoTime.split('.')[0]}${timeZoneOffset}`;
+}
+
+function convertToLocaleTime(dateStr) {
+ const date = new Date(dateStr);
+
+ const options = {
+ hour: '2-digit',
+ minute: '2-digit',
+ hour12: true,
+ };
+
+ return date.toLocaleTimeString('en-US', options);
+}
diff --git a/src/calender/calender.controller.ts b/src/calender/calender.controller.ts
index 7d4c953..661bcca 100644
--- a/src/calender/calender.controller.ts
+++ b/src/calender/calender.controller.ts
@@ -4,7 +4,6 @@ import { CalenderService } from './calender.service';
import { AuthGuard } from '../auth/auth.guard';
import { _OAuth2Client } from '../auth/decorators';
import { EventResponse, RoomResponse } from './dto';
-import { convertToRFC3339 } from './util/calender.util';
import { DeleteResponse } from './dto/delete.response';
@Controller()
@@ -29,16 +28,12 @@ export class CalenderController {
@Body('floor') floor?: number,
@Body('attendees') attendees?: string[],
): Promise {
- // start time
- const date = new Date(Date.now()).toISOString().split('T')[0];
- const formattedStartTime = convertToRFC3339(date, startTime);
-
// end time
- const startDate = new Date(formattedStartTime);
+ const startDate = new Date(startTime);
startDate.setMinutes(startDate.getMinutes() + durationInMins);
const endTime = startDate.toISOString();
- const event = await this.calenderService.createEvent(client, formattedStartTime, endTime, seats, createConference, title, floor, attendees);
+ const event = await this.calenderService.createEvent(client, startTime, endTime, seats, createConference, title, floor, attendees);
return event;
}
diff --git a/src/calender/calender.service.ts b/src/calender/calender.service.ts
index 9bf10e3..47d81ab 100644
--- a/src/calender/calender.service.ts
+++ b/src/calender/calender.service.ts
@@ -1,10 +1,10 @@
import { OAuth2Client } from 'google-auth-library';
import { ConflictException, ForbiddenException, Inject, Injectable, InternalServerErrorException, NotImplementedException } from '@nestjs/common';
import { ConfigType } from '@nestjs/config';
-import { calendar_v3, google } from 'googleapis';
+import { google } from 'googleapis';
import appConfig from '../config/env/app.config';
import { EventResponse, RoomResponse } from './dto';
-import { convertToLocaleTime, isRoomAvailable, parseLocation } from './util/calender.util';
+import { isRoomAvailable, parseLocation } from './util/calender.util';
import { Room } from './interfaces/room.interface';
import { AuthService } from '../auth/auth.service';
import { rooms } from '../config/rooms';
@@ -27,6 +27,11 @@ export class CalenderService {
floor?: number,
attendees?: string[],
): Promise {
+ console.log('current server date', new Date().toISOString());
+
+ console.log('startTime', startTime);
+ console.log('endTime', endTime);
+
const room = await this.getAvailableRoom(client, startTime, endTime, seats, floor);
if (!room) {
@@ -90,8 +95,8 @@ export class CalenderService {
return {
summary: result.data.summary,
meet: result.data.hangoutLink,
- start: convertToLocaleTime(result.data.start.dateTime),
- end: convertToLocaleTime(result.data.end.dateTime),
+ start: result.data.start.dateTime,
+ end: result.data.end.dateTime,
room: formattedRoom,
};
}
@@ -101,7 +106,7 @@ export class CalenderService {
const calendar = google.calendar({ version: 'v3', auth: client });
const filteredRoomIds = [];
for (const room of rooms) {
- if (room.seats >= minSeats && (!floor || room.floor === floor)) {
+ if (room.seats >= minSeats && room.floor === floor) {
filteredRoomIds.push(room.id);
}
}
@@ -111,9 +116,9 @@ export class CalenderService {
timeMin: start,
timeMax: end,
timeZone: 'Asia/Dhaka',
- items: rooms.map((room) => {
+ items: filteredRoomIds.map((id) => {
return {
- id: room.id,
+ id
};
}),
},
@@ -156,8 +161,8 @@ export class CalenderService {
room: parseLocation(event.location),
id: event.id,
title: event.summary,
- start: convertToLocaleTime(event.start.dateTime),
- end: convertToLocaleTime(event.end.dateTime),
+ start: event.start.dateTime,
+ end: event.end.dateTime,
} as RoomResponse;
});
diff --git a/src/calender/util/calender.util.ts b/src/calender/util/calender.util.ts
index 474593a..2fe1993 100644
--- a/src/calender/util/calender.util.ts
+++ b/src/calender/util/calender.util.ts
@@ -21,37 +21,3 @@ export function parseLocation(location: string) {
const parsedLocation = location.split(',');
return parsedLocation.length > 0 ? parsedLocation[0] : undefined;
}
-
-/**
- *
- * @param dateString in the format '2024-08-31'
- * @param timeString in the format '11:30 AM'
- * @param timeZoneOffset
- * @returns
- */
-export function convertToRFC3339(dateString: string, timeString: string, timeZoneOffset = '+06:00') {
- const date = new Date(`${dateString} ${timeString}`);
-
- const [offsetSign, offsetHours, offsetMinutes] = timeZoneOffset.match(/([+-])(\d{2}):(\d{2})/).slice(1);
-
- const offsetInMinutes = (parseInt(offsetHours) * 60 + parseInt(offsetMinutes)) * (offsetSign === '+' ? 1 : -1);
- date.setMinutes(date.getMinutes() + offsetInMinutes);
-
- const isoString = date.toISOString();
- const [isoDate, isoTime] = isoString.split('T');
-
- // Return the formatted date and time in RFC 3339 format
- return `${isoDate}T${isoTime.split('.')[0]}${timeZoneOffset}`;
-}
-
-export function convertToLocaleTime(dateStr: string) {
- const date = new Date(dateStr);
-
- const options: Intl.DateTimeFormatOptions = {
- hour: '2-digit',
- minute: '2-digit',
- hour12: true,
- };
-
- return date.toLocaleTimeString('en-US', options);
-}