Merged PR 472: 画面作成(利用規約同意画面)
## 概要 [Task2802: 画面作成(利用規約同意画面)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2802) - 何をどう変更したか、追加したライブラリなど - 利用規約同意画面の実装を行いました - このPull Requestでの対象/対象外 - api.tsおよびstyles - 影響範囲(他の機能にも影響があるか) - ありません ## レビューポイント - 特にレビューしてほしい箇所 - URLの妥当性(動作確認のため別タスクで追加していますが、内容は本タスクで見てほしいです) 違和感ないか確認お願いします。 <Route path="/accept-to-use" element={<AcceptToUsePage />} /> - 各処理のエラーハンドリングについて ## UIの変更 - Before/Afterのスクショなど - スクショ置き場 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/Task2802?csf=1&web=1&e=otF5YX ## 動作確認状況 - ローカルで確認済 ## 補足 - 相談、参考資料などがあれば
This commit is contained in:
parent
74bf434786
commit
7196491cf0
@ -21,7 +21,7 @@ import WorkflowPage from "pages/WorkflowPage";
|
|||||||
import TypistGroupSettingPage from "pages/TypistGroupSettingPage";
|
import TypistGroupSettingPage from "pages/TypistGroupSettingPage";
|
||||||
import WorktypeIdSettingPage from "pages/WorkTypeIdSettingPage";
|
import WorktypeIdSettingPage from "pages/WorkTypeIdSettingPage";
|
||||||
import AccountPage from "pages/AccountPage";
|
import AccountPage from "pages/AccountPage";
|
||||||
import AcceptToUsePage from "pages/AcceptToUsePage";
|
import AcceptToUsePage from "pages/TermsPage";
|
||||||
import { TemplateFilePage } from "pages/TemplateFilePage";
|
import { TemplateFilePage } from "pages/TemplateFilePage";
|
||||||
import { AccountDeleteSuccess } from "pages/AccountPage/accountDeleteSuccess";
|
import { AccountDeleteSuccess } from "pages/AccountPage/accountDeleteSuccess";
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ const AppRouter: React.FC = () => (
|
|||||||
path="/signup"
|
path="/signup"
|
||||||
element={<SignupPage completeTo="/signup/complete" />}
|
element={<SignupPage completeTo="/signup/complete" />}
|
||||||
/>
|
/>
|
||||||
<Route path="/accept-to-use" element={<AcceptToUsePage />} />
|
<Route path="/terms" element={<AcceptToUsePage />} />
|
||||||
<Route path="/signup/complete" element={<SignupCompletePage />} />
|
<Route path="/signup/complete" element={<SignupCompletePage />} />
|
||||||
<Route path="/mail-confirm/" element={<VerifyPage />} />
|
<Route path="/mail-confirm/" element={<VerifyPage />} />
|
||||||
<Route path="/mail-confirm/user" element={<UserVerifyPage />} />
|
<Route path="/mail-confirm/user" element={<UserVerifyPage />} />
|
||||||
|
|||||||
@ -18,6 +18,7 @@ import worktype from "features/workflow/worktype/worktypeSlice";
|
|||||||
import account from "features/account/accountSlice";
|
import account from "features/account/accountSlice";
|
||||||
import template from "features/workflow/template/templateSlice";
|
import template from "features/workflow/template/templateSlice";
|
||||||
import workflow from "features/workflow/workflowSlice";
|
import workflow from "features/workflow/workflowSlice";
|
||||||
|
import terms from "features/terms/termsSlice";
|
||||||
|
|
||||||
export const store = configureStore({
|
export const store = configureStore({
|
||||||
reducer: {
|
reducer: {
|
||||||
@ -40,6 +41,7 @@ export const store = configureStore({
|
|||||||
account,
|
account,
|
||||||
template,
|
template,
|
||||||
workflow,
|
workflow,
|
||||||
|
terms,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -62,3 +62,16 @@ export const isIdToken = (arg: any): arg is IdToken => {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getIdTokenFromLocalStorage = (
|
||||||
|
localStorageKeyforIdToken: string
|
||||||
|
): string | null => {
|
||||||
|
const idTokenString = localStorage.getItem(localStorageKeyforIdToken);
|
||||||
|
if (idTokenString) {
|
||||||
|
const idTokenObject = JSON.parse(idTokenString);
|
||||||
|
if (isIdToken(idTokenObject)) {
|
||||||
|
return idTokenObject.secret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|||||||
8
dictation_client/src/features/terms/constants.ts
Normal file
8
dictation_client/src/features/terms/constants.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* 利用規約の種類
|
||||||
|
* @const {string[]}
|
||||||
|
*/
|
||||||
|
export const TERMS_DOCUMENT_TYPE = {
|
||||||
|
DPA: "DPA",
|
||||||
|
EULA: "EULA",
|
||||||
|
} as const;
|
||||||
4
dictation_client/src/features/terms/index.ts
Normal file
4
dictation_client/src/features/terms/index.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export * from "./termsSlice";
|
||||||
|
export * from "./state";
|
||||||
|
export * from "./operations";
|
||||||
|
export * from "./selectors";
|
||||||
158
dictation_client/src/features/terms/operations.ts
Normal file
158
dictation_client/src/features/terms/operations.ts
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||||
|
import type { RootState } from "app/store";
|
||||||
|
import { ErrorObject, createErrorObject } from "common/errors";
|
||||||
|
import { getTranslationID } from "translation";
|
||||||
|
import { openSnackbar } from "features/ui/uiSlice";
|
||||||
|
import { getIdTokenFromLocalStorage } from "common/token";
|
||||||
|
import { TIERS } from "components/auth/constants";
|
||||||
|
import {
|
||||||
|
UsersApi,
|
||||||
|
GetAccountInfoMinimalAccessResponse,
|
||||||
|
AccountsApi,
|
||||||
|
TermsApi,
|
||||||
|
GetTermsInfoResponse,
|
||||||
|
} from "../../api/api";
|
||||||
|
import { Configuration } from "../../api/configuration";
|
||||||
|
|
||||||
|
export const getAccountInfoMinimalAccessAsync = createAsyncThunk<
|
||||||
|
GetAccountInfoMinimalAccessResponse,
|
||||||
|
{
|
||||||
|
localStorageKeyforIdToken: string;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// rejectした時の返却値の型
|
||||||
|
rejectValue: {
|
||||||
|
error: ErrorObject;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
>("accept/getAccountInfoMinimalAccessAsync", async (args, thunkApi) => {
|
||||||
|
const { localStorageKeyforIdToken } = args;
|
||||||
|
// apiのConfigurationを取得する
|
||||||
|
const { getState } = thunkApi;
|
||||||
|
const state = getState() as RootState;
|
||||||
|
const { configuration, accessToken } = state.auth;
|
||||||
|
const config = new Configuration(configuration);
|
||||||
|
const accountApi = new AccountsApi(config);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// IDトークンの取得
|
||||||
|
const idToken = getIdTokenFromLocalStorage(localStorageKeyforIdToken);
|
||||||
|
|
||||||
|
// IDトークンが取得できない場合エラーとする
|
||||||
|
if (!idToken) {
|
||||||
|
throw new Error("Unable to retrieve the ID token.");
|
||||||
|
}
|
||||||
|
const res = await accountApi.getAccountInfoMinimalAccess(
|
||||||
|
{ idToken },
|
||||||
|
{
|
||||||
|
headers: { authorization: `Bearer ${accessToken}` },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return res.data;
|
||||||
|
} catch (e) {
|
||||||
|
const error = createErrorObject(e);
|
||||||
|
thunkApi.dispatch(
|
||||||
|
openSnackbar({
|
||||||
|
level: "error",
|
||||||
|
message: getTranslationID("common.message.internalServerError"),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return thunkApi.rejectWithValue({ error });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export const getTermsInfoAsync = createAsyncThunk<
|
||||||
|
GetTermsInfoResponse,
|
||||||
|
void,
|
||||||
|
{
|
||||||
|
// rejectした時の返却値の型
|
||||||
|
rejectValue: {
|
||||||
|
error: ErrorObject;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
>("accept/getTermsInfoAsync", async (_args, thunkApi) => {
|
||||||
|
// apiのConfigurationを取得する
|
||||||
|
const { getState } = thunkApi;
|
||||||
|
const state = getState() as RootState;
|
||||||
|
const { configuration, accessToken } = state.auth;
|
||||||
|
const config = new Configuration(configuration);
|
||||||
|
const termsApi = new TermsApi(config);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const termsInfo = await termsApi.getTermsInfo({
|
||||||
|
headers: { authorization: `Bearer ${accessToken}` },
|
||||||
|
});
|
||||||
|
|
||||||
|
return termsInfo.data;
|
||||||
|
} catch (e) {
|
||||||
|
// e ⇒ errorObjectに変換"
|
||||||
|
const error = createErrorObject(e);
|
||||||
|
thunkApi.dispatch(
|
||||||
|
openSnackbar({
|
||||||
|
level: "error",
|
||||||
|
message: getTranslationID("common.message.internalServerError"),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return thunkApi.rejectWithValue({ error });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export const updateAcceptedVersionAsync = createAsyncThunk<
|
||||||
|
{
|
||||||
|
/* Empty Object */
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tier: number;
|
||||||
|
localStorageKeyforIdToken: string;
|
||||||
|
updateAccceptVersions: {
|
||||||
|
acceptedVerDPA: string;
|
||||||
|
acceptedVerEULA: string;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// rejectした時の返却値の型
|
||||||
|
rejectValue: {
|
||||||
|
error: ErrorObject;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
>("accept/UpdateAcceptedVersionAsync", async (args, thunkApi) => {
|
||||||
|
const { tier, localStorageKeyforIdToken, updateAccceptVersions } = args;
|
||||||
|
// apiのConfigurationを取得する
|
||||||
|
const { getState } = thunkApi;
|
||||||
|
const state = getState() as RootState;
|
||||||
|
const { configuration, accessToken } = state.auth;
|
||||||
|
const config = new Configuration(configuration);
|
||||||
|
const userApi = new UsersApi(config);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// IDトークンの取得
|
||||||
|
const idToken = getIdTokenFromLocalStorage(localStorageKeyforIdToken);
|
||||||
|
|
||||||
|
// IDトークンが取得できない場合エラーとする
|
||||||
|
if (!idToken) {
|
||||||
|
throw new Error("Unable to retrieve the ID token.");
|
||||||
|
}
|
||||||
|
await userApi.updateAcceptedVersion(
|
||||||
|
{
|
||||||
|
idToken,
|
||||||
|
acceptedEULAVersion: updateAccceptVersions.acceptedVerEULA,
|
||||||
|
acceptedDPAVersion: !(TIERS.TIER5 === tier.toString())
|
||||||
|
? updateAccceptVersions.acceptedVerDPA
|
||||||
|
: undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: { authorization: `Bearer ${accessToken}` },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return {};
|
||||||
|
} catch (e) {
|
||||||
|
const error = createErrorObject(e);
|
||||||
|
thunkApi.dispatch(
|
||||||
|
openSnackbar({
|
||||||
|
level: "error",
|
||||||
|
message: getTranslationID("common.message.internalServerError"),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return thunkApi.rejectWithValue({ error });
|
||||||
|
}
|
||||||
|
});
|
||||||
20
dictation_client/src/features/terms/selectors.ts
Normal file
20
dictation_client/src/features/terms/selectors.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { RootState } from "app/store";
|
||||||
|
import { TERMS_DOCUMENT_TYPE } from "features/terms/constants";
|
||||||
|
|
||||||
|
export const selectTermVersions = (state: RootState) => {
|
||||||
|
const { termsInfo } = state.terms.domain;
|
||||||
|
|
||||||
|
const acceptedVerDPA =
|
||||||
|
termsInfo.find(
|
||||||
|
(termInfo) => termInfo.documentType === TERMS_DOCUMENT_TYPE.DPA
|
||||||
|
)?.version || "";
|
||||||
|
|
||||||
|
const acceptedVerEULA =
|
||||||
|
termsInfo.find(
|
||||||
|
(termInfo) => termInfo.documentType === TERMS_DOCUMENT_TYPE.EULA
|
||||||
|
)?.version || "";
|
||||||
|
|
||||||
|
return { acceptedVerDPA, acceptedVerEULA };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const selectTier = (state: RootState) => state.terms.domain.tier;
|
||||||
15
dictation_client/src/features/terms/state.ts
Normal file
15
dictation_client/src/features/terms/state.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { TermInfo } from "../../api/api";
|
||||||
|
|
||||||
|
export interface AcceptState {
|
||||||
|
domain: Domain;
|
||||||
|
apps: Apps;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Domain {
|
||||||
|
tier: number;
|
||||||
|
termsInfo: TermInfo[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Apps {
|
||||||
|
isLoading: boolean;
|
||||||
|
}
|
||||||
64
dictation_client/src/features/terms/termsSlice.ts
Normal file
64
dictation_client/src/features/terms/termsSlice.ts
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import { createSlice } from "@reduxjs/toolkit";
|
||||||
|
import { AcceptState } from "./state";
|
||||||
|
import {
|
||||||
|
getAccountInfoMinimalAccessAsync,
|
||||||
|
getTermsInfoAsync,
|
||||||
|
updateAcceptedVersionAsync,
|
||||||
|
} from "./operations";
|
||||||
|
|
||||||
|
const initialState: AcceptState = {
|
||||||
|
domain: {
|
||||||
|
tier: 0,
|
||||||
|
termsInfo: [
|
||||||
|
{
|
||||||
|
documentType: "",
|
||||||
|
version: "",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
apps: {
|
||||||
|
isLoading: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const termsSlice = createSlice({
|
||||||
|
name: "terms",
|
||||||
|
initialState,
|
||||||
|
reducers: {},
|
||||||
|
extraReducers: (builder) => {
|
||||||
|
builder.addCase(getAccountInfoMinimalAccessAsync.pending, (state) => {
|
||||||
|
state.apps.isLoading = true;
|
||||||
|
});
|
||||||
|
builder.addCase(
|
||||||
|
getAccountInfoMinimalAccessAsync.fulfilled,
|
||||||
|
(state, actions) => {
|
||||||
|
state.apps.isLoading = false;
|
||||||
|
state.domain.tier = actions.payload.tier;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
builder.addCase(getAccountInfoMinimalAccessAsync.rejected, (state) => {
|
||||||
|
state.apps.isLoading = false;
|
||||||
|
});
|
||||||
|
builder.addCase(getTermsInfoAsync.pending, (state) => {
|
||||||
|
state.apps.isLoading = true;
|
||||||
|
});
|
||||||
|
builder.addCase(getTermsInfoAsync.fulfilled, (state, actions) => {
|
||||||
|
state.apps.isLoading = false;
|
||||||
|
state.domain.termsInfo = actions.payload.termsInfo;
|
||||||
|
});
|
||||||
|
builder.addCase(getTermsInfoAsync.rejected, (state) => {
|
||||||
|
state.apps.isLoading = false;
|
||||||
|
});
|
||||||
|
builder.addCase(updateAcceptedVersionAsync.pending, (state) => {
|
||||||
|
state.apps.isLoading = true;
|
||||||
|
});
|
||||||
|
builder.addCase(updateAcceptedVersionAsync.fulfilled, (state) => {
|
||||||
|
state.apps.isLoading = false;
|
||||||
|
});
|
||||||
|
builder.addCase(updateAcceptedVersionAsync.rejected, (state) => {
|
||||||
|
state.apps.isLoading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default termsSlice.reducer;
|
||||||
@ -1,25 +0,0 @@
|
|||||||
/* eslint-disable jsx-a11y/label-has-associated-control */
|
|
||||||
import styles from "styles/app.module.scss";
|
|
||||||
import { useNavigate } from "react-router-dom";
|
|
||||||
|
|
||||||
const AcceptToUsePage: React.FC = (): JSX.Element => {
|
|
||||||
// 遷移確認用のダミーページ
|
|
||||||
|
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
const navigateToLoginPage = () => {
|
|
||||||
navigate("/login");
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={styles.wrap}>
|
|
||||||
利用規約同意画面のダミー画面
|
|
||||||
<div>
|
|
||||||
{/* eslint-disable-next-line */}
|
|
||||||
<button onClick={navigateToLoginPage}>OK</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AcceptToUsePage;
|
|
||||||
@ -30,7 +30,7 @@ const LoginPage: React.FC = (): JSX.Element => {
|
|||||||
if (isErrorObject(payload)) {
|
if (isErrorObject(payload)) {
|
||||||
// 未同意の規約がある場合は利用規約同意画面に遷移する
|
// 未同意の規約がある場合は利用規約同意画面に遷移する
|
||||||
if (payload.error.code === "E010209") {
|
if (payload.error.code === "E010209") {
|
||||||
navigate("/accept-to-use");
|
navigate("/terms");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -268,10 +268,9 @@ const SignupInput: React.FC = (): JSX.Element => {
|
|||||||
/>
|
/>
|
||||||
{isPushCreateButton && hasErrorEmptyAdminName && (
|
{isPushCreateButton && hasErrorEmptyAdminName && (
|
||||||
<span className={styles.formError}>
|
<span className={styles.formError}>
|
||||||
{" "}
|
{` ${t(
|
||||||
{t(
|
|
||||||
getTranslationID("signupPage.message.inputEmptyError")
|
getTranslationID("signupPage.message.inputEmptyError")
|
||||||
)}
|
)}`}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</dd>
|
</dd>
|
||||||
@ -373,8 +372,9 @@ const SignupInput: React.FC = (): JSX.Element => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t(getTranslationID("signupPage.label.termsLink"))}
|
{t(getTranslationID("signupPage.label.termsLink"))}
|
||||||
</a>{" "}
|
</a>
|
||||||
{t(getTranslationID("signupPage.label.termsLinkFor"))} <br />
|
{` ${t(getTranslationID("signupPage.label.termsLinkFor"))} `}
|
||||||
|
<br />
|
||||||
<label htmlFor="check-box">
|
<label htmlFor="check-box">
|
||||||
<input
|
<input
|
||||||
id="check-box"
|
id="check-box"
|
||||||
|
|||||||
188
dictation_client/src/pages/TermsPage/index.tsx
Normal file
188
dictation_client/src/pages/TermsPage/index.tsx
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
/* eslint-disable jsx-a11y/label-has-associated-control */
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { getTranslationID } from "translation";
|
||||||
|
import Header from "components/header";
|
||||||
|
import { AppDispatch } from "app/store";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import styles from "styles/app.module.scss";
|
||||||
|
import { TIERS } from "components/auth/constants";
|
||||||
|
import Footer from "components/footer";
|
||||||
|
import { useCallback, useEffect, useState } from "react";
|
||||||
|
import {
|
||||||
|
getAccountInfoMinimalAccessAsync,
|
||||||
|
getTermsInfoAsync,
|
||||||
|
updateAcceptedVersionAsync,
|
||||||
|
selectTier,
|
||||||
|
selectTermVersions,
|
||||||
|
} from "features//terms";
|
||||||
|
import { selectLocalStorageKeyforIdToken } from "features/login";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
const TermsPage: React.FC = (): JSX.Element => {
|
||||||
|
const [t] = useTranslation();
|
||||||
|
const dispatch: AppDispatch = useDispatch();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const updateAccceptVersions = useSelector(selectTermVersions);
|
||||||
|
const localStorageKeyforIdToken = useSelector(
|
||||||
|
selectLocalStorageKeyforIdToken
|
||||||
|
);
|
||||||
|
const tier = useSelector(selectTier);
|
||||||
|
|
||||||
|
const [isCheckedEula, setIsCheckedEula] = useState(false);
|
||||||
|
const [isCheckedDpa, setIsCheckedDpa] = useState(false);
|
||||||
|
|
||||||
|
const [isClickedEulaLink, setIsClickedEulaLink] = useState(false);
|
||||||
|
const [isClickedDpaLink, setIsClickedDpaLink] = useState(false);
|
||||||
|
|
||||||
|
// 画面起動時
|
||||||
|
useEffect(() => {
|
||||||
|
dispatch(getTermsInfoAsync());
|
||||||
|
if (localStorageKeyforIdToken) {
|
||||||
|
dispatch(getAccountInfoMinimalAccessAsync({ localStorageKeyforIdToken }));
|
||||||
|
} else {
|
||||||
|
// ログイン画面を経由していないため、トップページに遷移する
|
||||||
|
navigate("/");
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// ユーザーが第5階層であるかどうかを判定する(アクセストークンから自分の階層を取得できないので自前で作成)
|
||||||
|
const isTier5 = () => TIERS.TIER5.includes(tier.toString());
|
||||||
|
|
||||||
|
// ボタン押下可否判定ロジック
|
||||||
|
const canClickButton = () => {
|
||||||
|
if (isTier5()) {
|
||||||
|
return isCheckedEula;
|
||||||
|
}
|
||||||
|
return isCheckedEula && isCheckedDpa;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ボタン押下時処理
|
||||||
|
const onAcceptTermsOfUse = useCallback(async () => {
|
||||||
|
if (
|
||||||
|
localStorageKeyforIdToken &&
|
||||||
|
updateAccceptVersions.acceptedVerDPA !== "" &&
|
||||||
|
updateAccceptVersions.acceptedVerEULA !== ""
|
||||||
|
) {
|
||||||
|
const { meta } = await dispatch(
|
||||||
|
updateAcceptedVersionAsync({
|
||||||
|
tier,
|
||||||
|
localStorageKeyforIdToken,
|
||||||
|
updateAccceptVersions,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// 同意済バージョンが更新できたら、再度トークン生成を行う
|
||||||
|
if (meta.requestStatus === "fulfilled") {
|
||||||
|
navigate("/login");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
navigate,
|
||||||
|
localStorageKeyforIdToken,
|
||||||
|
updateAccceptVersions,
|
||||||
|
tier,
|
||||||
|
dispatch,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.wrap}>
|
||||||
|
<Header />
|
||||||
|
|
||||||
|
<main className={styles.main}>
|
||||||
|
<div className={styles.mainSmall}>
|
||||||
|
<div>
|
||||||
|
<h1 className={`${styles.marginBtm1} ${styles.alignCenter}`}>
|
||||||
|
{t(getTranslationID("termsPage.label.title"))}
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<section className={styles.form}>
|
||||||
|
<form action="" name="" method="">
|
||||||
|
<dl className={`${styles.formList} ${styles.hasbg}`}>
|
||||||
|
<dt className={styles.formTitle} />
|
||||||
|
|
||||||
|
<dd className={`${styles.full} ${styles.alignCenter}`}>
|
||||||
|
<p>
|
||||||
|
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
|
||||||
|
<a
|
||||||
|
href="/" /* TODO Eula用の利用規約リンクが決定したら設定を行う */
|
||||||
|
target="_blank"
|
||||||
|
className={styles.linkTx}
|
||||||
|
onClick={() => setIsClickedEulaLink(true)}
|
||||||
|
>
|
||||||
|
{t(getTranslationID("termsPage.label.linkOfEula"))}
|
||||||
|
</a>
|
||||||
|
{` ${t(getTranslationID("termsPage.label.forOdds"))}`}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={isCheckedEula}
|
||||||
|
className={styles.formCheck}
|
||||||
|
value=""
|
||||||
|
onChange={(e) => setIsCheckedEula(e.target.checked)}
|
||||||
|
disabled={!isClickedEulaLink}
|
||||||
|
/>
|
||||||
|
{t(
|
||||||
|
getTranslationID("termsPage.label.checkBoxForConsent")
|
||||||
|
)}
|
||||||
|
</label>
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
{/* 第五階層以外の場合はEulaのリンクをあわせて表示する */}
|
||||||
|
{!isTier5() && (
|
||||||
|
<dd className={`${styles.full} ${styles.alignCenter}`}>
|
||||||
|
<p>
|
||||||
|
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
|
||||||
|
<a
|
||||||
|
href="/" /* TODO Dpa用の利用規約リンクが決定したら設定を行う */
|
||||||
|
target="_blank"
|
||||||
|
className={styles.linkTx}
|
||||||
|
onClick={() => setIsClickedDpaLink(true)}
|
||||||
|
>
|
||||||
|
{t(getTranslationID("termsPage.label.linkOfDpa"))}
|
||||||
|
</a>
|
||||||
|
{` ${t(getTranslationID("termsPage.label.forOdds"))}`}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={isCheckedDpa}
|
||||||
|
className={styles.formCheck}
|
||||||
|
value=""
|
||||||
|
onChange={(e) => setIsCheckedDpa(e.target.checked)}
|
||||||
|
disabled={!isClickedDpaLink}
|
||||||
|
/>
|
||||||
|
{t(
|
||||||
|
getTranslationID("termsPage.label.checkBoxForConsent")
|
||||||
|
)}
|
||||||
|
</label>
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
)}
|
||||||
|
<dd className={`${styles.full} ${styles.alignCenter}`}>
|
||||||
|
<p>
|
||||||
|
<input
|
||||||
|
type="button"
|
||||||
|
name="submit"
|
||||||
|
value={t(getTranslationID("termsPage.label.button"))}
|
||||||
|
className={`${styles.formSubmit} ${styles.marginBtm1} ${
|
||||||
|
canClickButton() ? styles.isActive : ""
|
||||||
|
}`}
|
||||||
|
onClick={onAcceptTermsOfUse}
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TermsPage;
|
||||||
@ -2266,8 +2266,7 @@ tr.isSelected .menuInTable li a.isDisable {
|
|||||||
}
|
}
|
||||||
.formChange ul.chooseMember li input + label:hover,
|
.formChange ul.chooseMember li input + label:hover,
|
||||||
.formChange ul.holdMember li input + label:hover {
|
.formChange ul.holdMember li input + label:hover {
|
||||||
background: #e6e6e6 url(../assets/images/arrow_circle_left.svg) no-repeat left
|
background: #e6e6e6 url(../assets/images/arrow_circle_left.svg) no-repeat left center;
|
||||||
center;
|
|
||||||
background-size: 1.3rem;
|
background-size: 1.3rem;
|
||||||
}
|
}
|
||||||
.formChange ul.chooseMember li input:checked + label,
|
.formChange ul.chooseMember li input:checked + label,
|
||||||
@ -2278,8 +2277,8 @@ tr.isSelected .menuInTable li a.isDisable {
|
|||||||
}
|
}
|
||||||
.formChange ul.chooseMember li input:checked + label:hover,
|
.formChange ul.chooseMember li input:checked + label:hover,
|
||||||
.formChange ul.holdMember li input:checked + label:hover {
|
.formChange ul.holdMember li input:checked + label:hover {
|
||||||
background: #e6e6e6 url(../assets/images/arrow_circle_right.svg) no-repeat
|
background: #e6e6e6 url(../assets/images/arrow_circle_right.svg) no-repeat right
|
||||||
right center;
|
center;
|
||||||
background-size: 1.3rem;
|
background-size: 1.3rem;
|
||||||
}
|
}
|
||||||
.formChange > p {
|
.formChange > p {
|
||||||
@ -2432,8 +2431,7 @@ tr.isSelected .menuInTable li a.isDisable {
|
|||||||
}
|
}
|
||||||
.formChange ul.chooseMember li input + label:hover,
|
.formChange ul.chooseMember li input + label:hover,
|
||||||
.formChange ul.holdMember li input + label:hover {
|
.formChange ul.holdMember li input + label:hover {
|
||||||
background: #e6e6e6 url(../assets/images/arrow_circle_left.svg) no-repeat left
|
background: #e6e6e6 url(../assets/images/arrow_circle_left.svg) no-repeat left center;
|
||||||
center;
|
|
||||||
background-size: 1.3rem;
|
background-size: 1.3rem;
|
||||||
}
|
}
|
||||||
.formChange ul.chooseMember li input:checked + label,
|
.formChange ul.chooseMember li input:checked + label,
|
||||||
@ -2444,8 +2442,8 @@ tr.isSelected .menuInTable li a.isDisable {
|
|||||||
}
|
}
|
||||||
.formChange ul.chooseMember li input:checked + label:hover,
|
.formChange ul.chooseMember li input:checked + label:hover,
|
||||||
.formChange ul.holdMember li input:checked + label:hover {
|
.formChange ul.holdMember li input:checked + label:hover {
|
||||||
background: #e6e6e6 url(../assets/images/arrow_circle_right.svg) no-repeat
|
background: #e6e6e6 url(../assets/images/arrow_circle_right.svg) no-repeat right
|
||||||
right center;
|
center;
|
||||||
background-size: 1.3rem;
|
background-size: 1.3rem;
|
||||||
}
|
}
|
||||||
.formChange > p {
|
.formChange > p {
|
||||||
|
|||||||
@ -500,7 +500,7 @@
|
|||||||
"backToTopPageLink": "(de)Back to TOP Page"
|
"backToTopPageLink": "(de)Back to TOP Page"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"acceptToUsePage": {
|
"termsPage": {
|
||||||
"label": {
|
"label": {
|
||||||
"title": "(de)Terms of Use has updated. Please confirm again.",
|
"title": "(de)Terms of Use has updated. Please confirm again.",
|
||||||
"linkOfEula": "(de)Click here to read the terms of use.",
|
"linkOfEula": "(de)Click here to read the terms of use.",
|
||||||
@ -510,4 +510,4 @@
|
|||||||
"button": "(de)Continue"
|
"button": "(de)Continue"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -500,7 +500,7 @@
|
|||||||
"backToTopPageLink": "Back to TOP Page"
|
"backToTopPageLink": "Back to TOP Page"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"acceptToUsePage": {
|
"termsPage": {
|
||||||
"label": {
|
"label": {
|
||||||
"title": "Terms of Use has updated. Please confirm again.",
|
"title": "Terms of Use has updated. Please confirm again.",
|
||||||
"linkOfEula": "Click here to read the terms of use.",
|
"linkOfEula": "Click here to read the terms of use.",
|
||||||
@ -510,4 +510,4 @@
|
|||||||
"button": "Continue"
|
"button": "Continue"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -500,7 +500,7 @@
|
|||||||
"backToTopPageLink": "(es)Back to TOP Page"
|
"backToTopPageLink": "(es)Back to TOP Page"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"acceptToUsePage": {
|
"termsPage": {
|
||||||
"label": {
|
"label": {
|
||||||
"title": "(es)Terms of Use has updated. Please confirm again.",
|
"title": "(es)Terms of Use has updated. Please confirm again.",
|
||||||
"linkOfEula": "(es)Click here to read the terms of use.",
|
"linkOfEula": "(es)Click here to read the terms of use.",
|
||||||
@ -510,4 +510,4 @@
|
|||||||
"button": "(es)Continue"
|
"button": "(es)Continue"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -500,7 +500,7 @@
|
|||||||
"backToTopPageLink": "(fr)Back to TOP Page"
|
"backToTopPageLink": "(fr)Back to TOP Page"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"acceptToUsePage": {
|
"termsPage": {
|
||||||
"label": {
|
"label": {
|
||||||
"title": "(fr)Terms of Use has updated. Please confirm again.",
|
"title": "(fr)Terms of Use has updated. Please confirm again.",
|
||||||
"linkOfEula": "(fr)Click here to read the terms of use.",
|
"linkOfEula": "(fr)Click here to read the terms of use.",
|
||||||
@ -510,4 +510,4 @@
|
|||||||
"button": "(fr)Continue"
|
"button": "(fr)Continue"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user