diff --git a/client/app/profile/[userId]/page.tsx b/client/app/profile/[userId]/page.tsx index b4dd4f2..40ba8dd 100644 --- a/client/app/profile/[userId]/page.tsx +++ b/client/app/profile/[userId]/page.tsx @@ -1,26 +1,62 @@ "use client"; +import BackgroundComponent from "@/components/profile/backgroundComp"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Button } from "@/components/ui/button"; import useGetUserProfile from "@/hooks/user_data/useGetUserProfile"; import { PersonIcon } from "@radix-ui/react-icons"; import { useParams } from "next/navigation"; import { useRouter } from "next/navigation"; +import { EditIcon, Factory, CircleUser } from "lucide-react"; +import {useEffect, useState} from "react"; +import { ProfileEditModal } from "@/components/modals/ProfileEditModal"; +import useGetAllRole from "@/hooks/user_data/useGetAllRole"; + +type RolesWithPermisson = { + id: string; + name: string; + permissions: [{ + name: string; + description: string; +}] +}; + export default function ProfilePage() { - const userId = useParams().userId.toString(); + const router = useRouter(); - const { userData } = useGetUserProfile(userId); + const { user, stsDetails, landfillDetails, getUserDetails} = useGetUserProfile(); // Destructure user and getUserDetails + const [role, setRole] = useState("Role Name"); + // const [permissions, setPermissions] = useState([]); + const RolePlace = 'Station'; + const { fetchAllRoles, roles, rolesWithPermissions } = useGetAllRole(); + useEffect(() => { + const fetchData = async () => { + await getUserDetails(); + await fetchAllRoles(); + + setRole(user.roleName); + }; + + fetchData(); + + }, []); + return ( -
+
+ -
+
+ {user.roleName} +
+
+
@@ -28,12 +64,113 @@ export default function ProfilePage() {

Profile Page

-

ID: {userId}

-

Email: {userData.email}

-

Role: {userData.role}

-

Name: {userData.name}

-

Assigned Area: {userData.assignedArea}

+

ID:

+

Email: {user.email}

+

Role: {user.roleName}

+

Profile Name: {user.profileName}

+

Username: {user.username}

+

Role Description: {user.roleDescription}

+ + +
+ + +
+ + + + {user?.roleName === 'STS_MANAGER' && stsDetails?.stsId?.toString().length > 1 &&
+
STS Details
+

Id: {stsDetails.stsId}

+

STS Name: {stsDetails.stsName}

+

Ward Number: {stsDetails.stsWardNumber}

+

Capacity: {stsDetails.stsCapacity}

+

Current Total Waste: {stsDetails.stsCurrentTotalWaste}

+

Coordinate: {stsDetails.stsLatitude}, {stsDetails.stsLongitude}

+ + +
+ + } + +{user?.roleName === 'STS_MANAGER' && stsDetails?.stsId?.toString().length < 1 &&
+
STS Not Assigned
+ Call your admin to assign your STS. +
+ } +{user?.roleName === 'STS_MANAGER' && rolesWithPermissions.some(role => role.name === 'STS_MANAGER') && ( +
+

STS Manager Permissions:

+
    + {rolesWithPermissions + .find(role => role.name === 'STS_MANAGER') + ?.permissions.map(permission => ( +
  • + {permission.name}: {permission.description} +
  • + ))} +
+
+)} + + + {user?.roleName === 'LAND_MANAGER' && landfillDetails?.landfillId?.toString().length > 1 &&
+
Landfill Details
+

ID: {landfillDetails.landfillId}

+

Landfill Name: {landfillDetails.landFillName}

+

Capacity: {landfillDetails.landFillCapacity}

+

Current Total Waste: {landfillDetails.landFillCurrentWaste}

+

Coordinate: {landfillDetails.landfillLatitude}, {landfillDetails.landFillLongitude}

+
} + + {user?.roleName === 'LAND_MANAGER' && landfillDetails?.landfillId?.toString().length < 1 && ( +
+
LandFill Not Assigned
+ Call your admin to assign your Landfill. +
+ )} + +{user?.roleName === 'LAND_MANAGER' && rolesWithPermissions.some(role => role.name === 'LAND_MANAGER') && ( +
+

Land Manager Permissions:

+
    + {rolesWithPermissions + .find(role => role.name === 'LAND_MANAGER') + ?.permissions.map(permission => ( +
  • + {permission.name}: {permission.description} +
  • + ))} +
+
+)} + + {user?.roleName === 'SYSTEM_ADMIN' &&
+
Admin
+
You are admin
+
} + {user?.roleName !== 'STS_MANAGER' && user?.roleName !== 'LAND_MANAGER' && user?.roleName !== 'SYSTEM_ADMIN' && ( +
Oops! Your role has not assigned yet
+ )} + +{user?.roleName === 'SYSTEM_ADMIN' && rolesWithPermissions.some(role => role.name === 'SYSTEM_ADMIN') && ( +
+

System Admin Permissions:

+
    + {rolesWithPermissions + .find(role => role.name === 'SYSTEM_ADMIN') + ?.permissions.map(permission => ( +
  • + {permission.name}: {permission.description} +
  • + ))} +
+
+)} + + +
); diff --git a/client/components/maps/AllStsShow.tsx b/client/components/maps/AllStsShow.tsx index 0d489ec..21024fd 100644 --- a/client/components/maps/AllStsShow.tsx +++ b/client/components/maps/AllStsShow.tsx @@ -2,6 +2,7 @@ import useGetAllSTS from "@/hooks/stsdata/useGetAllSTS"; import GoogleMapComponent from "@/components/maps/GoogleMap"; import * as React from "react"; +import useGetUserProfile from "@/hooks/user_data/useGetUserProfile"; type StsShow = { lat: number; @@ -11,6 +12,7 @@ type StsShow = { export const AllStsMapShow: React.FC = () => { const { getAllSTS, stsCoordinate, storagePercentage } = useGetAllSTS(); + const [coordinates, setCoordinates] = React.useState([]); // const staticCoordinates: StsShow[] = [ @@ -34,9 +36,11 @@ export const AllStsMapShow: React.FC = () => { }, [stsCoordinate]); + React.useEffect(() => { getMapData(); }, []); + return coordinates && ; }; diff --git a/client/components/modals/LandFillVehicleEntryModal.tsx b/client/components/modals/LandFillVehicleEntryModal.tsx index 7e8616f..efc7778 100644 --- a/client/components/modals/LandFillVehicleEntryModal.tsx +++ b/client/components/modals/LandFillVehicleEntryModal.tsx @@ -35,6 +35,11 @@ import useVehicleReleaseFromSTS from "@/hooks/StsDashboard/useVehicleReleaseFrom import useUpcomingVehicle from "@/hooks/landFillDashboard/useUpcomingVehiclesList"; import useTripComplete from "@/hooks/landFillDashboard/useTripComplete"; +import DatePicker from "react-datepicker"; + +import "react-datepicker/dist/react-datepicker.css"; + + type Vehicle = { tripId: string; weightOfWaste: string; @@ -62,12 +67,22 @@ export const LandfillVehicleEntryModal = ({ const [duration, setDuration] = useState(""); const { TripComplete } = useTripComplete(); + + + const [selectedDateTime, setSelectedDateTime] = useState(new Date()); + +const handleDateChange = (date: Date) => { + setSelectedDateTime(date); +}; + + + const handleSaveChanges = async () => { try { const postEntry = await TripComplete({ tripId: vehicleInfo.tripId, weightOfWaste: weightOfWaste, - entryTime: entryTime, + entryTime: selectedDateTime.toISOString()//entryTime, }); window.location.reload(); @@ -136,13 +151,24 @@ export const LandfillVehicleEntryModal = ({ - setEntryTime(e.target.value)} - /> + /> */} +
+ {/* Other component content */} + +
diff --git a/client/components/modals/ProfileEditModal.tsx b/client/components/modals/ProfileEditModal.tsx new file mode 100644 index 0000000..f98e2e4 --- /dev/null +++ b/client/components/modals/ProfileEditModal.tsx @@ -0,0 +1,158 @@ +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, + DialogClose +} from "@/components/ui/dialog"; + +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import React, { use, useEffect, useState } from "react"; +import { Send, Trash,EditIcon } from "lucide-react"; +import deleteUser from "@/hooks/user_data/deleteUser"; +import { + Select, + SelectTrigger, + SelectValue, + SelectContent, + SelectGroup, + SelectLabel, + SelectItem, +} from "../ui/select"; +import editUser from "@/hooks/user_data/editUser"; +import gettAllRoles from "@/hooks/user_data/useGetAllRole"; +import { number } from "prop-types"; +import { admin, landfillManager, stsManager, unassigned } from "@/data/roles"; +import editSTS from "@/hooks/entityCreation/editSTS"; +import getUserByRole from "@/hooks/user_data/getUserByRole"; +import VehicleRelaseRoute from "../maps/VehicleReleaseRoute"; +import useVehicleReleaseFromSTS from "@/hooks/StsDashboard/useVehicleReleaseFromSTS"; +import useUpcomingVehicle from "@/hooks/landFillDashboard/useUpcomingVehiclesList"; +import useTripComplete from "@/hooks/landFillDashboard/useTripComplete"; +import { profile } from "console"; +import useEditProfileInfo from "@/hooks/user_data/useEditProfileInfo"; +import useGetUserProfile from "@/hooks/user_data/useGetUserProfile"; + + +type User = { + id: string; + username: string; + email: string; + profileName: string; + roleName: string; + roleDescription: string; + +}; + + +export const ProfileEditModal = ({ profileInfo }: { profileInfo: User }) => { + const [profileData, setProfileData] = useState(profileInfo); + + const { user, stsDetails, landfillDetails, getUserDetails} = useGetUserProfile(); + + + const [username , setUsername] = useState(user.username); + const [profilename , setProfilename] = useState(user.profileName); + + const { EditProfileInfo } = useEditProfileInfo(); + + + + + const handleSaveChanges = async () => { + try { + + + const postEntry = await EditProfileInfo({ + username : username, + profileName: profilename + }); + + } catch (error) { + console.error("Error:", error); + } + + + }; + useEffect(() => { + getUserDetails(); + }, []); + + + return ( + + + + + + + + Edit Profile + + +
+

+ Role Name: + {user.roleName} +

+

+ Email: + {user.email} +

+

+ Username: + {user.username} +

+

+ Profile Name: + {user.profileName} +

+ + + +
+
+
+
+
+ + setUsername(e.target.value)} + /> +
+ +
+ + setProfilename(e.target.value)} + /> +
+
+ + + + + +
+
+ ); +}; diff --git a/client/components/modals/STSVehicleReleaseModal.tsx b/client/components/modals/STSVehicleReleaseModal.tsx index c7eb610..d30a650 100644 --- a/client/components/modals/STSVehicleReleaseModal.tsx +++ b/client/components/modals/STSVehicleReleaseModal.tsx @@ -32,7 +32,9 @@ import editSTS from "@/hooks/entityCreation/editSTS"; import getUserByRole from "@/hooks/user_data/getUserByRole"; import VehicleRelaseRoute from "../maps/VehicleReleaseRoute"; import useVehicleReleaseFromSTS from "@/hooks/StsDashboard/useVehicleReleaseFromSTS"; +import DatePicker from "react-datepicker"; +import "react-datepicker/dist/react-datepicker.css"; type Vehicle = { entryId: string, @@ -60,25 +62,12 @@ export const STSVehicleRelease = ({ vehicleInfo }: { vehicleInfo: Vehicle }) => const [distance, setDistance] = useState(""); const [duration, setDuration] = useState("");const { VehicleReleaseFromSTS } = useVehicleReleaseFromSTS(); - - -// const dummyCoordinates[ -// 23.76652752, 90.4258899 -// 23.76449486, 90.3879528 -// 23.73897468, 90.3750954 -// 23.76431111, 90.3651622 -// 23.77393625, 90.3814204 -// 23.76461481, 90.3915441 -// 23.77089053, 90.4042765 -// 23.72965447, 90.3873709 -// ] -// { -// "stsVehicleId": "sv1", -// "weightOfWaste" : 2, -// "exitTime" : "2024-03-27T08:00:00Z", -// "distance": "156.3", -// "estimatedDuration": "23" -// } + const [selectedDateTime, setSelectedDateTime] = useState(new Date()); + + const handleDateChange = (date: Date) => { + setSelectedDateTime(date); + }; + const handleSaveChanges = async () => { @@ -87,7 +76,7 @@ export const STSVehicleRelease = ({ vehicleInfo }: { vehicleInfo: Vehicle }) => const postEntry = await VehicleReleaseFromSTS({ stsVehicleId: vehicleInfo.entryId, weightOfWaste: weightOfWaste, - exitTime: exitTime, + exitTime: selectedDateTime.toISOString(), distance: distance, estimatedDuration: duration }); @@ -165,13 +154,24 @@ export const STSVehicleRelease = ({ vehicleInfo }: { vehicleInfo: Vehicle }) => - setExitTime(e.target.value)} - /> + /> */} +
+ {/* Other component content */} + +
diff --git a/client/components/modals/StsVehicleEntryModal.tsx b/client/components/modals/StsVehicleEntryModal.tsx index 88184ec..f121840 100644 --- a/client/components/modals/StsVehicleEntryModal.tsx +++ b/client/components/modals/StsVehicleEntryModal.tsx @@ -19,6 +19,10 @@ import { getCookie } from '@/lib/cookieFunctions'; import useVehicleEntry from "@/hooks/StsDashboard/useVehicleEntry"; import useVehicleList from "@/hooks/vehicles/useVehiclesData"; +import DatePicker from "react-datepicker"; + +import "react-datepicker/dist/react-datepicker.css"; + interface DialogWrapperProps { children: React.ReactNode; @@ -42,6 +46,12 @@ export const StsVehicleEntryModal: React.FC = ({ callVehcilse(); }, []); + const [selectedDateTime, setSelectedDateTime] = useState(new Date()); + +const handleDateChange = (date: Date) => { + setSelectedDateTime(date); +}; + const handleInputChange = (event: React.ChangeEvent) => { setSearchTerm(event.target.value); @@ -81,7 +91,7 @@ export const StsVehicleEntryModal: React.FC = ({ console.log(vehicleList); const postEntry = await VehicleEntry({ vehicleIds: vehicleId, - entryTimes: entryTime, + entryTimes: selectedDateTime.toISOString(), }); } catch (error) { @@ -134,13 +144,24 @@ export const StsVehicleEntryModal: React.FC = ({ - setEntryTime(e.target.value)} - /> + /> */} +
+ {/* Other component content */} + +
diff --git a/client/components/profile/backgroundComp.tsx b/client/components/profile/backgroundComp.tsx new file mode 100644 index 0000000..47d8518 --- /dev/null +++ b/client/components/profile/backgroundComp.tsx @@ -0,0 +1,17 @@ +// components/BackgroundComponent.tsx +"use client"; + +import React from 'react'; + +const BackgroundComponent: React.FC = () => { + return ( +
+ +
+ ); +}; + +export default BackgroundComponent; diff --git a/client/data/apiRoutes.ts b/client/data/apiRoutes.ts index 7df8625..ad3e4dd 100644 --- a/client/data/apiRoutes.ts +++ b/client/data/apiRoutes.ts @@ -29,6 +29,7 @@ export const apiRoutes = { getAllRecievedVechicleHistory: `${baseUrl}/trips/search?tripStatus=DELIVERED&landfillId=`, }, rbac: { + create: `${baseUrl}/rbac/roles`, getByRole: `${baseUrl}/rbac/roles/get/`, delete: `${baseUrl}/rbac/roles/delete/`, @@ -53,4 +54,8 @@ export const apiRoutes = { makeBill: `${baseUrl}/bills/create-from-trip/`, search: `${baseUrl}/bills/search`, }, + profile: { + getProfile: `${baseUrl}/profile`, + edit: `${baseUrl}/profile`, + } } \ No newline at end of file diff --git a/client/hooks/user_data/useEditProfileInfo.tsx b/client/hooks/user_data/useEditProfileInfo.tsx new file mode 100644 index 0000000..df963f4 --- /dev/null +++ b/client/hooks/user_data/useEditProfileInfo.tsx @@ -0,0 +1,39 @@ +import { useState } from 'react'; +import { setCookie, getCookie } from '@/lib/cookieFunctions'; +import axios from 'axios'; +import { jwtToken, stsId } from '@/data/cookieNames'; // Ensure these variables are properly defined +import { apiRoutes } from '@/data/apiRoutes'; + +export default function useEditProfileInfo() { + async function EditProfileInfo(data: { + username: string; + profileName: string; + }) { + + + try { + const editedProfile = { + username: data.username, + profileName: data.profileName, + }; + + + const res = await axios.put( + apiRoutes.profile.edit, + editedProfile, + { + headers: { Authorization: `Bearer ${getCookie(jwtToken)}` }, + } + ); + + + + return true; + } catch (error: any) { + alert(error.message?.toString() || 'Error Editing'); + return false; + } + } + + return { EditProfileInfo }; +} diff --git a/client/hooks/user_data/useGetAllRole.tsx b/client/hooks/user_data/useGetAllRole.tsx index c6431f7..4e8f8da 100644 --- a/client/hooks/user_data/useGetAllRole.tsx +++ b/client/hooks/user_data/useGetAllRole.tsx @@ -41,7 +41,7 @@ export default function useGetAllRole() { )}; })); await setRoles([unassigned, admin, landfillManager, stsManager]); - console.log(roles); + // console.log(roles); } catch (error: any) { alert("Error fetching roles... Are you authorized?"); console.log(error.message); @@ -49,6 +49,7 @@ export default function useGetAllRole() { } useEffect(() => { + fetchAllRoles(); }, []); diff --git a/client/hooks/user_data/useGetUserProfile.tsx b/client/hooks/user_data/useGetUserProfile.tsx index 5227fbe..a0dd207 100644 --- a/client/hooks/user_data/useGetUserProfile.tsx +++ b/client/hooks/user_data/useGetUserProfile.tsx @@ -1,35 +1,205 @@ + + + import { useState, useEffect } from 'react'; +import axios from 'axios'; +import { apiRoutes } from '@/data/apiRoutes'; // Adjust the import path +import { jwtToken } from '@/data/cookieNames'; // Adjust the import path +import { getCookie } from '@/lib/cookieFunctions'; // Adjust the import path + +type User = { + id: string; + username: string; + email: string; + profileName: string; + roleName: string; + roleDescription: string; + + userCreated: string; + userUpdated: string; + + +}; + +type STSType = { + stsId: string ; + stsName: string; + stsWardNumber: string; + stsCapacity: string; + stsCurrentTotalWaste: string; + stsLatitude: string; + stsLongitude: string; + + roleCreated: string; + roleUpdated: string; +} + +type LandfillType = { + landfillId: string ; + landFillName: string; + landFillCapacity: string; + landFillCurrentWaste: string; + landfillLatitude: string; + landFillLongitude: string; -export default function useGetUserProfile(userId: string) { + roleCreated: string; + roleUpdated: string; +} - const [userData, setUserData] = useState({ - email: "", - role: "", - name: "", - assignedArea: "", +export default function useGetUserProfile() { + const [user, setUser] = useState({ + id: '', + username: '', + email: '', + profileName: '', + roleName: '', + roleDescription: '', + userCreated: '', + userUpdated: '' + }); // Initialize with undefined + const [stsDetails, setStsDetails] = useState({ + stsId: '', + stsName: '', + stsWardNumber: '', + stsCapacity: '', + stsCurrentTotalWaste: '', + stsLatitude: '', + stsLongitude: '', + roleCreated: '', + roleUpdated: '' }); - useEffect(() => { - fetchUser(); - }, []); - - async function fetchUser() { - - setUserData({ - email: userId + "@gmail.com", - role: "STS Manager", - name: "Mehrajul Islam", - assignedArea: "Gulshan-1, Dhaka", - }); - - if (userData) { - // Call the API + const [landfillDetails, setLandfillDetails] = useState({ + landfillId: '', + landFillName: '', + landFillCapacity: '', + landFillCurrentWaste: '', + landfillLatitude: '', + landFillLongitude: '', + roleCreated: '', + roleUpdated: '' + }); + + async function getUserDetails() { + try { + const res = await axios.get(apiRoutes.profile.getProfile, { + headers: { Authorization: `Bearer ${getCookie(jwtToken)}` }, + + }); + // console.log(res.data); + if (res.data.roleName === "STS_MANAGER" ) { + const userDetails: User = { + id: res.data.id, + username: res.data.username, + email: res.data.email, + profileName: res.data.profileName, + roleName: res.data.roleName, + roleDescription: res.data.role.description, + + userCreated: res.data.createdAt, + userUpdated: res.data.updatedAt + + + + }; + + if(res.data.stsId){ + const ResStsDetails: STSType = { + stsId: res.data.sts.id, + stsName: res.data.sts.name, + stsWardNumber: res.data.sts.wardNumber, + stsCapacity: res.data.sts.capacity, + stsCurrentTotalWaste: res.data.sts.currentTotalWaste, + stsLatitude: res.data.sts.latitude, + stsLongitude: res.data.sts.longitude, + + roleCreated: res.data.role.createdAt, + roleUpdated: res.data.role.updatedAt + } + setStsDetails(ResStsDetails); + } + - return userData; - } - - return null; + + setUser(userDetails); + + } else if(res.data.roleName === "LAND_MANAGER" ) { + + const userDetails: User = { + id: res.data.id, + username: res.data.username, + email: res.data.email, + profileName: res.data.profileName, + roleName: res.data.roleName, + roleDescription: res.data.role.description, + + userCreated: res.data.createdAt, + userUpdated: res.data.updatedAt + }; + + if(res.data.landfillId){ + const ResLandDetails: LandfillType = { + + landfillId: res.data.landfill.id, + landFillName: res.data.landfill.name, + landFillCapacity: res.data.landfill.capacity, + landFillCurrentWaste: res.data.landfill.currentTotalWaste, + landfillLatitude: res.data.landfill.latitude, + landFillLongitude: res.data.landfill.longitude, + + roleCreated: res.data.role.createdAt, + roleUpdated: res.data.role.updatedAt + }; + setLandfillDetails(ResLandDetails); + + } + setUser(userDetails); + + }else if(res.data.roleName === "SYSTEM_ADMIN" ) { + + const userDetails: User = { + id: res.data.id, + username: res.data.username, + email: res.data.email, + profileName: res.data.profileName, + roleName: res.data.roleName, + roleDescription: res.data.role.description, + + userCreated: res.data.createdAt, + userUpdated: res.data.updatedAt + }; + + + setUser(userDetails); + + }else{ + const userDetails: User = { + id: res.data.id, + username: res.data.username, + email: res.data.email, + profileName: res.data.profileName, + roleName: res.data.roleName, + roleDescription: res.data.role.description, + + userCreated: res.data.createdAt, + userUpdated: res.data.updatedAt + }; + setUser(userDetails); + + } + + + + } catch (error: any) { + alert(error.message?.toString() || 'Error fetching user profile'); // Updated error message + } } - return {userData}; -} \ No newline at end of file + // useEffect(() => { + // console.log(user); + // console.log(stsDetails); + // console.log(landfillDetails) + // }, [user, stsDetails, landfillDetails]); // Call getUserDetails when the component mounts + + return { user, stsDetails, landfillDetails, getUserDetails }; +} diff --git a/client/package-lock.json b/client/package-lock.json index cedf5da..3210bc0 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -37,6 +37,7 @@ "next-themes": "^0.3.0", "react": "^18", "react-chartjs-2": "^5.2.0", + "react-datepicker": "^6.6.0", "react-dom": "^18", "react-google-recaptcha": "^3.1.0", "react-hook-form": "^7.51.1", @@ -52,6 +53,7 @@ "@hookform/resolvers": "^3.3.4", "@types/node": "^20", "@types/react": "^18", + "@types/react-datepicker": "^6.2.0", "@types/react-dom": "^18", "@types/react-google-recaptcha": "^2.1.9", "autoprefixer": "^10.0.1", @@ -1625,6 +1627,20 @@ "@floating-ui/utils": "^0.2.0" } }, + "node_modules/@floating-ui/react": { + "version": "0.26.10", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.10.tgz", + "integrity": "sha512-sh6f9gVvWQdEzLObrWbJ97c0clJObiALsFe0LiR/kb3tDRKwEhObASEH2QyfdoO/ZBPzwxa9j+nYFo+sqgbioA==", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@floating-ui/utils": "^0.2.0", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, "node_modules/@floating-ui/react-dom": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.8.tgz", @@ -2962,6 +2978,17 @@ "csstype": "^3.0.2" } }, + "node_modules/@types/react-datepicker": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@types/react-datepicker/-/react-datepicker-6.2.0.tgz", + "integrity": "sha512-+JtO4Fm97WLkJTH8j8/v3Ldh7JCNRwjMYjRaKh4KHH0M3jJoXtwiD3JBCsdlg3tsFIw9eQSqyAPeVDN2H2oM9Q==", + "dev": true, + "dependencies": { + "@floating-ui/react": "^0.26.2", + "@types/react": "*", + "date-fns": "^3.3.1" + } + }, "node_modules/@types/react-dom": { "version": "18.2.22", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.22.tgz", @@ -3925,6 +3952,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/date-fns": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, "node_modules/dayjs": { "version": "1.11.10", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", @@ -6731,6 +6767,22 @@ "react": "^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-datepicker": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-6.6.0.tgz", + "integrity": "sha512-ERC0/Q4pPC9bNIcGUpdCbHc+oCxhkU3WI3UOGHkyJ3A9fqALCYpEmLc5S5xvAd7DuCDdbsyW97oRPM6pWWwjww==", + "dependencies": { + "@floating-ui/react": "^0.26.2", + "clsx": "^2.1.0", + "date-fns": "^3.3.1", + "prop-types": "^15.7.2", + "react-onclickoutside": "^6.13.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17 || ^18", + "react-dom": "^16.9.0 || ^17 || ^18" + } + }, "node_modules/react-dom": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", @@ -6810,6 +6862,19 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/react-onclickoutside": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.13.0.tgz", + "integrity": "sha512-ty8So6tcUpIb+ZE+1HAhbLROvAIJYyJe/1vRrrcmW+jLsaM+/powDRqxzo6hSh9CuRZGSL1Q8mvcF5WRD93a0A==", + "funding": { + "type": "individual", + "url": "https://github.com/Pomax/react-onclickoutside/blob/master/FUNDING.md" + }, + "peerDependencies": { + "react": "^15.5.x || ^16.x || ^17.x || ^18.x", + "react-dom": "^15.5.x || ^16.x || ^17.x || ^18.x" + } + }, "node_modules/react-remove-scroll": { "version": "2.5.5", "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz", @@ -7560,6 +7625,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==" + }, "node_modules/tailwind-merge": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.2.2.tgz", diff --git a/client/package.json b/client/package.json index 5a99c45..e968cba 100644 --- a/client/package.json +++ b/client/package.json @@ -38,6 +38,7 @@ "next-themes": "^0.3.0", "react": "^18", "react-chartjs-2": "^5.2.0", + "react-datepicker": "^6.6.0", "react-dom": "^18", "react-google-recaptcha": "^3.1.0", "react-hook-form": "^7.51.1", @@ -53,6 +54,7 @@ "@hookform/resolvers": "^3.3.4", "@types/node": "^20", "@types/react": "^18", + "@types/react-datepicker": "^6.2.0", "@types/react-dom": "^18", "@types/react-google-recaptcha": "^2.1.9", "autoprefixer": "^10.0.1", diff --git a/client/public/profileBack.png b/client/public/profileBack.png new file mode 100644 index 0000000..2889ec5 Binary files /dev/null and b/client/public/profileBack.png differ diff --git a/server/src/controllers/auth.ts b/server/src/controllers/auth.ts index c59a828..e17f06b 100644 --- a/server/src/controllers/auth.ts +++ b/server/src/controllers/auth.ts @@ -7,7 +7,7 @@ import { getToken, invalidateToken, verifyToken, -} from "../services/token"; +} from "../services/Token"; import CustomError from "../services/CustomError"; import { randomOTPGenerator, randomPasswordGenerator } from "../services/utils"; import { sendMail, sendOTPMail } from "../services/mailService"; diff --git a/server/src/controllers/profile.ts b/server/src/controllers/profile.ts index c0b62de..5ccc7de 100644 --- a/server/src/controllers/profile.ts +++ b/server/src/controllers/profile.ts @@ -2,7 +2,7 @@ import errorWrapper from "../middlewares/errorWrapper"; import { PrismaClient, User } from "@prisma/client"; import { Request, Response } from "express"; import CustomError from "../services/CustomError"; -import { getToken, verifyToken } from "../services/token"; +import { getToken, verifyToken } from "../services/Token"; const prisma = new PrismaClient(); @@ -15,6 +15,8 @@ const getUserById = errorWrapper( }, include: { role: true, + sts: true, + landfill: true }, }); diff --git a/server/src/middlewares/auth.ts b/server/src/middlewares/auth.ts index 86a2009..5eea6b4 100644 --- a/server/src/middlewares/auth.ts +++ b/server/src/middlewares/auth.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import errorWrapper from "./errorWrapper"; import CustomError from "../services/CustomError"; -import { getToken, verifyToken } from "../services/token"; +import { getToken, verifyToken } from "../services/Token"; const authChecker = errorWrapper( async (req: Request, res: Response, next: NextFunction) => { diff --git a/server/src/prisma/seed.ts b/server/src/prisma/seed.ts index d53ed54..3c51b28 100644 --- a/server/src/prisma/seed.ts +++ b/server/src/prisma/seed.ts @@ -375,7 +375,7 @@ const stsData: Prisma.STSCreateInput[] = [ }, { id: "sts6", - name: "Motijheel", + name: "Motijheel STS", wardNumber: "4", capacity: 1500, currentTotalWaste: 1400,