From 153ccb2336f45d143cbfd5501315b68214a15616 Mon Sep 17 00:00:00 2001 From: Raymond <73725736+raymondanythings@users.noreply.github.com> Date: Thu, 30 Mar 2023 22:18:28 +0900 Subject: [PATCH] feature/search_result --- src/GlobalStyle.tsx | 23 +- src/api/gql.ts | 4 +- src/api/graphql.ts | 219 ++++++++++++- src/apollo.ts | 22 +- src/assets/carbon_error.svg | 3 + src/assets/kakao.svg | 10 + src/assets/mask.svg | 14 + src/assets/navigation.svg | 9 + src/assets/phone.svg | 9 + src/assets/wheelchair.svg | 8 + src/components/Search/DestinationCard.tsx | 171 ++++++++++ src/constants/common.ts | 1 + src/hooks/useGetSelection.ts | 19 ++ src/layout/Default.tsx | 79 +++-- src/routes/Router.tsx | 59 +++- src/screen/Search.tsx | 371 +++++++++------------- src/store/index.ts | 25 +- src/utils/index.ts | 2 + tsconfig.json | 2 + vite.config.ts | 12 + 20 files changed, 775 insertions(+), 287 deletions(-) create mode 100644 src/assets/carbon_error.svg create mode 100644 src/assets/kakao.svg create mode 100644 src/assets/mask.svg create mode 100644 src/assets/navigation.svg create mode 100644 src/assets/phone.svg create mode 100644 src/assets/wheelchair.svg create mode 100644 src/components/Search/DestinationCard.tsx create mode 100644 src/constants/common.ts create mode 100644 src/hooks/useGetSelection.ts diff --git a/src/GlobalStyle.tsx b/src/GlobalStyle.tsx index 3af4a51..bab61c9 100644 --- a/src/GlobalStyle.tsx +++ b/src/GlobalStyle.tsx @@ -4,11 +4,12 @@ const GlobalStyle = createGlobalStyle` @import url('https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css'); html { font-size: 62.5%; // 1rem = 10px 로 변경 + color : hsl(240, 3.8461538461538463%, 10.196078431372548%); width: 100%; max-height: calc(var(--var,1vh) * 100); } body { - background-color: #f9f9f9; + font-family: Pretendard, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; @@ -131,7 +132,7 @@ const GlobalStyle = createGlobalStyle` line-height: 2.8rem; } - .filter-smaill { + .filter-small { font-size: 1.5rem; line-height: 2.8rem; } @@ -140,6 +141,24 @@ const GlobalStyle = createGlobalStyle` color : #AFB1B6; } + .text-subdark { + color :#61646B; + } + + .main-text { + color : #4DB495; + } + + .body-small2 { + font-size : 0.9rem; + line-height: 1.6rem; + } + + .px { + padding-left :2rem; + padding-right: 2rem; + } + ` export default GlobalStyle diff --git a/src/api/gql.ts b/src/api/gql.ts index 17d7ba7..70d979a 100644 --- a/src/api/gql.ts +++ b/src/api/gql.ts @@ -14,7 +14,7 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/ */ const documents = { "\n fragment PlaceInfo on Place {\n parkingAvailable\n parkingCount\n wheelChairRentable\n elevatorAvailable\n toiletAvailable\n pathExists\n pathDescription\n latitude\n longitude\n etc\n basicInfo\n category\n id\n }\n": types.PlaceInfoFragmentDoc, - "\n query getPlace {\n places {\n ...PlaceInfo\n __typename\n }\n }\n \n": types.GetPlaceDocument, + "\n query GetSearchList(\n $before: String\n $after: String\n $first: Int\n $last: Int\n $categories: [String!]\n $parkingAvailable: Boolean\n $wheelChairRentable: Boolean\n $elevatorAvailable: Boolean\n $toiletAvailable: Boolean\n $pathExists: Boolean\n $needCompanion: Boolean!\n $coordinates: CoordinateInput\n ) {\n places(\n before: $before\n after: $after\n first: $first\n last: $last\n categories: $categories\n parkingAvailable: $parkingAvailable\n wheelChairRentable: $wheelChairRentable\n elevatorAvailable: $elevatorAvailable\n toiletAvailable: $toiletAvailable\n pathExists: $pathExists\n needCompanion: $needCompanion\n coordinates: $coordinates\n ) {\n pageInfo {\n startCursor\n endCursor\n hasNextPage\n hasNextPage\n }\n edges {\n node {\n id\n name\n address\n thumbnails\n parkingAvailable\n parkingCount\n wheelChairRentable\n elevatorAvailable\n toiletAvailable\n pathExists\n pathDescription\n latitude\n longitude\n category\n needCompanion\n distance\n tel\n }\n cursor\n }\n totalCount\n }\n }\n": types.GetSearchListDocument, }; /** @@ -38,7 +38,7 @@ export function graphql(source: "\n fragment PlaceInfo on Place {\n parkingA /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function graphql(source: "\n query getPlace {\n places {\n ...PlaceInfo\n __typename\n }\n }\n \n"): (typeof documents)["\n query getPlace {\n places {\n ...PlaceInfo\n __typename\n }\n }\n \n"]; +export function graphql(source: "\n query GetSearchList(\n $before: String\n $after: String\n $first: Int\n $last: Int\n $categories: [String!]\n $parkingAvailable: Boolean\n $wheelChairRentable: Boolean\n $elevatorAvailable: Boolean\n $toiletAvailable: Boolean\n $pathExists: Boolean\n $needCompanion: Boolean!\n $coordinates: CoordinateInput\n ) {\n places(\n before: $before\n after: $after\n first: $first\n last: $last\n categories: $categories\n parkingAvailable: $parkingAvailable\n wheelChairRentable: $wheelChairRentable\n elevatorAvailable: $elevatorAvailable\n toiletAvailable: $toiletAvailable\n pathExists: $pathExists\n needCompanion: $needCompanion\n coordinates: $coordinates\n ) {\n pageInfo {\n startCursor\n endCursor\n hasNextPage\n hasNextPage\n }\n edges {\n node {\n id\n name\n address\n thumbnails\n parkingAvailable\n parkingCount\n wheelChairRentable\n elevatorAvailable\n toiletAvailable\n pathExists\n pathDescription\n latitude\n longitude\n category\n needCompanion\n distance\n tel\n }\n cursor\n }\n totalCount\n }\n }\n"): (typeof documents)["\n query GetSearchList(\n $before: String\n $after: String\n $first: Int\n $last: Int\n $categories: [String!]\n $parkingAvailable: Boolean\n $wheelChairRentable: Boolean\n $elevatorAvailable: Boolean\n $toiletAvailable: Boolean\n $pathExists: Boolean\n $needCompanion: Boolean!\n $coordinates: CoordinateInput\n ) {\n places(\n before: $before\n after: $after\n first: $first\n last: $last\n categories: $categories\n parkingAvailable: $parkingAvailable\n wheelChairRentable: $wheelChairRentable\n elevatorAvailable: $elevatorAvailable\n toiletAvailable: $toiletAvailable\n pathExists: $pathExists\n needCompanion: $needCompanion\n coordinates: $coordinates\n ) {\n pageInfo {\n startCursor\n endCursor\n hasNextPage\n hasNextPage\n }\n edges {\n node {\n id\n name\n address\n thumbnails\n parkingAvailable\n parkingCount\n wheelChairRentable\n elevatorAvailable\n toiletAvailable\n pathExists\n pathDescription\n latitude\n longitude\n category\n needCompanion\n distance\n tel\n }\n cursor\n }\n totalCount\n }\n }\n"]; export function graphql(source: string) { return (documents as any)[source] ?? {}; diff --git a/src/api/graphql.ts b/src/api/graphql.ts index 59fc589..f131b1c 100644 --- a/src/api/graphql.ts +++ b/src/api/graphql.ts @@ -15,6 +15,11 @@ export type Scalars = { Float: number; }; +export type CoordinateInput = { + latitude: Scalars['Float']; + longitude: Scalars['Float']; +}; + export type Metadata = { __typename?: 'Metadata'; id: Scalars['String']; @@ -22,11 +27,20 @@ export type Metadata = { value: Scalars['String']; }; +export type PageInfo = { + __typename?: 'PageInfo'; + endCursor?: Maybe; + hasNextPage: Scalars['Boolean']; + hasPreviousPage: Scalars['Boolean']; + startCursor?: Maybe; +}; + export type Place = { __typename?: 'Place'; address: Scalars['String']; basicInfo: Scalars['String']; category: Scalars['String']; + distance: Scalars['Float']; elevatorAvailable: Scalars['Boolean']; etc?: Maybe; id: Scalars['String']; @@ -35,32 +49,95 @@ export type Place = { longitude: Scalars['Float']; metadata: Array; name: Scalars['String']; + needCompanion: Scalars['Boolean']; parkingAvailable: Scalars['Boolean']; parkingCount: Scalars['Float']; pathDescription?: Maybe; pathExists: Scalars['Boolean']; + tel?: Maybe; thumbnails: Array; toiletAvailable: Scalars['Boolean']; wheelChairRentable: Scalars['Boolean']; }; +export type PlaceCountInput = { + categories?: InputMaybe>; + elevatorAvailable?: InputMaybe; + needCompanion: Scalars['Boolean']; + parkingAvailable?: InputMaybe; + pathExists?: InputMaybe; + toiletAvailable?: InputMaybe; + wheelChairRentable?: InputMaybe; +}; + +export type PlaceEdge = { + __typename?: 'PlaceEdge'; + cursor: Scalars['String']; + node: Place; +}; + +export type PlacesConnection = { + __typename?: 'PlacesConnection'; + edges: Array; + pageInfo: PageInfo; + totalCount: Scalars['Float']; +}; + export type Query = { __typename?: 'Query'; - places: Array; + place?: Maybe; + placeCount: Scalars['Float']; + places: PlacesConnection; +}; + + +export type QueryPlaceArgs = { + id: Scalars['String']; +}; + + +export type QueryPlaceCountArgs = { + input: PlaceCountInput; +}; + + +export type QueryPlacesArgs = { + after?: InputMaybe; + before?: InputMaybe; + categories?: InputMaybe>; + coordinates?: InputMaybe; + elevatorAvailable?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; + needCompanion: Scalars['Boolean']; + parkingAvailable?: InputMaybe; + pathExists?: InputMaybe; + toiletAvailable?: InputMaybe; + wheelChairRentable?: InputMaybe; }; export type PlaceInfoFragment = { __typename?: 'Place', parkingAvailable: boolean, parkingCount: number, wheelChairRentable: boolean, elevatorAvailable: boolean, toiletAvailable: boolean, pathExists: boolean, pathDescription?: string | null, latitude: number, longitude: number, etc?: string | null, basicInfo: string, category: string, id: string } & { ' $fragmentName'?: 'PlaceInfoFragment' }; -export type GetPlaceQueryVariables = Exact<{ [key: string]: never; }>; +export type GetSearchListQueryVariables = Exact<{ + before?: InputMaybe; + after?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; + categories?: InputMaybe | Scalars['String']>; + parkingAvailable?: InputMaybe; + wheelChairRentable?: InputMaybe; + elevatorAvailable?: InputMaybe; + toiletAvailable?: InputMaybe; + pathExists?: InputMaybe; + needCompanion: Scalars['Boolean']; + coordinates?: InputMaybe; +}>; -export type GetPlaceQuery = { __typename?: 'Query', places: Array<( - { __typename: 'Place' } - & { ' $fragmentRefs'?: { 'PlaceInfoFragment': PlaceInfoFragment } } - )> }; +export type GetSearchListQuery = { __typename?: 'Query', places: { __typename?: 'PlacesConnection', totalCount: number, pageInfo: { __typename?: 'PageInfo', startCursor?: string | null, endCursor?: string | null, hasNextPage: boolean }, edges: Array<{ __typename?: 'PlaceEdge', cursor: string, node: { __typename?: 'Place', id: string, name: string, address: string, thumbnails: Array, parkingAvailable: boolean, parkingCount: number, wheelChairRentable: boolean, elevatorAvailable: boolean, toiletAvailable: boolean, pathExists: boolean, pathDescription?: string | null, latitude: number, longitude: number, category: string, needCompanion: boolean, distance: number, tel?: string | null } }> } }; export const PlaceInfoFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"PlaceInfo"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Place"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"parkingAvailable"}},{"kind":"Field","name":{"kind":"Name","value":"parkingCount"}},{"kind":"Field","name":{"kind":"Name","value":"wheelChairRentable"}},{"kind":"Field","name":{"kind":"Name","value":"elevatorAvailable"}},{"kind":"Field","name":{"kind":"Name","value":"toiletAvailable"}},{"kind":"Field","name":{"kind":"Name","value":"pathExists"}},{"kind":"Field","name":{"kind":"Name","value":"pathDescription"}},{"kind":"Field","name":{"kind":"Name","value":"latitude"}},{"kind":"Field","name":{"kind":"Name","value":"longitude"}},{"kind":"Field","name":{"kind":"Name","value":"etc"}},{"kind":"Field","name":{"kind":"Name","value":"basicInfo"}},{"kind":"Field","name":{"kind":"Name","value":"category"}},{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]} as unknown as DocumentNode; -export const GetPlaceDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"getPlace"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"places"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"PlaceInfo"}},{"kind":"Field","name":{"kind":"Name","value":"__typename"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"PlaceInfo"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Place"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"parkingAvailable"}},{"kind":"Field","name":{"kind":"Name","value":"parkingCount"}},{"kind":"Field","name":{"kind":"Name","value":"wheelChairRentable"}},{"kind":"Field","name":{"kind":"Name","value":"elevatorAvailable"}},{"kind":"Field","name":{"kind":"Name","value":"toiletAvailable"}},{"kind":"Field","name":{"kind":"Name","value":"pathExists"}},{"kind":"Field","name":{"kind":"Name","value":"pathDescription"}},{"kind":"Field","name":{"kind":"Name","value":"latitude"}},{"kind":"Field","name":{"kind":"Name","value":"longitude"}},{"kind":"Field","name":{"kind":"Name","value":"etc"}},{"kind":"Field","name":{"kind":"Name","value":"basicInfo"}},{"kind":"Field","name":{"kind":"Name","value":"category"}},{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]} as unknown as DocumentNode; +export const GetSearchListDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetSearchList"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"before"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"after"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"first"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"last"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"categories"}},"type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"parkingAvailable"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Boolean"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"wheelChairRentable"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Boolean"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"elevatorAvailable"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Boolean"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"toiletAvailable"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Boolean"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"pathExists"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Boolean"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"needCompanion"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Boolean"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"coordinates"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"CoordinateInput"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"places"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"before"},"value":{"kind":"Variable","name":{"kind":"Name","value":"before"}}},{"kind":"Argument","name":{"kind":"Name","value":"after"},"value":{"kind":"Variable","name":{"kind":"Name","value":"after"}}},{"kind":"Argument","name":{"kind":"Name","value":"first"},"value":{"kind":"Variable","name":{"kind":"Name","value":"first"}}},{"kind":"Argument","name":{"kind":"Name","value":"last"},"value":{"kind":"Variable","name":{"kind":"Name","value":"last"}}},{"kind":"Argument","name":{"kind":"Name","value":"categories"},"value":{"kind":"Variable","name":{"kind":"Name","value":"categories"}}},{"kind":"Argument","name":{"kind":"Name","value":"parkingAvailable"},"value":{"kind":"Variable","name":{"kind":"Name","value":"parkingAvailable"}}},{"kind":"Argument","name":{"kind":"Name","value":"wheelChairRentable"},"value":{"kind":"Variable","name":{"kind":"Name","value":"wheelChairRentable"}}},{"kind":"Argument","name":{"kind":"Name","value":"elevatorAvailable"},"value":{"kind":"Variable","name":{"kind":"Name","value":"elevatorAvailable"}}},{"kind":"Argument","name":{"kind":"Name","value":"toiletAvailable"},"value":{"kind":"Variable","name":{"kind":"Name","value":"toiletAvailable"}}},{"kind":"Argument","name":{"kind":"Name","value":"pathExists"},"value":{"kind":"Variable","name":{"kind":"Name","value":"pathExists"}}},{"kind":"Argument","name":{"kind":"Name","value":"needCompanion"},"value":{"kind":"Variable","name":{"kind":"Name","value":"needCompanion"}}},{"kind":"Argument","name":{"kind":"Name","value":"coordinates"},"value":{"kind":"Variable","name":{"kind":"Name","value":"coordinates"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"pageInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"startCursor"}},{"kind":"Field","name":{"kind":"Name","value":"endCursor"}},{"kind":"Field","name":{"kind":"Name","value":"hasNextPage"}},{"kind":"Field","name":{"kind":"Name","value":"hasNextPage"}}]}},{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"address"}},{"kind":"Field","name":{"kind":"Name","value":"thumbnails"}},{"kind":"Field","name":{"kind":"Name","value":"parkingAvailable"}},{"kind":"Field","name":{"kind":"Name","value":"parkingCount"}},{"kind":"Field","name":{"kind":"Name","value":"wheelChairRentable"}},{"kind":"Field","name":{"kind":"Name","value":"elevatorAvailable"}},{"kind":"Field","name":{"kind":"Name","value":"toiletAvailable"}},{"kind":"Field","name":{"kind":"Name","value":"pathExists"}},{"kind":"Field","name":{"kind":"Name","value":"pathDescription"}},{"kind":"Field","name":{"kind":"Name","value":"latitude"}},{"kind":"Field","name":{"kind":"Name","value":"longitude"}},{"kind":"Field","name":{"kind":"Name","value":"category"}},{"kind":"Field","name":{"kind":"Name","value":"needCompanion"}},{"kind":"Field","name":{"kind":"Name","value":"distance"}},{"kind":"Field","name":{"kind":"Name","value":"tel"}}]}},{"kind":"Field","name":{"kind":"Name","value":"cursor"}}]}},{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}}]}}]} as unknown as DocumentNode; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: string; @@ -70,6 +147,11 @@ export type Scalars = { Float: number; }; +export type CoordinateInput = { + latitude: Scalars['Float']; + longitude: Scalars['Float']; +}; + export type Metadata = { __typename?: 'Metadata'; id: Scalars['String']; @@ -77,11 +159,20 @@ export type Metadata = { value: Scalars['String']; }; +export type PageInfo = { + __typename?: 'PageInfo'; + endCursor?: Maybe; + hasNextPage: Scalars['Boolean']; + hasPreviousPage: Scalars['Boolean']; + startCursor?: Maybe; +}; + export type Place = { __typename?: 'Place'; address: Scalars['String']; basicInfo: Scalars['String']; category: Scalars['String']; + distance: Scalars['Float']; elevatorAvailable: Scalars['Boolean']; etc?: Maybe; id: Scalars['String']; @@ -90,29 +181,92 @@ export type Place = { longitude: Scalars['Float']; metadata: Array; name: Scalars['String']; + needCompanion: Scalars['Boolean']; parkingAvailable: Scalars['Boolean']; parkingCount: Scalars['Float']; pathDescription?: Maybe; pathExists: Scalars['Boolean']; + tel?: Maybe; thumbnails: Array; toiletAvailable: Scalars['Boolean']; wheelChairRentable: Scalars['Boolean']; }; +export type PlaceCountInput = { + categories?: InputMaybe>; + elevatorAvailable?: InputMaybe; + needCompanion: Scalars['Boolean']; + parkingAvailable?: InputMaybe; + pathExists?: InputMaybe; + toiletAvailable?: InputMaybe; + wheelChairRentable?: InputMaybe; +}; + +export type PlaceEdge = { + __typename?: 'PlaceEdge'; + cursor: Scalars['String']; + node: Place; +}; + +export type PlacesConnection = { + __typename?: 'PlacesConnection'; + edges: Array; + pageInfo: PageInfo; + totalCount: Scalars['Float']; +}; + export type Query = { __typename?: 'Query'; - places: Array; + place?: Maybe; + placeCount: Scalars['Float']; + places: PlacesConnection; +}; + + +export type QueryPlaceArgs = { + id: Scalars['String']; +}; + + +export type QueryPlaceCountArgs = { + input: PlaceCountInput; +}; + + +export type QueryPlacesArgs = { + after?: InputMaybe; + before?: InputMaybe; + categories?: InputMaybe>; + coordinates?: InputMaybe; + elevatorAvailable?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; + needCompanion: Scalars['Boolean']; + parkingAvailable?: InputMaybe; + pathExists?: InputMaybe; + toiletAvailable?: InputMaybe; + wheelChairRentable?: InputMaybe; }; export type PlaceInfoFragment = { __typename?: 'Place', parkingAvailable: boolean, parkingCount: number, wheelChairRentable: boolean, elevatorAvailable: boolean, toiletAvailable: boolean, pathExists: boolean, pathDescription?: string | null, latitude: number, longitude: number, etc?: string | null, basicInfo: string, category: string, id: string } & { ' $fragmentName'?: 'PlaceInfoFragment' }; -export type GetPlaceQueryVariables = Exact<{ [key: string]: never; }>; +export type GetSearchListQueryVariables = Exact<{ + before?: InputMaybe; + after?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; + categories?: InputMaybe | Scalars['String']>; + parkingAvailable?: InputMaybe; + wheelChairRentable?: InputMaybe; + elevatorAvailable?: InputMaybe; + toiletAvailable?: InputMaybe; + pathExists?: InputMaybe; + needCompanion: Scalars['Boolean']; + coordinates?: InputMaybe; +}>; -export type GetPlaceQuery = { __typename?: 'Query', places: Array<( - { __typename: 'Place' } - & { ' $fragmentRefs'?: { 'PlaceInfoFragment': PlaceInfoFragment } } - )> }; +export type GetSearchListQuery = { __typename?: 'Query', places: { __typename?: 'PlacesConnection', totalCount: number, pageInfo: { __typename?: 'PageInfo', startCursor?: string | null, endCursor?: string | null, hasNextPage: boolean }, edges: Array<{ __typename?: 'PlaceEdge', cursor: string, node: { __typename?: 'Place', id: string, name: string, address: string, thumbnails: Array, parkingAvailable: boolean, parkingCount: number, wheelChairRentable: boolean, elevatorAvailable: boolean, toiletAvailable: boolean, pathExists: boolean, pathDescription?: string | null, latitude: number, longitude: number, category: string, needCompanion: boolean, distance: number, tel?: string | null } }> } }; export type MetadataKeySpecifier = ('id' | 'key' | 'value' | MetadataKeySpecifier)[]; export type MetadataFieldPolicy = { @@ -120,11 +274,19 @@ export type MetadataFieldPolicy = { key?: FieldPolicy | FieldReadFunction, value?: FieldPolicy | FieldReadFunction }; -export type PlaceKeySpecifier = ('address' | 'basicInfo' | 'category' | 'elevatorAvailable' | 'etc' | 'id' | 'images' | 'latitude' | 'longitude' | 'metadata' | 'name' | 'parkingAvailable' | 'parkingCount' | 'pathDescription' | 'pathExists' | 'thumbnails' | 'toiletAvailable' | 'wheelChairRentable' | PlaceKeySpecifier)[]; +export type PageInfoKeySpecifier = ('endCursor' | 'hasNextPage' | 'hasPreviousPage' | 'startCursor' | PageInfoKeySpecifier)[]; +export type PageInfoFieldPolicy = { + endCursor?: FieldPolicy | FieldReadFunction, + hasNextPage?: FieldPolicy | FieldReadFunction, + hasPreviousPage?: FieldPolicy | FieldReadFunction, + startCursor?: FieldPolicy | FieldReadFunction +}; +export type PlaceKeySpecifier = ('address' | 'basicInfo' | 'category' | 'distance' | 'elevatorAvailable' | 'etc' | 'id' | 'images' | 'latitude' | 'longitude' | 'metadata' | 'name' | 'needCompanion' | 'parkingAvailable' | 'parkingCount' | 'pathDescription' | 'pathExists' | 'tel' | 'thumbnails' | 'toiletAvailable' | 'wheelChairRentable' | PlaceKeySpecifier)[]; export type PlaceFieldPolicy = { address?: FieldPolicy | FieldReadFunction, basicInfo?: FieldPolicy | FieldReadFunction, category?: FieldPolicy | FieldReadFunction, + distance?: FieldPolicy | FieldReadFunction, elevatorAvailable?: FieldPolicy | FieldReadFunction, etc?: FieldPolicy | FieldReadFunction, id?: FieldPolicy | FieldReadFunction, @@ -133,16 +295,31 @@ export type PlaceFieldPolicy = { longitude?: FieldPolicy | FieldReadFunction, metadata?: FieldPolicy | FieldReadFunction, name?: FieldPolicy | FieldReadFunction, + needCompanion?: FieldPolicy | FieldReadFunction, parkingAvailable?: FieldPolicy | FieldReadFunction, parkingCount?: FieldPolicy | FieldReadFunction, pathDescription?: FieldPolicy | FieldReadFunction, pathExists?: FieldPolicy | FieldReadFunction, + tel?: FieldPolicy | FieldReadFunction, thumbnails?: FieldPolicy | FieldReadFunction, toiletAvailable?: FieldPolicy | FieldReadFunction, wheelChairRentable?: FieldPolicy | FieldReadFunction }; -export type QueryKeySpecifier = ('places' | QueryKeySpecifier)[]; +export type PlaceEdgeKeySpecifier = ('cursor' | 'node' | PlaceEdgeKeySpecifier)[]; +export type PlaceEdgeFieldPolicy = { + cursor?: FieldPolicy | FieldReadFunction, + node?: FieldPolicy | FieldReadFunction +}; +export type PlacesConnectionKeySpecifier = ('edges' | 'pageInfo' | 'totalCount' | PlacesConnectionKeySpecifier)[]; +export type PlacesConnectionFieldPolicy = { + edges?: FieldPolicy | FieldReadFunction, + pageInfo?: FieldPolicy | FieldReadFunction, + totalCount?: FieldPolicy | FieldReadFunction +}; +export type QueryKeySpecifier = ('place' | 'placeCount' | 'places' | QueryKeySpecifier)[]; export type QueryFieldPolicy = { + place?: FieldPolicy | FieldReadFunction, + placeCount?: FieldPolicy | FieldReadFunction, places?: FieldPolicy | FieldReadFunction }; export type StrictTypedTypePolicies = { @@ -150,10 +327,22 @@ export type StrictTypedTypePolicies = { keyFields?: false | MetadataKeySpecifier | (() => undefined | MetadataKeySpecifier), fields?: MetadataFieldPolicy, }, + PageInfo?: Omit & { + keyFields?: false | PageInfoKeySpecifier | (() => undefined | PageInfoKeySpecifier), + fields?: PageInfoFieldPolicy, + }, Place?: Omit & { keyFields?: false | PlaceKeySpecifier | (() => undefined | PlaceKeySpecifier), fields?: PlaceFieldPolicy, }, + PlaceEdge?: Omit & { + keyFields?: false | PlaceEdgeKeySpecifier | (() => undefined | PlaceEdgeKeySpecifier), + fields?: PlaceEdgeFieldPolicy, + }, + PlacesConnection?: Omit & { + keyFields?: false | PlacesConnectionKeySpecifier | (() => undefined | PlacesConnectionKeySpecifier), + fields?: PlacesConnectionFieldPolicy, + }, Query?: Omit & { keyFields?: false | QueryKeySpecifier | (() => undefined | QueryKeySpecifier), fields?: QueryFieldPolicy, diff --git a/src/apollo.ts b/src/apollo.ts index e6e3a6f..5ab1aae 100644 --- a/src/apollo.ts +++ b/src/apollo.ts @@ -1,6 +1,26 @@ import { ApolloClient, InMemoryCache } from '@apollo/client' +import { relayStylePagination } from '@apollo/client/utilities' export const client = new ApolloClient({ uri: import.meta.env.VITE_API_URL, - cache: new InMemoryCache(), + cache: new InMemoryCache({ + typePolicies: { + Query: { + fields: { + places: relayStylePagination([ + 'first', + 'last', + 'categories', + 'parkingAvailable', + 'wheelChairRentable', + 'elevatorAvailable', + 'toiletAvailable', + 'pathExists', + 'needCompanion', + 'coordinates', + ]), + }, + }, + }, + }), }) diff --git a/src/assets/carbon_error.svg b/src/assets/carbon_error.svg new file mode 100644 index 0000000..d3c3f8e --- /dev/null +++ b/src/assets/carbon_error.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/kakao.svg b/src/assets/kakao.svg new file mode 100644 index 0000000..ad47a01 --- /dev/null +++ b/src/assets/kakao.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/assets/mask.svg b/src/assets/mask.svg new file mode 100644 index 0000000..d7297b9 --- /dev/null +++ b/src/assets/mask.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/assets/navigation.svg b/src/assets/navigation.svg new file mode 100644 index 0000000..f8323b9 --- /dev/null +++ b/src/assets/navigation.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/phone.svg b/src/assets/phone.svg new file mode 100644 index 0000000..dbdde56 --- /dev/null +++ b/src/assets/phone.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/wheelchair.svg b/src/assets/wheelchair.svg new file mode 100644 index 0000000..a7cc6e5 --- /dev/null +++ b/src/assets/wheelchair.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/components/Search/DestinationCard.tsx b/src/components/Search/DestinationCard.tsx new file mode 100644 index 0000000..8e46567 --- /dev/null +++ b/src/components/Search/DestinationCard.tsx @@ -0,0 +1,171 @@ +import { getDistance, linkToKaKaoMap } from 'utils/index' +import { motion, useInView } from 'framer-motion' +import styled from 'styled-components' +import { ReactComponent as Navigation } from 'assets/navigation.svg' +import { ReactComponent as Phone } from 'assets/phone.svg' +import { ReactComponent as WheelChair } from 'assets/wheelchair.svg' +import { FC, useEffect, useMemo, useRef } from 'react' + +const DestinationCard: FC = ({ node, maxLength, idx, fetchMore }) => { + const ref = useRef(null) + const inView = useInView(ref, { once: true }) + const isLast = useMemo(() => maxLength === idx + 1, [idx, maxLength]) + useEffect(() => { + if (isLast && inView) { + fetchMore() + } + }, [isLast, inView]) + return ( + + + + + + +
+

{node.name}

+ + 나와의 거리 {getDistance(node.distance)}km + +
+ {node.address + .split(' ') + .filter((_, i) => i !== 0) + .join(' ')} +
+
+ + + + + 전화하기 + + +
+
+ + + + + + + +
+ ) +} + +export default DestinationCard +const Destination = styled(motion.div)` + padding: 1rem; + border-radius: 1rem; + display: flex; + flex-direction: column; + background-color: white; + > div:first-child { + padding-bottom: 1.2rem; + border-bottom: 1px solid #efeff0; + overflow-x: scroll; + } + > div:last-child { + margin-top: 1.2rem; + overflow-x: scroll; + } +` + +const Location = styled.div` + display: flex; + align-items: center; + color: gray; + font-size: 12px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +` +const LocationWrapper = styled.div` + flex: 1; + display: flex; + flex-direction: column; + justify-content: flex-end; + row-gap: 1rem; +` + +const PlaceHolderWrapper = styled.div` + border-radius: 1.5rem; + aspect-ratio: 1/1; + width: 10rem; + height: 10rem; + position: relative; + overflow: hidden; + img { + aspect-ratio: 1/1; + object-fit: cover; + } +` +const TopButtons = styled.div` + display: flex; + align-items: center; + justify-content: space-between; + column-gap: 1rem; + button, + a { + height: 2.8rem; + display: flex; + align-items: center; + justify-content: center; + border: 1px solid #efeff0; + column-gap: 0.5rem; + flex: 1; + border-radius: 999rem; + } +` +const Top = styled.div` + display: flex; + column-gap: 1.5rem; +` +const Buttons = styled.div` + display: flex; + column-gap: 1.6rem; + /* justify-content: space-around; */ +` + +const BottomButtons = styled(Buttons)` + /* justify-content: space-around; */ +` + +const Address = styled.span` + word-break: break-all; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + width: inherit; +` + +const Button = styled.button` + width: 4.6rem; + aspect-ratio: 1/1; + display: flex; + justify-content: center; + align-items: center; + background-color: #efeff0; + border-radius: 999rem; +` diff --git a/src/constants/common.ts b/src/constants/common.ts new file mode 100644 index 0000000..65c1767 --- /dev/null +++ b/src/constants/common.ts @@ -0,0 +1 @@ +export const PER_PAGE = 10 diff --git a/src/hooks/useGetSelection.ts b/src/hooks/useGetSelection.ts new file mode 100644 index 0000000..f225f8a --- /dev/null +++ b/src/hooks/useGetSelection.ts @@ -0,0 +1,19 @@ +import { useCallback } from 'react' +import store, { IStore } from 'store/index' + +const useGetSelection = () => { + const selectorFn = useCallback( + (state: IStore) => + Object.keys(state.selection).reduce((acc, cur) => { + if (state.selection[cur] || cur === 'needCompanion') { + return { ...acc, [cur]: state.selection[cur] } + } + return { ...acc } + }, {}), + [], + ) + + return store(selectorFn, (a, b) => JSON.stringify(a) === JSON.stringify(b)) +} + +export default useGetSelection diff --git a/src/layout/Default.tsx b/src/layout/Default.tsx index 876a286..82f3d8c 100644 --- a/src/layout/Default.tsx +++ b/src/layout/Default.tsx @@ -4,15 +4,10 @@ import styled from 'styled-components' import { ReactComponent as Baby } from 'assets/baby.svg' import { ReactComponent as Reset } from 'assets/reset.svg' import store from 'store/index' -import { gql, useQuery } from '@apollo/client' - -import { GetPlaceQuery } from 'api/graphql' -import { placeInfoFragment } from '../fragments' import { AnimatePresence, easeInOut, motion, - useDragControls, useMotionValue, useTransform, Variants, @@ -34,18 +29,7 @@ const SliderVariants: Variants = { }, } -const q = gql` - query getPlace { - places { - ...PlaceInfo - __typename - } - } - ${placeInfoFragment} -` - const Default = () => { - const { data } = useQuery(q) const { setPosition, toggle, setToggle } = store((state) => ({ toggle: state.toggle, setPosition: state.setPosition, @@ -105,7 +89,6 @@ const Default = () => { setSliderHeight((prev) => sliderRef.current.clientHeight) } }, [sliderRef.current?.clientHeight]) - console.log(sliderHeight, 'sliderHeight') return (
@@ -145,41 +128,52 @@ const Default = () => { - 옵션 + 동행 여부 + + + 1 + 1 + + + + + 옵션 - 1 - 1 - 1 - 1 - 1 - 1 + 1 + 1 + 1 + 1 + 1 + 1 - 옵션 + 옵션 - 1 - 1 - 1 - 1 - 1 - 1 + 1 + 1 + 1 + 1 + 1 + 1
- 초기화 + + 초기화 +
@개 여행지 보기
@@ -203,10 +197,10 @@ const SnapBars = styled(motion.div)` transform: translateX(-50%); ` const SnapBar = styled.div` - width: 5rem; + width: 3.4rem; height: 0.4rem; border-radius: 999rem; - background-color: gray; + background-color: #efeff0; ` const Content = styled.div` @@ -231,12 +225,14 @@ const Footer = styled.div` const FilterList = styled.div` &:first-child { - padding-bottom: 2.2rem; - border-bottom: 1px solid rgba(0, 0, 0, 0.178); + padding-bottom: 1.4rem; + border-bottom: 1px solid #efeff0; } - + div { - padding: 2.2rem 0; + padding: 1.4rem 0; + &:not(:last-child) { + border-bottom: 1px solid #efeff0; + } } ` const FilterItems = styled.div` @@ -247,8 +243,8 @@ const FilterItems = styled.div` const FilterItem = styled.div` display: flex; justify-content: center; - padding: 0.5rem 0; - background-color: gray; + /* padding: 0.5rem 0; */ + background-color: #efeff0; border-radius: 999rem; align-items: center; ` @@ -285,8 +281,9 @@ const Slider = styled(motion.div)` const Main = styled.main` max-width: 412px; + width: 100vw; margin: 0 auto; - padding: 4rem 2rem; + /* padding: 4rem 2rem; */ ` const Fallback = styled.div` diff --git a/src/routes/Router.tsx b/src/routes/Router.tsx index 93f84f8..ea109f5 100644 --- a/src/routes/Router.tsx +++ b/src/routes/Router.tsx @@ -1,18 +1,71 @@ import ErrorBoundary from 'components/common/ErrorBoundary' import { LazyExoticComponent, Suspense, FC, lazy } from 'react' -import { BrowserRouter, Outlet, Route, Routes } from 'react-router-dom' +import { BrowserRouter, Link, Route, Routes } from 'react-router-dom' +import { ReactComponent as Carbon } from 'assets/carbon_error.svg' import GlobalStyle from '../GlobalStyle' import Default from 'layout/Default' +import styled from 'styled-components' const Error = () => { - return <>ERROR + return ( + + +

잠시 서비스 오류가 발생했어요.

+ + 홈으로 이동하기 + +
+ ) +} + +export const Loading: FC<{ text?: string }> = ({ text = '페이지를 불러오고 있어요...' }) => { + return ( + + +

{text}

+
+ ) } + +const LoadingIcon = styled.div` + width: 10rem; + height: 10rem; + background-color: gray; + border-radius: 999rem; +` + +const LoadingWrapper = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + row-gap: 4rem; + height: calc(var(--vh, 1vh) * 100); +` + +const ErrorWrapper = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + height: calc(var(--vh, 1vh) * 100); + > p { + margin: 3.5rem 0; + } +` +const GoHome = styled(Link)` + padding: 1rem 2.5rem; + border-radius: 999rem; + color: white; + background-color: #61646b; +` + const Loadable = (Component: LazyExoticComponent>) => (props: JSX.IntrinsicAttributes): JSX.Element => ( }> - + }> diff --git a/src/screen/Search.tsx b/src/screen/Search.tsx index 0db7452..aa82fa6 100644 --- a/src/screen/Search.tsx +++ b/src/screen/Search.tsx @@ -1,244 +1,184 @@ import styled from 'styled-components' -import { ReactComponent as Placeholder } from 'assets/placeholder.svg' -import { ReactComponent as LocationIcon } from 'assets/location.svg' +import { ReactComponent as Kakao } from 'assets/kakao.svg' + import store from 'store/index' +import { gql, useQuery } from '@apollo/client' +import { PER_PAGE } from 'constants/common' +import useGetSelection from 'hooks/useGetSelection' +import { GetSearchListQuery, GetSearchListQueryVariables } from 'api/graphql' +import { useMemo } from 'react' +import DestinationCard from 'components/Search/DestinationCard' +import { Loading } from 'routes/Router' + +const SearchQuery = gql` + query GetSearchList( + $before: String + $after: String + $first: Int + $last: Int + $categories: [String!] + $parkingAvailable: Boolean + $wheelChairRentable: Boolean + $elevatorAvailable: Boolean + $toiletAvailable: Boolean + $pathExists: Boolean + $needCompanion: Boolean! + $coordinates: CoordinateInput + ) { + places( + before: $before + after: $after + first: $first + last: $last + categories: $categories + parkingAvailable: $parkingAvailable + wheelChairRentable: $wheelChairRentable + elevatorAvailable: $elevatorAvailable + toiletAvailable: $toiletAvailable + pathExists: $pathExists + needCompanion: $needCompanion + coordinates: $coordinates + ) { + pageInfo { + startCursor + endCursor + hasNextPage + hasNextPage + } + edges { + node { + id + name + address + thumbnails + parkingAvailable + parkingCount + wheelChairRentable + elevatorAvailable + toiletAvailable + pathExists + pathDescription + latitude + longitude + category + needCompanion + distance + tel + } + cursor + } + totalCount + } + } +` + const Search = () => { - const [toggle, setToggle] = store((state) => [state.toggle, state.setToggle]) - return ( -
-

@개의 여행지를 추천드려요.

+ const { setToggle, position } = store((state) => ({ + setToggle: state.setToggle, + position: state.position, + })) + const selection = useGetSelection() + const { + data: { places } = {}, + fetchMore, + loading, + } = useQuery(SearchQuery, { + variables: { + ...selection, + coordinates: { + latitude: position?.coords.latitude, + longitude: position?.coords.longitude, + }, + first: PER_PAGE, + } as GetSearchListQueryVariables, + }) + + const hasNextPage = places?.pageInfo.hasNextPage + const edges = useMemo(() => places?.edges, [places?.edges]) + return loading ? ( + + ) : ( + +
+

+ 내 주변 가까운
+ {places?.totalCount}개의 추천 관광지 +

+ +
+ - setToggle()}> + setToggle(true)}> {Array.from({ length: 5 }, (_, i) => i + 1).map((item) => ( - {item} + + {item} + ))} - -
- - {/* 보호자 동행 */} - - - -
-

장소명

- - - 제주시 무슨주소 - -
- - - - -
-
- - - - - - - -
- -
- - {/* 보호자 동행 */} - - - -
-

장소명

- - - 제주시 무슨주소 - -
- - - - -
-
- - - - - - - -
- -
- - {/* 보호자 동행 */} - - - -
-

장소명

- - - 제주시 무슨주소 - -
- - - - -
-
- - - - - - - -
- -
- - {/* 보호자 동행 */} - - - -
-

장소명

- - - 제주시 무슨주소 - -
- - - - -
-
- - - - - - - -
- -
- - {/* 보호자 동행 */} - - - -
-

장소명

- - - 제주시 무슨주소 - -
- - - - -
-
- - - - - - - -
+ {edges + ? edges.map(({ node }, i) => ( + { + if (hasNextPage) { + fetchMore({ + variables: { + after: places.pageInfo.endCursor, + }, + }) + } + }} + maxLength={edges.length} + /> + )) + : null}
-
+ ) } export default Search -const Stickable = styled.div` - position: sticky; - top: 0; - z-index: 1; -` -const Buttons = styled.div` - display: flex; - column-gap: 1.6rem; - /* justify-content: space-around; */ -` - -const BottomButtons = styled(Buttons)` - justify-content: space-around; -` -const Button = styled.button` - width: 4.4rem; - aspect-ratio: 1/1; - display: flex; - justify-content: center; - align-items: center; - background-color: gray; - border-radius: 999rem; -` -const Tag = styled.div` - position: absolute; - padding: 0.4rem 0.7rem; - border-radius: 0.5rem; - margin: 1rem; - right: 0; - top: 0; - color: white; - background-color: #333; -` - -const Location = styled.div` - display: flex; - color: gray; - font-size: 12px; - column-gap: 0.5rem; -` - -const LocationWrapper = styled.div` - flex: 1; +const Wrapper = styled.div` display: flex; flex-direction: column; - justify-content: flex-end; - row-gap: 1rem; ` -const PlaceHolderWrapper = styled.div` - padding: 1rem; - border: 1px solid #333; - background-color: gray; - display: flex; - justify-content: center; - align-items: center; - border-radius: 50%; - position: relative; - aspect-ratio: 1/1; - flex: 0.65; +const Stickable = styled.div` + position: sticky; + top: 0; + z-index: 1; ` const DestinationList = styled.div` display: flex; flex-direction: column; row-gap: 1.5rem; + padding: 1.5rem 2rem; + background-color: #efeff0; ` const FilterList = styled.div` display: flex; column-gap: 0.75rem; - border-top: 1px solid gray; - border-bottom: 1px solid gray; + border-top: 1px solid #efeff0; + border-bottom: 1px solid #efeff0; padding: 1.5rem 2rem; - margin: 1.5rem 0; - position: relative; + background-color: white; - left: -2rem; + width: 100vw; overflow-x: scroll; ` @@ -247,15 +187,6 @@ const FilterItem = styled.div` padding: 0.25rem 0; width: 7rem; text-align: center; - background-color: gray; + background-color: #efeff0; border-radius: 999rem; ` - -const Destination = styled.div` - border: 1px solid #efeff0; - padding: 1rem; - border-radius: 1rem; - row-gap: 1.5rem; - display: flex; - flex-direction: column; -` diff --git a/src/store/index.ts b/src/store/index.ts index 0e5419f..3974443 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -2,20 +2,40 @@ import { getIsMobile } from './../utils/index' import { create } from 'zustand' import { persist, createJSONStorage } from 'zustand/middleware' -interface IStore { +export interface IStore { isMobile: boolean toggle: boolean + selection: { + categories: string[] | null + parkingAvailable: boolean + wheelChairRentable: boolean + elevatorAvailable: boolean + toiletAvailable: boolean + pathExists: boolean + needCompanion: boolean + } position?: GeolocationPosition | null setToggle: (flag?: boolean) => void setPosition: (p: GeolocationPosition) => void } -const store = create()( +interface Store extends IStore {} + +const store = create()( persist( (set) => ({ isMobile: getIsMobile(), toggle: false, position: null, + selection: { + categories: null, + parkingAvailable: false, + wheelChairRentable: false, + elevatorAvailable: false, + toiletAvailable: false, + pathExists: false, + needCompanion: false, + }, setPosition: (position: GeolocationPosition) => set((state) => ({ ...state, position })), setToggle: (flag) => { set((state) => ({ ...state, toggle: flag !== undefined ? flag : !state.toggle })) @@ -26,7 +46,6 @@ const store = create()( name: 'uhdre-gamdi', storage: createJSONStorage(() => localStorage), merge(persistedState: any, currentState) { - console.log(getIsMobile(), 'getIsMobile()') return { ...persistedState, ...currentState, diff --git a/src/utils/index.ts b/src/utils/index.ts index 21bdfd9..3012280 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -2,6 +2,8 @@ import { Coord } from 'types/kakaoMap' export const getIsMobile = () => /Android|iPhone/i.test(navigator.userAgent) +export const getDistance = (distance: number) => distance / 1000 + export const linkToKaKaoMap = (coord: Coord) => { const isMobile = getIsMobile() if (isMobile) { diff --git a/tsconfig.json b/tsconfig.json index 4075ded..33bf345 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,6 +2,8 @@ "compilerOptions": { "paths": { "routes/*":["./src/routes/*"], + "constants/*":["./src/constants/*"], + "hooks/*":["./src/hooks/*"], "api/*":["./src/api/*"], "gql/*":["./src/gql/*"], "components/*":["./src/components/*"], diff --git a/vite.config.ts b/vite.config.ts index c05e713..3d3d86f 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -29,6 +29,10 @@ export default ({ mode }) => { find: 'store', replacement: path.resolve(__dirname, 'src/store'), }, + { + find: 'constants', + replacement: path.resolve(__dirname, 'src/constants'), + }, { find: 'apollo', replacement: path.resolve(__dirname, 'apollo'), @@ -45,6 +49,14 @@ export default ({ mode }) => { find: 'api', replacement: path.resolve(__dirname, 'src/api'), }, + { + find: 'hooks', + replacement: path.resolve(__dirname, 'src/hooks'), + }, + { + find: 'routes', + replacement: path.resolve(__dirname, 'src/routes'), + }, { find: 'types', replacement: path.resolve(__dirname, 'types'),