Skip to content

Commit b211f13

Browse files
authored
merge: Record 수정 기능 추가 (#26)
merge: Record 수정 기능 추가 (#26)
2 parents 0a4bcc4 + d25a896 commit b211f13

File tree

9 files changed

+198
-70
lines changed

9 files changed

+198
-70
lines changed

packages/react-native/src/apis/queries/records/useRecordDetailQuery.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useRef } from 'react';
2-
import { useQuery } from '@tanstack/react-query';
2+
import { useSuspenseQuery } from '@tanstack/react-query';
33

4-
interface RecordGetResponse {
4+
export interface RecordGetResponse {
55
recordId: number;
66
name: string;
77
description: string;
@@ -15,7 +15,6 @@ interface UseRecordDetailQueryParams {
1515

1616
interface UseRecordDetailQueryReturn {
1717
recordDetail?: RecordGetResponse;
18-
isLoading: boolean;
1918
isError: boolean;
2019
refetch: () => void;
2120
}
@@ -25,7 +24,7 @@ export default function useRecordDetailQuery({
2524
}: UseRecordDetailQueryParams) {
2625
const returnRef = useRef({} as UseRecordDetailQueryReturn);
2726

28-
const { data, isLoading, isError, refetch } = useQuery({
27+
const { data, isError, refetch } = useSuspenseQuery({
2928
queryKey: ['logDetail'],
3029
queryFn: async () => ({
3130
recordId,
@@ -40,7 +39,6 @@ export default function useRecordDetailQuery({
4039
});
4140

4241
returnRef.current.recordDetail = data;
43-
returnRef.current.isLoading = isLoading;
4442
returnRef.current.isError = isError;
4543
returnRef.current.refetch = refetch;
4644

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { FlatList, Image, TouchableOpacity, View } from 'react-native';
2+
import { Font } from 'design-system';
3+
import PlusIcon from '@/assets/PlusIcon';
4+
import useRecordFormState from '@/hooks/useRecordFormState';
5+
6+
interface RecordFormImagesProps {
7+
handlePressAddPhoto: () => Promise<unknown>;
8+
}
9+
10+
export default function RecordFormImages({
11+
handlePressAddPhoto,
12+
}: RecordFormImagesProps) {
13+
const { images } = useRecordFormState();
14+
return (
15+
<>
16+
<Font type="body2" color="white">
17+
이미지 첨부
18+
</Font>
19+
<View className="flex-row items-center mt-2 ">
20+
<TouchableOpacity
21+
className="bg-SPOT-white/60 rounded-md p-6 aspect-square w-16 justify-center items-center "
22+
onPress={handlePressAddPhoto}
23+
>
24+
<PlusIcon />
25+
</TouchableOpacity>
26+
<FlatList
27+
className="ml-2"
28+
horizontal
29+
data={images}
30+
renderItem={({ item }) => {
31+
return (
32+
<Image
33+
source={{ uri: item }}
34+
style={{
35+
width: 64,
36+
height: 64,
37+
borderRadius: 6,
38+
}}
39+
/>
40+
);
41+
}}
42+
/>
43+
</View>
44+
</>
45+
);
46+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { View } from 'react-native';
2+
import { Button, Font } from 'design-system';
3+
import { useNavigation, useRoute } from '@react-navigation/native';
4+
import RecordFormDescription from '@/components/maps/RecordFormDescription';
5+
import RecordFormTitle from '@/components/maps/RecordFormTitle';
6+
import useRecordFormState from '@/hooks/useRecordFormState';
7+
import useRecordMutation from '@/apis/mutations/useRecordMutation';
8+
import { StackNavigation, StackRouteProps } from '@/types/navigation';
9+
import RecordFormImages from './RecordFormImages';
10+
import useGallery from '@/hooks/useGallery';
11+
12+
export default function RecordModifyForm() {
13+
const { validate, title, description, images, resetImages } =
14+
useRecordFormState();
15+
const { getPhoto } = useGallery();
16+
const { patchMutate } = useRecordMutation();
17+
const { params } = useRoute<StackRouteProps<'Maps/ModifyRecord'>>();
18+
const navigate = useNavigation<StackNavigation<'Maps/ModifyRecord'>>();
19+
20+
const handlePressAddPhoto = async () => {
21+
const photos = await getPhoto(10);
22+
if (photos && Array.isArray(photos)) resetImages(photos);
23+
};
24+
25+
const handlePress = async () => {
26+
if (!validate()) {
27+
return;
28+
}
29+
30+
await patchMutate({
31+
name: title,
32+
description,
33+
image: images,
34+
});
35+
36+
navigate.navigate('Maps/Record', {
37+
location: params.location,
38+
});
39+
};
40+
41+
return (
42+
<>
43+
<View className="gap-4 flex flex-col flex-1 px-4">
44+
<View>
45+
<RecordFormTitle />
46+
</View>
47+
<View>
48+
<RecordFormDescription />
49+
</View>
50+
<View>
51+
<RecordFormImages handlePressAddPhoto={handlePressAddPhoto} />
52+
</View>
53+
</View>
54+
<View className="mt-6">
55+
<Button disabled={!validate()} onPress={handlePress}>
56+
<Font type="body2" color="white">
57+
완료
58+
</Font>
59+
</Button>
60+
</View>
61+
</>
62+
);
63+
}

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

Lines changed: 8 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import { Button, Font } from 'design-system';
2-
import { FlatList, Image, TouchableOpacity, View } from 'react-native';
2+
import { View } from 'react-native';
33
import { useNavigation, useRoute } from '@react-navigation/native';
44
import RecordFormTitle from './RecordFormTitle';
55
import RecordFormDatePicker from './RecordFormDatePickers';
66
import Calendar from '@/assets/Calendar';
7-
import PlusIcon from '@/assets/PlusIcon';
87
import { StackNavigation, StackRouteProps } from '@/types/navigation';
98
import useRecordFormState from '@/hooks/useRecordFormState';
109
import useGallery from '@/hooks/useGallery';
1110
import useRecordMutation from '@/apis/mutations/useRecordMutation';
1211
import RecordFormDescription from './RecordFormDescription';
12+
import RecordFormImages from './RecordFormImages';
1313

1414
export default function RecordPostForm() {
1515
const { description, title, validate, images, resetImages } =
@@ -19,6 +19,11 @@ export default function RecordPostForm() {
1919

2020
const { getPhoto } = useGallery();
2121

22+
const handlePressAddPhoto = async () => {
23+
const photos = await getPhoto(10);
24+
if (photos && Array.isArray(photos)) resetImages(photos);
25+
};
26+
2227
const { postMutate } = useRecordMutation();
2328

2429
const handlePress = async () => {
@@ -64,37 +69,7 @@ export default function RecordPostForm() {
6469
</View>
6570

6671
<View>
67-
<Font type="body2" color="white">
68-
이미지 첨부
69-
</Font>
70-
<View className="flex-row items-center mt-2 ">
71-
<TouchableOpacity
72-
className="bg-SPOT-white/60 rounded-md p-6 aspect-square w-16 justify-center items-center "
73-
onPress={async () => {
74-
const photos = await getPhoto(10);
75-
if (photos && Array.isArray(photos)) resetImages(photos);
76-
}}
77-
>
78-
<PlusIcon />
79-
</TouchableOpacity>
80-
<FlatList
81-
className="ml-2"
82-
horizontal
83-
data={images}
84-
renderItem={({ item }) => {
85-
return (
86-
<Image
87-
source={{ uri: item }}
88-
style={{
89-
width: 64,
90-
height: 64,
91-
borderRadius: 6,
92-
}}
93-
/>
94-
);
95-
}}
96-
/>
97-
</View>
72+
<RecordFormImages handlePressAddPhoto={handlePressAddPhoto} />
9873
</View>
9974
<View>
10075
<RecordFormDescription />

packages/react-native/src/hooks/useRecordFormState.tsx

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { createContext, ReactNode, useContext, useMemo, useState } from 'react';
2+
import { RecordGetResponse } from '@/apis/queries/records/useRecordDetailQuery';
23

34
interface RecordFormContextState {
45
title: string;
@@ -26,12 +27,22 @@ interface RecordFormContextState {
2627
>;
2728
}
2829

30+
interface RecordFormProviderDefulatProps {
31+
children: ReactNode;
32+
defaultProps?: RecordGetResponse;
33+
}
34+
2935
const RecordFormContext = createContext<RecordFormContextState | null>(null);
3036

31-
export function RecordFormProvider({ children }: { children: ReactNode }) {
32-
const [title, setTitle] = useState('');
33-
const [description, setDescription] = useState('');
34-
const [images, setImages] = useState<string[]>([]);
37+
export function RecordFormProvider({
38+
children,
39+
defaultProps,
40+
}: RecordFormProviderDefulatProps) {
41+
const [title, setTitle] = useState(defaultProps?.name || '');
42+
const [description, setDescription] = useState(
43+
defaultProps?.description || '',
44+
);
45+
const [images, setImages] = useState<string[]>(defaultProps?.imageUrls || []);
3546

3647
const [date, setDate] = useState({
3748
start: new Date(),
Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
1-
import { View } from 'react-native';
1+
import { useRoute } from '@react-navigation/native';
2+
import useRecordDetailQuery from '@/apis/queries/records/useRecordDetailQuery';
3+
import Header from '@/components/common/Header';
4+
import withSuspense from '@/components/HOC/withSuspense';
5+
import RecordModifyForm from '@/components/maps/RecordModifyForm';
6+
import { RecordFormProvider } from '@/hooks/useRecordFormState';
7+
import BackGroundGradient from '@/layouts/BackGroundGradient';
8+
import { StackRouteProps } from '@/types/navigation';
29

3-
export default function ModifyLog() {
4-
return <View />;
5-
}
10+
export default withSuspense(function ModifyLog() {
11+
const route = useRoute<StackRouteProps<'Maps/ModifyRecord'>>();
12+
const { recordDetail } = useRecordDetailQuery({
13+
recordId: route.params.recordId,
14+
});
15+
16+
return (
17+
<BackGroundGradient>
18+
<Header title="로그 수정" />
19+
<RecordFormProvider defaultProps={recordDetail}>
20+
<RecordModifyForm />
21+
</RecordFormProvider>
22+
</BackGroundGradient>
23+
);
24+
});

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,17 @@ import useRecordDetailQuery from '@/apis/queries/records/useRecordDetailQuery';
66
import Header from '@/components/common/Header';
77
import BackGroundGradient from '@/layouts/BackGroundGradient';
88
import { StackNavigation, StackRouteProps } from '@/types/navigation';
9+
import withSuspense from '@/components/HOC/withSuspense';
910

1011
interface LogDetailProps {
1112
navigation: StackNavigation<'Maps/RecordDetail'>;
1213
}
1314

1415
const { width: fullWidth } = Dimensions.get('window');
1516

16-
export default function RecordDetail({ navigation }: LogDetailProps) {
17+
export default withSuspense(function RecordDetail({
18+
navigation,
19+
}: LogDetailProps) {
1720
const route = useRoute<StackRouteProps<'Maps/RecordDetail'>>();
1821
const [currentIndex, setCurrentIndex] = useState(0);
1922

@@ -93,4 +96,4 @@ export default function RecordDetail({ navigation }: LogDetailProps) {
9396
</View>
9497
</BackGroundGradient>
9598
);
96-
}
99+
});

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

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -60,28 +60,38 @@ export default function Records({ navigation }: RecordsProps) {
6060
bottom={16}
6161
right={16}
6262
/>
63-
<BottomSheet isShow={Boolean(selectedRecord)}>
64-
<View className="flex justify-evenly items-center mt-2 flex-col gap-4">
65-
<View className="flex">
66-
<Font.Bold type="mainTitle" color="black">
67-
{selectedRecord?.title}
68-
</Font.Bold>
63+
{selectedRecord && (
64+
<BottomSheet isShow={Boolean(selectedRecord)}>
65+
<View className="flex justify-evenly items-center mt-2 flex-col gap-4">
66+
<View className="flex">
67+
<Font.Bold type="mainTitle" color="black">
68+
{selectedRecord.title}
69+
</Font.Bold>
70+
</View>
71+
<View className="flex items-center w-full ">
72+
<TouchableOpacity
73+
className="py-2"
74+
onPress={() =>
75+
navigation.navigate('Maps/ModifyRecord', {
76+
location: route.params.location,
77+
recordId: selectedRecord.id,
78+
})
79+
}
80+
>
81+
<Font.Light type="title1" color="black">
82+
수정
83+
</Font.Light>
84+
</TouchableOpacity>
85+
<View className="w-[90%] h-[0.5px] bg-[#333333]" />
86+
<TouchableOpacity className="py-2">
87+
<Font.Light type="title1" color="black">
88+
삭제
89+
</Font.Light>
90+
</TouchableOpacity>
91+
</View>
6992
</View>
70-
<View className="flex items-center w-full ">
71-
<TouchableOpacity className="py-2">
72-
<Font.Light type="title1" color="black">
73-
수정
74-
</Font.Light>
75-
</TouchableOpacity>
76-
<View className="w-[90%] h-[0.5px] bg-[#333333]" />
77-
<TouchableOpacity className="py-2">
78-
<Font.Light type="title1" color="black">
79-
삭제
80-
</Font.Light>
81-
</TouchableOpacity>
82-
</View>
83-
</View>
84-
</BottomSheet>
93+
</BottomSheet>
94+
)}
8595
</View>
8696
);
8797
}

packages/react-native/src/types/navigation.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ export type StackParamList = {
2525
'Maps/PostRecord': {
2626
location: KoreaLocationName;
2727
};
28-
'Maps/ModifyRecord': undefined;
28+
'Maps/ModifyRecord': {
29+
recordId: number;
30+
location: KoreaLocationName;
31+
};
2932
'Maps/RecordDetail': {
3033
recordId: number;
3134
location: KoreaLocationName;

0 commit comments

Comments
 (0)