From 1d717cb3253343c86a60c3f6023839c37c4084e6 Mon Sep 17 00:00:00 2001 From: justine Date: Tue, 22 Apr 2025 15:16:45 -0600 Subject: [PATCH 1/4] feat: add frontend api setupf for dashboard --- frontend/src/api/dashboard.ts | 172 ++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 frontend/src/api/dashboard.ts diff --git a/frontend/src/api/dashboard.ts b/frontend/src/api/dashboard.ts new file mode 100644 index 0000000..a87eb62 --- /dev/null +++ b/frontend/src/api/dashboard.ts @@ -0,0 +1,172 @@ +const API_BASE_URL = 'http://localhost:8080/api'; + +export interface Flight { + servicetype_id: number; + departure_city: string; + arrival_city: string; + departure_time: string; + arrival_time: string; + flightclassoptions: string; + flight_price: number; +} + +export interface Bus { + servicetype_id: number; + departure_city: string; + arrival_city: string; + departure_time: string; + arrival_time: string; + seats_available: number; + capacity: number; + bus_price: number; + amenities: string; +} + +export interface HotelRoom { + servicetype_id: number; + room_number: string; + room_type: string; + check_in_time: string; + check_out_time: string; + price: number; + bed_type: string; + city: string; + capacity: number; + amenities: string; + floor_number: number; + status: string; +} + +export interface Activity { + servicetype_id: number; + description: string; + price: number; + capacity: number; + age_restriction: number; + start_time: string; + end_time: string; + signups: number; + city: string; +} + +// GET functions +export async function getCompanyFlights(companyId: number): Promise { + const response = await fetch( + `${API_BASE_URL}/dashboard/company/${companyId}/flights` + ); + if (!response.ok) { + throw new Error('Failed to fetch flights'); + } + return response.json(); +} + +export async function getCompanyBuses(companyId: number): Promise { + const response = await fetch( + `${API_BASE_URL}/dashboard/company/${companyId}/buses` + ); + if (!response.ok) { + throw new Error('Failed to fetch buses'); + } + return response.json(); +} + +export async function getCompanyHotelRooms( + companyId: number +): Promise { + const response = await fetch( + `${API_BASE_URL}/dashboard/company/${companyId}/hotel-rooms` + ); + if (!response.ok) { + throw new Error('Failed to fetch hotel rooms'); + } + return response.json(); +} + +export async function getCompanyActivities( + companyId: number +): Promise { + const response = await fetch( + `${API_BASE_URL}/dashboard/company/${companyId}/activities` + ); + if (!response.ok) { + throw new Error('Failed to fetch activities'); + } + return response.json(); +} + +// POST functions +export async function addCompanyFlight( + companyId: number, + flightData: Omit +): Promise { + const response = await fetch( + `${API_BASE_URL}/dashboard/company/${companyId}/flights`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(flightData), + } + ); + if (!response.ok) { + throw new Error('Failed to add flight'); + } +} + +export async function addCompanyBus( + companyId: number, + busData: Omit +): Promise { + const response = await fetch( + `${API_BASE_URL}/dashboard/company/${companyId}/buses`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(busData), + } + ); + if (!response.ok) { + throw new Error('Failed to add bus'); + } +} + +export async function addCompanyHotelRoom( + companyId: number, + hotelRoomData: Omit +): Promise { + const response = await fetch( + `${API_BASE_URL}/dashboard/company/${companyId}/hotel-rooms`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(hotelRoomData), + } + ); + if (!response.ok) { + throw new Error('Failed to add hotel room'); + } +} + +export async function addCompanyActivity( + companyId: number, + activityData: Omit +): Promise { + const response = await fetch( + `${API_BASE_URL}/dashboard/company/${companyId}/activities`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(activityData), + } + ); + if (!response.ok) { + throw new Error('Failed to add activity'); + } +} From 45991a95bcb997508d34a9d938eef0241171e210 Mon Sep 17 00:00:00 2001 From: justine Date: Tue, 22 Apr 2025 15:31:19 -0600 Subject: [PATCH 2/4] be fr rn --- backend/routes/company.routes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/routes/company.routes.js b/backend/routes/company.routes.js index 314b1d2..69bfd10 100644 --- a/backend/routes/company.routes.js +++ b/backend/routes/company.routes.js @@ -12,7 +12,7 @@ import { const router = express.Router(); -router.get('/:company_id', getCompanyDetails); +router.get('/companies/:company_id', getCompanyDetails); router.post('/auth/company/login', loginCompany); router.post('/auth/company/signup', signupCompany); From b8c39c874166a2a470e2156f27e1c1151766e1ee Mon Sep 17 00:00:00 2001 From: justine Date: Tue, 22 Apr 2025 15:35:25 -0600 Subject: [PATCH 3/4] feat(backend): api endpoints for getting info in dashboard --- backend/controllers/dashboard.controller.js | 92 ++++++++++++++++++++- backend/routes/dashboard.routes.js | 18 ++-- 2 files changed, 104 insertions(+), 6 deletions(-) diff --git a/backend/controllers/dashboard.controller.js b/backend/controllers/dashboard.controller.js index d01c4d7..195e0dd 100644 --- a/backend/controllers/dashboard.controller.js +++ b/backend/controllers/dashboard.controller.js @@ -1,3 +1,93 @@ import { client } from '../server.js'; -export async function getCompanyFlights(req, res) {} +export async function getCompanyFlights(req, res) { + const { company_id } = req.params; + + try { + const query = { + text: ` + SELECT f.*, c.company_name + FROM Flight f + JOIN FlightCompany_Offers_Flight fcof ON f.ServiceType_Id = fcof.ServiceType_Id + JOIN Company c ON fcof.Company_Id = c.Company_Id + WHERE c.Company_Id = $1 + `, + values: [company_id], + }; + + const result = await client.query(query); + res.json(result.rows); + } catch (err) { + console.error('Error fetching company flights:', err); + res.status(500).json({ error: 'Failed to fetch company flights' }); + } +} + +export async function getCompanyBuses(req, res) { + const { company_id } = req.params; + + try { + const query = { + text: ` + SELECT b.*, c.company_name + FROM Bus b + JOIN BusCompany_Offers_Bus bcob ON b.ServiceType_Id = bcob.ServiceType_Id + JOIN Company c ON bcob.Company_Id = c.Company_Id + WHERE c.Company_Id = $1 + `, + values: [company_id], + }; + + const result = await client.query(query); + res.json(result.rows); + } catch (err) { + console.error('Error fetching company buses:', err); + res.status(500).json({ error: 'Failed to fetch company buses' }); + } +} + +export async function getCompanyHotelRooms(req, res) { + const { company_id } = req.params; + + try { + const query = { + text: ` + SELECT h.*, c.company_name + FROM HotelRoom h + JOIN HotelCompany_Offers_HotelRoom hcoh ON h.ServiceType_Id = hcoh.ServiceType_Id + JOIN Company c ON hcoh.Company_Id = c.Company_Id + WHERE c.Company_Id = $1 + `, + values: [company_id], + }; + + const result = await client.query(query); + res.json(result.rows); + } catch (err) { + console.error('Error fetching company hotel rooms:', err); + res.status(500).json({ error: 'Failed to fetch company hotel rooms' }); + } +} + +export async function getCompanyActivities(req, res) { + const { company_id } = req.params; + + try { + const query = { + text: ` + SELECT a.*, c.company_name + FROM Activity a + JOIN ActivityCompany_Offers_Activity acoa ON a.ServiceType_Id = acoa.ServiceType_Id + JOIN Company c ON acoa.Company_Id = c.Company_Id + WHERE c.Company_Id = $1 + `, + values: [company_id], + }; + + const result = await client.query(query); + res.json(result.rows); + } catch (err) { + console.error('Error fetching company activities:', err); + res.status(500).json({ error: 'Failed to fetch company activities' }); + } +} diff --git a/backend/routes/dashboard.routes.js b/backend/routes/dashboard.routes.js index 7c5d8fd..771811f 100644 --- a/backend/routes/dashboard.routes.js +++ b/backend/routes/dashboard.routes.js @@ -1,11 +1,19 @@ import { Router } from 'express'; -import { getCompanyFlights } from '../controllers/dashboard.controller.js'; +import { + getCompanyFlights, + getCompanyBuses, + getCompanyHotelRooms, + getCompanyActivities, +} from '../controllers/dashboard.controller.js'; const dashboardRouter = Router(); -dashboardRouter.get( - '/company/dashboard/flights/:company_id', - getCompanyFlights -); +dashboardRouter.get('/company/:company_id/flights', getCompanyFlights); + +dashboardRouter.get('/company/:company_id/buses', getCompanyBuses); + +dashboardRouter.get('/company/:company_id/hotel-rooms', getCompanyHotelRooms); + +dashboardRouter.get('/company/:company_id/activities', getCompanyActivities); export default dashboardRouter; From 0ecd004cf4f2952efd4916d5a25209cd52879ad7 Mon Sep 17 00:00:00 2001 From: justine Date: Tue, 22 Apr 2025 15:42:52 -0600 Subject: [PATCH 4/4] feat(frontend): can now fetch company services in dashboard --- backend/routes/dashboard.routes.js | 17 +++- frontend/src/api/dashboard.ts | 6 +- .../src/components/dashboard/ServiceTabs.tsx | 96 +++++++++++-------- frontend/src/pages/Dashboard.tsx | 1 - 4 files changed, 73 insertions(+), 47 deletions(-) diff --git a/backend/routes/dashboard.routes.js b/backend/routes/dashboard.routes.js index 771811f..28fa089 100644 --- a/backend/routes/dashboard.routes.js +++ b/backend/routes/dashboard.routes.js @@ -8,12 +8,21 @@ import { const dashboardRouter = Router(); -dashboardRouter.get('/company/:company_id/flights', getCompanyFlights); +dashboardRouter.get( + '/dashboard/company/:company_id/flights', + getCompanyFlights +); -dashboardRouter.get('/company/:company_id/buses', getCompanyBuses); +dashboardRouter.get('/dashboard/company/:company_id/buses', getCompanyBuses); -dashboardRouter.get('/company/:company_id/hotel-rooms', getCompanyHotelRooms); +dashboardRouter.get( + '/dashboard/company/:company_id/hotel-rooms', + getCompanyHotelRooms +); -dashboardRouter.get('/company/:company_id/activities', getCompanyActivities); +dashboardRouter.get( + '/dashboard/company/:company_id/activities', + getCompanyActivities +); export default dashboardRouter; diff --git a/frontend/src/api/dashboard.ts b/frontend/src/api/dashboard.ts index a87eb62..cfa426d 100644 --- a/frontend/src/api/dashboard.ts +++ b/frontend/src/api/dashboard.ts @@ -8,6 +8,7 @@ export interface Flight { arrival_time: string; flightclassoptions: string; flight_price: number; + company_name: string; } export interface Bus { @@ -20,6 +21,7 @@ export interface Bus { capacity: number; bus_price: number; amenities: string; + company_name: string; } export interface HotelRoom { @@ -35,6 +37,7 @@ export interface HotelRoom { amenities: string; floor_number: number; status: string; + company_name: string; } export interface Activity { @@ -42,11 +45,12 @@ export interface Activity { description: string; price: number; capacity: number; - age_restriction: number; + age_restriction: boolean; start_time: string; end_time: string; signups: number; city: string; + company_name: string; } // GET functions diff --git a/frontend/src/components/dashboard/ServiceTabs.tsx b/frontend/src/components/dashboard/ServiceTabs.tsx index cd8de87..9c5698f 100644 --- a/frontend/src/components/dashboard/ServiceTabs.tsx +++ b/frontend/src/components/dashboard/ServiceTabs.tsx @@ -11,17 +11,19 @@ import { PopoverTrigger, } from '@/components/ui/popover'; import { - fetchFlights, - fetchBuses, - fetchHotelRooms, - fetchActivities, + getCompanyFlights, + getCompanyBuses, + getCompanyHotelRooms, + getCompanyActivities, Flight, Bus, HotelRoom, Activity, -} from '@/api/services'; +} from '@/api/dashboard'; +import { useAuth } from '@/contexts/AuthContext'; export const ServiceTabs = () => { + const { company } = useAuth(); const [activeTab, setActiveTab] = useState('flights'); const [showModal, setShowModal] = useState(false); const [flights, setFlights] = useState([]); @@ -50,7 +52,7 @@ export const ServiceTabs = () => { status: '', name: '', description: '', - ageRestriction: '', + ageRestriction: false, startTime: new Date(), endTime: new Date(), signups: '', @@ -58,14 +60,16 @@ export const ServiceTabs = () => { useEffect(() => { const loadData = async () => { + if (!company?.company_id) return; + try { setLoading(true); const [flightsData, busesData, hotelRoomsData, activitiesData] = await Promise.all([ - fetchFlights(), - fetchBuses(), - fetchHotelRooms(), - fetchActivities(), + getCompanyFlights(company.company_id), + getCompanyBuses(company.company_id), + getCompanyHotelRooms(company.company_id), + getCompanyActivities(company.company_id), ]); setFlights(flightsData); setBuses(busesData); @@ -81,7 +85,7 @@ export const ServiceTabs = () => { }; loadData(); - }, []); + }, [company?.company_id]); const handleTabChange = (value: string) => { setActiveTab(value); @@ -122,7 +126,7 @@ export const ServiceTabs = () => { status: '', name: '', description: '', - ageRestriction: '', + ageRestriction: false, startTime: new Date(), endTime: new Date(), signups: '', @@ -758,20 +762,25 @@ export const ServiceTabs = () => { ) : (
{flights.map((flight) => ( -
+

- {flight.departureCity} → {flight.arrivalCity} + {flight.departure_city} → {flight.arrival_city}

- {new Date(flight.departureTime).toLocaleString()} -{' '} - {new Date(flight.arrivalTime).toLocaleString()} + {new Date(flight.departure_time).toLocaleString()} -{' '} + {new Date(flight.arrival_time).toLocaleString()}

-

{flight.price}

-

{flight.class}

+

${flight.flight_price}

+

+ {flight.flightclassoptions} +

@@ -786,22 +795,22 @@ export const ServiceTabs = () => { ) : (
{buses.map((bus) => ( -
+

- {bus.departureCity} → {bus.arrivalCity} + {bus.departure_city} → {bus.arrival_city}

- {new Date(bus.departureTime).toLocaleString()} -{' '} - {new Date(bus.arrivalTime).toLocaleString()} + {new Date(bus.departure_time).toLocaleString()} -{' '} + {new Date(bus.arrival_time).toLocaleString()}

- Seats: {bus.seats} + Seats: {bus.seats_available}

-

{bus.price}

+

${bus.bus_price}

{bus.amenities}

@@ -817,24 +826,29 @@ export const ServiceTabs = () => { ) : (
{hotelRooms.map((room) => ( -
+

- Room {room.roomNumber} - {room.roomType} + Room {room.room_number} - {room.room_type}

- Check-in: {new Date(room.checkIn).toLocaleString()} + Check-in:{' '} + {new Date(room.check_in_time).toLocaleString()}
- Check-out: {new Date(room.checkOut).toLocaleString()} + Check-out:{' '} + {new Date(room.check_out_time).toLocaleString()}

- {room.bedType} bed • {room.capacity} guests • Floor{' '} - {room.floor} + {room.bed_type} bed • {room.capacity} guests • Floor{' '} + {room.floor_number}

-

{room.price}

+

${room.price}

{room.status}

@@ -850,24 +864,24 @@ export const ServiceTabs = () => { ) : (
{activities.map((activity) => ( -
+
-

{activity.name}

-

- {activity.description} -

+

{activity.description}

- {new Date(activity.startTime).toLocaleString()} -{' '} - {new Date(activity.endTime).toLocaleString()} + {new Date(activity.start_time).toLocaleString()} -{' '} + {new Date(activity.end_time).toLocaleString()}

- Signups: {activity.signups} • Age:{' '} - {activity.ageRestriction} + Signups: {activity.signups} • Age Restriction:{' '} + {activity.age_restriction ? 'Yes' : 'No'}

-

{activity.price}

+

${activity.price}

diff --git a/frontend/src/pages/Dashboard.tsx b/frontend/src/pages/Dashboard.tsx index d2209cc..045dbb2 100644 --- a/frontend/src/pages/Dashboard.tsx +++ b/frontend/src/pages/Dashboard.tsx @@ -35,7 +35,6 @@ export default function Dashboard() { Logout
-
);