diff --git a/App.tsx b/App.tsx index 5ff2096..9285517 100644 --- a/App.tsx +++ b/App.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; -import Login from './src/app/Login/page'; +import Login from './src/app/login/page'; import {NavigationContainer} from '@react-navigation/native'; import {createNativeStackNavigator} from '@react-navigation/native-stack'; import Community from './src/app/community/page'; @@ -18,12 +18,16 @@ import Write from './src/app/review/Write'; import KeywordReview from './src/app/review/KeywordReview'; import Search from './src/app/search/page'; import NavBar from './src/components/NavBar'; -import Signup from './src/app/Signup/page'; +import Signup from './src/app/signup/page'; import QandADetail from './src/app/review/QandADetail'; import Question from './src/app/review/Question'; import QueryProvider from './src/utils/query/Provider'; import ReduxProvider from './src/utils/store/Provider'; import MyPage from './src/app/mypage/page'; +import BookmarkSchool from './src/app/mypage/BookmarkSchool'; +import WritePost from './src/app/mypage/WritePost'; +import LikePost from './src/app/mypage/LikePost'; +import Setting from '@/app/mypage/Setting'; function App(): React.JSX.Element { const Stack = createNativeStackNavigator(); @@ -33,7 +37,7 @@ function App(): React.JSX.Element { + initialRouteName="Login"> @@ -47,6 +51,10 @@ function App(): React.JSX.Element { + + + + diff --git a/android/app/build.gradle b/android/app/build.gradle index 52f4e15..f83dac3 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -6,6 +6,10 @@ apply plugin: "com.facebook.react" * This is the configuration block to customize your React Native Android app. * By default you don't need to apply any configuration, just uncomment the lines you need. */ +project.ext.react = [ + enableHermes: true // Set to true to enable Hermes +] + react { /* Folders */ // The root of your project, i.e. where "package.json" lives. Default is '..' @@ -69,6 +73,7 @@ def enableProguardInReleaseBuilds = false */ def jscFlavor = 'org.webkit:android-jsc:+' + android { ndkVersion rootProject.ext.ndkVersion buildToolsVersion rootProject.ext.buildToolsVersion diff --git a/babel.config.js b/babel.config.js index 02c7d13..254490e 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,4 +1,15 @@ module.exports = { presets: ['module:@react-native/babel-preset'], - plugins: ['react-native-reanimated/plugin'], + plugins: [ + [ + 'module-resolver', + { + root: ['./src'], + alias: { + '@components': './src/components', + '@': './src', + }, + }, + ], + ], }; diff --git a/package.json b/package.json index a4f0237..af44af5 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "test": "jest" }, "dependencies": { + "@react-native-async-storage/async-storage": "^2.0.0", "@react-native-community/viewpager": "^5.0.11", "@react-navigation/bottom-tabs": "^6.5.20", "@react-navigation/material-top-tabs": "^6.6.13", @@ -22,7 +23,6 @@ "@types/redux-logger": "^3.0.13", "@types/styled-components": "^5.1.34", "axios": "^1.7.7", - "babel-plugin-module-resolver": "^5.0.2", "missing-asset-registry-path": "^0.0.0", "react": "18.2.0", "react-hook-form": "^7.53.0", @@ -59,6 +59,7 @@ "@types/react": "^18.2.6", "@types/react-test-renderer": "^18.0.0", "babel-jest": "^29.6.3", + "babel-plugin-module-resolver": "^5.0.2", "eslint": "^8.19.0", "jest": "^29.6.3", "metro-config": "^0.80.9", diff --git a/src/apis/cookie.ts b/src/apis/cookie.ts index e69de29..a9a9a8a 100644 --- a/src/apis/cookie.ts +++ b/src/apis/cookie.ts @@ -0,0 +1,9 @@ +import {instance} from './axios'; + +export const applyToken = (jwt: string) => { + instance.defaults.headers.Authorization = `Bearer ${jwt}`; +}; + +export const clearToken = () => { + instance.defaults.headers.Authorization = ''; +}; diff --git a/src/apis/mypage.ts b/src/apis/mypage.ts new file mode 100644 index 0000000..26d9dc4 --- /dev/null +++ b/src/apis/mypage.ts @@ -0,0 +1,31 @@ +import {instance} from './axios'; + +interface MypageInfo { + name: string; + enrolled_school: number; + image?: string; +} + +export const editMypage = async (mypageInfo: MypageInfo) => { + try { + const response = await instance.patch('/user/modify', { + name: mypageInfo.name, + enrolled_school: mypageInfo.enrolled_school, + ...(mypageInfo.image && {image: mypageInfo.image}), + }); + return response.data; + } catch (error) { + console.error('마이페이지 수정 오류:', error); + throw error; + } +}; + +export const getMypage = async () => { + try { + const response = await instance.get('/user/my'); + return response.data; + } catch (error) { + console.error('마이페이지 조회 오류:', error); + throw error; + } +}; diff --git a/src/apis/user.ts b/src/apis/user.ts index ba03030..4ff2a7b 100644 --- a/src/apis/user.ts +++ b/src/apis/user.ts @@ -1,4 +1,8 @@ import {instance} from './axios'; +import {useNavigation} from '@react-navigation/native'; +import {StackNavigationProp} from '@react-navigation/stack'; +import AsyncStorage from '@react-native-async-storage/async-storage'; +import {Alert} from 'react-native'; interface SignupData { id: string; @@ -18,35 +22,52 @@ interface ApiResponse { data: T; } -// export const login = async (data: LoginData): Promise> => { -// try { -// const response = await axios.post>(``, data); -// return response.data; -// } catch (error: any) { -// if (axios.isAxiosError(error)) { -// console.error('axios 에러:', error.response?.data); -// } -// return { -// success: false, -// message: error.response?.data.message || '로그인 실패', -// data: null, -// }; -// } -// }; -const auth = '/user'; - -export const postSignup = async (data: SignupData) => { - return await instance - .post(`${auth}/signup`, { +const navigation = useNavigation>(); + +export const signupHandler = async (data: SignupData) => { + try { + const response = await instance.post(`/user/signup`, { account_id: data.id, name: data.name, password: data.password, enrolled_school: data.schoolId, - }) - .then() - .catch(err => { - console.error(err); }); + } catch (error) { + console.log(error); + Alert.alert('아이디 또는 비밀번호를 잘못 입력했습니다.'); + } +}; + +export const loginHandler = async (data: LoginData, navigation: any) => { + try { + const response = await instance.post(`/user/login`, { + account_id: data.id, + password: data.password, + }); + + await AsyncStorage.setItem('AccessToken', response.data.accessToken); + await AsyncStorage.setItem('RefreshToken', response.data.refreshToken); + navigation.navigate('NavBar'); + } catch (error) { + console.error(error); + Alert.alert('로그인 오류', '로그인이 실패했습니다.'); + } }; -export const postLogin = () => {}; +export const checkDuplicationId = async (data: any) => { + try { + const response = await instance.get(`/user/check`); + return response.data; + } catch (error) { + console.error(error); + } +}; + +export const logoutHandler = async () => { + try { + AsyncStorage.clear(); + navigation.navigate('Login'); + } catch (error) { + console.error(error); + } +}; diff --git a/src/app/community/AddTag.tsx b/src/app/community/AddTag.tsx index 00f5dbe..486a111 100644 --- a/src/app/community/AddTag.tsx +++ b/src/app/community/AddTag.tsx @@ -4,7 +4,7 @@ import {TopBar, Input} from '../../components'; import {Arrow, Close, Plus} from '../../assets'; import {TouchableOpacity} from 'react-native'; import {useNavigation} from '@react-navigation/native'; -import {color, Font} from '../../styles'; +import {color, Font} from '@/styles'; import {StackNavigationProp} from '@react-navigation/stack'; function AddTag() { diff --git a/src/app/community/EditPost.tsx b/src/app/community/EditPost.tsx index 872132b..bb94dfd 100644 --- a/src/app/community/EditPost.tsx +++ b/src/app/community/EditPost.tsx @@ -1,8 +1,7 @@ import React, {useState} from 'react'; import styled from 'styled-components/native'; import {TopBar} from '../../components/TopBar'; -import {Font} from '../../styles/font'; -import {color} from '../../styles/color'; +import {Font, color} from '@/styles'; import ToggleButton from '../../components/ToggleButton'; import {Image, Close} from '../../assets'; import {useNavigation} from '@react-navigation/native'; diff --git a/src/app/community/InputComment.tsx b/src/app/community/InputComment.tsx index cef1790..9525042 100644 --- a/src/app/community/InputComment.tsx +++ b/src/app/community/InputComment.tsx @@ -1,7 +1,7 @@ import React, {useState} from 'react'; import {Dimensions} from 'react-native'; import styled from 'styled-components/native'; -import {color} from '../../styles/color'; +import {color} from '@/styles'; import {Heart} from '../../assets'; function InputComment() { diff --git a/src/app/community/Post.tsx b/src/app/community/Post.tsx index f92c640..db4a115 100644 --- a/src/app/community/Post.tsx +++ b/src/app/community/Post.tsx @@ -3,8 +3,7 @@ import styled from 'styled-components/native'; import {TopBar} from '../../components/TopBar'; import {Arrow, Menu} from '../../assets'; import {useNavigation} from '@react-navigation/native'; -import {Font} from '../../styles/font'; -import {color} from '../../styles/color'; +import {Font, color} from '@/styles'; import Tag from '../../components/Tag'; import Comment from '../../components/community/Comment'; import InputComment from './InputComment'; diff --git a/src/app/community/page.tsx b/src/app/community/page.tsx index 0b251ad..fe7d4a5 100644 --- a/src/app/community/page.tsx +++ b/src/app/community/page.tsx @@ -1,9 +1,8 @@ import React, {useState} from 'react'; import {Dimensions} from 'react-native'; import styled from 'styled-components/native'; -import {Font} from '../../styles/font'; +import {Font, color} from '@/styles'; import {Arrow, Blank, Edit} from '../../assets'; -import {color} from '../../styles/color'; import {ContentCard} from '../../components/ContentCard'; import {useNavigation} from '@react-navigation/native'; import {StackNavigationProp} from '@react-navigation/stack'; diff --git a/src/app/dummy/schoolList.ts b/src/app/dummy/schoolList.ts index a5f94e8..9b17cb7 100644 --- a/src/app/dummy/schoolList.ts +++ b/src/app/dummy/schoolList.ts @@ -1,6 +1,6 @@ import {SchoolListType} from '../../interfaces'; -export const schoolList: SchoolListType[] = [ +export const schoolList = [ {name: '대구대덕초등학교', location: '대구 남구'}, {name: '대덕초등학교', location: '대전 유성구 궁동'}, {name: '용인대덕초등학교', location: '경인 용인시 수지구'}, diff --git a/src/app/dummy/searchSchool.ts b/src/app/dummy/searchSchool.ts index e94a696..9da3b1c 100644 --- a/src/app/dummy/searchSchool.ts +++ b/src/app/dummy/searchSchool.ts @@ -1,10 +1,68 @@ export const searchSchool = [ - {schoolName: "대구대덕초등학교", address: "대구 남구", score: 5, reviewCount : 128}, - {schoolName: "대덕초등학교", address: "대구 남구", score: 5, reviewCount : 3}, - {schoolName: "대덕소프트웨어마이스터초등학교", address: "대구 남구", score: 5, reviewCount : 128}, - {schoolName: "용인대덕초등학교", address: "대구 남구", score: 5, reviewCount : 128}, - {schoolName: "대마초등학교", address: "대구 남구", score: 5, reviewCount : 128}, - {schoolName: "대구대덕초등학교", address: "대구 남구", score: 5, reviewCount : 128}, - {schoolName: "대구대덕초등학교", address: "대구 남구", score: 5, reviewCount : 128}, - {schoolName: "대구대덕초등학교", address: "대구 남구", score: 5, reviewCount : 128}, -] \ No newline at end of file + { + schoolName: '대구대덕초등학교', + address: '대구 남구', + score: 5, + reviewCount: 128, + }, + { + schoolName: '대덕초등학교', + address: '대구 남구', + score: 3.6, + reviewCount: 3, + }, + { + schoolName: '대덕소프트웨어마이스터고등학교', + address: '대구 남구', + score: 1.345, + reviewCount: 128, + }, + { + schoolName: '용인대덕초등학교', + address: '대구 남구', + score: 5, + reviewCount: 128, + }, + { + schoolName: '대마중학교', + address: '대구 남구', + score: 5, + reviewCount: 128, + }, + { + schoolName: '대구대덕초등학교', + address: '대구 남구', + score: 5, + reviewCount: 128, + }, + { + schoolName: '대구대덕초등학교', + address: '대구 남구', + score: 5, + reviewCount: 128, + }, + { + schoolName: '대구대덕초등학교', + address: '대구 남구', + score: 5, + reviewCount: 45, + }, + { + schoolName: '대구대덕초등학교', + address: '대구 남구', + score: 5, + reviewCount: 128, + }, + { + schoolName: '대구대덕초등학교', + address: '대구 남구', + score: 5, + reviewCount: 128, + }, + { + schoolName: '대덕대학교', + address: '대구 남구', + score: 5, + reviewCount: 45, + }, +]; diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index 2631a12..0efeb47 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -3,10 +3,13 @@ import {useNavigation} from '@react-navigation/native'; import styled from 'styled-components/native'; import {Logo} from '../../assets'; import {Button, Input} from '../../components'; -import {Font, color} from '../../styles'; +import {Font, color} from '@/styles'; import {StackNavigationProp} from '@react-navigation/stack'; import {Controller, useForm} from 'react-hook-form'; import {Alert} from 'react-native'; +import {loginHandler} from '@/apis/user'; +import AsyncStorage from '@react-native-async-storage/async-storage'; +import {instance} from '@/apis/axios'; function Login() { const navigation = useNavigation>(); @@ -21,11 +24,28 @@ function Login() { }, }); - const onLoginPress = (data: {id: string; password: string}) => { - if (data.id === 'hamster' && data.password === 'hamster@123') { + // const onLoginPress = (data: {id: string; password: string}) => { + // loginHandler(data, navigation); + // }; + + const loginHandler = async ( + data: {id: string; password: string}, + navigation: any, + ) => { + try { + const deviceToken = await AsyncStorage.getItem('deviceToken'); // Assuming you store the token + const response = await instance.post(`/user/login`, { + account_id: data.id, + password: data.password, + device_token: deviceToken, // Include the device token in the payload + }); + + await AsyncStorage.setItem('AccessToken', response.data.accessToken); + await AsyncStorage.setItem('RefreshToken', response.data.refreshToken); navigation.navigate('NavBar'); - } else { - Alert.alert('아이디 또는 비밀번호를 잘못 입력했습니다.'); + } catch (error) { + console.error('로그인 에러:', error); + Alert.alert('로그인 오류', '로그인이 실패했습니다.'); } }; @@ -65,7 +85,7 @@ function Login() { /> -