Skip to content

Commit 324d5d4

Browse files
authored
merge: record detail 선택 option bottom sheet 추가 (#21)
merge: record detail 선택 option bottom sheet 추가 (#21)
2 parents f4c4880 + 87cfaf9 commit 324d5d4

File tree

5 files changed

+145
-64
lines changed

5 files changed

+145
-64
lines changed

packages/react-native/src/components/maps/RecordCard.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ interface CardProps {
1616
location: KoreaLocationName;
1717
date: string;
1818
backgroundImage: string;
19+
handleClickCard: () => void;
1920
}
2021

2122
const { width } = Dimensions.get('window');
@@ -28,6 +29,7 @@ export default function RecordCard({
2829
location,
2930
date,
3031
backgroundImage,
32+
handleClickCard,
3133
}: CardProps) {
3234
const navigation = useNavigation<StackNavigation<'Maps/Record'>>();
3335
return (
@@ -48,9 +50,12 @@ export default function RecordCard({
4850
}}
4951
>
5052
<View className="flex-1 justify-between px-3 py-1.5 bg-black/20">
51-
<View className="flex items-end w-full">
53+
<TouchableOpacity
54+
className="flex items-end w-full"
55+
onPress={handleClickCard}
56+
>
5257
<DotMenuIcon />
53-
</View>
58+
</TouchableOpacity>
5459
<View className="p-2.5 gap-2">
5560
<Font.Bold type="body1" color="white">
5661
{title}

packages/react-native/src/components/maps/RecordCardList.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1+
import React from 'react';
12
import { View } from 'react-native';
23
import RecordCard, { CARD_GAP } from './RecordCard';
34
import { KoreaLocationName } from '@/types/map';
45

5-
type MockCardData = {
6+
export type MockCardData = {
67
id: number;
78
title: string;
89
location: KoreaLocationName;
@@ -37,7 +38,13 @@ const MOCK_LOG_CARD: MockCardData[] = [
3738
},
3839
];
3940

40-
export default function RecordCardList() {
41+
interface RecordCardListProps {
42+
handleOpenOptions: (data: MockCardData) => void;
43+
}
44+
45+
export default function RecordCardList({
46+
handleOpenOptions,
47+
}: RecordCardListProps) {
4148
return (
4249
<View
4350
className="mt-5 flex flex-row flex-wrap "
@@ -53,6 +60,7 @@ export default function RecordCardList() {
5360
date={data.date}
5461
location={data.location}
5562
backgroundImage={data.backgroundImage}
63+
handleClickCard={() => handleOpenOptions(data)}
5664
/>
5765
</View>
5866
))}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { ReactNode, useRef } from 'react';
2+
import BottomSheet, {
3+
BottomSheetBackdrop,
4+
BottomSheetBackdropProps,
5+
BottomSheetView,
6+
} from '@gorhom/bottom-sheet';
7+
8+
interface BottomSheetProps {
9+
isShow?: boolean;
10+
children: ReactNode;
11+
}
12+
13+
const SNAP_POINTS = ['30%'];
14+
15+
const renderBackdropComponent = (props: BottomSheetBackdropProps) => (
16+
<BottomSheetBackdrop
17+
// eslint-disable-next-line react/jsx-props-no-spreading
18+
{...props}
19+
pressBehavior="close"
20+
// Backdrop이 등장하기 시작하는 bottom sheet의 index
21+
appearsOnIndex={0}
22+
// Backdrop이 사라지기 시작하는 bottom sheet의 index
23+
disappearsOnIndex={-1}
24+
/>
25+
);
26+
27+
export default function useBottomSheet() {
28+
const bottomSheetRef = useRef<BottomSheet>(null);
29+
30+
function BottomSheetComponent({ isShow, children }: BottomSheetProps) {
31+
if (!isShow) {
32+
return null;
33+
}
34+
35+
return (
36+
<BottomSheet
37+
backdropComponent={renderBackdropComponent}
38+
ref={bottomSheetRef}
39+
snapPoints={SNAP_POINTS}
40+
enablePanDownToClose
41+
>
42+
<BottomSheetView>{children}</BottomSheetView>
43+
</BottomSheet>
44+
);
45+
}
46+
47+
const hideBottomSheet = () => {
48+
bottomSheetRef.current?.close();
49+
};
50+
51+
const showBottonSheet = () => {
52+
bottomSheetRef.current?.snapToIndex(0);
53+
};
54+
55+
return {
56+
BottomSheet: BottomSheetComponent,
57+
showBottonSheet,
58+
hideBottomSheet,
59+
};
60+
}

packages/react-native/src/pages/Maps/Maps.tsx

Lines changed: 32 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -2,39 +2,21 @@ import { Dimensions, View, TouchableOpacity } from 'react-native';
22
import { Font } from 'design-system';
33
import { geoPath, geoMercator } from 'd3-geo';
44
import { Svg, G, Path } from 'react-native-svg';
5-
import { useMemo, useRef, useState } from 'react';
6-
import BottomSheet, {
7-
BottomSheetBackdrop,
8-
BottomSheetBackdropProps,
9-
BottomSheetView,
10-
} from '@gorhom/bottom-sheet';
5+
import { useState } from 'react';
116
import mapData from '@/assets/mapData';
127
import { KoreaLocationName } from '@/types/map';
138
import { StackNavigation } from '@/types/navigation';
9+
import useBottomSheet from '@/hooks/useBottomSheet';
1410

1511
interface MapsMainProps {
1612
navigation: StackNavigation<'Maps/Main'>;
1713
}
1814

1915
const { width, height } = Dimensions.get('window');
2016

21-
const renderBackdropComponent = (props: BottomSheetBackdropProps) => (
22-
<BottomSheetBackdrop
23-
// eslint-disable-next-line react/jsx-props-no-spreading
24-
{...props}
25-
pressBehavior="close"
26-
// Backdrop이 등장하기 시작하는 bottom sheet의 index
27-
appearsOnIndex={0}
28-
// Backdrop이 사라지기 시작하는 bottom sheet의 index
29-
disappearsOnIndex={-1}
30-
/>
31-
);
32-
3317
export default function Maps({ navigation }: MapsMainProps) {
34-
const bottomSheetRef = useRef<BottomSheet>(null);
3518
const [region, setRegion] = useState<KoreaLocationName>();
36-
37-
const snapPoints = useMemo(() => ['30%'], []);
19+
const { BottomSheet, showBottonSheet } = useBottomSheet();
3820

3921
const projection = geoMercator() // 구형 투영도
4022
.scale(3300) // 스케일 조정
@@ -58,49 +40,41 @@ export default function Maps({ navigation }: MapsMainProps) {
5840
strokeWidth={1}
5941
onPress={() => {
6042
setRegion(feature.properties.CTP_KOR_NM);
61-
bottomSheetRef.current?.snapToIndex(0);
43+
showBottonSheet();
6244
}}
6345
/>
6446
);
6547
})}
6648
</G>
6749
</Svg>
68-
{region && (
69-
<BottomSheet
70-
backdropComponent={renderBackdropComponent}
71-
ref={bottomSheetRef}
72-
snapPoints={snapPoints}
73-
enablePanDownToClose
74-
>
75-
<BottomSheetView>
76-
<View className="flex justify-evenly items-center mt-2 flex-col gap-4">
77-
<View className="flex">
78-
<Font.Bold type="mainTitle" color="black">
79-
{region}
80-
</Font.Bold>
81-
</View>
82-
<View className="flex items-center w-full ">
83-
<TouchableOpacity className="py-2">
84-
<Font type="title1" color="black">
85-
대표사진 설정하기
86-
</Font>
87-
</TouchableOpacity>
88-
<View className="w-[90%] h-[0.5px] bg-[#333333]" />
89-
<TouchableOpacity
90-
className="py-2"
91-
onPress={() =>
92-
navigation.navigate('Maps/Record', { location: region })
93-
}
94-
>
95-
<Font type="title1" color="black">
96-
로그보기
97-
</Font>
98-
</TouchableOpacity>
99-
</View>
100-
</View>
101-
</BottomSheetView>
102-
</BottomSheet>
103-
)}
50+
<BottomSheet isShow={Boolean(region)}>
51+
<View className="flex justify-evenly items-center mt-2 flex-col gap-4">
52+
<View className="flex">
53+
<Font.Bold type="mainTitle" color="black">
54+
{region}
55+
</Font.Bold>
56+
</View>
57+
<View className="flex items-center w-full ">
58+
<TouchableOpacity className="py-2">
59+
<Font type="title1" color="black">
60+
대표사진 설정하기
61+
</Font>
62+
</TouchableOpacity>
63+
<View className="w-[90%] h-[0.5px] bg-[#333333]" />
64+
<TouchableOpacity
65+
className="py-2"
66+
onPress={() =>
67+
region &&
68+
navigation.navigate('Maps/Record', { location: region })
69+
}
70+
>
71+
<Font type="title1" color="black">
72+
로그보기
73+
</Font>
74+
</TouchableOpacity>
75+
</View>
76+
</View>
77+
</BottomSheet>
10478
</View>
10579
);
10680
}

packages/react-native/src/pages/Maps/Records.tsx

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,35 @@
11
import { TouchableOpacity, View } from 'react-native';
22
import { useRoute } from '@react-navigation/native';
3+
import { useState } from 'react';
4+
import { Font } from 'design-system';
35
import SortIcon from '@/assets/SortIcon';
46
import FloatingPlusButton from '@/components/maps/FloatingPlusButton';
57
import BackGroundGradient from '@/layouts/BackGroundGradient';
68
import { LOG_PADDING_X } from '@/components/maps/RecordCard';
7-
import RecordCardList from '@/components/maps/RecordCardList';
9+
import RecordCardList, { MockCardData } from '@/components/maps/RecordCardList';
810
import Header from '@/components/common/Header';
911
import { StackNavigation, StackRouteProps } from '@/types/navigation';
12+
import useBottomSheet from '@/hooks/useBottomSheet';
1013

1114
interface RecordsProps {
1215
navigation: StackNavigation<'Maps/Record'>;
1316
}
1417

1518
export default function Records({ navigation }: RecordsProps) {
19+
const { BottomSheet, showBottonSheet } = useBottomSheet();
20+
21+
const [selectedRecord, setSelectedRecord] = useState<MockCardData>();
1622
const sort = () => {
1723
// TODO: 실제 구현 필요(현재 UI없음)
1824
};
1925

2026
const route = useRoute<StackRouteProps<'Maps/Record'>>();
27+
28+
const handleClickCard = (selectedCardData: MockCardData) => {
29+
showBottonSheet();
30+
setSelectedRecord(selectedCardData);
31+
};
32+
2133
return (
2234
<View>
2335
<BackGroundGradient>
@@ -36,14 +48,36 @@ export default function Records({ navigation }: RecordsProps) {
3648
paddingRight: LOG_PADDING_X,
3749
}}
3850
>
39-
<RecordCardList />
51+
<RecordCardList handleOpenOptions={handleClickCard} />
4052
</View>
4153
</BackGroundGradient>
4254
<FloatingPlusButton
4355
onPress={() => navigation.navigate('Maps/PostRecord')}
4456
bottom={16}
4557
right={16}
4658
/>
59+
<BottomSheet isShow={Boolean(selectedRecord)}>
60+
<View className="flex justify-evenly items-center mt-2 flex-col gap-4">
61+
<View className="flex">
62+
<Font.Bold type="mainTitle" color="black">
63+
{selectedRecord?.title}
64+
</Font.Bold>
65+
</View>
66+
<View className="flex items-center w-full ">
67+
<TouchableOpacity className="py-2">
68+
<Font.Light type="title1" color="black">
69+
수정
70+
</Font.Light>
71+
</TouchableOpacity>
72+
<View className="w-[90%] h-[0.5px] bg-[#333333]" />
73+
<TouchableOpacity className="py-2">
74+
<Font.Light type="title1" color="black">
75+
삭제
76+
</Font.Light>
77+
</TouchableOpacity>
78+
</View>
79+
</View>
80+
</BottomSheet>
4781
</View>
4882
);
4983
}

0 commit comments

Comments
 (0)