Skip to content

Commit 440a650

Browse files
author
Joshua Zhou
committed
Create checkin form submit endpoint
1 parent 7e776fe commit 440a650

4 files changed

Lines changed: 172 additions & 0 deletions

File tree

controllers/checkin.controller.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"use strict";
2+
3+
const Services = {
4+
Sheets: require('../services/sheets.service')
5+
};
6+
7+
/**
8+
* @function submitCheckin
9+
* @param {{body: {formData: Object}}} req
10+
* @param {*} res
11+
* @return {JSON} Success status
12+
* @description Handles the check-in form submission and adds data to Google Sheets
13+
*/
14+
async function submitCheckin(req, res) {
15+
try {
16+
await Services.Sheets.appendCheckinData(req.body.formData);
17+
return res.status(200).json({
18+
message: "Check-in data successfully submitted",
19+
data: {}
20+
});
21+
} catch (error) {
22+
return res.status(500).json({
23+
message: "Error submitting check-in data",
24+
data: {}
25+
});
26+
}
27+
}
28+
29+
module.exports = {
30+
submitCheckin
31+
};
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"use strict";
2+
3+
const { body } = require('express-validator');
4+
5+
/**
6+
* Validator for check-in form submission
7+
*/
8+
const checkinValidator = [
9+
body('formData.teamMember1').notEmpty().withMessage('Team member 1 is required'),
10+
body('formData.teamMember2').optional(),
11+
body('formData.teamMember3').optional(),
12+
body('formData.teamMember4').optional(),
13+
body('formData.prizeCategories').isArray().withMessage('Prize categories must be an array'),
14+
body('formData.sponsorChallenges').isArray().withMessage('Sponsor challenges must be an array'),
15+
body('formData.workshopsAttended').isArray().withMessage('Workshops attended must be an array')
16+
];
17+
18+
module.exports = checkinValidator;

routes/api/checkin.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
"use strict";
2+
3+
const express = require("express");
4+
const router = express.Router();
5+
const Controllers = {
6+
Checkin: require("../../controllers/checkin.controller")
7+
};
8+
const Middleware = {
9+
Auth: require("../../middlewares/auth.middleware"),
10+
Validators: {
11+
checkinValidator: require("../../middlewares/validators/checkin.validator")
12+
}
13+
};
14+
15+
/**
16+
* @api {post} /api/hacker/checkin Submit check-in form data
17+
* @apiName SubmitCheckin
18+
* @apiGroup Checkin
19+
* @apiVersion 1.0.0
20+
*
21+
* @apiParam {Object} formData The check-in form data
22+
* @apiParam {String} formData.teamMember1 First team member's name
23+
* @apiParam {String} [formData.teamMember2] Second team member's name
24+
* @apiParam {String} [formData.teamMember3] Third team member's name
25+
* @apiParam {String} [formData.teamMember4] Fourth team member's name
26+
* @apiParam {String[]} formData.prizeCategories Array of prize categories
27+
* @apiParam {String[]} formData.sponsorChallenges Array of sponsor challenges
28+
* @apiParam {String[]} formData.workshopsAttended Array of workshops attended
29+
*
30+
* @apiSuccess {String} message Success message
31+
*
32+
* @apiError {String} message Error message
33+
*/
34+
router.post(
35+
"/checkin",
36+
Middleware.Auth.ensureAuthenticated(),
37+
Middleware.Validators.checkinValidator,
38+
Controllers.Checkin.submitCheckin
39+
);
40+
41+
function activate(apiRouter) {
42+
apiRouter.use("/hacker", router);
43+
}
44+
45+
module.exports = {
46+
activate: activate
47+
};

services/sheets.service.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
"use strict";
2+
3+
const { google } = require('googleapis');
4+
const Logger = require('./logger.service');
5+
6+
class SheetsService {
7+
constructor() {
8+
this.spreadsheetId = process.env.SPREADSHEET_ID;
9+
if (!this.spreadsheetId) {
10+
Logger.error('SPREADSHEET_ID is not set in environment variables');
11+
throw new Error('SPREADSHEET_ID is not set in environment variables');
12+
}
13+
14+
// Initialize Google Sheets API
15+
this.sheets = google.sheets('v4');
16+
17+
// Set up authentication using service account credentials
18+
this.auth = new google.auth.GoogleAuth({
19+
credentials: {
20+
type: process.env.TYPE,
21+
project_id: process.env.PROJECT_ID,
22+
private_key_id: process.env.PRIVATE_KEY_ID,
23+
private_key: process.env.PRIVATE_KEY.replace(/\\n/g, '\n'),
24+
client_email: process.env.CLIENT_EMAIL,
25+
client_id: process.env.CLIENT_ID,
26+
auth_uri: process.env.AUTH_URI,
27+
token_uri: process.env.TOKEN_URI,
28+
auth_provider_x509_cert_url: process.env.AUTH_PROVIDER_X509_CERT_URL,
29+
client_x509_cert_url: process.env.CLIENT_X509_CERT_URL
30+
},
31+
scopes: ['https://www.googleapis.com/auth/spreadsheets']
32+
});
33+
}
34+
35+
/**
36+
* Append check-in data to the spreadsheet
37+
* @param {Object} formData The check-in form data
38+
* @returns {Promise<void>}
39+
*/
40+
async appendCheckinData(formData) {
41+
try {
42+
const authClient = await this.auth.getClient();
43+
44+
// Format the data for the spreadsheet
45+
const values = [[
46+
new Date().toISOString(),
47+
formData.teamMember1,
48+
formData.teamMember2,
49+
formData.teamMember3,
50+
formData.teamMember4,
51+
formData.prizeCategories.join(', '),
52+
formData.sponsorChallenges.join(', '),
53+
formData.workshopsAttended.join(', ')
54+
]];
55+
56+
const request = {
57+
spreadsheetId: this.spreadsheetId,
58+
range: 'Sheet1!A:H', // Adjust range as needed
59+
valueInputOption: 'USER_ENTERED',
60+
insertDataOption: 'INSERT_ROWS',
61+
resource: {
62+
values: values
63+
},
64+
auth: authClient
65+
};
66+
67+
await this.sheets.spreadsheets.values.append(request);
68+
Logger.info('Successfully appended check-in data to spreadsheet');
69+
} catch (error) {
70+
Logger.error('Error appending data to spreadsheet:', error);
71+
throw error;
72+
}
73+
}
74+
}
75+
76+
module.exports = new SheetsService();

0 commit comments

Comments
 (0)