Skip to content

Commit

Permalink
Merge pull request #106 from farmtedPlaydata/feature/#104
Browse files Browse the repository at this point in the history
Feature/#104
  • Loading branch information
JinDalgi authored Dec 29, 2023
2 parents 7d7c6e1 + f45e815 commit 278a260
Show file tree
Hide file tree
Showing 22 changed files with 769 additions and 508 deletions.
5 changes: 4 additions & 1 deletion front-service/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -395,4 +395,7 @@ FodyWeavers.xsd
*.msp

# JetBrains Rider
*.sln.iml
*.sln.iml

####
.env
789 changes: 406 additions & 383 deletions front-service/package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions front-service/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@types/styled-components": "^5.1.34",
"axios": "^1.6.2",
"bootstrap": "^5.3.2",
"dotenv": "^16.3.1",
"express": "^4.18.2",
"html-webpack-plugin": "^5.6.0",
"moment": "^2.29.4",
Expand Down
7 changes: 4 additions & 3 deletions front-service/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import React from "react";
import styled, { createGlobalStyle } from "styled-components"
import {BrowserRouter as Router} from 'react-router-dom';
import Main from "./components/Main";
import UserRouteController from "./components/user/userRoute/UserRouteController";
import Sidebar from "./components/sidebar/sidebar";
import BiddingList from "./components/bidding/biddingList/BiddingList";

const GlobalStyle = createGlobalStyle`
body{
Expand All @@ -15,11 +13,14 @@ const GlobalStyle = createGlobalStyle`
flex-direction: column;
}
`


const App = () => (
<Router>
<Sidebar />
<GlobalStyle/>
<Main/>
{/*<BiddingList/>*/}
<Main/>
</Router>
);

Expand Down
7 changes: 6 additions & 1 deletion front-service/src/Login.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// src/components/LoginPage.tsx
import React from 'react';
import styled from 'styled-components';
import {Link} from "react-router-dom";



Expand Down Expand Up @@ -133,7 +134,11 @@ const LoginPage: React.FC = () => {
<Button>계속</Button>
<SignupButton>회원가입</SignupButton>
<div style={{margin:'20px 0px'}}>────── 또는 ──────</div>
<Button1><img src="/icons/google-icon.png" alt="Icon" />Google로 계속</Button1>
<Button1>
<Link to = "/oauth2/authorization/google" />
<img src="/icons/google-icon.png" alt="Icon" />
Google로 계속
</Button1>
<Button2><img src="/icons/kakaotalk-icon.png" alt="Icon" />Kakao Talk로 계속</Button2>
</LoginForm>
</Container>
Expand Down
3 changes: 1 addition & 2 deletions front-service/src/components/Main.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import React from "react"
import BoardRouteController from "./board/boardRoute/BoardRouteController"
import UserRouteController from "./user/userRoute/UserRouteController";

const Main = () => {
return (
<>

<BoardRouteController />
{/*<UserRouteController />*/}
</>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,21 @@ import BoardDetail from "../boardDetail/BoardDetail"
import Authentication from "../../user/authentication";
import BiddingList from "../../bidding/biddingList/BiddingList"
import Sidebar from "../../sidebar/sidebar";
import User from "../../user/loginedUser";

const BoardRouteController = () => {
return(

<>
<Routes>
<Route path="/" element={<BoardBody/>}>
<Route path='/boards' element={<BoardMain />} />
<Route path='/' element={<BoardMain />} />
<Route path='/bidding' element={<BiddingList/>}/>
<Route path='/' element={<Authentication />} />
<Route path='/auth' element={<Authentication />} />
<Route path="/boards/write" element={<CreateBoard/>}/>
<Route path="/boards/:boardUUID" element={<BoardDetail />}/>
<Route path="/boards/writer/:writerUuid" element={<BoardMain/>}/>
<Route path='mypage' element={<User />} />
</Route>
</Routes>
</>
Expand Down
1 change: 1 addition & 0 deletions front-service/src/components/inputbox/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ interface Props {
errorMessage?: string;
onKeyDown?: (event: KeyboardEvent<HTMLInputElement>) => void;
onButtonClick?: () => void;
onChange?: ChangeEvent;
}

// component: Input 상자 컴포넌트 //
Expand Down
8 changes: 8 additions & 0 deletions front-service/src/components/sidebar/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {useNavigate} from "react-router-dom";
import {Button, ButtonGroup} from "react-bootstrap";
import './sidebarStyle.css';


const Sidebar = () => {

const navigator = useNavigate();
Expand All @@ -23,6 +24,10 @@ const Sidebar = () => {
const handleBoardDetailClick = () => {
navigator(`/boards/firstBoardUUID`);
};
const handleMyPageClick = () => {
navigator(`/mypage`);
};


return (
<Accordion className='flex-accordion'>
Expand All @@ -43,6 +48,9 @@ const Sidebar = () => {
<Button variant="primary" size="sm" onClick={handleAuthenticationClick} className="mb-2">
인증 페이지로 이동
</Button>
<Button variant="primary" size="sm" onClick={handleMyPageClick} className="mb-2">
마이 페이지로 이동
</Button>
</ButtonGroup>
</Accordion.Body>
</Accordion.Item>
Expand Down
9 changes: 0 additions & 9 deletions front-service/src/components/sidebar/sidebarStyle.css
Original file line number Diff line number Diff line change
@@ -1,12 +1,3 @@
.flex-accordion {
display: flex;
flex-direction: column;
}

.flex-accordion .accordion-item {
flex: 1;
}

.flex-accordion .accordion-body {
flex: 1;
}
113 changes: 70 additions & 43 deletions front-service/src/components/user/authentication/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import './style.css';
import useUserStore from "../store/user.store";
import {useCookies} from "react-cookie";
import {useRef, useState, KeyboardEvent, ChangeEvent} from "react";
import {useNavigate} from "react-router-dom";
import {Link, useNavigate} from "react-router-dom";
import React from "react";
import {SignInRequestDto, SignUpRequestDto} from "../dto/request";
import Swal from "sweetalert2";
import InputBox from "../../inputbox";
import {Address, useDaumPostcodePopup} from "react-daum-postcode";
import userLoginUserStore from "../store/user.store";



Expand All @@ -16,14 +16,15 @@ import {Address, useDaumPostcodePopup} from "react-daum-postcode";
export default function Authentication() {

// state: 로그인 유저 전역 상태 //
const {user, setUser} = useUserStore();
const {loginUser, setLoginUser} = userLoginUserStore();
// state: 쿠키 상태 //
const [cookies, setCookie] = useCookies();
// state: 화면 상태 //
const [view, setView] = useState<'sign-in' | 'sign-up'>('sign-in');
// state: UUID 상태 //
const [uuid, setUuid] = useState<string | null>(null);

// state: 페이지 번호 상태 //
const [page, setPage] = useState<1 | 2>(1);

// function: 네비게이트 함수 //
const navigator = useNavigate();
Expand Down Expand Up @@ -74,22 +75,40 @@ export default function Authentication() {
const SIGN_IN_ENDPOINT = '/api/pass-service/login';

const response = await fetch(SIGN_IN_ENDPOINT, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(requestBody),
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(requestBody),
}
).then(response=>{
const uuidFromHeader = response.headers.get("UUID");
setUuid(uuidFromHeader);
navigator("/boards");
}
).then(
()=>{ navigator("/bidding");}
);
)
};

// event handler: 회원가입 링크 클릭 이벤트 처리 //
const onSignUpLinkClickHandler = () => {
setView('sign-up');
}

// event handler: 구글 로그인 클릭 이벤트 처리 //
const onGoogleButtonClickHandler = () => {

const CLIENT_ID = process.env.REACT_APP_CLIENT_ID;
const REDIRECT_URI = process.env.REACT_APP_REDIRECT_URI;
window.location.href = 'https://accounts.google.com/o/oauth2/v2/auth?client_id=' +
CLIENT_ID + '&redirect_uri=' + REDIRECT_URI + '&response_type=code&scope=email profile';

setPage(2);
setView('sign-up');
}




// render: sign in 카드 컴포넌트 렌더링 //
return (
<div className='auth-card'>
Expand All @@ -109,6 +128,10 @@ export default function Authentication() {
</div>
)}
<div className='auth-button' onClick={onSignInButtonClickHandler}>{'로그인'}</div>
<div className='auth-button' onClick={onGoogleButtonClickHandler}>
<img src="/icons/google-icon.png" alt="Icon" />
Google로 계속
</div>
<div className='auth-description-box'>
<div className='auth-description'>{'신규 사용자이신가요? '}<span className='description-emphasis' onClick={onSignUpLinkClickHandler}>{'회원가입'}</span></div>
</div>
Expand All @@ -120,8 +143,6 @@ export default function Authentication() {
// component: sign up 카드 컴포넌트 //
const SignUpCard = () => {

// state: 페이지 번호 상태 //
const [page, setPage] = useState<1 | 2>(1);

// state: 이메일 상태 //
const [email, setEmail] = useState<string>('');
Expand Down Expand Up @@ -182,31 +203,15 @@ export default function Authentication() {
const [consentError, setConsentError] = useState<boolean>(false);

// state: 프로필 이미지 상태 //
const [profileImage, setProfileImage] = useState<File | null>(null);

const [profileImage, setProfileImage] = useState<File | string>('');

const fileToString = (file: File | null): Promise<string | null> => {
return new Promise((resolve, reject) => {
if (!file) {
resolve(null);
} else {
const reader = new FileReader();
reader.onloadend = () => {
const result = reader.result as string;
resolve(result);
};
reader.onerror = reject;
reader.readAsDataURL(file);
}
});
};

// event handler: 프로필 이미지 이벤트 처리 //
const profileImageChange = (e: ChangeEvent<HTMLInputElement>) => {
if (e.target.files) {
setProfileImage(e.target.files[0]);
} else {
setProfileImage(null);
setProfileImage('https://framted-product.s3.ap-northeast-2.amazonaws.com/profile.png');
}
};

Expand Down Expand Up @@ -294,12 +299,14 @@ export default function Authentication() {
body: JSON.stringify(requestBody),
}).then(response => {
if (response.ok) {
const uuidFromHeader = response.headers.get("UUID");
setUuid(uuidFromHeader);
return response.text();
} else {
throw new Error('회원 정보 작성에 실패했습니다.');
}
}).then(() => {
navigator("/");
setPage(2);
})
.catch(()=>{
Swal.fire({
Expand All @@ -322,6 +329,19 @@ export default function Authentication() {
setMemberAddressErrorMessage('');
setConsentError(false);

// description: 이메일 여부 확인 //
const checkedEmail = email.trim().length === 0;
if (checkedEmail) {
setEmailError(true);
setEmailErrorMessage('이메일을 확일할 수 없습니다.');
}

// description: UUID 여부 확인 //
const checkedUuid = uuid?.trim().length === 0;
if (checkedUuid) {
alert('uuid를 확인할 수 없습니다.');
}

// description: 이름 입력 여부 확인 //
const checkedmemberName = memberName.trim().length === 0;
if (checkedmemberName) {
Expand All @@ -345,28 +365,35 @@ export default function Authentication() {
// description: 개인정보동의 여부 확인 //
if (!consent) setConsentError(true);

var myHeaders = new Headers();

const formData = new FormData();
formData.append("IMAGE", profileImage);

if (checkedmemberName || checkedmemberPhone || checkedmemberAddress || !consent) return;

const requestBody: SignUpRequestDto = {
email, uuid,
profileImage: profileImage ? await fileToString(profileImage) : undefined ?? null,
memberAddress, memberName, memberPhone, memberAddressDetail, consent};
memberAddress, memberName,
memberPhone, memberAddressDetail,
consent};
const data = new Blob([JSON.stringify(requestBody)], {type: "application/json"})
formData.append("CREATE", data);

const DETAILS_ENDPOINT = '/api/member-service/members';

fetch(DETAILS_ENDPOINT, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(requestBody),
headers: myHeaders,
body: formData,
}).then(response => {
if (response.ok) {
return response.text();
return response.json();
} else {
throw new Error('회원 정보 작성에 실패했습니다.');
}
});
navigator('/');
}


Expand All @@ -383,14 +410,14 @@ export default function Authentication() {
<InputBox label='이메일 주소*' type='text' placeholder='이메일 주소를 입력해주세요.' value={email} setValue={setEmail} error={emailError} errorMessage={emailErrorMessage} />
<InputBox label='비밀번호*' type={passwordType} placeholder='비밀번호를 입력해주세요.' value={password} setValue={setPassword} icon={passwordIcon} error={passwordError} errorMessage={passwordErrorMessage} onButtonClick={onPasswordIconClickHandler} />
<InputBox label='비밀번호 확인*' type={passwordCheckType} placeholder='비밀번호를 다시 입력해주세요.' value={passwordCheck} setValue={setPasswordCheck} icon={passwordCheckIcon} error={passwordCheckError} errorMessage={passwordCheckErrorMessage} onButtonClick={onPasswordCheckIconClickHandler} />
<div className='auth-button' onClick={onSignUpButtonClickHandler}>{'회원가입'}</div>
<div className='auth-button' onClick={onSignUpButtonClickHandler}>{'다음으로'}</div>
</>)}
{page === 2 && (<>
<InputBox label='이름*' type='text' placeholder='이름을 입력해주세요.' value={memberName} setValue={setmemberName} error={memberNameError} errorMessage={memberNameErrorMessage} />
<InputBox label='전화번호*' type='text' placeholder='전화번호를 입력해주세요.' value={memberPhone} setValue={setmemberPhone} error={memberPhoneError} errorMessage={telNumbeErrorMessage} />
<InputBox label='프로필 이미지 설정' type={'text'} error={false} placeholder={'프로필 이미지를 설정할 수 있습니다.'} value={profileImage} setValue={setProfileImage} />
<InputBox label='주소*' type='text' placeholder='우편번호 찾기' value={memberAddress} setValue={setMemberAddress} icon='right-arrow-icon' error={memberAddressError} errorMessage={memberAddressErrorMessage} onButtonClick={onmemberAddressIconClickHandler} />
<InputBox label='상세 주소' type='text' placeholder='상세 주소를 입력해주세요.' value={memberAddressDetail} setValue={setMemberAddressDetail} error={false} />
<input type='file' accept='.png, .jpg, .jpeg' onChange={profileImageChange} />
</>)}
</div>
<div className='auth-card-bottom'>
Expand All @@ -402,7 +429,7 @@ export default function Authentication() {
<div className={consentError ? 'auth-consent-title-error' : 'auth-consent-title'}>{'개인정보동의'}</div>
<div className='auth-consent-link'>{'더보기>'}</div>
</div>
<div className='auth-button' onClick={onSignUpButtonClickHandler}>{'회원가입'}</div>
<div className='auth-button' onClick={onDetailsButtonClickHandler}>{'회원가입'}</div>
</>)}
<div className='auth-description-box'>
<div className='auth-description'>{'이미 계정이 있으신가요? '}<span className='description-emphasis' >{'로그인'}</span></div>
Expand Down
Loading

0 comments on commit 278a260

Please sign in to comment.