-
Notifications
You must be signed in to change notification settings - Fork 0
feat: реализован UI для билета #15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
dianakuprava
wants to merge
12
commits into
dev
Choose a base branch
from
FELL02-8
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
3de4d0a
feat: add Ticket components and logic
dianakuprava 0f64a86
Update postcss.config.js
dianakuprava ac82214
Update postcss.config.js
dianakuprava 5d25a2f
WIP: временные изменения перед переключением ветки
dianakuprava 055d493
Рефакторинг компонентов билета: типизация, разделение TariffsSection
dianakuprava d1bb0ad
Разрешение конфликтов после merge с dev
dianakuprava 38ea911
Merge remote changes into FELL02-8
dianakuprava 0c17e90
Рефакторинг: удаление лишних комментариев, правки компонентов
dianakuprava 2fb4d2b
Merge dev into FELL02-8: resolve conflicts
dianakuprava 850eda7
FELL02-8
dianakuprava 0ad3f90
Merge branch 'dev' into FELL02-8
dianakuprava 63dc597
Merge branch 'dev' into FELL02-8
dianakuprava File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,5 +2,5 @@ export default { | |
| plugins: { | ||
| '@tailwindcss/postcss': {}, | ||
| autoprefixer: {}, | ||
| }, | ||
| }; | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| export { TicketCard } from './ui/TicketCard'; | ||
| export { TariffsSection } from './ui/TariffsSection'; | ||
| export { RouteInfo } from './ui/RouteInfo'; | ||
| export { TicketHeader } from './ui/TicketHeader'; | ||
|
|
||
| export type { ITicket } from './model'; | ||
| export { mockTicket } from './model'; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| import type { ITicket } from './types.ts'; | ||
|
|
||
| export const mockTicket: ITicket = { | ||
| id: '1', | ||
| airline: 'Q Globus LLC', | ||
| flightNumber: 'GF-2025', | ||
| isDirect: true, | ||
| departure: { | ||
| time: '05:00', | ||
| city: 'Санкт-Петербург', | ||
| date: '30 июн, Пт', | ||
| airport: 'LED' | ||
| }, | ||
| arrival: { | ||
| time: '06:40', | ||
| city: 'Москва', | ||
| date: '30 июн, Пт', | ||
| airport: 'DME' | ||
| }, | ||
| duration: '1ч 40м', | ||
| tariffs: { | ||
| economy: { | ||
| basic: 3787, | ||
| standard: 5887, | ||
| plus: 12437 | ||
| } | ||
| }, | ||
| baggage: { | ||
| included: false, | ||
| price: 1500 | ||
| }, | ||
| seatsLeft: 2 | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| export type { ITicket } from './types'; | ||
| export { mockTicket } from './constants'; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| export interface ITicket { | ||
| id: string; | ||
| airline: string; | ||
| flightNumber: string; | ||
| isDirect: boolean; | ||
| departure: { | ||
| time: string; | ||
| city: string; | ||
| date: string; | ||
| airport: string; | ||
| }; | ||
| arrival: { | ||
| time: string; | ||
| city: string; | ||
| date: string; | ||
| airport: string; | ||
| }; | ||
| duration: string; | ||
| tariffs: { | ||
| economy: { | ||
| basic: number; | ||
| standard: number; | ||
| plus: number; | ||
| }; | ||
| }; | ||
| baggage: { | ||
| included: boolean; | ||
| price?: number; | ||
| }; | ||
| seatsLeft: number; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| import { AirplaneLandingIcon, AirplaneTakeoffIcon, LineIcon } from '@shared/ui/icons'; | ||
| import type { ITicket } from '@entities/Ticket'; | ||
|
|
||
| export type RouteInfoProps = Pick<ITicket, 'departure' | 'arrival' | 'duration'>; | ||
|
|
||
| export const RouteInfo = ({ departure, arrival, duration }: RouteInfoProps) => { | ||
| return ( | ||
| <div className="flex flex-col"> | ||
| <div className="flex items-center justify-center text-sm text-gray-500"> | ||
| <AirplaneTakeoffIcon className="w-4 h-4 mr-2" /> | ||
| <span className="font-roboto font-medium text-base leading-5 text-[#808080]"> | ||
| в пути {duration} | ||
| </span> | ||
| <AirplaneLandingIcon className="w-4 h-4 ml-2" /> | ||
| </div> | ||
|
|
||
| <div className="flex items-center justify-between"> | ||
| <div className="flex items-center"> | ||
| <span className="font-roboto font-semibold text-[28px] leading-[32px] text-[#2E2E2E] text-right"> | ||
| {departure.time} | ||
| </span> | ||
| <span className="text-base font-medium text-[#2E2E2E] ml-4">{departure.airport}</span> | ||
| </div> | ||
|
|
||
| <LineIcon className="flex-1 mx-4 text-gray-300" /> | ||
|
|
||
| <div className="flex items-center"> | ||
| <span className="text-medium font-medium text-[#2E2E2E] mr-4">{arrival.airport}</span> | ||
| <span className="font-roboto font-semibold text-[28px] leading-[32px] text-[#2E2E2E] text-right"> | ||
| {arrival.time} | ||
| </span> | ||
| </div> | ||
| </div> | ||
|
|
||
| <div className="flex items-center justify-between mt-[4px]"> | ||
| <div className="flex flex-col"> | ||
| <span className="font-roboto font-medium text-base leading-5 text-[#808080]"> | ||
| {departure.city} | ||
| </span> | ||
| <span className="font-roboto font-medium text-base leading-5 text-[#808080]"> | ||
| {departure.date} | ||
| </span> | ||
| </div> | ||
|
|
||
| <div className="flex flex-col items-end"> | ||
| <span className="font-roboto font-medium text-base leading-5 text-[#808080] text-right"> | ||
| {arrival.city} | ||
| </span> | ||
| <span className="font-roboto font-medium text-base leading-5 text-[#808080] text-right"> | ||
| {arrival.date} | ||
| </span> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| ); | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| export { RouteInfo } from './RouteInfo'; | ||
| export type { RouteInfoProps} from './RouteInfo'; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| import type { ReactNode } from 'react'; | ||
| import { getSeatText } from '@shared/utils/getSeatText.ts'; | ||
| import type { ITicket } from '@entities/Ticket'; | ||
| import { WarningCircleIcon } from '@shared/ui/icons'; | ||
|
|
||
| interface TariffCardProps extends Pick<ITicket, 'seatsLeft'> { | ||
| title: string; | ||
| price: number; | ||
| isSelected: boolean; | ||
| onClick: () => void; | ||
| icons: ReactNode; | ||
| showSeatsLeft?: boolean; | ||
| bgColor?: string; | ||
| dimensions?: string; | ||
| } | ||
|
|
||
| export const TariffCard = ({ | ||
| title, | ||
| price, | ||
| isSelected, | ||
| onClick, | ||
| icons, | ||
| showSeatsLeft = false, | ||
| seatsLeft = 0, | ||
| bgColor = 'bg-[#EBF3FF]', | ||
| dimensions = '' | ||
| }: TariffCardProps) => { | ||
| const shadowClass = 'shadow-[0_4px_4px_rgba(0,0,0,0.25)]'; | ||
|
|
||
| return ( | ||
| <button | ||
| type="button" | ||
| onClick={onClick} | ||
| className={`flex flex-col text-left ${bgColor} rounded-lg pt-[20px] p-4 relative transition-shadow ${dimensions} ${ | ||
| isSelected ? shadowClass : '' | ||
| }`} | ||
| > | ||
| <div className="flex justify-between items-center mb-[17px]"> | ||
| <span className="font-medium text-[16px] leading-[20px] tracking-normal text-[#2E2E2E] font-roboto"> | ||
| {title} | ||
| </span> | ||
| <div className="flex items-center">{icons}</div> | ||
| </div> | ||
|
|
||
| <span className="font-semibold text-[28px] leading-[32px] tracking-normal font-roboto"> | ||
| {new Intl.NumberFormat('ru-RU').format(price)} ₽ | ||
| </span> | ||
|
|
||
| {showSeatsLeft && ( | ||
| <div className=" absolute bottom-4 left-4 right-4 text-sm font-medium text-[#808080] flex items-center gap-1 mt-[22px]"> | ||
| <WarningCircleIcon /> | ||
| {`Осталось ${seatsLeft} ${getSeatText(seatsLeft)}`} | ||
| </div> | ||
| )} | ||
| </button> | ||
| ); | ||
| }; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| export { TariffCard } from './TariffCard'; | ||
| export type { TariffCardProps } from './TariffCard'; |
111 changes: 111 additions & 0 deletions
111
src/entities/Ticket/ui/TariffsSection/TariffsSection.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| import { useState } from 'react'; | ||
| import { | ||
| BackpackIcon, | ||
| SuitcaseIcon, | ||
| ArrowsClockwiseIcon, | ||
| ArmchairIcon | ||
| } from '@shared/ui/icons'; | ||
| import { TariffCard } from '@entities/Ticket/ui/TariffCard'; | ||
| import type { ITicket } from '@entities/Ticket'; | ||
|
|
||
| export type TariffsSectionProps = Pick<ITicket, 'tariffs' | 'seatsLeft'>; | ||
|
|
||
| export const TariffsSection = ({ tariffs, seatsLeft }: TariffsSectionProps) => { | ||
| const [selectedTariff, setSelectedTariff] = useState<string | null>(null); | ||
|
|
||
| const servicesAvailability = { | ||
| basic: { | ||
| backpack: true, | ||
| suitcase: false, | ||
| arrows: false, | ||
| armchair: false | ||
| }, | ||
| standard: { | ||
| backpack: true, | ||
| suitcase: true, | ||
| arrows: false, | ||
| armchair: false | ||
| }, | ||
| plus: { | ||
| backpack: true, | ||
| suitcase: true, | ||
| arrows: true, | ||
| armchair: true | ||
| } | ||
| }; | ||
|
|
||
| const getColorClass = ( | ||
| tariffType: keyof typeof servicesAvailability, | ||
| icon: keyof typeof servicesAvailability.basic | ||
| ) => { | ||
| return servicesAvailability[tariffType][icon] | ||
| ? 'text-[#227420]' | ||
| : 'text-[#808080]'; | ||
| }; | ||
|
|
||
| const tariffConfigs = [ | ||
| { | ||
| type: 'basic' as const, | ||
| title: 'Эконом Базовый', | ||
| price: tariffs.economy.basic, | ||
| bgColor: 'bg-[#EBF3FF]', | ||
| icons: ( | ||
| <> | ||
| <BackpackIcon className={`w-5 h-4.5 mr-[3px] ml-[10px] ${getColorClass('basic', 'backpack')}`} /> | ||
| <SuitcaseIcon className={`mr-[3px] ${getColorClass('basic', 'suitcase')}`} /> | ||
| <ArrowsClockwiseIcon className={`mr-[3px] ${getColorClass('basic', 'arrows')}`} /> | ||
| <ArmchairIcon className={`${getColorClass('basic', 'armchair')}`} /> | ||
| </> | ||
| ), | ||
| showSeatsLeft: true | ||
| }, | ||
| { | ||
| type: 'standard' as const, | ||
| title: 'Эконом Стандарт', | ||
| price: tariffs.economy.standard, | ||
| bgColor: 'bg-[#EBF3FF]', | ||
| icons: ( | ||
| <> | ||
| <BackpackIcon className={`w-4.5 h-4.5 mr-[2px] ml-[10px] ${getColorClass('standard', 'backpack')}`} /> | ||
| <SuitcaseIcon className={`mr-[4px] ${getColorClass('standard', 'suitcase')}`} /> | ||
| <ArrowsClockwiseIcon className={`mr-[2px] ${getColorClass('standard', 'arrows')}`} /> | ||
| <ArmchairIcon className={`${getColorClass('standard', 'armchair')}`} /> | ||
| </> | ||
| ) | ||
| }, | ||
| { | ||
| type: 'plus' as const, | ||
| title: 'Эконом Плюс', | ||
| price: tariffs.economy.plus, | ||
| bgColor: 'bg-[#C2DCFF]', | ||
| icons: ( | ||
| <> | ||
| <BackpackIcon className={`w-5 h-4.5 mr-[3px] ${getColorClass('plus', 'backpack')}`} /> | ||
| <SuitcaseIcon className={`mr-[4.88px] ${getColorClass('plus', 'suitcase')}`} /> | ||
| <ArrowsClockwiseIcon className={`mr-[3px] ${getColorClass('plus', 'arrows')}`} /> | ||
| <ArmchairIcon className={`${getColorClass('plus', 'armchair')}`} /> | ||
| </> | ||
| ), | ||
| dimensions: 'w-[260px] h-[165px]' | ||
| } | ||
| ]; | ||
|
|
||
| return ( | ||
| <div className="flex gap-4 w-full"> | ||
| {tariffConfigs.map((config) => ( | ||
| <TariffCard | ||
| key={config.type} | ||
| title={config.title} | ||
| price={config.price} | ||
| isSelected={selectedTariff === config.type} | ||
| onClick={() => setSelectedTariff(config.type)} | ||
| icons={config.icons} | ||
| showSeatsLeft={config.showSeatsLeft} | ||
| seatsLeft={seatsLeft} | ||
| bgColor={config.bgColor} | ||
| dimensions={config.dimensions} | ||
| /> | ||
| ))} | ||
| </div> | ||
| ); | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| export { TariffsSection } from './TariffsSection'; | ||
| export type { TariffsSectionProps } from './TariffsSection'; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| import type { ITicket } from '@entities/Ticket'; | ||
| import { TicketHeader } from '@entities/Ticket'; | ||
| import { RouteInfo } from '@entities/Ticket'; | ||
| import { TariffsSection } from '@entities/Ticket'; | ||
|
|
||
| export interface TicketCardProps { | ||
| ticket: ITicket; | ||
| } | ||
|
|
||
| export const TicketCard = ({ ticket }: TicketCardProps) => { | ||
| return ( | ||
| <div className="bg-white rounded-lg shadow-[0_4px_4px_0_rgba(0,0,0,0.25)] border border-gray-200 w-[1356px] ml-0"> | ||
| <div className="flex"> | ||
| <div className="flex-1 py-[25px] px-[37px] "> | ||
| <TicketHeader airline={ticket.airline} isDirect={ticket.isDirect} /> | ||
| <RouteInfo | ||
| departure={ticket.departure} | ||
| arrival={ticket.arrival} | ||
| duration={ticket.duration} | ||
| /> | ||
| </div> | ||
| <div className="w-[855px] flex-shrink-0 py-[15px]"> | ||
| <TariffsSection | ||
| tariffs={ticket.tariffs} | ||
| seatsLeft={ticket.seatsLeft} | ||
| /> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| ); | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| export { TicketCard } from './TicketCard'; | ||
| export type { TicketCardProps } from './TicketCard'; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| import { CaretDownIcon, LogoIcon } from '@shared/ui/icons'; | ||
| import type { ITicket } from '@entities/Ticket'; | ||
|
|
||
| export type TicketHeaderProps = Pick<ITicket, 'airline' | 'isDirect'>; | ||
|
|
||
| export const TicketHeader = ({ airline, isDirect }: TicketHeaderProps) => { | ||
| return ( | ||
| <div className="flex items-center justify-between mb-[11px]"> | ||
| <div className="flex items-center"> | ||
| <div className="mr-3"> | ||
| <LogoIcon size={40} /> | ||
| </div> | ||
| <span className="font-medium text-[#808080]">{airline}</span> | ||
| </div> | ||
| {isDirect && ( | ||
| <div className="flex items-center gap-1 font-medium text-base leading-5 tracking-normal text-center text-[#4797FF] font-roboto"> | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Вместо Скорее всего здесь нужно использовать элемент выпадающего списка |
||
| Прямой рейс | ||
| <CaretDownIcon className="text-[#4797FF]" /> | ||
| </div> | ||
| )} | ||
| </div> | ||
| ); | ||
| }; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| export { TicketHeader } from './TicketHeader'; | ||
| export type { TicketHeaderProps } from './TicketHeader'; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| export { TicketCard } from './TicketCard'; | ||
| export { TariffsSection } from './TariffsSection'; | ||
| export { RouteInfo } from './RouteInfo'; | ||
| export { TicketHeader } from './TicketHeader'; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.