Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/steven+yoto vsr personal info #24

Merged
merged 49 commits into from
Feb 25, 2024
Merged
Show file tree
Hide file tree
Changes from 44 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
2e91d71
lint fixes
2s2e Jan 19, 2024
2882ed1
Added route to POST and VSR controller
yotzkim Jan 19, 2024
bd86e86
Added validation functions for form responses
2s2e Jan 26, 2024
c5f9be6
Added validation functions for form responses
2s2e Jan 26, 2024
191d148
Removed numOfBoys, numOfGirls from schema, cleaned up backend, rename…
2s2e Jan 26, 2024
b962925
Added tests for validate spouse name
2s2e Jan 26, 2024
4bbf60c
Added tests for validate ethnicity
2s2e Jan 26, 2024
9c8791b
Basic text field, multiple choice, dropdown, and submit
yotzkim Jan 28, 2024
ae56430
Fix linting issues and minor edit to gender field validation
yotzkim Jan 28, 2024
713a852
Basic components
yotzkim Jan 28, 2024
aa064e2
app now uses post route
2s2e Jan 29, 2024
1cf38cf
Attempt at linking front end with back end, onbooarding code for fron…
2s2e Jan 30, 2024
ef8da1c
Reworked TextField component to do ref-forwarding, successfully pushe…
2s2e Jan 30, 2024
e84c5a0
Fixed couple bugs with date verification
2s2e Jan 31, 2024
9ea7802
Removed forwardRef
yotzkim Jan 31, 2024
bb4e877
Resolved merge conflicts between local and remote branches.
yotzkim Jan 31, 2024
9dc911b
Added title and description, required fields, and overall more styling
yotzkim Feb 5, 2024
3a36749
updated date to use current date, added more fields for the vsr page
2s2e Feb 6, 2024
5c4f986
Prototype of ethnicity selector
2s2e Feb 6, 2024
361c880
Made options unselectable
2s2e Feb 9, 2024
c7a9650
Working version of ethnicity form
2s2e Feb 9, 2024
d14e4bb
Prototype of appearing and disappearing children form
2s2e Feb 9, 2024
21f6579
Added more styling
yotzkim Feb 11, 2024
8a8a6f5
Added more styling
yotzkim Feb 12, 2024
102fe1f
Added backend functionality for ages, changed Child #n name to Child …
2s2e Feb 14, 2024
2375b64
Fixed small bug with ethnicity, added numBoys and spouse to createVSR…
yotzkim Feb 14, 2024
4c62275
Fixed small bug with ethnicity, added numBoys and spouse to createVSR…
yotzkim Feb 14, 2024
3de89d6
fixed issue with ethnicity selection
2s2e Feb 16, 2024
33df593
merge conflict resolve
2s2e Feb 16, 2024
3981b09
Changed textbox styling to flex 1
yotzkim Feb 16, 2024
4a2fee2
Styling
yotzkim Feb 16, 2024
31bc3f8
Fixed issue with null values in age array
2s2e Feb 16, 2024
bfade0b
Page number component
yotzkim Feb 16, 2024
4146ee3
Page Number component
yotzkim Feb 16, 2024
f9a7374
added girls form
2s2e Feb 16, 2024
ba472c9
Merge branch 'feature/steven+yoto-vsr-personal-info' of https://githu…
2s2e Feb 16, 2024
2d49188
changes with validation
yotzkim Feb 16, 2024
be0365a
changes with validation
yotzkim Feb 16, 2024
6fc45e9
Yet even more lint fixes
2s2e Feb 20, 2024
ee25030
prettier
2s2e Feb 20, 2024
5683ce4
Merge branch 'main' into feature/steven+yoto-vsr-personal-info
benjaminJohnson2204 Feb 21, 2024
40f0fa0
Fix CSS styles & clean up code
benjaminJohnson2204 Feb 23, 2024
ad04b6a
Update favicon, title, & description, remove unused boilerplate
benjaminJohnson2204 Feb 23, 2024
01f7db2
Remove commented-out code & make ethnicity an array
benjaminJohnson2204 Feb 23, 2024
7637592
Fix bugs with entering ages of children
benjaminJohnson2204 Feb 24, 2024
8cfaa05
Only require spouse's name for Married marital status
benjaminJohnson2204 Feb 24, 2024
f3c8d35
Fix age validation
benjaminJohnson2204 Feb 24, 2024
3c2a5aa
Fix bugs with VSR age & num children
benjaminJohnson2204 Feb 24, 2024
26ca311
Address Daniel's review comments
benjaminJohnson2204 Feb 25, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions backend/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "dotenv/config";
import cors from "cors";
import express, { NextFunction, Request, Response } from "express";
import { isHttpError } from "http-errors";
import vsrRoutes from "../src/routes/vsr";
import { userRouter } from "src/routes/users";
import env from "src/util/validateEnv";

Expand Down Expand Up @@ -52,4 +53,6 @@ app.use((error: unknown, req: Request, res: Response, next: NextFunction) => {
res.status(statusCode).json({ error: errorMessage });
});

app.use("/api/vsr", vsrRoutes);

export default app;
51 changes: 51 additions & 0 deletions backend/src/controllers/vsr.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { RequestHandler } from "express";
import { validationResult } from "express-validator";
import VSRModel from "src/models/vsr";
import validationErrorParser from "src/util/validationErrorParser";

export const createVSR: RequestHandler = async (req, res, next) => {
// extract any errors that were found by the validator
const errors = validationResult(req);
const {
name,
gender,
age,
maritalStatus,
spouseName,
agesOfBoys,
agesOfGirls,
ethnicity,
employmentStatus,
incomeLevel,
sizeOfHome,
} = req.body;

try {
// if there are errors, then this function throws an exception
validationErrorParser(errors);

// Get the current date as a timestamp for when VSR was submitted
const date = new Date();

const vsr = await VSRModel.create({
name,
date,
gender,
age,
maritalStatus,
spouseName,
agesOfBoys,
agesOfGirls,
ethnicity,
employmentStatus,
incomeLevel,
sizeOfHome,
});

// 201 means a new resource has been created successfully
// the newly created VSR is sent back to the user
res.status(201).json(vsr);
} catch (error) {
next(error);
}
};
20 changes: 20 additions & 0 deletions backend/src/models/vsr.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { InferSchemaType, Schema, model } from "mongoose";

const vsrSchema = new Schema({
name: { type: String, required: true },
date: { type: Date, required: true },
gender: { type: String, require: true },
age: { type: Number, require: true },
maritalStatus: { type: String, required: true },
spouseName: { type: String },
agesOfBoys: { type: [Number] },
agesOfGirls: { type: [Number] },
ethnicity: { type: [String], require: true },
employmentStatus: { type: String, require: true },
incomeLevel: { type: String, require: true },
sizeOfHome: { type: String, require: true },
});

type VSR = InferSchemaType<typeof vsrSchema>;

export default model<VSR>("VSR", vsrSchema);
9 changes: 9 additions & 0 deletions backend/src/routes/vsr.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import express from "express";
import * as VSRController from "src/controllers/vsr";
import * as VSRValidator from "src/validators/vsr";

const router = express.Router();

router.post("/", VSRValidator.createVSR, VSRController.createVSR);

export default router;
25 changes: 25 additions & 0 deletions backend/src/util/validationErrorParser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Result, ValidationError } from "express-validator";
import createHttpError from "http-errors";

/**
* Parses through errors thrown by validator (if any exist). Error messages are
* added to a string and that string is used as the error message for the HTTP
* error.
*
* @param errors the validation result provided by express validator middleware
*/
const validationErrorParser = (errors: Result<ValidationError>) => {
if (!errors.isEmpty()) {
let errorString = "";

// parse through errors returned by the validator and append them to the error string
for (const error of errors.array()) {
errorString += error.msg + " ";
}

// trim removes the trailing space created in the for loop
throw createHttpError(400, errorString.trim());
}
};

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

const makeNameValidator = () =>
body("name")
.exists({ checkFalsy: true })
.withMessage("Name is required")
.isString()
.withMessage("Name must be a string");

const makeGenderValidator = () =>
body("gender")
.exists({ checkFalsy: true })
.withMessage("Gender is required")
.isString()
.withMessage("Gender must be a string");

const makeAgeValidator = () =>
body("age")
.exists({ checkFalsy: true })
.withMessage("Age is required")
.isInt({ min: 0 })
.withMessage("Age must be a positive integer");

const makeMaritalStatusValidator = () =>
body("maritalStatus")
.exists({ checkFalsy: true })
.withMessage("Marital Status is required")
.isString()
.withMessage("Marital Status must be a string");

const makeSpouseNameValidator = () =>
body("spouseName")
.optional({ checkFalsy: true })
.isString()
.withMessage("Spouse Name must be a string");

const makeAgesOfBoysValidator = () =>
body("agesOfBoys")
.exists({ checkFalsy: true })
.isArray()
.withMessage("Ages of Boys must be an array of numbers")
.custom((ages: number[]) => ages.every((age) => Number.isInteger(age) && age >= 0))
.withMessage("Each age in Ages of Boys must be a positive integer");

const makeAgesOfGirlsValidator = () =>
body("agesOfGirls")
.exists({ checkFalsy: true })
.isArray()
.withMessage("Ages of Girls must be an array of numbers")
.custom((ages: number[]) => ages.every((age) => Number.isInteger(age) && age >= 0))
.withMessage("Each age in Ages of Girls must be a positive integer");

const makeEthnicityValidator = () =>
body("ethnicity")
.exists({ checkFalsy: true })
.withMessage("Ethnicity is required")
.isArray()
.withMessage("Ethnicity must be an array")
.custom((ethnicities: string[]) =>
ethnicities.every((ethnicity) => typeof ethnicity === "string"),
)
.withMessage("Each ethnicity in Ethnicities must be a positive integer");

const makeEmploymentStatusValidator = () =>
body("employmentStatus")
.exists({ checkFalsy: true })
.withMessage("Employment Status is required")
.isString()
.withMessage("Employment Status must be a string");

const makeIncomeLevelValidator = () =>
body("incomeLevel")
.exists({ checkFalsy: true })
.withMessage("Income Level is required")
.isString()
.withMessage("Income Level must be a string");

const makeSizeOfHomeValidator = () =>
body("sizeOfHome")
.exists({ checkFalsy: true })
.withMessage("Size of Home is required")
.isString()
.withMessage("Size of Home must be a string");

export const createVSR = [
makeNameValidator(),
makeGenderValidator(),
makeAgeValidator(),
makeMaritalStatusValidator(),
makeSpouseNameValidator(),
makeAgesOfBoysValidator(),
makeAgesOfGirlsValidator(),
makeEthnicityValidator(),
makeEmploymentStatusValidator(),
makeIncomeLevelValidator(),
makeSizeOfHomeValidator(),
];
Loading
Loading