diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..e69de29b diff --git a/backend/src/middlewares/validateAuth.ts b/backend/src/middlewares/validateAuth.ts index 7084a157..12ff125a 100644 --- a/backend/src/middlewares/validateAuth.ts +++ b/backend/src/middlewares/validateAuth.ts @@ -8,7 +8,7 @@ const validateAuth = (req: Request, res: Response, next: NextFunction) => { }; switch (req.path) { - case "/register": + case "/signup": { const { first_name, last_name, email, password, confirm_password } = req.body; diff --git a/backend/src/routes/cars.ts b/backend/src/routes/cars.ts index 5885e41f..27a84314 100644 --- a/backend/src/routes/cars.ts +++ b/backend/src/routes/cars.ts @@ -9,7 +9,7 @@ router.post("/check-license", async (req: Request, res: Response) => { const { license_number } = req.body; const { rows: drivers } = await pool.query( - `SELECT id FROM drivers WHERE license_number = $1`, + `SELECT * FROM drivers WHERE license_number = $1`, [license_number] ); diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index dd5aa9a9..4b1e7338 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -3,30 +3,33 @@ import "react-activity/dist/Spinner.css"; import "react-toastify/dist/ReactToastify.css"; import LoginPage from "./pages/LoginPage.tsx"; + import HomePage from "./pages/HomePage.tsx"; -import SignUp from "./pages/SignUpPage.tsx"; import AboutPage from "./pages/AboutPage.tsx"; +import SignUpPage from "./pages/SignUpPage.tsx"; +import UnauthorizedPage from "./pages/UnauthorizedPage.tsx"; +import AddViolationPage from "./pages/AddViolationPage.tsx"; import AdminLandingPage from "./pages/AdminHomePage.tsx"; import EncodePage from "./pages/EncodePage.tsx"; import ViolatorList from "./pages/ViolatorList.tsx"; import DriversList from "./pages/DriverList.tsx"; -import RegisterDriver from "./pages/RegisterDriver.tsx"; import AddDriver from "./pages/AddDriver.tsx"; -import UnauthorizedPage from "./pages/UnauthorizedPage.tsx"; -import HomepageDriver from "./components/NotificationsList.tsx"; import RegistrationList from "./pages/RegistrationList.tsx"; +import RegisterDriver from "./pages/RegisterDriver.tsx"; +import SendNotif from "./pages/SendNotif.tsx"; + +import ViewProfile from "./pages/ViewProfile.tsx"; +import Protocols from "./components/Policies/protocols.tsx"; +import Rules from "./components/Policies/rules.tsx"; +import ChangePassword from "./pages/ChangePassword.tsx"; + import RequireAuth from "./components/RequireAuth.tsx"; import PersistLogin from "./components/PersistLogin.tsx"; + import Loading from "./components/Loading.tsx"; import { LoadingContextType } from "./types/loading.types.ts"; import useLoading from "./hooks/context-hooks/useLoading.ts"; -import ViewProfile from "./pages/ViewProfile.tsx"; -import Protocols from "./components/Policies/protocols.tsx"; -import Rules from "./components/Policies/rules.tsx"; -import ChangePassword from "./pages/ChangePassword.tsx"; -import AddViolationPage from "./pages/AddViolationPage.tsx"; -import SendNotif from "./pages/SendNotif.tsx"; const Main = () => { const { appLoading }: LoadingContextType = useLoading(); @@ -39,26 +42,63 @@ const Main = () => { {/* PUBLIC ROUTES */} - } /> - } /> + + } + /> + } + /> - } /> + } + /> - } /> + } + /> }> {/* FOR ALL LOGGED IN */} - } /> - } /> + } + /> + } + /> {/* USER ROUTES */} }> - } /> - } /> - } /> - } /> - } /> - } /> + } + /> + } + /> + } + /> + } + /> + } + /> {/* ADMIN ROUTES */} @@ -94,7 +134,7 @@ const Main = () => { } - /> + /> @@ -102,4 +142,4 @@ const Main = () => { ); }; -export default Main \ No newline at end of file +export default Main; diff --git a/frontend/src/components/PreviewProfile.tsx b/frontend/src/components/PreviewProfile.tsx index 82063a3d..9e133d15 100644 --- a/frontend/src/components/PreviewProfile.tsx +++ b/frontend/src/components/PreviewProfile.tsx @@ -26,45 +26,45 @@ const PreviewProfile = ({
-

+

Last Name

-

+

{selectedEntry.last_name || ""}

-

+

First Name

-

+

{selectedEntry.first_name || ""}

-
-

+
+

Sex

-

+

{selectedEntry.sex || ""}

-
-

+
+

Date of Birth

-

+

{selectedEntry.date_of_birth || "MM/DD/YY"}

-
-

+
+

Driver Type

-

+

{selectedEntry.driver_type || ""}

@@ -73,18 +73,18 @@ const PreviewProfile = ({
-

+

License Number

-

+

{selectedEntry.license_number || ""}

-

+

License Expiration Date

-

+

{selectedEntry.license_expiration_date || ""}

@@ -93,12 +93,12 @@ const PreviewProfile = ({
diff --git a/frontend/src/components/RegistrationListCard.tsx b/frontend/src/components/RegistrationListCard.tsx index 5576d69e..d1c47267 100644 --- a/frontend/src/components/RegistrationListCard.tsx +++ b/frontend/src/components/RegistrationListCard.tsx @@ -13,7 +13,7 @@ const RegistrationListCard = ({

Name

- {last_name} {first_name} + {first_name} {last_name}

diff --git a/frontend/src/components/ViolatorsListCard.tsx b/frontend/src/components/ViolatorsListCard.tsx index 83b80083..33ca1de6 100644 --- a/frontend/src/components/ViolatorsListCard.tsx +++ b/frontend/src/components/ViolatorsListCard.tsx @@ -5,41 +5,47 @@ const ViolatorsListCard = ({ last_name, driver_type, license_number, - violations , + violations, }: Violators) => { - return (
-
- -
-

Violations

-

+ className="border-b-2 flex-col flex-1 border-t-transparent w-full border-b-inputfield" + id="row"> +
+
+

+ Violations +

+

{violations ? violations.length : 0} -

-
-
-

Name

-

- {first_name} {last_name} -

-
-
-

Driver Type

-

- {driver_type} -

-
-
-

License Number

-

- {license_number} -

-
+

+
+
+

+ Name +

+

+ {first_name} {last_name} +

+
+
+

+ Driver Type +

+

+ {driver_type} +

+
+
+

+ License Number +

+

+ {license_number} +

+
); }; diff --git a/frontend/src/hooks/registration-hooks/useApproveRegistration.ts b/frontend/src/hooks/registration-hooks/useApproveRegistration.ts index 34bdfa3e..fa23c6b3 100644 --- a/frontend/src/hooks/registration-hooks/useApproveRegistration.ts +++ b/frontend/src/hooks/registration-hooks/useApproveRegistration.ts @@ -1,20 +1,21 @@ -import { useState } from "react"; import { toast } from "react-toastify"; import { fetchWithAuth } from "../../utils/fetch"; // Custom fetch utility import useFetchWithAuthExports from "../context-hooks/useFetchWithAuthExports"; +import { LoadingContextType } from "../../types/loading.types"; +import useLoading from "../context-hooks/useLoading"; export const useApproveRegistration = () => { - const [processLoading, setProcessLoading] = useState(false); const { auth, refresh, navigate } = useFetchWithAuthExports(); + const { setAppLoading }: LoadingContextType = useLoading(); + + const approveRegistration = async (licenseNumber: string) => { + setAppLoading!(true); - const approveRegistration = async (licenseNumber: string): Promise => { if (!licenseNumber) { toast.error("License number is required."); return; } - setProcessLoading(true); - try { const response = await fetchWithAuth( navigate, @@ -28,7 +29,7 @@ export const useApproveRegistration = () => { if (!response.ok) { const errorData = await response.json(); toast.error(errorData.message || "Failed to approve registration."); - return; + return false; } const data = await response.json(); @@ -39,9 +40,9 @@ export const useApproveRegistration = () => { "Network error occurred. Could not connect to the server. Please try again." ); } finally { - setProcessLoading(false); + setAppLoading!(false); } }; - return { approveRegistration, processLoading }; -}; \ No newline at end of file + return { approveRegistration }; +}; diff --git a/frontend/src/hooks/useEditViolation.ts b/frontend/src/hooks/useEditViolation.ts deleted file mode 100644 index 3090245f..00000000 --- a/frontend/src/hooks/useEditViolation.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { useEffect, useState } from "react"; -import { BackendMessage } from "../types/response.types"; -import { toast } from "react-toastify"; -import { Violation } from "../types/datatypes"; -import { fetchWithAuth } from "../utils/fetch"; -import useFetchWithAuthExports from "./context-hooks/useFetchWithAuthExports"; - -const useEditViolation = (id: string) => { - const [loading, setLoading] = useState(true); - const { auth, refresh, navigate } = useFetchWithAuthExports(); - const [violation, setViolation] = useState({}); - - useEffect(() => { - const editViolation = async (violationId: string) => { - setLoading(true); - try { - const response = await fetchWithAuth( - navigate, - refresh, - auth, - "/violation/update", - "patch", - { id: violationId } - ); - - if (response.status === 401) { - const backendError: BackendMessage = await response.json(); - toast.error(backendError.message); - navigate("/unauthorized"); - throw Error("WALA TAWO NGA LOGGED IN"); - } - - if (!response.ok) { - const backendError: BackendMessage = await response.json(); - toast.error(backendError.message); - throw Error("may sala sa backend hahaha"); - } - - const editedViolation = await response.json(); - setViolation(editedViolation); - } catch (error) { - console.error(error); - } - }; - - editViolation(id); - }, [auth, id, navigate, refresh]); - - return { violation, loading }; -}; - -export default useEditViolation; diff --git a/frontend/src/hooks/useRefresh.ts b/frontend/src/hooks/useRefresh.ts index b393d9df..b0d79791 100644 --- a/frontend/src/hooks/useRefresh.ts +++ b/frontend/src/hooks/useRefresh.ts @@ -30,6 +30,7 @@ const useRefresh = () => { ...prev, accessToken: foundUser.accessToken, isAdmin: foundUser.isAdmin, + id: foundUser.id, }; }); diff --git a/frontend/src/hooks/useSignUp.ts b/frontend/src/hooks/useSignUp.ts index ff4e5d0b..ab0500f7 100644 --- a/frontend/src/hooks/useSignUp.ts +++ b/frontend/src/hooks/useSignUp.ts @@ -16,13 +16,15 @@ const useSignUp = () => { const backendError: BackendMessage = await response.json(); console.log(backendError); toast.error(`${backendError.message}`); - return; + return false; } const notification = await response.json(); toast.success(`${notification.message}!`); + return true } catch (error) { alert(error); + return false; } finally { setLoading(false); } diff --git a/frontend/src/pages/AddViolationPage.tsx b/frontend/src/pages/AddViolationPage.tsx index 5fdb23ad..58cc438a 100644 --- a/frontend/src/pages/AddViolationPage.tsx +++ b/frontend/src/pages/AddViolationPage.tsx @@ -4,6 +4,7 @@ import { useState } from "react"; import { toast } from "react-toastify"; import useCheckLicenseNumber from "../hooks/car-hooks/useCheckLicenseNumber"; // import the hook import { DriverWithVandC } from "../types/datatypes"; +import AddViolationComponent from "../components/AddViolationComponent"; const AddViolation = () => { const navigate = useNavigate(); @@ -12,6 +13,7 @@ const AddViolation = () => { const [currentStep, setCurrentStep] = useState(1); const [licenseNumber, setLicenseNumber] = useState(""); const [driverProfile, setDriverProfile] = useState(); // Store the driver profile + const [violationModalActive, setViolationModalActive] = useState(false); const handleCancelButton = () => { navigate("/encode"); @@ -20,15 +22,14 @@ const AddViolation = () => { const handleNextClick = async () => { try { const driver = await checkLicenseNumber(licenseNumber); - console.log(driver); if (driver) { setDriverProfile(driver); setCurrentStep(currentStep + 1); return; } } catch (error) { - alert(error); - toast.error("Something went wrong!"); + const errorMessage = (error as Error).message; + toast.error(errorMessage); } }; @@ -106,9 +107,7 @@ const AddViolation = () => {
-

- Sex -

+

Sex

{driverProfile.sex}

@@ -196,14 +195,20 @@ const AddViolation = () => {
)} + {violationModalActive && ( + + )}
); }; -export default AddViolation; \ No newline at end of file +export default AddViolation; diff --git a/frontend/src/pages/DriverList.tsx b/frontend/src/pages/DriverList.tsx index 51acf225..6b9b6d1b 100644 --- a/frontend/src/pages/DriverList.tsx +++ b/frontend/src/pages/DriverList.tsx @@ -72,7 +72,7 @@ const DriversList = () => {

- Driver's List + Drivers' List

List of Drivers within the university. @@ -87,7 +87,7 @@ const DriversList = () => {

{sortedDrivers && sortedDrivers.length > 0 ? ( diff --git a/frontend/src/pages/RegistrationList.tsx b/frontend/src/pages/RegistrationList.tsx index aa9b4a71..5c931ed6 100644 --- a/frontend/src/pages/RegistrationList.tsx +++ b/frontend/src/pages/RegistrationList.tsx @@ -14,7 +14,7 @@ const RegistrationList = () => { useDeleteRegistration(); const [selectedRegistration, setSelectedRegistration] = useState(); - const { approveRegistration, processLoading } = useApproveRegistration(); + const { approveRegistration } = useApproveRegistration(); const handleRegisterClick = (registration: Registration) => { setSelectedRegistration(registration); @@ -27,9 +27,6 @@ const RegistrationList = () => { } await approveRegistration(selectedRegistration.license_number); - setTimeout(() => { - window.location.reload(); - }, 500); }; const handleReject = async () => { @@ -144,10 +141,8 @@ const RegistrationList = () => {
-

Create new account

+

+ Create new account +

Already have an account?{" "}

- +
{ type="submit" className="flex justify-center items-center justify-self-end w-auto bg-buttongreen font-syke-regular text-white py-2 px-5 hover:bg-[#33471a] transition-colors rounded-sm lg:text-sm md:text-xs text-xxs"> {loading ? ( - + ) : ( "Create account" )} @@ -129,4 +137,4 @@ const SignUp = () => { ); }; -export default SignUp; +export default SignUpPage; diff --git a/frontend/src/pages/ViewProfile.tsx b/frontend/src/pages/ViewProfile.tsx index ee7e0bfe..ead9baf0 100644 --- a/frontend/src/pages/ViewProfile.tsx +++ b/frontend/src/pages/ViewProfile.tsx @@ -30,65 +30,79 @@ const ViewProfile = () => {
{auth!.isAdmin ? :
}
-
-
- + {activeSection === "profile" && } + {activeSection === "vehicle" && } + {activeSection === "violation" && ( + + )} +
+ {auth?.isAdmin && ( + <> + + + )}
- - -
+ )}
); diff --git a/frontend/src/pages/ViolatorList.tsx b/frontend/src/pages/ViolatorList.tsx index 5c79e157..07bd36e7 100644 --- a/frontend/src/pages/ViolatorList.tsx +++ b/frontend/src/pages/ViolatorList.tsx @@ -55,25 +55,29 @@ const ViolatorList = () => {
-
-
-
+
+
+
{selectedViolator ? ( ) : ( -
+
Select a violator to see details.
)}
-
-
+
+
-
+
-

Violator's List

-
List of Violators within the university.
+

+ Violators' List +

+

+ List of Violators within the university. +

{
{sortedViolators && sortedViolators.length > 0 ? ( diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js index 772b9f65..5162fe63 100644 --- a/frontend/tailwind.config.js +++ b/frontend/tailwind.config.js @@ -12,7 +12,7 @@ export default { "2xl": "1536px", }, fontSize: { - "2xxs": ["0.5rem", "0.8rem"], + "2xs": ["0.5rem", "0.8rem"], xxs: ["0.5rem", "0.75rem"], xxxs: ["0.4rem", "0.65rem"], }, diff --git a/package-lock.json b/package-lock.json index 44b2d174..a7d569ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "eslint-plugin-react-hooks": "^5.0.0", "eslint-plugin-react-refresh": "^0.4.14", "globals": "^15.13.0", + "prettier": "^3.4.2", "typescript-eslint": "^8.17.0" } }, @@ -3485,6 +3486,21 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", + "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/pretty-format": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", diff --git a/package.json b/package.json index 17c6c0f7..034d8053 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "eslint-plugin-react-hooks": "^5.0.0", "eslint-plugin-react-refresh": "^0.4.14", "globals": "^15.13.0", + "prettier": "^3.4.2", "typescript-eslint": "^8.17.0" } }