Skip to content

Commit 9f56812

Browse files
authored
Merge pull request #199 from P-pick/modify/#197/shorts-1
[#197] tour filter정보 스토리지에 저장
2 parents bdf5012 + 0cce596 commit 9f56812

17 files changed

Lines changed: 117 additions & 165 deletions

File tree

src/app/router/Router.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export default function Router() {
2828
<Route path="around-search" element={<AroundSearch />} />
2929
</Route>
3030
<Route path="/tour" element={<Tour />}>
31+
<Route path=":contentId" element={<GeoTrip />} />
3132
<Route path="geo-trip" element={<GeoTrip />} />
3233
<Route path="single/:contentId" element={<TourSingleInfo />} />
3334
<Route path="list" element={<TourList />} />

src/features/aroundTourist/ui/GeoAroundTouristMap.tsx

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useMemo, useRef, useState } from 'react';
1+
import { useMemo, useRef } from 'react';
22
import { useQuery } from '@tanstack/react-query';
33
import { Map } from 'react-kakao-maps-sdk';
44

@@ -10,26 +10,25 @@ import {
1010
NearbyTouristAttractionPinPoint,
1111
MiddleContent,
1212
} from '@/features/aroundTourist';
13-
import { TouristContentsTypeFilter } from '@/shared';
13+
import { TouristContentsTypeFilter, useLocalStorage } from '@/shared';
1414

15-
import type { AroundContentTypeId, TourItem } from '@/entities/tour';
15+
import type { TourItem } from '@/entities/tour';
1616
import type { GeoTripLocation } from '@/shared';
17+
import type { TourInjected } from '@/features/tour';
1718

1819
interface GeoAroundTouristMapProps {
1920
location: GeoTripLocation;
2021
contentId: string;
21-
tourContentTypeId: AroundContentTypeId;
2222
}
2323

24-
function GeoAroundTouristMap({
25-
location,
26-
tourContentTypeId,
27-
}: GeoAroundTouristMapProps) {
28-
const [selectedContentTypeId, setSelectedContentTypeId] =
29-
useState<AroundContentTypeId>(tourContentTypeId);
24+
function GeoAroundTouristMap({ location }: GeoAroundTouristMapProps) {
25+
const [tourFilter, setTourFilter] = useLocalStorage('tourInfo', {
26+
distance: '20000',
27+
contentTypeId: '12',
28+
} as TourInjected);
3029

3130
const { data: aroundTouristObjects = [] } = useQuery(
32-
aroundTouristQueries.list(location, selectedContentTypeId),
31+
aroundTouristQueries.list(location, tourFilter.contentTypeId),
3332
);
3433

3534
const middleTouristRef = useRef<TourItem | null>(null);
@@ -53,8 +52,8 @@ function GeoAroundTouristMap({
5352
<Map center={location} className="w-full h-full relative" level={7}>
5453
<div className="absolute top-0 left-0 z-10 w-full">
5554
<TouristContentsTypeFilter
56-
contentTypeId={selectedContentTypeId}
57-
setContentTypeId={setSelectedContentTypeId}
55+
contentTypeId={tourFilter.contentTypeId}
56+
setContentTypeId={setTourFilter}
5857
/>
5958
</div>
6059
<ResizingMap points={allLocation} />

src/features/map/lib/withAroundMapParams.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,13 @@ export default function withAroundMapParams<P extends InjectedProps>(
1919
const mapx = searchParams.get('lng');
2020
const mapy = searchParams.get('lat');
2121
const contentId = searchParams.get('contentId');
22-
const tourContentTypeId = searchParams.get(
23-
'contentTypeId',
24-
) as AroundContentTypeId;
2522

2623
const location: GeoTripLocation = {
2724
lat: mapy ? Number(mapy) : 0,
2825
lng: mapx ? Number(mapx) : 0,
2926
};
3027

31-
if (!location || !contentId || !tourContentTypeId) {
28+
if (!location || !contentId) {
3229
return (
3330
<div>
3431
필요한 정보가 부족합니다. 위치, 콘텐츠 ID, 관광지 타입을 확인해주세요.
@@ -41,7 +38,6 @@ export default function withAroundMapParams<P extends InjectedProps>(
4138
{...(props as P)}
4239
location={location}
4340
contentId={contentId}
44-
tourContentTypeId={tourContentTypeId}
4541
/>
4642
);
4743
};

src/features/tour/lib/withGeoTripParams.tsx

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,32 @@
1-
import { useSearchParams } from 'react-router-dom';
2-
31
import { isValidTourType } from '@/features/map';
42

5-
import type { AroundContentTypeId } from '@/entities/tour';
6-
interface InjectedProps {
7-
distance: string;
8-
tourContentTypeId: AroundContentTypeId;
9-
}
3+
import { useLocalStorage } from '@/shared';
4+
import type { TourInjected } from '../types';
105

11-
export function withGeoTripParams<P extends InjectedProps>(
6+
export function withGeoTripParams<P extends TourInjected>(
127
WrappedComponent: React.ComponentType<P>,
138
) {
14-
return function GeoTripWrapper(props: Omit<P, keyof InjectedProps>) {
15-
const [searchParams] = useSearchParams();
16-
const distance = searchParams.get('distance');
17-
const tourContentTypeId = searchParams.get('tour-type');
9+
return function GeoTripWrapper(props: Omit<P, keyof TourInjected>) {
10+
const [tourInfo] = useLocalStorage('tourInfo', {
11+
distance: '20000',
12+
contentTypeId: '12',
13+
});
1814

19-
if (!distance || !tourContentTypeId) {
15+
if (!tourInfo.distance || !tourInfo.contentTypeId) {
2016
throw new Error(
2117
'필요한 정보가 부족합니다. 거리와 관광지 타입을 확인해주세요.',
2218
);
2319
}
2420

25-
if (!isValidTourType(tourContentTypeId)) {
21+
if (!isValidTourType(tourInfo.contentTypeId)) {
2622
throw new Error('잘못된 관광 타입입니다.');
2723
}
2824

2925
return (
3026
<WrappedComponent
3127
{...(props as P)}
32-
distance={distance}
33-
tourContentTypeId={tourContentTypeId}
28+
distance={tourInfo.distance}
29+
contentTypeId={tourInfo.contentTypeId}
3430
/>
3531
);
3632
};

src/features/tour/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,8 @@ export type TourDetailImage = {
3333
originimgurl?: string;
3434
serialnum: string;
3535
};
36+
37+
export type TourInjected = {
38+
distance: string;
39+
contentTypeId: AroundContentTypeId;
40+
};

src/features/tourFilter/hook/index.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/features/tourFilter/hook/useTourFilterQuery.ts

Lines changed: 0 additions & 37 deletions
This file was deleted.

src/features/tourFilter/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
export * from './ui';
22
export * from './const';
33
export * from './type';
4-
export * from './hook';

src/features/tourFilter/ui/DistanceSlider.tsx

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,37 @@
1-
import type { Dispatch } from 'react';
2-
import type { Distance } from '@/features/tourFilter';
1+
import type { TourInjected } from '@/features/tour/types';
32

43
interface DistanceSliderProps {
5-
distance: number;
6-
setDistance: Dispatch<React.SetStateAction<Distance>>;
4+
distance: string;
5+
setDistance: (
6+
value: TourInjected | ((val: TourInjected) => TourInjected),
7+
) => void;
78
}
89

910
export default function DistanceSlider({
1011
distance,
1112
setDistance,
1213
}: DistanceSliderProps) {
14+
const handleDistanceChange = (e: React.ChangeEvent<HTMLInputElement>) => {
15+
setDistance(prev => ({
16+
...prev,
17+
distance: e.target.value,
18+
}));
19+
};
20+
1321
return (
1422
<>
1523
<div className="flex items-center justify-between text-sm text-black mb-1">
1624
<span>1km</span>
25+
<span>{distance}m</span>
1726
<span>20km</span>
1827
</div>
1928
<input
2029
type="range"
21-
min={1}
22-
max={20}
23-
step={1}
30+
min={'1000'}
31+
max={'20000'}
32+
step={'1000'}
2433
value={distance}
25-
onChange={e => setDistance(Number(e.target.value) as Distance)}
34+
onChange={handleDistanceChange}
2635
className="w-full"
2736
/>
2837
</>

src/features/tourFilter/ui/TourFilterSidebar.tsx

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
1-
import { useState } from 'react';
21
import { AnimatePresence, motion } from 'framer-motion';
32

4-
import {
5-
DistanceSlider,
6-
SortOptions,
7-
useTourFilterQuery,
8-
} from '@/features/tourFilter';
9-
import { TouristContentsTypeFilter } from '@/shared';
10-
11-
import type { SortOption } from '@/features/tourFilter';
3+
import { DistanceSlider } from '@/features/tourFilter';
4+
import { TouristContentsTypeFilter, useLocalStorage } from '@/shared';
5+
import type { TourInjected } from '@/features/tour/types';
6+
import { useState } from 'react';
127

138
interface BottomSheetProps {
149
onClose: () => void;
@@ -19,19 +14,31 @@ export default function TourFilterSidebar({
1914
onClose,
2015
isOpen,
2116
}: BottomSheetProps) {
22-
const { getQuery, updateQuery } = useTourFilterQuery();
17+
const [tourFilter, setTourFilter] = useLocalStorage('tourInfo', {
18+
distance: '20000',
19+
contentTypeId: '12',
20+
} as TourInjected);
2321

24-
const [aroundContentTypeId, setAroundContentTypeId] = useState(
25-
getQuery()?.tourType ?? '12',
26-
);
27-
const [distance, setDistance] = useState(getQuery()?.distance || 1);
28-
const [sortOption, setSortOption] = useState<SortOption>('distance');
22+
const [currentTourFilter, setCurrentTourFilter] = useState<TourInjected>({
23+
distance: tourFilter.distance,
24+
contentTypeId: tourFilter.contentTypeId,
25+
});
2926

3027
const handleSubmit = () => {
31-
updateQuery({ tourType: aroundContentTypeId, distance });
28+
setTourFilter({
29+
distance: currentTourFilter.distance,
30+
contentTypeId: currentTourFilter.contentTypeId,
31+
});
3232
onClose();
3333
};
3434

35+
const handleReset = () => {
36+
setCurrentTourFilter({
37+
distance: '20000',
38+
contentTypeId: '12',
39+
});
40+
};
41+
3542
return (
3643
<AnimatePresence>
3744
{isOpen && (
@@ -58,28 +65,25 @@ export default function TourFilterSidebar({
5865
관광 타입
5966
</label>
6067
<TouristContentsTypeFilter
61-
contentTypeId={aroundContentTypeId}
62-
setContentTypeId={setAroundContentTypeId}
68+
contentTypeId={currentTourFilter.contentTypeId}
69+
setContentTypeId={setCurrentTourFilter}
6370
/>
6471
</section>
6572
<section className="my-5 py-5 px-5 rounded-xl shadow mr-3">
6673
<label className="block mb-2 text-lg font-semibold text-black">
6774
거리
6875
</label>
69-
<DistanceSlider distance={distance} setDistance={setDistance} />
70-
</section>
71-
<section className="my-5 py-5 px-5 rounded-xl shadow mr-3">
72-
<label className="block mb-2 text-lg font-semibold text-black">
73-
정렬
74-
</label>
75-
<SortOptions
76-
selected={sortOption}
77-
setSelected={setSortOption}
76+
<DistanceSlider
77+
distance={currentTourFilter.distance}
78+
setDistance={setCurrentTourFilter}
7879
/>
7980
</section>
8081
</main>
8182
<footer className="flex gap-3">
82-
<button className="w-30 rounded-2xl bg-gray-300 px-5 py-2 text-black cursor-pointer ">
83+
<button
84+
className="w-30 rounded-2xl bg-gray-300 px-5 py-2 text-black cursor-pointer"
85+
onClick={handleReset}
86+
>
8387
초기화
8488
</button>
8589
<button

0 commit comments

Comments
 (0)