diff --git a/apps/react/src/app/features/online-board/components/board-flight-body.scss b/apps/react/src/app/features/online-board/components/board-flight-body.scss new file mode 100644 index 000000000..5de49923b --- /dev/null +++ b/apps/react/src/app/features/online-board/components/board-flight-body.scss @@ -0,0 +1,26 @@ +.board-flight-body { + padding: 16px; + background: #fafafa; + border-top: 1px solid #e0e0e0; +} + +.board-flight-body__section { + margin-bottom: 16px; + + &:last-child { + margin-bottom: 0; + } + + h3 { + margin: 0 0 8px 0; + font-size: 14px; + font-weight: 600; + color: #333; + } + + p { + margin: 0; + color: #666; + font-size: 14px; + } +} diff --git a/apps/react/src/app/features/online-board/components/board-flight-body.tsx b/apps/react/src/app/features/online-board/components/board-flight-body.tsx new file mode 100644 index 000000000..64d5489d4 --- /dev/null +++ b/apps/react/src/app/features/online-board/components/board-flight-body.tsx @@ -0,0 +1,21 @@ +import React from 'react' +import './board-flight-body.scss' + +export interface BoardFlightBodyProps { + flight: any +} + +export const BoardFlightBody: React.FC = ({ flight }) => { + return ( +
+
+

Departure

+

{flight.departure.airport} - {flight.departure.city}

+
+
+

Arrival

+

{flight.arrival.airport} - {flight.arrival.city}

+
+
+ ) +} diff --git a/apps/react/src/app/features/online-board/components/board-flight-header.scss b/apps/react/src/app/features/online-board/components/board-flight-header.scss new file mode 100644 index 000000000..c3e977da3 --- /dev/null +++ b/apps/react/src/app/features/online-board/components/board-flight-header.scss @@ -0,0 +1,73 @@ +.board-flight-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 16px; + cursor: pointer; + user-select: none; + border-bottom: 1px solid #f0f0f0; + transition: background 0.2s ease; + + &:hover { + background: #f9f9f9; + } + + &--expanded { + background: #f5f5f5; + border-bottom: 1px solid #e0e0e0; + } +} + +.board-flight-header__content { + flex: 1; + display: grid; + grid-template-columns: 80px 100px 1fr 1fr; + gap: 16px; + align-items: center; + + @media (max-width: 768px) { + grid-template-columns: 1fr; + gap: 8px; + } +} + +.board-flight-header__number { + font-weight: 600; + font-size: 16px; + color: #1976d2; +} + +.board-flight-header__status { + padding: 4px 8px; + border-radius: 4px; + background: #e8f5e9; + color: #2e7d32; + font-size: 12px; + font-weight: 500; + white-space: nowrap; +} + +.board-flight-header__times { + display: flex; + align-items: center; + gap: 8px; + font-weight: 500; + color: #333; + + span:first-child, + span:last-child { + min-width: 60px; + } +} + +.board-flight-header__route { + color: #666; + font-size: 14px; +} + +.board-flight-header__arrow { + margin-left: 16px; + color: #999; + font-size: 12px; + transition: transform 0.2s ease; +} diff --git a/apps/react/src/app/features/online-board/components/board-flight-header.tsx b/apps/react/src/app/features/online-board/components/board-flight-header.tsx new file mode 100644 index 000000000..3a604f7e5 --- /dev/null +++ b/apps/react/src/app/features/online-board/components/board-flight-header.tsx @@ -0,0 +1,38 @@ +import React from 'react' +import './board-flight-header.scss' + +export interface BoardFlightHeaderProps { + flight: any + isExpanded: boolean + onToggle: () => void +} + +export const BoardFlightHeader: React.FC = ({ + flight, + isExpanded, + onToggle, +}) => { + return ( +
+
+
{flight.flightNumber}
+
{flight.status}
+
+ {flight.departure.scheduled} + + {flight.arrival.scheduled} +
+
+ {flight.departure.city} → {flight.arrival.city} +
+
+
+ {isExpanded ? '▼' : '▶'} +
+
+ ) +} diff --git a/apps/react/src/app/features/online-board/components/board-search-result.scss b/apps/react/src/app/features/online-board/components/board-search-result.scss new file mode 100644 index 000000000..4a4193795 --- /dev/null +++ b/apps/react/src/app/features/online-board/components/board-search-result.scss @@ -0,0 +1,14 @@ +.board-search-result { + display: flex; + flex-direction: column; + gap: 12px; +} + +.board-search-result__item { + overflow: hidden; +} + +.board-search-result__flight { + display: flex; + flex-direction: column; +} diff --git a/apps/react/src/app/features/online-board/components/board-search-result.tsx b/apps/react/src/app/features/online-board/components/board-search-result.tsx new file mode 100644 index 000000000..a8e0832b2 --- /dev/null +++ b/apps/react/src/app/features/online-board/components/board-search-result.tsx @@ -0,0 +1,77 @@ +import React, { useState } from 'react' +import { Card } from '@app/components/card' +import { BoardFlightHeader } from './board-flight-header' +import { BoardFlightBody } from './board-flight-body' +import './board-search-result.scss' + +export interface Flight { + id: string + flightNumber: string + status: string + operator?: string + aircraft?: string + departure: { + airport: string + city: string + scheduled: string + actual?: string + terminal?: string + gate?: string + } + arrival: { + airport: string + city: string + scheduled: string + actual?: string + terminal?: string + gate?: string + } + codesharing?: string[] + boarding?: { + time: string + gate: string + } + deboarding?: { + time: string + gate: string + } +} + +export interface BoardSearchResultProps { + flights: Flight[] + 'data-testid'?: string +} + +export const BoardSearchResult: React.FC = ({ + flights, + 'data-testid': dataTestId, +}) => { + const [expandedFlightId, setExpandedFlightId] = useState(null) + + const toggleExpanded = (flightId: string) => { + setExpandedFlightId(expandedFlightId === flightId ? null : flightId) + } + + return ( +
+ {flights.map((flight) => ( + +
+ toggleExpanded(flight.id)} + /> + {expandedFlightId === flight.id && ( + + )} +
+
+ ))} +
+ ) +} diff --git a/apps/react/src/app/features/online-board/components/index.ts b/apps/react/src/app/features/online-board/components/index.ts index 419c42985..2c6b51b7f 100644 --- a/apps/react/src/app/features/online-board/components/index.ts +++ b/apps/react/src/app/features/online-board/components/index.ts @@ -1,3 +1,7 @@ export { OnlineBoardFilter } from './online-board-filter' export { FlightNumberFilter } from './flight-number-filter' export { RouteFilter } from './route-filter' +export { BoardSearchResult } from './board-search-result' +export { BoardFlightHeader } from './board-flight-header' +export { BoardFlightBody } from './board-flight-body' +export type { Flight } from './board-search-result'