Skip to content

Commit

Permalink
Merge VSR form page 1 branch
Browse files Browse the repository at this point in the history
  • Loading branch information
benjaminJohnson2204 committed Feb 23, 2024
2 parents 81e86af + 01f7db2 commit af07992
Show file tree
Hide file tree
Showing 27 changed files with 932 additions and 449 deletions.
9 changes: 4 additions & 5 deletions backend/src/controllers/vsr.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { RequestHandler } from "express";
//import createHttpError from "http-errors";
import { validationResult } from "express-validator";
import createHttpError from "http-errors";
import VSRModel from "src/models/vsr";
Expand All @@ -25,7 +24,6 @@ export const createVSR: RequestHandler = async (req, res, next) => {
const errors = validationResult(req);
const {
name,
date,
gender,
age,
maritalStatus,
Expand All @@ -38,12 +36,13 @@ export const createVSR: RequestHandler = async (req, res, next) => {
sizeOfHome,
} = req.body;

console.log(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,
Expand All @@ -60,7 +59,7 @@ export const createVSR: RequestHandler = async (req, res, next) => {
});

// 201 means a new resource has been created successfully
// the newly created task is sent back to the user
// the newly created VSR is sent back to the user
res.status(201).json(vsr);
} catch (error) {
next(error);
Expand Down
2 changes: 1 addition & 1 deletion backend/src/models/vsr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const vsrSchema = new Schema({
numOfGirls: { type: Number, required: true },
agesOfBoys: { type: [Number] },
agesOfGirls: { type: [Number] },
ethnicity: { type: String, require: true },
ethnicity: { type: [String], require: true },
employmentStatus: { type: String, require: true },
incomeLevel: { type: String, require: true },
sizeOfHome: { type: String, require: true },
Expand Down
7 changes: 0 additions & 7 deletions backend/src/routes/vsr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,6 @@ import * as VSRValidator from "src/validators/vsr";

const router = express.Router();

/**
* TaskValidator.createTask serves as middleware for this route. This means
* that instead of immediately serving up the route when the request is made,
* Express firsts passes the request to TaskValidator.createTask.
* TaskValidator.createTask processes the request and determines whether the
* request should be sent through or an error should be thrown.
*/
router.get("/:id", VSRController.getVSR);
router.post("/", VSRValidator.createVSR, VSRController.createVSR);

Expand Down
48 changes: 16 additions & 32 deletions backend/src/validators/vsr.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,12 @@
import { body } from "express-validator";

// name: {type: String, required: true },
// date: {type: Date, required: true},
// gender: {type: String, require: true},
// age: {type: Number, require: true},
// martialStatus: {type: String, required: true },
// spouseName: {type: String},
// numOfBoys: {type: Number},
// numOfGirls: {type: Number},
// 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}

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

const makeDateValidator = () =>
body("date")
.exists({ checkFalsy: true })
.withMessage("Date is required")
.isISO8601()
.withMessage("Date must be in ISO 8601 format");

const makeGenderValidator = () =>
body("gender")
.exists({ checkFalsy: true })
Expand Down Expand Up @@ -56,14 +34,17 @@ const makeSpouseNameValidator = () =>
.isString()
.withMessage("Spouse Name must be a string");

const makeNumOfBoysValidator = () =>
body("numOfBoys")
.optional({ checkFalsy: true })
.isInt({ min: 0 })
.withMessage("Number of Boys must be a positive integer");
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")
.optional({ checkFalsy: true })
.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))
Expand All @@ -73,8 +54,12 @@ const makeEthnicityValidator = () =>
body("ethnicity")
.exists({ checkFalsy: true })
.withMessage("Ethnicity is required")
.isString()
.withMessage("Ethnicity must be a string");
.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")
Expand All @@ -99,12 +84,11 @@ const makeSizeOfHomeValidator = () =>

export const createVSR = [
makeNameValidator(),
makeDateValidator(),
makeGenderValidator(),
makeAgeValidator(),
makeMaritalStatusValidator(),
makeSpouseNameValidator(),
makeNumOfBoysValidator(),
makeAgesOfBoysValidator(),
makeAgesOfGirlsValidator(),
makeEthnicityValidator(),
makeEmploymentStatusValidator(),
Expand Down
107 changes: 3 additions & 104 deletions frontend/__tests__/exampleTest.test.ts
Original file line number Diff line number Diff line change
@@ -1,108 +1,7 @@
import "@testing-library/jest-dom";

import {
isnum,
validateAge,
validateEthnicityOther,
validateSpouseName,
} from "../src/util/validateResponses";

describe("Frontend Validator Tests", () => {
describe("IsNum", () => {
it("Correctly classifies '0' as a number", () => {
expect(isnum("0")).toEqual(true);
});

it("Correctly classifies various numbers as numbers", () => {
expect(isnum("1")).toEqual(true);
expect(isnum("2")).toEqual(true);
expect(isnum("3")).toEqual(true);
expect(isnum("23948")).toEqual(true);
expect(isnum("56")).toEqual(true);
});

it("Correctly classifies various non-numbers as non-numbers", () => {
expect(isnum("")).toEqual(false);
expect(isnum(" ")).toEqual(false);
expect(isnum("abc")).toEqual(false);
expect(isnum("a")).toEqual(false);
expect(isnum("32 049")).toEqual(false);
expect(isnum("32,049")).toEqual(false);
expect(isnum("32.049")).toEqual(false);
expect(isnum("32-049")).toEqual(false);
expect(isnum("32/049")).toEqual(false);
expect(isnum("-5")).toEqual(false);
});
});

describe("ValidateAge", () => {
it("Correctly classifies valid ages", () => {
expect(validateAge("0")).toEqual("Success");
expect(validateAge("1")).toEqual("Success");
expect(validateAge("2")).toEqual("Success");
expect(validateAge("50")).toEqual("Success");
});

it("Correctly classifies invalid ages", () => {
expect(validateAge("")).toEqual("Age is not a number");
expect(validateAge("five years old")).toEqual("Age is not a number");
expect(validateAge("abc")).toEqual("Age is not a number");
expect(validateAge("a")).toEqual("Age is not a number");
expect(validateAge("-5")).toEqual("Age is not a number");
});
});

describe("ValidateSpouseName", () => {
it("Correctly classifies married and has spouse name", () => {
expect(validateSpouseName("Married", "Bob")).toEqual("Success");
expect(validateSpouseName("Married", "Bob Smith")).toEqual("Success");
expect(validateSpouseName("Married", "Bob Smith Jr.")).toEqual("Success");
});

it("Correctly classifies married and has no spouse name", () => {
expect(validateSpouseName("Married", "")).toEqual("Spouse name is required");
});

it("Correctly classifies single and has spouse name", () => {
expect(validateSpouseName("Single", "Bob")).toEqual("Spouse name is not required");
expect(validateSpouseName("Single", "Bob Smith")).toEqual("Spouse name is not required");
expect(validateSpouseName("Single", "Bob Smith Jr.")).toEqual("Spouse name is not required");
});

it("Correctly classifies single and has no spouse name", () => {
expect(validateSpouseName("Single", "")).toEqual("Success");
});

it("Correctly classifies is complicated", () => {
expect(validateSpouseName("It's Complicated", "")).toEqual("Success");
expect(validateSpouseName("It's Complicated", "Bob")).toEqual("Success");
expect(validateSpouseName("It's Complicated", "Bob Smith")).toEqual("Success");
});
});

describe("ValidateEthnicityOther", () => {
it("Correctly classifies no ethnicity and no other", () => {
expect(validateEthnicityOther("", "")).toEqual("Please fill out the other field");
});

it("Correctly classifies no ethnicity and other", () => {
expect(validateEthnicityOther("", "Other")).toEqual("Success");
expect(validateEthnicityOther("", "Polynesian")).toEqual("Success");
});

it("Correctly classifies has ethnicity and has other", () => {
expect(validateEthnicityOther("Asian", "Other")).toEqual(
"Please leave the other field empty",
);
expect(validateEthnicityOther("Asian", "Polynesian")).toEqual(
"Please leave the other field empty",
);
});

it("Correctly classifies ethnicity, no other", () => {
expect(validateEthnicityOther("Asian", "")).toEqual("Success");
expect(validateEthnicityOther("Hispanic", "")).toEqual("Success");
expect(validateEthnicityOther("Not Given", "")).toEqual("Success");
});
describe("ExampleTests", () => {
it("Passes example test", () => {
expect(1 + 1).toEqual(2);
});
});
1 change: 0 additions & 1 deletion frontend/public/next.svg

This file was deleted.

1 change: 0 additions & 1 deletion frontend/public/vercel.svg

This file was deleted.

33 changes: 9 additions & 24 deletions frontend/src/api/VSRs.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,5 @@
import { APIResult, handleAPIError, post, get } from "@/api/requests";

/*
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 },*/
export interface VSRJson {
_id: string;
name: string;
Expand All @@ -22,9 +8,9 @@ export interface VSRJson {
age: number;
maritalStatus: string;
spouseName?: string;
agesOfBoys?: number[];
agesOfGirls?: number[];
ethnicity: string;
agesOfBoys: number[];
agesOfGirls: number[];
ethnicity: string[];
employmentStatus: string;
incomeLevel: string;
sizeOfHome: string;
Expand Down Expand Up @@ -62,9 +48,9 @@ export interface VSR {
age: number;
maritalStatus: string;
spouseName?: string;
agesOfBoys?: number[];
agesOfGirls?: number[];
ethnicity: string;
agesOfBoys: number[];
agesOfGirls: number[];
ethnicity: string[];
employmentStatus: string;
incomeLevel: string;
sizeOfHome: string;
Expand Down Expand Up @@ -96,14 +82,13 @@ export interface VSR {

export interface CreateVSRRequest {
name: string;
date: string;
gender: string;
age: number;
maritalStatus: string;
spouseName?: string;
agesOfBoys?: number[];
agesOfGirls?: number[];
ethnicity: string;
agesOfBoys: number[];
agesOfGirls: number[];
ethnicity: string[];
employmentStatus: string;
incomeLevel: string;
sizeOfHome: string;
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/api/requests.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const API_BASE_URL = process.env.NEXT_PUBLIC_BACKEND_URL;
import env from "@/util/validateEnv";

const API_BASE_URL = env.NEXT_PUBLIC_BACKEND_URL;
type Method = "GET" | "POST" | "PUT";

/**
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/app/dummyPage/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export const metadata = {
title: "Next.js",
description: "Generated by Next.js",
title: "Patriots & Paws",
description: "Web application for Patriots & Paws",
};

export default function DummyLayout({ children }: { children: React.ReactNode }) {
Expand Down
Binary file modified frontend/src/app/favicon.ico
Binary file not shown.
4 changes: 2 additions & 2 deletions frontend/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import "@/app/globals.css";
const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
title: "Patriots & Paws",
description: "Web application for Patriots & Paws",
};

export default function RootLayout({ children }: { children: React.ReactNode }) {
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/app/login/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export const metadata = {
title: "Next.js",
description: "Generated by Next.js",
title: "Patriots & Paws",
description: "Web application for Patriots & Paws",
};

export default function LoginLayout({ children }: { children: React.ReactNode }) {
Expand Down
Loading

0 comments on commit af07992

Please sign in to comment.