Merged PR 12: タスク 1465: 画面実装(アカウント作成画面)
## 概要 [Task: 1465](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/OMDSDictation/_sprints/taskboard/OMDSDictation%20%E3%83%81%E3%83%BC%E3%83%A0/OMDSDictation/%E3%82%B9%E3%83%97%E3%83%AA%E3%83%B3%E3%83%88%204-1?workitem=1465) - アカウント登録 ## レビューポイント - ## UIの変更 - https://ndstokyo.sharepoint.com/:f:/r/sites/Piranha/Shared%20Documents/General/OMDS/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88/Task1465?csf=1&web=1&e=bHB7XJ ## 動作確認状況 - 型チェック - ローカルで動作確認 ## 補足
@ -4,3 +4,4 @@ build/
|
|||||||
jest.config.js
|
jest.config.js
|
||||||
vite.config.ts
|
vite.config.ts
|
||||||
.env.local
|
.env.local
|
||||||
|
|
||||||
|
|||||||
2262
dictation_client/package-lock.json
generated
@ -46,7 +46,6 @@
|
|||||||
"redux-mock-store": "^1.5.4",
|
"redux-mock-store": "^1.5.4",
|
||||||
"redux-thunk": "^2.4.1",
|
"redux-thunk": "^2.4.1",
|
||||||
"sass": "^1.58.3",
|
"sass": "^1.58.3",
|
||||||
"styled-components": "^5.3.5",
|
|
||||||
"typescript": "^4.7.4",
|
"typescript": "^4.7.4",
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
},
|
},
|
||||||
@ -59,7 +58,6 @@
|
|||||||
"@types/react": "^18.0.0",
|
"@types/react": "^18.0.0",
|
||||||
"@types/react-dom": "^18.0.0",
|
"@types/react-dom": "^18.0.0",
|
||||||
"@types/redux-mock-store": "^1.0.3",
|
"@types/redux-mock-store": "^1.0.3",
|
||||||
"@types/styled-components": "^5.1.25",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^5.30.5",
|
"@typescript-eslint/eslint-plugin": "^5.30.5",
|
||||||
"@typescript-eslint/parser": "^5.30.5",
|
"@typescript-eslint/parser": "^5.30.5",
|
||||||
"@vitejs/plugin-react": "^1.3.0",
|
"@vitejs/plugin-react": "^1.3.0",
|
||||||
@ -75,8 +73,9 @@
|
|||||||
"license-checker": "^25.0.1",
|
"license-checker": "^25.0.1",
|
||||||
"prettier": "^2.7.1",
|
"prettier": "^2.7.1",
|
||||||
"redux-mock-store": "^1.5.4",
|
"redux-mock-store": "^1.5.4",
|
||||||
|
"sass": "^1.58.3",
|
||||||
"typescript": "^4.7.4",
|
"typescript": "^4.7.4",
|
||||||
"vite": "^2.9.9",
|
"vite": "^4.1.4",
|
||||||
"vite-plugin-env-compatible": "^1.1.1",
|
"vite-plugin-env-compatible": "^1.1.1",
|
||||||
"vite-plugin-sass-dts": "^1.3.1",
|
"vite-plugin-sass-dts": "^1.3.1",
|
||||||
"vite-tsconfig-paths": "^3.5.0"
|
"vite-tsconfig-paths": "^3.5.0"
|
||||||
|
|||||||
@ -1,17 +1,18 @@
|
|||||||
import { Route, Routes } from "react-router-dom";
|
import { Route, Routes } from "react-router-dom";
|
||||||
import styled from "styled-components";
|
|
||||||
import TopPage from "pages/TopPage";
|
import TopPage from "pages/TopPage";
|
||||||
import LoginPage from "pages/LoginPage";
|
import LoginPage from "pages/LoginPage";
|
||||||
import SamplePage from "pages/SamplePage";
|
import SamplePage from "pages/SamplePage";
|
||||||
import { AuthErrorPage } from "pages/ErrorPage";
|
import { AuthErrorPage } from "pages/ErrorPage";
|
||||||
import { NotFoundPage } from "pages/ErrorPage/notFound";
|
import { NotFoundPage } from "pages/ErrorPage/notFound";
|
||||||
import { RouteAuthGuard } from "components/auth/routeAuthGuard";
|
import { RouteAuthGuard } from "components/auth/routeAuthGuard";
|
||||||
|
import SignupPage from "pages/SignupPage";
|
||||||
|
|
||||||
const AppRouter: React.FC = () => (
|
const AppRouter: React.FC = () => (
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={<TopPage />} />
|
<Route path="/" element={<TopPage />} />
|
||||||
<Route path="/login" element={<LoginPage />} />
|
<Route path="/login" element={<LoginPage />} />
|
||||||
<Route path="/AuthError" element={<AuthErrorPage />} />
|
<Route path="/AuthError" element={<AuthErrorPage />} />
|
||||||
|
<Route path="/signup" element={<SignupPage completeTo="/" />} />
|
||||||
<Route
|
<Route
|
||||||
path="/XXX"
|
path="/XXX"
|
||||||
element={<RouteAuthGuard component={<SamplePage />} />}
|
element={<RouteAuthGuard component={<SamplePage />} />}
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
import { configureStore, ThunkAction, Action } from "@reduxjs/toolkit";
|
import { configureStore, ThunkAction, Action } from "@reduxjs/toolkit";
|
||||||
import login from "features/login/loginSlice";
|
import login from "features/login/loginSlice";
|
||||||
import auth from "features/auth/authSlice";
|
import auth from "features/auth/authSlice";
|
||||||
|
import signup from "features/signup/signupSlice";
|
||||||
|
|
||||||
export const store = configureStore({
|
export const store = configureStore({
|
||||||
reducer: {
|
reducer: {
|
||||||
login,
|
login,
|
||||||
auth,
|
auth,
|
||||||
|
signup,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
15
dictation_client/src/assets/images/account_circle.svg
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 27.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
|
||||||
|
y="0px" viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#A5A5A5;}
|
||||||
|
</style>
|
||||||
|
<path class="st0" d="M11.1,35.2c2.1-1.3,4.2-3.3,6.2-4s4.3-1.5,6.7-1.5s4.6,0.8,6.7,1.5s4.2,2.7,6.2,4c1.5-1.8,2.5-3.6,3.1-5.4
|
||||||
|
C40.7,28,41,26,41,24c0-4.8-1.6-8.9-4.9-12.1S28.8,7,24,7s-8.9,1.6-12.1,4.9S7,19.2,7,24c0,2,0.3,4,1,5.8
|
||||||
|
C8.6,31.6,9.6,33.5,11.1,35.2z M24,27.1c-2.1,0-3.9-0.7-5.3-2.1c-1.4-1.4-2.2-3.1-2.2-5.2s0.7-3.8,2.2-5.2s3.2-2.1,5.3-2.1
|
||||||
|
s3.9,0.7,5.3,2.1s2.2,3.1,2.2,5.2s-0.7,3.8-2.2,5.2C27.9,26.5,26.1,27.1,24,27.1z M24,44c-2.8,0-5.4-0.5-7.8-1.6
|
||||||
|
c-2.4-1-4.6-2.5-6.4-4.3c-1.8-1.8-3.2-3.9-4.3-6.4c-1-2.4-1.6-5-1.6-7.8s0.5-5.4,1.6-7.8c1-2.4,2.5-4.5,4.3-6.3s3.9-3.2,6.4-4.3
|
||||||
|
c2.4-1,5-1.6,7.8-1.6s5.4,0.5,7.8,1.6c2.4,1.1,4.5,2.5,6.3,4.3s3.2,3.9,4.3,6.4c1.1,2.4,1.6,5,1.6,7.8s-0.5,5.3-1.6,7.8
|
||||||
|
c-1,2.4-2.5,4.5-4.3,6.4s-3.9,3.2-6.4,4.3C29.4,43.5,26.8,44,24,44z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
@ -1,7 +1 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?><svg id="_レイヤー_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><defs><style>.cls-1{fill:#fff;}</style></defs><path class="cls-1" d="m16,32l-2.1-2.1,12.4-12.4H0v-3h26.2L13.9,2.1l2.1-2.1,16,16-16,16Z"/></svg>
|
||||||
<svg id="_レイヤー_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
|
||||||
<defs>
|
|
||||||
<style>.cls-1{fill:#fff;}</style>
|
|
||||||
</defs>
|
|
||||||
<path class="cls-1" d="m16,32l-2.1-2.1,12.4-12.4H0v-3h26.2L13.9,2.1l2.1-2.1,16,16-16,16Z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 277 B After Width: | Height: | Size: 262 B |
15
dictation_client/src/assets/images/badge.svg
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 27.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
|
||||||
|
y="0px" viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#282828;}
|
||||||
|
</style>
|
||||||
|
<path class="st0" d="M7,44c-0.8,0-1.5-0.3-2.1-0.9C4.3,42.5,4,41.8,4,41V17c0-0.8,0.3-1.5,0.9-2.1C5.5,14.3,6.2,14,7,14h11.9V7
|
||||||
|
c0-0.8,0.3-1.5,0.9-2.1S21.1,4,21.9,4h4.4c0.8,0,1.5,0.3,2.1,0.9c0.6,0.6,0.9,1.3,0.9,2.1v7H41c0.8,0,1.5,0.3,2.1,0.9
|
||||||
|
c0.6,0.6,0.9,1.3,0.9,2.1v24c0,0.8-0.3,1.5-0.9,2.1C42.5,43.7,41.8,44,41,44H7z M11.6,35.7h12V35c0-0.6-0.2-1.1-0.5-1.6
|
||||||
|
c-0.3-0.5-0.7-0.8-1.1-0.9c-1.1-0.4-1.9-0.6-2.5-0.7c-0.6-0.1-1.2-0.2-1.8-0.2c-0.6,0-1.3,0.1-2,0.2c-0.7,0.1-1.5,0.4-2.4,0.7
|
||||||
|
c-0.5,0.2-0.9,0.5-1.2,0.9c-0.3,0.5-0.4,1-0.4,1.6V35.7z M28.4,32.3h8.5v-2.5h-8.5V32.3z M17.7,29.8c0.8,0,1.4-0.3,1.9-0.8
|
||||||
|
c0.5-0.5,0.8-1.2,0.8-1.9s-0.3-1.4-0.8-1.9c-0.5-0.5-1.2-0.8-1.9-0.8c-0.8,0-1.4,0.3-1.9,0.8c-0.5,0.5-0.8,1.2-0.8,1.9
|
||||||
|
s0.3,1.4,0.8,1.9C16.3,29.5,16.9,29.8,17.7,29.8z M28.4,26.6h8.5v-2.5h-8.5V26.6z M21.9,17h4.4V7h-4.4V17z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
15
dictation_client/src/assets/images/check_circle.svg
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 27.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
|
||||||
|
y="0px" viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#A5A5A5;}
|
||||||
|
</style>
|
||||||
|
<path class="st0" d="M21,28.5l-4.9-4.9c-0.3-0.3-0.7-0.5-1.1-0.5s-0.8,0.2-1.1,0.5c-0.3,0.3-0.5,0.7-0.5,1.1c0,0.4,0.2,0.8,0.5,1.1
|
||||||
|
L20,32c0.3,0.3,0.6,0.5,1,0.5s0.7-0.1,1-0.5l12-12c0.3-0.3,0.4-0.7,0.4-1.1c0-0.4-0.2-0.8-0.5-1.1c-0.3-0.3-0.7-0.5-1.1-0.5
|
||||||
|
c-0.4,0-0.8,0.2-1.2,0.5L21,28.5z M24,44c-2.8,0-5.5-0.5-7.9-1.5c-2.4-1-4.6-2.4-6.4-4.2s-3.2-3.9-4.2-6.4S4,26.8,4,24
|
||||||
|
c0-2.8,0.5-5.4,1.5-7.9S8,11.6,9.8,9.8s3.9-3.2,6.4-4.2S21.2,4,24,4c2.8,0,5.4,0.5,7.9,1.6s4.5,2.4,6.4,4.2c1.8,1.8,3.2,3.9,4.2,6.3
|
||||||
|
s1.5,5,1.5,7.9c0,2.8-0.5,5.5-1.5,7.9s-2.5,4.6-4.2,6.4c-1.8,1.8-3.9,3.2-6.4,4.2C29.4,43.5,26.8,44,24,44z M24,41
|
||||||
|
c4.8,0,8.9-1.6,12.1-4.9S41,28.8,41,24s-1.6-8.9-4.9-12.1S28.8,7,24,7s-8.9,1.6-12.1,4.9S7,19.2,7,24s1.6,8.9,4.9,12.1
|
||||||
|
S19.2,41,24,41z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
12
dictation_client/src/assets/images/check_circle_fill.svg
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 27.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
|
||||||
|
y="0px" viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#00B4AA;}
|
||||||
|
</style>
|
||||||
|
<path class="st0" d="M21,33.1L35.2,19l-2.3-2.2L21.1,28.6l-6-6l-2.2,2.2L21,33.1z M24,44c-2.7,0-5.3-0.5-7.8-1.6
|
||||||
|
c-2.4-1-4.6-2.5-6.4-4.3s-3.2-3.9-4.3-6.4S4,26.7,4,24c0-2.8,0.5-5.4,1.6-7.8s2.5-4.5,4.3-6.4s3.9-3.2,6.4-4.3S21.3,4,24,4
|
||||||
|
c2.8,0,5.4,0.5,7.8,1.6s4.6,2.5,6.3,4.3c1.8,1.8,3.2,3.9,4.3,6.4c1.1,2.4,1.6,5,1.6,7.8c0,2.7-0.5,5.3-1.6,7.8
|
||||||
|
c-1,2.4-2.5,4.6-4.3,6.4c-1.8,1.8-3.9,3.2-6.4,4.3C29.4,43.5,26.8,44,24,44z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 841 B |
@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?><svg id="_レイヤー_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40"><defs><style>.cls-1{fill:#fff;}</style></defs><path class="cls-1" d="m17,24.5l-4.9-4.9c-.3-.3-.7-.5-1.1-.5s-.8.2-1.1.5-.5.7-.5,1.1.2.8.5,1.1l6.1,6.2c.3.3.6.5,1,.5s.7-.1,1-.5l12-12c.3-.3.4-.7.4-1.1s-.2-.8-.5-1.1c-.3-.3-.7-.5-1.1-.5s-.8.2-1.2.5l-10.6,10.7Zm3,15.5c-2.8,0-5.5-.5-7.9-1.5s-4.6-2.4-6.4-4.2-3.2-3.9-4.2-6.4-1.5-5.1-1.5-7.9.5-5.4,1.5-7.9,2.5-4.5,4.3-6.3,3.9-3.2,6.4-4.2,5-1.6,7.8-1.6,5.4.5,7.9,1.6c2.5,1.1,4.5,2.4,6.4,4.2,1.8,1.8,3.2,3.9,4.2,6.3s1.5,5,1.5,7.9-.5,5.5-1.5,7.9c-1,2.4-2.5,4.6-4.2,6.4-1.8,1.8-3.9,3.2-6.4,4.2-2.5,1-5.1,1.5-7.9,1.5Zm0-3c4.8,0,8.9-1.6,12.1-4.9s4.9-7.3,4.9-12.1-1.6-8.9-4.9-12.1-7.3-4.9-12.1-4.9-8.9,1.6-12.1,4.9-4.9,7.3-4.9,12.1,1.6,8.9,4.9,12.1,7.3,4.9,12.1,4.9Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 828 B |
13
dictation_client/src/assets/images/circle.svg
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 27.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
|
||||||
|
y="0px" viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#A5A5A5;}
|
||||||
|
</style>
|
||||||
|
<path class="st0" d="M24,44c-2.7,0-5.3-0.5-7.8-1.6c-2.4-1-4.6-2.5-6.4-4.3s-3.2-3.9-4.3-6.4S4,26.7,4,24c0-2.8,0.5-5.4,1.6-7.8
|
||||||
|
s2.5-4.6,4.3-6.4s3.9-3.2,6.4-4.3S21.3,4,24,4c2.8,0,5.4,0.5,7.8,1.6s4.6,2.5,6.4,4.3s3.2,3.9,4.3,6.4c1.1,2.4,1.6,5,1.6,7.8
|
||||||
|
c0,2.7-0.5,5.3-1.6,7.8c-1,2.4-2.5,4.6-4.3,6.4s-3.9,3.2-6.4,4.3C29.4,43.5,26.8,44,24,44z M24,41c4.7,0,8.8-1.7,12-5
|
||||||
|
c3.3-3.3,5-7.3,5-12c0-4.7-1.6-8.8-5-12.1C32.8,8.6,28.7,7,24,7c-4.7,0-8.7,1.6-12,4.9S7,19.3,7,24c0,4.7,1.7,8.7,5,12
|
||||||
|
S19.3,41,24,41z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 924 B |
10
dictation_client/src/assets/images/close.svg
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 27.3.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="_レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
|
||||||
|
y="0px" viewBox="0 0 27.3 27.3" style="enable-background:new 0 0 27.3 27.3;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#282828;}
|
||||||
|
</style>
|
||||||
|
<path class="st0" d="M2.1,27.4l-2.1-2.1l11.6-11.6L0.1,2l2.1-2.1l11.5,11.6L25.2,0l2.1,2.1L15.8,13.6l11.6,11.5l-2.1,2.1L13.7,15.7
|
||||||
|
L2.1,27.4z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 575 B |
1
dictation_client/src/assets/images/close_white.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?><svg id="_レイヤー_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 27.3 27.3"><defs><style>.cls-1{fill:#fff;}</style></defs><path class="cls-1" d="m2.1,27.3l-2.1-2.1,11.55-11.55L0,2.1,2.1,0l11.55,11.55L25.2,0l2.1,2.1-11.55,11.55,11.55,11.55-2.1,2.1-11.55-11.55L2.1,27.3Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 324 B |
10
dictation_client/src/assets/images/delete.svg
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 27.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
|
||||||
|
y="0px" viewBox="0 0 40 40" style="enable-background:new 0 0 40 40;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#282828;}
|
||||||
|
</style>
|
||||||
|
<path class="st0" d="M11.1,35c-0.8,0-1.4-0.3-1.9-0.8c-0.5-0.6-0.8-1.2-0.8-2v-23H6.7V6.4h8V5h10.7v1.4h8v2.8h-1.7v23
|
||||||
|
c0,0.8-0.3,1.4-0.8,2c-0.5,0.6-1.2,0.8-1.9,0.8H11.1z M15.2,28.7H18V12.6h-2.8V28.7z M22,28.7h2.8V12.6H22V28.7z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 651 B |
10
dictation_client/src/assets/images/edit.svg
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 27.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
|
||||||
|
y="0px" viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#282828;}
|
||||||
|
</style>
|
||||||
|
<path class="st0" d="M39.7,14.7l-6.4-6.4l2.1-2.1c0.6-0.6,1.3-0.8,2.1-0.8c0.8,0,1.6,0.3,2.1,0.9l2.1,2.1c0.6,0.6,0.9,1.3,0.9,2.1
|
||||||
|
s-0.3,1.5-0.9,2.1L39.7,14.7z M37.6,16.8L12.4,42H6v-6.4l25.2-25.2L37.6,16.8z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 630 B |
12
dictation_client/src/assets/images/person_add.svg
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 27.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
|
||||||
|
y="0px" viewBox="0 0 40 40" style="enable-background:new 0 0 40 40;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#282828;}
|
||||||
|
</style>
|
||||||
|
<path class="st0" d="M30.3,23.3V18H25v-2.8h5.3V10H33v5.3h5.3V18H33v5.3H30.3z M15,20c-1.8,0-3.4-0.6-4.6-1.8
|
||||||
|
c-1.2-1.2-1.8-2.7-1.8-4.6s0.6-3.4,1.8-4.6c1.2-1.2,2.7-1.8,4.6-1.8s3.4,0.6,4.6,1.8c1.2,1.2,1.8,2.7,1.8,4.6s-0.6,3.4-1.8,4.6
|
||||||
|
C18.4,19.4,16.8,20,15,20z M1.7,33.3v-4.2c0-1,0.2-1.9,0.7-2.6c0.5-0.8,1.2-1.4,2.1-1.8c1.9-0.9,3.8-1.5,5.4-1.9
|
||||||
|
c1.7-0.4,3.4-0.6,5.1-0.6s3.4,0.2,5.1,0.6c1.7,0.4,3.5,1,5.5,1.9c0.9,0.4,1.5,1,2,1.8c0.5,0.8,0.8,1.7,0.8,2.6v4.2H1.7z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 886 B |
1
dictation_client/src/assets/images/report_white.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?><svg id="_レイヤー_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 42.52 42.52"><defs><style>.cls-1{fill:#fff;}</style></defs><path class="cls-1" d="m21.26,33.01c.55,0,1.03-.21,1.45-.62s.62-.9.62-1.45-.21-1.03-.62-1.45-.9-.62-1.45-.62-1.03.21-1.45.62-.62.9-.62,1.45.21,1.03.62,1.45.9.62,1.45.62Zm-1.77-8.5h3.54v-15.53h-3.54v15.53Zm-7.09,18.01L0,30.12V12.4L12.4,0h17.72l12.4,12.4v17.72l-12.4,12.4H12.4Zm1.48-3.54h14.76l10.33-10.33v-14.76L28.64,3.54h-14.76L3.54,13.88v14.76l10.33,10.33Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 538 B |
15
dictation_client/src/assets/images/visibility.svg
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 27.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
|
||||||
|
y="0px" viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#A5A5A5;}
|
||||||
|
</style>
|
||||||
|
<path class="st0" d="M25,27.8c1.3,0,2.5-0.5,3.4-1.4c0.9-0.9,1.4-2.1,1.4-3.4s-0.5-2.5-1.4-3.4c-0.9-0.9-2.1-1.4-3.4-1.4
|
||||||
|
s-2.5,0.5-3.4,1.4s-1.4,2.1-1.4,3.4s0.5,2.5,1.4,3.4C22.5,27.3,23.7,27.8,25,27.8z M25,26.2c-0.9,0-1.6-0.3-2.3-0.9
|
||||||
|
c-0.6-0.6-0.9-1.3-0.9-2.3c0-0.9,0.3-1.6,0.9-2.3s1.3-0.9,2.3-0.9s1.6,0.3,2.3,0.9s0.9,1.3,0.9,2.3c0,0.9-0.3,1.6-0.9,2.3
|
||||||
|
C26.6,25.9,25.9,26.2,25,26.2z M25,31.5c-2.7,0-5.3-0.8-7.5-2.4c-2.3-1.6-3.9-3.6-5-6.1c1.1-2.6,2.7-4.6,5-6.1s4.7-2.4,7.5-2.4
|
||||||
|
s5.3,0.8,7.5,2.4s3.9,3.6,5,6.1c-1.1,2.6-2.7,4.6-5,6.1C30.3,30.7,27.7,31.5,25,31.5z M25,29.8c2.3,0,4.3-0.7,6.3-1.9
|
||||||
|
c1.9-1.2,3.4-2.9,4.3-4.9c-1-2.1-2.5-3.7-4.3-4.9c-1.9-1.2-4.1-1.9-6.3-1.9s-4.3,0.7-6.3,1.9c-1.9,1.2-3.4,2.9-4.4,4.9
|
||||||
|
c1,2.1,2.5,3.7,4.4,4.9C20.7,29.2,22.7,29.8,25,29.8z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
17
dictation_client/src/assets/images/visibility_off.svg
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 27.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
|
||||||
|
y="0px" viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#A5A5A5;}
|
||||||
|
</style>
|
||||||
|
<path class="st0" d="M29.3,25.4l-1.2-1.2c0.5-1.3,0.2-2.5-0.8-3.3c-1-0.9-2.1-1.1-3.3-0.7l-1.2-1.4c0.3-0.2,0.7-0.4,1.1-0.5
|
||||||
|
s0.8-0.1,1.2-0.1c1.3,0,2.5,0.5,3.4,1.4s1.4,2.1,1.4,3.4c0,0.4-0.1,0.8-0.2,1.2C29.7,24.7,29.5,25,29.3,25.4z M33,29l-1.2-1.1
|
||||||
|
c0.9-0.7,1.7-1.4,2.4-2.3c0.7-0.8,1.2-1.7,1.5-2.5c-0.9-2.1-2.4-3.8-4.3-5c-1.9-1.2-3.9-1.8-6.2-1.8c-0.8,0-1.6,0.1-2.4,0.2
|
||||||
|
c-0.8,0.2-1.5,0.3-2,0.5l-1.3-1.3c0.7-0.3,1.5-0.6,2.5-0.8c1-0.2,2-0.3,3-0.3c2.7,0,5.2,0.8,7.4,2.3c2.2,1.5,3.9,3.6,4.9,6.2
|
||||||
|
c-0.5,1.2-1.1,2.3-1.9,3.3S34,28.3,33,29z M34.6,35.3l-4.8-4.7c-0.7,0.3-1.4,0.5-2.2,0.6c-0.8,0.2-1.7,0.3-2.5,0.3
|
||||||
|
c-2.8,0-5.3-0.8-7.5-2.3s-3.9-3.6-5-6.2c0.4-1,0.9-1.9,1.6-2.9c0.7-0.9,1.5-1.8,2.5-2.7l-3.6-3.6l1.2-1.2l21.5,21.5L34.6,35.3z
|
||||||
|
M17.8,18.7c-0.7,0.5-1.4,1.2-2,2c-0.7,0.8-1.1,1.6-1.4,2.4c1,2.1,2.4,3.8,4.4,5s4.1,1.8,6.6,1.8c0.6,0,1.2,0,1.8-0.1
|
||||||
|
c0.6-0.1,1.1-0.2,1.4-0.3l-1.9-1.9c-0.2,0.1-0.5,0.2-0.8,0.2s-0.6,0.1-0.9,0.1c-1.3,0-2.5-0.5-3.4-1.4s-1.4-2.1-1.4-3.4
|
||||||
|
c0-0.3,0-0.6,0.1-0.9c0-0.3,0.1-0.5,0.2-0.8L17.8,18.7z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.4 KiB |
56
dictation_client/src/features/signup/selectors.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import { RootState } from "app/store";
|
||||||
|
|
||||||
|
export const selectInputValidationErrors = (state: RootState) => {
|
||||||
|
// 必須項目のチェック
|
||||||
|
const hasErrorEmptyEmail = state.signup.apps.email === "";
|
||||||
|
const hasErrorEmptyPassword = state.signup.apps.password === "";
|
||||||
|
const hasErrorEmptyCompany = state.signup.apps.company === "";
|
||||||
|
const hasErrorEmptyCountry = state.signup.apps.country === "";
|
||||||
|
const hasErrorEmptyAdminName = state.signup.apps.adminName === "";
|
||||||
|
/* TODO ディーラーはPBI1125対象外
|
||||||
|
const hasErrorEmptyDealer = state.signup.apps.dealer === "";
|
||||||
|
*/
|
||||||
|
|
||||||
|
const hasErrorIncorrectPassword = checkErrorIncorrectPassword(
|
||||||
|
state.signup.apps.password
|
||||||
|
);
|
||||||
|
|
||||||
|
const hasErrorIncorrectEmail =
|
||||||
|
(state.signup.apps.email as string).match(/^[^@]+@[^@]+$/)?.length !== 1;
|
||||||
|
|
||||||
|
return {
|
||||||
|
hasErrorEmptyEmail,
|
||||||
|
hasErrorEmptyCountry,
|
||||||
|
hasErrorEmptyPassword,
|
||||||
|
hasErrorEmptyCompany,
|
||||||
|
hasErrorEmptyAdminName,
|
||||||
|
hasErrorIncorrectEmail,
|
||||||
|
hasErrorIncorrectPassword,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const selectEmail = (state: RootState) => state.signup.apps.email;
|
||||||
|
|
||||||
|
export const selectPassword = (state: RootState) => state.signup.apps.password;
|
||||||
|
|
||||||
|
export const selectPageState = (state: RootState) =>
|
||||||
|
state.signup.apps.pageState;
|
||||||
|
|
||||||
|
export const checkErrorIncorrectPassword = (password: string): boolean => {
|
||||||
|
// 英字の大文字、英字の小文字、アラビア数字、記号(!@#$%^&*()+-={}[]:;'<>,./?_∼\)から2種類以上組み合わせ
|
||||||
|
const charaTypePattern =
|
||||||
|
/^((?=.*[a-z])(?=.*[A-Z])|(?=.*[a-z])(?=.*[\d])|(?=.*[a-z])(?=.*[!@#$%^&*()+-={}:;'<>,./?_~[\\\]])|(?=.*[A-Z])(?=.*[\d])|(?=.*[A-Z])(?=.*[!@#$%^&*()+-={}:;'<>,./?_~[\\\]])|(?=.*[\d])(?=.*[!@#$%^&*()+-={}:;'<>,./?_~[\\\]]))[a-zA-Z\d!@#$%^&*()+-={}:;'<>,./?_~[\\\]]{8,64}$/;
|
||||||
|
const charaType = new RegExp(charaTypePattern).test(password);
|
||||||
|
|
||||||
|
// 同じ文字の3連続は禁止
|
||||||
|
const repeatPattern = /(.)\1{2,}/;
|
||||||
|
const repeat = new RegExp(repeatPattern).test(password);
|
||||||
|
|
||||||
|
// 特定文字列は禁止
|
||||||
|
const unavailableCharaPattern =
|
||||||
|
/password|passwd|test|admin|administrator|sysadmin|0123|1234|2345|3456|4567|5678|6789|9876|8765|7654|6543|5432|4321|3210/;
|
||||||
|
const unavailableChara = !new RegExp(unavailableCharaPattern, "i").test(
|
||||||
|
password
|
||||||
|
);
|
||||||
|
return !charaType || repeat || !unavailableChara;
|
||||||
|
};
|
||||||
65
dictation_client/src/features/signup/signupSlice.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||||
|
import { SignupState } from "./state";
|
||||||
|
|
||||||
|
const initialState: SignupState = {
|
||||||
|
apps: {
|
||||||
|
pageState: "input",
|
||||||
|
company: "",
|
||||||
|
country: "",
|
||||||
|
dealer: "",
|
||||||
|
adminName: "",
|
||||||
|
email: "",
|
||||||
|
password: "",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const signupSlice = createSlice({
|
||||||
|
name: "signup",
|
||||||
|
initialState,
|
||||||
|
reducers: {
|
||||||
|
changePageState: (
|
||||||
|
state,
|
||||||
|
action: PayloadAction<{ pageState: "input" | "confirm" }>
|
||||||
|
) => {
|
||||||
|
const { pageState } = action.payload;
|
||||||
|
state.apps.pageState = pageState;
|
||||||
|
},
|
||||||
|
changeCompany: (state, action: PayloadAction<{ company: string }>) => {
|
||||||
|
const { company } = action.payload;
|
||||||
|
state.apps.company = company;
|
||||||
|
},
|
||||||
|
changeCountry: (state, action: PayloadAction<{ country: string }>) => {
|
||||||
|
const { country } = action.payload;
|
||||||
|
state.apps.country = country;
|
||||||
|
},
|
||||||
|
changeDealer: (state, action: PayloadAction<{ dealer: string }>) => {
|
||||||
|
const { dealer } = action.payload;
|
||||||
|
state.apps.dealer = dealer;
|
||||||
|
},
|
||||||
|
changeAdminName: (state, action: PayloadAction<{ adminName: string }>) => {
|
||||||
|
const { adminName } = action.payload;
|
||||||
|
state.apps.adminName = adminName;
|
||||||
|
},
|
||||||
|
changeEmail: (state, action: PayloadAction<{ email: string }>) => {
|
||||||
|
const { email } = action.payload;
|
||||||
|
state.apps.email = email;
|
||||||
|
},
|
||||||
|
changePassword: (state, action: PayloadAction<{ password: string }>) => {
|
||||||
|
const { password } = action.payload;
|
||||||
|
state.apps.password = password;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
extraReducers: () => {
|
||||||
|
//
|
||||||
|
},
|
||||||
|
});
|
||||||
|
export const {
|
||||||
|
changePageState,
|
||||||
|
changeEmail,
|
||||||
|
changeAdminName,
|
||||||
|
changeCompany,
|
||||||
|
changeCountry,
|
||||||
|
changeDealer,
|
||||||
|
changePassword,
|
||||||
|
} = signupSlice.actions;
|
||||||
|
export default signupSlice.reducer;
|
||||||
13
dictation_client/src/features/signup/state.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
export interface SignupState {
|
||||||
|
apps: Apps;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Apps {
|
||||||
|
pageState: "input" | "confirm" | "complete";
|
||||||
|
company: string;
|
||||||
|
country: string;
|
||||||
|
dealer: string;
|
||||||
|
adminName: string;
|
||||||
|
email: string;
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
44
dictation_client/src/pages/SignupPage/constants.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
export const COUNTRY_LIST = [
|
||||||
|
{ value: "", label: "Select Country" },
|
||||||
|
{ value: "Canada", label: "Canada" },
|
||||||
|
{ value: "Cayman Islands", label: "Cayman Islands" },
|
||||||
|
{ value: "U.S.A.", label: "U.S.A." },
|
||||||
|
{ value: "Australia", label: "Australia" },
|
||||||
|
{ value: "New Zealand", label: "New Zealand" },
|
||||||
|
{ value: "Austria", label: "Austria" },
|
||||||
|
{ value: "Belgium", label: "Belgium" },
|
||||||
|
{ value: "Bulgaria", label: "Bulgaria" },
|
||||||
|
{ value: "Croatia", label: "Croatia" },
|
||||||
|
{ value: "Cyprus", label: "Cyprus" },
|
||||||
|
{ value: "Czech Republic", label: "Czech Republic" },
|
||||||
|
{ value: "Denmark", label: "Denmark" },
|
||||||
|
{ value: "Estonia", label: "Estonia" },
|
||||||
|
{ value: "Finland", label: "Finland" },
|
||||||
|
{ value: "France", label: "France" },
|
||||||
|
{ value: "Germany", label: "Germany" },
|
||||||
|
{ value: "Greece", label: "Greece" },
|
||||||
|
{ value: "Hungary", label: "Hungary" },
|
||||||
|
{ value: "Iceland", label: "Iceland" },
|
||||||
|
{ value: "Ireland", label: "Ireland" },
|
||||||
|
{ value: "Italy", label: "Italy" },
|
||||||
|
{ value: "Latvia", label: "Latvia" },
|
||||||
|
{ value: "Liechtenstein", label: "Liechtenstein" },
|
||||||
|
{ value: "Lithuania", label: "Lithuania" },
|
||||||
|
{ value: "Luxembourg", label: "Luxembourg" },
|
||||||
|
{ value: "Malta", label: "Malta" },
|
||||||
|
{ value: "Netherlands", label: "Netherlands" },
|
||||||
|
{ value: "Norway", label: "Norway" },
|
||||||
|
{ value: "Poland", label: "Poland" },
|
||||||
|
{ value: "Portugal", label: "Portugal" },
|
||||||
|
{ value: "Romania", label: "Romania" },
|
||||||
|
{ value: "Serbia", label: "Serbia" },
|
||||||
|
{ value: "Slovakia", label: "Slovakia" },
|
||||||
|
{ value: "Slovenia", label: "Slovenia" },
|
||||||
|
{ value: "South Africa", label: "South Africa" },
|
||||||
|
{ value: "Spain", label: "Spain" },
|
||||||
|
{ value: "Sweden", label: "Sweden" },
|
||||||
|
{ value: "Switzerland", label: "Switzerland" },
|
||||||
|
{ value: "Turkey", label: "Turkey" },
|
||||||
|
{ value: "United Kingdom", label: "United Kingdom" },
|
||||||
|
{ value: "Thailand", label: "Thailand" },
|
||||||
|
];
|
||||||
32
dictation_client/src/pages/SignupPage/index.tsx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { selectPageState } from "features/signup/selectors";
|
||||||
|
import React from "react";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
import { Navigate } from "react-router-dom";
|
||||||
|
import SignupInput from "./signupInput";
|
||||||
|
|
||||||
|
const SignupPage: React.FC<{ completeTo: string }> = ({
|
||||||
|
completeTo,
|
||||||
|
}): JSX.Element => {
|
||||||
|
const state = useSelector(selectPageState);
|
||||||
|
|
||||||
|
return getComponent(state, completeTo);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 現在のサインアップ画面の状態に応じて表示Componentを出し分ける
|
||||||
|
const getComponent = (
|
||||||
|
state: "input" | "confirm" | "complete",
|
||||||
|
completeTo: string
|
||||||
|
) => {
|
||||||
|
switch (state) {
|
||||||
|
case "input":
|
||||||
|
return <SignupInput />;
|
||||||
|
case "confirm":
|
||||||
|
return <div>確認画面</div>;
|
||||||
|
case "complete":
|
||||||
|
return <Navigate to={completeTo} replace />;
|
||||||
|
default:
|
||||||
|
return <div />;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SignupPage;
|
||||||
203
dictation_client/src/pages/SignupPage/signup.module.scss
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
.wrap {
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: auto 1fr auto;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
grid-template-areas: "header" "main" "footer";
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
.main {
|
||||||
|
grid-area: main;
|
||||||
|
}
|
||||||
|
.mainSmall {
|
||||||
|
width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 3.2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formList {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
dt {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.7;
|
||||||
|
letter-spacing: 0;
|
||||||
|
font-weight: normal;
|
||||||
|
width: 22%;
|
||||||
|
padding: 0.5rem 4% 0;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
dd {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.7;
|
||||||
|
letter-spacing: 0;
|
||||||
|
font-weight: normal;
|
||||||
|
width: 66%;
|
||||||
|
padding-right: 4%;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
dt.formTitle {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.5rem 4%;
|
||||||
|
text-align: left;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
line-height: 1.7;
|
||||||
|
letter-spacing: 0.07rem;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
dt.overLine {
|
||||||
|
padding: 0 4% 0;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
dd.full {
|
||||||
|
width: 100%;
|
||||||
|
padding-right: 0;
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.formListHasbg {
|
||||||
|
border-top: 2px #282828 solid;
|
||||||
|
background: #fafafa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formInput {
|
||||||
|
width: 350px;
|
||||||
|
padding: 0.6rem 0.8rem;
|
||||||
|
border: 1px #999999 solid;
|
||||||
|
background: #ffffff;
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.4;
|
||||||
|
letter-spacing: 0;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
.formInputIsError {
|
||||||
|
background: rgba(229, 0, 0, 0.08);
|
||||||
|
}
|
||||||
|
.formInputPassword[type="password"] {
|
||||||
|
+ {
|
||||||
|
span {
|
||||||
|
background: url(../../assets/images/visibility_off.svg) no-repeat top
|
||||||
|
right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.formInputPassword[type="text"] {
|
||||||
|
+ {
|
||||||
|
span {
|
||||||
|
background: url(../../assets/images/visibility_off.svg) no-repeat top
|
||||||
|
right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.formIconEye {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
float: right;
|
||||||
|
margin-top: -40px;
|
||||||
|
margin-right: 45px;
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.formIconEyeImg {
|
||||||
|
width: 2.5rem;
|
||||||
|
}
|
||||||
|
.formCheck {
|
||||||
|
width: 1.2rem;
|
||||||
|
height: 1.2rem;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formError {
|
||||||
|
display: block;
|
||||||
|
padding-top: 0.3rem;
|
||||||
|
color: #e60000;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 1.4;
|
||||||
|
letter-spacing: 0;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
.formComment {
|
||||||
|
display: inline-block;
|
||||||
|
padding-top: 0.5rem;
|
||||||
|
color: #999999;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 1.4;
|
||||||
|
letter-spacing: 0;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formSubmit {
|
||||||
|
min-width: 15rem;
|
||||||
|
padding: 0.8rem 2rem;
|
||||||
|
border: 1px #999999 solid;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.4;
|
||||||
|
letter-spacing: 0.04rem;
|
||||||
|
font-weight: normal;
|
||||||
|
opacity: 0.7;
|
||||||
|
pointer-events: none;
|
||||||
|
border-radius: 0.3rem;
|
||||||
|
position: relative;
|
||||||
|
-moz-transition: all 0.3s ease-out;
|
||||||
|
-ms-transition: all 0.3s ease-out;
|
||||||
|
-webkit-transition: all 0.3s ease-out;
|
||||||
|
transition: all 0.3s ease-out;
|
||||||
|
}
|
||||||
|
.formSubmitIsActive {
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: 1;
|
||||||
|
color: #ffffff;
|
||||||
|
background: #004086;
|
||||||
|
border: 1px #004086 solid;
|
||||||
|
pointer-events: auto;
|
||||||
|
&:hover {
|
||||||
|
background: rgba(0, 94, 184, 0.7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.formButtonTx {
|
||||||
|
padding: 0.2rem 2rem;
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
color: #0084b2;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.4;
|
||||||
|
letter-spacing: 0.04rem;
|
||||||
|
font-weight: normal;
|
||||||
|
cursor: pointer;
|
||||||
|
-moz-transition: all 0.3s ease-out;
|
||||||
|
-ms-transition: all 0.3s ease-out;
|
||||||
|
-webkit-transition: all 0.3s ease-out;
|
||||||
|
transition: all 0.3s ease-out;
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.linkTx {
|
||||||
|
color: #0084b2;
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
img {
|
||||||
|
width: 1rem;
|
||||||
|
margin: 0 4px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.alignCenter {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.marginBtm0 {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
.marginBtm1 {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
.marginBtm2 {
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
27
dictation_client/src/pages/SignupPage/signup.module.scss.d.ts
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
declare const classNames: {
|
||||||
|
readonly wrap: "wrap";
|
||||||
|
readonly main: "main";
|
||||||
|
readonly mainSmall: "mainSmall";
|
||||||
|
readonly formList: "formList";
|
||||||
|
readonly formTitle: "formTitle";
|
||||||
|
readonly overLine: "overLine";
|
||||||
|
readonly full: "full";
|
||||||
|
readonly formListHasbg: "formListHasbg";
|
||||||
|
readonly formInput: "formInput";
|
||||||
|
readonly formInputIsError: "formInputIsError";
|
||||||
|
readonly formInputPassword: "formInputPassword";
|
||||||
|
readonly formIconEye: "formIconEye";
|
||||||
|
readonly formIconEyeImg: "formIconEyeImg";
|
||||||
|
readonly formCheck: "formCheck";
|
||||||
|
readonly formError: "formError";
|
||||||
|
readonly formComment: "formComment";
|
||||||
|
readonly formSubmit: "formSubmit";
|
||||||
|
readonly formSubmitIsActive: "formSubmitIsActive";
|
||||||
|
readonly formButtonTx: "formButtonTx";
|
||||||
|
readonly linkTx: "linkTx";
|
||||||
|
readonly alignCenter: "alignCenter";
|
||||||
|
readonly marginBtm0: "marginBtm0";
|
||||||
|
readonly marginBtm1: "marginBtm1";
|
||||||
|
readonly marginBtm2: "marginBtm2";
|
||||||
|
};
|
||||||
|
export = classNames;
|
||||||
295
dictation_client/src/pages/SignupPage/signupInput.tsx
Normal file
@ -0,0 +1,295 @@
|
|||||||
|
import { AppDispatch } from "app/store";
|
||||||
|
import { selectInputValidationErrors } from "features/signup/selectors";
|
||||||
|
import {
|
||||||
|
changeAdminName,
|
||||||
|
changeCompany,
|
||||||
|
changeCountry,
|
||||||
|
changeEmail,
|
||||||
|
changePageState,
|
||||||
|
changePassword,
|
||||||
|
} from "features/signup/signupSlice";
|
||||||
|
import React, { useCallback, useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { getTranslationID } from "translation";
|
||||||
|
import { COUNTRY_LIST } from "./constants";
|
||||||
|
import styles from "./signup.module.scss";
|
||||||
|
|
||||||
|
const SignupInputPage: React.FC = (): JSX.Element => {
|
||||||
|
const dispatch: AppDispatch = useDispatch();
|
||||||
|
const [t] = useTranslation();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const [isPasswordHide, setIsPasswordHide] = useState<boolean>(true);
|
||||||
|
const [isOpenPolicy, setIsOpenPolicy] = useState<boolean>(false);
|
||||||
|
const [isAgreePolicy, setIsAgreePolicy] = useState<boolean>(false);
|
||||||
|
const [isPushCreateButton, setIsPushCreateButton] = useState<boolean>(false);
|
||||||
|
const {
|
||||||
|
hasErrorEmptyAdminName,
|
||||||
|
hasErrorEmptyCompany,
|
||||||
|
hasErrorEmptyCountry,
|
||||||
|
hasErrorEmptyEmail,
|
||||||
|
hasErrorEmptyPassword,
|
||||||
|
hasErrorIncorrectEmail,
|
||||||
|
hasErrorIncorrectPassword,
|
||||||
|
} = useSelector(selectInputValidationErrors);
|
||||||
|
const onSubmit = useCallback(() => {
|
||||||
|
if (
|
||||||
|
hasErrorEmptyAdminName ||
|
||||||
|
hasErrorEmptyCompany ||
|
||||||
|
hasErrorEmptyCountry ||
|
||||||
|
hasErrorEmptyEmail ||
|
||||||
|
hasErrorEmptyPassword ||
|
||||||
|
hasErrorIncorrectEmail ||
|
||||||
|
hasErrorIncorrectPassword
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dispatch(changePageState({ pageState: "confirm" }));
|
||||||
|
}, [
|
||||||
|
dispatch,
|
||||||
|
hasErrorEmptyAdminName,
|
||||||
|
hasErrorEmptyCompany,
|
||||||
|
hasErrorEmptyCountry,
|
||||||
|
hasErrorEmptyEmail,
|
||||||
|
hasErrorEmptyPassword,
|
||||||
|
hasErrorIncorrectEmail,
|
||||||
|
hasErrorIncorrectPassword,
|
||||||
|
]);
|
||||||
|
return (
|
||||||
|
<div className={styles.wrap}>
|
||||||
|
<header />
|
||||||
|
<main className={styles.main}>
|
||||||
|
<div className={styles.mainSmall}>
|
||||||
|
<div>
|
||||||
|
<h1 className={styles.marginBtm1}>
|
||||||
|
{t(getTranslationID("signupPage.text.title"))}
|
||||||
|
</h1>
|
||||||
|
<p className={styles.marginBtm2}>
|
||||||
|
{t(getTranslationID("signupPage.text.pageExplanation"))}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<section>
|
||||||
|
<form>
|
||||||
|
<dl className={`${styles.formList} ${styles.formListHasbg}`}>
|
||||||
|
<dt className={` ${styles.formTitle} ${styles.marginBtm0}`}>
|
||||||
|
{t(getTranslationID("signupPage.text.accountInfoTitle"))}
|
||||||
|
</dt>
|
||||||
|
<dt> {t(getTranslationID("signupPage.label.company"))}</dt>
|
||||||
|
<dd>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
size={64}
|
||||||
|
autoComplete="organization"
|
||||||
|
className={`${styles.formInput} ${
|
||||||
|
isPushCreateButton &&
|
||||||
|
hasErrorEmptyCompany &&
|
||||||
|
styles.formInputIsError
|
||||||
|
}`}
|
||||||
|
onChange={(e) => {
|
||||||
|
dispatch(changeCompany({ company: e.target.value }));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{isPushCreateButton && hasErrorEmptyCompany && (
|
||||||
|
<span className={styles.formError}>
|
||||||
|
{" "}
|
||||||
|
{t(getTranslationID("common.message.inputEmptyError"))}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</dd>
|
||||||
|
<dt> {t(getTranslationID("signupPage.label.country"))}</dt>
|
||||||
|
<dd>
|
||||||
|
<select
|
||||||
|
className={`${styles.formInput} ${
|
||||||
|
isPushCreateButton &&
|
||||||
|
hasErrorEmptyCountry &&
|
||||||
|
styles.formInputIsError
|
||||||
|
}`}
|
||||||
|
onChange={(event) => {
|
||||||
|
dispatch(changeCountry({ country: event.target.value }));
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{COUNTRY_LIST.map((x) => (
|
||||||
|
<option key={x.value} value={x.value}>
|
||||||
|
{x.label}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
{isPushCreateButton && hasErrorEmptyCountry && (
|
||||||
|
<span className={styles.formError}>Error message</span>
|
||||||
|
)}
|
||||||
|
<span className={styles.formComment}>
|
||||||
|
{t(getTranslationID("signupPage.text.countryExplanation"))}
|
||||||
|
</span>
|
||||||
|
</dd>
|
||||||
|
<dt> {t(getTranslationID("signupPage.label.dealer"))}</dt>
|
||||||
|
<dd>
|
||||||
|
<select className={styles.formInput}>
|
||||||
|
<option>Select dealer</option>
|
||||||
|
<option value="Tokyo">Tokyo</option>
|
||||||
|
</select>
|
||||||
|
<span className={styles.formComment}>
|
||||||
|
{t(getTranslationID("signupPage.text.dealerExplanation"))}
|
||||||
|
</span>
|
||||||
|
</dd>
|
||||||
|
<dt className={` ${styles.formTitle} ${styles.marginBtm0}`}>
|
||||||
|
{t(getTranslationID("signupPage.text.adminInfoTitle"))}
|
||||||
|
</dt>
|
||||||
|
<dt> {t(getTranslationID("signupPage.label.adminName"))}</dt>
|
||||||
|
<dd>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
size={256}
|
||||||
|
autoComplete="organization"
|
||||||
|
className={`${styles.formInput} ${
|
||||||
|
isPushCreateButton &&
|
||||||
|
hasErrorEmptyAdminName &&
|
||||||
|
styles.formInputIsError
|
||||||
|
}`}
|
||||||
|
onChange={(e) => {
|
||||||
|
dispatch(changeAdminName({ adminName: e.target.value }));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{isPushCreateButton && hasErrorEmptyAdminName && (
|
||||||
|
<span className={styles.formError}>
|
||||||
|
{" "}
|
||||||
|
{t(getTranslationID("common.message.inputEmptyError"))}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</dd>
|
||||||
|
<dt> {t(getTranslationID("signupPage.label.email"))}</dt>
|
||||||
|
<dd>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
size={64}
|
||||||
|
autoComplete="organization"
|
||||||
|
className={`${styles.formInput}
|
||||||
|
${
|
||||||
|
isPushCreateButton &&
|
||||||
|
(hasErrorEmptyEmail || hasErrorIncorrectEmail) &&
|
||||||
|
styles.formInputIsError
|
||||||
|
}`}
|
||||||
|
onChange={(e) => {
|
||||||
|
dispatch(changeEmail({ email: e.target.value }));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{isPushCreateButton && hasErrorEmptyEmail && (
|
||||||
|
<span className={styles.formError}>
|
||||||
|
{t(getTranslationID("common.message.inputEmptyError"))}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{isPushCreateButton && hasErrorIncorrectEmail && (
|
||||||
|
<span className={styles.formError}>
|
||||||
|
{t(
|
||||||
|
getTranslationID("common.message.emailIncorrectError")
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</dd>
|
||||||
|
<dt> {t(getTranslationID("signupPage.label.password"))}</dt>
|
||||||
|
<dd className={styles.marginBtm1}>
|
||||||
|
<input
|
||||||
|
type={isPasswordHide ? "password" : "text"}
|
||||||
|
size={64}
|
||||||
|
className={`${styles.formInput} ${styles.formInputPassword}
|
||||||
|
${
|
||||||
|
isPushCreateButton &&
|
||||||
|
(hasErrorIncorrectPassword || hasErrorEmptyPassword) &&
|
||||||
|
styles.formInputIsError
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
onChange={(e) => {
|
||||||
|
dispatch(changePassword({ password: e.target.value }));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
className={styles.formIconEye}
|
||||||
|
onClick={() => {
|
||||||
|
setIsPasswordHide(!isPasswordHide);
|
||||||
|
}}
|
||||||
|
onKeyDown={() => {
|
||||||
|
setIsPasswordHide(!isPasswordHide);
|
||||||
|
}}
|
||||||
|
role="button"
|
||||||
|
tabIndex={0}
|
||||||
|
aria-label="IconEye"
|
||||||
|
/>
|
||||||
|
{isPushCreateButton && hasErrorEmptyPassword && (
|
||||||
|
<span className={styles.formError}>
|
||||||
|
{t(getTranslationID("common.message.inputEmptyError"))}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{isPushCreateButton && hasErrorIncorrectPassword && (
|
||||||
|
<span className={styles.formError}>
|
||||||
|
{t(
|
||||||
|
getTranslationID(
|
||||||
|
"common.message.passwordIncorrectError"
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
<span className={styles.formComment}>
|
||||||
|
{t(getTranslationID("signupPage.text.passwordTerms"))}
|
||||||
|
</span>
|
||||||
|
</dd>
|
||||||
|
<dd className={`${styles.full} ${styles.alignCenter}`}>
|
||||||
|
<a
|
||||||
|
href="/"
|
||||||
|
target="_blank"
|
||||||
|
className={styles.linkTx}
|
||||||
|
onClick={() => {
|
||||||
|
setIsOpenPolicy(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t(getTranslationID("signupPage.label.termsLink"))}
|
||||||
|
</a>{" "}
|
||||||
|
{t(getTranslationID("signupPage.label.termsLinkFor"))} <br />
|
||||||
|
<label htmlFor="check-box">
|
||||||
|
<input
|
||||||
|
id="check-box"
|
||||||
|
type="checkbox"
|
||||||
|
className={styles.formCheck}
|
||||||
|
disabled={!isOpenPolicy}
|
||||||
|
onChange={(e) => {
|
||||||
|
setIsAgreePolicy(e.target.checked);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{t(getTranslationID("signupPage.label.termsCheckBox"))}
|
||||||
|
</label>
|
||||||
|
</dd>
|
||||||
|
<dd className={` ${styles.full} ${styles.alignCenter}`}>
|
||||||
|
<input
|
||||||
|
type="button"
|
||||||
|
name="submit"
|
||||||
|
value={t(
|
||||||
|
getTranslationID("signupPage.label.createAccountButton")
|
||||||
|
)}
|
||||||
|
className={`${styles.formSubmit}
|
||||||
|
${isAgreePolicy && styles.formSubmitIsActive}
|
||||||
|
${styles.marginBtm0}`}
|
||||||
|
onClick={() => {
|
||||||
|
setIsPushCreateButton(true);
|
||||||
|
onSubmit();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<br />
|
||||||
|
<input
|
||||||
|
type="button"
|
||||||
|
name="cancel"
|
||||||
|
value={t(getTranslationID("common.label.cancel"))}
|
||||||
|
className={styles.formButtonTx}
|
||||||
|
onClick={() => {
|
||||||
|
navigate("/");
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SignupInputPage;
|
||||||
@ -74,7 +74,7 @@ const TopPage: React.FC = (): JSX.Element => {
|
|||||||
</dd>
|
</dd>
|
||||||
<dt>{t(getTranslationID("topPage.label.newUser"))}</dt>
|
<dt>{t(getTranslationID("topPage.label.newUser"))}</dt>
|
||||||
<dd className={`${styles.marginBtm1}`}>
|
<dd className={`${styles.marginBtm1}`}>
|
||||||
<a href="●●" className={`${styles.buttonBase}`}>
|
<a href="/signup" className={`${styles.buttonBase}`}>
|
||||||
{t(getTranslationID("topPage.label.signUpButton"))}
|
{t(getTranslationID("topPage.label.signUpButton"))}
|
||||||
<img
|
<img
|
||||||
src={arrow_forward_bule}
|
src={arrow_forward_bule}
|
||||||
|
|||||||
2
dictation_client/src/react-app-env.d.ts
vendored
@ -1,6 +1,6 @@
|
|||||||
/* eslint-disable @typescript-eslint/naming-convention */
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
// 環境変数のコード補完
|
// 環境変数のコード補完
|
||||||
/// <reference types="react-scripts" />
|
/// <reference types="vite/client" />
|
||||||
interface ImportMetaEnv {
|
interface ImportMetaEnv {
|
||||||
readonly VITE_STAGE: string;
|
readonly VITE_STAGE: string;
|
||||||
readonly VITE_B2C_CLIENTID: string;
|
readonly VITE_B2C_CLIENTID: string;
|
||||||
|
|||||||
@ -1,6 +1,12 @@
|
|||||||
{
|
{
|
||||||
"common": {
|
"common": {
|
||||||
|
"message": {
|
||||||
|
"inputEmptyError": "(de)Error Message",
|
||||||
|
"passwordIncorrectError": "(de)Error Message",
|
||||||
|
"emailIncorrectError": "(de)Error Message"
|
||||||
|
},
|
||||||
"label": {
|
"label": {
|
||||||
|
"cancel": "(de)Cancel",
|
||||||
"headerTitle": "(de)ODMS Cloud",
|
"headerTitle": "(de)ODMS Cloud",
|
||||||
"copyRight": "(de)OM Digital Solutions 2023"
|
"copyRight": "(de)OM Digital Solutions 2023"
|
||||||
}
|
}
|
||||||
@ -17,5 +23,28 @@
|
|||||||
"newUser": "(de)New user?",
|
"newUser": "(de)New user?",
|
||||||
"signUpButton": "(de)Create a new account"
|
"signUpButton": "(de)Create a new account"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"signupPage": {
|
||||||
|
"text": {
|
||||||
|
"title": "(de)Create your account",
|
||||||
|
"pageExplanation": "(de)Explanation...",
|
||||||
|
"accountInfoTitle": "(de)Register your account information",
|
||||||
|
"countryExplanation": "(de) Please select your country or the nearest country.",
|
||||||
|
"dealerExplanation": "(de)Please select the dealer to purchase a license.",
|
||||||
|
"adminInfoTitle": "(de)Register primary administrator's information",
|
||||||
|
"passwordTerms": "(de) Please set a password or issue an initial password.\nThe password must be more than 8 or less than 25 letters,numbers and symbols."
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"company": "(de)Company Name",
|
||||||
|
"country": "(de)Country",
|
||||||
|
"dealer": "(de)Dealer (Optional)",
|
||||||
|
"adminName": "(de)Admin Name",
|
||||||
|
"email": "(de)Email",
|
||||||
|
"password": "(de)Password",
|
||||||
|
"termsLink": "(de)Click here to read the terms of use",
|
||||||
|
"termsLinkFor": "(de)for ODDS.",
|
||||||
|
"termsCheckBox": "(de)Yes, I agree to the terms of use.",
|
||||||
|
"createAccountButton": "(de)Create account"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,12 @@
|
|||||||
{
|
{
|
||||||
"common": {
|
"common": {
|
||||||
|
"message": {
|
||||||
|
"inputEmptyError": "Error Message",
|
||||||
|
"passwordIncorrectError": "Error Message",
|
||||||
|
"emailIncorrectError": "Error Message"
|
||||||
|
},
|
||||||
"label": {
|
"label": {
|
||||||
|
"cancel": "Cancel",
|
||||||
"headerTitle": "ODMS Cloud",
|
"headerTitle": "ODMS Cloud",
|
||||||
"copyRight": "OM Digital Solutions 2023"
|
"copyRight": "OM Digital Solutions 2023"
|
||||||
}
|
}
|
||||||
@ -17,5 +23,28 @@
|
|||||||
"newUser": "New user?",
|
"newUser": "New user?",
|
||||||
"signUpButton": "Create a new account"
|
"signUpButton": "Create a new account"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"signupPage": {
|
||||||
|
"text": {
|
||||||
|
"title": "Create your account",
|
||||||
|
"pageExplanation": "Explanation...",
|
||||||
|
"accountInfoTitle": "Register your account information",
|
||||||
|
"countryExplanation": " Please select your country or the nearest country.",
|
||||||
|
"dealerExplanation": "Please select the dealer to purchase a license.",
|
||||||
|
"adminInfoTitle": "Register primary administrator's information",
|
||||||
|
"passwordTerms": " Please set a password or issue an initial password. \nThe password must be more than 8 or less than 25 letters,numbers and symbols."
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"company": "Company Name",
|
||||||
|
"country": "Country",
|
||||||
|
"dealer": "Dealer (Optional)",
|
||||||
|
"adminName": "Admin Name",
|
||||||
|
"email": "Email",
|
||||||
|
"password": "Password",
|
||||||
|
"termsLink": "Click here to read the terms of use",
|
||||||
|
"termsLinkFor": "for ODDS.",
|
||||||
|
"termsCheckBox": "Yes, I agree to the terms of use.",
|
||||||
|
"createAccountButton": "Create account"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,12 @@
|
|||||||
{
|
{
|
||||||
"common": {
|
"common": {
|
||||||
|
"message": {
|
||||||
|
"inputEmptyError": "(es)Error Message",
|
||||||
|
"passwordIncorrectError": "(es)Error Message",
|
||||||
|
"emailIncorrectError": "(es)Error Message"
|
||||||
|
},
|
||||||
"label": {
|
"label": {
|
||||||
|
"cancel": "(es)Cancel",
|
||||||
"headerTitle": "(es)ODMS Cloud",
|
"headerTitle": "(es)ODMS Cloud",
|
||||||
"copyRight": "(es)OM Digital Solutions 2023"
|
"copyRight": "(es)OM Digital Solutions 2023"
|
||||||
}
|
}
|
||||||
@ -17,5 +23,28 @@
|
|||||||
"newUser": "(es)New user?",
|
"newUser": "(es)New user?",
|
||||||
"signUpButton": "(es)Create a new account"
|
"signUpButton": "(es)Create a new account"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"signupPage": {
|
||||||
|
"text": {
|
||||||
|
"title": "(es)Create your account",
|
||||||
|
"pageExplanation": "(es)Explanation...",
|
||||||
|
"accountInfoTitle": "(es)Register your account information",
|
||||||
|
"countryExplanation": "(es) Please select your country or the nearest country.",
|
||||||
|
"dealerExplanation": "(es)Please select the dealer to purchase a license.",
|
||||||
|
"adminInfoTitle": "(es)Register primary administrator's information",
|
||||||
|
"passwordTerms": "(es) Please set a password or issue an initial password.\nThe password must be more than 8 or less than 25 letters,numbers and symbols."
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"company": "(es)Company Name",
|
||||||
|
"country": "(es)Country",
|
||||||
|
"dealer": "(es)Dealer (Optional)",
|
||||||
|
"adminName": "(es)Admin Name",
|
||||||
|
"email": "(es)Email",
|
||||||
|
"password": "(es)Password",
|
||||||
|
"termsLink": "(es)Click here to read the terms of use",
|
||||||
|
"termsLinkFor": "(es)for ODDS.",
|
||||||
|
"termsCheckBox": "(es)Yes, I agree to the terms of use.",
|
||||||
|
"createAccountButton": "(es)Create account"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,12 @@
|
|||||||
{
|
{
|
||||||
"common": {
|
"common": {
|
||||||
|
"message": {
|
||||||
|
"inputEmptyError": "(fr)Error Message",
|
||||||
|
"passwordIncorrectError": "(fr)Error Message",
|
||||||
|
"emailIncorrectError": "(fr)Error Message"
|
||||||
|
},
|
||||||
"label": {
|
"label": {
|
||||||
|
"cancel": "(fr)Cancel",
|
||||||
"headerTitle": "(fr)ODMS Cloud",
|
"headerTitle": "(fr)ODMS Cloud",
|
||||||
"copyRight": "(fr)OM Digital Solutions 2023"
|
"copyRight": "(fr)OM Digital Solutions 2023"
|
||||||
}
|
}
|
||||||
@ -17,5 +23,28 @@
|
|||||||
"newUser": "(fr)New user?",
|
"newUser": "(fr)New user?",
|
||||||
"signUpButton": "(fr)Create a new account"
|
"signUpButton": "(fr)Create a new account"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"signupPage": {
|
||||||
|
"text": {
|
||||||
|
"title": "(fr)Create your account",
|
||||||
|
"pageExplanation": "(fr)Explanation...",
|
||||||
|
"accountInfoTitle": "(fr)Register your account information",
|
||||||
|
"countryExplanation": "(fr) Please select your country or the nearest country.",
|
||||||
|
"dealerExplanation": "(fr)Please select the dealer to purchase a license.",
|
||||||
|
"adminInfoTitle": "(fr)Register primary administrator's information",
|
||||||
|
"passwordTerms": "(fr) Please set a password or issue an initial password.\nThe password must be more than 8 or less than 25 letters,numbers and symbols."
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"company": "(fr)Company Name",
|
||||||
|
"country": "(fr)Country",
|
||||||
|
"dealer": "(fr)Dealer (Optional)",
|
||||||
|
"adminName": "(fr)Admin Name",
|
||||||
|
"email": "(fr)Email",
|
||||||
|
"password": "(fr)Password",
|
||||||
|
"termsLink": "(fr)Click here to read the terms of use",
|
||||||
|
"termsLinkFor": "(fr)for ODDS.",
|
||||||
|
"termsCheckBox": "(fr)Yes, I agree to the terms of use.",
|
||||||
|
"createAccountButton": "(fr)Create account"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,8 +15,7 @@
|
|||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"baseUrl": "src",
|
"baseUrl": "src"
|
||||||
"plugins": [{ "name": "typescript-styled-plugin" }]
|
|
||||||
},
|
},
|
||||||
"include": ["src"]
|
"include": ["src"]
|
||||||
}
|
}
|
||||||
|
|||||||
14
dictation_server/package-lock.json
generated
@ -27,6 +27,7 @@
|
|||||||
"connect-redis": "^6.1.3",
|
"connect-redis": "^6.1.3",
|
||||||
"cookie-parser": "^1.4.6",
|
"cookie-parser": "^1.4.6",
|
||||||
"express-session": "^1.17.3",
|
"express-session": "^1.17.3",
|
||||||
|
"helmet": "^6.0.1",
|
||||||
"jsonwebtoken": "^9.0.0",
|
"jsonwebtoken": "^9.0.0",
|
||||||
"jwk-to-pem": "^2.0.5",
|
"jwk-to-pem": "^2.0.5",
|
||||||
"mysql2": "^2.3.3",
|
"mysql2": "^2.3.3",
|
||||||
@ -5934,6 +5935,14 @@
|
|||||||
"minimalistic-assert": "^1.0.1"
|
"minimalistic-assert": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/helmet": {
|
||||||
|
"version": "6.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/helmet/-/helmet-6.0.1.tgz",
|
||||||
|
"integrity": "sha512-8wo+VdQhTMVBMCITYZaGTbE4lvlthelPYSvoyNvk4RECTmrVjMerp9RfUOQXZWLvCcAn1pKj7ZRxK4lI9Alrcw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hexoid": {
|
"node_modules/hexoid": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz",
|
||||||
@ -15442,6 +15451,11 @@
|
|||||||
"minimalistic-assert": "^1.0.1"
|
"minimalistic-assert": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"helmet": {
|
||||||
|
"version": "6.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/helmet/-/helmet-6.0.1.tgz",
|
||||||
|
"integrity": "sha512-8wo+VdQhTMVBMCITYZaGTbE4lvlthelPYSvoyNvk4RECTmrVjMerp9RfUOQXZWLvCcAn1pKj7ZRxK4lI9Alrcw=="
|
||||||
|
},
|
||||||
"hexoid": {
|
"hexoid": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz",
|
||||||
|
|||||||
@ -43,6 +43,7 @@
|
|||||||
"connect-redis": "^6.1.3",
|
"connect-redis": "^6.1.3",
|
||||||
"cookie-parser": "^1.4.6",
|
"cookie-parser": "^1.4.6",
|
||||||
"express-session": "^1.17.3",
|
"express-session": "^1.17.3",
|
||||||
|
"helmet": "^6.0.1",
|
||||||
"jsonwebtoken": "^9.0.0",
|
"jsonwebtoken": "^9.0.0",
|
||||||
"jwk-to-pem": "^2.0.5",
|
"jwk-to-pem": "^2.0.5",
|
||||||
"mysql2": "^2.3.3",
|
"mysql2": "^2.3.3",
|
||||||
|
|||||||
@ -4,12 +4,29 @@ import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
|
|||||||
import { AppModule } from './app.module';
|
import { AppModule } from './app.module';
|
||||||
import { ValidationPipe } from '@nestjs/common';
|
import { ValidationPipe } from '@nestjs/common';
|
||||||
import { LoggerMiddleware } from './common/loggerMiddleware';
|
import { LoggerMiddleware } from './common/loggerMiddleware';
|
||||||
|
import helmet from 'helmet';
|
||||||
|
import crypto from 'crypto';
|
||||||
|
const helmetDirectives = helmet.contentSecurityPolicy.getDefaultDirectives();
|
||||||
|
helmetDirectives['connect-src'] = [
|
||||||
|
"'self'",
|
||||||
|
'https://adb2codmsdev.b2clogin.com/adb2codmsdev.onmicrosoft.com/b2c_1_signin_dev/v2.0/.well-known/openid-configuration',
|
||||||
|
'https://adb2codmsdev.b2clogin.com/adb2codmsdev.onmicrosoft.com/b2c_1_signin_dev/oauth2/v2.0/token',
|
||||||
|
];
|
||||||
|
helmetDirectives['navigate-to'] = ["'self'"];
|
||||||
|
helmetDirectives['style-src'] = ["'self'", 'https:'];
|
||||||
|
helmetDirectives['report-uri'] = ["'self'"];
|
||||||
async function bootstrap() {
|
async function bootstrap() {
|
||||||
const app = await NestFactory.create(AppModule, {
|
const app = await NestFactory.create(AppModule, {
|
||||||
cors: process.env.CORS === 'TRUE',
|
cors: process.env.CORS === 'TRUE',
|
||||||
});
|
});
|
||||||
app.use(new LoggerMiddleware(), cookieParser());
|
app.use(
|
||||||
|
helmet({
|
||||||
|
contentSecurityPolicy: {
|
||||||
|
directives: helmetDirectives,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
cookieParser(),
|
||||||
|
);
|
||||||
|
|
||||||
// バリデーター(+型の自動変換機能)を適用
|
// バリデーター(+型の自動変換機能)を適用
|
||||||
app.useGlobalPipes(
|
app.useGlobalPipes(
|
||||||
|
|||||||