From e7080ff557233b6156d62836bd12c5a81168dc2c Mon Sep 17 00:00:00 2001 From: shawon-majid Date: Wed, 27 Mar 2024 16:30:21 +0600 Subject: [PATCH 1/6] land fill managers api and trip apis completed --- server/src/controllers/trip.ts | 67 ++++++++++++++++++++++++++++++- server/src/controllers/vehicle.ts | 28 +++++++++++++ server/src/prisma/schema.prisma | 1 + server/src/prisma/seed.ts | 9 +++++ server/src/routes/trip.ts | 4 +- server/src/routes/vehicles.ts | 2 + 6 files changed, 108 insertions(+), 3 deletions(-) diff --git a/server/src/controllers/trip.ts b/server/src/controllers/trip.ts index 2f72086..ab24ec9 100644 --- a/server/src/controllers/trip.ts +++ b/server/src/controllers/trip.ts @@ -1,6 +1,6 @@ import { Request, Response } from "express"; import errorWrapper from "../middlewares/errorWrapper"; -import { addTrip } from "../services/tripServices"; +import { addTrip, getTripById } from "../services/tripServices"; import { Prisma, Trip } from "@prisma/client"; import { PrismaClient } from "@prisma/client"; import CustomError from "../services/CustomError"; @@ -23,6 +23,16 @@ const createTrip = errorWrapper(async (req: Request, res: Response) => { throw new CustomError("No such Vehicle entry found", 404); } + await prisma.sTSVehicleEntry.update({ + where: { + id: stsVehicleId, + }, + data: { + exitTime, + weightOfWaste, + }, + }); + const vehicle = stsVehicleInfo.vehicle; const sts = stsVehicleInfo.sts; @@ -48,4 +58,57 @@ const createTrip = errorWrapper(async (req: Request, res: Response) => { res.status(201).json(newTrip); }); -export { createTrip }; +const getListOfTrips = errorWrapper(async (req: Request, res: Response) => { + const { tripStatus } = req.query; + + let where: Prisma.TripWhereInput | undefined = undefined; + + if (tripStatus) { + where = { + tripStatus: tripStatus as string, + }; + } + + const trips = await prisma.trip.findMany({ + where, + }); + res.json(trips); +}); + +const completeTrip = errorWrapper(async (req: Request, res: Response) => { + const { tripId, landfillId, vehicleId, weightOfWaste, entryTime } = req.body; + + prisma.landfillVehicleEntry.create({ + data: { + landfillId, + vehicleId, + weightOfWaste, + entryTime, + }, + }); + + const trip = await getTripById(tripId); + + if (!trip) { + throw new CustomError("No such trip found", 404); + } + + const shortage = Number(trip.weightOfWaste) - weightOfWaste; + + // calculate actual duration + + const completedTrip = await prisma.trip.update({ + where: { + id: tripId, + }, + data: { + tripStatus: "COMPLETED", + weightOfWaste, + shortage, + }, + }); + + res.json(completedTrip); +}); + +export { createTrip, getListOfTrips, completeTrip }; diff --git a/server/src/controllers/vehicle.ts b/server/src/controllers/vehicle.ts index 89e6db8..e47eae0 100644 --- a/server/src/controllers/vehicle.ts +++ b/server/src/controllers/vehicle.ts @@ -1,3 +1,4 @@ +import { Prisma } from "./../../node_modules/.prisma/client/index.d"; import { PrismaClient, Vehicle } from "@prisma/client"; import { Request, Response } from "express"; import errorWrapper from "../middlewares/errorWrapper"; @@ -63,10 +64,37 @@ const removeVehicle = errorWrapper( { statusCode: 500, message: "Couldn't delete vehicle" } ); +const getVehiclesOnQuery = errorWrapper(async (req: Request, res: Response) => { + const { landFillId, vehicleType, vehicleNumber } = req.query; + + let where: Prisma.VehicleWhereInput | undefined = undefined; + if (landFillId || vehicleType || vehicleNumber) { + where = {}; + if (landFillId) { + where.landFillId = landFillId as string; + } + + if (vehicleType) { + where.vehicleType = vehicleType as string; + } + + if (vehicleNumber) { + where.vehicleNumber = vehicleNumber as string; + } + } + + const vehicles = await prisma.vehicle.findMany({ + where, + }); + + res.json(vehicles); +}); + export { createVehicle, fetchAllVehicles, fetchVehicleById, editVehicle, removeVehicle, + getVehiclesOnQuery, }; diff --git a/server/src/prisma/schema.prisma b/server/src/prisma/schema.prisma index 46fd547..f86f1bb 100644 --- a/server/src/prisma/schema.prisma +++ b/server/src/prisma/schema.prisma @@ -177,6 +177,7 @@ model Trip { vehicleId String weightOfWaste Decimal? + shortage Decimal? estimatedFuelCost Decimal? distance Decimal? diff --git a/server/src/prisma/seed.ts b/server/src/prisma/seed.ts index 2ae36e4..76b0691 100644 --- a/server/src/prisma/seed.ts +++ b/server/src/prisma/seed.ts @@ -332,6 +332,15 @@ async function main() { console.log(newStsVehicleEntry); } + console.log("Seeding trips..."); + + for (const trip of tripData) { + const newTrip = await prisma.trip.create({ + data: trip, + }); + console.log(newTrip); + } + console.log("Seeding completed!"); } diff --git a/server/src/routes/trip.ts b/server/src/routes/trip.ts index 8ae05b1..d296fc5 100644 --- a/server/src/routes/trip.ts +++ b/server/src/routes/trip.ts @@ -1,7 +1,9 @@ import express from "express"; -import { createTrip } from "../controllers/trip"; +import { completeTrip, createTrip, getListOfTrips } from "../controllers/trip"; const router = express.Router(); router.route("/create").post(createTrip); +router.route("/search").get(getListOfTrips); +router.route("/complete").post(completeTrip); export default router; diff --git a/server/src/routes/vehicles.ts b/server/src/routes/vehicles.ts index 93d6a47..f9839af 100644 --- a/server/src/routes/vehicles.ts +++ b/server/src/routes/vehicles.ts @@ -4,12 +4,14 @@ import { editVehicle, fetchAllVehicles, fetchVehicleById, + getVehiclesOnQuery, removeVehicle, } from "../controllers/vehicle"; const router = express.Router(); router.route("/create").post(createVehicle); +router.route("/search").get(getVehiclesOnQuery); router.route("/").get(fetchAllVehicles); router.route("/:vehicleId").get(fetchVehicleById); router.route("/:vehicleId").put(editVehicle); From 837a9c571991bc913a82d7f42c48e46a1f2d1cbc Mon Sep 17 00:00:00 2001 From: nafi-ullah Date: Wed, 27 Mar 2024 18:53:16 +0600 Subject: [PATCH 2/6] getting vehicle from db --- .../modals/StsVehicleEntryModal.tsx | 35 +++++++------ client/data/constant.tsx | 1 + client/hooks/StsDashboard/useVehicleEntry.tsx | 49 ++++++++----------- client/hooks/vehicles/useVehiclesData.tsx | 49 +++++++++++++++++++ server/src/controllers/auth.ts | 2 +- server/src/controllers/profile.ts | 2 +- server/src/middlewares/auth.ts | 2 +- 7 files changed, 92 insertions(+), 48 deletions(-) create mode 100644 client/data/constant.tsx create mode 100644 client/hooks/vehicles/useVehiclesData.tsx diff --git a/client/components/modals/StsVehicleEntryModal.tsx b/client/components/modals/StsVehicleEntryModal.tsx index 22f0d9f..8424259 100644 --- a/client/components/modals/StsVehicleEntryModal.tsx +++ b/client/components/modals/StsVehicleEntryModal.tsx @@ -1,3 +1,4 @@ +"use client"; import { Button } from "@/components/ui/button"; import { Dialog, @@ -15,7 +16,9 @@ import { Label } from "@/components/ui/label"; import React , {useState, useEffect} from "react"; import { getCookie } from '@/lib/cookieFunctions'; -import { jwtToken, role, uid } from '@/data/cookieNames'; +import useVehicleEntry from "@/hooks/StsDashboard/useVehicleEntry"; +import useVehicleList from "@/hooks/vehicles/useVehiclesData"; + interface DialogWrapperProps { children: React.ReactNode; @@ -24,29 +27,29 @@ interface DialogWrapperProps { export const StsVehicleEntryModal: React.FC = ({ children, }) => { + const { entryTime, setEntryTime,vehicleId, setVehicleId, VehicleEntry } = useVehicleEntry(); + const { vehicleList, vehicleNumberList, getVehicleList } = useVehicleList(); + const [weightOfWaste, setWeightOfWaste] = useState(""); - const [entryTime, setEntryTime] = useState(new Date().toLocaleString()); + const callVehcilse = async () => { + const sucess = await getVehicleList(); + }; + + useEffect(() => { + callVehcilse(); + }, []); - const token = getCookie(jwtToken); - const userRole = getCookie(role); - const userId = getCookie(uid); + - // useEffect(() => { - // const intervalId = setInterval(() => { - // setEntryTime(new Date().toLocaleString()); - // }, 1000); - // return () => clearInterval(intervalId); - // }, []); - - const handleSaveChanges = () => { + const handleSaveChanges = async () => { + console.log("Vehicle Number:", weightOfWaste); console.log("Vehicle Number:", entryTime); - console.log("Token:", token); - console.log("User Role:", userRole); - console.log("User ID:", userId); + console.log(vehicleList); + console.log(vehicleNumberList); }; diff --git a/client/data/constant.tsx b/client/data/constant.tsx new file mode 100644 index 0000000..6384f8d --- /dev/null +++ b/client/data/constant.tsx @@ -0,0 +1 @@ +export const uri = "http://localhost:8585"; \ No newline at end of file diff --git a/client/hooks/StsDashboard/useVehicleEntry.tsx b/client/hooks/StsDashboard/useVehicleEntry.tsx index db76aaa..c476831 100644 --- a/client/hooks/StsDashboard/useVehicleEntry.tsx +++ b/client/hooks/StsDashboard/useVehicleEntry.tsx @@ -2,41 +2,32 @@ import { useState } from 'react'; import {admin, landfillManager, stsManager, unassigned} from '@/data/roles'; import { setCookie, getCookie } from '@/lib/cookieFunctions'; import axios from 'axios'; -import { jwtToken, role , uid , stsId, username} from '@/data/cookieNames'; +import { jwtToken, role , uid , username, stsId} from '@/data/cookieNames'; +import { uri } from '@/data/constant'; export default function useVehicleEntry() { - const [loginData, setloginData] = useState({ - email: "", - password: "", - }); - - async function login() { + const [entryTime, setEntryTime] = useState(new Date().toLocaleString()); + const [vehicleId, setVehicleId] = useState(""); + + async function VehicleEntry() { + const userStsId = getCookie(stsId); - if (loginData) { - // Call the login API - const res = await axios.post('http://localhost:8585/auth/login', { - email: loginData.email, - password: loginData.password - }) - // res.data.user.roleName.startsWith(admin) ? setCookie(role, admin, 1) : - // res.data.user.roleName.startsWith(landfillManager) ? setCookie(role, landfillManager, 1) : - // res.data.user.roleName.startsWith(stsManager) ? setCookie(role, stsManager, 1) : - // res.data.user.roleName.startsWith(unassigned) ? setCookie(role, unassigned, 1) : - // setCookie(role, res.data.user.roleName , 1); - // setCookie(uid, res.data.user.id ,1 ); - // setCookie(jwtToken, res.data.token , 1); - // setCookie(stsId, res.data.stsId, 1); - // setCookie(username, res.data.username, 1); + try { + const res = await axios.post('http://localhost:8585/sts-entry/create', { + stsId : userStsId, + vehicleId: vehicleId, + entryTime: entryTime + }); + //use the response from here - console.log(res); - return true; - } - + return true; + } catch (error: any) { + alert(error.message?.toString() || "error logging in"); + return false; + } - alert("Invalid credentials!"); - return false; } - return {loginData, setloginData, login}; + return {entryTime, setEntryTime,vehicleId, setVehicleId, VehicleEntry}; } \ No newline at end of file diff --git a/client/hooks/vehicles/useVehiclesData.tsx b/client/hooks/vehicles/useVehiclesData.tsx new file mode 100644 index 0000000..8e6d33e --- /dev/null +++ b/client/hooks/vehicles/useVehiclesData.tsx @@ -0,0 +1,49 @@ +import { useState } from 'react'; +import axios from 'axios'; +import { uri } from '@/data/constant'; + +type Vehicle = { + id: string; + vehicleNumber: string; + vehicleType: string; + capacity: number; + loadedFuelCostPerKm: number; + unloadedFuelCostPerKm: number; + landFillId: string; + createdAt: string; + updatedAt: string; +}; + +export default function useVehicleList() { + const [vehicleList, setVehicleList] = useState([]); // Initialize with an empty array of Vehicle objects + const [vehicleNumberList, setVehicleNumberList] = useState([]); + + async function getVehicleList() { + try { + const res = await axios.get('http://localhost:8585/vehicles'); + // Assuming the response data is an array of vehicles + const AllVehicle: Vehicle[] = res.data.map((vehicle: any) => ({ + id: vehicle.id, + vehicleNumber: vehicle.vehicleNumber, + vehicleType: vehicle.vehicleType, + capacity: vehicle.capacity, + loadedFuelCostPerKm: vehicle.loadedFuelCostPerKm, + unloadedFuelCostPerKm: vehicle.unloadedFuelCostPerKm, + landFillId: vehicle.landFillId, + createdAt: vehicle.createdAt, + updatedAt: vehicle.updatedAt + })); + const vehicleNumbers = res.data.map((vehicle: Vehicle) => vehicle.vehicleNumber); + + setVehicleList(AllVehicle); + setVehicleNumberList(vehicleNumbers); + + return true; + } catch (error: any) { + alert(error.message?.toString() || "Error fetching vehicle list"); + return false; + } + } + + return { vehicleList, vehicleNumberList, getVehicleList }; +} diff --git a/server/src/controllers/auth.ts b/server/src/controllers/auth.ts index 956d754..3487057 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..38661a9 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(); 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) => { From bb4100f69a37f6caeab314cc4452d9d1c12d7f80 Mon Sep 17 00:00:00 2001 From: shawon-majid Date: Wed, 27 Mar 2024 23:25:35 +0600 Subject: [PATCH 3/6] included land fill information with vehicle ion get current sts entry api --- server/src/controllers/stsVehicle.ts | 6 +++++- server/src/prisma/schema.prisma | 6 ++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/server/src/controllers/stsVehicle.ts b/server/src/controllers/stsVehicle.ts index af28509..0d8ab13 100644 --- a/server/src/controllers/stsVehicle.ts +++ b/server/src/controllers/stsVehicle.ts @@ -72,7 +72,11 @@ const getCurrentVehiclesInSTS = errorWrapper( }, include: { sts: true, - vehicle: true, + vehicle: { + include: { + landFill: true, + }, + }, }, }); diff --git a/server/src/prisma/schema.prisma b/server/src/prisma/schema.prisma index f86f1bb..d0bacc3 100644 --- a/server/src/prisma/schema.prisma +++ b/server/src/prisma/schema.prisma @@ -64,12 +64,14 @@ model RolePermission { } model Vehicle { - id String @id @default(uuid()) - vehicleNumber String @unique + id String @id @default(uuid()) + vehicleNumber String @unique vehicleType String capacity Decimal loadedFuelCostPerKm Decimal unloadedFuelCostPerKm Decimal + currentLatitude Decimal? + currentLongitude Decimal? landFill Landfill @relation(fields: [landFillId], references: [id]) landFillId String From a5c63448e5e3c7f85dd4b5ddd5b196676422aa99 Mon Sep 17 00:00:00 2001 From: nafi-ullah Date: Wed, 27 Mar 2024 23:42:26 +0600 Subject: [PATCH 4/6] vehicle name updated --- .../components/dataTables/StsVehicleList.tsx | 316 ++++++++++++++++++ .../modals/StsVehicleEntryModal.tsx | 84 ++++- client/hooks/StsDashboard/useVehicleEntry.tsx | 15 +- client/hooks/vehicles/useGetStsVehicles.tsx | 72 ++++ server/src/controllers/stsVehicle.ts | 7 +- 5 files changed, 472 insertions(+), 22 deletions(-) create mode 100644 client/components/dataTables/StsVehicleList.tsx create mode 100644 client/hooks/vehicles/useGetStsVehicles.tsx diff --git a/client/components/dataTables/StsVehicleList.tsx b/client/components/dataTables/StsVehicleList.tsx new file mode 100644 index 0000000..dcd1b7c --- /dev/null +++ b/client/components/dataTables/StsVehicleList.tsx @@ -0,0 +1,316 @@ +"use client" + +import * as React from "react" +import { + CaretSortIcon, + ChevronDownIcon, + DotsHorizontalIcon, +} from "@radix-ui/react-icons" +import { + ColumnDef, + ColumnFiltersState, + SortingState, + VisibilityState, + flexRender, + getCoreRowModel, + getFilteredRowModel, + getPaginationRowModel, + getSortedRowModel, + useReactTable, +} from "@tanstack/react-table" + +import { Button } from "@/components/ui/button" +import { Checkbox } from "@/components/ui/checkbox" +import { + DropdownMenu, + DropdownMenuCheckboxItem, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" +import { Input } from "@/components/ui/input" +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table" + +const data: Payment[] = [ + { + id: "m5gr84i9", + amount: 316, + status: "success", + email: "ken99@yahoo.com", + }, + { + id: "3u1reuv4", + amount: 242, + status: "success", + email: "Abe45@gmail.com", + }, + { + id: "derv1ws0", + amount: 837, + status: "processing", + email: "Monserrat44@gmail.com", + }, + { + id: "5kma53ae", + amount: 874, + status: "success", + email: "Silas22@gmail.com", + }, + { + id: "bhqecj4p", + amount: 721, + status: "failed", + email: "carmella@hotmail.com", + }, +] + +export type Payment = { + id: string + amount: number + status: "pending" | "processing" | "success" | "failed" + email: string +} + +export const columns: ColumnDef[] = [ + { + id: "select", + header: ({ table }) => ( + table.toggleAllPageRowsSelected(!!value)} + aria-label="Select all" + /> + ), + cell: ({ row }) => ( + row.toggleSelected(!!value)} + aria-label="Select row" + /> + ), + enableSorting: false, + enableHiding: false, + }, + { + accessorKey: "status", + header: "Status", + cell: ({ row }) => ( +
{row.getValue("status")}
+ ), + }, + { + accessorKey: "email", + header: ({ column }) => { + return ( + + ) + }, + cell: ({ row }) =>
{row.getValue("email")}
, + }, + { + accessorKey: "amount", + header: () =>
Amount
, + cell: ({ row }) => { + const amount = parseFloat(row.getValue("amount")) + + // Format the amount as a dollar amount + const formatted = new Intl.NumberFormat("en-US", { + style: "currency", + currency: "USD", + }).format(amount) + + return
{formatted}
+ }, + }, + { + id: "actions", + enableHiding: false, + cell: ({ row }) => { + const payment = row.original + + return ( + + + + + + Actions + navigator.clipboard.writeText(payment.id)} + > + Copy payment ID + + + View customer + View payment details + + + ) + }, + }, +] + +export function StsVehicleTable() { + const [sorting, setSorting] = React.useState([]) + const [columnFilters, setColumnFilters] = React.useState( + [] + ) + const [columnVisibility, setColumnVisibility] = + React.useState({}) + const [rowSelection, setRowSelection] = React.useState({}) + + const table = useReactTable({ + data, + columns, + onSortingChange: setSorting, + onColumnFiltersChange: setColumnFilters, + getCoreRowModel: getCoreRowModel(), + getPaginationRowModel: getPaginationRowModel(), + getSortedRowModel: getSortedRowModel(), + getFilteredRowModel: getFilteredRowModel(), + onColumnVisibilityChange: setColumnVisibility, + onRowSelectionChange: setRowSelection, + state: { + sorting, + columnFilters, + columnVisibility, + rowSelection, + }, + }) + + return ( +
+
+ + table.getColumn("email")?.setFilterValue(event.target.value) + } + className="max-w-sm" + /> + + + + + + {table + .getAllColumns() + .filter((column) => column.getCanHide()) + .map((column) => { + return ( + + column.toggleVisibility(!!value) + } + > + {column.id} + + ) + })} + + +
+
+ + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => { + return ( + + {header.isPlaceholder + ? null + : flexRender( + header.column.columnDef.header, + header.getContext() + )} + + ) + })} + + ))} + + + {table.getRowModel().rows?.length ? ( + table.getRowModel().rows.map((row) => ( + + {row.getVisibleCells().map((cell) => ( + + {flexRender( + cell.column.columnDef.cell, + cell.getContext() + )} + + ))} + + )) + ) : ( + + + No results. + + + )} + +
+
+
+
+ {table.getFilteredSelectedRowModel().rows.length} of{" "} + {table.getFilteredRowModel().rows.length} row(s) selected. +
+
+ + +
+
+
+ ) +} diff --git a/client/components/modals/StsVehicleEntryModal.tsx b/client/components/modals/StsVehicleEntryModal.tsx index 8424259..8b4767d 100644 --- a/client/components/modals/StsVehicleEntryModal.tsx +++ b/client/components/modals/StsVehicleEntryModal.tsx @@ -27,8 +27,11 @@ interface DialogWrapperProps { export const StsVehicleEntryModal: React.FC = ({ children, }) => { - const { entryTime, setEntryTime,vehicleId, setVehicleId, VehicleEntry } = useVehicleEntry(); + const { entryTime,setEntryTime, vehicleId, setVehicleId, VehicleEntry } = useVehicleEntry(); const { vehicleList, vehicleNumberList, getVehicleList } = useVehicleList(); + + const [searchTerm, setSearchTerm] = useState(""); + const [showSuggestions, setShowSuggestions] = useState(false); const [weightOfWaste, setWeightOfWaste] = useState(""); const callVehcilse = async () => { @@ -40,17 +43,52 @@ export const StsVehicleEntryModal: React.FC = ({ }, []); + const handleInputChange = (event: React.ChangeEvent) => { + setSearchTerm(event.target.value); + setShowSuggestions(true); + }; + const handleSuggestionClick = (suggestion: string) => { + setSearchTerm(suggestion); + setShowSuggestions(false); + }; + const filteredSuggestions = vehicleNumberList.filter((suggestion) => + suggestion.toString().toLowerCase().includes(searchTerm.toString().toLowerCase()) + ); + const getVehicleIdByNumber = (vehicleNumber: string): string | undefined => { + const vehicle = vehicleList.find(vehicle => vehicle.vehicleNumber === vehicleNumber); + if (vehicle) { + return vehicle.id.toString(); + } + + // If vehicle is not found, return undefined + return "no vehicle"; +}; + + const handleSaveChanges = async () => { + setVehicleId(searchTerm); + - console.log("Vehicle Number:", weightOfWaste); - console.log("Vehicle Number:", entryTime); - console.log(vehicleList); - console.log(vehicleNumberList); + // console.log(vehicleId); + //console.log(entryTime); + const vehicleId = getVehicleIdByNumber(searchTerm); + + try { + console.log(vehicleList); + const postEntry = await VehicleEntry({ + vehicleIds: vehicleId, + entryTimes: entryTime, + }); + + } catch (error) { + console.error("Error:", error); + } }; + return ( @@ -67,18 +105,30 @@ export const StsVehicleEntryModal: React.FC = ({
-
-
+ +
diff --git a/client/hooks/StsDashboard/useVehicleEntry.tsx b/client/hooks/StsDashboard/useVehicleEntry.tsx index c476831..bc9cc78 100644 --- a/client/hooks/StsDashboard/useVehicleEntry.tsx +++ b/client/hooks/StsDashboard/useVehicleEntry.tsx @@ -8,18 +8,23 @@ import { uri } from '@/data/constant'; export default function useVehicleEntry() { const [entryTime, setEntryTime] = useState(new Date().toLocaleString()); - const [vehicleId, setVehicleId] = useState(""); + const [vehicleId, setVehicleId] = useState("Default"); - async function VehicleEntry() { + async function VehicleEntry(data: { vehicleIds: string; entryTimes: string }) { const userStsId = getCookie(stsId); + // console.log(stsId); + console.log(data.vehicleIds); + console.log(data.entryTimes); try { + const isoString = new Date(data.entryTimes).toISOString(); const res = await axios.post('http://localhost:8585/sts-entry/create', { - stsId : userStsId, - vehicleId: vehicleId, - entryTime: entryTime + stsId : "sts1", + vehicleId: data.vehicleIds, + entryTime: isoString }); //use the response from here + console.log(res.data); return true; } catch (error: any) { diff --git a/client/hooks/vehicles/useGetStsVehicles.tsx b/client/hooks/vehicles/useGetStsVehicles.tsx new file mode 100644 index 0000000..b995129 --- /dev/null +++ b/client/hooks/vehicles/useGetStsVehicles.tsx @@ -0,0 +1,72 @@ +import { useState } from 'react'; +import axios from 'axios'; +import { uri } from '@/data/constant'; + +interface StsEntryDataType { + id: string; + stsId: string; + vehicleId: string; + weightOfWaste: number | null; + entryTime: string; + exitTime: string | null; + createdAt: string; + updatedAt: string; + sts: { + id: string; + name: string; + wardNumber: string; + capacity: string; + currentTotalWaste: number | null; + latitude: string; + longitude: string; + createdAt: string; + updatedAt: string; + }; + vehicle: { + id: string; + vehicleNumber: string; + vehicleType: string; + capacity: string; + loadedFuelCostPerKm: string; + unloadedFuelCostPerKm: string; + landFillId: string | null; + createdAt: string; + updatedAt: string; + }; + } + + +type Vehicle = { + id: string; + vehicleNumber: string; + vehicleType: string; + capacity: number; + loadedFuelCostPerKm: number; + unloadedFuelCostPerKm: number; + landFillId: string; + createdAt: string; + updatedAt: string; + }; + +export default function useGetStsVehicles() { + const [vehicleList, setVehicleList] = useState([]); // Initialize with an empty array of Vehicle objects + + async function getVehicleList() { + try { + const res = await axios.get('http://localhost:8585/sts-entry/sts1/get-current-vehicles'); + + const StsVehicles = res.data.map((vehicle: StsEntryDataType) => vehicle.vehicle); + + //setVehicleList(AllVehicle); + setVehicleList(StsVehicles); + console.log(vehicleList); + + return true; + } catch (error: any) { + alert(error.message?.toString() || "Error fetching vehicle list"); + return false; + } + } + + return { vehicleList, useGetStsVehicles }; +} diff --git a/server/src/controllers/stsVehicle.ts b/server/src/controllers/stsVehicle.ts index af28509..cf406c5 100644 --- a/server/src/controllers/stsVehicle.ts +++ b/server/src/controllers/stsVehicle.ts @@ -94,7 +94,12 @@ const getLeftVehiclesInSTS = errorWrapper( }, include: { sts: true, - vehicle: true, + vehicle: { + include:{ + landFill: true + + } + }, }, }); From 8d504115d74ffef95fc530c4bd07fd13e7e564ec Mon Sep 17 00:00:00 2001 From: nafi-ullah Date: Wed, 27 Mar 2024 23:49:29 +0600 Subject: [PATCH 5/6] new schedules --- .../mainContent/stsManagerContents/Schedules.tsx | 2 ++ client/hooks/StsDashboard/useVehicleEntry.tsx | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/client/components/dashboard-componenets/mainContent/stsManagerContents/Schedules.tsx b/client/components/dashboard-componenets/mainContent/stsManagerContents/Schedules.tsx index 7673f3d..75ae87f 100644 --- a/client/components/dashboard-componenets/mainContent/stsManagerContents/Schedules.tsx +++ b/client/components/dashboard-componenets/mainContent/stsManagerContents/Schedules.tsx @@ -2,6 +2,7 @@ import EmptyFillContainer from "../../cards/EmptyFillContainer"; import { ChakraProvider, theme } from "@chakra-ui/react"; import OptimizedRouteMap from "@/components/maps/OptimizedRoute"; import RouteMap from "@/components/maps/RouteMap"; +import { StsVehicleTable } from "@/components/dataTables/StsVehicleList"; export default function STSManagerSchedules() { return ( @@ -11,6 +12,7 @@ export default function STSManagerSchedules() {
UPCOMING - CRITICAL FIRST SCHEDULES +
{/*
diff --git a/client/hooks/StsDashboard/useVehicleEntry.tsx b/client/hooks/StsDashboard/useVehicleEntry.tsx index bc9cc78..415023b 100644 --- a/client/hooks/StsDashboard/useVehicleEntry.tsx +++ b/client/hooks/StsDashboard/useVehicleEntry.tsx @@ -10,7 +10,7 @@ export default function useVehicleEntry() { const [entryTime, setEntryTime] = useState(new Date().toLocaleString()); const [vehicleId, setVehicleId] = useState("Default"); - async function VehicleEntry(data: { vehicleIds: string; entryTimes: string }) { + async function VehicleEntry(data: { vehicleIds: string | undefined; entryTimes: string }) { const userStsId = getCookie(stsId); // console.log(stsId); console.log(data.vehicleIds); From dc8eace922956761c56e306ea1b2bc35912427db Mon Sep 17 00:00:00 2001 From: codermehraj Date: Thu, 28 Mar 2024 00:50:21 +0600 Subject: [PATCH 6/6] STS Entered vehicle showed and delete functionality added --- .../stsManagerContents/Schedules.tsx | 4 +- .../components/dataTables/StsVehicleList.tsx | 267 +++++++++--------- .../modals/DeleteVehicleModalForSTS.tsx | 105 +++++++ client/data/apiRoutes.ts | 3 + .../deleteVehicleEntryFromSTS.tsx | 23 ++ client/hooks/vehicles/useGetVeicleForSTS.tsx | 59 ++++ 6 files changed, 329 insertions(+), 132 deletions(-) create mode 100644 client/components/modals/DeleteVehicleModalForSTS.tsx create mode 100644 client/hooks/StsDashboard/deleteVehicleEntryFromSTS.tsx create mode 100644 client/hooks/vehicles/useGetVeicleForSTS.tsx diff --git a/client/components/dashboard-componenets/mainContent/stsManagerContents/Schedules.tsx b/client/components/dashboard-componenets/mainContent/stsManagerContents/Schedules.tsx index 75ae87f..0c02f1f 100644 --- a/client/components/dashboard-componenets/mainContent/stsManagerContents/Schedules.tsx +++ b/client/components/dashboard-componenets/mainContent/stsManagerContents/Schedules.tsx @@ -2,7 +2,7 @@ import EmptyFillContainer from "../../cards/EmptyFillContainer"; import { ChakraProvider, theme } from "@chakra-ui/react"; import OptimizedRouteMap from "@/components/maps/OptimizedRoute"; import RouteMap from "@/components/maps/RouteMap"; -import { StsVehicleTable } from "@/components/dataTables/StsVehicleList"; +import STSVehicleList from "@/components/dataTables/StsVehicleList"; export default function STSManagerSchedules() { return ( @@ -12,7 +12,7 @@ export default function STSManagerSchedules() {
UPCOMING - CRITICAL FIRST SCHEDULES - +
{/*
diff --git a/client/components/dataTables/StsVehicleList.tsx b/client/components/dataTables/StsVehicleList.tsx index dcd1b7c..50cd3d0 100644 --- a/client/components/dataTables/StsVehicleList.tsx +++ b/client/components/dataTables/StsVehicleList.tsx @@ -1,11 +1,14 @@ -"use client" +"use client"; -import * as React from "react" +import * as React from "react"; import { CaretSortIcon, ChevronDownIcon, DotsHorizontalIcon, -} from "@radix-ui/react-icons" +} from "@radix-ui/react-icons"; + +import { Button } from "@/components/ui/button"; + import { ColumnDef, ColumnFiltersState, @@ -17,10 +20,8 @@ import { getPaginationRowModel, getSortedRowModel, useReactTable, -} from "@tanstack/react-table" +} from "@tanstack/react-table"; -import { Button } from "@/components/ui/button" -import { Checkbox } from "@/components/ui/checkbox" import { DropdownMenu, DropdownMenuCheckboxItem, @@ -29,8 +30,8 @@ import { DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu" -import { Input } from "@/components/ui/input" +} from "@/components/ui/dropdown-menu"; +import { Input } from "@/components/ui/input"; import { Table, TableBody, @@ -38,147 +39,154 @@ import { TableHead, TableHeader, TableRow, -} from "@/components/ui/table" +} from "@/components/ui/table"; +import useGetAllUser from "@/hooks/user_data/useGetAllUser"; +import { DeleteUserModal } from "../modals/DeleteUserModal"; +import { Copy, EditIcon } from "lucide-react"; +import { EditUserModal } from "../modals/EditUserInfoModal"; +import gettAllRoles from "@/hooks/user_data/useGetAllRole"; +import { roleList } from "@/data/roles"; +import useGetAllSTS from "@/hooks/dataQuery/useGetAllSTS"; +import { EditSTSInfoModal } from "../modals/EditSTSInfoModal"; +import { DeleteSTSModal } from "../modals/DeleteSTSModal"; +import useVehicleList from "@/hooks/vehicles/useVehiclesData"; +import useVehicleListForSTS from "@/hooks/vehicles/useGetVeicleForSTS"; +import { DeleteVehicleModalForSTS } from "../modals/DeleteVehicleModalForSTS"; -const data: Payment[] = [ - { - id: "m5gr84i9", - amount: 316, - status: "success", - email: "ken99@yahoo.com", - }, - { - id: "3u1reuv4", - amount: 242, - status: "success", - email: "Abe45@gmail.com", - }, - { - id: "derv1ws0", - amount: 837, - status: "processing", - email: "Monserrat44@gmail.com", - }, - { - id: "5kma53ae", - amount: 874, - status: "success", - email: "Silas22@gmail.com", - }, - { - id: "bhqecj4p", - amount: 721, - status: "failed", - email: "carmella@hotmail.com", - }, -] +type Vehicle = { + entryId: string, + id: string, + vehicleNumber: string, + vehicleType: string, + capacity: string, + loadedFuelCostPerKm: string, + unloadedFuelCostPerKm: string, + landFillId: string, + entryTime: string, + landFillName: string, + stsLattitude: string, + stsLongitude: string, + landfillLattitude: string, + landfillLongitude: string, +}; -export type Payment = { - id: string - amount: number - status: "pending" | "processing" | "success" | "failed" - email: string -} - -export const columns: ColumnDef[] = [ +export const columns: ColumnDef[] = [ { - id: "select", - header: ({ table }) => ( - table.toggleAllPageRowsSelected(!!value)} - aria-label="Select all" - /> - ), + accessorKey: "vehicleNumber", + header: ({ column }) => { + return ( +
+ +
+ ); + }, cell: ({ row }) => ( - row.toggleSelected(!!value)} - aria-label="Select row" - /> +
{row.getValue("vehicleNumber")}
), - enableSorting: false, - enableHiding: false, }, { - accessorKey: "status", - header: "Status", + accessorKey: "vehicleType", + header: ({ column }) => { + return ( +
+ +
+ ); + }, cell: ({ row }) => ( -
{row.getValue("status")}
+
+ {row.getValue("vehicleType")} +
), }, { - accessorKey: "email", + accessorKey: "entryTime", header: ({ column }) => { return ( - - ) +
+ +
+ ); }, - cell: ({ row }) =>
{row.getValue("email")}
, + cell: ({ row }) => ( +
{row.getValue("entryTime")}
+ ), }, { - accessorKey: "amount", - header: () =>
Amount
, - cell: ({ row }) => { - const amount = parseFloat(row.getValue("amount")) - - // Format the amount as a dollar amount - const formatted = new Intl.NumberFormat("en-US", { - style: "currency", - currency: "USD", - }).format(amount) - - return
{formatted}
+ accessorKey: "landFillName", + header: ({ column }) => { + return ( +
+ +
+ ); }, + cell: ({ row }) => ( +
{row.getValue("landFillName")}
+ ), }, { id: "actions", enableHiding: false, cell: ({ row }) => { - const payment = row.original + const sts: Vehicle = row.original; return ( - - - - - - Actions - navigator.clipboard.writeText(payment.id)} - > - Copy payment ID - - - View customer - View payment details - - - ) +
+ + {/* */} +
+ ); }, }, -] +]; -export function StsVehicleTable() { - const [sorting, setSorting] = React.useState([]) +export default function STSVehicleList() { + const [data, setData] = React.useState([]); + const { getVehicleList, vehicleList } = useVehicleListForSTS(); + const [sorting, setSorting] = React.useState([]); const [columnFilters, setColumnFilters] = React.useState( [] - ) + ); const [columnVisibility, setColumnVisibility] = - React.useState({}) - const [rowSelection, setRowSelection] = React.useState({}) + React.useState({}); + const [rowSelection, setRowSelection] = React.useState({}); + + React.useEffect(() => { + getVehicleList(); + }, []); + + React.useEffect(() => { + setData(vehicleList); + }, [vehicleList]); const table = useReactTable({ data, @@ -197,16 +205,15 @@ export function StsVehicleTable() { columnVisibility, rowSelection, }, - }) - + }); return ( -
-
+ <> +
- table.getColumn("email")?.setFilterValue(event.target.value) + table.getColumn("name")?.setFilterValue(event.target.value) } className="max-w-sm" /> @@ -232,7 +239,7 @@ export function StsVehicleTable() { > {column.id} - ) + ); })} @@ -252,7 +259,7 @@ export function StsVehicleTable() { header.getContext() )} - ) + ); })} ))} @@ -311,6 +318,6 @@ export function StsVehicleTable() {
-
- ) + + ); } diff --git a/client/components/modals/DeleteVehicleModalForSTS.tsx b/client/components/modals/DeleteVehicleModalForSTS.tsx new file mode 100644 index 0000000..daa8af2 --- /dev/null +++ b/client/components/modals/DeleteVehicleModalForSTS.tsx @@ -0,0 +1,105 @@ +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; + +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import React, { useState } from "react"; +import { Trash } from "lucide-react"; +import deleteUser from "@/hooks/user_data/deleteUser"; +import deleteVehicleEntryFromSTS from "@/hooks/StsDashboard/deleteVehicleEntryFromSTS"; + +type Vehicle = { + entryId: string, + id: string, + vehicleNumber: string, + vehicleType: string, + capacity: string, + loadedFuelCostPerKm: string, + unloadedFuelCostPerKm: string, + landFillId: string, + entryTime: string, + landFillName: string, + stsLattitude: string, + stsLongitude: string, + landfillLattitude: string, + landfillLongitude: string, +}; +export const DeleteVehicleModalForSTS = ({ vehicleInfo }: { vehicleInfo: Vehicle }) => { + const [confirmText, setConfirmText] = useState(""); + console.log(vehicleInfo); + return ( + + + + + + + + Confirm Delete User? + + +
+

+ ID: + {vehicleInfo.id} +

+

+ Vehicle Number: + {vehicleInfo.vehicleNumber} +

+

+ Vehicle Type: + {vehicleInfo.vehicleType} +

+

+ Entry Time: + {vehicleInfo.entryTime} +

+
+
+
+
+
+
+ + setConfirmText(e.target.value)} + required + /> +
+
+ + + +
+
+
+ ); +}; diff --git a/client/data/apiRoutes.ts b/client/data/apiRoutes.ts index 1b0051b..ee26e02 100644 --- a/client/data/apiRoutes.ts +++ b/client/data/apiRoutes.ts @@ -16,6 +16,9 @@ export const apiRoutes = { getAll: `${baseUrl}/sts`, delete: `${baseUrl}/sts/`, edit: `${baseUrl}/sts/`, + vehicle: { + delete: `${baseUrl}/sts-entry/`, + }, }, landfill: { create: `${baseUrl}/landfills/create`, diff --git a/client/hooks/StsDashboard/deleteVehicleEntryFromSTS.tsx b/client/hooks/StsDashboard/deleteVehicleEntryFromSTS.tsx new file mode 100644 index 0000000..5e04798 --- /dev/null +++ b/client/hooks/StsDashboard/deleteVehicleEntryFromSTS.tsx @@ -0,0 +1,23 @@ +"use client"; +import { apiRoutes } from "@/data/apiRoutes"; +import { jwtToken } from "@/data/cookieNames"; +import { admin, landfillManager, stsManager, unassigned } from "@/data/roles"; +import { getCookie } from "@/lib/cookieFunctions"; +import axios from "axios"; + +export default async function deleteVehicleEntryFromSTS(entryId: string) { + if (entryId) { + try { + const res = await axios.delete(apiRoutes.sts.vehicle.delete + entryId, { + headers: { + Authorization: `Bearer ${await getCookie(jwtToken)}`, + }, + }); + return "vehicle removed successfully"; + } catch (error: any) { + return error.message?.toString() || "error removing vehicle"; + } + } + + return null; +} diff --git a/client/hooks/vehicles/useGetVeicleForSTS.tsx b/client/hooks/vehicles/useGetVeicleForSTS.tsx new file mode 100644 index 0000000..6a550a7 --- /dev/null +++ b/client/hooks/vehicles/useGetVeicleForSTS.tsx @@ -0,0 +1,59 @@ +import { useState } from 'react'; +import axios from 'axios'; +import { uri } from '@/data/constant'; + +type Vehicle = { + entryId: string, + id: string, + vehicleNumber: string, + vehicleType: string, + capacity: string, + loadedFuelCostPerKm: string, + unloadedFuelCostPerKm: string, + landFillId: string, + entryTime: string, + landFillName: string, + stsLattitude: string, + stsLongitude: string, + landfillLattitude: string, + landfillLongitude: string, +}; + +export default function useVehicleListForSTS() { + const [vehicleList, setVehicleList] = useState([]); // Initialize with an empty array of Vehicle objects + const [vehicleNumberList, setVehicleNumberList] = useState([]); + + async function getVehicleList() { + try { + const res = await axios.get('http://localhost:8585/sts-entry/sts1/get-current-vehicles'); + // Assuming the response data is an array of vehicles + const AllVehicle: Vehicle[] = res.data.map((vehicle: any) => ({ + entryId: vehicle.id, + id: vehicle.vehicleId, + vehicleNumber: vehicle.vehicle.vehicleNumber, + vehicleType: vehicle.vehicle.vehicleType, + capacity: vehicle.vehicle.capacity, + loadedFuelCostPerKm: vehicle.vehicle.loadedFuelCostPerKm, + unloadedFuelCostPerKm: vehicle.vehicle.unloadedFuelCostPerKm, + landFillId: vehicle.landFillId, + entryTime: vehicle.entryTime, + landFillName: "vehicle.landfill.landFillName", + stsLattitude: vehicle.sts.stsLattitude, + stsLongitude: vehicle.sts.stsLongitude, + landfillLattitude: "vehicle.landfill.landfillLattitude", + landfillLongitude: "vehicle.landfill.landfillLongitude", + })); + const vehicleNumbers = res.data.map((vehicle: Vehicle) => vehicle.vehicleNumber); + + setVehicleList(AllVehicle); + setVehicleNumberList(vehicleNumbers); + + return true; + } catch (error: any) { + alert(error.message?.toString() || "Error fetching vehicle list"); + return false; + } + } + + return { vehicleList, vehicleNumberList, getVehicleList }; +}