Skip to content

Commit 4224d74

Browse files
authored
Merge pull request #160 from Code-Hammers/CHE-84/subtask/Create-Tests-And-Error-Handling-For-userController-authUser
Che 84/subtask/create tests and error handling for user controller auth user
2 parents a59881d + 8217643 commit 4224d74

File tree

56 files changed

+1312
-1031
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1312
-1031
lines changed

.github/workflows/build-tests.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ jobs:
1212
uses: actions/setup-node@v2
1313
with:
1414
node-version: '20.14.0'
15+
- name: Set up Docker Buildx
16+
uses: docker/setup-buildx-action@v2
17+
- name: Install Docker Compose
18+
run: sudo apt-get update && sudo apt-get install -y docker-compose
1519
- name: Build Docker Image
1620
run: docker build -t codehammers/ch-dev-dep-v3:latest -f Dockerfile-dev .
1721
- name: Install Root Dependencies

server/controllers/alumniControllers.ts renamed to server/controllers/alumniController/getAllAlumniData/getAllAumniData.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
1-
import Alumni from '../models/alumniModel';
1+
import Alumni from '../../../models/alumniModel';
22
import { Request, Response } from 'express';
3-
import { IAlumni } from '../types/alumni';
3+
import { IAlumni } from '../../../types/alumni';
44

55
interface SearchQuery {
66
name?: { $regex: string; $options: string };
77
company?: { $regex: string; $options: string };
88
}
99

10+
// ENDPOINT GET api/users/login
11+
// PURPOSE Retrieve all alumni data
12+
// ACCESS Private
1013
const getAllAlumniData = async (req: Request, res: Response) => {
1114
const page = parseInt(req.query.page as string) || 1;
1215
const limit = parseInt(req.query.limit as string) || 10;
@@ -38,4 +41,4 @@ const getAllAlumniData = async (req: Request, res: Response) => {
3841
}
3942
};
4043

41-
export { getAllAlumniData };
44+
export default getAllAlumniData;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import getAllAlumniData from './getAllAlumniData/getAllAumniData';
2+
3+
export { getAllAlumniData };
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { Request, Response } from 'express';
2+
import { pool } from '../../../config/sql-db';
3+
4+
const createApplication = async (req: Request, res: Response) => {
5+
try {
6+
const {
7+
title,
8+
company,
9+
location,
10+
description,
11+
url,
12+
status_id,
13+
quick_apply,
14+
date_applied,
15+
general_notes,
16+
user_id,
17+
} = req.body;
18+
19+
const appliedDate = new Date(date_applied).toISOString();
20+
21+
const jobQuery = `
22+
INSERT INTO jobs (title, company, location, description, url)
23+
VALUES ($1, $2, $3, $4, $5)
24+
RETURNING id
25+
`;
26+
const jobValues = [title, company, location, description, url];
27+
const jobResult = await pool.query(jobQuery, jobValues);
28+
const job_id = jobResult.rows[0].id;
29+
30+
const applicationQuery = `
31+
INSERT INTO applications (job_id, status_id, user_id, quick_apply, date_applied, general_notes, last_updated)
32+
VALUES ($1, $2, $3, $4, $5, $6, NOW())
33+
RETURNING id
34+
`;
35+
const applicationValues = [job_id, status_id, user_id, quick_apply, appliedDate, general_notes];
36+
const applicationResult = await pool.query(applicationQuery, applicationValues);
37+
38+
res.status(201).json({ id: applicationResult.rows[0].id });
39+
} catch (error) {
40+
console.error('Error creating application:', error);
41+
res.status(500).json({ message: 'Internal server error' });
42+
}
43+
};
44+
45+
export default createApplication;
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { Request, Response } from 'express';
2+
import { pool } from '../../../config/sql-db';
3+
4+
interface StatusCount {
5+
status: string;
6+
count: string;
7+
}
8+
9+
const getAggregatedUserStats = async (req: Request, res: Response) => {
10+
const { userId } = req.params;
11+
if (!req.user || req.user.id !== userId)
12+
return res.status(401).json({ message: 'You are not authorized to retrieve those records' });
13+
try {
14+
const applicationsByStatusQuery = `
15+
SELECT statuses.name AS status, COUNT(*) AS count
16+
FROM applications
17+
JOIN statuses ON applications.status_id = statuses.id
18+
WHERE applications.user_id = $1
19+
GROUP BY statuses.name
20+
`;
21+
const applicationsByStatusResult = await pool.query<StatusCount>(applicationsByStatusQuery, [
22+
userId,
23+
]);
24+
25+
const totalApplications = applicationsByStatusResult.rows.reduce(
26+
(sum: number, row: StatusCount) => sum + parseInt(row.count, 10),
27+
0,
28+
);
29+
30+
res.json({
31+
totalApplications,
32+
applicationsByStatus: applicationsByStatusResult.rows,
33+
});
34+
} catch (error) {
35+
console.error('Error fetching aggregated data:', error);
36+
res.status(500).send('Internal server error');
37+
}
38+
};
39+
40+
export default getAggregatedUserStats;
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { Request, Response } from 'express';
2+
import { pool } from '../../../config/sql-db';
3+
4+
const getAllApplications = async (req: Request, res: Response) => {
5+
try {
6+
const { userId, status, date } = req.query;
7+
8+
let query = `
9+
SELECT
10+
applications.id,
11+
jobs.company,
12+
jobs.title,
13+
statuses.name AS status,
14+
applications.general_notes,
15+
applications.date_applied,
16+
applications.last_updated,
17+
applications.notification_period,
18+
applications.notifications_paused
19+
FROM
20+
applications
21+
INNER JOIN jobs ON applications.job_id = jobs.id
22+
INNER JOIN statuses ON applications.status_id = statuses.id
23+
WHERE
24+
applications.user_id = $1
25+
`;
26+
27+
const queryParams = [userId];
28+
let paramIndex = 2;
29+
30+
if (status) {
31+
query += ` AND statuses.name != $${paramIndex}`;
32+
queryParams.push(status);
33+
paramIndex += 1;
34+
}
35+
36+
if (date) {
37+
query += ` AND applications.date_applied >= $${paramIndex}`;
38+
queryParams.push(date);
39+
}
40+
41+
const { rows } = await pool.query(query, queryParams);
42+
43+
res.json(rows);
44+
} catch (error) {
45+
console.error('Error fetching job applications:', error);
46+
res.status(500).json({ message: 'Internal server error' });
47+
}
48+
};
49+
50+
export default getAllApplications;
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { Request, Response } from 'express';
2+
import { pool } from '../../../config/sql-db';
3+
4+
const getApplicationById = async (req: Request, res: Response) => {
5+
const { id } = req.params;
6+
try {
7+
const query = `
8+
SELECT
9+
applications.id,
10+
jobs.title,
11+
jobs.company,
12+
jobs.location,
13+
jobs.description,
14+
jobs.url,
15+
statuses.id AS status_id,
16+
statuses.name AS status,
17+
applications.quick_apply,
18+
applications.date_applied,
19+
applications.general_notes,
20+
applications.job_id,
21+
applications.user_id
22+
FROM
23+
applications
24+
INNER JOIN jobs ON applications.job_id = jobs.id
25+
INNER JOIN statuses ON applications.status_id = statuses.id
26+
WHERE
27+
applications.id = $1
28+
`;
29+
const { rows } = await pool.query(query, [id]);
30+
31+
if (rows.length === 0) {
32+
return res.status(404).json({ message: 'Application not found' });
33+
}
34+
35+
if (!req.user || req.user.id !== rows[0].user_id)
36+
return res.status(401).json({ message: 'You are not authorized to retrieve those records' });
37+
38+
res.json(rows[0]);
39+
} catch (error) {
40+
console.error('Error fetching application by id:', error);
41+
res.status(500).json({ message: 'Internal server error' });
42+
}
43+
};
44+
45+
export default getApplicationById;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { Request, Response } from 'express';
2+
import { pool } from '../../../config/sql-db';
3+
4+
const getStatuses = async (req: Request, res: Response) => {
5+
try {
6+
const { rows } = await pool.query('SELECT * FROM statuses');
7+
res.json(rows);
8+
} catch (error) {
9+
console.error('Error fetching statuses:', error);
10+
res.status(500).json({ message: 'Internal server error' });
11+
}
12+
};
13+
14+
export default getStatuses;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import createApplication from './createApplication/createApplication';
2+
import getAggregatedUserStats from './getAggregateUserStats/getAggregateUserStats';
3+
import getAllApplications from './getAllApplications/getAllApplications';
4+
import getApplicationById from './getApplicationById/getApplicationById';
5+
import getStatuses from './getStatuses/getStatuses';
6+
import pauseNotifications from './pauseNotifications/pauseNotifications';
7+
import updateApplication from './updateApplication/updateApplication';
8+
import updateNotificationPeriod from './updateNotificationPeriod/updateNotificationPeriod';
9+
10+
export {
11+
createApplication,
12+
getAggregatedUserStats,
13+
getAllApplications,
14+
getApplicationById,
15+
getStatuses,
16+
pauseNotifications,
17+
updateNotificationPeriod,
18+
updateApplication,
19+
};
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { Request, Response } from 'express';
2+
import { pool } from '../../../config/sql-db';
3+
4+
const pauseNotifications = async (req: Request, res: Response) => {
5+
try {
6+
const { id } = req.params;
7+
const { pause } = req.body;
8+
9+
const query = `
10+
UPDATE applications
11+
SET notifications_paused = $1
12+
WHERE id = $2
13+
`;
14+
await pool.query(query, [pause, id]);
15+
res.status(200).json({ message: `Notifications ${pause ? 'paused' : 'resumed'} successfully` });
16+
} catch (error) {
17+
console.error('Error pausing/resuming notifications:', error);
18+
res.status(500).json({ message: 'Internal server error' });
19+
}
20+
};
21+
22+
export default pauseNotifications;

0 commit comments

Comments
 (0)