Merged PR 13: タスク 1470: 画面実装(トップページ)

## 概要
[タスク 1470: 画面実装(トップページ)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/OMDSDictation/_workitems/edit/1470)

- トップページのデザインを適用しました。

## レビューポイント
- デザイン適用は適切か
- CSSの使い方に問題はないか

## UIの変更
- トップページのデザイン適用
  - [Task1470](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/Task1470?csf=1&web=1&e=BgUfMX)

## 動作確認状況
- ローカルで起動してデザイン確認
This commit is contained in:
makabe.t 2023-03-14 07:17:36 +00:00
parent 5d4ef8e094
commit a69d8b19f3
15 changed files with 1083 additions and 1159 deletions

File diff suppressed because it is too large Load Diff

View File

@ -30,6 +30,7 @@
"@types/react-router-dom": "^5.3.3",
"@types/redux-mock-store": "^1.0.3",
"axios": "^0.27.2",
"classnames-generics": "^1.0.9",
"eslint-plugin-prefer-arrow": "^1.2.3",
"i18next": "^21.10.0",
"jwt-decode": "^3.1.2",
@ -44,6 +45,7 @@
"react-router-dom": "^6.4.1",
"redux-mock-store": "^1.5.4",
"redux-thunk": "^2.4.1",
"sass": "^1.58.3",
"styled-components": "^5.3.5",
"typescript": "^4.7.4",
"web-vitals": "^2.1.4"
@ -76,6 +78,7 @@
"typescript": "^4.7.4",
"vite": "^2.9.9",
"vite-plugin-env-compatible": "^1.1.1",
"vite-plugin-sass-dts": "^1.3.1",
"vite-tsconfig-paths": "^3.5.0"
},
"eslintConfig": {

View File

@ -1,6 +1,5 @@
import AppRouter from "AppRouter";
import { BrowserRouter } from "react-router-dom";
import { GlobalStyle } from "styles/GlobalStyle";
import { PublicClientApplication } from "@azure/msal-browser";
import { MsalProvider, useMsal } from "@azure/msal-react";
import { msalConfig } from "common/msalConfig";
@ -9,6 +8,7 @@ import { useDispatch } from "react-redux";
import globalAxios, { AxiosError, AxiosResponse } from "axios";
import { clearToken } from "features/auth";
import { useTranslation } from "react-i18next";
import "./styles/GlobalStyle.css";
const App = (): JSX.Element => {
const dispatch = useDispatch();
@ -47,14 +47,11 @@ const App = (): JSX.Element => {
}, [i18n]);
return (
<>
<GlobalStyle />
<MsalProvider instance={pca}>
<BrowserRouter>
<AppRouter />
</BrowserRouter>
</MsalProvider>
</>
<MsalProvider instance={pca}>
<BrowserRouter>
<AppRouter />
</BrowserRouter>
</MsalProvider>
);
};

View File

@ -8,20 +8,16 @@ import { NotFoundPage } from "pages/ErrorPage/notFound";
import { RouteAuthGuard } from "components/auth/routeAuthGuard";
const AppRouter: React.FC = () => (
<BaseDiv>
<Routes>
<Route path="/" element={<TopPage />} />
<Route path="/login" element={<LoginPage />} />
<Route path="/AuthError" element={<AuthErrorPage />} />
<Route
path="/XXX"
element={<RouteAuthGuard component={<SamplePage />} />}
/>
<Route path="*" element={<NotFoundPage />} />
</Routes>
</BaseDiv>
<Routes>
<Route path="/" element={<TopPage />} />
<Route path="/login" element={<LoginPage />} />
<Route path="/AuthError" element={<AuthErrorPage />} />
<Route
path="/XXX"
element={<RouteAuthGuard component={<SamplePage />} />}
/>
<Route path="*" element={<NotFoundPage />} />
</Routes>
);
const BaseDiv = styled.div``;
export default AppRouter;

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@ -0,0 +1,272 @@
.wrap {
display: grid;
grid-template-rows: auto 1fr auto;
grid-template-columns: 1fr;
grid-template-areas: "header" "main" "footer";
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 {
grid-area: main;
}
.mainSmall {
width: 600px;
margin: 0 auto;
padding: 3.2rem 0;
}
.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;
background: #282828;
}
.buttonNormal {
display: inline-block;
width: 15rem;
padding: 0.8rem 2rem;
color: #ffffff;
background: #004086;
border: 1px #004086 solid;
text-decoration: none;
border-radius: 0.3rem;
position: relative;
font-size: 14px;
line-height: 1.4;
letter-spacing: 0;
font-weight: normal;
-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;
}
.buttonNormal:hover {
background: rgba(0, 64, 134, 0.7);
}
.buttonNormal.small {
width: auto;
padding: 0.75rem 2rem;
}
.buttonNormal.red {
background: #e60000;
border: 1px #e60000 solid;
}
.buttonNormal.red:hover {
background: rgba(230, 0, 0, 0.7);
}
.buttonBase {
display: inline-block;
width: 15rem;
padding: 0.8rem 2rem;
color: #004086;
background: #ffffff;
border: 1px #004086 solid;
text-decoration: none;
border-radius: 0.3rem;
position: relative;
font-size: 14px;
line-height: 1.4;
letter-spacing: 0;
font-weight: normal;
-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;
}
.buttonBase:hover {
background: rgba(0, 64, 134, 0.04);
}
.buttonBase.small {
width: auto;
padding: 0.75rem 2rem;
}
.form select option[disabled] {
background: #f5f5f5;
}
.form select option[value=""] {
color: #999999;
}
.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;
}
.formInput:focus {
outline: 0;
}
.formInput.isError {
background: rgba(229, 0, 0, 0.08);
}
.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;
}
}
@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 {
width: 400px;
margin: 15vh auto 0;
padding: 2rem;
background: #ffffff;
box-shadow: 0 0 5px #aaa;
border-radius: 0.3rem;
}
@media only screen and (min-width: 1280px) {
.pgHome > div {
margin: 25vh auto 0 50px;
}
}
.pgHomeLinks {
width: calc(400px - 4rem);
margin: 0 auto;
text-align: center;
}
.pgHomeLinks dt {
padding: 0 0 0.5rem 1rem;
font-size: 16px;
line-height: 1.6;
letter-spacing: 0;
font-weight: normal;
text-align: left;
}
.pgHomeLinks dt:first-of-type {
display: inline-block;
// 言語選択時のデザイン崩れ対応のため調整
min-width: 45%;
width: auto;
padding: 0 0 0 0;
margin-right: 0.3rem;
white-space: nowrap;
}
.pgHomeLinks dd a .buttonIcon {
width: 16px;
height: 16px;
position: absolute;
top: 50%;
right: 2rem;
transform: translateY(-50%);
opacity: 0;
-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;
}
.pgHomeLinks dd a:hover .buttonIcon {
top: 50%;
right: 1.7rem;
opacity: 1;
}
.pgHomeLinks dd:first-of-type {
display: inline-block;
width: 45%;
text-align: left;
}
.pgHomeLinks dd .formInput {
width: auto;
}
.marginBtm1 {
margin-bottom: 1rem;
}
.marginBtm2 {
margin-bottom: 2rem;
}
.marginBtm3 {
margin-bottom: 3rem;
}

View File

@ -0,0 +1,24 @@
declare const classNames: {
readonly wrap: "wrap";
readonly header: "header";
readonly headerLogo: "headerLogo";
readonly headerSub: "headerSub";
readonly main: "main";
readonly mainSmall: "mainSmall";
readonly footer: "footer";
readonly buttonNormal: "buttonNormal";
readonly small: "small";
readonly red: "red";
readonly buttonBase: "buttonBase";
readonly form: "form";
readonly formInput: "formInput";
readonly isError: "isError";
readonly home: "home";
readonly pgHome: "pgHome";
readonly pgHomeLinks: "pgHomeLinks";
readonly buttonIcon: "buttonIcon";
readonly marginBtm1: "marginBtm1";
readonly marginBtm2: "marginBtm2";
readonly marginBtm3: "marginBtm3";
};
export = classNames;

View File

@ -4,6 +4,10 @@ import React from "react";
import { useTranslation } from "react-i18next";
import { getTranslationID } from "translation";
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_bule from "../../assets/images/arrow_forward_blue.svg";
import styles from "./TopPage.module.scss";
const TopPage: React.FC = (): JSX.Element => {
const { instance } = useMsal();
@ -11,21 +15,27 @@ const TopPage: React.FC = (): JSX.Element => {
const [t, i18n] = useTranslation();
return (
<div>
<header>
<div>
<img src="../../assets/images/OMS_logo_black.svg" alt="OM System" />
<div className={`${styles.wrap} ${styles.home}`}>
<header className={`${styles.header} ${styles.home}`}>
<div className={`${styles.headerLogo}`}>
<img src={logo} alt="OM System" />
</div>
<p>ODMS Cloud</p>
<p className={`${styles.headerSub}`}>
{t(getTranslationID("common.label.headerTitle"))}
</p>
</header>
<main>
<section>
<main className={`${styles.main} ${styles.home}`}>
<section className={`${styles.pgHome}`}>
<div>
<dl>
<dt>{t(getTranslationID("topPage.label.displayLanguage"))}</dt>
<dd>
<dl className={`${styles.pgHomeLinks}`}>
<dt>
{`${t(getTranslationID("topPage.label.displayLanguage"))} :`}
</dt>
<dd className={`${styles.marginBtm3}`}>
<select
className={`${styles.formInput}`}
value={i18n.language}
onChange={(e) => {
i18n.changeLanguage(e.currentTarget.value);
// 既にcookieに選択言語があれば削除
@ -41,10 +51,11 @@ const TopPage: React.FC = (): JSX.Element => {
))}
</select>
</dd>
<dt>Already have an account?</dt>
<dd>
<dt>{t(getTranslationID("topPage.label.alreadyHaveAccount"))}</dt>
<dd className={`${styles.marginBtm2}`}>
{/* eslint-disable */}
<a
className={`${styles.buttonNormal}`}
onClick={() => {
// AADB2Cのサインイン画面に言語選択情報を渡す追加のクエリパラメータを設定
loginRequest.extraQueryParameters = {
@ -53,17 +64,22 @@ const TopPage: React.FC = (): JSX.Element => {
instance.loginRedirect(loginRequest);
}}
>
Sign in
<img src="../../assets/images/arrow_forward.svg" alt="" />
{t(getTranslationID("topPage.label.signInButton"))}
<img
src={arrow_forward}
alt=""
className={`${styles.buttonIcon}`}
/>
</a>
</dd>
<dt>New user?</dt>
<dd>
<a href="●●">
Create a new account
<dt>{t(getTranslationID("topPage.label.newUser"))}</dt>
<dd className={`${styles.marginBtm1}`}>
<a href="●●" className={`${styles.buttonBase}`}>
{t(getTranslationID("topPage.label.signUpButton"))}
<img
src="../../assets/images/arrow_forward_blue.svg"
src={arrow_forward_bule}
alt=""
className={`${styles.buttonIcon}`}
/>
</a>
</dd>
@ -72,8 +88,8 @@ const TopPage: React.FC = (): JSX.Element => {
</section>
</main>
<footer>
<div>&copy; OM Digital Solutions 2023</div>
<footer className={`${styles.footer}`}>
<div>&copy; {t(getTranslationID("common.label.copyRight"))}</div>
</footer>
</div>
);

View File

@ -0,0 +1,194 @@
html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
hgroup,
main,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
menu,
nav,
section {
display: block;
}
/* HTML5 hidden-attribute fix for newer browsers */
*[hidden] {
display: none;
}
body {
line-height: 1;
}
ol,
ul {
list-style: none;
}
blockquote,
q {
quotes: none;
}
blockquote:before,
blockquote:after,
q:before,
q:after {
content: "";
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
button {
appearance: none;
padding: 0;
border: none;
outline: none;
background-color: transparent;
cursor: pointer;
}
html {
color: #333333;
font-size: 16px;
line-height: 1.7;
letter-spacing: 0;
font-weight: normal;
}
body {
font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
position: relative;
}
h1 {
font-size: 2.4rem;
line-height: 3.14rem;
letter-spacing: 0.07rem;
font-weight: normal;
}
h2 {
font-size: 2rem;
line-height: 2.57rem;
letter-spacing: 0.07rem;
font-weight: normal;
}
h3 {
font-size: 1.6rem;
line-height: 2rem;
letter-spacing: 0.07rem;
font-weight: normal;
}
h4 {
font-size: 1.2rem;
line-height: 1.57rem;
letter-spacing: 0.07rem;
font-weight: normal;
}
h5 {
font-size: 1.1rem;
line-height: 1.57rem;
letter-spacing: 0.06rem;
font-weight: normal;
}

View File

@ -1,5 +0,0 @@
import { createGlobalStyle } from "styled-components";
/* eslint-disable-next-line @typescript-eslint/naming-convention */
export const GlobalStyle = createGlobalStyle`
`;

View File

@ -1,11 +1,21 @@
{
"common": {
"label": {
"headerTitle": "(de)ODMS Cloud",
"copyRight": "(de)OM Digital Solutions 2023"
}
},
"topPage": {
"label": {
"displayLanguage": "(de)Display Language",
"displayLanguage": "(de)Display language",
"languageEnglish": "(de)English",
"languageGerman": "(de)German",
"languageSpanish": "(de)Spanish",
"languageFrench": "(de)French",
"languageSpanish": "(de)Spanish"
"alreadyHaveAccount": "(de)Already have an account?",
"signInButton": "(de)Sign in",
"newUser": "(de)New user?",
"signUpButton": "(de)Create a new account"
}
}
}

View File

@ -1,11 +1,21 @@
{
"common": {
"label": {
"headerTitle": "ODMS Cloud",
"copyRight": "OM Digital Solutions 2023"
}
},
"topPage": {
"label": {
"displayLanguage": "Display Language",
"displayLanguage": "Display language",
"languageEnglish": "English",
"languageGerman": "German",
"languageSpanish": "Spanish",
"languageFrench": "French",
"languageSpanish": "Spanish"
"alreadyHaveAccount": "Already have an account?",
"signInButton": "Sign in",
"newUser": "New user?",
"signUpButton": "Create a new account"
}
}
}

View File

@ -1,11 +1,21 @@
{
"common": {
"label": {
"headerTitle": "(es)ODMS Cloud",
"copyRight": "(es)OM Digital Solutions 2023"
}
},
"topPage": {
"label": {
"displayLanguage": "(es)Display Language",
"displayLanguage": "(es)Display language",
"languageEnglish": "(es)English",
"languageGerman": "(es)German",
"languageSpanish": "(es)Spanish",
"languageFrench": "(es)French",
"languageSpanish": "(es)Spanish"
"alreadyHaveAccount": "(es)Already have an account?",
"signInButton": "(es)Sign in",
"newUser": "(es)New user?",
"signUpButton": "(es)Create a new account"
}
}
}

View File

@ -1,11 +1,21 @@
{
"common": {
"label": {
"headerTitle": "(fr)ODMS Cloud",
"copyRight": "(fr)OM Digital Solutions 2023"
}
},
"topPage": {
"label": {
"displayLanguage": "(fr)Display Language",
"displayLanguage": "(fr)Display language",
"languageEnglish": "(fr)English",
"languageGerman": "(fr)German",
"languageSpanish": "(fr)Spanish",
"languageFrench": "(fr)French",
"languageSpanish": "(fr)Spanish"
"alreadyHaveAccount": "(fr)Already have an account?",
"signInButton": "(fr)Sign in",
"newUser": "(fr)New user?",
"signUpButton": "(fr)Create a new account"
}
}
}

View File

@ -2,6 +2,7 @@ import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import tsconfigPaths from "vite-tsconfig-paths";
import env from "vite-plugin-env-compatible";
import sassDts from "vite-plugin-sass-dts";
export default defineConfig({
server: {
@ -14,5 +15,5 @@ export default defineConfig({
sourcemap: true,
minify: false,
},
plugins: [env(), tsconfigPaths(), react()],
plugins: [env(), tsconfigPaths(), react(), sassDts()],
});