Skip to content

Commit

Permalink
Feat: 팝업상세뷰 리뷰 API 후 즉시반영
Browse files Browse the repository at this point in the history
  • Loading branch information
puretension committed Jun 21, 2024
1 parent 1ca2f8a commit 7e50d1a
Show file tree
Hide file tree
Showing 10 changed files with 147 additions and 45 deletions.
2 changes: 1 addition & 1 deletion ios/PoppinProject/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>7</string>
<string>9</string>
<key>FirebaseAppDelegateProxyEnabled</key>
<true/>
<key>ITSAppUsesNonExemptEncryption</key>
Expand Down
1 change: 1 addition & 0 deletions src/apis/popup/detailPopUp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const getDetailPopUp = async (
});

if (response.data.success) {
console.log('DetailPopUpDataNonPublic:', response.data);
return response.data;
} else {
return {
Expand Down
39 changes: 29 additions & 10 deletions src/hooks/detailPopUp/useGetDetailPopUp.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
// src/hooks/detailPopUp/useGetDetailPopUp.ts
import {useState, useEffect} from 'react';
import {DetailPopUpDataNonPublic} from '../../types/DetailPopUpDataNonPublic.ts';
import getDetailPopUp from '../../apis/popup/detailPopUp.ts';
import getDetailPopUpPublic from '../../apis/public/detailPopUpPublic.ts';
import {DetailPopUpDataNonPublic} from '../../types/DetailPopUpDataNonPublic';
import getDetailPopUp from '../../apis/popup/detailPopUp';
import getDetailPopUpPublic from '../../apis/public/detailPopUpPublic';
import {useDispatch} from 'react-redux';
import {
setPopupDetailData,
setPopupDetailLoading,
setPopupDetailError,
} from '../../redux/slices/popupDetailSlice.ts';

interface DetailPopUpState {
loading: boolean;
Expand All @@ -12,7 +19,7 @@ interface DetailPopUpState {
function useGetDetailPopUp(
popUpId: number,
isPublic: boolean,
fetchTrigger: boolean, // Add fetchTrigger as a parameter
fetchTrigger: boolean,
): DetailPopUpState {
const [getDetailPopUpState, setGetDetailPopUpState] =
useState<DetailPopUpState>({
Expand All @@ -21,43 +28,55 @@ function useGetDetailPopUp(
error: null,
});

const dispatch = useDispatch();

useEffect(() => {
// 팝업 상세 정보를 가져오는 비동기 함수
const fetchDetailPopUp = async () => {
setGetDetailPopUpState({
loading: true,
data: null,
error: null,
});
dispatch(setPopupDetailLoading(true));

try {
const response = isPublic
? await getDetailPopUpPublic(popUpId)
: await getDetailPopUp(popUpId);
if (response.success) {

if (response.success && response.data) {
setGetDetailPopUpState({
loading: false,
data: response.data,
error: null,
});
console.log(response.data);
dispatch(setPopupDetailData(response.data));
} else {
const errorMessage =
response.error?.message || 'An unknown error occurred';
setGetDetailPopUpState({
loading: false,
data: null,
error: response.error?.message || 'An unknown error occurred',
error: errorMessage,
});
dispatch(setPopupDetailError(errorMessage));
}
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : 'An error occurred';
setGetDetailPopUpState({
loading: false,
data: null,
error: error instanceof Error ? error.message : 'An error occurred',
error: errorMessage,
});
dispatch(setPopupDetailError(errorMessage));
} finally {
dispatch(setPopupDetailLoading(false));
}
};

fetchDetailPopUp();
}, [popUpId, isPublic, fetchTrigger]); // Add fetchTrigger as a dependency
}, [popUpId, isPublic, fetchTrigger, dispatch]);

return getDetailPopUpState;
}
Expand Down
9 changes: 8 additions & 1 deletion src/hooks/review/useCreateReview.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
// src/hooks/review/useCreateReview.tsx
import {useState} from 'react';
import createPopUpReview from '../../apis/popup/createReview.tsx';
import {ImageType} from '../../types/ImageType.ts';
import {useDispatch} from 'react-redux';
import {setReviewSubmitted} from '../../redux/slices/reviewSubmittedSlice.ts';
import getDetailPopUp from '../../apis/popup/detailPopUp';

interface CreateReviewState {
loading: boolean;
Expand All @@ -17,6 +21,8 @@ const useCreateReview = () => {
},
);

const dispatch = useDispatch();

const createReview = async (
popupId: number,
text: string,
Expand Down Expand Up @@ -44,7 +50,7 @@ const useCreateReview = () => {
isVisited,
);
if (response.success) {
console.log(response);
dispatch(setReviewSubmitted(true));
setCreateReviewState({loading: false, error: null, success: true});
return response;
} else {
Expand All @@ -66,6 +72,7 @@ const useCreateReview = () => {
return {success: false, error: {code: 'unknown', message: err.message}};
}
};

return {...createReviewState, createReview};
};

Expand Down
73 changes: 43 additions & 30 deletions src/pages/detail/PopUpDetailScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,46 +12,52 @@ import {
Text,
View,
} from 'react-native';
import useGetDetailPopUp from '../../hooks/detailPopUp/useGetDetailPopUp.tsx';
import {useDispatch, useSelector} from 'react-redux';
import {
toggleInterest,
setInterest,
} from '../../redux/slices/interestedPopUpSlice'; // 추가
import useGetDetailPopUp from '../../hooks/detailPopUp/useGetDetailPopUp';
import ShareSvg from '../../assets/detail/share.svg';
import StarOffSvg from '../../assets/detail/starOff.svg';
import StarOnSvg from '../../assets/detail/starOn.svg';
import MapSvg from '../../assets/detail/map.svg';
import Text20B from '../../styles/texts/title/Text20B.ts';
import Text14R from '../../styles/texts/body_medium/Text14R.ts';
import globalColors from '../../styles/color/globalColors.ts';
import Text20B from '../../styles/texts/title/Text20B';
import Text14R from '../../styles/texts/body_medium/Text14R';
import globalColors from '../../styles/color/globalColors';
import DetailDividerLine from '../../assets/detail/detailDivider.svg';
import Text14B from '../../styles/texts/body_medium/Text14B.ts';
import Text14M from '../../styles/texts/body_medium/Text14M.ts';
import RealTimeVisitorsViewButton from '../../components/atoms/button/CommonButton.tsx';
import DividerLine from '../../components/DividerLine.tsx';
import useAddInterestPopUp from '../../hooks/detailPopUp/useAddInterestPopUp.tsx';
import useDeleteInterestPopUp from '../../hooks/detailPopUp/useDeleteInterestPopUp.tsx';
import Text14B from '../../styles/texts/body_medium/Text14B';
import Text14M from '../../styles/texts/body_medium/Text14M';
import RealTimeVisitorsViewButton from '../../components/atoms/button/CommonButton';
import DividerLine from '../../components/DividerLine';
import useAddInterestPopUp from '../../hooks/detailPopUp/useAddInterestPopUp';
import useDeleteInterestPopUp from '../../hooks/detailPopUp/useDeleteInterestPopUp';
import ReviewProfileSvg from '../../assets/detail/reviewProfile.svg';
import VerifiedReviewSvg from '../../assets/detail/verifiedReview.svg';
import WriteReviewSvg from '../../assets/detail/writeReview.svg';
import SvgWithNameBoxLabel from '../../components/SvgWithNameBoxLabel.tsx';
import UnderlinedTextButton from '../../components/UnderlineTextButton.tsx';
import SvgWithNameBoxLabel from '../../components/SvgWithNameBoxLabel';
import UnderlinedTextButton from '../../components/UnderlineTextButton';
import LikeReviewSvg from '../../assets/detail/likesReview.svg';
import Text16M from '../../styles/texts/body_medium_large/Text16M.ts';
import OrderSvg from '../../assets/icons/order.svg';
import ReasonItem from '../../components/ReasonItem.tsx';
import CongestionSection from '../../components/organisms/section/CongestionSection.tsx';
import {VisitorDataDetail} from '../../types/DetailPopUpDataNonPublic.ts';
import Text16M from '../../styles/texts/body_medium_large/Text16M';
import OrderSvg from '../../assets/icons/order';
import ReasonItem from '../../components/ReasonItem';
import CongestionSection from '../../components/organisms/section/CongestionSection';
import {VisitorDataDetail} from '../../types/DetailPopUpDataNonPublic';
import WebSvg from '../../assets/detail/web.svg';
import InstagramTestSvg from '../../assets/detail/instagramTest.svg';
import ToastComponent from '../../components/atoms/toast/ToastComponent.tsx';
import VisitButton from '../../components/atoms/button/VisitButton.tsx';
import ToastComponent from '../../components/atoms/toast/ToastComponent';
import VisitButton from '../../components/atoms/button/VisitButton';
import VisitModalSvg from '../../assets/detail/visitModal.svg';
import CustomModal from '../../components/atoms/modal/CustomModal.tsx';
import CustomModal from '../../components/atoms/modal/CustomModal';
import Geolocation from 'react-native-geolocation-service';
import useAddRecommendReview from '../../hooks/detailPopUp/useAddRecommendReview.tsx';
import useAddRecommendReview from '../../hooks/detailPopUp/useAddRecommendReview';
import {useNavigation} from '@react-navigation/native';
import useIsLoggedIn from '../../hooks/auth/useIsLoggedIn.tsx';
import useAddVisitor from '../../hooks/detailPopUp/useAddVisitor.ts';
import useIsLoggedIn from '../../hooks/auth/useIsLoggedIn';
import useAddVisitor from '../../hooks/detailPopUp/useAddVisitor';
import {NativeStackNavigationProp} from '@react-navigation/native-stack';
import {AppNavigatorParamList} from '../../types/AppNavigatorParamList.ts';
import PopUpDetailOptions from '../../navigators/options/PopUpDetailOptions.tsx';
import {AppNavigatorParamList} from '../../types/AppNavigatorParamList';
import PopUpDetailOptions from '../../navigators/options/PopUpDetailOptions';
import {RootState} from '../../redux/stores/reducer';

async function requestPermissions() {
if (Platform.OS === 'ios') {
Expand Down Expand Up @@ -114,6 +120,10 @@ const PopUpDetailScreen = ({route}) => {
const navigation = useNavigation<PopUpDetailScreenNavigationProp>();
const [fetchTrigger, setFetchTrigger] = useState(false);
const {id, name} = route.params;
const dispatch = useDispatch();
const isInterested = useSelector(
(state: RootState) => state.interestedPopups[id],
); // 추가

const {
data: detailPopUpData,
Expand All @@ -130,13 +140,18 @@ const PopUpDetailScreen = ({route}) => {
name: detailPopUpData.name,
}),
);
dispatch(
setInterest({
popupId: detailPopUpData.id,
isInterested: detailPopUpData.isInterested,
}),
); // 추가
}
}, [navigation, detailPopUpData]);
}, [navigation, detailPopUpData, dispatch]);

const firstImageUrl =
detailPopUpData?.images?.[0] ??
'https://v1-popup-poster.s3.ap-northeast-2.amazonaws.com/4/1.jpg';
const [isInterested, setIsInterested] = useState(false);
const [isShowToast, setIsShowToast] = useState(false);
const [toastMessage, setToastMessage] = useState('');
const {addRecommendCount} = useAddRecommendReview();
Expand All @@ -154,7 +169,6 @@ const PopUpDetailScreen = ({route}) => {

useEffect(() => {
if (detailPopUpData) {
setIsInterested(detailPopUpData.isInterested);
setToastMessage('이 팝업이 근처에 있어요!!');
setIsShowToast(true);
}
Expand Down Expand Up @@ -220,7 +234,7 @@ const PopUpDetailScreen = ({route}) => {
setToastMessage('관심팝업에 저장되었어요!');
}
setIsShowToast(true);
setIsInterested(!isInterested);
dispatch(toggleInterest(id)); // 추가
};

const handleOpenLink = url => {
Expand Down Expand Up @@ -250,7 +264,6 @@ const PopUpDetailScreen = ({route}) => {
}
setIsShowToast(true);
};

if (loading) {
return (
<View style={styles.loadingContainer}>
Expand Down
3 changes: 2 additions & 1 deletion src/pages/detail/PopUpEditRequestScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ function PopUpEditRequestScreen() {
if (response.success) {
navigation.goBack();
} else if (response.error) {
console.error('Review submission error:', response.error.message);
navigation.goBack();
// console.error('Review submission error:', response.error.message);
}
setCompleteModalVisible(true);
};
Expand Down
6 changes: 5 additions & 1 deletion src/pages/myPage/ReviewWriteScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import Text12R from '../../styles/texts/label/Text12R';
import {AppNavigatorParamList} from '../../types/AppNavigatorParamList.ts';
import useCreateReview from '../../hooks/review/useCreateReview.tsx';
import {useImageSelector} from '../../hooks/useImageSelector.tsx';
import getDetailPopUp from '../../apis/popup/detailPopUp.ts';

type ReviewWriteScreenRouteProp = RouteProp<
AppNavigatorParamList,
Expand Down Expand Up @@ -71,7 +72,10 @@ function ReviewWriteScreen() {
isVisited,
);
if (response.success) {
navigation.goBack();
const resp = await getDetailPopUp(popupId);
if (resp.success) {
navigation.goBack();
}
} else if (response.error) {
console.error('Review submission error:', response.error.message);
}
Expand Down
39 changes: 39 additions & 0 deletions src/redux/slices/popupDetailSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// src/slices/popupDetailSlice.ts
import {createSlice, PayloadAction} from '@reduxjs/toolkit';
import {DetailPopUpDataNonPublic} from '../../types/DetailPopUpDataNonPublic';

interface PopupDetailState {
data: DetailPopUpDataNonPublic | null;
loading: boolean;
error: string | null;
}

const initialState: PopupDetailState = {
data: null,
loading: false,
error: null,
};

const popupDetailSlice = createSlice({
name: 'popupDetail',
initialState,
reducers: {
setPopupDetailData(
state,
action: PayloadAction<DetailPopUpDataNonPublic | null>,
) {
state.data = action.payload;
},
setPopupDetailLoading(state, action: PayloadAction<boolean>) {
state.loading = action.payload;
},
setPopupDetailError(state, action: PayloadAction<string | null>) {
state.error = action.payload;
},
},
});

export const {setPopupDetailData, setPopupDetailLoading, setPopupDetailError} =
popupDetailSlice.actions;

export default popupDetailSlice;
13 changes: 13 additions & 0 deletions src/redux/slices/reviewSubmittedSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// src/redux/slices/reviewSubmittedSlice.ts
import {createSlice} from '@reduxjs/toolkit';

const reviewSubmittedSlice = createSlice({
name: 'reviewSubmitted',
initialState: false,
reducers: {
setReviewSubmitted: (state, action) => action.payload,
},
});

export const {setReviewSubmitted} = reviewSubmittedSlice.actions;
export default reviewSubmittedSlice;
7 changes: 6 additions & 1 deletion src/redux/stores/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@ import userSlice from '../slices/user.ts';
import loadingSlice from '../slices/loading.ts';
import bottomSheetSlice from '../slices/bottomSheetSlice.ts';
import preferenceSlice from '../slices/preferenceSlice.ts';

import interestedPopupsSlice from '../slices/interestedPopUpSlice.ts';
import popupDetailSlice from '../slices/popupDetailSlice.ts';
import reviewSubmittedSlice from '../slices/reviewSubmittedSlice.ts'; // 추가
// 모든 상태를 결합
const rootReducer = combineReducers({
user: userSlice.reducer,
loading: loadingSlice.reducer,
bottomSheet: bottomSheetSlice.reducer,
preference: preferenceSlice.reducer,
interestedPopups: interestedPopupsSlice.reducer, // 추가
popupDetail: popupDetailSlice.reducer, // 추가
reviewSubmitted: reviewSubmittedSlice.reducer,
});

export default rootReducer;
Expand Down

0 comments on commit 7e50d1a

Please sign in to comment.