From 6401af12735df927e8c98594b6a59f1d1b008815 Mon Sep 17 00:00:00 2001 From: Dindb-dong Date: Sat, 9 Nov 2024 03:27:05 +0900 Subject: [PATCH] feat/148/fix a lot errors, Navigating, UI, etc... --- App.tsx | 98 +++---- package-lock.json | 9 +- package.json | 2 +- src/assets/common/Logo.svg | 4 +- src/common/Context.tsx | 5 +- src/common/SignUpCompleteModal.tsx | 17 +- src/components/Auth/BasicForm.tsx | 183 ++++++++----- src/components/Auth/Login.tsx | 8 +- src/components/Auth/Reformer/CareerModal.tsx | 2 +- .../Auth/Reformer/ReformFormCareer.tsx | 2 +- .../Auth/Reformer/ReformFormSubmit.tsx | 18 +- src/components/Auth/Reformer/Reformer.tsx | 16 +- .../Auth/Reformer/ReformerMyPage.tsx | 253 ++++++++++++------ src/components/Auth/SignIn.tsx | 18 +- src/components/Auth/Upcyer/Upcyer.tsx | 86 +++--- src/components/Auth/Upcyer/UpcyerMyPage.tsx | 71 ++--- .../Home/Market/ServiceRegistration.tsx | 3 +- .../Home/Market/WriteDetailPage.tsx | 5 +- .../Home/Market/WriteReviewPage.tsx | 4 +- src/components/Home/Order/CompletedOrder.tsx | 39 +-- src/components/Home/Order/OrderManagement.tsx | 41 ++- src/components/Home/Order/OrderPage.tsx | 13 +- src/pages/Home.tsx | 36 +-- src/pages/MyPage.tsx | 236 +++++++++++----- yarn.lock | 13 +- 25 files changed, 700 insertions(+), 482 deletions(-) diff --git a/App.tsx b/App.tsx index 578a109..1d04d9f 100644 --- a/App.tsx +++ b/App.tsx @@ -3,7 +3,6 @@ import { View, TouchableOpacity, Text } from 'react-native'; import { NavigationContainer, DefaultTheme, - getFocusedRouteNameFromRoute, } from '@react-navigation/native'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; import { @@ -16,24 +15,23 @@ import MyPageScreen from './src/pages/MyPage'; import OrderManagement from './src/components/Home/Order/OrderManagement'; import useLoginGuard from './src/hooks/useLoginGuard'; - import HomeIcon from './src/assets/navbar/Home.svg'; import MyPageIcon from './src/assets/navbar/MyPage.svg'; import OrderManagementIcon from './src/assets/navbar/OrderManagement.svg'; import SignIn from './src/components/Auth/SignIn'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; import { BottomBarProvider, useBottomBar } from './contexts/BottomBarContext'; -import { LoginContext, LoginProvider, UserProvider } from './src/common/Context'; +import { LoginProvider, UserProvider } from './src/common/Context'; import Reformer from './src/components/Auth/Reformer/Reformer'; import SplashScreen from './src/common/SplashScreen'; export type StackProps = { - Home: undefined; + Main: undefined; Signin: undefined; ReformProfile: undefined; }; -const Stack = createNativeStackNavigator(); +const AppStack = createNativeStackNavigator(); // 최상위 스택. SignInStack에는 바텀바 안 뜸. const GlobalTheme = { ...DefaultTheme, @@ -60,14 +58,13 @@ function App(): React.JSX.Element { {!isSplashFinished ? ( ) : ( - ({ - headerShown: false, - })}> - - - - + + + + + )} @@ -79,22 +76,21 @@ function App(): React.JSX.Element { export type TabProps = { 홈: undefined; + 주문관리: undefined; 마이페이지: undefined; }; const CustomTab = ({ state, descriptors, navigation }: BottomTabBarProps) => { const loginGuard = useLoginGuard(); - const { options } = descriptors; - const { isVisible } = useBottomBar(); // 바텀바 보임/숨김 상태를 가져옵니다. + const { isVisible } = useBottomBar(); // 바텀바 보임/숨김 상태를 가져옴. if (!isVisible) { - return null; // isVisible이 false일 경우 탭바를 렌더링하지 않습니다. + return null; // isVisible이 false일 경우 탭바를 렌더링하지 않음. } return ( { paddingHorizontal: 10, }}> {state.routes.map((route, index) => { - const isFocused = state.index == index; - const onPress = () => { // 하단 탭바 추가하면 여기 수정해야합니다!!!! - if (route.name == '홈') { - if (isFocused) - navigation.reset({ - routes: [{ name: route.name, params: { id: undefined } }], - }); - else navigation.navigate(route.name, { id: undefined }); - } else if (route.name == '주문관리') { - if (isFocused) - navigation.reset({ - routes: [{ name: route.name, params: { id: undefined } }], - }); - else navigation.navigate(route.name, { id: undefined }); - } else if (route.name == '마이페이지') { - if (isFocused) - navigation.reset({ - routes: [{ name: route.name, params: { id: undefined } }], - }); - else navigation.navigate(route.name, { id: undefined }); + const isFocused = state.index === index; // 한 번 더 눌렀을 때 + const onPress = () => { + if (isFocused) { + navigation.reset({ + routes: [{ name: route.name }], + }); + } else { + navigation.navigate(route.name); } }; + return ( - { - { - 0: , - 1: , - 2: , - - }[index] - } + {{ + 홈: , + 주문관리: , + 마이페이지: , + }[route.name]} { }; const Tab = createBottomTabNavigator(); -const HomeTab = (): JSX.Element => { + +// 하단 탭 네비게이터 정의 +const MainTabNavigator = () => { return ( } - id="MainHome" initialRouteName="홈" - screenOptions={() => ({ - headerShown: false, - })}> - - - + screenOptions={{ headerShown: false }} + > + + + ); }; -export default App; +export default App; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 6215632..d7ed643 100644 --- a/package-lock.json +++ b/package-lock.json @@ -63,7 +63,7 @@ "devDependencies": { "@babel/core": "^7.20.0", "@babel/preset-env": "^7.20.0", - "@babel/runtime": "^7.20.0", + "@babel/runtime": "^7.26.0", "@react-native-community/eslint-config": "^3.2.0", "@react-native/babel-preset": "0.73.19", "@react-native/eslint-config": "0.73.2", @@ -2038,9 +2038,10 @@ "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" }, "node_modules/@babel/runtime": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.6.tgz", - "integrity": "sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", + "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", + "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" }, diff --git a/package.json b/package.json index 039c865..0ff6c39 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "devDependencies": { "@babel/core": "^7.20.0", "@babel/preset-env": "^7.20.0", - "@babel/runtime": "^7.20.0", + "@babel/runtime": "^7.26.0", "@react-native-community/eslint-config": "^3.2.0", "@react-native/babel-preset": "0.73.19", "@react-native/eslint-config": "0.73.2", diff --git a/src/assets/common/Logo.svg b/src/assets/common/Logo.svg index 1fcc263..bea7d1e 100644 --- a/src/assets/common/Logo.svg +++ b/src/assets/common/Logo.svg @@ -1,3 +1,3 @@ - - + + \ No newline at end of file diff --git a/src/common/Context.tsx b/src/common/Context.tsx index 5696f4e..42cccde 100644 --- a/src/common/Context.tsx +++ b/src/common/Context.tsx @@ -85,9 +85,8 @@ export const LoginProvider = ({ children }: { children: ReactNode }) => { const { setUser, setRole } = useUser(); const logout = () => { - setUser(null); - setRole(''); - setIsLogin(false); + setRole('customer'); + setIsLogin(false); }; const setLogin = (value: boolean) => { diff --git a/src/common/SignUpCompleteModal.tsx b/src/common/SignUpCompleteModal.tsx index ef31f00..ac2070d 100644 --- a/src/common/SignUpCompleteModal.tsx +++ b/src/common/SignUpCompleteModal.tsx @@ -1,6 +1,6 @@ import { FC, useEffect, useState } from 'react'; import { Modal, View, Text, TouchableOpacity, StyleSheet } from 'react-native'; -import { useNavigation, useRoute } from '@react-navigation/native'; +import { CommonActions, useNavigation, useRoute } from '@react-navigation/native'; import Check from '../assets/common/CheckIcon.svg' import { StackNavigationProp } from '@react-navigation/stack'; import { SignInParams } from '../components/Auth/SignIn'; @@ -13,16 +13,23 @@ const SignupCompleteModal = ({ visible, onClose }: SignupModalProps) => { const handleGoToReformer = async () => { onClose(); // 모달을 닫고 await new Promise(resolve => setTimeout(resolve, 100)); // 딜레이 추가 + console.log('BasicForm에서 Reformer로 이동합니다.'); navigation.navigate('Reformer'); // 네비게이션 수행 }; const handleSkip = async () => { onClose(); // 모달을 닫고 await new Promise(resolve => setTimeout(resolve, 100)); // 딜레이 추가 - navigation.getParent()?.reset({ - index: 0, // 첫 번째 화면부터 시작 - routes: [{ name: 'Home' }], // 새로운 스택에 홈 화면만 남김 - }); + navigation.dispatch( + CommonActions.navigate({ + name: "Main", + params: { + screen: "홈", // MainTabNavigator의 홈 화면으로 이동 + }, + }) + ); + console.log('홈으로 이동합니다.'); + }; return ( diff --git a/src/components/Auth/BasicForm.tsx b/src/components/Auth/BasicForm.tsx index bfeabdd..60dc4f4 100644 --- a/src/components/Auth/BasicForm.tsx +++ b/src/components/Auth/BasicForm.tsx @@ -6,7 +6,7 @@ import { TextInput, Alert, } from 'react-native'; -import { Body16B, Body16M, Caption11M } from '../../styles/GlobalText'; +import { Body16B, Body16M, Caption11M, Caption14M } from '../../styles/GlobalText'; import styled from 'styled-components/native'; import { BLACK2, PURPLE } from '../../styles/GlobalColor'; import CheckIcon from '../../assets/common/CheckIcon.svg'; @@ -40,6 +40,7 @@ interface Agreement { } export interface BasicFormProps2 { + full_name: string; mail: string; domain: string | undefined; password: string; @@ -58,6 +59,7 @@ const SectionView = styled.View` position: relative; margin-top: 8px; margin-bottom: 8px; + padding: 0px 0px 0px 6px; `; const TermsView = styled(SectionView)` @@ -65,28 +67,6 @@ const TermsView = styled(SectionView)` align-items: center; `; -const MailView = styled.View` - width: 100%; - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; -`; - -const SelectView = styled.View` - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; - height: 44px; - width: 44%; - border-width: 2px; - border-color: #929292; - border-radius: 5px; - padding-left: 16px; - padding-right: 10px; -`; - // 페이지 들어올 때, is_reformer인지 is_consumer인지 받아오는거 해야함. // 그 이후, 그에 따라서 '다음' 눌렀을 때에 이동하는 페이지가 달라져야... @@ -104,6 +84,7 @@ export default function BasicForm({ navigation, route }: FormProps) { const is_reformer = route.params?.is_reformer ?? false; const { width, height } = Dimensions.get('window'); const [form, setForm] = useState({ + full_name: route.params?.full_name || '', mail: route.params?.mail || '', domain: route.params?.domain || undefined, password: route.params?.password || '', @@ -147,19 +128,20 @@ export default function BasicForm({ navigation, route }: FormProps) { }; const passwordValidation = async () => { - const form_ = { ...form } - if (form_.agreement.a === false || form_.agreement.b === false || form_.agreement.c === false || - form_.domain === undefined || form_.mail === '') { + if (form.agreement.a === false || form.agreement.b === false || form.agreement.c === false || + form.domain === undefined || form.mail === '' || form.full_name === '') { Alert.alert('필수 사항들을 모두 입력해주세요.') - } else if (!form_.domain.includes('.')) { + } else if (!form.domain.includes('.')) { Alert.alert('올바른 이메일 형식이 아닙니다.') } else { // 누락된거 없을 때 - if (passwordRegExp.exec(form_.password)) { + if (passwordRegExp.exec(form.password)) { if (is_reformer === true) { // 리폼러의 경우 await handleSubmit(); // 일단 회원가입 하고, handleLogin(); // 토큰 발급 로직 } else { // 업씨러의 경우 - navigation.navigate('Upcyer', { form_ }) + await handleSubmit2(); + handleLogin(); + navigation.navigate('Upcyer', { form }) } } else { Alert.alert('비밀번호가 올바르지 않습니다.'); @@ -171,8 +153,35 @@ export default function BasicForm({ navigation, route }: FormProps) { } }; + const handleSubmit2 = async () => { // 수정된 백 API 따라서 수정 필요 + const params = { + full_name: form.full_name, + email: form.mail + '@' + form.domain, + password: form.password, + agreement_terms: form.agreement.d, + }; + try { + const response = await request.post(`/api/user/signup`, params); + if (response?.status === 201) { + console.log(params); + const accessToken = await response.data.access; + const refreshToken = await response.data.refresh; + console.log({ accessToken }, '||', { refreshToken }); + } else if (response?.status === 500) { + console.log(response); + Alert.alert('이미 가입된 이메일입니다.'); + } else { + console.error('Error Status:', response?.status); + Alert.alert('가입에 실패했습니다.'); + } + } catch (err) { + console.log(err); + } + }; + const handleSubmit = async () => { // 수정된 백 API 따라서 수정 필요 const params = { + full_name: form.full_name, email: form.mail + '@' + form.domain, password: form.password, agreement_terms: form.agreement.d, @@ -205,7 +214,17 @@ export default function BasicForm({ navigation, route }: FormProps) { setModalVisible(false); // 모달 닫기 }; - + const setAllAgreementsTrue = () => { + setForm(prev => ({ + ...prev, + agreement: { + a: true, + b: true, + c: true, + d: true, + }, + })); + }; return ( @@ -222,26 +241,33 @@ export default function BasicForm({ navigation, route }: FormProps) { - - 이메일 - - + setForm(prev => { + return { ...prev, full_name: text }; + }) + } + placeholder="입력해 주세요" + style={{ height: 44, marginTop: 8 }} + /> + + + setForm(prev => { @@ -249,12 +275,16 @@ export default function BasicForm({ navigation, route }: FormProps) { }) } placeholder="입력해 주세요" - style={{ height: 44, marginTop: 8, width: '44%' }} + style={{ height: 44, marginTop: 8 }} /> - @ + + + @ + + setForm(prev => { @@ -262,9 +292,10 @@ export default function BasicForm({ navigation, route }: FormProps) { }) } items={['gmail.com', 'naver.com', 'kakao.com']} + style={{ flex: 1, marginTop: 34 }} /> - + - 만 19세 이상입니다. (필수) @@ -363,35 +393,44 @@ export default function BasicForm({ navigation, route }: FormProps) { } /> - { - console.log(form); - passwordValidation(); - }} - // onPress={() => handleNext()} // 이건 임시. - style={{ - width: '75%', - alignSelf: 'center', - marginTop: 'auto', - marginBottom: 30, - }} - /> + + 전체 동의합니다. + + + { + passwordValidation(); + }} + style={{ + width: '90%', + alignSelf: 'center', + marginTop: 'auto', + marginBottom: 40, + }} + /> diff --git a/src/components/Auth/Login.tsx b/src/components/Auth/Login.tsx index a82388f..2ab89a6 100644 --- a/src/components/Auth/Login.tsx +++ b/src/components/Auth/Login.tsx @@ -219,11 +219,11 @@ export default function Login({ navigation, route }: LoginProps) { navigation.navigate('Signup')}> 회원가입 - | - 비밀번호 찾기 + {/* | + 비밀번호 찾기 */} - - + */} ); diff --git a/src/components/Auth/Reformer/CareerModal.tsx b/src/components/Auth/Reformer/CareerModal.tsx index 125669d..30db241 100644 --- a/src/components/Auth/Reformer/CareerModal.tsx +++ b/src/components/Auth/Reformer/CareerModal.tsx @@ -384,7 +384,7 @@ export default function CareerModal({ }} max={1} /> - */} + */} {/* 파일 업로드 로직은 백엔드 구현되고 나면 다시 적용 */} {careerIndex >= 0 && ( diff --git a/src/components/Auth/Reformer/ReformFormSubmit.tsx b/src/components/Auth/Reformer/ReformFormSubmit.tsx index 6c6c4fa..74415dc 100644 --- a/src/components/Auth/Reformer/ReformFormSubmit.tsx +++ b/src/components/Auth/Reformer/ReformFormSubmit.tsx @@ -1,11 +1,15 @@ import { Dimensions, SafeAreaView, Text, View } from 'react-native'; import { Title20B } from '../../../styles/GlobalText'; import BottomButton from '../../../common/BottomButton'; -import { SignupProp } from '../Signup'; +import SignupProp from '../Signup'; import Hand from '../../../assets/common/hand.svg' +import { CommonActions, useNavigation } from '@react-navigation/native'; +import { StackNavigationProp } from '@react-navigation/stack'; +import { SignInParams } from '../SignIn'; -export default function ReformFormSubmit({ navigation, route }: SignupProp) { +export default function ReformFormSubmit() { + const navigation = useNavigation>(); const { height } = Dimensions.get('screen'); return ( @@ -23,7 +27,15 @@ export default function ReformFormSubmit({ navigation, route }: SignupProp) { { - navigation.getParent()?.navigate('Home'); + navigation.dispatch( + CommonActions.navigate({ + name: "Main", + params: { + screen: "홈", // MainTabNavigator의 홈 화면으로 이동 + }, + }) + ); + console.log('홈으로 이동합니다.'); }} pressed={false} style={{ diff --git a/src/components/Auth/Reformer/Reformer.tsx b/src/components/Auth/Reformer/Reformer.tsx index 3366e54..c872b06 100644 --- a/src/components/Auth/Reformer/Reformer.tsx +++ b/src/components/Auth/Reformer/Reformer.tsx @@ -6,6 +6,17 @@ import ReformFormProfile from './ReformFormProfile'; import BackArrow from '../../../assets/common/Arrow.svg'; // Import the back arrow icon import { PhotoType } from '../../../hooks/useImagePicker'; import { RegionType, EducType, CareerType, AwardsType, CertifiType, FreeType, FieldType } from '../../../types/UserTypes'; +import { useNavigation } from '@react-navigation/native'; + +export interface ReformProps { + form: ReformProfileType; + setForm: Dispatch>; +} + +export interface ModalProps extends ReformProps { + open: boolean; + setOpen: Dispatch>; +} export type ReformProfileType = { picture?: undefined | PhotoType; @@ -21,7 +32,8 @@ export type ReformProfileType = { field: FieldType; }; -export default function Reformer({ navigation }) { +export default function Reformer() { + const navigation = useNavigation(); const defaultProfile: ReformProfileType = { picture: undefined, nickname: '', @@ -43,7 +55,7 @@ export default function Reformer({ navigation }) { {/* Custom Header */} - navigation.goBack()} style={styles.backButton}> + { navigation.getParent()?.navigate('홈'); }} style={styles.backButton}> 프로필 등록 diff --git a/src/components/Auth/Reformer/ReformerMyPage.tsx b/src/components/Auth/Reformer/ReformerMyPage.tsx index 6d5065c..385e82b 100644 --- a/src/components/Auth/Reformer/ReformerMyPage.tsx +++ b/src/components/Auth/Reformer/ReformerMyPage.tsx @@ -1,4 +1,4 @@ -import React, { useRef, useState } from 'react'; +import React, { useCallback, useContext, useEffect, useRef, useState } from 'react'; import { SafeAreaView, ScrollView, @@ -8,6 +8,7 @@ import { Image, ImageBackground, StyleSheet, + Dimensions, } from 'react-native'; import { Tabs, MaterialTabBar } from 'react-native-collapsible-tab-view'; import { BLACK, PURPLE } from '../../../styles/GlobalColor.tsx'; @@ -16,105 +17,176 @@ import Arrow from '../../../assets/common/Arrow.svg'; import ServicePage from '../../../components/Home/Market/ServicePage'; import InfoPage from '../../../components/Home/Market/InfoPage.tsx'; import TempStorage from '../../../components/Home/Market/TempStorage.tsx'; -import ServiceRegistration from '../../../components/Home/Market/ServiceRegistration.tsx'; import FixMyPage from '../../../pages/FixMyPage.tsx'; import ScrollTopButton from '../../../common/ScrollTopButton.tsx'; -import LoginContext from '../../../common/Context'; +import { LoginContext } from '../../../common/Context'; import { StackScreenProps, createStackNavigator, } from '@react-navigation/stack'; import styled from 'styled-components/native'; import DetailScreenHeader from '../../../components/Home/components/DetailScreenHeader.tsx'; +import { HomeStackParams } from '../../../pages/Home.tsx'; +import { PhotoType } from '../../../hooks/useImagePicker.ts'; +import ServiceRegistrationPage from '../../../components/Home/Market/ServiceRegistration.tsx'; +import WriteDetailPage from '../../Home/Market/WriteDetailPage.tsx'; +import Request from '../../../common/requests.js'; +import { MypageStackProps } from '../../../pages/MyPage.tsx'; +import { getAccessToken } from '../../../common/storage.js'; +import { useFocusEffect } from '@react-navigation/native'; +import { Title20B } from '../../../styles/GlobalText.tsx'; -const Stack = createStackNavigator(); -export default function AppNavigator() { - return ( - - - - - - - ); -} - -export const ProfileSection = ({ - navigation, - userInfo, +const ProfileSection = ({ + nickname, + backgroundphoto, + profile_image, + editProfile, + introduce, }: { - navigation: any; - userInfo: any; + nickname: string; + backgroundphoto: any; + profile_image: PhotoType; + editProfile: any; + introduce: string; }) => { - const marketName = '이하늘의 마켓'; - + const { width, height } = Dimensions.get('screen'); return ( - + {}} - onPressRight={() => navigation.navigate('FixMyPage', { userInfo })} - leftButton='CustomBack' - rightButton='Fix' - style = {{ backgroundColor: '#E9EBF8' }} + title="" + leftButton="CustomBack" + onPressLeft={() => { }} + rightButton="Fix" + onPressRight={editProfile} /> - - - + + + {profile_image === undefined || profile_image.uri === undefined ? ( // 전자는 편집페이지에서 사진 삭제했을 경우, 후자는 가장 처음에 로딩될 경우 + + ) : ( + + )} + + {nickname} + + 리폼러 - - {marketName} - ); }; -const MarketTabView = ({ - navigation, - route, -}: StackScreenProps) => { +export const ReformerMyPageScreen = ({ navigation, route }: MypageStackProps) => { const [activeTab, setActiveTab] = useState('profile'); const scrollRef = useRef(null); - const userInfo = { - nickname: '이하늘', - introduce: '나는야 업씨러 이하늘 환경을 사랑하지요 눈누난나', + const request = Request(); + const { isLogin, setLogin } = useContext(LoginContext); + const [userInfo, setUserInfo] = useState({ + nickname: route.params?.nickname || '', + backgroundphoto: + 'https://image.made-in-china.com/2f0j00efRbSJMtHgqG/Denim-Bag-Youth-Fashion-Casual-Small-Mini-Square-Ladies-Shoulder-Bag-Women-Wash-Bags.webp', profile_image: + route.params?.profile_image || 'https://image.made-in-china.com/2f0j00efRbSJMtHgqG/Denim-Bag-Youth-Fashion-Casual-Small-Mini-Square-Ladies-Shoulder-Bag-Women-Wash-Bags.webp', + introduce: route.params?.introduce || '', + }); + + useEffect(() => { + if (route.params?.userInfo) { + setUserInfo(route.params.userInfo); + } + }, [route.params?.userInfo]); + + const getProfile = async () => { + // 유저 프로필 가져오기-> setUserInfo로 관리 + const accessToken = await getAccessToken(); + const headers = { + Authorization: `Bearer ${accessToken}`, + }; + try { + const response = await request.get(`/api/user`, {}, headers); + const encodedUrl = encodeURI(response.data.profile_image_url); + const decodedUri = decodeURIComponent(encodedUrl); + const profileImage: PhotoType = { + fileName: response.data.profile_image_url ? 'profile.jpg' : undefined, + width: undefined, // width는 알 수 없으므로 undefined로 설정 + height: undefined, // height는 알 수 없으므로 undefined로 설정 + uri: + decodedUri || + 'https://image.made-in-china.com/2f0j00efRbSJMtHgqG/Denim-Bag-Youth-Fashion-Casual-Small-Mini-Square-Ladies-Shoulder-Bag-Women-Wash-Bags.webp', + }; + if (response.status === 200) { + console.log('User data fetched successfully:', response.data); + setUserInfo({ + nickname: response.data.nickname, + // 우선 기본이미지 + backgroundphoto: + 'https://image.made-in-china.com/2f0j00efRbSJMtHgqG/Denim-Bag-Youth-Fashion-Casual-Small-Mini-Square-Ladies-Shoulder-Bag-Women-Wash-Bags.webp', + profile_image: profileImage, + introduce: + response.data.introduce || + '나는야 업씨러 이하늘 환경을 사랑하지요 눈누난나', + }); + return response.data; + } else { + console.log('Failed to fetch user data:', response); + return null; + } + } catch (error) { + // 에러 처리 + console.error('Error fetching user data:', error); + return null; + } }; + useFocusEffect( + useCallback(() => { + if (isLogin) { + getProfile(); // 로그인 상태일 때 프로필을 가져옴 + } + }, [isLogin]), + ); + return ( ( - + navigation.navigate('FixMyPage', { userInfo })} + introduce={userInfo.introduce} + /> )} headerContainerStyle={{ shadowOpacity: 0, @@ -150,6 +222,7 @@ const MarketTabView = ({ style={styles.saveButton} onPress={() => navigation.navigate('TempStorage')}> 임시저장 (5) + {/*수정 필요*/} @@ -160,14 +233,16 @@ const MarketTabView = ({ {activeTab === 'service' ? ( navigation.navigate( - 'ServiceRegistration')}> + onPress={() => { + navigation.navigate( + 'ServiceRegistrationPage') + }}> 서비스 추가 ) : ( navigation.navigate('FixMyPage', { userInfo })}> + onPress={() => { navigation.navigate('FixMyPage', { userInfo }) }}> 프로필 수정하기 )} @@ -176,23 +251,23 @@ const MarketTabView = ({ }; const styles = StyleSheet.create({ - saveButton: { - height: 35, - paddingVertical: 10, - paddingHorizontal: 16, - justifyContent: 'center', - alignItems: 'center', - borderRadius: 4, - backgroundColor: '#DBFC72', // var(--NeonGreen-upcy-green) 값으로 설정 - flexDirection: 'row', // 가로 방향 배치 설정 - alignSelf: 'flex-start', - }, - saveButtonText: { - marginLeft: 10, // gap 대신 텍스트에 좌측 여백 설정 - color: '#612FEF', - fontSize: 14, - fontWeight: '600', - lineHeight: 24, + saveButton: { + height: 35, + paddingVertical: 10, + paddingHorizontal: 16, + justifyContent: 'center', + alignItems: 'center', + borderRadius: 4, + backgroundColor: '#DBFC72', // var(--NeonGreen-upcy-green) 값으로 설정 + flexDirection: 'row', // 가로 방향 배치 설정 + alignSelf: 'flex-start', + }, + saveButtonText: { + marginLeft: 10, // gap 대신 텍스트에 좌측 여백 설정 + color: '#612FEF', + fontSize: 14, + fontWeight: '600', + lineHeight: 24, }, fixedButton: { position: 'absolute', diff --git a/src/components/Auth/SignIn.tsx b/src/components/Auth/SignIn.tsx index d80fedc..0586050 100644 --- a/src/components/Auth/SignIn.tsx +++ b/src/components/Auth/SignIn.tsx @@ -30,16 +30,16 @@ export type SignInParams = { }; export default function SignIn() { // 스택 네비게이터 설정 - const Stack = createNativeStackNavigator(); + const SignInStack = createNativeStackNavigator(); return ( - - - - - - - - + + + + + + + + ); } diff --git a/src/components/Auth/Upcyer/Upcyer.tsx b/src/components/Auth/Upcyer/Upcyer.tsx index 2c02f45..eeb6700 100644 --- a/src/components/Auth/Upcyer/Upcyer.tsx +++ b/src/components/Auth/Upcyer/Upcyer.tsx @@ -103,6 +103,7 @@ export const UpcyFormProfile = ({ navigation, route }: UpcyerPageProps) => { const request = Request(); const form = route.params.form; const [form_, setForm] = useState({ + full_name: form?.full_name || '', mail: form?.mail || '', domain: form?.domain || '', password: form?.password || '', @@ -113,30 +114,54 @@ export const UpcyFormProfile = ({ navigation, route }: UpcyerPageProps) => { }); useEffect(() => { - form.agreement = form_.agreement; - form.domain = form_.domain; - form.introduce = form_.introduce; - form.mail = form_.mail; - form.nickname = form_.nickname; - form.password = form_.password; - form.profile_image = form_.profile_image; - }, [form_]) + if (route.params?.form) { + console.log("Form received in UpcyFormProfile:", route.params.form); + setForm(route.params.form); + } else { + console.warn("Form parameter is missing in UpcyFormProfile"); + } + }, [route.params?.form]); + const handleSubmit = async () => { + const accessToken = await getAccessToken(); + // 이 아래는 프로필 이미지 등록 + const headers_ = { + Authorization: `Bearer ${accessToken}`, + 'Content-Type': 'multipart/form-data', // multipart/form-data 설정 + }; + const formData = new FormData(); + formData.append('profile_image', { + uri: form_.profile_image?.uri, // 파일의 URI + type: 'image/jpeg', // 이미지 형식 (예: 'image/jpeg') + name: form_.profile_image?.fileName || 'profile.jpg', // 파일 이름 + }); + try { + const response = await request.post(`/api/user/profile-image`, formData, headers_) + if (response && response.status === 201) { + console.log(formData, '프로필 이미지 등록 성공') + } else { + console.log('이미지 업로드 실패'); + console.log(response); + } + } + catch (err) { + console.error(err) + } + // 이 아래는 닉네임, 소개글 + const headers = { + Authorization: `Bearer ${accessToken}` + }; const params = { - email: form_.mail + '@' + form_.domain, - password: form_.password, nickname: form_.nickname, - agreement_terms: form_.agreement.d, introduce: form_.introduce, }; if (form_.nickname != '') { try { - const response = await request.post('/api/user/signup', params); - if (response?.status === 201) { + const response = await request.put(`/api/user`, params, headers); + if (response?.status === 200) { console.log(params); setModalVisible(true); - // 3초 후 모달 닫고 페이지 이동 setTimeout(() => { setModalVisible(false); @@ -155,6 +180,7 @@ export const UpcyFormProfile = ({ navigation, route }: UpcyerPageProps) => { } catch (err) { console.log(err); } + } else { Alert.alert('닉네임을 입력해주세요.') } @@ -186,7 +212,7 @@ export const UpcyFormProfile = ({ navigation, route }: UpcyerPageProps) => { } caption={{ default: '본인을 나타내는 닉네임을 작성해주세요' }} /> - @@ -196,25 +222,21 @@ export const UpcyFormProfile = ({ navigation, route }: UpcyerPageProps) => { } caption={{ default: '본인을 소개하는 글을 작성해주세요' }} long={true} - /> - console.log(form)}> - ddddddd - - + /> */} - - + { setModalVisible(false); // 백 버튼 등으로 모달을 닫을 때 처리 }}> diff --git a/src/components/Auth/Upcyer/UpcyerMyPage.tsx b/src/components/Auth/Upcyer/UpcyerMyPage.tsx index b89ef9e..eb884e9 100644 --- a/src/components/Auth/Upcyer/UpcyerMyPage.tsx +++ b/src/components/Auth/Upcyer/UpcyerMyPage.tsx @@ -15,7 +15,6 @@ import { StackScreenProps, createStackNavigator, } from '@react-navigation/stack'; -import { TabProps } from '../../App'; import { getAccessToken, removeAccessToken, @@ -34,42 +33,15 @@ import ReviewPage from '../../../components/Home/Market/ReviewPage'; import ScrollToTopButton from '../../../common/ScrollToTopButtonFlat'; import FixMyPage from '../../../pages/FixMyPage'; import Login from '../../../components/Auth/Login'; -import { PhotoType } from '../hooks/useImagePicker'; import Request from '../../../common/requests'; -import useUser from '../common/Context'; import OrderPage from '../../../components/Home/Order/OrderPage'; import { useFocusEffect } from '@react-navigation/native'; import { print } from '@gorhom/bottom-sheet/lib/typescript/utilities/logger'; -export type MyPageStackParams = { - MyPage: { userInfo?: any | undefined }; - FixMyPage: { userInfo: any }; - Login: undefined; -}; - -export interface MypageStackProps { - navigation: any; - route: any; -} - -const MyPageStack = createStackNavigator(); - -const MyPageScreen = ({ - navigation, - route, -}: StackScreenProps) => { - return ( - ({ - headerShown: false, - })}> - - - - - ); -}; +import { TabProps } from '../../../../App'; +import { PhotoType } from '../../../hooks/useImagePicker'; +import { MyPageStackParams, MypageStackProps } from '../../../pages/MyPage'; -const MyPageMainScreen = ({ navigation, route }: MypageStackProps) => { +export const UpcyerMyPageMainScreen = ({ navigation, route }: MypageStackProps) => { const { width, height } = Dimensions.get('screen'); const ProfileSection = ({ nickname, @@ -84,17 +56,18 @@ const MyPageMainScreen = ({ navigation, route }: MypageStackProps) => { editProfile: any; introduce: string; }) => { + const { width, height } = Dimensions.get('screen'); return ( {}} + onPressLeft={() => { }} rightButton="Fix" onPressRight={editProfile} /> - + {profile_image === undefined || profile_image.uri === undefined ? ( // 전자는 편집페이지에서 사진 삭제했을 경우, 후자는 가장 처음에 로딩될 경우 { profile_image ? { uri: profile_image.uri } // 유효한 URL이면 그대로 사용 : { - uri: 'https://image.made-in-china.com/2f0j00efRbSJMtHgqG/Denim-Bag-Youth-Fashion-Casual-Small-Mini-Square-Ladies-Shoulder-Bag-Women-Wash-Bags.webp', - } // 기본 이미지 URL 사용 + uri: 'https://image.made-in-china.com/2f0j00efRbSJMtHgqG/Denim-Bag-Youth-Fashion-Casual-Small-Mini-Square-Ladies-Shoulder-Bag-Women-Wash-Bags.webp', + } // 기본 이미지 URL 사용 } /> )} - {nickname} - - - + {nickname} + ); }; @@ -210,8 +181,8 @@ const MyPageMainScreen = ({ navigation, route }: MypageStackProps) => { // }; const [routes] = useState([ - { key: 'order', title: '주문내역' }, - // { key: 'like', title: '좋아요' }, + { key: 'order', title: '주문내역' }, + // { key: 'like', title: '좋아요' }, ]); const flatListRef = useRef(null); const scrollRef = useRef(null); @@ -251,25 +222,23 @@ const MyPageMainScreen = ({ navigation, route }: MypageStackProps) => { fontWeight: '700', fontSize: 16, }} - //onTabPress={() => Alert.alert('준비중입니다!ㅠㅠ')} - // 룩북, 좋아요 모아보기 기능 구현되면 위의 onTapPress는 삭제할 것 + //onTabPress={() => Alert.alert('준비중입니다!ㅠㅠ')} + // 룩북, 좋아요 모아보기 기능 구현되면 위의 onTapPress는 삭제할 것 /> )}> - {routes.map(route => ( - ( -a {route.key === 'order' && } + {routes.map(route_ => ( + ( + {route_.key === 'order' && } - {/* {route.key === 'like' && + {/* {route.key === 'like' && } } */} - ) + ) ))} ); }; - -export default MyPageScreen; diff --git a/src/components/Home/Market/ServiceRegistration.tsx b/src/components/Home/Market/ServiceRegistration.tsx index cd7fb5a..ff245bc 100644 --- a/src/components/Home/Market/ServiceRegistration.tsx +++ b/src/components/Home/Market/ServiceRegistration.tsx @@ -48,6 +48,7 @@ import Help from '../../../assets/common/Help.svg'; import { Modal } from 'react-native'; import { getAccessToken, getMarketUUID } from '../../../common/storage'; import Request from '../../../common/requests'; +import { MyPageStackParams } from '../../../pages/MyPage'; const { width } = Dimensions.get('window'); @@ -133,7 +134,7 @@ interface Material { const ServiceRegistrationPage = ({ navigation, route, -}: StackScreenProps) => { +}: StackScreenProps) => { // 마켓 페이지도 그냥 홈스택에 놔두면, 얘도 냅둬야 하나? const { hideBottomBar, showBottomBar } = useBottomBar(); diff --git a/src/components/Home/Market/WriteDetailPage.tsx b/src/components/Home/Market/WriteDetailPage.tsx index f0335f9..72c67e0 100644 --- a/src/components/Home/Market/WriteDetailPage.tsx +++ b/src/components/Home/Market/WriteDetailPage.tsx @@ -11,14 +11,13 @@ import DetailScreenHeader from '../components/DetailScreenHeader'; import { useBottomBar } from '../../../../contexts/BottomBarContext'; import ImageCarousel from '../../../common/ImageCarousel'; import { PhotoType } from '../../../hooks/useImagePicker'; +import { MyPageStackParams } from '../../../pages/MyPage'; const { width, height } = Dimensions.get('window'); -type WriteDetailPageProps = StackScreenProps; - -const WriteDetailPage: React.FC = ({ navigation, route }) => { +const WriteDetailPage = ({ navigation, route }: StackScreenProps) => { const { inputText } = route.params; // route 파라미터 전달받아옴 const { detailphoto } = route.params; const [localInput, setLocalInput] = useState(inputText); // 로컬변수 지정 diff --git a/src/components/Home/Market/WriteReviewPage.tsx b/src/components/Home/Market/WriteReviewPage.tsx index 3e5b55b..ffdea9b 100644 --- a/src/components/Home/Market/WriteReviewPage.tsx +++ b/src/components/Home/Market/WriteReviewPage.tsx @@ -33,6 +33,7 @@ import { useBottomBar } from '../../../../contexts/BottomBarContext'; import { handleBackPress } from '../../../common/navigationUtils'; import { useNavigation } from '@react-navigation/native'; import BouncyCheckbox from 'react-native-bouncy-checkbox'; +import { OrderProps } from '../Order/OrderManagement'; const statusBarHeight = getStatusBarHeight(true); const { width, height } = Dimensions.get('window'); @@ -62,8 +63,7 @@ const ReviewComponent = ({ feedBack }: any) => { ); }; -const WriteReviewPage = ({ scrollViewRef }: WriteReviewPageProps) => { - const navigation = useNavigation(); +const WriteReviewPage = ({ navigation, route }: OrderProps) => { const [detail, setDetail] = useState(''); const [marketName] = useState('마켓명'); const [serviceName] = useState('서비스 이름 어쩌구저쩌구'); diff --git a/src/components/Home/Order/CompletedOrder.tsx b/src/components/Home/Order/CompletedOrder.tsx index 5195228..4144af9 100644 --- a/src/components/Home/Order/CompletedOrder.tsx +++ b/src/components/Home/Order/CompletedOrder.tsx @@ -4,36 +4,37 @@ import Arrow from '../../../assets/common/Arrow.svg'; import { GREEN } from "../../../styles/GlobalColor"; import { useNavigation } from '@react-navigation/native'; import BottomButton from '../../../common/BottomButton'; +import { OrderProps } from "./OrderManagement"; -const CompletedOrder = () => { - const navigation = useNavigation(); +const CompletedOrder = ({ navigation, route }: OrderProps) => { - const handlePress = () => { - navigation.navigate('Home'); // 'Home'을 실제 네비게이션 스택에 맞게 수정 - }; + + // const handlePress = () => { + // navigation.navigate('Home'); // 'Home'을 실제 네비게이션 스택에 맞게 수정 + // }; return ( - - - - - 거래가 완료 되었습니다 - navigation.navigate('WriteReviewPage')}> - + + + + + 거래가 완료 되었습니다 + navigation.navigate('WriteReviewPage')}> + 구매한 상품이 마음에 드시나요? 후기 작성하러 가기 - navigation.navigate('Home')}> - - 이 마켓이 마음에 들었나요? - SDP 마켓의 다른 서비스 보러가기 - - - + navigation.navigate('Home')}> + + 이 마켓이 마음에 들었나요? + SDP 마켓의 다른 서비스 보러가기 + + + diff --git a/src/components/Home/Order/OrderManagement.tsx b/src/components/Home/Order/OrderManagement.tsx index d8e4626..3ebba98 100644 --- a/src/components/Home/Order/OrderManagement.tsx +++ b/src/components/Home/Order/OrderManagement.tsx @@ -9,14 +9,19 @@ import { BLACK, BLACK2 } from '../../../styles/GlobalColor.tsx'; import { useNavigation } from '@react-navigation/native'; -import { StackScreenProps } from '@react-navigation/stack'; -import { HomeStackParams } from '../../../pages/Home'; +import { createStackNavigator, StackScreenProps } from '@react-navigation/stack'; import Hashtag from '../../../common/Hashtag.tsx'; import DetailScreenHeader from '../components/DetailScreenHeader.tsx'; import ScrollToTopButton from '../../../common/ScrollToTopButtonFlat.tsx'; import ScrollTopButton from '../../../common/ScrollTopButton.tsx'; +import { BottomTabScreenProps } from '@react-navigation/bottom-tabs'; +import { TabProps } from '../../../../App.tsx'; +import OrderPage from './OrderPage.tsx'; +import QuotationPage, { QuotationProps } from '../Quotation/QuotationPage.tsx'; +import CompletedOrder from './CompletedOrder.tsx'; +import WriteReviewPage from '../Market/WriteReviewPage.tsx'; type OrderInfoType = { id: string; @@ -27,6 +32,35 @@ type OrderInfoType = { navigation: any; } +export type OrderProps = { + navigation: any; + route: any; + flatListRef?: React.RefObject>; +} + +export type OrderStackParams = { + OrderPage: undefined; + CompletedOrder: undefined; + QuotationPage: QuotationProps; + WriteReviewPage: undefined; +} + +const OrderStack = createStackNavigator(); + +const OrderScreen = ({ + navigation, + route, +}: BottomTabScreenProps) => { + return ( + + + + + + + ) +} + const OrderInfo = ({ id, name, customer, orderDate, is_online, navigation }: OrderInfoType) => ( {name} @@ -41,10 +75,9 @@ const OrderInfo = ({ id, name, customer, orderDate, is_online, navigation }: Ord ); -const OrderManagement = () => { +const OrderManagement = ({ navigation, route }: BottomTabScreenProps) => { const { width } = Dimensions.get('window'); const scrollRef = useRef(null); - const navigation = useNavigation(); const [orderlist, setOrderList] = useState([ { diff --git a/src/components/Home/Order/OrderPage.tsx b/src/components/Home/Order/OrderPage.tsx index 0c38ef7..2d1dba5 100644 --- a/src/components/Home/Order/OrderPage.tsx +++ b/src/components/Home/Order/OrderPage.tsx @@ -9,6 +9,7 @@ import { Title20B, Body14R, Body16B, Caption11M } from '../../../styles/GlobalTe import { useNavigation } from '@react-navigation/native'; import { StackScreenProps } from '@react-navigation/stack'; import { HomeStackParams } from '../../../pages/Home'; +import { OrderProps, OrderStackParams } from './OrderManagement.tsx'; @@ -22,7 +23,7 @@ interface OrderInfoProps { navigation: any; } -const OrderInfo: React.FC = ({ name, customer, estimated_price, is_online, navigation }) => ( +const OrderInfo = ({ name, customer, estimated_price, is_online, navigation }: OrderInfoProps) => ( {name} 주문자: {customer} @@ -114,16 +115,10 @@ const OrderInfoContainer = styled.View` border: 1px solid white; `; +// 리폼러가 마이페이지에서 보는 주문관리 탭 -export interface OrderPageProps extends StackScreenProps { - flatListRef: React.RefObject>; - navigation: any; - route: any; -} - - -const OrderPage: React.FC = ({ flatListRef, navigation, route }) => { +const OrderPage = ({ flatListRef, navigation, route }: OrderProps) => { const [selectedFilter, setSelectedFilter] = useState('전체'); const [isModalVisible, setIsModalVisible] = useState(false); diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index fa7b533..448a7c3 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -36,7 +36,6 @@ import { PURPLE } from '../styles/GlobalColor'; import OrderManagement from '../components/Home/Order/OrderManagement'; import CompletedOrder from '../components/Home/Order/CompletedOrder'; import ReformerMarket from '../components/Home/Market/ReformerMarket'; -import ReformerProfileService from '../components/Auth/Reformer/ReformerMyPage'; import Service from '../components/Home/Market/Service'; import { PhotoType } from '../hooks/useImagePicker'; import { Styles } from '../types/UserTypes'; @@ -57,15 +56,12 @@ export type HomeStackParams = { backgroundImageUri: string; profileImageUri?: string; }; - OrderManagement: undefined; - CompletedOrder: undefined; GoodsDetailPage: undefined; QuotationForm: undefined; QuotationPage: QuotationProps; SentQuotation: undefined; - ServiceRegistrationPage: { inputText?: string; detailphoto?: PhotoType[] }; + // ServiceRegistrationPage: { inputText?: string; detailphoto?: PhotoType[] }; GoodsRegistrationPage: undefined; - TempStorage: undefined; TempStorageEdit: undefined; WriteDetailPage: { inputText: string; detailphoto?: PhotoType[] }; AddPortfolio: undefined; @@ -73,7 +69,6 @@ export type HomeStackParams = { QuotationConfirm: undefined; Rejection: undefined; SentRejection: undefined; - WriteReviewPage: undefined; ReformerMarket: undefined; TestComponents: undefined; MarketTabView: { @@ -81,7 +76,6 @@ export type HomeStackParams = { // id: string; reformerName: string; }; - ReformerProfileService: undefined; }; const HomeStack = createStackNavigator(); @@ -110,15 +104,13 @@ const HomeScreen = ({ name="ServiceDetailPage" component={ServiceDetailPageScreen} /> - + /> */} - - - @@ -135,13 +126,8 @@ const HomeScreen = ({ - - ); }; @@ -216,10 +202,6 @@ const HomeMainScreen = ({ {selectedTab === 'Market' && } {selectedTab === 'temp' && ( - @@ -239,12 +221,6 @@ const HomeMainScreen = ({ onPress={() => navigation.navigate('ServiceDetailPage', {})}> 서비스 디테일 - @@ -255,12 +231,6 @@ const HomeMainScreen = ({ - - diff --git a/src/pages/MyPage.tsx b/src/pages/MyPage.tsx index 37c3814..14cef9f 100644 --- a/src/pages/MyPage.tsx +++ b/src/pages/MyPage.tsx @@ -1,72 +1,23 @@ -import React, { useContext } from 'react'; +import React, { useCallback, useContext, useEffect, useState } from 'react'; import { View, Text, TouchableOpacity, StyleSheet } from 'react-native'; import { useUser, LoginContext } from '../common/Context'; -import LockIcon from "../assets/common/Lock.svg"; -import ReformerMyPage from '../components/Auth/Reformer/ReformerMyPage.tsx'; -import ConsumerMyPage from '../components/Auth/Upcyer/UpcyerMyPage.tsx'; +import Lock from "../assets/common/Lock.svg"; +import { ReformerMyPageScreen } from '../components/Auth/Reformer/ReformerMyPage.tsx'; +import { UpcyerMyPageMainScreen } from '../components/Auth/Upcyer/UpcyerMyPage.tsx'; import Login from '../components/Auth/Login'; -import ReformerProfile from '../components/Auth/Reformer/Reformer.tsx'; -import { createStackNavigator } from '@react-navigation/stack'; - -const Stack = createStackNavigator(); - -const MyPageScreen = ({ navigation }) => { - const { user } = useUser(); - const { isLogin } = useContext(LoginContext); - - if (!isLogin) { - return ; - } - -// if (user.nickname === "") { -// return ( -// -// -// -// -// 리폼러 프로필 등록을 완료해야{'\n'}나의 서비스를 제공할 수 있습니다. -// -// -// -// navigation.navigate('ReformerProfile')} // Navigate to profile registration page -// > -// 리폼러 프로필 등록하기 -// -// -// ); -// } else { - if (user.role === 'reformer') { - return ; - } else if (user.role === 'customer') { - return ; - } else { - return ( - - Role not assigned or data missing - - ); - } -// } -}; - -const MyPageStack = () => { - return ( - - - - - ); -}; +import { createStackNavigator, StackScreenProps } from '@react-navigation/stack'; +import { BottomTabScreenProps } from '@react-navigation/bottom-tabs'; +import { TabProps } from '../../App.tsx'; +import { getAccessToken, getUserRole } from '../common/storage.js'; +import TempStorage from '../components/Home/Market/TempStorage.tsx'; +import ServiceRegistrationPage from '../components/Home/Market/ServiceRegistration.tsx'; +import WriteDetailPage from '../components/Home/Market/WriteDetailPage.tsx'; +import { PhotoType } from '../hooks/useImagePicker.ts'; +import FixMyPage from './FixMyPage.tsx'; +import Request from '../common/requests.js'; +import { useFocusEffect } from '@react-navigation/native'; +import { Body16B } from '../styles/GlobalText.tsx'; +import BottomButton from '../common/BottomButton.tsx'; const styles = StyleSheet.create({ container: { @@ -110,4 +61,155 @@ const styles = StyleSheet.create({ }, }); -export default MyPageStack; +export type MyPageStackParams = { + MyPage: { userInfo?: any | undefined }; + FixMyPage: { userInfo: any }; + Login: undefined; + ReformerMyPageScreen: { navigation: any, route: any }; + UpcyerMyPageMainScreen: { navigation: any, route: any }; + TempStorage: undefined; + ServiceRegistrationPage: { inputText?: string; detailphoto?: PhotoType[] }; + WriteDetailPage: { inputText: string; detailphoto?: PhotoType[] }; +}; + +export interface MypageStackProps { + navigation: any; + route: any; +} + +const MyPageStack = createStackNavigator(); +const MyPageScreen = ({ + navigation, + route, +}: BottomTabScreenProps) => { + return ( + + + + + + + + + + + ); +}; + +const MyPageMainScreen = ({ navigation, route }: MypageStackProps) => { + const request = Request(); + const { isLogin, setLogin } = useContext(LoginContext); + const [role, setRole] = useState(''); + const [userInfo, setUserInfo] = useState({ + nickname: route.params?.userInfo?.nickname || '', + backgroundphoto: + route.params?.userInfo?.backgroundphoto || + 'https://image.made-in-china.com/2f0j00efRbSJMtHgqG/Denim-Bag-Youth-Fashion-Casual-Small-Mini-Square-Ladies-Shoulder-Bag-Women-Wash-Bags.webp', + profile_image: + route.params?.userInfo?.profile_image || + 'https://image.made-in-china.com/2f0j00efRbSJMtHgqG/Denim-Bag-Youth-Fashion-Casual-Small-Mini-Square-Ladies-Shoulder-Bag-Women-Wash-Bags.webp', + introduce: route.params?.userInfo?.introduce || '', + }); + + + + useEffect(() => { + if (route.params?.userInfo) { + setUserInfo(route.params.userInfo); + } + }, [route.params?.userInfo]); + + const getProfile = async () => { + // 유저 프로필 가져오기-> setUserInfo로 관리 + const accessToken = await getAccessToken(); + const headers = { + Authorization: `Bearer ${accessToken}`, + }; + try { + const response = await request.get(`/api/user`, {}, headers); + const encodedUrl = encodeURI(response.data.profile_image_url); + const decodedUri = decodeURIComponent(encodedUrl); + const profileImage: PhotoType = { + fileName: response.data.profile_image_url ? 'profile.jpg' : undefined, + width: undefined, // width는 알 수 없으므로 undefined로 설정 + height: undefined, // height는 알 수 없으므로 undefined로 설정 + uri: + decodedUri || + 'https://image.made-in-china.com/2f0j00efRbSJMtHgqG/Denim-Bag-Youth-Fashion-Casual-Small-Mini-Square-Ladies-Shoulder-Bag-Women-Wash-Bags.webp', + }; + if (response.status === 200) { + console.log('User data fetched successfully:', response.data); + setUserInfo({ + nickname: response.data.nickname, + // 우선 기본이미지 + backgroundphoto: + 'https://image.made-in-china.com/2f0j00efRbSJMtHgqG/Denim-Bag-Youth-Fashion-Casual-Small-Mini-Square-Ladies-Shoulder-Bag-Women-Wash-Bags.webp', + profile_image: profileImage, + introduce: + response.data.introduce || + '나는야 업씨러 이하늘 환경을 사랑하지요 눈누난나', + }); + setRole(response.data.role); + return response.data; + } else { + console.log('Failed to fetch user data:', response); + return null; + } + } catch (error) { + // 에러 처리 + console.error('Error fetching user data:', error); + return null; + } + }; + + useFocusEffect( + useCallback(() => { + if (isLogin) { + getProfile(); // 로그인 상태일 때 프로필을 가져옴 + } + }, [isLogin]), + ); + + if (userInfo.nickname === '' || userInfo.nickname === null) { + return ( + + + {''} + 리폼러 프로필 등록을 완료해야 + 나의 서비스를 제공할 수 있습니다. + { + navigation.navigate('Signin', { screen: 'Reformer' }); // 최상위 스택에 접근 + }} + style={{ + width: '90%', + alignSelf: 'center', + marginTop: 'auto', + marginBottom: 20, + position: "absolute", + bottom: 0, + }} + /> + + ); + } else { + if (role === 'reformer') { + return ; + } else if (role === 'customer') { + return ; + } else { + return ( + + Role not assigned or data missing + + ); + } + } +}; + + + +export default MyPageScreen; diff --git a/yarn.lock b/yarn.lock index 71e8ce5..2d0211e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1126,10 +1126,10 @@ resolved "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz" integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== -"@babel/runtime@^7.0.0", "@babel/runtime@^7.20.0", "@babel/runtime@^7.20.6", "@babel/runtime@^7.23.2", "@babel/runtime@^7.8.4": - version "7.23.6" - resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.6.tgz" - integrity sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ== +"@babel/runtime@^7.0.0", "@babel/runtime@^7.20.6", "@babel/runtime@^7.23.2", "@babel/runtime@^7.26.0", "@babel/runtime@^7.8.4": + version "7.26.0" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz" + integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw== dependencies: regenerator-runtime "^0.14.0" @@ -4230,6 +4230,11 @@ fs.realpath@^1.0.0: resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== +fsevents@^2.3.2: + version "2.3.3" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + function-bind@^1.1.1, function-bind@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz"