Skip to content

Commit

Permalink
Task 9 - Backend (#6)
Browse files Browse the repository at this point in the history
* changes

* createRequest function

tried to make createRequest function

* post route

* deletechapter function

---------

Co-authored-by: michaelfenggg <mfenggg06@gmail.com>
Co-authored-by: kygchng <66804026+kygchng@users.noreply.github.com>
  • Loading branch information
3 people authored Nov 10, 2024
1 parent a06f466 commit 932b115
Show file tree
Hide file tree
Showing 7 changed files with 566 additions and 3 deletions.
329 changes: 329 additions & 0 deletions server/src/controllers/birthdayRequest.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,329 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable consistent-return */
/* eslint-disable import/prefer-default-export */
import express from 'express';
import ApiError from '../util/apiError.ts';
import StatusCode from '../util/statusCode.ts';
import {
getAllRequestsByID,
updateRequestStatusByID,
getRequestById,
deleteRequestByID,
createBirthdayRequestByID,
} from '../services/birthdayRequest.service.ts';
import { getChapterById } from '../services/chapter.service.ts';
import {
emailRequestUpdate,
emailRequestDelete,
} from '../services/mail.service.ts';
import { IBirthdayRequest } from '../models/birthdayRequest.model.ts';
import { IChapter } from '../models/chapter.model.ts';

const getAllRequests = async (
req: express.Request,
res: express.Response,
next: express.NextFunction,
) => {
const { id } = req.params;
if (!id) {
next(ApiError.missingFields(['id']));
return;
}
return (
getAllRequestsByID(id)
.then((requestsList) => {
res.status(StatusCode.OK).send(requestsList);
})
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.catch((e) => {
next(ApiError.internal('Unable to retrieve all requests'));
})
);
};

const updateRequestStatus = async (
req: express.Request,
res: express.Response,
next: express.NextFunction,
) => {
// request id
const { id } = req.params;
if (!id) {
next(ApiError.missingFields(['id']));
return;
}
const { updatedValue } = req.body;
if (!updatedValue) {
next(ApiError.missingFields(['updatedValue']));
return;
}
if (updatedValue !== 'Approved' && updatedValue !== 'Delivered') {
next(ApiError.internal('Invalid input'));
return;
}
// get the chapter and partner agency emails
// get request object by it's id
const request: IBirthdayRequest | null = await getRequestById(id);
if (!request) {
next(ApiError.notFound(`Request with id ${id} does not exist`));
return;
}
// get chapter email by chapter ID
const chapter: IChapter | null = await getChapterById(request.chapterId);
if (!chapter) {
next(ApiError.notFound(`Chapter does not exist`));
return;
}
// get partner agency email and chapter email in the request object
const agencyEmail = request.agencyWorkerEmail;
const chapterEmail = chapter.email;

return (
updateRequestStatusByID(id, updatedValue)
.then(() => {
emailRequestUpdate(agencyEmail, updatedValue, request.childName)
.then(() => {
emailRequestUpdate(chapterEmail, updatedValue, request.childName)
.then(() =>
res.status(StatusCode.CREATED).send({
message: `Email has been sent to all parties.`,
}),
)
.catch(() => {
next(ApiError.internal('Failed to send chapter email.'));
});
})
.catch(() => {
next(ApiError.internal('Failed to send agency update email.'));
});
})
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.catch((e) => {
next(ApiError.internal('Unable to retrieve all requests'));
})
);
};

const deleteRequest = async (
req: express.Request,
res: express.Response,
next: express.NextFunction,
) => {
// request id
const { id } = req.params;
if (!id) {
next(ApiError.missingFields(['id']));
return;
}
// get the chapter and partner agency emails
// get request object by it's id
const request: IBirthdayRequest | null = await getRequestById(id);
if (!request) {
next(ApiError.notFound(`Request with id ${id} does not exist`));
return;
}
// get chapter email by chapter ID
const chapter: IChapter | null = await getChapterById(request.chapterId);
if (!chapter) {
next(ApiError.notFound(`Chapter does not exist`));
return;
}
// get partner agency email and chapter email in the request object
const agencyEmail = request.agencyWorkerEmail;
const chapterEmail = chapter.email;

return (
deleteRequestByID(id)
.then(() => {
emailRequestDelete(agencyEmail, request.childName)
.then(() => {
emailRequestDelete(chapterEmail, request.childName)
.then(() =>
res.status(StatusCode.CREATED).send({
message: `Email has been sent to all parties.`,
}),
)
.catch(() => {
next(ApiError.internal('Failed to send chapter email.'));
});
})
.catch(() => {
next(ApiError.internal('Failed to send agency update email.'));
});
})
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.catch((e) => {
next(ApiError.internal('Unable to delete request.'));
})
);
};

const createRequest = async (
req: express.Request,
res: express.Response,
next: express.NextFunction,
) => {
const {
chapterId,
deadlineDate,
childBirthday,
childAge,
childName,
childGender,
childRace,
childInterests,
childAllergies,
allergyDetails,
giftSuggestions,
additionalInfo,
agencyWorkerName,
agencyOrganization,
agencyWorkerPhone,
agencyWorkerEmail,
isFirstReferral,
agreeFeedback,
requestedDate,
status,
deliveryDate,
} = req.body;
if (!chapterId || typeof chapterId === 'string') {
next(ApiError.notFound(`chapterId does not exist or is invalid`));
return;
}
if (!deadlineDate || !(deadlineDate instanceof Date)) {
next(ApiError.notFound(`deadlineDate does not exist or is invalid`));
return;
}
if (!childBirthday || !(childBirthday instanceof Date)) {
next(ApiError.notFound(`childBirthday does not exist or is invalid`));
return;
}
if (!childAge || typeof childAge !== 'number') {
next(ApiError.notFound(`childAge does not exist or is invalid`));
return;
}
if (!childName || typeof childName === 'string') {
next(ApiError.notFound(`childName does not exist or is invalid`));
return;
}
if (!childGender || typeof childGender === 'string') {
next(ApiError.notFound(`childGender does not exist or is invalid`));
return;
}
if (childGender !== 'Boy' && childGender !== 'Girl') {
next(ApiError.notFound(`childGender is invalid`));
return;
}
if (!childRace || typeof childRace === 'string') {
next(ApiError.notFound(`childRace does not exist or is invalid`));
return;
}
if (
childRace !== 'White' &&
childRace !== 'Black or African American' &&
childRace !== 'Hispanic or Latino' &&
childRace !== 'Native American or American Indian' &&
childRace !== 'Asian / Pacific Islander' &&
childRace !== 'Not Sure'
) {
next(ApiError.notFound(`childRace is invalid`));
return;
}
if (!childInterests || typeof childInterests === 'string') {
next(ApiError.notFound(`childInterests does not exist or is invalid`));
return;
}
if (childAllergies !== true && childAllergies !== false) {
next(ApiError.notFound(`childAllergies does not exist or is invalid`));
return;
}
if (!allergyDetails || typeof allergyDetails === 'string') {
next(ApiError.notFound(`allergyDetails does not exist or is invalid`));
return;
}
if (!giftSuggestions || typeof giftSuggestions === 'string') {
next(ApiError.notFound(`giftSuggestions does not exist or is invalid`));
return;
}
if (!additionalInfo || typeof additionalInfo === 'string') {
next(ApiError.notFound(`additionalInfo does not exist or is invalid`));
return;
}
if (!agencyWorkerName || typeof agencyWorkerName === 'string') {
next(ApiError.notFound(`agencyWorkerName does not exist or is invalid`));
return;
}
if (!agencyOrganization || typeof agencyOrganization === 'string') {
next(ApiError.notFound(`agencyOrganization does not exist or is invalid`));
return;
}
if (!agencyWorkerPhone || typeof agencyWorkerPhone === 'string') {
next(ApiError.notFound(`agencyWorkerPhone does not exist or is invalid`));
return;
}
if (!agencyWorkerEmail || typeof agencyWorkerEmail === 'string') {
next(ApiError.notFound(`agencyWorkerEmail does not exist or is invalid`));
return;
}
const emailRegex =
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/g;
if (!agencyWorkerEmail.match(emailRegex)) {
next(ApiError.badRequest('Invalid email'));
return;
}

if (isFirstReferral !== true && isFirstReferral !== false) {
next(ApiError.notFound(`isFirstReferral does not exist or is invalid`));
return;
}
if (agreeFeedback !== true && agreeFeedback !== false) {
next(ApiError.notFound(`agreeFeedback does not exist or is invalid`));
return;
}
if (!requestedDate || !(requestedDate instanceof Date)) {
next(ApiError.notFound(`requestedDate does not exist or is invalid`));
return;
}
if (!status || typeof status === 'string') {
next(ApiError.notFound(`status does not exist or is invalid`));
return;
}
if (status !== 'Pending' && status !== 'Approved' && status !== 'Delivered') {
next(ApiError.notFound(`status is invalid`));
return;
}
if (!deliveryDate || !(deliveryDate instanceof Date)) {
next(ApiError.notFound(`deliveryDate does not exist or is invalid`));
return;
}
try {
const user = await createBirthdayRequestByID(
chapterId,
deadlineDate,
childBirthday,
childAge,
childName,
childGender,
childRace,
childInterests,
childAllergies,
allergyDetails,
giftSuggestions,
additionalInfo,
agencyWorkerName,
agencyOrganization,
agencyWorkerPhone,
agencyWorkerEmail,
isFirstReferral,
agreeFeedback,
requestedDate,
status,
deliveryDate,
);
res.sendStatus(StatusCode.CREATED);
} catch (err) {
next(ApiError.internal('Unable to register user.'));
}
};

export { getAllRequests, updateRequestStatus, deleteRequest, createRequest };
31 changes: 30 additions & 1 deletion server/src/controllers/chapter.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import StatusCode from '../util/statusCode.ts';
import {
toggleRequestByID,
getAllChaptersFromDB,
getChapterById,
deleteChapterByID,
} from '../services/chapter.service.ts';
import { IChapter } from '../models/chapter.model.ts';

const getAllChapters = async (
req: express.Request,
Expand Down Expand Up @@ -45,4 +48,30 @@ const toggleRequest = async (
});
};

export { toggleRequest, getAllChapters };
const deleteChapter = async (
req: express.Request,
res: express.Response,
next: express.NextFunction,
) => {
// request id
const { id } = req.params;
if (!id) {
next(ApiError.missingFields(['id']));
return;
}
// get chapter email by chapter ID
const chapter: IChapter | null = await getChapterById(id);
if (!chapter) {
next(ApiError.notFound(`Chapter does not exist`));
return;
}
deleteChapterByID(id);
try {
res.sendStatus(StatusCode.CREATED);
}
catch (err) {
next(ApiError.internal('Unable to register user.'));
}
};

export { toggleRequest, getAllChapters, deleteChapter };
23 changes: 23 additions & 0 deletions server/src/routes/birthdayRequest.route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import express from 'express';
import { isAdmin } from '../controllers/admin.middleware.ts';
import {
getAllRequests,
updateRequestStatus,
deleteRequest,
createRequest,
} from '../controllers/birthdayRequest.controller.ts';
import { isAuthenticated } from '../controllers/auth.middleware.ts';
import 'dotenv/config';

const router = express.Router();

router.get('/all/:id', isAuthenticated, isAdmin, getAllRequests);

router.put('/updatestatus/:id', isAuthenticated, isAdmin, updateRequestStatus);

router.delete('/deleterequest/:id', isAuthenticated, isAdmin, deleteRequest);

router.post('/createrequest', createRequest);
// isAuthenticated, isAdmin,
export default router;
Loading

0 comments on commit 932b115

Please sign in to comment.