From e3c9a3572604de42621fc019ceab3d327c8bb9eb Mon Sep 17 00:00:00 2001 From: Sean Date: Sun, 9 Jun 2024 07:59:23 -0400 Subject: [PATCH 1/9] CHE-192 Updated getAllApplications to handle optional filter parameters for status and date --- server/controllers/applicationsController.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/server/controllers/applicationsController.ts b/server/controllers/applicationsController.ts index 0d1dd73..2a00f6d 100644 --- a/server/controllers/applicationsController.ts +++ b/server/controllers/applicationsController.ts @@ -9,9 +9,9 @@ interface StatusCount { const getAllApplications = async (req: Request, res: Response) => { try { - const userId = req.query.user_id; + const { userId, status, date } = req.query; - const query = ` + let query = ` SELECT applications.id, jobs.company, @@ -26,7 +26,19 @@ const getAllApplications = async (req: Request, res: Response) => { applications.user_id = $1 `; - const { rows } = await pool.query(query, [userId]); + const queryParams = [userId]; + + if (status) { + query += ' AND statuses.name != $2'; + queryParams.push(status); + } + + if (date) { + query += ' AND applications.date_applied >= $3'; + queryParams.push(date); + } + + const { rows } = await pool.query(query, queryParams); res.json(rows); } catch (error) { console.error('Error fetching job applications:', error); From 2fd76b47f9c293643ccc302732edb4016c964eea Mon Sep 17 00:00:00 2001 From: Sean Date: Sun, 9 Jun 2024 10:57:54 -0400 Subject: [PATCH 2/9] CHE-192 Application page updated with toggles for filters --- .../ApplicationsPage/ApplicationsPage.tsx | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/client/src/pages/ApplicationsPage/ApplicationsPage.tsx b/client/src/pages/ApplicationsPage/ApplicationsPage.tsx index e46f299..e5f6a5e 100644 --- a/client/src/pages/ApplicationsPage/ApplicationsPage.tsx +++ b/client/src/pages/ApplicationsPage/ApplicationsPage.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import axios from 'axios'; import { useAppSelector } from '../../app/hooks'; @@ -8,20 +8,30 @@ import ApplicationDashboard from '../../components/ApplicationDashBoard/Applicat const ApplicationsPage = (): JSX.Element => { const navigate = useNavigate(); const [applications, setApplications] = useState([]); + const [showRejected, setShowRejected] = useState(true); + const [dateFilter, setDateFilter] = useState(''); const user = useAppSelector((state) => state.user.userData); useEffect(() => { async function fetchApplications() { try { - const response = await axios.get(`/api/applications?user_id=${user?._id}`); + const params: any = { userId: user?._id }; + if (!showRejected) params.status = 'Rejected'; + + //TODO adjust time delay for production - Let user select dif times from dropdown? + if (dateFilter) params.date = new Date(Date.now() - 30 * 1000).toISOString(); + console.log(params); + + const response = await axios.get(`/api/applications`, { params }); setApplications(response.data); + console.log(applications); } catch (error) { console.error('Error fetching applications:', error); } } fetchApplications(); - }, []); + }, [showRejected, dateFilter]); return (
@@ -34,6 +44,24 @@ const ApplicationsPage = (): JSX.Element => { Create New Application
+
+ + +
    {applications.map((application) => (
  • From ea528564d966cd928f2f200e0d1fde8e113f6712 Mon Sep 17 00:00:00 2001 From: Sean Date: Sun, 9 Jun 2024 19:42:47 -0400 Subject: [PATCH 3/9] CHE-192 Debugging logic --- .../src/pages/ApplicationsPage/ApplicationsPage.tsx | 11 +++++++---- server/controllers/applicationsController.ts | 7 +++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/client/src/pages/ApplicationsPage/ApplicationsPage.tsx b/client/src/pages/ApplicationsPage/ApplicationsPage.tsx index f5a37cf..69f96e4 100644 --- a/client/src/pages/ApplicationsPage/ApplicationsPage.tsx +++ b/client/src/pages/ApplicationsPage/ApplicationsPage.tsx @@ -9,7 +9,7 @@ const ApplicationsPage = (): JSX.Element => { const navigate = useNavigate(); const [applications, setApplications] = useState([]); const [showRejected, setShowRejected] = useState(true); - const [dateFilter, setDateFilter] = useState(''); + const [dateFilter, setDateFilter] = useState(false); const user = useAppSelector((state) => state.user.userData); useEffect(() => { @@ -19,7 +19,10 @@ const ApplicationsPage = (): JSX.Element => { if (!showRejected) params.status = 'Rejected'; //TODO adjust time delay for production - Let user select dif times from dropdown? - if (dateFilter) params.date = new Date(Date.now() - 30 * 1000).toISOString(); + if (dateFilter) { + const thirtySecondsAgo = new Date(Date.now() - 30 * 1000); + params.date = thirtySecondsAgo.toISOString(); + } console.log(params); const response = await axios.get(`/api/applications`, { params }); @@ -88,8 +91,8 @@ const ApplicationsPage = (): JSX.Element => { diff --git a/server/controllers/applicationsController.ts b/server/controllers/applicationsController.ts index ff63dc6..73c01d1 100644 --- a/server/controllers/applicationsController.ts +++ b/server/controllers/applicationsController.ts @@ -10,6 +10,7 @@ interface StatusCount { const getAllApplications = async (req: Request, res: Response) => { try { const { userId, status, date } = req.query; + console.log('data: ', date); let query = ` SELECT @@ -30,14 +31,16 @@ const getAllApplications = async (req: Request, res: Response) => { `; const queryParams = [userId]; + let paramIndex = 2; if (status) { - query += ' AND statuses.name != $2'; + query += ` AND statuses.name != $${paramIndex}`; queryParams.push(status); + paramIndex += 1; } if (date) { - query += ' AND applications.date_applied >= $3'; + query += ` AND applications.date_applied >= $${paramIndex}`; queryParams.push(date); } From 542c8c8a3a610b9f5b7685e3360583a3479242bd Mon Sep 17 00:00:00 2001 From: Sean Date: Mon, 10 Jun 2024 14:16:25 -0400 Subject: [PATCH 4/9] CHE-192 Code tweaks to ensure stamps are consistent across files --- .../ApplicationsPage/ApplicationsPage.tsx | 11 ++++++---- .../CreateApplicationPage.tsx | 11 +++++++--- server/controllers/applicationsController.ts | 22 +++++++++++-------- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/client/src/pages/ApplicationsPage/ApplicationsPage.tsx b/client/src/pages/ApplicationsPage/ApplicationsPage.tsx index 69f96e4..aac0fcf 100644 --- a/client/src/pages/ApplicationsPage/ApplicationsPage.tsx +++ b/client/src/pages/ApplicationsPage/ApplicationsPage.tsx @@ -20,21 +20,24 @@ const ApplicationsPage = (): JSX.Element => { //TODO adjust time delay for production - Let user select dif times from dropdown? if (dateFilter) { - const thirtySecondsAgo = new Date(Date.now() - 30 * 1000); + const thirtySecondsAgo = new Date(Date.now() - 30 * 3000); params.date = thirtySecondsAgo.toISOString(); } - console.log(params); + console.log('Fetching applications with params: ', params); const response = await axios.get(`/api/applications`, { params }); setApplications(response.data); - console.log(applications); + console.log('Fetched applications: ', applications); } catch (error) { console.error('Error fetching applications:', error); } } fetchApplications(); + // TODO Not sure I want to keep this. here for testing + const intervalId = setInterval(fetchApplications, 5000); + return () => clearInterval(intervalId); }, [showRejected, dateFilter]); const calculateIsInactive = (application: IApplication) => { @@ -42,7 +45,7 @@ const ApplicationsPage = (): JSX.Element => { if (notifications_paused) return false; const lastUpdatedDate = new Date(last_updated); - const notificationPeriodMs = (notification_period * 24 * 60 * 60 * 1000) / 60 / 60 / 24; + const notificationPeriodMs = notification_period * 5000; return new Date().getTime() - lastUpdatedDate.getTime() > notificationPeriodMs; }; diff --git a/client/src/pages/CreateApplicationPage/CreateApplicationPage.tsx b/client/src/pages/CreateApplicationPage/CreateApplicationPage.tsx index e96fabb..da0b181 100644 --- a/client/src/pages/CreateApplicationPage/CreateApplicationPage.tsx +++ b/client/src/pages/CreateApplicationPage/CreateApplicationPage.tsx @@ -18,7 +18,7 @@ const CreateApplicationPage = (): JSX.Element => { status_id: 1, user_id: user?._id || '', quick_apply: false, - date_applied: new Date().toISOString().split('T')[0], + date_applied: new Date().toISOString().slice(0, 16), general_notes: '', job_id: 0, }); @@ -54,6 +54,11 @@ const CreateApplicationPage = (): JSX.Element => { ...prevFormData, [name]: checked, })); + } else if (name === 'date_applied') { + setFormData((prevFormData) => ({ + ...prevFormData, + [name]: value, + })); } else { setFormData((prevFormData) => ({ ...prevFormData, @@ -159,8 +164,8 @@ const CreateApplicationPage = (): JSX.Element => { className="w-full p-2 rounded bg-gray-800 text-white" id="date_applied" name="date_applied" - type="date" - value={formData.date_applied} + type="datetime-local" + value={new Date(formData.date_applied).toISOString().slice(0, 16)} onChange={handleChange} required /> diff --git a/server/controllers/applicationsController.ts b/server/controllers/applicationsController.ts index 73c01d1..64465ce 100644 --- a/server/controllers/applicationsController.ts +++ b/server/controllers/applicationsController.ts @@ -10,7 +10,7 @@ interface StatusCount { const getAllApplications = async (req: Request, res: Response) => { try { const { userId, status, date } = req.query; - console.log('data: ', date); + console.log('Filter date: ', date); let query = ` SELECT @@ -19,6 +19,7 @@ const getAllApplications = async (req: Request, res: Response) => { jobs.title, statuses.name AS status, applications.general_notes, + applications.date_applied, applications.last_updated, applications.notification_period, applications.notifications_paused @@ -44,7 +45,14 @@ const getAllApplications = async (req: Request, res: Response) => { queryParams.push(date); } + console.log('date params: '); + console.log(' QUERY: ', query); + const { rows } = await pool.query(query, queryParams); + + rows.forEach((row) => { + console.log('Application date_applied:', row.date_applied); + }); res.json(rows); } catch (error) { console.error('Error fetching job applications:', error); @@ -77,6 +85,9 @@ const createApplication = async (req: Request, res: Response) => { user_id, } = req.body; + const appliedDate = new Date(date_applied).toISOString(); + console.log('Inserting application with date_applied:', appliedDate); + const jobQuery = ` INSERT INTO jobs (title, company, location, description, url) VALUES ($1, $2, $3, $4, $5) @@ -91,14 +102,7 @@ const createApplication = async (req: Request, res: Response) => { VALUES ($1, $2, $3, $4, $5, $6, NOW()) RETURNING id `; - const applicationValues = [ - job_id, - status_id, - user_id, - quick_apply, - date_applied, - general_notes, - ]; + const applicationValues = [job_id, status_id, user_id, quick_apply, appliedDate, general_notes]; const applicationResult = await pool.query(applicationQuery, applicationValues); res.status(201).json({ id: applicationResult.rows[0].id }); From fd5e4284e9da8964fb25b0665d8b8d6242b4e83f Mon Sep 17 00:00:00 2001 From: Brok3Turtl3 Date: Mon, 10 Jun 2024 15:21:24 -0400 Subject: [PATCH 5/9] CHE-192 Code cleanup --- client/src/pages/ApplicationsPage/ApplicationsPage.tsx | 4 +--- .../pages/CreateApplicationPage/CreateApplicationPage.tsx | 3 +-- server/controllers/applicationsController.ts | 8 -------- 3 files changed, 2 insertions(+), 13 deletions(-) diff --git a/client/src/pages/ApplicationsPage/ApplicationsPage.tsx b/client/src/pages/ApplicationsPage/ApplicationsPage.tsx index aac0fcf..4229586 100644 --- a/client/src/pages/ApplicationsPage/ApplicationsPage.tsx +++ b/client/src/pages/ApplicationsPage/ApplicationsPage.tsx @@ -5,7 +5,7 @@ import { useAppSelector } from '../../app/hooks'; import { IApplication } from '../../../types/applications'; import ApplicationDashboard from '../../components/ApplicationDashBoard/ApplicationDashBoard'; -const ApplicationsPage = (): JSX.Element => { +const ApplicationsPage = () => { const navigate = useNavigate(); const [applications, setApplications] = useState([]); const [showRejected, setShowRejected] = useState(true); @@ -23,12 +23,10 @@ const ApplicationsPage = (): JSX.Element => { const thirtySecondsAgo = new Date(Date.now() - 30 * 3000); params.date = thirtySecondsAgo.toISOString(); } - console.log('Fetching applications with params: ', params); const response = await axios.get(`/api/applications`, { params }); setApplications(response.data); - console.log('Fetched applications: ', applications); } catch (error) { console.error('Error fetching applications:', error); } diff --git a/client/src/pages/CreateApplicationPage/CreateApplicationPage.tsx b/client/src/pages/CreateApplicationPage/CreateApplicationPage.tsx index da0b181..f855445 100644 --- a/client/src/pages/CreateApplicationPage/CreateApplicationPage.tsx +++ b/client/src/pages/CreateApplicationPage/CreateApplicationPage.tsx @@ -4,7 +4,7 @@ import { useAppSelector, useAppDispatch } from '../../app/hooks'; import { createApplication } from '../../features/applications/applicationSlice'; import { IStatus, IApplicationFormData } from '../../../types/applications'; -const CreateApplicationPage = (): JSX.Element => { +const CreateApplicationPage = () => { const user = useAppSelector((state) => state.user.userData); const { status } = useAppSelector((state) => state.application); @@ -41,7 +41,6 @@ const CreateApplicationPage = (): JSX.Element => { const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); dispatch(createApplication(formData)); - console.log(formData); }; const handleChange = ( diff --git a/server/controllers/applicationsController.ts b/server/controllers/applicationsController.ts index 64465ce..400c26f 100644 --- a/server/controllers/applicationsController.ts +++ b/server/controllers/applicationsController.ts @@ -10,7 +10,6 @@ interface StatusCount { const getAllApplications = async (req: Request, res: Response) => { try { const { userId, status, date } = req.query; - console.log('Filter date: ', date); let query = ` SELECT @@ -45,14 +44,8 @@ const getAllApplications = async (req: Request, res: Response) => { queryParams.push(date); } - console.log('date params: '); - console.log(' QUERY: ', query); - const { rows } = await pool.query(query, queryParams); - rows.forEach((row) => { - console.log('Application date_applied:', row.date_applied); - }); res.json(rows); } catch (error) { console.error('Error fetching job applications:', error); @@ -86,7 +79,6 @@ const createApplication = async (req: Request, res: Response) => { } = req.body; const appliedDate = new Date(date_applied).toISOString(); - console.log('Inserting application with date_applied:', appliedDate); const jobQuery = ` INSERT INTO jobs (title, company, location, description, url) From 46a19dbdcab37279a7d3528a6410c2a5c99b38be Mon Sep 17 00:00:00 2001 From: Brok3Turtl3 Date: Mon, 10 Jun 2024 15:50:27 -0400 Subject: [PATCH 6/9] CHE-192 Typing update --- client/src/pages/ApplicationsPage/ApplicationsPage.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/client/src/pages/ApplicationsPage/ApplicationsPage.tsx b/client/src/pages/ApplicationsPage/ApplicationsPage.tsx index 4229586..069f81b 100644 --- a/client/src/pages/ApplicationsPage/ApplicationsPage.tsx +++ b/client/src/pages/ApplicationsPage/ApplicationsPage.tsx @@ -5,6 +5,12 @@ import { useAppSelector } from '../../app/hooks'; import { IApplication } from '../../../types/applications'; import ApplicationDashboard from '../../components/ApplicationDashBoard/ApplicationDashBoard'; +interface Params { + userId: string; + status?: string; + date?: string; +} + const ApplicationsPage = () => { const navigate = useNavigate(); const [applications, setApplications] = useState([]); @@ -15,7 +21,7 @@ const ApplicationsPage = () => { useEffect(() => { async function fetchApplications() { try { - const params: any = { userId: user?._id }; + const params: Params = { userId: user?._id }; if (!showRejected) params.status = 'Rejected'; //TODO adjust time delay for production - Let user select dif times from dropdown? From c5e6b43e40493b3729f943fa6af481d09cd67b77 Mon Sep 17 00:00:00 2001 From: Brok3Turtl3 Date: Mon, 10 Jun 2024 15:59:08 -0400 Subject: [PATCH 7/9] CHE-192 Typing... --- client/src/pages/ApplicationsPage/ApplicationsPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/pages/ApplicationsPage/ApplicationsPage.tsx b/client/src/pages/ApplicationsPage/ApplicationsPage.tsx index 069f81b..07c3bd8 100644 --- a/client/src/pages/ApplicationsPage/ApplicationsPage.tsx +++ b/client/src/pages/ApplicationsPage/ApplicationsPage.tsx @@ -21,7 +21,7 @@ const ApplicationsPage = () => { useEffect(() => { async function fetchApplications() { try { - const params: Params = { userId: user?._id }; + const params: Params = { userId: user?._id ?? '' }; if (!showRejected) params.status = 'Rejected'; //TODO adjust time delay for production - Let user select dif times from dropdown? From 541811c643997268cea938faf6a94c0c27895782 Mon Sep 17 00:00:00 2001 From: Sean Date: Tue, 11 Jun 2024 06:37:03 -0400 Subject: [PATCH 8/9] CHE-192 Updated image for lint and test compose, added credentials for postgres to dev container and code cleanup --- client/src/pages/ApplicationsPage/ApplicationsPage.tsx | 2 -- .../pages/CreateApplicationPage/CreateApplicationPage.tsx | 1 - docker-compose-dev.yml | 3 +++ docker-compose-lint.yml | 2 +- docker-compose-test.yml | 2 +- server/controllers/applicationsController.ts | 8 -------- 6 files changed, 5 insertions(+), 13 deletions(-) diff --git a/client/src/pages/ApplicationsPage/ApplicationsPage.tsx b/client/src/pages/ApplicationsPage/ApplicationsPage.tsx index aac0fcf..140ea12 100644 --- a/client/src/pages/ApplicationsPage/ApplicationsPage.tsx +++ b/client/src/pages/ApplicationsPage/ApplicationsPage.tsx @@ -23,12 +23,10 @@ const ApplicationsPage = (): JSX.Element => { const thirtySecondsAgo = new Date(Date.now() - 30 * 3000); params.date = thirtySecondsAgo.toISOString(); } - console.log('Fetching applications with params: ', params); const response = await axios.get(`/api/applications`, { params }); setApplications(response.data); - console.log('Fetched applications: ', applications); } catch (error) { console.error('Error fetching applications:', error); } diff --git a/client/src/pages/CreateApplicationPage/CreateApplicationPage.tsx b/client/src/pages/CreateApplicationPage/CreateApplicationPage.tsx index da0b181..557f299 100644 --- a/client/src/pages/CreateApplicationPage/CreateApplicationPage.tsx +++ b/client/src/pages/CreateApplicationPage/CreateApplicationPage.tsx @@ -41,7 +41,6 @@ const CreateApplicationPage = (): JSX.Element => { const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); dispatch(createApplication(formData)); - console.log(formData); }; const handleChange = ( diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index bc16e6a..1c99cda 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -15,6 +15,9 @@ services: environment: - NODE_ENV=development - DATABASE_URL=postgres://codehammers:ch-dev@postgres:5432/ch-dev-database + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=ch-dev + - POSTGRES_DB=ch-dev-database depends_on: - postgres postgres: diff --git a/docker-compose-lint.yml b/docker-compose-lint.yml index 8f8c9f0..52c5031 100644 --- a/docker-compose-lint.yml +++ b/docker-compose-lint.yml @@ -1,7 +1,7 @@ version: '3' services: dev: - image: codehammers/ch-dev-dep-v2:latest + image: codehammers/ch-tracker-dev:latest container_name: ch-lint ports: - '3333:3333' diff --git a/docker-compose-test.yml b/docker-compose-test.yml index ec4be8c..2fa5abd 100644 --- a/docker-compose-test.yml +++ b/docker-compose-test.yml @@ -2,7 +2,7 @@ version: '3' services: test: - image: codehammers/ch-dev-dep-v2:latest + image: codehammers/ch-tracker-dev:latest container_name: ch-test ports: - '3000:3000' diff --git a/server/controllers/applicationsController.ts b/server/controllers/applicationsController.ts index 64465ce..400c26f 100644 --- a/server/controllers/applicationsController.ts +++ b/server/controllers/applicationsController.ts @@ -10,7 +10,6 @@ interface StatusCount { const getAllApplications = async (req: Request, res: Response) => { try { const { userId, status, date } = req.query; - console.log('Filter date: ', date); let query = ` SELECT @@ -45,14 +44,8 @@ const getAllApplications = async (req: Request, res: Response) => { queryParams.push(date); } - console.log('date params: '); - console.log(' QUERY: ', query); - const { rows } = await pool.query(query, queryParams); - rows.forEach((row) => { - console.log('Application date_applied:', row.date_applied); - }); res.json(rows); } catch (error) { console.error('Error fetching job applications:', error); @@ -86,7 +79,6 @@ const createApplication = async (req: Request, res: Response) => { } = req.body; const appliedDate = new Date(date_applied).toISOString(); - console.log('Inserting application with date_applied:', appliedDate); const jobQuery = ` INSERT INTO jobs (title, company, location, description, url) From 3b5f0c28c3873c38f93a49e47a8fa399ca42c2fd Mon Sep 17 00:00:00 2001 From: Sean Date: Tue, 11 Jun 2024 07:30:03 -0400 Subject: [PATCH 9/9] CHE-192 Basic validation that stops user from picking a future date when creating an application --- .../CreateApplicationPage/CreateApplicationPage.tsx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/client/src/pages/CreateApplicationPage/CreateApplicationPage.tsx b/client/src/pages/CreateApplicationPage/CreateApplicationPage.tsx index f855445..83e6bd0 100644 --- a/client/src/pages/CreateApplicationPage/CreateApplicationPage.tsx +++ b/client/src/pages/CreateApplicationPage/CreateApplicationPage.tsx @@ -9,6 +9,7 @@ const CreateApplicationPage = () => { const { status } = useAppSelector((state) => state.application); const [statuses, setStatuses] = useState([]); + const [errorMessage, setErrorMessage] = useState(null); const [formData, setFormData] = useState({ title: '', company: '', @@ -40,6 +41,14 @@ const CreateApplicationPage = () => { const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); + const selectedDate = new Date(formData.date_applied); + const currentDate = new Date(); + + if (selectedDate > currentDate) { + setErrorMessage("Sean S says time travel isn't a thing."); + return; + } + setErrorMessage(null); dispatch(createApplication(formData)); }; @@ -70,6 +79,9 @@ const CreateApplicationPage = () => {

    Create Applications

    + {errorMessage && ( +
    {errorMessage}
    + )}