Merged PR 51: タスク 1468: 部品component作成(ヘッダー・フッター)
## 概要 [Task: 1468](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-2?workitem=1468) - ヘッダーcomponentを作成 - ログイン前とログイン後でヘッダーが異なるので各ページに配置するようにした - 呼び出すcomponentは一つとして作成し、内部でヘッダーを切り替えるようにした - フッターcomponentを作成 - ログイン前とログイン後でページのデザインが異なるのでヘッダー同様、各ページに配置することにした ## レビューポイント - ヘッダーの作成方法に問題はないか ## 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/Task1468?csf=1&web=1&e=K2tFjK ## 動作確認状況 - 型チェック - ローカルで動作確認 ## 補足
This commit is contained in:
parent
dfd9abc1c3
commit
b4cd0208e6
@ -13,6 +13,7 @@ import "./styles/GlobalStyle.css";
|
|||||||
const App = (): JSX.Element => {
|
const App = (): JSX.Element => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const { instance } = useMsal();
|
const { instance } = useMsal();
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
const [t, i18n] = useTranslation();
|
const [t, i18n] = useTranslation();
|
||||||
const pca = new PublicClientApplication(msalConfig);
|
const pca = new PublicClientApplication(msalConfig);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@ -11,10 +11,31 @@ 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 path="/signup" element={<SignupPage completeTo="/" />} />
|
||||||
<Route
|
<Route
|
||||||
path="/XXX"
|
path="/xxx"
|
||||||
|
element={<RouteAuthGuard component={<SamplePage />} />}
|
||||||
|
/>
|
||||||
|
{/* XXX ヘッダーの挙動確認のため仮のページを作成 */}
|
||||||
|
<Route
|
||||||
|
path="/account"
|
||||||
|
element={<RouteAuthGuard component={<SamplePage />} />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="/user"
|
||||||
|
element={<RouteAuthGuard component={<SamplePage />} />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="/dictations"
|
||||||
|
element={<RouteAuthGuard component={<SamplePage />} />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="/license"
|
||||||
|
element={<RouteAuthGuard component={<SamplePage />} />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="/workflow"
|
||||||
element={<RouteAuthGuard component={<SamplePage />} />}
|
element={<RouteAuthGuard component={<SamplePage />} />}
|
||||||
/>
|
/>
|
||||||
<Route path="*" element={<NotFoundPage />} />
|
<Route path="*" element={<NotFoundPage />} />
|
||||||
|
|||||||
10
dictation_client/src/components/footer/footer.module.scss
Normal file
10
dictation_client/src/components/footer/footer.module.scss
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
.footer {
|
||||||
|
grid-area: footer;
|
||||||
|
padding: 0.6rem 0;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 11px;
|
||||||
|
line-height: 1.45;
|
||||||
|
letter-spacing: 0.4px;
|
||||||
|
font-weight: normal;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
4
dictation_client/src/components/footer/footer.module.scss.d.ts
vendored
Normal file
4
dictation_client/src/components/footer/footer.module.scss.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
declare const classNames: {
|
||||||
|
readonly footer: "footer";
|
||||||
|
};
|
||||||
|
export = classNames;
|
||||||
10
dictation_client/src/components/footer/index.tsx
Normal file
10
dictation_client/src/components/footer/index.tsx
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import React from "react";
|
||||||
|
import styles from "./footer.module.scss";
|
||||||
|
|
||||||
|
const Footer: React.FC = () => (
|
||||||
|
<footer className={`${styles.footer}`}>
|
||||||
|
<div>© OM Digital Solutions 2023</div>
|
||||||
|
</footer>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default Footer;
|
||||||
12
dictation_client/src/components/header/constants.ts
Normal file
12
dictation_client/src/components/header/constants.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { HeaderMenus, LoginedPaths } from "./types";
|
||||||
|
|
||||||
|
export const HEADER_MENUS: { label: HeaderMenus; path: LoginedPaths }[] = [
|
||||||
|
{ label: "Account", path: "/account" },
|
||||||
|
{ label: "Dictations", path: "/dictations" },
|
||||||
|
{ label: "License", path: "/license" },
|
||||||
|
{ label: "User", path: "/user" },
|
||||||
|
{ label: "Workflow", path: "/workflow" },
|
||||||
|
{ label: "XXX", path: "/xxx" }, // XXX 仮のタブ
|
||||||
|
];
|
||||||
|
|
||||||
|
export const HEADER_NAME = "ODMS Cloud";
|
||||||
47
dictation_client/src/components/header/header.module.scss
Normal file
47
dictation_client/src/components/header/header.module.scss
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
.header {
|
||||||
|
grid-area: header;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-between;
|
||||||
|
box-shadow: 0 0 3px #282828;
|
||||||
|
background: linear-gradient(#ffffff, #ffffff 70%, #f0f0f0 100%);
|
||||||
|
z-index: 4;
|
||||||
|
}
|
||||||
|
.headerLogo {
|
||||||
|
margin: 1.8rem 2rem 1rem;
|
||||||
|
font-size: 1.71rem;
|
||||||
|
line-height: 2rem;
|
||||||
|
letter-spacing: 0.07rem;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
.headerLogo img {
|
||||||
|
width: 198px;
|
||||||
|
}
|
||||||
|
.headerSub {
|
||||||
|
margin: 1.8rem 2rem 1rem;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
line-height: 2rem;
|
||||||
|
letter-spacing: 0.07rem;
|
||||||
|
font-weight: normal;
|
||||||
|
font-weight: 600;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (min-width: 1280px) {
|
||||||
|
.header.home {
|
||||||
|
display: block;
|
||||||
|
padding-top: 30vh;
|
||||||
|
padding-left: 40%;
|
||||||
|
background: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header.home .headerSub {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
line-height: 2rem;
|
||||||
|
letter-spacing: 0.07rem;
|
||||||
|
font-weight: 600;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
7
dictation_client/src/components/header/header.module.scss.d.ts
vendored
Normal file
7
dictation_client/src/components/header/header.module.scss.d.ts
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
declare const classNames: {
|
||||||
|
readonly header: "header";
|
||||||
|
readonly headerLogo: "headerLogo";
|
||||||
|
readonly headerSub: "headerSub";
|
||||||
|
readonly home: "home";
|
||||||
|
};
|
||||||
|
export = classNames;
|
||||||
25
dictation_client/src/components/header/index.tsx
Normal file
25
dictation_client/src/components/header/index.tsx
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { useLocation } from "react-router-dom";
|
||||||
|
import LoginedHeader from "./loginedHeader";
|
||||||
|
import NotLoginHeader from "./notLoginHeader";
|
||||||
|
import { isLoginPaths } from "./utils";
|
||||||
|
|
||||||
|
interface HeaderProps {
|
||||||
|
userName?: string;
|
||||||
|
// userRole: string; ログインユーザーのロールに応じてタブの活性非活性に使用する想定
|
||||||
|
}
|
||||||
|
// ヘッダー切り替え用のcomponent
|
||||||
|
const Header: React.FC<HeaderProps> = (props) => {
|
||||||
|
const { userName } = props;
|
||||||
|
const location = useLocation();
|
||||||
|
return getHeader(location.pathname, userName);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Header;
|
||||||
|
|
||||||
|
const getHeader = (path: string, userName?: string) => {
|
||||||
|
if (isLoginPaths(path) && userName) {
|
||||||
|
return <LoginedHeader name={userName} activePath={path} />;
|
||||||
|
}
|
||||||
|
return <NotLoginHeader isMobile={path === "/"} />;
|
||||||
|
};
|
||||||
@ -0,0 +1,87 @@
|
|||||||
|
.header {
|
||||||
|
grid-area: header;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-between;
|
||||||
|
box-shadow: 0 0 3px #282828;
|
||||||
|
background: linear-gradient(#ffffff, #ffffff 70%, #f0f0f0 100%);
|
||||||
|
z-index: 4;
|
||||||
|
}
|
||||||
|
.headerLogo {
|
||||||
|
margin: 1.2rem 2rem 1rem;
|
||||||
|
font-size: 1.71rem;
|
||||||
|
line-height: 2rem;
|
||||||
|
letter-spacing: 0.07rem;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
.headerLogo img {
|
||||||
|
width: 198px;
|
||||||
|
}
|
||||||
|
.headerSub {
|
||||||
|
margin: 1.4rem 2rem 1rem;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
line-height: 2rem;
|
||||||
|
letter-spacing: 0.07rem;
|
||||||
|
font-weight: normal;
|
||||||
|
font-weight: 600;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.headerMenu {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.headerMenu ul {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: 0 2rem;
|
||||||
|
}
|
||||||
|
.headerMenu ul li {
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 2rem;
|
||||||
|
letter-spacing: 0.07rem;
|
||||||
|
font-weight: normal;
|
||||||
|
border-left: 1px #e6e6e6 solid;
|
||||||
|
}
|
||||||
|
.headerMenu ul li a {
|
||||||
|
display: block;
|
||||||
|
padding: 0 2rem;
|
||||||
|
color: #333333;
|
||||||
|
text-decoration: none;
|
||||||
|
-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;
|
||||||
|
}
|
||||||
|
.headerMenu ul li a:hover {
|
||||||
|
background: #fafafa;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.headerMenu ul li a.isActive {
|
||||||
|
font-weight: 600;
|
||||||
|
pointer-events: none;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.headerMenu ul li a.isActive::after {
|
||||||
|
content: "";
|
||||||
|
border-right: 0.6rem transparent solid;
|
||||||
|
border-bottom: 0.6rem #282828 solid;
|
||||||
|
border-left: 0.6rem transparent solid;
|
||||||
|
position: absolute;
|
||||||
|
bottom: -4px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.accountInfo {
|
||||||
|
position: absolute;
|
||||||
|
right: 2rem;
|
||||||
|
bottom: 0.3rem;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
line-height: 1.6rem;
|
||||||
|
letter-spacing: 0.04rem;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
.accountIcon {
|
||||||
|
width: 1.4rem;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
10
dictation_client/src/components/header/loginedHeader.module.scss.d.ts
vendored
Normal file
10
dictation_client/src/components/header/loginedHeader.module.scss.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
declare const classNames: {
|
||||||
|
readonly header: "header";
|
||||||
|
readonly headerLogo: "headerLogo";
|
||||||
|
readonly headerSub: "headerSub";
|
||||||
|
readonly headerMenu: "headerMenu";
|
||||||
|
readonly isActive: "isActive";
|
||||||
|
readonly accountInfo: "accountInfo";
|
||||||
|
readonly accountIcon: "accountIcon";
|
||||||
|
};
|
||||||
|
export = classNames;
|
||||||
51
dictation_client/src/components/header/loginedHeader.tsx
Normal file
51
dictation_client/src/components/header/loginedHeader.tsx
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import React from "react";
|
||||||
|
import styles from "./loginedHeader.module.scss";
|
||||||
|
|
||||||
|
import logo from "../../assets/images/OMS_logo_black.svg";
|
||||||
|
import ac from "../../assets/images/account_circle.svg";
|
||||||
|
import { LoginedPaths } from "./types";
|
||||||
|
import { HEADER_MENUS, HEADER_NAME } from "./constants";
|
||||||
|
|
||||||
|
interface HeaderProps {
|
||||||
|
// userRole: "user" | "partner"; ログインユーザーのロールに応じてタブの活性非活性に使用する想定
|
||||||
|
name: string;
|
||||||
|
activePath: LoginedPaths;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ログイン後のヘッダー
|
||||||
|
const LoginedHeader: React.FC<HeaderProps> = (props: HeaderProps) => {
|
||||||
|
const { name, activePath } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<header className={styles.header}>
|
||||||
|
<div className={styles.headerLogo}>
|
||||||
|
<img src={logo} alt="OM System" />
|
||||||
|
</div>
|
||||||
|
<div className={styles.headerSub}>{HEADER_NAME}</div>
|
||||||
|
<div className={styles.headerMenu}>
|
||||||
|
<ul>
|
||||||
|
{HEADER_MENUS.map((x) => (
|
||||||
|
<li key={x.label}>
|
||||||
|
<a
|
||||||
|
href={x.path}
|
||||||
|
className={
|
||||||
|
activePath.toUpperCase() === x.path.toUpperCase()
|
||||||
|
? styles.isActive
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{x.label}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
<p className={styles.accountInfo}>
|
||||||
|
<img src={ac} alt="" className={styles.accountIcon} />
|
||||||
|
|
||||||
|
<span>{name}</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default LoginedHeader;
|
||||||
27
dictation_client/src/components/header/notLoginHeader.tsx
Normal file
27
dictation_client/src/components/header/notLoginHeader.tsx
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import React from "react";
|
||||||
|
import styles from "./header.module.scss";
|
||||||
|
|
||||||
|
import logo from "../../assets/images/OMS_logo_black.svg";
|
||||||
|
import { HEADER_NAME } from "./constants";
|
||||||
|
|
||||||
|
interface NotLoginHeaderProps {
|
||||||
|
isMobile?: boolean;
|
||||||
|
}
|
||||||
|
// ログインしていない時のヘッダー
|
||||||
|
const NotLoginHeader: React.FC<NotLoginHeaderProps> = (
|
||||||
|
props: NotLoginHeaderProps
|
||||||
|
) => {
|
||||||
|
const { isMobile } = props;
|
||||||
|
return (
|
||||||
|
<header className={`${styles.header} ${isMobile && styles.home}`}>
|
||||||
|
<div className={`${styles.headerLogo}`}>
|
||||||
|
<img src={logo} alt="OM System" />
|
||||||
|
</div>
|
||||||
|
<p className={`${styles.headerSub}`}>{HEADER_NAME}</p>
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
NotLoginHeader.defaultProps = {
|
||||||
|
isMobile: false,
|
||||||
|
};
|
||||||
|
export default NotLoginHeader;
|
||||||
20
dictation_client/src/components/header/types.ts
Normal file
20
dictation_client/src/components/header/types.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// ページパス
|
||||||
|
export type Paths = LoginedPaths | "/" | "/signup" | "login";
|
||||||
|
|
||||||
|
// ログイン後のヘッダータブ
|
||||||
|
export type HeaderMenus =
|
||||||
|
| "Account"
|
||||||
|
| "User"
|
||||||
|
| "License"
|
||||||
|
| "Dictations"
|
||||||
|
| "Workflow"
|
||||||
|
| "XXX";
|
||||||
|
|
||||||
|
// ログイン後に遷移しうるパス
|
||||||
|
export type LoginedPaths =
|
||||||
|
| "/account"
|
||||||
|
| "/user"
|
||||||
|
| "/license"
|
||||||
|
| "/dictations"
|
||||||
|
| "/workflow"
|
||||||
|
| "/xxx";
|
||||||
21
dictation_client/src/components/header/utils.ts
Normal file
21
dictation_client/src/components/header/utils.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { LoginedPaths } from "./types";
|
||||||
|
|
||||||
|
// ログイン後のパスかどうか判定
|
||||||
|
export const isLoginPaths = (d: string): d is LoginedPaths => {
|
||||||
|
// caseに入力補完で取りうるリテラルしか出なくする
|
||||||
|
const type = d as LoginedPaths;
|
||||||
|
switch (type) {
|
||||||
|
case "/account":
|
||||||
|
case "/user":
|
||||||
|
case "/license":
|
||||||
|
case "/dictations":
|
||||||
|
case "/workflow":
|
||||||
|
case "/xxx":
|
||||||
|
return true;
|
||||||
|
default: {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
const _: never = type;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -1,9 +1,7 @@
|
|||||||
import { UpdateTokenTimer } from "components/auth/updateTokenTimer";
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
export const AuthErrorPage = (): JSX.Element => (
|
export const AuthErrorPage = (): JSX.Element => (
|
||||||
<div>
|
<div>
|
||||||
<UpdateTokenTimer />
|
|
||||||
<p>ログインに失敗しました</p>
|
<p>ログインに失敗しました</p>
|
||||||
<br />
|
<br />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import { InteractionStatus, SilentRequest } from "@azure/msal-browser";
|
import { InteractionStatus, SilentRequest } from "@azure/msal-browser";
|
||||||
import { useIsAuthenticated, useMsal } from "@azure/msal-react";
|
import { useIsAuthenticated, useMsal } from "@azure/msal-react";
|
||||||
import { AppDispatch } from "app/store";
|
import { AppDispatch } from "app/store";
|
||||||
|
import Footer from "components/footer";
|
||||||
|
import Header from "components/header";
|
||||||
import { loginAsync } from "features/login";
|
import { loginAsync } from "features/login";
|
||||||
import React, { useCallback, useEffect } from "react";
|
import React, { useCallback, useEffect } from "react";
|
||||||
import { useDispatch } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
@ -26,7 +28,7 @@ const LoginPage: React.FC = (): JSX.Element => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (meta.requestStatus === "fulfilled") {
|
if (meta.requestStatus === "fulfilled") {
|
||||||
navigate("/XXX");
|
navigate("/xxx");
|
||||||
}
|
}
|
||||||
}, [accounts, dispatch, instance, navigate]);
|
}, [accounts, dispatch, instance, navigate]);
|
||||||
|
|
||||||
@ -45,7 +47,13 @@ const LoginPage: React.FC = (): JSX.Element => {
|
|||||||
navigate,
|
navigate,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return <h3>loading ...</h3>;
|
return (
|
||||||
|
<>
|
||||||
|
<Header />
|
||||||
|
<h3>loading ...</h3>
|
||||||
|
<Footer />
|
||||||
|
</>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LoginPage;
|
export default LoginPage;
|
||||||
|
|||||||
@ -1,26 +1,33 @@
|
|||||||
import { useMsal } from "@azure/msal-react";
|
import { useMsal } from "@azure/msal-react";
|
||||||
import { AppDispatch } from "app/store";
|
import { AppDispatch } from "app/store";
|
||||||
import { UpdateTokenTimer } from "components/auth/updateTokenTimer";
|
import { UpdateTokenTimer } from "components/auth/updateTokenTimer";
|
||||||
|
import Footer from "components/footer";
|
||||||
|
import Header from "components/header";
|
||||||
import { clearToken } from "features/auth";
|
import { clearToken } from "features/auth";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useDispatch } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
|
import styles from "./sample.module.scss";
|
||||||
|
|
||||||
const SamplePage: React.FC = (): JSX.Element => {
|
const SamplePage: React.FC = (): JSX.Element => {
|
||||||
const { instance } = useMsal();
|
const { instance } = useMsal();
|
||||||
const dispatch: AppDispatch = useDispatch();
|
const dispatch: AppDispatch = useDispatch();
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className={styles.wrap}>
|
||||||
|
<Header userName="XXXXXX" />
|
||||||
<UpdateTokenTimer />
|
<UpdateTokenTimer />
|
||||||
<h1>hello world!!</h1>
|
<div>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
className={styles.button}
|
||||||
instance.logout({ postLogoutRedirectUri: "/" });
|
onClick={() => {
|
||||||
dispatch(clearToken());
|
instance.logout({ postLogoutRedirectUri: "/" });
|
||||||
}}
|
dispatch(clearToken());
|
||||||
>
|
}}
|
||||||
sign out
|
>
|
||||||
</button>
|
sign out
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
21
dictation_client/src/pages/SamplePage/sample.module.scss
Normal file
21
dictation_client/src/pages/SamplePage/sample.module.scss
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
.wrap {
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: auto 1fr auto;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
grid-template-areas: "header" "main" "footer";
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
display: block;
|
||||||
|
padding: 12px 0;
|
||||||
|
color: #ffffff;
|
||||||
|
text-decoration: none;
|
||||||
|
background: #005eb8;
|
||||||
|
border: 1px #005eb8 solid;
|
||||||
|
margin-left: 100px;
|
||||||
|
cursor: pointer;
|
||||||
|
:hover {
|
||||||
|
background: rgba(0, 94, 184, 0.7);
|
||||||
|
}
|
||||||
|
}
|
||||||
5
dictation_client/src/pages/SamplePage/sample.module.scss.d.ts
vendored
Normal file
5
dictation_client/src/pages/SamplePage/sample.module.scss.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
declare const classNames: {
|
||||||
|
readonly wrap: "wrap";
|
||||||
|
readonly button: "button";
|
||||||
|
};
|
||||||
|
export = classNames;
|
||||||
@ -1,3 +1,5 @@
|
|||||||
|
import Footer from "components/footer";
|
||||||
|
import Header from "components/header";
|
||||||
import { selectPageState } from "features/signup/selectors";
|
import { selectPageState } from "features/signup/selectors";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
@ -9,7 +11,13 @@ const SignupPage: React.FC<{ completeTo: string }> = ({
|
|||||||
}): JSX.Element => {
|
}): JSX.Element => {
|
||||||
const state = useSelector(selectPageState);
|
const state = useSelector(selectPageState);
|
||||||
|
|
||||||
return getComponent(state, completeTo);
|
return (
|
||||||
|
<>
|
||||||
|
<Header />
|
||||||
|
{getComponent(state, completeTo)}
|
||||||
|
<Footer />
|
||||||
|
</>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 現在のサインアップ画面の状態に応じて表示Componentを出し分ける
|
// 現在のサインアップ画面の状態に応じて表示Componentを出し分ける
|
||||||
|
|||||||
@ -6,39 +6,6 @@
|
|||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
|
||||||
grid-area: header;
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: space-between;
|
|
||||||
box-shadow: 0 0 3px #282828;
|
|
||||||
background: linear-gradient(#ffffff, #ffffff 70%, #f0f0f0 100%);
|
|
||||||
z-index: 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.headerLogo {
|
|
||||||
margin: 1.8rem 2rem 1rem;
|
|
||||||
font-size: 1.71rem;
|
|
||||||
line-height: 2rem;
|
|
||||||
letter-spacing: 0.07rem;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.headerLogo img {
|
|
||||||
width: 198px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.headerSub {
|
|
||||||
margin: 1.8rem 2rem 1rem;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
line-height: 2rem;
|
|
||||||
letter-spacing: 0.07rem;
|
|
||||||
font-weight: normal;
|
|
||||||
font-weight: 600;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main {
|
.main {
|
||||||
grid-area: main;
|
grid-area: main;
|
||||||
}
|
}
|
||||||
@ -171,24 +138,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (min-width: 1280px) {
|
|
||||||
.header.home {
|
|
||||||
display: block;
|
|
||||||
padding-top: 30vh;
|
|
||||||
padding-left: 40%;
|
|
||||||
background: none;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header.home .headerSub {
|
|
||||||
font-size: 1.4rem;
|
|
||||||
line-height: 2rem;
|
|
||||||
letter-spacing: 0.07rem;
|
|
||||||
font-weight: 600;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.pgHome > div {
|
.pgHome > div {
|
||||||
width: 400px;
|
width: 400px;
|
||||||
margin: 15vh auto 0;
|
margin: 15vh auto 0;
|
||||||
|
|||||||
@ -1,8 +1,5 @@
|
|||||||
declare const classNames: {
|
declare const classNames: {
|
||||||
readonly wrap: "wrap";
|
readonly wrap: "wrap";
|
||||||
readonly header: "header";
|
|
||||||
readonly headerLogo: "headerLogo";
|
|
||||||
readonly headerSub: "headerSub";
|
|
||||||
readonly main: "main";
|
readonly main: "main";
|
||||||
readonly mainSmall: "mainSmall";
|
readonly mainSmall: "mainSmall";
|
||||||
readonly footer: "footer";
|
readonly footer: "footer";
|
||||||
|
|||||||
@ -3,8 +3,9 @@ import { loginRequest } from "common/msalConfig";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { getTranslationID } from "translation";
|
import { getTranslationID } from "translation";
|
||||||
|
import Header from "components/header";
|
||||||
|
import Footer from "components/footer";
|
||||||
import { LANGUAGE_LIST } from "../../features/top/constants";
|
import { LANGUAGE_LIST } from "../../features/top/constants";
|
||||||
import logo from "../../assets/images/OMS_logo_black.svg";
|
|
||||||
import arrow_forward from "../../assets/images/arrow_forward.svg";
|
import arrow_forward from "../../assets/images/arrow_forward.svg";
|
||||||
import arrow_forward_bule from "../../assets/images/arrow_forward_blue.svg";
|
import arrow_forward_bule from "../../assets/images/arrow_forward_blue.svg";
|
||||||
import styles from "./TopPage.module.scss";
|
import styles from "./TopPage.module.scss";
|
||||||
@ -16,14 +17,7 @@ const TopPage: React.FC = (): JSX.Element => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`${styles.wrap} ${styles.home}`}>
|
<div className={`${styles.wrap} ${styles.home}`}>
|
||||||
<header className={`${styles.header} ${styles.home}`}>
|
<Header />
|
||||||
<div className={`${styles.headerLogo}`}>
|
|
||||||
<img src={logo} alt="OM System" />
|
|
||||||
</div>
|
|
||||||
<p className={`${styles.headerSub}`}>
|
|
||||||
{t(getTranslationID("common.label.headerTitle"))}
|
|
||||||
</p>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<main className={`${styles.main} ${styles.home}`}>
|
<main className={`${styles.main} ${styles.home}`}>
|
||||||
<section className={`${styles.pgHome}`}>
|
<section className={`${styles.pgHome}`}>
|
||||||
@ -87,10 +81,7 @@ const TopPage: React.FC = (): JSX.Element => {
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
<Footer />
|
||||||
<footer className={`${styles.footer}`}>
|
|
||||||
<div>© {t(getTranslationID("common.label.copyRight"))}</div>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
21
dictation_client/src/styles/app.module.scss
Normal file
21
dictation_client/src/styles/app.module.scss
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
.wrap {
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: auto 1fr auto;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
grid-template-areas: "header" "main" "footer";
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
.wrap.home {
|
||||||
|
background: url("../assets/images/top-bg04.png") no-repeat bottom center;
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (min-width: 1280px) {
|
||||||
|
.wrap.home {
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: 1fr auto;
|
||||||
|
grid-template-columns: 45% 1fr;
|
||||||
|
grid-template-areas: "header main" "footer footer";
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
}
|
||||||
5
dictation_client/src/styles/app.module.scss.d.ts
vendored
Normal file
5
dictation_client/src/styles/app.module.scss.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
declare const classNames: {
|
||||||
|
readonly wrap: "wrap";
|
||||||
|
readonly home: "home";
|
||||||
|
};
|
||||||
|
export = classNames;
|
||||||
Loading…
x
Reference in New Issue
Block a user