Files
flights_web/src/ui/flights/FlightCard.scss
T
gnezim 76f7acb0dd Implement inline expandable flight-card details
Clicking a row on the board search results page now toggles an inline
details panel instead of immediately navigating away. The layout
matches Angular's board-flight-header:

- Aircraft model ('Sukhoi SuperJet 100') appears below the flight
  number when expanded.
- 'Время' detail row: По расписанию / Фактическое times with UTC
  offsets for both the departure and the arrival sides.
- 'Посадка' detail row: boarding status (через the
  BOARDING-STATUSES.* keys), start and end times.
- 'Детали рейса' button (blue) in the bottom-right navigates to the
  full details page.
- Active rows get a blue left border + light-blue background.
- Chevron icon on the right rotates on expand.

Wire-up: FlightCard has two new props (expandable, onViewDetails).
FlightList automatically passes expandable=true when a click handler
is provided. Added SHARED.BOARDING-START / SHARED.BOARDING-END keys
across all nine locales for the time captions.
2026-04-18 15:36:14 +03:00

196 lines
3.2 KiB
SCSS

@use "../../styles/variables" as vars;
@use "../../styles/colors" as colors;
@use "../../styles/fonts" as fonts;
@use "../../styles/screen" as screen;
.flight-card {
display: flex;
flex-direction: column;
background: transparent;
transition: background-color 120ms ease;
& + & {
border-top: 1px dashed colors.$border;
}
&--expanded {
background: #f3f6fb;
border-left: 3px solid colors.$blue;
}
&--clickable .flight-card__row {
cursor: pointer;
&:hover {
background-color: rgba(46, 87, 255, 0.04);
}
&:focus-visible {
outline: 2px solid colors.$blue;
outline-offset: -2px;
}
}
&__row {
display: grid;
grid-template-columns: 70px 100px 80px 1fr 90px 80px 1fr auto;
align-items: center;
gap: 12px;
padding: 18px vars.$space-xl;
min-height: 68px;
}
&__number {
font-weight: fonts.$font-medium;
color: #222;
font-size: 14px;
}
&__aircraft {
font-size: 11px;
color: #8a8a8a;
font-weight: normal;
margin-top: 4px;
}
&__operator {
display: flex;
align-items: center;
}
&__time {
font-size: 20px;
line-height: 1.1;
color: #222;
text-align: left;
&--arrival {
text-align: left;
}
}
&__station {
min-width: 0;
text-align: left;
&--arrival {
text-align: right;
.station {
align-items: flex-start;
}
}
}
&__status {
display: flex;
justify-content: center;
}
&__chevron {
color: colors.$blue;
font-size: 18px;
transition: transform 150ms ease;
&--open {
transform: rotate(180deg);
}
}
&__expanded {
padding: 0 vars.$space-xl vars.$space-xl;
display: flex;
flex-direction: column;
gap: vars.$space-m;
background: #f8fafd;
}
&__detail-row {
display: grid;
grid-template-columns: 140px 1fr 1fr;
gap: vars.$space-xl;
padding: vars.$space-m 0;
border-bottom: 1px dashed #e0e6f0;
align-items: flex-start;
&:last-child {
border-bottom: none;
}
}
&__detail-label {
color: #8a8a8a;
font-size: 14px;
}
&__detail-group {
display: flex;
gap: vars.$space-xl;
flex-wrap: wrap;
> div {
display: flex;
flex-direction: column;
gap: 2px;
}
}
&__detail-caption {
font-size: 12px;
color: #8a8a8a;
}
&__detail-value {
font-weight: 500;
color: #222;
font-size: 14px;
}
&__detail-status {
color: #2457ff;
}
&__actions {
display: flex;
justify-content: flex-end;
padding-top: vars.$space-s;
}
&__details-btn {
background: colors.$blue;
color: #fff;
border: none;
border-radius: 4px;
padding: 10px 24px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: background-color 150ms ease;
&:hover {
background: #1c45cc;
}
}
@include screen.mobile {
&__row {
grid-template-columns: 1fr 1fr;
gap: vars.$space-m;
}
&__operator,
&__status,
&__chevron {
display: none;
}
&__station--arrival {
text-align: left;
}
&__detail-row {
grid-template-columns: 1fr;
}
}
}