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/kevinsophia/newsletter #29

Merged
merged 14 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -12,6 +12,7 @@ import backgroundImageRoutes from "src/routes/background_images";
import eventDetailsRoutes from "./routes/eventDetails";
import volunteerDetailsRoutes from "./routes/volunteerDetails";
import testimonialRoutes from "src/routes/testimonial";
import newsletterRoutes from "src/routes/newsletter"; // Import newsletter routes
import emailRoutes from "src/routes/emails";

const app = express();
Expand All @@ -38,7 +39,9 @@ app.use("/api/BackgroundImage", backgroundImageRoutes);
app.use("/api/eventDetails", eventDetailsRoutes);
app.use("/api/volunteerDetails", volunteerDetailsRoutes);
app.use("/api/testimonial", testimonialRoutes);
app.use("/api/newsletter", newsletterRoutes); // Use newsletter routes
app.use("/api/emails", emailRoutes);

/**
* Error handler; all errors thrown by server are handled here.
* Explicit typings required here because TypeScript cannot infer the argument types.
Expand Down
85 changes: 85 additions & 0 deletions backend/src/controllers/newsletter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { RequestHandler } from "express";
import { validationResult } from "express-validator";
import createHttpError from "http-errors";
import Newsletter from "src/models/newsletter";
import validationErrorParser from "src/util/validationErrorParser";

export const getAllNewsletters: RequestHandler = async (req, res, next) => {
try {
const newsletters = await Newsletter.find({});

if (!newsletters) {
res.status(200).json({ message: "No newsletters found." });
}

res.status(200).json(newsletters);
} catch (error) {
next(error);
}
};

export const getNewsletter: RequestHandler = async (req, res, next) => {
const { id } = req.params;

try {
const newsletter = await Newsletter.findById(id);

if (!newsletter) {
throw createHttpError(404, "Newsletter not found.");
}

res.status(200).json(newsletter);
} catch (error) {
next(error);
}
};

export const createNewsletter: RequestHandler = async (req, res, next) => {
const errors = validationResult(req);
const { _id, image, title, description, date, content } = req.body;

try {
validationErrorParser(errors);

const newsletter = await Newsletter.create({
_id,
image,
title,
description,
date,
content,
});

res.status(201).json(newsletter);
} catch (error) {
next(error);
}
};

export const updateNewsletter: RequestHandler = async (req, res, next) => {
const errors = validationResult(req);
const { id } = req.params;

if (id !== req.body._id) {
// If the _id in the URL does not match the _id in the body, bad request
res.status(400);
}

try {
validationErrorParser(errors);

const newsletter = await Newsletter.findByIdAndUpdate(id, req.body);
if (newsletter === null) {
// No newsletter found
res.status(404);
}
const updatedNewsletter = await Newsletter.findById(id);
if (updatedNewsletter === null) {
// No newsletter found, something went wrong
res.status(404);
}
res.status(200).json(updatedNewsletter);
} catch (error) {
next(error);
}
};
4 changes: 4 additions & 0 deletions backend/src/controllers/subscriber.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ export const createSubscriber: RequestHandler = async (req, res, next) => {
validationErrorParser(errors);
const subscriber = await Subscriber.create({
email: email,
firstName: req.body.firstName,
lastName: req.body.lastName,
quarterlyUpdates: req.body.quarterlyUpdates,
specialUpdates: req.body.specialUpdates,
});

/*
Expand Down
4 changes: 2 additions & 2 deletions backend/src/controllers/testimonial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import TestimonialModel from "src/models/testimonial";

export const createTestimonial: RequestHandler = async (req, res, next) => {
const { title, description, image, type } = req.body;
console.log("here");

try {
const testimonial = await TestimonialModel.create({
title: title,
description: description,
image: image,
type: type,
});
console.log("here");

res.status(201).json(testimonial);
} catch (error) {
next(error);
Expand Down
14 changes: 14 additions & 0 deletions backend/src/models/newsletter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { InferSchemaType, Schema, model } from "mongoose";

const newsletterSchema = new Schema({
image: { type: String, required: true },
title: { type: String, required: true },
description: { type: String, required: true },
date: { type: String, required: true },
content: { type: [String], required: true },
archive: { type: Boolean, required: true },
});

type Newsletters = InferSchemaType<typeof newsletterSchema>;

export default model<Newsletters>("Newsletters", newsletterSchema);
4 changes: 4 additions & 0 deletions backend/src/models/subscriber.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import { InferSchemaType, Schema, model } from "mongoose";

const subscriberSchema = new Schema({
email: { type: String, required: true },
firstName: { type: String },
lastName: { type: String },
quarterlyUpdates: { type: Boolean },
specialUpdates: { type: Boolean },
});

type Subscriber = InferSchemaType<typeof subscriberSchema>;
Expand Down
16 changes: 16 additions & 0 deletions backend/src/routes/newsletter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import express from "express";
import * as NewsletterController from "src/controllers/newsletter";
import * as NewsletterValidator from "src/validators/newsletter";

const router = express.Router();

router.get("/", NewsletterController.getAllNewsletters);
router.get("/:id", NewsletterValidator.getNewsletter, NewsletterController.getNewsletter);
router.put(
"/:id", // getNewsletter validator works to just check ID
NewsletterValidator.getNewsletter,
NewsletterController.updateNewsletter,
);
router.post("/", NewsletterValidator.createNewsletter, NewsletterController.createNewsletter);

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

const makeIDValidator = () =>
body("_id")
.exists()
.withMessage("_id is required")
.bail()
.isString()
.withMessage("_id must be a number");
const makeImageValidator = () =>
body("image")
.exists()
.withMessage("image is required")
.bail()
.isString()
.withMessage("image must be a string");
const makeTitleValidator = () =>
body("title")
.exists()
.withMessage("title is required")
.bail()
.isString()
.withMessage("title must be a string");
const makeDescriptionValidator = () =>
body("description")
.exists()
.withMessage("description is required")
.bail()
.isString()
.withMessage("description must be a string");
const makeDateValidator = () =>
body("date")
.exists()
.withMessage("date is required")
.bail()
.isString()
.withMessage("date must be a string");
const makeContentValidator = () =>
body("content")
.exists()
.withMessage("content is required")
.bail()
.isArray()
.withMessage("content must be an array of strings");

export const createNewsletter = [
makeIDValidator(),
makeImageValidator(),
makeTitleValidator(),
makeDescriptionValidator(),
makeDateValidator(),
makeContentValidator(),
];

export const getNewsletter = [makeIDValidator()];
20 changes: 19 additions & 1 deletion backend/src/validators/subscriber.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,22 @@ const makeEmailValidator = () =>
}
});

export const createSubscriber = [makeEmailValidator()];
const makeFirstNameValidator = () =>
body("firstName").optional().isString().withMessage("firstName must be a string");

const makeLastNameValidator = () =>
body("lastName").optional().isString().withMessage("lastName must be a string");

const makeQuarterlyUpdatesValidator = () =>
body("quarterlyUpdates").optional().isBoolean().withMessage("quarterlyUpdates must be a boolean");

const makeSpecialUpdatesValidator = () =>
body("specialUpdates").optional().isBoolean().withMessage("specialUpdates must be a boolean");

export const createSubscriber = [
makeEmailValidator(),
makeFirstNameValidator(),
makeLastNameValidator(),
makeQuarterlyUpdatesValidator(),
makeSpecialUpdatesValidator(),
];
Loading
Loading