Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link rel="icon" type="image/svg+xml" href="/w2cLogo.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
<title>W2C 問題集</title>
</head>
<body>
<div id="root"></div>
Expand Down
9 changes: 9 additions & 0 deletions public/w2cLogo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
52 changes: 38 additions & 14 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,50 @@
import React, { useState } from 'react'
import React, { useEffect, useState } from 'react'
import './App.css'
import {
createBrowserRouter,
createRoutesFromElements,
Navigate,
Outlet,
Route,
RouterProvider,
} from 'react-router-dom'
import Login from './pages/Login/page'
import Home from './pages/Home/page'
import Home from './pages/Home'
import NotFound from './pages/NotFound'
import Problems from './pages/Problems'
import CreateProblem from './pages/CreateProblem'
import CreateProblemDetail from './pages/CreateProblem/detail'
import Header from './components/Header/Header'
import Admin from './pages/Admin'
import Signup from './pages/Signup/page'
import Login from './pages/Login'
import Signup from './pages/Signup'
import { UserCookieFmt0001VO } from './models/entity/client/fmt/UserCookieFmt0001VO'
import { getCookie, getToken } from './utils/getCookie'

const RequireAuth: React.FC = () => {
const token = getToken('W2CToken')
return token ? <Outlet /> : <Navigate to="/login" replace />
}

const MainLayout: React.FC = () => {
const [state, setState] = useState<boolean>(true)
const [user, setUser] = useState<UserCookieFmt0001VO.Type | undefined>(
undefined,
)

useEffect(() => {
const userStr = getCookie('user')
const user: UserCookieFmt0001VO.Type = userStr
? JSON.parse(userStr)
: null

setUser(user)
}, [])

console.log(user)

return (
<main>
<Header void={() => setState(!state)} state={state} />
<Header void={() => setState(state)} state={state} />
<div
style={{
marginLeft: state ? '240px' : '0px',
Expand All @@ -42,15 +64,17 @@ const router = createBrowserRouter(
<>
<Route path="/login" element={<Login />} />
<Route path="/signup" element={<Signup />} />
<Route path="/" element={<MainLayout />}>
<Route path="/" element={<Home />} />
<Route path="/problem" element={<Problems />} />
<Route path="/createProblem" element={<CreateProblem />} />
<Route
path="/createProblem/detail"
element={<CreateProblemDetail />}
/>
<Route path="/admin" element={<Admin />} />
<Route element={<RequireAuth />}>
<Route path="/" element={<MainLayout />}>
<Route index element={<Home />} />
<Route path="problem" element={<Problems />} />
<Route path="createProblem" element={<CreateProblem />} />
<Route
path="createProblem/detail"
element={<CreateProblemDetail />}
/>
<Route path="admin" element={<Admin />} />
</Route>
</Route>
<Route path="/*" element={<NotFound />} />
</>,
Expand Down
16 changes: 16 additions & 0 deletions src/models/ApiType/Login/type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export namespace LoginApi {
export namespace POST {
export type Request = {
email: string
password: string
}
export type Response = {
token: string
id: number
email: string
name: string
role: string
class_name: string
}
}
}
16 changes: 16 additions & 0 deletions src/models/ApiType/Signup/type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export namespace SignupApi {
export namespace POST {
export type Request = {
name: string
email: string
password: string
role: string
class_name: string
}

export type Response = {
name: string
email: string
}
}
}
26 changes: 26 additions & 0 deletions src/models/entity/client/Users.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
export namespace UsersVO {
export type Type = {
id?: number
name: string
email: string
password_digest: string
role?: number
class_name?: number
created_at: string
updated_at: string
delete_flag: boolean
version: number
}

export function create(): UsersVO.Type {
return {
name: '',
email: '',
password_digest: '',
created_at: '',
updated_at: '',
delete_flag: false,
version: 0,
}
}
}
13 changes: 13 additions & 0 deletions src/models/entity/client/fmt/LoginFmt0001VO.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export namespace LoginFmt0001VO {
export type Type = {
email: string
password: string
}

export function create(): LoginFmt0001VO.Type {
return {
email: '',
password: '',
}
}
}
9 changes: 9 additions & 0 deletions src/models/entity/client/fmt/SignupFmt0001VO.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export namespace SignupFmt0001VO {
export type Type = {
name: string
email: string
password: string
role: string
class_name: string
}
}
9 changes: 9 additions & 0 deletions src/models/entity/client/fmt/UserCookieFmt0001VO.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export namespace UserCookieFmt0001VO {
export type Type = {
id: number
name: string
email: string
role: string
class_name: string
}
}
31 changes: 29 additions & 2 deletions src/pages/Home/page.tsx → src/pages/Home/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { getCookie } from '@/utils/getCookie'
import styles from './style.module.css'
import { useState } from 'react'
import { useEffect, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { UserCookieFmt0001VO } from '@/models/entity/client/fmt/UserCookieFmt0001VO'

export default function Home() {
const [filter, setFilter] = useState('stillAns')
const [userName, setUserName] = useState('')
const navigate = useNavigate()

const tasks = [
{
Expand Down Expand Up @@ -36,10 +41,21 @@ export default function Home() {
filter === 'all' ? true : task.status === filter,
)

useEffect(() => {
const userStr = getCookie('user')
const user: UserCookieFmt0001VO.Type = userStr
? JSON.parse(userStr)
: null

const name = user.name

setUserName(name)
}, [])

return (
<>
<div className={styles.content}>
<h1>平田晃大</h1>
<h1>{userName}</h1>
<div className={styles.filterNav}>
<div className={styles.filterWrap}>
<select name="genre" id="genreFilter">
Expand Down Expand Up @@ -108,6 +124,17 @@ export default function Home() {
</tbody>
</table>
</div>
<div className={styles.logoutBtn}>
<button
onClick={() => {
document.cookie = 'W2CToken=; path=/; max-age=0'
document.cookie = 'user=; path=/; max-age=0'
navigate('/login')
}}
>
ログアウト
</button>
</div>
</div>
</>
)
Expand Down
7 changes: 7 additions & 0 deletions src/pages/Home/style.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,10 @@
}
}

.logoutBtn {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
margin-top: 40px;
}
85 changes: 85 additions & 0 deletions src/pages/Login/action.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { ActionType } from './reducer'
import { LoginApi } from '@/models/ApiType/Login/type'
import { UserCookieFmt0001VO } from '@/models/entity/client/fmt/UserCookieFmt0001VO'
import { baseURL } from '@/utils/baseURL'
import type { NavigateFunction } from 'react-router-dom'

export namespace Action {
export async function editForm(
dispatch: React.Dispatch<ActionType>,
targetName: string,
value: any,
) {
dispatch({
type: 'EDIT_FORM',
payload: {
targetName,
value,
},
})
}

export async function logIn(
dispatch: React.Dispatch<ActionType>,
email: string,
password: string,
navigate: NavigateFunction,
) {
dispatch({ type: 'LOGIN_REQUEST' })

if (!email || !password) {
throw new Error('未入力項目があります')
}

try {
const json: LoginApi.POST.Request = {
email,
password,
}

const res = await fetch(`${baseURL}auth/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(json),
})

const result: LoginApi.POST.Response = await res.json()

dispatch({
type: 'LOGIN_SUCCESS',
payload: {
token: result.token,
id: result.id,
email: result.email,
name: result.name,
role: result.role,
class_name: result.class_name,
},
})

const maxAge = 60 * 60 * 24 * 7

document.cookie = `W2CToken=${result.token}; path=/; max-age=${maxAge}`

const userData: UserCookieFmt0001VO.Type = {
id: result.id,
name: result.name,
email: result.email,
role: result.role,
class_name: result.class_name,
}
document.cookie = `user=${encodeURIComponent(JSON.stringify(userData))}; path=/; max-age=${maxAge}`

navigate('/')
} catch (e) {
dispatch({ type: 'LOGIN_FAILURE' })
throw e
}
}

export async function ShowPass(dispatch: React.Dispatch<ActionType>) {
dispatch({ type: 'SHOW_PASS' })
}
}
Loading
Loading