-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' of https://github.com/SPARCS-Service-Hackathon-20…
- Loading branch information
Showing
11 changed files
with
309 additions
and
101 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,19 @@ | ||
import React from 'react'; | ||
import { BrowserRouter, Routes, Route } from 'react-router-dom'; | ||
import "./tailwind.css"; | ||
import Splash from './pages/Splash'; | ||
import Login from './pages/Login'; | ||
import JoinWay from './pages/JoinWay'; | ||
import Join from './pages/Join'; | ||
import Home from './pages/Home'; | ||
import Alarm from './pages/Alarm'; | ||
import SearchPerson from './pages/SearchPerson'; | ||
import SearchPlace from './pages/SearchPlace'; | ||
import Store from './pages/Store'; | ||
import Videos from './pages/Videos'; | ||
import './tailwind.css'; | ||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; | ||
import Router from './routes/Router'; | ||
import { AuthProvider } from './api/auth'; | ||
|
||
const App: React.FC = () => { | ||
const queryClient = new QueryClient(); | ||
|
||
const App: React.FC = () => { | ||
return ( | ||
<BrowserRouter> | ||
<Routes> | ||
<Route path='/' element={<Splash />}/> | ||
<Route path='/Login' element={<Login/>}/> | ||
<Route path='/JoinWay' element={<JoinWay/>}/> | ||
<Route path='/Join' element={<Join/>}/> | ||
<Route path='/Home' element={<Home/>}/> | ||
<Route path='/Alarm' element={<Alarm/>}/> | ||
<Route path='/SearchPerson' element={<SearchPerson/>}/> | ||
<Route path='/SearchPlace' element={<SearchPlace/>}/> | ||
<Route path='/Store' element={<Store/>}/> | ||
<Route path='/Videos' element={<Videos/>}/> | ||
</Routes> | ||
</BrowserRouter> | ||
<QueryClientProvider client={queryClient}> | ||
<AuthProvider> | ||
<Router /> | ||
</AuthProvider> | ||
</QueryClientProvider> | ||
); | ||
}; | ||
|
||
export default App; | ||
export default App; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { useMutation } from '@tanstack/react-query'; | ||
import api from '.'; | ||
import { createContext, useContext } from 'react'; | ||
|
||
const loginByEmail = ({ | ||
email, | ||
password, | ||
}: { | ||
email: string; | ||
password: string; | ||
}) => | ||
api.post('/auth/email/login', { email, password }).then(({ data }) => ({ | ||
accessToken: data.accessToken as string, | ||
})); | ||
|
||
const useAuthProvider = () => { | ||
const { mutate: mutateByEmail, error: emailLoginError } = useMutation({ | ||
mutationFn: loginByEmail, | ||
}); | ||
return { loginByEmail: mutateByEmail, error: emailLoginError }; | ||
}; | ||
|
||
const authContext = createContext< | ||
ReturnType<typeof useAuthProvider> | undefined | ||
>(undefined); | ||
|
||
export const AuthProvider = ({ children }: React.PropsWithChildren) => { | ||
const value = useAuthProvider(); | ||
return <authContext.Provider value={value}>{children}</authContext.Provider>; | ||
}; | ||
|
||
// eslint-disable-next-line react-refresh/only-export-components | ||
export const useAuth = () => { | ||
const value = useContext(authContext); | ||
if (!value) | ||
throw new Error( | ||
'Cannot find AuthProvider. Please wrap your component with AuthProvider', | ||
); | ||
return value; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import axios from 'axios'; | ||
|
||
const api = axios.create({ baseURL: 'https://wayu.hackathon.sparcs.net/' }); | ||
|
||
export default api; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,75 @@ | ||
import { useEffect, useState } from 'react'; | ||
import Btn from './component/Btn'; | ||
import Input from './component/Input'; | ||
import LinkText from './component/LinkText'; | ||
import { useAuth } from '../api/auth'; | ||
|
||
export default function Login() { | ||
const [emailError, setEmailError] = useState<string>(); | ||
const [passwordError, setPasswordError] = useState<string>(); | ||
const { loginByEmail, error } = useAuth(); | ||
|
||
useEffect(() => { | ||
const message = error | ||
? '이메일 또는 비밀번호가 일치하지 않습니다' | ||
: undefined; | ||
setEmailError(message); | ||
setPasswordError(message); | ||
}, [error]); | ||
|
||
const login = (e: React.FormEvent<HTMLFormElement>) => { | ||
e.preventDefault(); | ||
const payload = { | ||
email: e.currentTarget.email.value, | ||
password: e.currentTarget.password.value, | ||
}; | ||
|
||
if (!payload.email) { | ||
setEmailError('이메일을 입력해주세요'); | ||
return; | ||
} | ||
setEmailError(undefined); | ||
if (!payload.password) { | ||
setPasswordError('비밀번호를 입력해주세요'); | ||
return; | ||
} | ||
setPasswordError(undefined); | ||
|
||
loginByEmail(payload); | ||
}; | ||
|
||
return ( | ||
<div className="mx-[10%] pt-[30%]"> | ||
<form onSubmit={login} className="mx-[10%] pt-[30%]"> | ||
<h3 className="text-3xl leading-[100px] text-center font-bold">로그인</h3> | ||
<Input type="text" text="아이디 또는 이메일주소" /> | ||
<Input type="password" text="비밀번호" /> | ||
<Input | ||
type="text" | ||
text="이메일주소" | ||
name="email" | ||
autoCapitalize="off" | ||
autoComplete="off" | ||
errorMessage={emailError} | ||
/> | ||
<Input | ||
type="password" | ||
text="비밀번호" | ||
name="password" | ||
errorMessage={passwordError} | ||
/> | ||
<LinkText | ||
className="leading-[30px] mb-[40px] justify-end" | ||
LinkMsg="비밀번호 재설정" | ||
to="/Login" | ||
/> | ||
<Btn text="로그인" className="bg-primary text-white" /> | ||
<Btn | ||
text="카카오톡으로 로그인하기" | ||
className="bg-[#F2DA00] text-[#282732] border border-[#E8E9EA]" | ||
to="/login" | ||
/> | ||
<Btn className="bg-primary text-white">로그인</Btn> | ||
<Btn className="bg-[#F2DA00] text-[#282732] border border-[#E8E9EA]"> | ||
카카오톡으로 로그인하기 | ||
</Btn> | ||
<LinkText | ||
className="leading-[80px] mb-[40px] justify-center" | ||
text="아직계정이 없으신가요?" | ||
LinkMsg="회원가입" | ||
to="/JoinWay" | ||
/> | ||
</div> | ||
</form> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,23 @@ | ||
import React from 'react'; | ||
|
||
type BtnProps = { | ||
text: string; | ||
className: string; | ||
action?: () => void; | ||
} | ||
className: string; | ||
}; | ||
|
||
const Btn: React.FC<BtnProps> = ({text, className, action}) => { | ||
return ( | ||
<div className={`w-[100%] h-[48px] mb-[10px] ${className} text-lg text-center leading-[48px] rounded-lg`}> | ||
{text} | ||
</div> | ||
); | ||
} | ||
const Btn = ({ | ||
children, | ||
className, | ||
...props | ||
}: React.PropsWithChildren<BtnProps> & | ||
React.ButtonHTMLAttributes<HTMLButtonElement>) => { | ||
return ( | ||
<button | ||
{...props} | ||
className={`w-[100%] h-[48px] mb-[10px] ${className} text-lg text-center leading-[48px] rounded-lg`} | ||
> | ||
{children} | ||
</button> | ||
); | ||
}; | ||
|
||
export default Btn; | ||
export default Btn; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,43 +1,70 @@ | ||
import React, { useState } from 'react'; | ||
|
||
type InputProps = { | ||
text: string; | ||
type: string; | ||
label?: string; | ||
className?: string; | ||
errorMsg?: string; | ||
condition?: string; | ||
action?: () => void; | ||
} | ||
text: string; | ||
type: string; | ||
label?: string; | ||
className?: string; | ||
errorMessage?: string; | ||
}; | ||
|
||
const Input: React.FC<InputProps> = ({ type, text, label, className, action, errorMsg, condition}) => { | ||
const [value, setValue] = useState<string>(''); | ||
const [typeInput, setTypeInput] = useState<string>(type); | ||
const Input = ({ | ||
type, | ||
text, | ||
label, | ||
className, | ||
errorMessage, | ||
...inputProps | ||
}: InputProps & React.InputHTMLAttributes<HTMLInputElement>) => { | ||
const [value, setValue] = useState<string>(''); | ||
const [typeInput, setTypeInput] = useState<string>(type); | ||
|
||
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { | ||
const newValue = event.target.value; | ||
setValue(newValue); | ||
} | ||
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { | ||
const newValue = event.target.value; | ||
setValue(newValue); | ||
}; | ||
|
||
const togglePasswordVisibility = () => { | ||
setTypeInput(typeInput === "text" ? "password" : "text"); | ||
} | ||
const togglePasswordVisibility = () => { | ||
setTypeInput(typeInput === 'text' ? 'password' : 'text'); | ||
}; | ||
|
||
return ( | ||
<div className={`${className}`}> | ||
{label && <h3 className='leading-[30px]'>{label}</h3>} | ||
<div className={` w-[100%] h-[48px] flex justify-between mb-[8px] pl-3 leading-[48px] rounded-lg border border-[#E5E5E5] bg-[#F7F8F9]`}> | ||
<input | ||
type={typeInput} | ||
value={value} | ||
onChange={handleChange} | ||
className={`${type=="text"? "w-[98%]": "w-[85%]"} h-[48px] text-base mb-[4px] outline-none placeholder-[#CECED1] bg-[#F7F8F9]`} | ||
placeholder={text} | ||
/> | ||
{type=="password"&& <button onClick={togglePasswordVisibility} className='bg-transparent outline-none h-[24px] w-[24px] m-auto'><img src={typeInput=="text" ? "/assets/show.png" : "/assets/hide.png"} alt="eye" className="object-cover w-full h-full" /></button>} | ||
</div> | ||
</div> | ||
); | ||
} | ||
return ( | ||
<div className={`${className} mb-[8px]`}> | ||
{label && <h3 className="leading-[30px]">{label}</h3>} | ||
<div | ||
className={`w-[100%] h-[48px] flex justify-between pl-3 leading-[48px] rounded-lg border border-[#E5E5E5] bg-[#F7F8F9]`} | ||
> | ||
<input | ||
{...inputProps} | ||
type={typeInput} | ||
value={value} | ||
onChange={handleChange} | ||
className={`${ | ||
type == 'text' ? 'w-[98%]' : 'w-[85%]' | ||
} h-[48px] text-base mb-[4px] outline-none placeholder-[#CECED1] bg-[#F7F8F9]`} | ||
placeholder={text} | ||
/> | ||
{type == 'password' && ( | ||
<button | ||
type="button" | ||
onClick={togglePasswordVisibility} | ||
className="bg-transparent outline-none h-[24px] w-[24px] m-auto" | ||
> | ||
<img | ||
src={ | ||
typeInput == 'text' ? '/assets/show.png' : '/assets/hide.png' | ||
} | ||
alt="eye" | ||
className="object-cover w-full h-full" | ||
/> | ||
</button> | ||
)} | ||
</div> | ||
{errorMessage && ( | ||
<p className="text-[#FF0000] text-sm leading-[24px]">{errorMessage}</p> | ||
)} | ||
</div> | ||
); | ||
}; | ||
|
||
export default Input; |
Oops, something went wrong.