Skip to content

Commit

Permalink
Merge branch 'main' into feature/vs2961/login_backend
Browse files Browse the repository at this point in the history
  • Loading branch information
vs2961 committed Feb 19, 2024
2 parents 088fccb + e2edeb7 commit 0a6f176
Show file tree
Hide file tree
Showing 13 changed files with 214 additions and 106 deletions.
1 change: 0 additions & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
* @adhi0331
* @parth4apple
94 changes: 4 additions & 90 deletions backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions backend/src/controllers/program.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* eslint-disable @typescript-eslint/no-misused-promises */
import { RequestHandler } from "express";
import { validationResult } from "express-validator";

import ProgramFormModel from "../models/program-form";
import validationErrorParser from "../util/validationErrorParser";

export type Program = {
name: string;
abbreviation: string;
type: string;
daysOfWeek: string[];
startDate: string;
endDate: string;
color: string; //colorValueHex;
};

export const createForm: RequestHandler = async (req, res, next) => {
const errors = validationResult(req);

try {
validationErrorParser(errors);

const programForm = await ProgramFormModel.create(req.body as Program);

res.status(201).json(programForm);
} catch (error) {
next(error);
}
};
2 changes: 1 addition & 1 deletion backend/src/errors/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { InternalError } from "./internal";
/**
* Generic Error Handler
*/
export const errorHandler = (err: Error, req: Request, res: Response, _next: NextFunction) => {
export const errorHandler = (err: Error, _req: Request, res: Response, _nxt: NextFunction) => {
if (!err) return;
if (err instanceof CustomError && !(err instanceof InternalError)) {
console.log(err.displayMessage(true));
Expand Down
17 changes: 17 additions & 0 deletions backend/src/models/program-form.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//modified from onboarding repo for program form backend

import { InferSchemaType, Schema, model } from "mongoose";

const programSchema = new Schema({
name: { type: String, required: true },
abbreviation: { type: String, required: true }, // e.g. ENTR
type: { type: String, required: true }, // regular vs. varying
daysOfWeek: { type: [String], required: true }, // M, T, W, TH, F
startDate: { type: Date, required: true },
endDate: { type: Date, required: true },
color: { type: String, required: true }, // options: 1 (teal, #4FA197), 2 (yellow, #FFB800), 3 (pink, #FF7A5E), 4 (olive, #B6BF0E)
});

type ProgramForm = InferSchemaType<typeof programSchema>;

export default model<ProgramForm>("ProgramForm", programSchema);
4 changes: 3 additions & 1 deletion backend/src/routes/api.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import express from "express";

import programRoutes from "./program";
import studentRoutes from "./student";
import { userRouter } from "./user";
import userRouter from "./user";

const router = express.Router();

// Register routers
router.use("/user", userRouter);
router.use("/student", studentRoutes);
router.use("/program", programRoutes);

export default router;
14 changes: 14 additions & 0 deletions backend/src/routes/program.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* Task route requests.
*/

import express from "express"; // { RequestHandler }

import * as ProgramController from "../controllers/program";
import * as ProgramValidator from "../validators/program";

const router = express.Router();

router.post("/", ProgramValidator.createForm, ProgramController.createForm);

export default router;
2 changes: 1 addition & 1 deletion backend/src/routes/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ router.use(express.json());
router.post("/login", UserValidator.loginUser, UserController.loginUser);

Check warning on line 10 in backend/src/routes/user.ts

View workflow job for this annotation

GitHub Actions / Backend lint and style check

Promise returned in function argument where a void return was expected
router.post("/", UserValidator.createUser, UserController.createUser);

Check warning on line 11 in backend/src/routes/user.ts

View workflow job for this annotation

GitHub Actions / Backend lint and style check

Promise returned in function argument where a void return was expected

export { router as userRouter };
export default router;
114 changes: 114 additions & 0 deletions backend/src/validators/program.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { body } from "express-validator";

import { Program } from "../controllers/program";

const makeNameValidator = () =>
body("name")
.exists()
.withMessage("name needed")
.bail()
.isString()
.withMessage("name must be a string")
.bail()
.notEmpty()
.withMessage("name must not be empty");
const makeAbbreviationValidator = () =>
body("abbreviation")
.exists()
.withMessage("abbreviation needed")
.bail()
.isString()
.withMessage("abbreviation must be a string")
.bail()
.notEmpty()
.withMessage("abbreviation must not be empty");
const makeTypeValidator = () =>
body("type")
.exists()
.withMessage("type needed")
.bail()
.isString()
.withMessage("type must be a string")
.bail()
.notEmpty()
.withMessage("type must not be empty")
.custom((value: string) => {
if (value !== "regular" && value !== "varying")
throw new Error("program type must be regular or varying");
return true;
});
const makeDaysOfWeekValidator = () =>
body("daysOfWeek")
.exists()
.withMessage("days of week selection needed")
.bail()
.isArray()
.withMessage("days of week selection must be an array")
.custom((value: string[]) => {
if (value.length === 0) throw new Error("days of week selection needed");
for (const valuei of value) {
if (valuei !== "M" && valuei !== "T" && valuei !== "W" && valuei !== "TH" && valuei !== "F")
throw new Error("days of week selection must be M, T, W, TH, or F");
}
return true;
});
const makeStartDateValidator = () =>
body("startDate")
.exists()
.withMessage("start date needed")
.bail()
.isISO8601()
.withMessage("start date must be a valid date-time string");
const makeEndDateValidator = () =>
body("endDate")
.exists()
.withMessage("end date needed")
.bail()
.isISO8601()
.withMessage("end date must be a valid date-time string")
.bail()
.custom((value: string, { req }) => {
const reqBody: Program = req.body as Program;
if (new Date(value) < new Date(reqBody.startDate))
throw new Error("end date must be after start date");
return true;
});
const makeColorValidator = () =>
body("color")
.exists()
.withMessage("color needed")
.bail()
.isString()
.withMessage("color hex should be string")
.isLength({ min: 7, max: 7 })
.withMessage("color hex should have 7 characters")
.bail()
.notEmpty()
.withMessage("color hex required")
.bail()
.custom((value: string) => {
if (value.length !== 7) throw new Error("color hex should have 7 characters");
if (!value.startsWith("#")) throw new Error("color hex should start with #");
for (let i = 1; i <= 6; i++) {
const code = value.charCodeAt(i);
if (
!(code > 47 && code < 58) && // numeric (0-9)
!(code > 64 && code < 91)
) {
// upper alpha (A-Z)
throw new Error("color hex must be a hex string, with characters 0-9 or A-F");
}
}
return true;
});
// check for first chara being # and others being 1-F

export const createForm = [
makeNameValidator(),
makeAbbreviationValidator(),
makeTypeValidator(),
makeDaysOfWeekValidator(),
makeStartDateValidator(),
makeEndDateValidator(),
makeColorValidator(),
];
15 changes: 10 additions & 5 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 0a6f176

Please sign in to comment.