diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx index 1103426..1fc3cf3 100644 --- a/src/components/Header/index.tsx +++ b/src/components/Header/index.tsx @@ -1,13 +1,16 @@ import React from "preact/compat"; import { useState } from "preact/hooks"; import './style.css'; +import { useSelector } from "react-redux"; +import { UserRootState } from "../../store/type"; function Header() { - const [searchVal, setSearchVal] = useState(''); const [dropdown, setDropdown] = useState(false); + const user = useSelector((state: UserRootState) => state.auth) + const onInput = (e: React.ChangeEvent): void => { const val = e.target as HTMLInputElement; setSearchVal(val.value) @@ -33,18 +36,25 @@ function Header() {

Hilingin

-
- -
- @@ -58,7 +68,7 @@ function Header() { Stories News / Events Forum - Sign in + {user.username ? user.username : 'Sign in'} ) diff --git a/src/components/Header/style.css b/src/components/Header/style.css index 7ce784d..88f3214 100644 --- a/src/components/Header/style.css +++ b/src/components/Header/style.css @@ -37,6 +37,11 @@ margin-left: 0; } + div.user-img { + display: block; + margin-left: auto; + } + button.dropdown-menu { display: block; } @@ -66,9 +71,6 @@ display: none; } -.search-input { - margin-left: auto; -} label { position: relative; @@ -114,4 +116,12 @@ label:before { /* display: 'inline-block'; max-width: '100%'; text-align: 'center'; */ +} + +.search-input { + margin-left: auto; +} + +.user-img { + display: none; } \ No newline at end of file diff --git a/src/constants/api.ts b/src/constants/api.ts index 6adaff8..28576ee 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -1,6 +1,7 @@ const BASE_URL = "http://localhost:8888" const SIGNUP_URI = `${BASE_URL}/user/signup` +const LOGIN_URI = `${BASE_URL}/user/login` const GET_LIST_LOCATIONS_URI = `${BASE_URL}/locations`; @@ -14,6 +15,7 @@ const GET_IMAGES_BY_LOCATION_URI = `${BASE_URL}/images/location` export { BASE_URL, SIGNUP_URI, + LOGIN_URI, GET_LIST_RECENT_LOCATIONS_RATING_URI, GET_LIST_TOP_LOCATIONS, GET_LIST_LOCATIONS_URI, diff --git a/src/index.css b/src/index.css index ee0e987..9663783 100644 --- a/src/index.css +++ b/src/index.css @@ -18,6 +18,13 @@ -webkit-text-size-adjust: 100%; } +input:focus { + outline: none; +} + +a:hover { + cursor: pointer; +} /* a { font-weight: 500; color: #646cff; diff --git a/src/pages/Login/index.css b/src/pages/Login/index.css new file mode 100644 index 0000000..6e7d2e7 --- /dev/null +++ b/src/pages/Login/index.css @@ -0,0 +1,4 @@ +input { + padding: 5px; + font-size: 14px; +} \ No newline at end of file diff --git a/src/pages/Login/index.tsx b/src/pages/Login/index.tsx new file mode 100644 index 0000000..a47ba43 --- /dev/null +++ b/src/pages/Login/index.tsx @@ -0,0 +1,104 @@ +import { ChangeEvent, TargetedEvent, useState } from "preact/compat"; +import { createAccountService, loginService } from "../../services"; +import { useNavigate } from "react-router-dom"; +import { useDispatch } from "react-redux"; +import { authAdded } from "../../features/auth/authSlice/authSlice"; +import './index.css'; + +function Login() { + const dispatch = useDispatch(); + const [form, setFrom] = useState({ + username: '', + password: '' + }) + + const [errorMsg, setErrorMsg] = useState([{ + field: '', + msg: '' + }]) + + const navigation = useNavigate() + + async function handleSignIn(e: TargetedEvent) { + e.preventDefault(); + try { + const res = await loginService({username: form.username, password: form.password}) + if (res.error) { + setErrorMsg(res.error.response.data.errors) + return + } + dispatch(authAdded(res.data)) + // localStorage.setItem("user", JSON.stringify(res.data)) + navigation("/") + } catch(err) { + console.log(err) + } + } + + async function handleSignUp(e: TargetedEvent) { + e.preventDefault(); + try { + const res = await createAccountService({ + username: form.username, + password: form.password + }) + + if(res.error) { + setErrorMsg(res.error.response.data.errors) + return; + } + console.log(res.data) + } catch (err) { + alert(err) + } + } + + function onChangeInput(e: ChangeEvent) { + const val = e.target as HTMLInputElement; + setFrom({ ...form, [val.placeholder]: val.value }) + + } + + return ( +
+

Sign in

+
+ + + + + + + + + + + +
username:
password:
+ Forgout account ? + +
+

Create Account

+
+ + + + + + + + + + + +
username:
password:
+ {errorMsg.map(x => ( +

{x.msg}

+ ))} + +
+
+ ) +} + +export default Login; \ No newline at end of file diff --git a/src/pages/index.tsx b/src/pages/index.tsx index f81cbe4..7dc3a56 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -4,8 +4,11 @@ import Discovery from "./Discovery"; import Story from "./Stories"; import NewsEvent from "./NewsEvents"; import LocationDetail from "./LocationDetail"; +import Login from './Login'; export { + Login, + Home, BestLocation, diff --git a/src/services/auth.ts b/src/services/auth.ts new file mode 100644 index 0000000..7b1a43e --- /dev/null +++ b/src/services/auth.ts @@ -0,0 +1,47 @@ +import { AxiosError } from "axios"; +import { LOGIN_URI, SIGNUP_URI } from "../constants/api"; +import { client } from "./config"; + +const initialState: IEmptyResponseState = { + data: null, + error: AxiosError +} + +interface IAuthentication { + username: String + password: String +} + +async function createAccountService({ username, password }: IAuthentication) { + const newState = { ...initialState }; + const url = `${SIGNUP_URI}` + try { + const response = await client({ method: 'POST', url: url, data: { username, password } }) + newState.data = response.data + newState.error = null + return newState + } catch (error) { + newState.error = error + return newState + } +} + +async function loginService({ username, password }: IAuthentication) { + const newState = { ...initialState }; + const url = `${LOGIN_URI}` + try { + const response = await client({ method: 'POST', url: url, data: { username, password } }) + newState.data = response.data + newState.error = null + return newState + } catch (error) { + newState.error = error + return newState + } + +} + +export { + loginService, + createAccountService +}; \ No newline at end of file diff --git a/src/services/index.ts b/src/services/index.ts index 78f3560..1339cf7 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -7,8 +7,12 @@ import { } from "./locations"; import { getImagesByLocationService } from "./images" +import { createAccountService, loginService } from "./auth"; export { + createAccountService, + loginService, + getListLocationsService, getListRecentLocationsRatingsService, getListTopLocationsService, diff --git a/src/types/common.ts b/src/types/common.ts index a32d500..12044c5 100644 --- a/src/types/common.ts +++ b/src/types/common.ts @@ -5,3 +5,9 @@ interface GetRequestPagination { page: number, page_size: number, } + + +interface IEmptyResponseState { + data: unknown, + error: any, +}; \ No newline at end of file