From 4b2a03fb181bcae2de0fb7b4db8280196de52b1f Mon Sep 17 00:00:00 2001 From: gnezim Date: Sun, 5 Apr 2026 21:22:01 +0300 Subject: [PATCH] feat: create ScheduleFlightDetailsPage with schedule flight details --- .../src/app/features/schedule/pages/index.ts | 1 + .../pages/schedule-flight-details-page.scss | 174 +++++++++++++ .../pages/schedule-flight-details-page.tsx | 246 ++++++++++++++++++ 3 files changed, 421 insertions(+) create mode 100644 apps/react/src/app/features/schedule/pages/schedule-flight-details-page.scss create mode 100644 apps/react/src/app/features/schedule/pages/schedule-flight-details-page.tsx diff --git a/apps/react/src/app/features/schedule/pages/index.ts b/apps/react/src/app/features/schedule/pages/index.ts index b8c804bb1..f21d81fcd 100644 --- a/apps/react/src/app/features/schedule/pages/index.ts +++ b/apps/react/src/app/features/schedule/pages/index.ts @@ -1,2 +1,3 @@ export { ScheduleStartPage } from './schedule-start-page' export { ScheduleSearchPage } from './schedule-search-page' +export { ScheduleFlightDetailsPage } from './schedule-flight-details-page' diff --git a/apps/react/src/app/features/schedule/pages/schedule-flight-details-page.scss b/apps/react/src/app/features/schedule/pages/schedule-flight-details-page.scss new file mode 100644 index 000000000..b874c5a45 --- /dev/null +++ b/apps/react/src/app/features/schedule/pages/schedule-flight-details-page.scss @@ -0,0 +1,174 @@ +.schedule-flight-details-page { + width: 100%; +} + +.schedule-flight-details-page__content { + display: flex; + flex-direction: column; + gap: 16px; +} + +.schedule-flight-details-page__mini-list { + padding: 16px; + + h3 { + margin: 0 0 12px 0; + font-size: 18px; + font-weight: 600; + color: #1976d2; + } + + p { + margin: 0 0 8px 0; + font-size: 14px; + color: #666; + + &:last-child { + margin-bottom: 0; + } + } +} + +.schedule-flight-details-page__header { + padding: 20px; +} + +.schedule-flight-details-page__header-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); + gap: 20px; + + @media (max-width: 768px) { + grid-template-columns: repeat(2, 1fr); + } + + @media (max-width: 480px) { + grid-template-columns: 1fr; + } +} + +.schedule-flight-details-page__header-item { + display: flex; + flex-direction: column; + gap: 8px; +} + +.schedule-flight-details-page__header-label { + font-size: 12px; + color: #999; + text-transform: uppercase; + font-weight: 500; +} + +.schedule-flight-details-page__header-value { + font-size: 18px; + color: #333; + font-weight: 600; +} + +.schedule-flight-details-page__departure, +.schedule-flight-details-page__arrival { + padding: 20px; + + h3 { + margin: 0 0 16px 0; + font-size: 16px; + font-weight: 600; + color: #333; + } +} + +.schedule-flight-details-page__info-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); + gap: 12px; + + @media (max-width: 768px) { + grid-template-columns: repeat(2, 1fr); + } + + @media (max-width: 480px) { + grid-template-columns: 1fr; + } +} + +.schedule-flight-details-page__info-item { + display: flex; + flex-direction: column; + gap: 4px; + padding: 8px; + background: #f5f5f5; + border-radius: 4px; +} + +.schedule-flight-details-page__label { + font-size: 11px; + color: #999; + text-transform: uppercase; + font-weight: 500; +} + +.schedule-flight-details-page__value { + font-size: 14px; + color: #333; + font-weight: 500; + display: flex; + flex-direction: column; + gap: 2px; +} + +.schedule-flight-details-page__city { + font-size: 12px; + color: #999; +} + +.schedule-flight-details-page__schedule { + padding: 20px; + + h3 { + margin: 0 0 16px 0; + font-size: 16px; + font-weight: 600; + color: #333; + } +} + +.schedule-flight-details-page__days { + display: flex; + flex-wrap: wrap; + gap: 8px; +} + +.schedule-flight-details-page__day { + padding: 8px 12px; + border: 1px solid #e0e0e0; + border-radius: 4px; + background: white; + font-size: 12px; + font-weight: 500; + color: #666; + text-align: center; + min-width: 50px; + + &.active { + background: #1976d2; + color: white; + border-color: #1976d2; + } +} + +.schedule-flight-details-page__additional { + padding: 20px; +} + +.schedule-flight-details-page__detail-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 12px 0; + border-bottom: 1px solid #f0f0f0; + + &:last-child { + border-bottom: none; + } +} diff --git a/apps/react/src/app/features/schedule/pages/schedule-flight-details-page.tsx b/apps/react/src/app/features/schedule/pages/schedule-flight-details-page.tsx new file mode 100644 index 000000000..2977be7ee --- /dev/null +++ b/apps/react/src/app/features/schedule/pages/schedule-flight-details-page.tsx @@ -0,0 +1,246 @@ +import React, { useState, useEffect } from 'react' +import { useNavigate } from 'react-router-dom' +import axios from 'axios' +import { Button } from 'primereact/button' +import { PageLayout } from '@app/components/page-layout' +import { PageTabs } from '@app/components/page-tabs' +import { PageLoader } from '@app/components/page-loader' +import { PageEmptyList } from '@app/components/page-empty-list' +import { Card } from '@app/components/card' +import { useTranslation } from 'react-i18next' +import './schedule-flight-details-page.scss' + +interface ScheduleFlightDetails { + id: string + flightNumber: string + operator?: string + aircraft?: { + type: string + registration?: string + } + departure: { + airport: string + city: string + time: string + terminal?: string + gate?: string + } + arrival: { + airport: string + city: string + time: string + terminal?: string + gate?: string + } + daysOfWeek?: string[] + frequency?: string + duration?: string + stops?: number + codeshare?: string[] + remarks?: string +} + +const DAYS_OF_WEEK = ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN'] + +export const ScheduleFlightDetailsPage: React.FC = () => { + const navigate = useNavigate() + const { t } = useTranslation() + const [flight, setFlight] = useState(null) + const [loading, setLoading] = useState(true) + const [error, setError] = useState(null) + + useEffect(() => { + const fetchFlightDetails = async () => { + try { + setLoading(true) + setError(null) + + // Get flight ID from URL params or other source + // For now, using a placeholder - would be extracted from route + const response = await axios.get('/api/schedule/flight/1') + setFlight(response.data) + } catch (err) { + console.error('Failed to load flight details:', err) + setError('Failed to load flight information') + } finally { + setLoading(false) + } + } + + fetchFlightDetails() + }, []) + + const handleBack = () => { + navigate(-1) + } + + if (loading) { + return + } + + if (error || !flight) { + return ( +
+ + +
+ ) + } + + return ( +
+ + + + } + contentLeft={ + +

{flight.flightNumber}

+

{flight.departure.airport} → {flight.arrival.airport}

+ {flight.frequency &&

{flight.frequency}

} +
+ } + > +
+ {/* Header Card */} + +
+
+ {t('SHARED.FLIGHT')} + {flight.flightNumber} +
+ {flight.operator && ( +
+ {t('SHARED.OPERATOR')} + {flight.operator} +
+ )} + {flight.aircraft && ( +
+ {t('SHARED.AIRCRAFT')} + {flight.aircraft.type} +
+ )} + {flight.duration && ( +
+ {t('SCHEDULE.DURATION')} + {flight.duration} +
+ )} +
+
+ + {/* Departure Section */} + +

{t('SHARED.DEPARTURE')}

+
+
+ {t('SHARED.AIRPORT')} + + {flight.departure.airport} + {flight.departure.city} + +
+
+ {t('SHARED.TIME')} + {flight.departure.time} +
+ {flight.departure.terminal && ( +
+ {t('SHARED.TERMINAL')} + {flight.departure.terminal} +
+ )} + {flight.departure.gate && ( +
+ {t('SHARED.GATE')} + {flight.departure.gate} +
+ )} +
+
+ + {/* Arrival Section */} + +

{t('SHARED.ARRIVAL')}

+
+
+ {t('SHARED.AIRPORT')} + + {flight.arrival.airport} + {flight.arrival.city} + +
+
+ {t('SHARED.TIME')} + {flight.arrival.time} +
+ {flight.arrival.terminal && ( +
+ {t('SHARED.TERMINAL')} + {flight.arrival.terminal} +
+ )} + {flight.arrival.gate && ( +
+ {t('SHARED.GATE')} + {flight.arrival.gate} +
+ )} +
+
+ + {/* Schedule Section */} + +

{t('SCHEDULE.OPERATING_DAYS')}

+
+ {DAYS_OF_WEEK.map((day) => ( + + {day} + + ))} +
+
+ + {/* Additional Info */} + {(flight.stops !== undefined || flight.codeshare || flight.remarks) && ( + + {flight.stops !== undefined && ( +
+ {t('SCHEDULE.STOPS')} + {flight.stops} +
+ )} + {flight.codeshare && flight.codeshare.length > 0 && ( +
+ {t('SCHEDULE.CODESHARE')} + {flight.codeshare.join(', ')} +
+ )} + {flight.remarks && ( +
+ {t('SHARED.REMARKS')} + {flight.remarks} +
+ )} +
+ )} +
+
+
+ ) +}