From a97bba09833e54939675552824e235c38bb5e61f Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Mon, 2 Dec 2024 22:24:10 +0900 Subject: [PATCH 01/38] =?UTF-8?q?data:=20add=20mock=20data=20/=20api=20?= =?UTF-8?q?=EC=9E=91=EB=8F=99=20=EC=95=88=ED=95=A0=20=EC=8B=9C=20=EB=9D=84?= =?UTF-8?q?=EC=9B=8C=EC=A4=84=20=EB=8D=B0=EC=9D=B4=ED=84=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ..._info.json => bus_ticket_seoul_busan.json} | 0 .../mock/bus_ticket_seoul_daejeon.json | 242 ++++++++++++++++++ 2 files changed, 242 insertions(+) rename src/constants/mock/{bus_ticket_info.json => bus_ticket_seoul_busan.json} (100%) create mode 100644 src/constants/mock/bus_ticket_seoul_daejeon.json diff --git a/src/constants/mock/bus_ticket_info.json b/src/constants/mock/bus_ticket_seoul_busan.json similarity index 100% rename from src/constants/mock/bus_ticket_info.json rename to src/constants/mock/bus_ticket_seoul_busan.json diff --git a/src/constants/mock/bus_ticket_seoul_daejeon.json b/src/constants/mock/bus_ticket_seoul_daejeon.json new file mode 100644 index 0000000..3112cba --- /dev/null +++ b/src/constants/mock/bus_ticket_seoul_daejeon.json @@ -0,0 +1,242 @@ +{ + "response": { + "header": { + "resultCode": "00", + "resultMsg": "NORMAL SERVICE." + }, + "body": { + "items": { + "item": [ + { + "arrPlaceNm": "대전복합", + "arrPlandTime": 202412020800, + "charge": 18100, + "depPlaceNm": "동서울", + "depPlandTime": 202412020600, + "gradeNm": "우등", + "routeId": "NAEK032300" + }, + { + "arrPlaceNm": "대전복합", + "arrPlandTime": 202412020850, + "charge": 18100, + "depPlaceNm": "동서울", + "depPlandTime": 202412020650, + "gradeNm": "우등", + "routeId": "NAEK032300" + }, + { + "arrPlaceNm": "대전복합", + "arrPlandTime": 202412020940, + "charge": 12400, + "depPlaceNm": "동서울", + "depPlandTime": 202412020740, + "gradeNm": "고속", + "routeId": "NAEK032300" + }, + { + "arrPlaceNm": "대전복합", + "arrPlandTime": 202412021020, + "charge": 18100, + "depPlaceNm": "동서울", + "depPlandTime": 202412020820, + "gradeNm": "우등", + "routeId": "NAEK032300" + }, + { + "arrPlaceNm": "대전복합", + "arrPlandTime": 202412021100, + "charge": 18100, + "depPlaceNm": "동서울", + "depPlandTime": 202412020900, + "gradeNm": "우등", + "routeId": "NAEK032300" + }, + { + "arrPlaceNm": "대전복합", + "arrPlandTime": 202412021130, + "charge": 12400, + "depPlaceNm": "동서울", + "depPlandTime": 202412020930, + "gradeNm": "고속", + "routeId": "NAEK032300" + }, + { + "arrPlaceNm": "대전복합", + "arrPlandTime": 202412021200, + "charge": 18100, + "depPlaceNm": "동서울", + "depPlandTime": 202412021000, + "gradeNm": "우등", + "routeId": "NAEK032300" + }, + { + "arrPlaceNm": "대전복합", + "arrPlandTime": 202412021240, + "charge": 18100, + "depPlaceNm": "동서울", + "depPlandTime": 202412021040, + "gradeNm": "우등", + "routeId": "NAEK032300" + }, + { + "arrPlaceNm": "대전복합", + "arrPlandTime": 202412021320, + "charge": 18100, + "depPlaceNm": "동서울", + "depPlandTime": 202412021120, + "gradeNm": "우등", + "routeId": "NAEK032300" + }, + { + "arrPlaceNm": "대전복합", + "arrPlandTime": 202412021400, + "charge": 18100, + "depPlaceNm": "동서울", + "depPlandTime": 202412021200, + "gradeNm": "우등", + "routeId": "NAEK032300" + }, + { + "arrPlaceNm": "대전복합", + "arrPlandTime": 202412021440, + "charge": 18100, + "depPlaceNm": "동서울", + "depPlandTime": 202412021240, + "gradeNm": "우등", + "routeId": "NAEK032300" + }, + { + "arrPlaceNm": "대전복합", + "arrPlandTime": 202412021510, + "charge": 12400, + "depPlaceNm": "동서울", + "depPlandTime": 202412021310, + "gradeNm": "고속", + "routeId": "NAEK032300" + }, + { + "arrPlaceNm": "대전복합", + "arrPlandTime": 202412021550, + "charge": 18100, + "depPlaceNm": "동서울", + "depPlandTime": 202412021350, + "gradeNm": "우등", + "routeId": "NAEK032300" + }, + { + "arrPlaceNm": "대전복합", + "arrPlandTime": 202412021630, + "charge": 18100, + "depPlaceNm": "동서울", + "depPlandTime": 202412021430, + "gradeNm": "우등", + "routeId": "NAEK032300" + }, + { + "arrPlaceNm": "대전복합", + "arrPlandTime": 202412021710, + "charge": 12400, + "depPlaceNm": "동서울", + "depPlandTime": 202412021510, + "gradeNm": "고속", + "routeId": "NAEK032300" + }, + { + "arrPlaceNm": "대전복합", + "arrPlandTime": 202412021750, + "charge": 18100, + "depPlaceNm": "동서울", + "depPlandTime": 202412021550, + "gradeNm": "우등", + "routeId": "NAEK032300" + }, + { + "arrPlaceNm": "대전복합", + "arrPlandTime": 202412021830, + "charge": 18100, + "depPlaceNm": "동서울", + "depPlandTime": 202412021630, + "gradeNm": "우등", + "routeId": "NAEK032300" + }, + { + "arrPlaceNm": "대전복합", + "arrPlandTime": 202412021910, + "charge": 12400, + "depPlaceNm": "동서울", + "depPlandTime": 202412021710, + "gradeNm": "고속", + "routeId": "NAEK032300" + }, + { + "arrPlaceNm": "대전복합", + "arrPlandTime": 202412021940, + "charge": 18100, + "depPlaceNm": "동서울", + "depPlandTime": 202412021740, + "gradeNm": "우등", + "routeId": "NAEK032300" + }, + { + "arrPlaceNm": "대전복합", + "arrPlandTime": 202412022020, + "charge": 18100, + "depPlaceNm": "동서울", + "depPlandTime": 202412021820, + "gradeNm": "우등", + "routeId": "NAEK032300" + }, + { + "arrPlaceNm": "대전복합", + "arrPlandTime": 202412022100, + "charge": 18100, + "depPlaceNm": "동서울", + "depPlandTime": 202412021900, + "gradeNm": "우등", + "routeId": "NAEK032300" + }, + { + "arrPlaceNm": "대전복합", + "arrPlandTime": 202412022140, + "charge": 18100, + "depPlaceNm": "동서울", + "depPlandTime": 202412021940, + "gradeNm": "우등", + "routeId": "NAEK032300" + }, + { + "arrPlaceNm": "대전복합", + "arrPlandTime": 202412022220, + "charge": 18100, + "depPlaceNm": "동서울", + "depPlandTime": 202412022020, + "gradeNm": "우등", + "routeId": "NAEK032300" + }, + { + "arrPlaceNm": "대전복합", + "arrPlandTime": 202412022300, + "charge": 12400, + "depPlaceNm": "동서울", + "depPlandTime": 202412022100, + "gradeNm": "고속", + "routeId": "NAEK032300" + }, + { + "arrPlaceNm": "대전복합", + "arrPlandTime": 202412030010, + "charge": 19900, + "depPlaceNm": "동서울", + "depPlandTime": 202412022210, + "gradeNm": "심야우등", + "routeId": "NAEK032300" + } + ] + }, + "numOfRows": 100, + "pageNo": 1, + "totalCount": 25 + } + } +} From ac5ebd69cea2a4344da6eea8b203377b73c90d42 Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Mon, 2 Dec 2024 22:24:21 +0900 Subject: [PATCH 02/38] style: info button style --- src/routes/booking/tickets/index.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/routes/booking/tickets/index.tsx b/src/routes/booking/tickets/index.tsx index 4386d32..14df9f6 100644 --- a/src/routes/booking/tickets/index.tsx +++ b/src/routes/booking/tickets/index.tsx @@ -123,6 +123,9 @@ function ButtonComponent({ busTicket }: { busTicket: BusTicket }) { @@ -145,6 +148,7 @@ function RouteComponent() { convertYYYYMMDD(searchQuery.startDate) ) .then((data) => { + console.log(data); setBusTickets(data.response.body.items.item); // TODO: 전역 상태에 넣기 From 2af1d1d5c1244592f8ba2161c46665e730c73cc2 Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Mon, 2 Dec 2024 22:46:59 +0900 Subject: [PATCH 03/38] =?UTF-8?q?fix:=20=EC=8B=9C=EA=B0=84=20=EC=B0=A8?= =?UTF-8?q?=EC=9D=B4=20=EA=B3=84=EC=82=B0=20bug=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/getBusTickets.ts | 2 +- src/routes/booking/tickets/index.tsx | 11 +++++++---- src/utils/convertDate.ts | 21 ++++++++++++++++++++- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/apis/getBusTickets.ts b/src/apis/getBusTickets.ts index f7a9b2e..2f8cc91 100644 --- a/src/apis/getBusTickets.ts +++ b/src/apis/getBusTickets.ts @@ -32,7 +32,7 @@ export interface BusTicket { depPlaceNm: string; depPlandTime: number; gradeNm: string; - routeId: number; + routeId: number | string; } interface ResponseBusTickets { diff --git a/src/routes/booking/tickets/index.tsx b/src/routes/booking/tickets/index.tsx index 14df9f6..0e40e6f 100644 --- a/src/routes/booking/tickets/index.tsx +++ b/src/routes/booking/tickets/index.tsx @@ -13,13 +13,14 @@ import { import useSearchQueryStore from '../../../stores/useSearchQueryStore'; import { convertAMPMHHMM, - convertMinutesToHHMM, + getDifferenceInMinutes, convertMMDDday, convertYYYYMMDD, } from '../../../utils/convertDate'; import { searchTerminalNameToCode } from '../../../utils/searchTerminalInfo'; import useForwardBusListStore from '../../../stores/useTowardBusListStore'; import { Tooltip } from 'react-tooltip'; +import MOCK_busTickets from '../../../constants/mock/bus_ticket_seoul_daejeon.json'; const container = (theme: Theme) => css` padding: 15px 20px; @@ -102,8 +103,9 @@ function ButtonComponent({ busTicket }: { busTicket: BusTicket }) { color: ${theme.colors.gray[4]}; `} > - {convertMinutesToHHMM( - busTicket.arrPlandTime - busTicket.depPlandTime + {getDifferenceInMinutes( + busTicket.arrPlandTime.toString(), + busTicket.depPlandTime.toString() )}{' '} 예상 @@ -148,7 +150,6 @@ function RouteComponent() { convertYYYYMMDD(searchQuery.startDate) ) .then((data) => { - console.log(data); setBusTickets(data.response.body.items.item); // TODO: 전역 상태에 넣기 @@ -157,6 +158,8 @@ function RouteComponent() { }) .catch((error) => { console.error(error); + //error인 경우, mock data로 초기화 + setBusTickets(MOCK_busTickets.response.body.items.item); }); }, []); diff --git a/src/utils/convertDate.ts b/src/utils/convertDate.ts index 70bc13f..5e3ecfe 100644 --- a/src/utils/convertDate.ts +++ b/src/utils/convertDate.ts @@ -36,7 +36,26 @@ export function convertAMPMHHMM(datetime: number): string { }); } -export function convertMinutesToHHMM(minutes: number): string { +function parseYYYYMMDDHHMM(datetime: string): Date { + const year = parseInt(datetime.substring(0, 4), 10); + const month = parseInt(datetime.substring(4, 6), 10) - 1; // Month is 0-indexed + const day = parseInt(datetime.substring(6, 8), 10); + const hour = parseInt(datetime.substring(8, 10), 10); + const minute = parseInt(datetime.substring(10, 12), 10); + + return new Date(year, month, day, hour, minute); +} + +export function getDifferenceInMinutes( + datetime1: string, + datetime2: string +): string { + const date1 = parseYYYYMMDDHHMM(datetime1); + const date2 = parseYYYYMMDDHHMM(datetime2); + + const diffInMs = Math.abs(date2.getTime() - date1.getTime()); + const minutes = Math.floor(diffInMs / 60000); // Convert milliseconds to minutes + const hour = Math.floor(minutes / 60); const minute = minutes % 60; From 4e6f60d9f12e3a50c10193aa03a2a19767f13feb Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Tue, 3 Dec 2024 13:28:21 +0900 Subject: [PATCH 04/38] style: add selected star icon --- src/assets/FavoriteStarIcon-selected.svg | 3 +++ src/routes/booking/tickets/index.tsx | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 src/assets/FavoriteStarIcon-selected.svg diff --git a/src/assets/FavoriteStarIcon-selected.svg b/src/assets/FavoriteStarIcon-selected.svg new file mode 100644 index 0000000..256eab8 --- /dev/null +++ b/src/assets/FavoriteStarIcon-selected.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/routes/booking/tickets/index.tsx b/src/routes/booking/tickets/index.tsx index 0e40e6f..b719978 100644 --- a/src/routes/booking/tickets/index.tsx +++ b/src/routes/booking/tickets/index.tsx @@ -153,8 +153,10 @@ function RouteComponent() { setBusTickets(data.response.body.items.item); // TODO: 전역 상태에 넣기 - //concat(data.response.body.items.item); + // concat(data.response.body.items.item); + // 기본 adults 요금, teens 요금은 20% 할인, children 요금은 50% 할인 + // throw new Error('dd'); }) .catch((error) => { console.error(error); From f4055bd1c014552388747f4f7df7fb32f12d6e1d Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Tue, 3 Dec 2024 13:44:59 +0900 Subject: [PATCH 05/38] =?UTF-8?q?fix:=20forward=20store=20=EB=A7=A4?= =?UTF-8?q?=EA=B0=9C=EB=B3=80=EC=88=98=20=EC=98=A4=ED=83=80=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routes/booking/tickets/index.tsx | 3 ++- src/stores/useTowardBusListStore/index.types.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/routes/booking/tickets/index.tsx b/src/routes/booking/tickets/index.tsx index b719978..a7483b4 100644 --- a/src/routes/booking/tickets/index.tsx +++ b/src/routes/booking/tickets/index.tsx @@ -153,9 +153,10 @@ function RouteComponent() { setBusTickets(data.response.body.items.item); // TODO: 전역 상태에 넣기 + // 기본 adults 요금, teens 요금은 20% 할인, children 요금은 50% 할인 + // concat(data.response.body.items.item); - // 기본 adults 요금, teens 요금은 20% 할인, children 요금은 50% 할인 // throw new Error('dd'); }) .catch((error) => { diff --git a/src/stores/useTowardBusListStore/index.types.ts b/src/stores/useTowardBusListStore/index.types.ts index d7cbd7b..81fb387 100644 --- a/src/stores/useTowardBusListStore/index.types.ts +++ b/src/stores/useTowardBusListStore/index.types.ts @@ -2,7 +2,7 @@ import { BusList } from '../../types'; export interface ForwardBusListState { forwardBusList: BusList; - concat: (backwardBusList: BusList) => void; + concat: (forwardBusList: BusList) => void; deleteByStartId: (startId: string) => void; reset: () => void; } From 363aa41b9eac6ddd3aea5e468826270de977de32 Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Tue, 3 Dec 2024 14:17:30 +0900 Subject: [PATCH 06/38] =?UTF-8?q?feat:=20API=EB=A1=9C=20=EB=B0=9B=EC=95=84?= =?UTF-8?q?=EC=98=A8=20BusTickets=20BusList=EB=A1=9C=20=EB=B0=94=EA=BF=94?= =?UTF-8?q?=EC=84=9C=20=EB=84=A3=EC=96=B4=EC=A3=BC=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routes/booking/tickets/index.tsx | 27 +++++++++++---------- src/types/index.ts | 4 ++-- src/utils/convertBusTicketsToBusList.ts | 31 +++++++++++++++++++++++++ src/utils/convertDate.ts | 2 +- 4 files changed, 49 insertions(+), 15 deletions(-) create mode 100644 src/utils/convertBusTicketsToBusList.ts diff --git a/src/routes/booking/tickets/index.tsx b/src/routes/booking/tickets/index.tsx index a7483b4..a891bdf 100644 --- a/src/routes/booking/tickets/index.tsx +++ b/src/routes/booking/tickets/index.tsx @@ -5,11 +5,7 @@ import LeftArrowIcon from '../../../assets/LeftArrowIcon.svg'; import FavIcon from '../../../assets/FavoriteStarIcon.svg'; import InfoIcon from '../../../assets/InfoIcon.svg?react'; import { useEffect, useState } from 'react'; -import { - BusTicket, - getBusNowTimeAPI, - getBusTicketsAPI, -} from '../../../apis/getBusTickets'; +import { BusTicket, getBusTicketsAPI } from '../../../apis/getBusTickets'; import useSearchQueryStore from '../../../stores/useSearchQueryStore'; import { convertAMPMHHMM, @@ -21,6 +17,11 @@ import { searchTerminalNameToCode } from '../../../utils/searchTerminalInfo'; import useForwardBusListStore from '../../../stores/useTowardBusListStore'; import { Tooltip } from 'react-tooltip'; import MOCK_busTickets from '../../../constants/mock/bus_ticket_seoul_daejeon.json'; +import { convertBusTicketsToBusList } from '../../../utils/convertBusTicketsToBusList'; + +export const Route = createFileRoute('/booking/tickets/')({ + component: RouteComponent, +}); const container = (theme: Theme) => css` padding: 15px 20px; @@ -30,10 +31,6 @@ const container = (theme: Theme) => css` background-color: ${theme.colors.gray[3]}; `; -export const Route = createFileRoute('/booking/tickets/')({ - component: RouteComponent, -}); - const buttonCSS = (theme: Theme) => css` background-color: ${theme.colors.gray.white}; padding: 16px; @@ -153,9 +150,9 @@ function RouteComponent() { setBusTickets(data.response.body.items.item); // TODO: 전역 상태에 넣기 - // 기본 adults 요금, teens 요금은 20% 할인, children 요금은 50% 할인 - - // concat(data.response.body.items.item); + concat( + convertBusTicketsToBusList(data.response.body.items.item, searchQuery) + ); // throw new Error('dd'); }) @@ -163,6 +160,12 @@ function RouteComponent() { console.error(error); //error인 경우, mock data로 초기화 setBusTickets(MOCK_busTickets.response.body.items.item); + concat( + convertBusTicketsToBusList( + MOCK_busTickets.response.body.items.item, + searchQuery + ) + ); }); }, []); diff --git a/src/types/index.ts b/src/types/index.ts index 8c60e15..0b9ce7d 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -25,8 +25,8 @@ interface Bus { destIdList: string[]; company: string; fee: Fee; - eta: number; - class: Class; + eta: string; // n시간 n분 + class: Class | string; // string으로 '우등' | '고속' | '프리미엄' | '심야프리미엄' 등으로 넘김 seats: Seat[]; distance: number; isExpress: boolean; diff --git a/src/utils/convertBusTicketsToBusList.ts b/src/utils/convertBusTicketsToBusList.ts new file mode 100644 index 0000000..94ecc54 --- /dev/null +++ b/src/utils/convertBusTicketsToBusList.ts @@ -0,0 +1,31 @@ +import { BusTicket } from '../apis/getBusTickets'; +import { BusList, SearchQuery } from '../types'; +import { getDifferenceInMinutes, parseYYYYMMDDHHMM } from './convertDate'; + +export function convertBusTicketsToBusList( + busTickets: BusTicket[], + searchQuery: SearchQuery +): BusList { + // 기본 adults 요금, teens 요금은 20% 할인, children 요금은 50% 할인 + return busTickets.map((busTicket) => { + return { + startDate: parseYYYYMMDDHHMM(busTicket.depPlandTime.toString()), + startId: searchQuery.startId, + destIdList: [searchQuery.destId], + company: '경기고속', + fee: { + children: busTicket.charge * 0.5, + teens: busTicket.charge * 0.8, + adults: busTicket.charge, + }, + eta: getDifferenceInMinutes( + busTicket.arrPlandTime.toString(), + busTicket.depPlandTime.toString() + ), + class: busTicket.gradeNm, + seats: [], + distance: 0, + isExpress: true, + }; + }); +} diff --git a/src/utils/convertDate.ts b/src/utils/convertDate.ts index 5e3ecfe..70201f8 100644 --- a/src/utils/convertDate.ts +++ b/src/utils/convertDate.ts @@ -36,7 +36,7 @@ export function convertAMPMHHMM(datetime: number): string { }); } -function parseYYYYMMDDHHMM(datetime: string): Date { +export function parseYYYYMMDDHHMM(datetime: string): Date { const year = parseInt(datetime.substring(0, 4), 10); const month = parseInt(datetime.substring(4, 6), 10) - 1; // Month is 0-indexed const day = parseInt(datetime.substring(6, 8), 10); From 8feeaf9f9e81ced10f6e6c76aeb51f5177e55589 Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Tue, 3 Dec 2024 15:09:31 +0900 Subject: [PATCH 07/38] =?UTF-8?q?chore:=20add=20kumoneygo=20=EB=B0=B0?= =?UTF-8?q?=ED=8F=AC=20=EC=A3=BC=EC=86=8C=20QR=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/kumoneygo_QR.png | Bin 0 -> 11391 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 public/kumoneygo_QR.png diff --git a/public/kumoneygo_QR.png b/public/kumoneygo_QR.png new file mode 100644 index 0000000000000000000000000000000000000000..3765e641d84ef69b075f1cfe832e90f0c708d495 GIT binary patch literal 11391 zcmaia2Q*w?yS{E>lu=>?(GwzCq6X1}sG~lpsmK5_i1YX6%cH&OZw`z|NOl(3J7 zaHWmABvJhdD*ATHpvnZB7NT34MTdDt0dP^PuF7Joi7&phfkwyP7ZERCHTxnDjb4q_ zy5FK~7x}+F_p}0@3-rw+9%#Wuw7+Ms1d>mL#>apjcd!Q{!7sZp*gODqqrf{f_3g!`>Bl%q1_rpsw2ez`h z`ohgktZ4Z6@82UM27C+xA_2!+mSt~6wY|4znoybs&ssAQL4NC`VH}3yubcT8qw6h% z*y35FA@N<_^%h^B`P`mukDw_(xc5+de+S=gR!Z=Ij{yhhM+M4b5t;|RUJ3Xh-#{`G-K}+p{*U8!z(T>eu|iR@(A5- z%M#I!uVB1S5UbKcFKhv+Dkj_H#cCswNHJz{pS#SlN5{vh=6X9!`p*>IZ~2FzbqGqB zt3J-Log%D`D>A9emM?#^UvdR^L0d~*26ebtV&dY~0$OT5rKP1+Vh>xNtJ{*Qp3=@a1=CYMoR4YgZQDny$Ws#2^vJapZ?(ZMF-&cx^W z0RaJ)rKYB)lT%Y^eM@9yWIulV;Bg3ab91w?;YjVPuBkCLHg2f+R$FUg&#g=@aN3eL zmmK9JAr8IGJ7*;L08K?jY^+yEj2YYQ(RI~QW_c>I>5Q*Ubg?S)EX3iJ38l@5XP=I&~A1 z)F)A8WkQO5z<<1RZ4NPLC_;_Uo!A08@Xzpqf`VN4KaaeiczmJ-^hZL2H#0M1H4*h8 z;4I$ZuR!)3FDa zxtt$2WR>4}_|s{k%#uaIO=RV(ZF{)o_t*aO+<|}&5ZQgcEBBLE%hv=bE- zWi)bhbhP{WArBfi&Qhglps$=8EHbJF2fA~(E{bv?;TKAtQf8|ZfRlRbMVsL-ThC^%kT*|;Og%F z%k#Li^NBhM$%4%((a8n4i;qL=QH0aTu@Tiny`$yNd3o&#%4%v6yoVtbD8`m$*GF%n zM3z{2)6Ia@W^Lz|5ffV+BmCo~l#|e1D^~~IxmiUZx8F9T8Fp_OG&$N-yg6I6cZxYb z-WFzze#Z!0fTAQ*JmgU?sa-QEiZF9-yV!VAn3_$t=dy^B?gJOw-(J&B^ znkuF^uuhJ^P9z9x38k)BI88yKy|l&(AO?F<(-cp8O&H9({bg|cwW>N}TZ~uOO~}97 zz{>%D@HxD?xR@eGj<2X5FVWJ4Y*!Sa%VF~=cQM^Xt4Vy+(uj3?_)(>ZhQiH16~uKa{^w%IVX9%O&w`it@-)29a0t<7B4JI*rgu!W^OsY zo9m<27Ovi4cwWYL>wTd8GZZR~#XZ!kx|&h-?Oc5E>l>dVNEc5rh(HqRw8S`bsj`*< z-Q;R_h0K9pXJC#Gs?ufKbwu)6mg5bfp`r6ja$;hmlan9Sc>rYv%RK*2bz(Su?VAQ@ zn>xv_u)_?Y7Rg~xPe46YIoJPsJ&Km7x1hGN1sP#kFH%TqKcW(MZX&G5jy&G`VfTA@ zv&5W39c}L>y>NGDyLD@K?d{zB{Csz}y0^FY-J}OhDs{!1!9MfP1SCX7m20R5e*TPP zz0)T7?hQZf=KJDNGbK?vENZ)C>MC|CUYPY&`N+t~`O&6mQKiQ$7I2)|@my84wSC{e zv{aTJ9lZ|S1(mr#Bmx1uHRHJiSfhomczUrf!TxNWBxmREIf! zUZAiTJKBDQM11vJQ07(twHDZ` zBqpccnEck2-I4h?fSOfmE+_togVmaYM3Q5n9`IAYS!)jt4{wyYr8%0IObidd+as>Y z&(8s3hUjLc7;44KAzdU|}M z1>GxNqyesDC-BlUkVG+>irk&pM7)S~^W{rtXFk_z;OVsPipt1DvyMzoPHNrd_TpdB zVrFJ;e5mklG!32(6(RBm)8HMr>2d&P`SV3I@*H%+g^Vh3BBqZeP*9T9BSXo$D zn3%ekyuN(-lAN3@w6U?dc{s>6eV73khWy;`2nW1okD;p3=0+{2ff`T8CwqG!qTeojlhlLFM4R=yJLclE>ga5Pu z5rV2n-6=wjIrfaBbjVpOYruSoAS>g>0BYkjqrs1`HUtO;lKkN3=jX3z+{KtTx3_D1 zN!XOFLVf}7IlI4?!d)(F;uum^P*8y5j;2E(@X1hy`HD~3M&i!RUZFD5(!~o=xrY2k zy=YK?m+C01iDDL~}+ zD+Cy=q^qm@{5kjJ2MGy@ql1I@cY4ikj9Wuip_NY6WH^9sf*C0dCmE z)peRmBb+|E6DXORnN3Yi0j7D*(9iSP?2TiT4lC=fr%@kO) z<;;!TZQ|HE<_BMOLsmakSy6TSoOV|M9I$ms26FI zZYfFmtXt3+h_<%&^z^ibS@?@I;5W_$aVy5+_w|PX5zg$+(_eI_2y9c+<;qZ=)PzPG z9u7o366s5hA!I8isJt>t#gcO4P%XkR1x^sCsZueTR}_{s6a9x^>POHE%rViF8?6|G z$f2i;o~6ofkKS~(DUvFi%56MZ(pAAeS|J3&rzr;qswzK^n(~0$QO32VCc^^UyMicU zrEDOsdpS7YGgj%8(erxbs%c9%wDr!9IM^VELCb^a9Rg zJeER#J0m1iEdBDNS)nK*Sbf_PS@v{Y_!*HvBx8sd>kO4eh+?o$v(1eP4l|P88FgA{ z9b3`DSz{z`;o!+xqzzAXot)A|TZoBgu!n88+W40K0vFM`Fe0yc(C#h=PVIy-9AUpH zBrb%iz|wQV7#Ta9sN3@hW|dw(xn~Z|A)s9gZDRz5?D2Dhj>#eMp`7d(_uez9oaF3L zoby*wrEJ-!l zp9=b`B=(o3=$y~qcw&#FkiGF{AhGa#* z#<2zMk$D-j364a_H6Y2UueqUI4;ai5ppffPdbjMdtj`(1jx0mehQqcNv4y%O17kkb6E0uIk~Dqs$=G-3;|+1yJ=J z_N6I=&E%gy1^O;`&r@&EV#HBUGiNPYo@J1`bgo4@jX;3u8@Lq1-E!jgh){X4Rge`& z-Hmu+oI2*MS5PJaXi0iy4)paBk7*|F^=^hM)Kg1KDY+s2m{&sf^arS4*veb8@A9Yr zGlPio`0loZc;1w6S8enxd|^{cA%{?Xk;R4N$$1j*jxw z;)R5S!rSq{S;$S|{>fsHG`%l}6>P3l>cjd(*=fhC^w%>@Ys26e3LJOd9oMT^Ume78 zC%tZy2y)})`NSJ55g~Z0JH~;AhM_|}YC`SdM=fvfeIN>1b=moU!;ynlb}K~3n)*s+ zx^i>CpR~9<&GnW+$ zA>k&Z#Q$v5$_R1_yUzkm#t%QT-nwPFS{S8b=jX@7Bo!7!c#I-q|6%)z2RE+o!sv7M z1mnOuebzZY8gtnvdyk2OOM>J5V_6u4+u;yg$Cs=G7?j*9?t&NLTRI^&G-1?TH{UT$(ENCV7$CCUR z>_+9o9UoT`6m+lH%%R!Y#bs@4ORliA`ulhDMWwswo9YUy1_ytZ$E@iv(&tDMV-(Og z6lBF$;$nYUE@OHheRGs<#(&uqIhEz7mGi{<%|d<0&egXofpUmn!viojET-}p*S%yO z88H>)nmnL;lSF8|faCaRJo;M@!#@qLy{}Wgp9M9Kz&hGJ{$3w7aXW23{!}*$i6g&qC^;l%Y3PgFFvb^d{sFT}aQYA`PB>5N>)Mz zczH}(MSeSUwH6Tg>5JSppY_|qWFV*aMkKb` zc-TmR&w@BYvJpi&Evu{Y2=6~vf_B#>en$%&^7ASn7IV+dC<;5^0LRpIX)Hp z_ynh&>YC*0H$>LBF?|fq;=_ch6mcEQD_d`~UtH0|T~#?w`-kSKbr--@J2&$ z9y*G0%bVib-bQ?ljz$NYN!v}5qD{{%N{fn$V#?yelnQLiqEzH-YKrr>76Rk~x1DNn z)yE&NTqUe(+z-txQR;X`k}saK!ie0@)O6Qp4dJg!CggS}g=w%si!|HLmqV`Hw=d5h zULRfUmyAnJSeoeR?Ru2Cicl^XOiW*-_l(|Iw%pmy^4lo!MgHyGmz;r5I*yc{9C+aN zKALY^@CgN7p6g=0yACnFVEBAJl2bAw4*um!>0C5(JPN9DkOA)O{Ql;8UtaEH z#cRKNO-2)9LV0dFJ2^TkCM(-mQDI{`-qzN(v$JEW*SEaiWB-sY>ci6W?k==ZqB_q< ztv5x7UbrESr#uXDCv#bm=}yISpL+O9oTtBV+zd;zxKTf05QwoG4+yR+H2g5S%{zEN zMnobx&AHp%<*5GEq$qGv5{((ZV}WFUBo{b;%@(kfkz|nbcJL;PP{RW&mKzy?Pj-Mi z!m(_R3H`jr`(AAz8{zPrlOcT03#MAD zWE^r9i9@vBZMwLrm6GR|<=5cAa&OmeYoPu(GZ~4I3lu9*u{^|7@oV;RyND->I|bHdCoR zxo~1aRC-yWAA&Yard<4Rmpz<3OJU-N|1L6zdMyIpjv3 zFSLi-A~tJ%gYZWI8sr#YRi>|gr*_Q*ET<1Vu0A(tE=-+hz$paJ6}a-SS;Gc@^wucC z6t()h3Xw;-woJ7aAEl-Rm$63$e$$uQ zz8Pn$G*r{Uyqe(pT0`zTM_`JnXOj{wH#;;CvS;Hgg=d}O66L3z=Fjspy~b};n3roX zhwtu7#=r1&;pg!3z^H0$Kp6@iX;z1{8M^v1FVdrFvUKV=YswA=n*Dbtzc&vVo$c2* zuV#F_-g!Nigr=cvmumK!Hr;-FJ^Gy@8tiR04PuAX*Sh^{?2%7PlM1%Q;;>M+tG=;= zQ2FcK<8U$!OHzoyg9$q}AH|s-1;u># z@-Hj~XGJ5|T=zTS^kT4My`&AVYx$?*v`st3fvWk@88Y13tg_VU%4Yla1P)N-&Fe$? zCF|Q1CSgJQQ-&}5?{pRF%3hAJH_3Q=U8eP>HV^yu_}`bChb6OFEWUP`>`^+g;A@m0 zYjWtZAO8ChFlTLg@7Lmk2;+%Ad7T46LDx)RK-bmJ_@Kjm(d!Yh7~Rppi=H@n{)|Sy z<;AGk^ZllQ+owGr%j*vs!I^c)i4+49BNLQcGZ4VHEi3f}(MG9kklzv#5Fl8X2cdy} zL&+uH&kAb{vG`qfYnHS7JDsT%<<7rb1H0Gnr2&@n$hG`IX{wd{S(__&(#UqX>CMa7 z=<>$PwRICUTZ8fy+7Fy1?-!n#i0a+`Rmly`-Nd_;_;tgZq7wq(=l`3Fqjx^yPZA+*bTpL`ToT=yTD#;r^VuS9zL>ojn5 zRG)qlpsm_~e(tE3<+X(LP9bzsIMNQmY4aAh0ma}b>R+}`CS9eMMNP#1V%^$ORI!MS z5WW|guiE~je`#OF2{R-67Q!d!Hu#=m`t}Zje(wOj9pKX{70hm4K*GkM`og;Kz#AS?FC*xcSvpxpr6GtK9kK+1*>*1S?k%U55d7MTMG%l*l&|LzL^?bzha5nKCYx zhkB5z5_NaqES&8l`!i)stX)LT@{aYmT8I84h+9jEma_*gXZ|Q41FzCA+Ff|^}!r z`#aMVFvL~oyKVK<+MlFJ1jHc>>z?#kM%Suxx#5{%m`S(dnlSB=j@7OR8upYo8b%%9 zPy&5obc%K))aq7L1t|$2vr*C*Mju6@bV3&u<|Rx?)J@HxBN1ZdXUEgV2-z6n*+mq( zC8&DPCwwySd-uWZC6;kGfQz^zpKINp$c*6uD~Ti?`VOKX@~$nBp{!^Y$W0of8Q*!6aEFSf{}~YNefcZBNIa%I9tIX~W9%I`idu)^ zj2Nuh69H5K6wYi5CSm=OY@%1%yu&u``;H0_0!d8?xv17iQ&t`^v81%uiw*9lPbqPC))|Q)y8`YZ8;-%TP=kbVI_UE713J#>tArW)dig{#e|5Toe5 z;GE!PB5Ei4xUA*Sb-Cz|3@xx0Z^DRg_ip<;g#*Zn6eux_q?guDXfFHdwqSqal5Apk z~j;&DqyYl!VGovQJZJ&Po5SYEj%*80Lv&Tn?la5hKqONVu*XKO|zUmqg!$ zoS_*T{75J-3GepJAhQO@3ptn~%7e4FN0p%Q1n8k&h2S2F0|cA`{&#YS|rnKg$rn4}PdRI4ppS$UdgBJQFV5wk>39I08r>>OF&w^G%^XcB@?jW&| zJ6AwR{JY$nx{S^&7%NUh7()tLo~<}+qkvynMDJM@R}axkjNtWp{-lS$Q{IKwSc>fY#aIn$%aM?yptcqug``t|KBJA5(`StHgt>;Q%tFXi+x3E; z&d$15UgcV_hGvhG)nhp+W5V-{AFh~4n$E6LcY%tkTd!he?~uNYnT^21>j2z6yNC}=q$aGnL~;#sE^y+J~So(1=l3a1LK5?+WA+r z75%ei0Z6q%L)sa}#y4<@5-WJ&_{}se~JgPF!aYTG%6@s&a= z0F%R{V43G=3ws|51RiMbB2mQ5S6*iw6CdyNZ4va+t$->mH|HXjHTykRKv7%f=CE)UR9q7aX0Zm<(jOGcz-layVqLDb(GX zbQqRrmL7OKcO{%?i5XUD>1HOt2#^V6*(7~9*y5MH>H&~m7!Xz0zL`OID?zaF4GFJO zHb?M7%PnkPULMAQsVSRl zN`}OM>tNM+oYl%y5Y0hGSKMvQ!Vx)V#&Fx8{r&kPtIxaQZfS8O7Jg<_@i=W>7}EUu zY;>2T@G-_vDDh$l?uU2VJ+hb#AYP^#7zAG`=m*CkEXEP`5UTiYp~!0Odys zNk@A{buFOug={FJf+6~y`4(|hrQ7f6X8+ebi+g-*EEOf?qF4R+_;_!x2J|(6YH7R` z{<}%QWHkRo5YP0Yr|Uk;=K^!%gw0g<|B>Hu#XpphN$;^QE-C4&tjWnybU}E!OLi2| z3A@|?vVfKQ9b}WMDL3uYU-90(+uPvtUZ;?kmsjwWmX1!r$P3R3TE`{t@nAjEV`4mx&+1&>}5 z_MV~VeqI3vC@wAz#<%!%{(n*r#Ll1GsI$SbbKqDs2)T~QgSiMzeLX#ghU)6;>tFt< z@y{$Bt`P2;e!>=5R-=kXc_M>F0#HN@TQme{!pgEp&)c_ezZ)JM8p1#Ic|XBtA+kjS zar8D&IK3pyW>UZW3~*Qc55?^t<-pVzEy!@-NpUi0%sFw`B#r?VgbWU(G?dEBi!ZI#ukvdF|QHSA{uPzNfz;QJpu zbJJF>)(emUZbBRL!lUrNp9b<^Y<2jAPQ zSUHWu9F6$J3y-%1cn`xUXiNafG{z`5Vx^4@MG#iRBxB7Kpve(&p2n-lNwd$J3u zO^~p*=lTDMw@L!6C*Y_En3+oArFfL*OSWV1krIgF5=f25#l(~zjHqxukd+mXf#HNL z+<#_?$@}AhlL~NfaqEc2!~JY+6<=o)%?KN=RWlU`Fsx;Nq{9hkcVpejClmwhIMF#{ za2CH|X~-57X78GSmv+___$*Sz>`ts}mKwb+EYNC_P^?(6A8b^uT+&oYh$T|$X$>K{ zRaL)DOm3~1N%nD+7&k`!RxSecJ|aPoRZ-?S{}@=>!6Wo}kz$GR_$x{aBctTeK|>>>)+8rd0y!G9 zHI)~Mf~>n8WJ^}g4-hSKqet6D81m+$Dc9Si*N}HTi-Us+q1Pn#zv5b64es0wR+XNQ zqN-FDBqDuW_xLEMpoDxD8~A;EJ&$lgk(&<_5)IMw-v9h6!0;%VoXt;RZC{PeZ;r4X z>YNiwCNxhYSi@+g5Mwwg4D|dfL*|Yk)_eJv{lgb0M1nqpEl)0TI>+0beG3`n;xd)*JOpL(3p^=tM-%heT1mN_*J9-5 zpOTUi>%hY?Di#Tt=E&mW;@|%C!h(VgYh!Ec>uBo>qBJIp8u^PI?s(bx`gn;QEtenWE5`5p z{YRssqAEKOt3GeMyoU9=78gHvla7vjD0uYX0iomsy9pylel9J@y{$IEOplD@JfDS` zx!3G_LxXfu&(B}KxF!ZRHr(zeVSsq6Zz?>TtekQu#0$tPW(09o=kgpy|8H(llluAd z=fuRs^%iB-)zy`i!|05rrY1JCg6|LCos(jMILrTOsgwio9I501Y9HWt{oYsC)f3mp zbjyvj{E3kFi+dd1?$x0vf@?qJ`UbH_I-fW%3~bbL%@miGMvn?H<>j=m4D*W=>og6{0jR=(Wn+C}gA{7GM4LhJ~d z*HBVYuK1maCTjq(g4<+eXJ-H~6RL=|6OYN9g5a5B^12n>PP+%GeXF^BkzEV*7CIL$ z-Cjgqfnk8itTlU1f_nmSnXe!N#pB11V`F3Oy+{5{Dox>Yy@Seb=6HDZr|S&NwMuqM zFdKwG$foz#04rZrH99`tz;aE+`#&N}(^jY3kqZHV%U;~KZ37EAJ`ZmWj9_z{H;*&i_CkI?Ex!E2d3^{#EGBsRL`S7e$p-Zw=?Oq$ literal 0 HcmV?d00001 From fd702116201d8adc138322f4b7e368adc31f6938 Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Tue, 3 Dec 2024 17:19:42 +0900 Subject: [PATCH 08/38] style: add tag reset css, button width --- src/index.styles.ts | 11 +++ src/routes/booking/tickets/index.tsx | 108 ++++++++++++++------------- 2 files changed, 68 insertions(+), 51 deletions(-) diff --git a/src/index.styles.ts b/src/index.styles.ts index 0ae2da8..bdeb65d 100644 --- a/src/index.styles.ts +++ b/src/index.styles.ts @@ -9,4 +9,15 @@ export const globalStyle = css` * { box-sizing: border-box; } + + a { + color: #fff; + text-decoration: none; + outline: none; + } + a:hover, + a:active { + text-decoration: none; + color: #fff; + } `; diff --git a/src/routes/booking/tickets/index.tsx b/src/routes/booking/tickets/index.tsx index a891bdf..a6cacea 100644 --- a/src/routes/booking/tickets/index.tsx +++ b/src/routes/booking/tickets/index.tsx @@ -32,6 +32,7 @@ const container = (theme: Theme) => css` `; const buttonCSS = (theme: Theme) => css` + width: 100%; background-color: ${theme.colors.gray.white}; padding: 16px; border-radius: 20px; @@ -66,69 +67,74 @@ const buttonCSS = (theme: Theme) => css` function ButtonComponent({ busTicket }: { busTicket: BusTicket }) { return ( - + + ); } From 6b2aa23f0353289a3a8af5669d2bf6eb4eb266f0 Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Tue, 3 Dec 2024 17:21:45 +0900 Subject: [PATCH 09/38] style: change tag color to original --- src/index.styles.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/index.styles.ts b/src/index.styles.ts index bdeb65d..c2fdc57 100644 --- a/src/index.styles.ts +++ b/src/index.styles.ts @@ -11,13 +11,11 @@ export const globalStyle = css` } a { - color: #fff; text-decoration: none; outline: none; } a:hover, a:active { text-decoration: none; - color: #fff; } `; From cc69d3ef015c093a0103d7ff8eb6f9ab0d838410 Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Wed, 4 Dec 2024 13:43:56 +0900 Subject: [PATCH 10/38] =?UTF-8?q?feat:=20convertDate=20=EC=9E=85=EB=A0=A5?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20Date=EB=8F=84=20=EB=B0=9B=EC=9D=84=20?= =?UTF-8?q?=EC=88=98=20=EC=9E=88=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/convertDate.ts | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/utils/convertDate.ts b/src/utils/convertDate.ts index 70201f8..20003c2 100644 --- a/src/utils/convertDate.ts +++ b/src/utils/convertDate.ts @@ -21,15 +21,22 @@ export function convertMMDDday(Date: Date): string { return `${month}월 ${date}일 (${korDay(day)})`; } -export function convertAMPMHHMM(datetime: number): string { - const date = new Date( - Math.trunc(datetime / 100000000), - Math.trunc(datetime / 1000000) % 100, - Math.trunc(datetime / 10000) % 100, - Math.trunc(datetime / 100) % 100, - datetime % 100 - ); - return date.toLocaleString('ko-KR', { +export function convertAMPMHHMM(datetime: number | Date): string { + if (typeof datetime === 'number') { + const date = new Date( + Math.trunc(datetime / 100000000), + Math.trunc(datetime / 1000000) % 100, + Math.trunc(datetime / 10000) % 100, + Math.trunc(datetime / 100) % 100, + datetime % 100 + ); + return date.toLocaleString('ko-KR', { + hour: '2-digit', + minute: '2-digit', + hour12: true, + }); + } + return datetime.toLocaleString('ko-KR', { hour: '2-digit', minute: '2-digit', hour12: true, From cb231861d60cc93b072fdaba6b4f382eeccc766e Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Wed, 4 Dec 2024 13:44:44 +0900 Subject: [PATCH 11/38] =?UTF-8?q?fix:=20=EC=A0=84=EC=97=AD=20busList=20?= =?UTF-8?q?=EC=8A=A4=ED=86=A0=EC=96=B4=20side=20effect=20=EB=B0=9C?= =?UTF-8?q?=EC=83=9D=EC=9C=BC=EB=A1=9C=20=EB=A1=9C=EC=A7=81=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20-=20=EA=B8=B0=EC=A1=B4=20=EC=A0=95=EB=B3=B4=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0=ED=95=98=EA=B3=A0=20=EC=83=88=EB=A1=9C=20?= =?UTF-8?q?=EB=B0=9B=EC=9D=80=20=EC=A0=95=EB=B3=B4=EB=A7=8C=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=ED=95=98=EB=8F=84=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routes/booking/tickets/index.tsx | 32 ++++++++++------------- src/stores/useTowardBusListStore/index.ts | 2 +- src/types/index.ts | 2 +- 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/routes/booking/tickets/index.tsx b/src/routes/booking/tickets/index.tsx index a6cacea..1a181b1 100644 --- a/src/routes/booking/tickets/index.tsx +++ b/src/routes/booking/tickets/index.tsx @@ -18,6 +18,7 @@ import useForwardBusListStore from '../../../stores/useTowardBusListStore'; import { Tooltip } from 'react-tooltip'; import MOCK_busTickets from '../../../constants/mock/bus_ticket_seoul_daejeon.json'; import { convertBusTicketsToBusList } from '../../../utils/convertBusTicketsToBusList'; +import { Bus } from '../../../types'; export const Route = createFileRoute('/booking/tickets/')({ component: RouteComponent, @@ -65,12 +66,12 @@ const buttonCSS = (theme: Theme) => css` } `; -function ButtonComponent({ busTicket }: { busTicket: BusTicket }) { +function ButtonComponent({ bus }: { bus: Bus }) { return ( - {busTickets && - busTickets.map((busTicket, index) => ( - + {forwardBusList && + forwardBusList.map((bus, index) => ( + ))} diff --git a/src/stores/useTowardBusListStore/index.ts b/src/stores/useTowardBusListStore/index.ts index fedbe3f..ffb3dba 100644 --- a/src/stores/useTowardBusListStore/index.ts +++ b/src/stores/useTowardBusListStore/index.ts @@ -11,7 +11,7 @@ const useForwardBusListStore = create((set) => ({ concat: (newforwardBusList) => set((state) => ({ ...state, - forwardBusList: [...state.forwardBusList, ...newforwardBusList], + forwardBusList: [...newforwardBusList], })), deleteByStartId: (targetStartId) => set((state) => ({ diff --git a/src/types/index.ts b/src/types/index.ts index 0b9ce7d..7a0fa55 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -19,7 +19,7 @@ export interface Seat { type Class = 'economy' | 'first' | 'premium'; -interface Bus { +export interface Bus { startDate: Date; startId: string; destIdList: string[]; From 91f5fd569cadc69e9f18c12076c8c74bf3b503e6 Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Thu, 5 Dec 2024 17:06:37 +0900 Subject: [PATCH 12/38] =?UTF-8?q?feat:=20searchTerminal=20id=EC=97=90?= =?UTF-8?q?=EB=8A=94=20NAEK=20=EB=B6=99=EC=9D=B4=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EB=8A=94=20=EA=B1=B8=EB=A1=9C=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/searchTerminalInfo.ts | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/utils/searchTerminalInfo.ts b/src/utils/searchTerminalInfo.ts index accb158..dd6942a 100644 --- a/src/utils/searchTerminalInfo.ts +++ b/src/utils/searchTerminalInfo.ts @@ -17,10 +17,17 @@ interface ResponseGosokTerminalInfo { }; } +/** + * 터미널 코드를 받아 ㅌ터미널 이름을 반환하는 함수 + * @param code 터미널 코드 (NAEK를 붙인 코드 | 숫자 코드) + * @returns 터미널 이름 + */ export function searchTerminalNameToCode(code: string): string | null { const terminal = ( TerminalInfo as ResponseGosokTerminalInfo - ).response.body.items.item.find((item) => item.terminalId === code); + ).response.body.items.item.find( + (item) => item.terminalId === parseBusTerminalId(code) + ); if (!terminal) { return null; @@ -28,6 +35,11 @@ export function searchTerminalNameToCode(code: string): string | null { return terminal.terminalNm; } +/** + * 터미널 이름을 받아 터미널 코드를 반환하는 함수 + * @param name 터미널 이름 + * @returns NAEK가 없는 터미널 코드 + */ export function searchTerminalCodeToName(name: string): string | null { const terminal = ( TerminalInfo as ResponseGosokTerminalInfo @@ -36,5 +48,17 @@ export function searchTerminalCodeToName(name: string): string | null { if (!terminal) { return null; } - return terminal.terminalId; + return terminal.terminalId.slice(4); } + +/** + * NAEK가 붙었는지 판단하는 함수 + * @param busTmnId + * @returns + */ +export const parseBusTerminalId = (busTmnId: string) => { + if (busTmnId.length === 3 || Number.isNaN(Number(busTmnId)) === false) { + return `NAEK${busTmnId}`; + } + return busTmnId; +}; From ebecbbe2b1e79e6534d58da3c5164e116a7d47da Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Thu, 5 Dec 2024 17:07:03 +0900 Subject: [PATCH 13/38] =?UTF-8?q?chore:=20=ED=95=A8=EC=88=98=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/getBusTickets.ts | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/apis/getBusTickets.ts b/src/apis/getBusTickets.ts index 2f8cc91..e5a49e1 100644 --- a/src/apis/getBusTickets.ts +++ b/src/apis/getBusTickets.ts @@ -1,3 +1,5 @@ +import { parseBusTerminalId } from '../utils/searchTerminalInfo'; + export const getBusNowTimeAPI = async (fromTmnId: string, toTmnId: string) => { const queryStringParams: Record = { serviceKey: import.meta.env.VITE_OPEN_API_KEY, @@ -49,18 +51,6 @@ interface ResponseBusTickets { }; } -/** - * - * @param busTmnId - * @returns - */ -const parseBusTerminalId = (busTmnId: string) => { - if (busTmnId.length === 3) { - return `NAEK${busTmnId}`; - } - return busTmnId; -}; - export const getBusTicketsAPI = async ( fromTmnId: string, toTmnId: string, From 3d405da848518efeb87a9a1618067e2180ca6bc0 Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Thu, 5 Dec 2024 17:07:27 +0900 Subject: [PATCH 14/38] =?UTF-8?q?fix:=20backward=20bus=20list=20side=20eff?= =?UTF-8?q?ect=20=EB=B0=A9=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/stores/useBackwardBusListStore/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stores/useBackwardBusListStore/index.ts b/src/stores/useBackwardBusListStore/index.ts index deebbd4..d56d95c 100644 --- a/src/stores/useBackwardBusListStore/index.ts +++ b/src/stores/useBackwardBusListStore/index.ts @@ -10,7 +10,7 @@ const useBackwardBusListStore = create((set) => ({ concat: (newBackwardBusList) => set((state) => ({ ...state, - backwardBusList: [...state.backwardBusList, ...newBackwardBusList], + backwardBusList: [...newBackwardBusList], })), deleteByStartId: (targetStartId) => set((state) => ({ From 2f5fa0ced835cfa3144a192a665bbba0b63faa4a Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Fri, 6 Dec 2024 20:28:30 +0900 Subject: [PATCH 15/38] =?UTF-8?q?feat:=20add=20=EC=A6=90=EA=B2=A8=EC=B0=BE?= =?UTF-8?q?=EA=B8=B0=20=EA=B2=BD=EB=A1=9C=20store?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/stores/useFavoriteRouteStore/index.ts | 38 +++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/stores/useFavoriteRouteStore/index.ts diff --git a/src/stores/useFavoriteRouteStore/index.ts b/src/stores/useFavoriteRouteStore/index.ts new file mode 100644 index 0000000..91bb3db --- /dev/null +++ b/src/stores/useFavoriteRouteStore/index.ts @@ -0,0 +1,38 @@ +import { create } from 'zustand'; + +interface FavoriteRoute { + startId: string; // NAEK 없는 ID + destId: string; // NAEK 없는 ID +} + +interface FavoriteRouteState { + favoriteRouteList: FavoriteRoute[]; + addRoute: (newFavoriteRoute: FavoriteRoute) => void; + deleteRoute: (route: FavoriteRoute) => void; + reset: () => void; +} + +const useFavoriteRouteStore = create((set) => ({ + favoriteRouteList: [], + addRoute: (newFavoriteRoute) => + set((state) => ({ + favoriteRouteList: state.favoriteRouteList.some( + (favoriteRoute) => + favoriteRoute.startId === newFavoriteRoute.startId && + favoriteRoute.destId === newFavoriteRoute.destId + ) + ? state.favoriteRouteList + : [...state.favoriteRouteList, newFavoriteRoute], + })), + deleteRoute: (route) => + set((state) => ({ + favoriteRouteList: state.favoriteRouteList.filter( + (favoriteRoute) => + favoriteRoute.startId !== route.startId && + favoriteRoute.destId !== route.destId + ), + })), + reset: () => set({ favoriteRouteList: [] }), +})); + +export default useFavoriteRouteStore; From 725634662f847bd1575fd9fc9ecf11cab043ca5a Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Fri, 6 Dec 2024 20:41:45 +0900 Subject: [PATCH 16/38] feat: add persist middleware to zustand --- src/stores/useBackwardBusListStore/index.ts | 39 ++++++++++++--------- src/stores/useTowardBusListStore/index.ts | 39 ++++++++++++--------- 2 files changed, 44 insertions(+), 34 deletions(-) diff --git a/src/stores/useBackwardBusListStore/index.ts b/src/stores/useBackwardBusListStore/index.ts index d462643..edd0e02 100644 --- a/src/stores/useBackwardBusListStore/index.ts +++ b/src/stores/useBackwardBusListStore/index.ts @@ -1,28 +1,33 @@ import { create } from 'zustand'; import type { BackwardBusListState } from './index.types'; -import { devtools } from 'zustand/middleware'; +import { devtools, persist } from 'zustand/middleware'; const initialState = { backwardBusList: [], }; const useBackwardBusListStore = create()( - devtools((set) => ({ - ...initialState, - concat: (newBackwardBusList) => - set((state) => ({ - ...state, - backwardBusList: [...newBackwardBusList], - })), - deleteByStartId: (targetStartId) => - set((state) => ({ - ...state, - backwardBusList: state.backwardBusList.filter( - (backwardBus) => backwardBus.startId !== targetStartId - ), - })), - reset: () => set({ ...initialState }), - })) + persist( + devtools((set) => ({ + ...initialState, + concat: (newBackwardBusList) => + set((state) => ({ + ...state, + backwardBusList: [...newBackwardBusList], + })), + deleteByStartId: (targetStartId) => + set((state) => ({ + ...state, + backwardBusList: state.backwardBusList.filter( + (backwardBus) => backwardBus.startId !== targetStartId + ), + })), + reset: () => set({ ...initialState }), + })), + { + name: 'backward-bus-list', + } + ) ); export default useBackwardBusListStore; diff --git a/src/stores/useTowardBusListStore/index.ts b/src/stores/useTowardBusListStore/index.ts index 4d7edb8..c443325 100644 --- a/src/stores/useTowardBusListStore/index.ts +++ b/src/stores/useTowardBusListStore/index.ts @@ -1,28 +1,33 @@ import { create } from 'zustand'; import type { ForwardBusListState } from './index.types'; -import { devtools } from 'zustand/middleware'; +import { devtools, persist } from 'zustand/middleware'; const initialState = { forwardBusList: [], }; const useForwardBusListStore = create()( - devtools((set) => ({ - ...initialState, - reset: () => set({ ...initialState }), - concat: (newforwardBusList) => - set((state) => ({ - ...state, - forwardBusList: [...newforwardBusList], - })), - deleteByStartId: (targetStartId) => - set((state) => ({ - ...state, - forwardBusList: state.forwardBusList.filter( - (forwardBus) => forwardBus.startId !== targetStartId - ), - })), - })) + persist( + devtools((set) => ({ + ...initialState, + reset: () => set({ ...initialState }), + concat: (newforwardBusList) => + set((state) => ({ + ...state, + forwardBusList: [...newforwardBusList], + })), + deleteByStartId: (targetStartId) => + set((state) => ({ + ...state, + forwardBusList: state.forwardBusList.filter( + (forwardBus) => forwardBus.startId !== targetStartId + ), + })), + })), + { + name: 'forward-bus-list', + } + ) ); export default useForwardBusListStore; From 3ba37ca25693dcd8bb957cbbe14ad61e6ad33b63 Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Fri, 6 Dec 2024 20:47:25 +0900 Subject: [PATCH 17/38] =?UTF-8?q?feat:=20useSearchQuery=EB=8F=84=20localSt?= =?UTF-8?q?orage=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routes/booking/tickets/index.tsx | 4 ---- src/stores/useSearchQueryStore/index.ts | 23 ++++++++++++++--------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/routes/booking/tickets/index.tsx b/src/routes/booking/tickets/index.tsx index f1aac30..fa96e94 100644 --- a/src/routes/booking/tickets/index.tsx +++ b/src/routes/booking/tickets/index.tsx @@ -150,18 +150,14 @@ export default function RouteComponent() { convertYYYYMMDD(searchQuery.startDate) ) .then((data) => { - //setBusTickets(data.response.body.items.item); // TODO: 전역 상태에 넣기 concat( convertBusTicketsToBusList(data.response.body.items.item, searchQuery) ); - - // throw new Error('dd'); }) .catch((error) => { console.error(error); //error인 경우, mock data로 초기화 - //setBusTickets(MOCK_busTickets.response.body.items.item); concat( convertBusTicketsToBusList( MOCK_busTickets.response.body.items.item, diff --git a/src/stores/useSearchQueryStore/index.ts b/src/stores/useSearchQueryStore/index.ts index b8cc269..06228d6 100644 --- a/src/stores/useSearchQueryStore/index.ts +++ b/src/stores/useSearchQueryStore/index.ts @@ -1,6 +1,6 @@ import { create } from 'zustand'; import type { SearchQueryState } from './index.types'; -import { devtools } from 'zustand/middleware'; +import { devtools, persist } from 'zustand/middleware'; const initialState = { searchQuery: { @@ -12,14 +12,19 @@ const initialState = { }; const useSearchQueryStore = create()( - devtools((set) => ({ - ...initialState, - setSearchQuery: (query) => - set((state) => ({ - searchQuery: { ...state.searchQuery, ...query }, - })), - resetSearchQuery: () => set({ ...initialState }), - })) + persist( + devtools((set) => ({ + ...initialState, + setSearchQuery: (query) => + set((state) => ({ + searchQuery: { ...state.searchQuery, ...query }, + })), + resetSearchQuery: () => set({ ...initialState }), + })), + { + name: 'search-query', + } + ) ); export default useSearchQueryStore; From c04f1ea21e871886902c0c1ce5c270afc9958ece Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Fri, 6 Dec 2024 21:04:04 +0900 Subject: [PATCH 18/38] =?UTF-8?q?fix:=20useSearchQuery=20persist=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/booking/index.tsx | 9 ++++++--- src/routes/booking/tickets/index.tsx | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/pages/booking/index.tsx b/src/pages/booking/index.tsx index eb2cbad..7a61513 100644 --- a/src/pages/booking/index.tsx +++ b/src/pages/booking/index.tsx @@ -105,7 +105,6 @@ function BookingPage() { return terminal?.tmnNm; }; - return (
@@ -182,7 +181,7 @@ function BookingPage() {
{ setSearchQuery({ startDate: new Date(value), @@ -198,7 +197,11 @@ function BookingPage() { { setShowEndDatePicker(true); setShowStartDatePicker(false); diff --git a/src/routes/booking/tickets/index.tsx b/src/routes/booking/tickets/index.tsx index fa96e94..7edac63 100644 --- a/src/routes/booking/tickets/index.tsx +++ b/src/routes/booking/tickets/index.tsx @@ -147,7 +147,7 @@ export default function RouteComponent() { getBusTicketsAPI( searchQuery.startId || 'NAEK032', searchQuery.destId || 'NAEK300', - convertYYYYMMDD(searchQuery.startDate) + convertYYYYMMDD(new Date(searchQuery.startDate)) ) .then((data) => { // TODO: 전역 상태에 넣기 @@ -186,7 +186,7 @@ export default function RouteComponent() { {searchTerminalNameToCode(searchQuery.startId) ?? '동서울'} →{' '} {searchTerminalNameToCode(searchQuery.destId) ?? '대전복합'}
-
{convertMMDDday(searchQuery.startDate)}
+
{convertMMDDday(new Date(searchQuery.startDate))}
} rightSlot={} From 58845edbde16da791e68173b871639409ae84642 Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Fri, 6 Dec 2024 21:10:43 +0900 Subject: [PATCH 19/38] refactor: remove unused imports --- src/routes/booking/payment/index.tsx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/routes/booking/payment/index.tsx b/src/routes/booking/payment/index.tsx index b47ca45..b852c25 100644 --- a/src/routes/booking/payment/index.tsx +++ b/src/routes/booking/payment/index.tsx @@ -1,12 +1,5 @@ import * as React from 'react'; import { createFileRoute } from '@tanstack/react-router'; -import { Typography } from '../../../common/components'; -import Flex from '../../../common/components/Flex'; -import useTicketListStore from '../../../stores/useTicketListStore'; -import PrimaryCard from '../../../common/components/PrimaryCard'; -import RouteRow from '../../../common/components/RouteRow'; -import SeatDetailsTable from '../../../common/components/SeatDetailsTable'; -import FeeSumRow from '../../../common/components/FeeSumRow'; import BookingPaymentPage from '../../../pages/BookingPaymentPage'; export const Route = createFileRoute('/booking/payment/')({ From 2714bc31458b5ab409db24b4403eb209477cbcc2 Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Fri, 6 Dec 2024 21:10:55 +0900 Subject: [PATCH 20/38] feat: convert Header to sticky --- src/routes/booking/tickets/index.tsx | 43 +++++++++++++++------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/src/routes/booking/tickets/index.tsx b/src/routes/booking/tickets/index.tsx index 7edac63..4f66c4b 100644 --- a/src/routes/booking/tickets/index.tsx +++ b/src/routes/booking/tickets/index.tsx @@ -19,6 +19,7 @@ import { Tooltip } from 'react-tooltip'; import MOCK_busTickets from '../../../constants/mock/bus_ticket_seoul_daejeon.json'; import { convertBusTicketsToBusList } from '../../../utils/convertBusTicketsToBusList'; import { Bus } from '../../../types'; +import StikcyHeader from '../../../common/components/StickyHeader'; export const Route = createFileRoute('/booking/tickets/')({ component: RouteComponent, @@ -169,28 +170,30 @@ export default function RouteComponent() { return (
- { - e.preventDefault(); - history.go(-1); - }} - > - back button - - } - centerSlot={ -
+ + { + e.preventDefault(); + history.go(-1); + }} + > + back button + + } + centerSlot={
- {searchTerminalNameToCode(searchQuery.startId) ?? '동서울'} →{' '} - {searchTerminalNameToCode(searchQuery.destId) ?? '대전복합'} +
+ {searchTerminalNameToCode(searchQuery.startId) ?? '동서울'} →{' '} + {searchTerminalNameToCode(searchQuery.destId) ?? '대전복합'} +
+
{convertMMDDday(new Date(searchQuery.startDate))}
-
{convertMMDDday(new Date(searchQuery.startDate))}
-
- } - rightSlot={} - /> + } + rightSlot={} + /> +
container(theme)}> From 972dcefd165f517fcaae5fe36f2cee2b354882cb Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Fri, 6 Dec 2024 21:24:04 +0900 Subject: [PATCH 21/38] =?UTF-8?q?feat:=20=EC=A6=90=EA=B2=A8=EC=B0=BE?= =?UTF-8?q?=EA=B8=B0=20route=20=EA=B8=B0=EB=8A=A5=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/FavoriteStarIcon-selected.svg | 4 +- src/routes/booking/tickets/index.tsx | 36 +++++++++++++++- src/stores/useFavoriteRouteStore/index.ts | 50 +++++++++++++---------- 3 files changed, 65 insertions(+), 25 deletions(-) diff --git a/src/assets/FavoriteStarIcon-selected.svg b/src/assets/FavoriteStarIcon-selected.svg index 256eab8..02fbf0c 100644 --- a/src/assets/FavoriteStarIcon-selected.svg +++ b/src/assets/FavoriteStarIcon-selected.svg @@ -1,3 +1,3 @@ - - + + diff --git a/src/routes/booking/tickets/index.tsx b/src/routes/booking/tickets/index.tsx index 4f66c4b..df9fa1c 100644 --- a/src/routes/booking/tickets/index.tsx +++ b/src/routes/booking/tickets/index.tsx @@ -3,6 +3,7 @@ import { Button, TopBar, Typography } from '../../../common/components'; import { css, Theme } from '@emotion/react'; import LeftArrowIcon from '../../../assets/LeftArrowIcon.svg'; import FavIcon from '../../../assets/FavoriteStarIcon.svg'; +import SelectedFavIcon from '../../../assets/FavoriteStarIcon-selected.svg'; import InfoIcon from '../../../assets/InfoIcon.svg?react'; import { useEffect, useState } from 'react'; import { BusTicket, getBusTicketsAPI } from '../../../apis/getBusTickets'; @@ -20,6 +21,7 @@ import MOCK_busTickets from '../../../constants/mock/bus_ticket_seoul_daejeon.js import { convertBusTicketsToBusList } from '../../../utils/convertBusTicketsToBusList'; import { Bus } from '../../../types'; import StikcyHeader from '../../../common/components/StickyHeader'; +import useFavoriteRouteStore from '../../../stores/useFavoriteRouteStore'; export const Route = createFileRoute('/booking/tickets/')({ component: RouteComponent, @@ -142,7 +144,22 @@ export default function RouteComponent() { const [busSearchTime, setBusSearchTime] = useState(202411290500); const { searchQuery } = useSearchQueryStore((state) => state); - const { forwardBusList, concat } = useForwardBusListStore((state) => state); + const { forwardBusList, concat } = useForwardBusListStore(); + const { favoriteRouteList, addRoute, deleteRoute } = useFavoriteRouteStore(); + + const handleFavoriteRoute = () => { + if ( + favoriteRouteList.some( + (route) => + route.startId === searchQuery.startId && + route.destId === searchQuery.destId + ) + ) { + deleteRoute({ startId: searchQuery.startId, destId: searchQuery.destId }); + } else { + addRoute({ startId: searchQuery.startId, destId: searchQuery.destId }); + } + }; useEffect(() => { getBusTicketsAPI( @@ -191,7 +208,22 @@ export default function RouteComponent() {
{convertMMDDday(new Date(searchQuery.startDate))}
} - rightSlot={} + rightSlot={ + + route.startId === searchQuery.startId && + route.destId === searchQuery.destId + ) + ? SelectedFavIcon + : FavIcon + } + alt="favorite" + /> + } /> diff --git a/src/stores/useFavoriteRouteStore/index.ts b/src/stores/useFavoriteRouteStore/index.ts index 91bb3db..30e4e4b 100644 --- a/src/stores/useFavoriteRouteStore/index.ts +++ b/src/stores/useFavoriteRouteStore/index.ts @@ -1,4 +1,5 @@ import { create } from 'zustand'; +import { devtools, persist } from 'zustand/middleware'; interface FavoriteRoute { startId: string; // NAEK 없는 ID @@ -12,27 +13,34 @@ interface FavoriteRouteState { reset: () => void; } -const useFavoriteRouteStore = create((set) => ({ - favoriteRouteList: [], - addRoute: (newFavoriteRoute) => - set((state) => ({ - favoriteRouteList: state.favoriteRouteList.some( - (favoriteRoute) => - favoriteRoute.startId === newFavoriteRoute.startId && - favoriteRoute.destId === newFavoriteRoute.destId - ) - ? state.favoriteRouteList - : [...state.favoriteRouteList, newFavoriteRoute], +const useFavoriteRouteStore = create()( + persist( + devtools((set) => ({ + favoriteRouteList: [], + addRoute: (newFavoriteRoute) => + set((state) => ({ + favoriteRouteList: state.favoriteRouteList.some( + (favoriteRoute) => + favoriteRoute.startId === newFavoriteRoute.startId && + favoriteRoute.destId === newFavoriteRoute.destId + ) + ? state.favoriteRouteList + : [...state.favoriteRouteList, newFavoriteRoute], + })), + deleteRoute: (route) => + set((state) => ({ + favoriteRouteList: state.favoriteRouteList.filter( + (favoriteRoute) => + favoriteRoute.startId !== route.startId && + favoriteRoute.destId !== route.destId + ), + })), + reset: () => set({ favoriteRouteList: [] }), })), - deleteRoute: (route) => - set((state) => ({ - favoriteRouteList: state.favoriteRouteList.filter( - (favoriteRoute) => - favoriteRoute.startId !== route.startId && - favoriteRoute.destId !== route.destId - ), - })), - reset: () => set({ favoriteRouteList: [] }), -})); + { + name: 'favorite-route', + } + ) +); export default useFavoriteRouteStore; From 675efb1e7af5567b0777fb61275d6021f523d763 Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Fri, 6 Dec 2024 21:36:44 +0900 Subject: [PATCH 22/38] =?UTF-8?q?feat:=20booking=20=ED=99=94=EB=A9=B4?= =?UTF-8?q?=EC=97=90=20=EC=A6=90=EA=B2=A8=EC=B0=BE=EA=B8=B0=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/booking/index.tsx | 54 ++++++++++++++++------- src/stores/useFavoriteRouteStore/index.ts | 2 +- 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/src/pages/booking/index.tsx b/src/pages/booking/index.tsx index 7a61513..a00e7e2 100644 --- a/src/pages/booking/index.tsx +++ b/src/pages/booking/index.tsx @@ -39,24 +39,51 @@ import terminalData from '../../constants/terminal.json'; import useSearchQueryStore from '../../stores/useSearchQueryStore'; import LanguageSwitchButton from '../../common/components/LanguageSwitchButton'; import { buildInput } from '../../common/components/Input/index.styles'; +import useFavoriteRouteStore from '../../stores/useFavoriteRouteStore'; + +const tmnCdToTmnNm = (tmnCd: string | number) => { + const terminal = terminalData.response.body.items.item.find( + (terminal) => terminal.tmnCd.toString() === tmnCd.toString() + ); + return terminal?.tmnNm; +}; function BookmarkList() { const navigate = useNavigate(); const theme = useTheme(); + + const { favoriteRouteList } = useFavoriteRouteStore(); + const { setSearchQuery } = useSearchQueryStore(); + return ( -
+
즐겨찾기 - + {favoriteRouteList.map((route, index) => ( + + ))}
); } @@ -98,13 +125,6 @@ function BookingPage() { return `${month}. ${day} (${weekday})`; }; - const tmnCdToTmnNm = (tmnCd: string | number) => { - const terminal = terminalData.response.body.items.item.find( - (terminal) => terminal.tmnCd.toString() === tmnCd.toString() - ); - return terminal?.tmnNm; - }; - return (
diff --git a/src/stores/useFavoriteRouteStore/index.ts b/src/stores/useFavoriteRouteStore/index.ts index 30e4e4b..f2b327a 100644 --- a/src/stores/useFavoriteRouteStore/index.ts +++ b/src/stores/useFavoriteRouteStore/index.ts @@ -16,7 +16,7 @@ interface FavoriteRouteState { const useFavoriteRouteStore = create()( persist( devtools((set) => ({ - favoriteRouteList: [], + favoriteRouteList: [{ startId: '032', destId: '300' }], addRoute: (newFavoriteRoute) => set((state) => ({ favoriteRouteList: state.favoriteRouteList.some( From 0a9358a9cb4bb227bcdb7bb7cab151f37db3badb Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Fri, 6 Dec 2024 21:40:42 +0900 Subject: [PATCH 23/38] =?UTF-8?q?fix:=20=EB=8F=84=EC=B0=A9=EC=A7=80=20?= =?UTF-8?q?=EC=84=A0=ED=83=9D=20=EC=95=88=ED=95=B4=EB=8F=84=20=EC=B6=9C?= =?UTF-8?q?=EB=B0=9C=EC=A7=80=20=EC=84=A0=ED=83=9D=EB=A7=8C=20=ED=95=98?= =?UTF-8?q?=EB=A9=B4=20=EB=8F=84=EC=B0=A9=EC=A7=80=20=EC=84=A0=ED=83=9D=20?= =?UTF-8?q?div=EA=B0=80=20=EA=B3=B5=EB=B0=B1=EB=90=98=EB=8A=94=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/booking/index.styles.ts | 1 + src/pages/booking/index.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/booking/index.styles.ts b/src/pages/booking/index.styles.ts index 61bd830..78990c3 100644 --- a/src/pages/booking/index.styles.ts +++ b/src/pages/booking/index.styles.ts @@ -5,6 +5,7 @@ export const container = css({ display: 'flex', flexDirection: 'column', minHeight: '100vh', + userSelect: 'none', }); export const topBarWrapper = css({ diff --git a/src/pages/booking/index.tsx b/src/pages/booking/index.tsx index a00e7e2..897291d 100644 --- a/src/pages/booking/index.tsx +++ b/src/pages/booking/index.tsx @@ -192,7 +192,7 @@ function BookingPage() { navigate({ to: '/booking/arrivalLocation' }); }} > - {searchQuery.startId + {searchQuery.destId ? tmnCdToTmnNm(searchQuery.destId) : '도착지 선택'} From 67de0854156824fffa64d4d3ccb88266eee450d6 Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Fri, 6 Dec 2024 21:59:03 +0900 Subject: [PATCH 24/38] =?UTF-8?q?fix:=20type=20error=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=20/=20Ticket=20class=EC=97=90=20string=20type=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/types/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/index.ts b/src/types/index.ts index 711c140..8033919 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -38,7 +38,7 @@ export interface Ticket { startDate: Date; isExpress: boolean; company: string; - class: Class; + class: Class | string; startId: string; destIdList: string[]; seats: Seat[]; From e4b66d3d89b3b96d38d6a0f50487e5162c0811bb Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Fri, 6 Dec 2024 22:21:07 +0900 Subject: [PATCH 25/38] chore: add bus company dummy data --- src/routes/booking/tickets/index.tsx | 4 +- src/utils/convertBusTicketsToBusList.ts | 49 ++++++++++++++----------- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/routes/booking/tickets/index.tsx b/src/routes/booking/tickets/index.tsx index df9fa1c..0de1cf3 100644 --- a/src/routes/booking/tickets/index.tsx +++ b/src/routes/booking/tickets/index.tsx @@ -74,7 +74,7 @@ function ButtonComponent({ bus }: { bus: Bus }) { + + ); +} + +export default ButtonComponent; diff --git a/src/pages/tickets/ticketListButton/index.styles.ts b/src/pages/tickets/ticketListButton/index.styles.ts new file mode 100644 index 0000000..9486611 --- /dev/null +++ b/src/pages/tickets/ticketListButton/index.styles.ts @@ -0,0 +1,35 @@ +import { css, Theme } from '@emotion/react'; + +export const buttonCSS = (theme: Theme) => css` + width: 100%; + background-color: ${theme.colors.gray.white}; + padding: 16px; + border-radius: 20px; + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: flex-start; + + .charge-time__container { + text-align: left; + display: flex; + flex-direction: column; + align-items: start; + gap: 5px; + + .tags { + display: flex; + flex-direction: row; + align-items: center; + gap: 5px; + } + } + + .busInfo { + text-align: right; + display: flex; + flex-direction: column; + align-items: flex-end; + gap: 5px; + } +`; diff --git a/src/routes/booking/tickets/index.tsx b/src/routes/booking/tickets/index.tsx index 0de1cf3..2db626e 100644 --- a/src/routes/booking/tickets/index.tsx +++ b/src/routes/booking/tickets/index.tsx @@ -4,24 +4,21 @@ import { css, Theme } from '@emotion/react'; import LeftArrowIcon from '../../../assets/LeftArrowIcon.svg'; import FavIcon from '../../../assets/FavoriteStarIcon.svg'; import SelectedFavIcon from '../../../assets/FavoriteStarIcon-selected.svg'; -import InfoIcon from '../../../assets/InfoIcon.svg?react'; import { useEffect, useState } from 'react'; -import { BusTicket, getBusTicketsAPI } from '../../../apis/getBusTickets'; +import { getBusTicketsAPI } from '../../../apis/getBusTickets'; import useSearchQueryStore from '../../../stores/useSearchQueryStore'; import { convertAMPMHHMM, - getDifferenceInMinutes, convertMMDDday, convertYYYYMMDD, } from '../../../utils/convertDate'; import { searchTerminalNameToCode } from '../../../utils/searchTerminalInfo'; import useForwardBusListStore from '../../../stores/useTowardBusListStore'; -import { Tooltip } from 'react-tooltip'; import MOCK_busTickets from '../../../constants/mock/bus_ticket_seoul_daejeon.json'; import { convertBusTicketsToBusList } from '../../../utils/convertBusTicketsToBusList'; -import { Bus } from '../../../types'; import StikcyHeader from '../../../common/components/StickyHeader'; import useFavoriteRouteStore from '../../../stores/useFavoriteRouteStore'; +import ButtonComponent from '../../../pages/tickets/ticketListButton/TicketListButton'; export const Route = createFileRoute('/booking/tickets/')({ component: RouteComponent, @@ -35,109 +32,6 @@ const container = (theme: Theme) => css` background-color: ${theme.colors.gray[3]}; `; -const buttonCSS = (theme: Theme) => css` - width: 100%; - background-color: ${theme.colors.gray.white}; - padding: 16px; - border-radius: 20px; - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: flex-start; - - .charge-time__container { - text-align: left; - display: flex; - flex-direction: column; - align-items: start; - gap: 5px; - - .tags { - display: flex; - flex-direction: row; - align-items: center; - gap: 5px; - } - } - - .busInfo { - text-align: right; - display: flex; - flex-direction: column; - align-items: flex-end; - gap: 5px; - } -`; - -function ButtonComponent({ bus }: { bus: Bus }) { - return ( - - - - ); -} - export default function RouteComponent() { // 가는 날(가는 길 버스를 선택하세요) 및 오는 날 페이지 구현하기 // const [busTickets, setBusTickets] = useState([]); From 802e32a5ac00dc02ace969d862342b8911ff691b Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Fri, 6 Dec 2024 22:52:28 +0900 Subject: [PATCH 28/38] =?UTF-8?q?feat:=20inbound=20/=20outbound=EC=97=90?= =?UTF-8?q?=20=EB=94=B0=EB=A5=B8=20store=20=EC=A0=80=EC=9E=A5=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ticketListButton/TicketListButton.tsx | 122 ++++++++++-------- src/routes/booking/tickets/index.tsx | 6 +- 2 files changed, 71 insertions(+), 57 deletions(-) diff --git a/src/pages/tickets/ticketListButton/TicketListButton.tsx b/src/pages/tickets/ticketListButton/TicketListButton.tsx index 8004f47..35e7a6a 100644 --- a/src/pages/tickets/ticketListButton/TicketListButton.tsx +++ b/src/pages/tickets/ticketListButton/TicketListButton.tsx @@ -1,4 +1,4 @@ -import { Link } from '@tanstack/react-router'; +import { useNavigate } from '@tanstack/react-router'; import { Button, Typography } from '../../../common/components'; import { css } from '@emotion/react'; import { convertAMPMHHMM } from '../../../utils/convertDate'; @@ -6,73 +6,87 @@ import { buttonCSS } from './index.styles'; import { Bus } from '../../../types'; import InfoIcon from '../../../assets/InfoIcon.svg?react'; import { Tooltip } from 'react-tooltip'; +import useReservationStore from '../../../stores/useReservationStore'; + +function ButtonComponent({ + bus, + direction, +}: { + bus: Bus; + direction: 'outbound' | 'inbound'; +}) { + const navigate = useNavigate(); + const { selectInboundBus, selectOutboundBus } = useReservationStore(); + + const handleClickBusBtn = () => { + if (direction === 'outbound') { + selectOutboundBus(bus); + } else { + selectInboundBus(bus); + } + navigate({ to: '/booking/seats' }); + }; -function ButtonComponent({ bus }: { bus: Bus }) { return ( - - - + + {bus.fee.adults.toLocaleString()} 원 + + css` + color: ${theme.colors.gray[4]}; + `} + > + {bus.eta} 예상 + +
+
+ + {`${bus.seats.length || 28}석`} + + css` + color: ${theme.colors.primary.base}; + `} + > + {bus.class} + + + +
+ ); } diff --git a/src/routes/booking/tickets/index.tsx b/src/routes/booking/tickets/index.tsx index 2db626e..32bf486 100644 --- a/src/routes/booking/tickets/index.tsx +++ b/src/routes/booking/tickets/index.tsx @@ -57,8 +57,8 @@ export default function RouteComponent() { useEffect(() => { getBusTicketsAPI( - searchQuery.startId || 'NAEK032', - searchQuery.destId || 'NAEK300', + searchQuery.startId, + searchQuery.destId, convertYYYYMMDD(new Date(searchQuery.startDate)) ) .then((data) => { @@ -153,7 +153,7 @@ export default function RouteComponent() { {forwardBusList && forwardBusList.map((bus, index) => ( - + ))}
From 00faeb8a482df9c9d5a307f70ed04448cd557cfc Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Sat, 7 Dec 2024 14:44:00 +0900 Subject: [PATCH 29/38] feat: add react-select --- package.json | 1 + src/routes/booking/tickets/index.tsx | 90 +++++++++++++++++++++++----- yarn.lock | 90 ++++++++++++++++++++++++---- 3 files changed, 156 insertions(+), 25 deletions(-) diff --git a/package.json b/package.json index f27d26e..6d21bc6 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "react": "^18.3.1", "react-datepicker": "^7.5.0", "react-dom": "^18.3.1", + "react-select": "^5.8.3", "react-tooltip": "^5.28.0", "zustand": "^5.0.1" }, diff --git a/src/routes/booking/tickets/index.tsx b/src/routes/booking/tickets/index.tsx index 32bf486..f816a32 100644 --- a/src/routes/booking/tickets/index.tsx +++ b/src/routes/booking/tickets/index.tsx @@ -1,6 +1,6 @@ import { createFileRoute, Link } from '@tanstack/react-router'; import { Button, TopBar, Typography } from '../../../common/components'; -import { css, Theme } from '@emotion/react'; +import { css, Theme, useTheme } from '@emotion/react'; import LeftArrowIcon from '../../../assets/LeftArrowIcon.svg'; import FavIcon from '../../../assets/FavoriteStarIcon.svg'; import SelectedFavIcon from '../../../assets/FavoriteStarIcon-selected.svg'; @@ -19,6 +19,7 @@ import { convertBusTicketsToBusList } from '../../../utils/convertBusTicketsToBu import StikcyHeader from '../../../common/components/StickyHeader'; import useFavoriteRouteStore from '../../../stores/useFavoriteRouteStore'; import ButtonComponent from '../../../pages/tickets/ticketListButton/TicketListButton'; +import Select from 'react-select'; export const Route = createFileRoute('/booking/tickets/')({ component: RouteComponent, @@ -35,12 +36,28 @@ const container = (theme: Theme) => css` export default function RouteComponent() { // 가는 날(가는 길 버스를 선택하세요) 및 오는 날 페이지 구현하기 // const [busTickets, setBusTickets] = useState([]); - const [busSearchTime, setBusSearchTime] = useState(202411290500); - + const theme = useTheme(); const { searchQuery } = useSearchQueryStore((state) => state); const { forwardBusList, concat } = useForwardBusListStore(); const { favoriteRouteList, addRoute, deleteRoute } = useFavoriteRouteStore(); + const [busSearchTime, setBusSearchTime] = useState( + searchQuery.startDate + ); + const [busSearchOption, setBusSearchOption] = useState<{ + value: string; + label: string; + }>({ value: '전체', label: '전체' }); + + const options = [ + { value: '전체', label: '전체' }, + { value: '무정차', label: '무정차' }, + { value: '경유', label: '경유' }, + { value: '고속', label: '고속' }, + { value: '우등', label: '우등' }, + { value: '심야', label: '심야' }, + ]; + const handleFavoriteRoute = () => { if ( favoriteRouteList.some( @@ -138,17 +155,62 @@ export default function RouteComponent() { {convertAMPMHHMM(busSearchTime)} 이후 - + + setBusSearchOption(newValue as { value: string; label: string }) + } + options={options} + styles={{ + control: (baseStyles, state) => ({ + ...baseStyles, + backgroundColor: theme.colors.gray[2], + borderColor: state.isFocused + ? theme.colors.primary.base + : theme.colors.gray[2], + borderRadius: '20px', + minWidth: '100px', + }), + option: (baseStyles, state) => ({ + ...baseStyles, + backgroundColor: state.isFocused + ? theme.colors.primary.base + : theme.colors.gray[2], + color: state.isFocused + ? theme.colors.gray.white + : theme.colors.gray[4], + }), + }} + />
{forwardBusList && diff --git a/yarn.lock b/yarn.lock index 0b0587c..ca9b2d8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -152,7 +152,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/runtime@^7.12.5", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3": +"@babel/runtime@^7.12.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7": version "7.26.0" resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz" integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw== @@ -228,6 +228,17 @@ "@emotion/weak-memoize" "^0.4.0" stylis "4.2.0" +"@emotion/cache@^11.13.5", "@emotion/cache@^11.4.0": + version "11.13.5" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.13.5.tgz#e78dad0489e1ed7572507ba8ed9d2130529e4266" + integrity sha512-Z3xbtJ+UcK76eWkagZ1onvn/wAVb1GOMuR15s30Fm2wrMgC7jzpnO2JZXr4eujTTqoQFUrZIw/rT0c6Zzjca1g== + dependencies: + "@emotion/memoize" "^0.9.0" + "@emotion/sheet" "^1.4.0" + "@emotion/utils" "^1.4.2" + "@emotion/weak-memoize" "^0.4.0" + stylis "4.2.0" + "@emotion/hash@^0.9.2": version "0.9.2" resolved "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz" @@ -259,6 +270,20 @@ "@emotion/weak-memoize" "^0.4.0" hoist-non-react-statics "^3.3.1" +"@emotion/react@^11.8.1": + version "11.13.5" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.13.5.tgz#fc818ff5b13424f86501ba4d0740f343ae20b8d9" + integrity sha512-6zeCUxUH+EPF1s+YF/2hPVODeV/7V07YU5x+2tfuRL8MdW6rv5vb2+CBEGTGwBdux0OIERcOS+RzxeK80k2DsQ== + dependencies: + "@babel/runtime" "^7.18.3" + "@emotion/babel-plugin" "^11.13.5" + "@emotion/cache" "^11.13.5" + "@emotion/serialize" "^1.3.3" + "@emotion/use-insertion-effect-with-fallbacks" "^1.1.0" + "@emotion/utils" "^1.4.2" + "@emotion/weak-memoize" "^0.4.0" + hoist-non-react-statics "^3.3.1" + "@emotion/serialize@^1.3.1", "@emotion/serialize@^1.3.3": version "1.3.3" resolved "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz" @@ -727,7 +752,7 @@ dependencies: "@floating-ui/utils" "^0.2.8" -"@floating-ui/dom@^1.0.0", "@floating-ui/dom@^1.6.1": +"@floating-ui/dom@^1.0.0", "@floating-ui/dom@^1.0.1", "@floating-ui/dom@^1.6.1": version "1.6.12" resolved "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.12.tgz" integrity sha512-NP83c0HjokcGVEMeoStg317VD9W7eDlGK7457dMBANbKA6GJZdc7rjujdgqzTaz93jkGgc5P/jeWbaCHnMNc+w== @@ -1477,20 +1502,13 @@ resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz" integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== -"@types/node@*": +"@types/node@*", "@types/node@^22.10.1": version "22.10.1" resolved "https://registry.npmjs.org/@types/node/-/node-22.10.1.tgz" integrity sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ== dependencies: undici-types "~6.20.0" -"@types/node@^22.10.1": - version "22.10.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.1.tgz#41ffeee127b8975a05f8c4f83fb89bcb2987d766" - integrity sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ== - dependencies: - undici-types "~6.20.0" - "@types/parse-json@^4.0.0": version "4.0.2" resolved "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz" @@ -1515,6 +1533,13 @@ dependencies: "@types/react" "*" +"@types/react-transition-group@^4.4.0": + version "4.4.11" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.11.tgz#d963253a611d757de01ebb241143b1017d5d63d5" + integrity sha512-RM05tAniPZ5DZPzzNFP+DmrcOdD0efDUxMy3145oljWSl3x9ZV5vhme98gTxFrj2lhXvmGNnUiuDyJgY9IKkNA== + dependencies: + "@types/react" "*" + "@types/react@*", "@types/react@^18.3.12": version "18.3.12" resolved "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz" @@ -2123,6 +2148,14 @@ dom-accessibility-api@^0.6.3: resolved "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz" integrity sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w== +dom-helpers@^5.0.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902" + integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA== + dependencies: + "@babel/runtime" "^7.8.7" + csstype "^3.0.2" + dot-case@^3.0.4: version "3.0.4" resolved "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz" @@ -2998,6 +3031,11 @@ map-or-similar@^1.5.0: resolved "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz" integrity sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg== +memoize-one@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045" + integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw== + memoizerific@^1.11.3: version "1.11.3" resolved "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz" @@ -3265,7 +3303,7 @@ process@^0.11.10: resolved "https://registry.npmjs.org/process/-/process-0.11.10.tgz" integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== -prop-types@^15.8.1: +prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -3345,6 +3383,21 @@ react-refresh@^0.14.2: resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz" integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== +react-select@^5.8.3: + version "5.8.3" + resolved "https://registry.yarnpkg.com/react-select/-/react-select-5.8.3.tgz#64e89ad20a846348b18c6fbb395b939d0153ed74" + integrity sha512-lVswnIq8/iTj1db7XCG74M/3fbGB6ZaluCzvwPGT5ZOjCdL/k0CLWhEK0vCBLuU5bHTEf6Gj8jtSvi+3v+tO1w== + dependencies: + "@babel/runtime" "^7.12.0" + "@emotion/cache" "^11.4.0" + "@emotion/react" "^11.8.1" + "@floating-ui/dom" "^1.0.1" + "@types/react-transition-group" "^4.4.0" + memoize-one "^6.0.0" + prop-types "^15.6.0" + react-transition-group "^4.3.0" + use-isomorphic-layout-effect "^1.1.2" + react-tooltip@^5.28.0: version "5.28.0" resolved "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.28.0.tgz" @@ -3353,6 +3406,16 @@ react-tooltip@^5.28.0: "@floating-ui/dom" "^1.6.1" classnames "^2.3.0" +react-transition-group@^4.3.0: + version "4.4.5" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1" + integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g== + dependencies: + "@babel/runtime" "^7.5.5" + dom-helpers "^5.0.1" + loose-envify "^1.4.0" + prop-types "^15.6.2" + "react@^16.8.0 || ^17.0.0 || ^18.0.0", react@^18.3.1: version "18.3.1" resolved "https://registry.npmjs.org/react/-/react-18.3.1.tgz" @@ -3748,6 +3811,11 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +use-isomorphic-layout-effect@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.0.tgz#afb292eb284c39219e8cb8d3d62d71999361a21d" + integrity sha512-q6ayo8DWoPZT0VdG4u3D3uxcgONP3Mevx2i2b0434cwWBoL+aelL1DzkXI6w3PhTZzUeR2kaVlZn70iCiseP6w== + use-sync-external-store@^1.2.2: version "1.2.2" resolved "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz" From 54a2724573c7644d1cb7873ce7da2a82c227a48f Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Sat, 7 Dec 2024 14:44:18 +0900 Subject: [PATCH 30/38] =?UTF-8?q?fix:=20=EC=B2=98=EC=9D=8C=20=EB=82=A0?= =?UTF-8?q?=EC=A7=9C=20=EC=84=A0=ED=83=9D=20=EC=8B=9C=20=EC=B6=9C=EB=B0=9C?= =?UTF-8?q?=20=EB=82=A0=EC=A7=9C=EB=8A=94=20=ED=95=AD=EC=83=81=20=ED=98=84?= =?UTF-8?q?=EC=9E=AC=20=EC=8B=9C=EA=B0=84=EC=9C=BC=EB=A1=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/booking/index.tsx | 4 +++- src/stores/useSearchQueryStore/index.ts | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/pages/booking/index.tsx b/src/pages/booking/index.tsx index 897291d..fa68798 100644 --- a/src/pages/booking/index.tsx +++ b/src/pages/booking/index.tsx @@ -292,9 +292,11 @@ function BookingPage() { {showStartDatePicker && (
{ if (!date) return; + const nowDate = new Date(Date.now()); + date.setHours(nowDate.getHours(), nowDate.getMinutes(), 0, 0); setSearchQuery({ startDate: date }); setShowStartDatePicker(false); }} diff --git a/src/stores/useSearchQueryStore/index.ts b/src/stores/useSearchQueryStore/index.ts index 06228d6..cc9cabf 100644 --- a/src/stores/useSearchQueryStore/index.ts +++ b/src/stores/useSearchQueryStore/index.ts @@ -6,7 +6,7 @@ const initialState = { searchQuery: { startId: '', destId: '', - startDate: new Date(), + startDate: new Date(Date.now()), destDate: null, }, }; From 353f73d7c06152d3a8397745bdc79c454b5783a4 Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Sat, 7 Dec 2024 15:00:53 +0900 Subject: [PATCH 31/38] =?UTF-8?q?style:=20=EC=8B=9C=EA=B0=84=EC=84=A0?= =?UTF-8?q?=ED=83=9D=20chip=20=EC=A0=9C=EC=9E=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routes/booking/tickets/index.tsx | 39 +++++++++++++++------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/routes/booking/tickets/index.tsx b/src/routes/booking/tickets/index.tsx index f816a32..e700f8c 100644 --- a/src/routes/booking/tickets/index.tsx +++ b/src/routes/booking/tickets/index.tsx @@ -41,14 +41,27 @@ export default function RouteComponent() { const { forwardBusList, concat } = useForwardBusListStore(); const { favoriteRouteList, addRoute, deleteRoute } = useFavoriteRouteStore(); - const [busSearchTime, setBusSearchTime] = useState( - searchQuery.startDate - ); + const [busSearchTime, setBusSearchTime] = useState<{ + value: string; + label: string; + }>({ + value: `${convertAMPMHHMM(new Date(searchQuery.startDate))} 이후`, + label: `${convertAMPMHHMM(new Date(searchQuery.startDate))} 이후`, + }); const [busSearchOption, setBusSearchOption] = useState<{ value: string; label: string; }>({ value: '전체', label: '전체' }); + const timeOptions = Array.from({ length: 24 }, (_, i) => { + const date = new Date(searchQuery.startDate); + date.setHours(i, 0, 0, 0); + return { + value: `${convertAMPMHHMM(date)} 이후`, + label: `${convertAMPMHHMM(date)} 이후`, + }; + }); + const options = [ { value: '전체', label: '전체' }, { value: '무정차', label: '무정차' }, @@ -144,24 +157,13 @@ export default function RouteComponent() {
- Date: Sat, 7 Dec 2024 15:17:08 +0900 Subject: [PATCH 32/38] =?UTF-8?q?feat:=20=EC=8B=9C=EA=B0=84=20=EC=84=A0?= =?UTF-8?q?=ED=83=9D,=20=EA=B0=81=20=EC=A1=B0=EA=B1=B4=20=EC=84=A0?= =?UTF-8?q?=ED=83=9D=EC=9C=BC=EB=A1=9C=20=EB=B2=84=EC=8A=A4=20list=20?= =?UTF-8?q?=EA=B3=A8=EB=9D=BC=EB=82=B4=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routes/booking/tickets/index.tsx | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/routes/booking/tickets/index.tsx b/src/routes/booking/tickets/index.tsx index e700f8c..85a1cba 100644 --- a/src/routes/booking/tickets/index.tsx +++ b/src/routes/booking/tickets/index.tsx @@ -42,10 +42,10 @@ export default function RouteComponent() { const { favoriteRouteList, addRoute, deleteRoute } = useFavoriteRouteStore(); const [busSearchTime, setBusSearchTime] = useState<{ - value: string; + value: Date; label: string; }>({ - value: `${convertAMPMHHMM(new Date(searchQuery.startDate))} 이후`, + value: new Date(searchQuery.startDate), label: `${convertAMPMHHMM(new Date(searchQuery.startDate))} 이후`, }); const [busSearchOption, setBusSearchOption] = useState<{ @@ -57,7 +57,7 @@ export default function RouteComponent() { const date = new Date(searchQuery.startDate); date.setHours(i, 0, 0, 0); return { - value: `${convertAMPMHHMM(date)} 이후`, + value: date, label: `${convertAMPMHHMM(date)} 이후`, }; }); @@ -161,7 +161,7 @@ export default function RouteComponent() { placeholder="시간 선택" value={busSearchTime} onChange={(newValue) => - setBusSearchTime(newValue as { value: string; label: string }) + setBusSearchTime(newValue as { value: Date; label: string }) } options={timeOptions} styles={{ @@ -217,9 +217,17 @@ export default function RouteComponent() {
{forwardBusList && - forwardBusList.map((bus, index) => ( - - ))} + forwardBusList + .filter( + (bus) => + bus.startDate >= busSearchTime.value && + (busSearchOption.value === '전체' || + busSearchOption.value === '무정차' || + bus.class.includes(busSearchOption.value)) + ) + .map((bus, index) => ( + + ))}
); From 75c979da51bc8daec3475b681e6496219add591b Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Sat, 7 Dec 2024 15:54:17 +0900 Subject: [PATCH 33/38] =?UTF-8?q?feat:=20inbound=20=EC=98=A4=EB=8A=94=20?= =?UTF-8?q?=EB=82=A0=20=EB=B2=84=EC=8A=A4=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EC=A0=9C=EC=9E=91=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/booking/index.tsx | 2 +- src/routes/booking/tickets/inbound.tsx | 233 +++++++++++++++++++++++++ src/routes/booking/tickets/index.tsx | 6 +- 3 files changed, 238 insertions(+), 3 deletions(-) create mode 100644 src/routes/booking/tickets/inbound.tsx diff --git a/src/pages/booking/index.tsx b/src/pages/booking/index.tsx index fa68798..d463dad 100644 --- a/src/pages/booking/index.tsx +++ b/src/pages/booking/index.tsx @@ -333,7 +333,7 @@ function BookingPage() { {showEndDatePicker && (
{ setSearchQuery({ destDate: date }); setShowEndDatePicker(false); diff --git a/src/routes/booking/tickets/inbound.tsx b/src/routes/booking/tickets/inbound.tsx new file mode 100644 index 0000000..078f9d5 --- /dev/null +++ b/src/routes/booking/tickets/inbound.tsx @@ -0,0 +1,233 @@ +import * as React from 'react'; +import { createFileRoute, Link } from '@tanstack/react-router'; +import { css, useTheme } from '@emotion/react'; +import useSearchQueryStore from '../../../stores/useSearchQueryStore'; +import useBackwardBusListStore from '../../../stores/useBackwardBusListStore'; +import useFavoriteRouteStore from '../../../stores/useFavoriteRouteStore'; +import { + convertAMPMHHMM, + convertMMDDday, + convertYYYYMMDD, +} from '../../../utils/convertDate'; +import { getBusTicketsAPI } from '../../../apis/getBusTickets'; +import { convertBusTicketsToBusList } from '../../../utils/convertBusTicketsToBusList'; +import MOCK_busTickets from '../../../constants/mock/bus_ticket_seoul_daejeon.json'; +import StikcyHeader from '../../../common/components/StickyHeader'; +import { TopBar, Typography } from '../../../common/components'; +import LeftArrowIcon from '../../../assets/LeftArrowIcon.svg'; +import FavIcon from '../../../assets/FavoriteStarIcon.svg'; +import SelectedFavIcon from '../../../assets/FavoriteStarIcon-selected.svg'; +import { searchTerminalNameToCode } from '../../../utils/searchTerminalInfo'; +import { container } from '.'; +import Select from 'react-select'; +import ButtonComponent from '../../../pages/tickets/ticketListButton/TicketListButton'; +import ErrorComponent from '../../../pages/error'; + +export const Route = createFileRoute('/booking/tickets/inbound')({ + component: RouteComponent, +}); + +export default function RouteComponent() { + // 가는 날(가는 길 버스를 선택하세요) 및 오는 날 페이지 구현하기 + // const [busTickets, setBusTickets] = useState([]); + const theme = useTheme(); + const { searchQuery } = useSearchQueryStore((state) => state); + + const { backwardBusList, concat } = useBackwardBusListStore(); + const { favoriteRouteList, addRoute, deleteRoute } = useFavoriteRouteStore(); + + const [busSearchTime, setBusSearchTime] = React.useState<{ + value: Date; + label: string; + }>({ + value: new Date(searchQuery.destDate ?? Date.now()), + label: `${convertAMPMHHMM(new Date(searchQuery.destDate ?? Date.now()))} 이후`, + }); + const [busSearchOption, setBusSearchOption] = React.useState<{ + value: string; + label: string; + }>({ value: '전체', label: '전체' }); + + const timeOptions = Array.from({ length: 24 }, (_, i) => { + const date = new Date(searchQuery.destDate ?? Date.now()); + date.setHours(i, 0, 0, 0); + return { + value: date, + label: `${convertAMPMHHMM(date)} 이후`, + }; + }); + + const options = [ + { value: '전체', label: '전체' }, + { value: '무정차', label: '무정차' }, + { value: '경유', label: '경유' }, + { value: '고속', label: '고속' }, + { value: '우등', label: '우등' }, + { value: '심야', label: '심야' }, + ]; + + const handleFavoriteRoute = () => { + if ( + favoriteRouteList.some( + (route) => + route.startId === searchQuery.startId && + route.destId === searchQuery.destId + ) + ) { + deleteRoute({ startId: searchQuery.startId, destId: searchQuery.destId }); + } else { + addRoute({ startId: searchQuery.startId, destId: searchQuery.destId }); + } + }; + + React.useEffect(() => { + getBusTicketsAPI( + searchQuery.startId, + searchQuery.destId, + convertYYYYMMDD(new Date(searchQuery.destDate ?? Date.now())) + ) + .then((data) => { + // TODO: 전역 상태에 넣기 + concat( + convertBusTicketsToBusList(data.response.body.items.item, searchQuery) + ); + }) + .catch((error) => { + console.error(error); + //error인 경우, mock data로 초기화 + concat( + convertBusTicketsToBusList( + MOCK_busTickets.response.body.items.item, + searchQuery + ) + ); + }); + }, []); + + return ( +
+ + { + e.preventDefault(); + history.go(-1); + }} + > + back button + + } + centerSlot={ +
+
+ {searchTerminalNameToCode(searchQuery.destId)} →{' '} + {searchTerminalNameToCode(searchQuery.startId)} +
+
+ {convertMMDDday(new Date(searchQuery.destDate ?? Date.now()))} +
+
+ } + rightSlot={ + + route.startId === searchQuery.startId && + route.destId === searchQuery.destId + ) + ? SelectedFavIcon + : FavIcon + } + alt="favorite" + /> + } + /> +
+ +
container(theme)}> + +
+ 오는 길

버스를 선택하세요 +
+
+ +
+ + setBusSearchOption(newValue as { value: string; label: string }) + } + options={options} + styles={{ + control: (baseStyles, state) => ({ + ...baseStyles, + backgroundColor: theme.colors.gray[2], + borderColor: state.isFocused + ? theme.colors.primary.base + : theme.colors.gray[2], + borderRadius: '20px', + minWidth: '100px', + }), + option: (baseStyles, state) => ({ + ...baseStyles, + backgroundColor: state.isFocused + ? theme.colors.primary.base + : theme.colors.gray[2], + color: state.isFocused + ? theme.colors.gray.white + : theme.colors.gray[4], + }), + }} + /> +
+ + {backwardBusList && + backwardBusList + .filter( + (bus) => + bus.startDate >= busSearchTime.value && + (busSearchOption.value === '전체' || + busSearchOption.value === '무정차' || + bus.class.includes(busSearchOption.value)) + ) + .map((bus, index) => ( + + ))} +
+
+ ); +} diff --git a/src/routes/booking/tickets/index.tsx b/src/routes/booking/tickets/index.tsx index 85a1cba..9a70890 100644 --- a/src/routes/booking/tickets/index.tsx +++ b/src/routes/booking/tickets/index.tsx @@ -25,7 +25,7 @@ export const Route = createFileRoute('/booking/tickets/')({ component: RouteComponent, }); -const container = (theme: Theme) => css` +export const container = (theme: Theme) => css` padding: 15px 20px; display: flex; flex-direction: column; @@ -153,7 +153,9 @@ export default function RouteComponent() {
container(theme)}> - 버스를 선택하세요 +
+ 가는 길

버스를 선택하세요 +
From d04a27c43c4f9cbc56bd182c08a29e90b38f2541 Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Sat, 7 Dec 2024 16:07:39 +0900 Subject: [PATCH 34/38] =?UTF-8?q?feat:=20Error=20=EB=A9=94=EC=84=B8?= =?UTF-8?q?=EC=A7=80=20=EB=B3=B4=EC=97=AC=EC=A4=84=20componnet=20=EC=A0=9C?= =?UTF-8?q?=EC=9E=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/error/index.tsx | 29 ++++++++++++++++++++++++++ src/routes/booking/tickets/inbound.tsx | 5 +++++ src/routes/booking/tickets/index.tsx | 6 ++++++ 3 files changed, 40 insertions(+) create mode 100644 src/pages/error/index.tsx diff --git a/src/pages/error/index.tsx b/src/pages/error/index.tsx new file mode 100644 index 0000000..ca723cb --- /dev/null +++ b/src/pages/error/index.tsx @@ -0,0 +1,29 @@ +import { useNavigate } from '@tanstack/react-router'; +import { Typography } from '../../common/components'; +import MainButton from '../../common/components/MainButton'; + +function ErrorComponent() { + const navigate = useNavigate(); + + return ( +
+ +

이 경로와 시간대의 버스를 검색하지 못했어요.

+

조건을 바꾸어 다시 검색해 주세요.

+

+ 배차에 대해 추가로 궁금한 점이 있다면

출발 터미널에 문의해 + 주세요. +

+
+ { + navigate({ to: '/booking' }); + }} + /> +
+ ); +} + +export default ErrorComponent; diff --git a/src/routes/booking/tickets/inbound.tsx b/src/routes/booking/tickets/inbound.tsx index 078f9d5..5e7deb5 100644 --- a/src/routes/booking/tickets/inbound.tsx +++ b/src/routes/booking/tickets/inbound.tsx @@ -88,6 +88,10 @@ export default function RouteComponent() { ) .then((data) => { // TODO: 전역 상태에 넣기 + if (!data.response.body.items.item) { + concat([]); + return; + } concat( convertBusTicketsToBusList(data.response.body.items.item, searchQuery) ); @@ -228,6 +232,7 @@ export default function RouteComponent() { ))}
+ {backwardBusList.length === 0 && }
); } diff --git a/src/routes/booking/tickets/index.tsx b/src/routes/booking/tickets/index.tsx index 9a70890..3af0865 100644 --- a/src/routes/booking/tickets/index.tsx +++ b/src/routes/booking/tickets/index.tsx @@ -20,6 +20,7 @@ import StikcyHeader from '../../../common/components/StickyHeader'; import useFavoriteRouteStore from '../../../stores/useFavoriteRouteStore'; import ButtonComponent from '../../../pages/tickets/ticketListButton/TicketListButton'; import Select from 'react-select'; +import ErrorComponent from '../../../pages/error'; export const Route = createFileRoute('/booking/tickets/')({ component: RouteComponent, @@ -93,6 +94,10 @@ export default function RouteComponent() { ) .then((data) => { // TODO: 전역 상태에 넣기 + if (!data.response.body.items.item) { + concat([]); + return; + } concat( convertBusTicketsToBusList(data.response.body.items.item, searchQuery) ); @@ -231,6 +236,7 @@ export default function RouteComponent() { ))} + {forwardBusList.length === 0 && }
); } From b3e6bcdaa316d8d9e3badaf570e42397854175da Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Sat, 7 Dec 2024 16:17:03 +0900 Subject: [PATCH 35/38] =?UTF-8?q?fix:=20=EB=B2=84=ED=8A=BC=20cursor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/booking/index.styles.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/booking/index.styles.ts b/src/pages/booking/index.styles.ts index 78990c3..a0d247f 100644 --- a/src/pages/booking/index.styles.ts +++ b/src/pages/booking/index.styles.ts @@ -58,6 +58,7 @@ export const transferButtonWrapper = css({ top: '50%', transform: 'translate(-50%, -50%)', zIndex: 2, + cursor: 'pointer', }); export const dateSelector = css({ From 8a5a7185a2650378390a491dc0a3835a4664464e Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Sat, 7 Dec 2024 16:22:24 +0900 Subject: [PATCH 36/38] =?UTF-8?q?feat:=20error=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/error/index.tsx | 26 ++++++++++++++++---------- src/routes/booking/tickets/inbound.tsx | 10 +++++++++- src/routes/booking/tickets/index.tsx | 9 ++++++++- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/pages/error/index.tsx b/src/pages/error/index.tsx index ca723cb..28252e0 100644 --- a/src/pages/error/index.tsx +++ b/src/pages/error/index.tsx @@ -2,26 +2,32 @@ import { useNavigate } from '@tanstack/react-router'; import { Typography } from '../../common/components'; import MainButton from '../../common/components/MainButton'; -function ErrorComponent() { +function ErrorComponent({ needRebooking }: { needRebooking: boolean }) { const navigate = useNavigate(); return (
-

이 경로와 시간대의 버스를 검색하지 못했어요.

-

조건을 바꾸어 다시 검색해 주세요.

+ {needRebooking ? ( +

이 경로와 날짜의 버스를 검색하지 못했어요.

+ ) : ( +

시간, 조건에 맞는 버스를 검색하지 못했어요.

+ )} +

시간이나 조건을 바꾸어 다시 검색해 주세요.

배차에 대해 추가로 궁금한 점이 있다면

출발 터미널에 문의해 주세요.

- { - navigate({ to: '/booking' }); - }} - /> + {needRebooking && ( + { + navigate({ to: '/booking' }); + }} + /> + )}
); } diff --git a/src/routes/booking/tickets/inbound.tsx b/src/routes/booking/tickets/inbound.tsx index 5e7deb5..2c6e2ce 100644 --- a/src/routes/booking/tickets/inbound.tsx +++ b/src/routes/booking/tickets/inbound.tsx @@ -232,7 +232,15 @@ export default function RouteComponent() { ))} - {backwardBusList.length === 0 && } + {backwardBusList.length === 0 && } + {backwardBusList && + backwardBusList.filter( + (bus) => + bus.startDate >= busSearchTime.value && + (busSearchOption.value === '전체' || + busSearchOption.value === '무정차' || + bus.class.includes(busSearchOption.value)) + ).length === 0 && } ); } diff --git a/src/routes/booking/tickets/index.tsx b/src/routes/booking/tickets/index.tsx index 3af0865..a60f286 100644 --- a/src/routes/booking/tickets/index.tsx +++ b/src/routes/booking/tickets/index.tsx @@ -236,7 +236,14 @@ export default function RouteComponent() { ))} - {forwardBusList.length === 0 && } + {forwardBusList.length === 0 && } + {forwardBusList.filter( + (bus) => + bus.startDate >= busSearchTime.value && + (busSearchOption.value === '전체' || + busSearchOption.value === '무정차' || + bus.class.includes(busSearchOption.value)) + ).length === 0 && } ); } From a290efab30bcb59254eaa424ce052ad868715e46 Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Sat, 7 Dec 2024 16:31:17 +0900 Subject: [PATCH 37/38] =?UTF-8?q?feat:=20booking=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EC=99=95=EB=B3=B5=20=EC=84=A0=ED=83=9D=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EB=B2=84=ED=8A=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/booking/index.styles.ts | 1 + src/pages/booking/index.tsx | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/pages/booking/index.styles.ts b/src/pages/booking/index.styles.ts index a0d247f..ce07f74 100644 --- a/src/pages/booking/index.styles.ts +++ b/src/pages/booking/index.styles.ts @@ -66,6 +66,7 @@ export const dateSelector = css({ flexDirection: 'row', gap: '12px', marginTop: '8px', + position: 'relative', }); export const dateBox = css({ diff --git a/src/pages/booking/index.tsx b/src/pages/booking/index.tsx index d463dad..e360164 100644 --- a/src/pages/booking/index.tsx +++ b/src/pages/booking/index.tsx @@ -26,6 +26,7 @@ import PersonIcon from '../../assets/PersonIcon.svg?react'; import TransferBtn from '../../assets/booking/btn_transfer.svg?react'; import LeftArrowMonthIcon from '../../assets/booking/btn_leftArrowMonth.svg?react'; import RightArrowMonthIcon from '../../assets/booking/btn_rightArrowMonth.svg?react'; +import CloseIcon from '../../assets/CloseIcon.svg?react'; import { buildTypography } from '../../common/components/Typography/index.styles'; import { container as buttonContainer } from '../../common/components/Button/index.styles'; @@ -232,6 +233,19 @@ function BookingPage() { throw new Error('Function not implemented.'); }} /> +
From 43108bae1bff98c2120f80850e48196a5cb2fbed Mon Sep 17 00:00:00 2001 From: kim jihwan Date: Sat, 7 Dec 2024 18:11:45 +0900 Subject: [PATCH 38/38] =?UTF-8?q?refactor:=20new=20Date(Date.now())?= =?UTF-8?q?=EC=99=80=20new=20Date()=20=EA=B2=B0=EA=B3=BC=EA=B0=80=20?= =?UTF-8?q?=EB=8F=99=EC=9D=BC=ED=95=98=EC=97=AC=20=EB=8D=94=20=EC=A7=A7?= =?UTF-8?q?=EA=B2=8C=20=EB=B0=94=EA=BE=B8=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/booking/index.tsx | 2 +- src/stores/useSearchQueryStore/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/booking/index.tsx b/src/pages/booking/index.tsx index e360164..c3099ac 100644 --- a/src/pages/booking/index.tsx +++ b/src/pages/booking/index.tsx @@ -309,7 +309,7 @@ function BookingPage() { selected={new Date(searchQuery.startDate)} onChange={(date: Date | null) => { if (!date) return; - const nowDate = new Date(Date.now()); + const nowDate = new Date(); date.setHours(nowDate.getHours(), nowDate.getMinutes(), 0, 0); setSearchQuery({ startDate: date }); setShowStartDatePicker(false); diff --git a/src/stores/useSearchQueryStore/index.ts b/src/stores/useSearchQueryStore/index.ts index cc9cabf..06228d6 100644 --- a/src/stores/useSearchQueryStore/index.ts +++ b/src/stores/useSearchQueryStore/index.ts @@ -6,7 +6,7 @@ const initialState = { searchQuery: { startId: '', destId: '', - startDate: new Date(Date.now()), + startDate: new Date(), destDate: null, }, };