Merged PR 255: 画面実装(パートナーアカウント追加PU)
## 概要 [Task2156: 画面実装(パートナーアカウント追加PU)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2156) - 何をどう変更したか、追加したライブラリなど パートナー画面のAdd Partner押下時のポップアップ画面の実装を行いました。 - このPull Requestでの対象/対象外 呼び出し元の画面であるパートナー一覧画面は仮実装なので、対象外 - 影響範囲(他の機能にも影響があるか) 新規のため、なし ## レビューポイント - 特にレビューしてほしい箇所 デザイナさんのデザインと相違がないか。 ローディング中の処理など、他機能からの取りこぼしがないか。 ## 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/Task2156?csf=1&web=1&e=JdT2Bx ## 動作確認状況 - ローカルで表示確認 先にDONEのAPIと合わせてローカル環境で、パートナー追加の一連の流れが行えることを確認。 ## 補足 - 相談、参考資料などがあれば
This commit is contained in:
parent
478d454259
commit
28a88a1b3d
@ -336,6 +336,37 @@ export interface CreateOrdersRequest {
|
||||
*/
|
||||
'orderCount': number;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface CreatePartnerAccountRequest
|
||||
*/
|
||||
export interface CreatePartnerAccountRequest {
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof CreatePartnerAccountRequest
|
||||
*/
|
||||
'companyName': string;
|
||||
/**
|
||||
* 国名(ISO 3166-1 alpha-2)
|
||||
* @type {string}
|
||||
* @memberof CreatePartnerAccountRequest
|
||||
*/
|
||||
'country': string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof CreatePartnerAccountRequest
|
||||
*/
|
||||
'adminName': string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof CreatePartnerAccountRequest
|
||||
*/
|
||||
'email'?: string;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
@ -1119,6 +1150,46 @@ export const AccountsApiAxiosParamCreator = function (configuration?: Configurat
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary
|
||||
* @param {CreatePartnerAccountRequest} createPartnerAccountRequest
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
createPartnerAccount: async (createPartnerAccountRequest: CreatePartnerAccountRequest, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
// verify required parameter 'createPartnerAccountRequest' is not null or undefined
|
||||
assertParamExists('createPartnerAccount', 'createPartnerAccountRequest', createPartnerAccountRequest)
|
||||
const localVarPath = `/accounts/partner`;
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||
let baseOptions;
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions;
|
||||
}
|
||||
|
||||
const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
|
||||
const localVarHeaderParameter = {} as any;
|
||||
const localVarQueryParameter = {} as any;
|
||||
|
||||
// authentication bearer required
|
||||
// http bearer authentication required
|
||||
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
||||
|
||||
|
||||
|
||||
localVarHeaderParameter['Content-Type'] = 'application/json';
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
localVarRequestOptions.data = serializeDataIfNeeded(createPartnerAccountRequest, localVarRequestOptions, configuration)
|
||||
|
||||
return {
|
||||
url: toPathString(localVarUrlObj),
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
* 指定したアカウントのライセンス集計情報を取得します
|
||||
* @summary
|
||||
@ -1282,6 +1353,17 @@ export const AccountsApiFp = function(configuration?: Configuration) {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.createAccount(createAccountRequest, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary
|
||||
* @param {CreatePartnerAccountRequest} createPartnerAccountRequest
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async createPartnerAccount(createPartnerAccountRequest: CreatePartnerAccountRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<object>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.createPartnerAccount(createPartnerAccountRequest, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
* 指定したアカウントのライセンス集計情報を取得します
|
||||
* @summary
|
||||
@ -1343,6 +1425,16 @@ export const AccountsApiFactory = function (configuration?: Configuration, baseP
|
||||
createAccount(createAccountRequest: CreateAccountRequest, options?: any): AxiosPromise<object> {
|
||||
return localVarFp.createAccount(createAccountRequest, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary
|
||||
* @param {CreatePartnerAccountRequest} createPartnerAccountRequest
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
createPartnerAccount(createPartnerAccountRequest: CreatePartnerAccountRequest, options?: any): AxiosPromise<object> {
|
||||
return localVarFp.createPartnerAccount(createPartnerAccountRequest, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
* 指定したアカウントのライセンス集計情報を取得します
|
||||
* @summary
|
||||
@ -1402,6 +1494,18 @@ export class AccountsApi extends BaseAPI {
|
||||
return AccountsApiFp(this.configuration).createAccount(createAccountRequest, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @summary
|
||||
* @param {CreatePartnerAccountRequest} createPartnerAccountRequest
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof AccountsApi
|
||||
*/
|
||||
public createPartnerAccount(createPartnerAccountRequest: CreatePartnerAccountRequest, options?: AxiosRequestConfig) {
|
||||
return AccountsApiFp(this.configuration).createPartnerAccount(createPartnerAccountRequest, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定したアカウントのライセンス集計情報を取得します
|
||||
* @summary
|
||||
|
||||
@ -10,6 +10,7 @@ import licenseCardIssue from "features/license/licenseCardIssue/licenseCardIssue
|
||||
import licenseCardActivate from "features/license/licenseCardActivate/licenseCardActivateSlice";
|
||||
import licenseSummary from "features/license/licenseSummary/licenseSummarySlice";
|
||||
import dictation from "features/dictation/dictationSlice";
|
||||
import partner from "features/partner/partnerSlice";
|
||||
|
||||
export const store = configureStore({
|
||||
reducer: {
|
||||
@ -24,6 +25,7 @@ export const store = configureStore({
|
||||
licenseCardActivate,
|
||||
licenseSummary,
|
||||
dictation,
|
||||
partner,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
4
dictation_client/src/features/partner/index.ts
Normal file
4
dictation_client/src/features/partner/index.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export * from "./state";
|
||||
export * from "./operations";
|
||||
export * from "./selectors";
|
||||
export * from "./partnerSlice";
|
||||
64
dictation_client/src/features/partner/operations.ts
Normal file
64
dictation_client/src/features/partner/operations.ts
Normal file
@ -0,0 +1,64 @@
|
||||
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 { AccountsApi, CreatePartnerAccountRequest } from "../../api/api";
|
||||
import { Configuration } from "../../api/configuration";
|
||||
|
||||
export const createPartnerAccountAsync = createAsyncThunk<
|
||||
{
|
||||
/* Empty Object */
|
||||
},
|
||||
CreatePartnerAccountRequest,
|
||||
{
|
||||
// rejectした時の返却値の型
|
||||
rejectValue: {
|
||||
error: ErrorObject;
|
||||
};
|
||||
}
|
||||
>("partner/createPartnerAccountAsync", async (args, thunkApi) => {
|
||||
const createPartnerAccountRequest = 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 {
|
||||
await accountApi.createPartnerAccount(createPartnerAccountRequest, {
|
||||
headers: { authorization: `Bearer ${accessToken}` },
|
||||
});
|
||||
thunkApi.dispatch(
|
||||
openSnackbar({
|
||||
level: "info",
|
||||
message: getTranslationID(
|
||||
"addPartnerAccountPopupPage.message.addAccountSuccess"
|
||||
),
|
||||
})
|
||||
);
|
||||
return {};
|
||||
} catch (e) {
|
||||
const error = createErrorObject(e);
|
||||
if (error.code === "E010301") {
|
||||
thunkApi.dispatch(
|
||||
openSnackbar({
|
||||
level: "error",
|
||||
message: getTranslationID(
|
||||
"addPartnerAccountPopupPage.message.emailConflictError"
|
||||
),
|
||||
})
|
||||
);
|
||||
} else {
|
||||
thunkApi.dispatch(
|
||||
openSnackbar({
|
||||
level: "error",
|
||||
message: getTranslationID("common.message.internalServerError"),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return thunkApi.rejectWithValue({ error });
|
||||
}
|
||||
});
|
||||
60
dictation_client/src/features/partner/partnerSlice.ts
Normal file
60
dictation_client/src/features/partner/partnerSlice.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||
import { PartnerState } from "./state";
|
||||
import { createPartnerAccountAsync } from "./operations";
|
||||
|
||||
const initialState: PartnerState = {
|
||||
apps: {
|
||||
addPartner: {
|
||||
companyName: "",
|
||||
country: "",
|
||||
adminName: "",
|
||||
email: "",
|
||||
},
|
||||
isLoading: false,
|
||||
},
|
||||
};
|
||||
|
||||
export const partnerSlice = createSlice({
|
||||
name: "partner",
|
||||
initialState,
|
||||
reducers: {
|
||||
changeCompany: (state, action: PayloadAction<{ company: string }>) => {
|
||||
const { company } = action.payload;
|
||||
state.apps.addPartner.companyName = company;
|
||||
},
|
||||
changeCountry: (state, action: PayloadAction<{ country: string }>) => {
|
||||
const { country } = action.payload;
|
||||
state.apps.addPartner.country = country;
|
||||
},
|
||||
changeAdminName: (state, action: PayloadAction<{ adminName: string }>) => {
|
||||
const { adminName } = action.payload;
|
||||
state.apps.addPartner.adminName = adminName;
|
||||
},
|
||||
changeEmail: (state, action: PayloadAction<{ email: string }>) => {
|
||||
const { email } = action.payload;
|
||||
state.apps.addPartner.email = email;
|
||||
},
|
||||
cleanupAddPartner: (state) => {
|
||||
state.apps.addPartner = initialState.apps.addPartner;
|
||||
},
|
||||
},
|
||||
extraReducers: (builder) => {
|
||||
builder.addCase(createPartnerAccountAsync.pending, (state) => {
|
||||
state.apps.isLoading = true;
|
||||
});
|
||||
builder.addCase(createPartnerAccountAsync.fulfilled, (state) => {
|
||||
state.apps.isLoading = false;
|
||||
});
|
||||
builder.addCase(createPartnerAccountAsync.rejected, (state) => {
|
||||
state.apps.isLoading = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
export const {
|
||||
changeEmail,
|
||||
changeAdminName,
|
||||
changeCompany,
|
||||
changeCountry,
|
||||
cleanupAddPartner,
|
||||
} = partnerSlice.actions;
|
||||
export default partnerSlice.reducer;
|
||||
35
dictation_client/src/features/partner/selectors.ts
Normal file
35
dictation_client/src/features/partner/selectors.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { RootState } from "app/store";
|
||||
|
||||
export const selectInputValidationErrors = (state: RootState) => {
|
||||
// 必須項目のチェック
|
||||
const hasErrorEmptyCompany = state.partner.apps.addPartner.companyName === "";
|
||||
const hasErrorEmptyCountry = state.partner.apps.addPartner.country === "";
|
||||
const hasErrorEmptyAdminName = state.partner.apps.addPartner.adminName === "";
|
||||
const hasErrorEmptyEmail = state.partner.apps.addPartner.email === "";
|
||||
|
||||
const hasErrorIncorrectEmail =
|
||||
(state.partner.apps.addPartner.email as string).match(/^[^@]+@[^@]+$/)
|
||||
?.length !== 1;
|
||||
|
||||
return {
|
||||
hasErrorEmptyCompany,
|
||||
hasErrorEmptyCountry,
|
||||
hasErrorEmptyAdminName,
|
||||
hasErrorEmptyEmail,
|
||||
hasErrorIncorrectEmail,
|
||||
};
|
||||
};
|
||||
|
||||
// Account Info
|
||||
export const selectCompany = (state: RootState) =>
|
||||
state.partner.apps.addPartner.companyName;
|
||||
export const selectCountry = (state: RootState) =>
|
||||
state.partner.apps.addPartner.country;
|
||||
|
||||
// Admin Info
|
||||
export const selectAdminName = (state: RootState) =>
|
||||
state.partner.apps.addPartner.adminName;
|
||||
export const selectEmail = (state: RootState) =>
|
||||
state.partner.apps.addPartner.email;
|
||||
export const selectIsLoading = (state: RootState) =>
|
||||
state.partner.apps.isLoading;
|
||||
10
dictation_client/src/features/partner/state.ts
Normal file
10
dictation_client/src/features/partner/state.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { CreatePartnerAccountRequest } from "../../api/api";
|
||||
|
||||
export interface PartnerState {
|
||||
apps: Apps;
|
||||
}
|
||||
|
||||
export interface Apps {
|
||||
addPartner: CreatePartnerAccountRequest;
|
||||
isLoading: boolean;
|
||||
}
|
||||
@ -0,0 +1,291 @@
|
||||
import { AppDispatch } from "app/store";
|
||||
import React, { useState, useCallback, useEffect } from "react";
|
||||
import styles from "styles/app.module.scss";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { getTranslationID } from "translation";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
selectAdminName,
|
||||
selectCompany,
|
||||
selectCountry,
|
||||
selectEmail,
|
||||
selectInputValidationErrors,
|
||||
selectIsLoading,
|
||||
} from "features/partner/selectors";
|
||||
import {
|
||||
changeAdminName,
|
||||
changeCompany,
|
||||
changeCountry,
|
||||
changeEmail,
|
||||
cleanupAddPartner,
|
||||
} from "features/partner/partnerSlice";
|
||||
import { createPartnerAccountAsync } from "features/partner";
|
||||
import close from "../../assets/images/close.svg";
|
||||
import progress_activit from "../../assets/images/progress_activit.svg";
|
||||
import { COUNTRY_LIST } from "../SignupPage/constants";
|
||||
|
||||
interface AddPartnerAccountPopup {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export const AddPartnerAccountPopup: React.FC<AddPartnerAccountPopup> = (
|
||||
props
|
||||
) => {
|
||||
const { isOpen, onClose } = props;
|
||||
const dispatch: AppDispatch = useDispatch();
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
hasErrorEmptyCompany,
|
||||
hasErrorEmptyCountry,
|
||||
hasErrorEmptyAdminName,
|
||||
hasErrorEmptyEmail,
|
||||
hasErrorIncorrectEmail,
|
||||
} = useSelector(selectInputValidationErrors);
|
||||
|
||||
const [isPushCreateButton, setIsPushCreateButton] = useState<boolean>(false);
|
||||
|
||||
const companyName = useSelector(selectCompany);
|
||||
const country = useSelector(selectCountry);
|
||||
const adminName = useSelector(selectAdminName);
|
||||
const email = useSelector(selectEmail);
|
||||
const isLoading = useSelector(selectIsLoading);
|
||||
|
||||
// ブラウザのウィンドウが閉じられようとしている場合に発火するイベントハンドラ
|
||||
const handleBeforeUnload = (e: BeforeUnloadEvent) => {
|
||||
// isLoadingがtrueの場合は確認ダイアログを表示する
|
||||
if (isLoading) {
|
||||
e.preventDefault();
|
||||
// ChromeではreturnValueが必要
|
||||
e.returnValue = "";
|
||||
}
|
||||
};
|
||||
// コンポーネントがマウントされた時にイベントハンドラを登録する
|
||||
useEffect(() => {
|
||||
window.addEventListener("beforeunload", handleBeforeUnload);
|
||||
// コンポーネントがアンマウントされるときにイベントハンドラを解除する
|
||||
return () => {
|
||||
window.removeEventListener("beforeunload", handleBeforeUnload);
|
||||
};
|
||||
});
|
||||
|
||||
const closePopup = useCallback(() => {
|
||||
if (isLoading) {
|
||||
return;
|
||||
}
|
||||
setIsPushCreateButton(false);
|
||||
dispatch(cleanupAddPartner());
|
||||
onClose();
|
||||
}, [isLoading, onClose, dispatch]);
|
||||
|
||||
const onAddPartner = useCallback(async () => {
|
||||
setIsPushCreateButton(true);
|
||||
if (
|
||||
hasErrorEmptyCompany ||
|
||||
hasErrorEmptyCountry ||
|
||||
hasErrorEmptyAdminName ||
|
||||
hasErrorEmptyEmail ||
|
||||
hasErrorIncorrectEmail
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { meta } = await dispatch(
|
||||
createPartnerAccountAsync({
|
||||
companyName,
|
||||
country,
|
||||
adminName,
|
||||
email,
|
||||
})
|
||||
);
|
||||
setIsPushCreateButton(false);
|
||||
|
||||
if (meta.requestStatus === "fulfilled") {
|
||||
closePopup();
|
||||
}
|
||||
}, [
|
||||
dispatch,
|
||||
closePopup,
|
||||
hasErrorEmptyCompany,
|
||||
hasErrorEmptyCountry,
|
||||
hasErrorEmptyAdminName,
|
||||
hasErrorEmptyEmail,
|
||||
hasErrorIncorrectEmail,
|
||||
companyName,
|
||||
country,
|
||||
adminName,
|
||||
email,
|
||||
]);
|
||||
|
||||
return (
|
||||
<div className={`${styles.modal} ${isOpen ? styles.isShow : ""}`}>
|
||||
<div className={styles.modalBox}>
|
||||
<p className={styles.modalTitle}>
|
||||
{t(getTranslationID("addPartnerAccountPopupPage.text.title"))}
|
||||
<button type="button" onClick={closePopup}>
|
||||
<img src={close} className={styles.modalTitleIcon} alt="close" />
|
||||
</button>
|
||||
</p>
|
||||
<form className={styles.form}>
|
||||
<dl className={`${styles.formList} ${styles.hasbg}`}>
|
||||
<dt className={`${styles.formTitle} ${styles.marginBtm0}`}>
|
||||
{t(
|
||||
getTranslationID(
|
||||
"addPartnerAccountPopupPage.text.accountInfoTitle"
|
||||
)
|
||||
)}
|
||||
</dt>
|
||||
<dt>
|
||||
{t(getTranslationID("addPartnerAccountPopupPage.label.company"))}
|
||||
</dt>
|
||||
<dd>
|
||||
<input
|
||||
type="text"
|
||||
size={64}
|
||||
className={`${styles.formInput} ${
|
||||
isPushCreateButton && hasErrorEmptyCompany && styles.isError
|
||||
}`}
|
||||
onChange={(e) => {
|
||||
dispatch(changeCompany({ company: e.target.value }));
|
||||
}}
|
||||
value={companyName}
|
||||
/>
|
||||
{isPushCreateButton && hasErrorEmptyCompany && (
|
||||
<span className={styles.formError}>
|
||||
{t(
|
||||
getTranslationID(
|
||||
"addPartnerAccountPopupPage.message.inputEmptyError"
|
||||
)
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
</dd>
|
||||
<dt>
|
||||
{t(getTranslationID("addPartnerAccountPopupPage.label.country"))}
|
||||
</dt>
|
||||
<dd>
|
||||
<select
|
||||
className={`${styles.formInput} ${
|
||||
isPushCreateButton && hasErrorEmptyCountry && styles.isError
|
||||
}`}
|
||||
onChange={(event) => {
|
||||
dispatch(changeCountry({ country: event.target.value }));
|
||||
}}
|
||||
value={
|
||||
COUNTRY_LIST.find((x) => x.value === country)?.value ?? ""
|
||||
}
|
||||
>
|
||||
{COUNTRY_LIST.map((x) => (
|
||||
<option key={x.value} value={x.value}>
|
||||
{x.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
{isPushCreateButton && hasErrorEmptyCountry && (
|
||||
<span className={styles.formError}>
|
||||
{t(
|
||||
getTranslationID(
|
||||
"addPartnerAccountPopupPage.message.inputEmptyError"
|
||||
)
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
</dd>
|
||||
<dt className={` ${styles.formTitle} ${styles.marginBtm0}`}>
|
||||
{t(
|
||||
getTranslationID(
|
||||
"addPartnerAccountPopupPage.text.adminInfoTitle"
|
||||
)
|
||||
)}
|
||||
</dt>
|
||||
<dt>
|
||||
{t(
|
||||
getTranslationID("addPartnerAccountPopupPage.label.adminName")
|
||||
)}
|
||||
</dt>
|
||||
<dd>
|
||||
<input
|
||||
type="text"
|
||||
size={256}
|
||||
className={`${styles.formInput} ${
|
||||
isPushCreateButton && hasErrorEmptyAdminName && styles.isError
|
||||
}`}
|
||||
onChange={(e) => {
|
||||
dispatch(changeAdminName({ adminName: e.target.value }));
|
||||
}}
|
||||
value={adminName}
|
||||
/>
|
||||
{isPushCreateButton && hasErrorEmptyAdminName && (
|
||||
<span className={styles.formError}>
|
||||
{t(
|
||||
getTranslationID(
|
||||
"addPartnerAccountPopupPage.message.inputEmptyError"
|
||||
)
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
</dd>
|
||||
<dt>
|
||||
{t(getTranslationID("addPartnerAccountPopupPage.label.email"))}
|
||||
</dt>
|
||||
<dd>
|
||||
<input
|
||||
type="text"
|
||||
size={64}
|
||||
className={`${styles.formInput}
|
||||
${
|
||||
isPushCreateButton &&
|
||||
(hasErrorEmptyEmail || hasErrorIncorrectEmail) &&
|
||||
styles.isError
|
||||
}`}
|
||||
onChange={(e) => {
|
||||
dispatch(changeEmail({ email: e.target.value }));
|
||||
}}
|
||||
value={email}
|
||||
/>
|
||||
{isPushCreateButton && hasErrorEmptyEmail && (
|
||||
<span className={styles.formError}>
|
||||
{t(
|
||||
getTranslationID(
|
||||
"addPartnerAccountPopupPage.message.inputEmptyError"
|
||||
)
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
{isPushCreateButton && hasErrorIncorrectEmail && (
|
||||
<span className={styles.formError}>
|
||||
{t(
|
||||
getTranslationID(
|
||||
"addPartnerAccountPopupPage.message.emailIncorrectError"
|
||||
)
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
</dd>
|
||||
<dd className={`${styles.full} ${styles.alignCenter}`}>
|
||||
<input
|
||||
type="button"
|
||||
name="submit"
|
||||
value={t(
|
||||
getTranslationID(
|
||||
"addPartnerAccountPopupPage.label.createAccountButton"
|
||||
)
|
||||
)}
|
||||
className={`${styles.formSubmit} ${styles.marginBtm1} ${
|
||||
!isLoading ? styles.isActive : ""
|
||||
}`}
|
||||
onClick={onAddPartner}
|
||||
/>
|
||||
<img
|
||||
style={{ display: isLoading ? "inline" : "none" }}
|
||||
src={progress_activit}
|
||||
className={styles.icLoading}
|
||||
alt="Loading"
|
||||
/>
|
||||
</dd>
|
||||
</dl>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@ -4,19 +4,21 @@ import { UpdateTokenTimer } from "components/auth/updateTokenTimer";
|
||||
import Footer from "components/footer";
|
||||
import Header from "components/header";
|
||||
import { clearToken } from "features/auth";
|
||||
import React from "react";
|
||||
import React, { useCallback, useState } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import styles from "styles/app.module.scss";
|
||||
import { loadAccessToken, isApproveTier } from "features/auth/utils";
|
||||
import postAdd from "../../assets/images/post_add.svg";
|
||||
import { decodeToken } from "../../common/decodeToken";
|
||||
import { TIERS } from "../../components/auth/constants";
|
||||
import { AddPartnerAccountPopup } from "./addPartnerAccountPopup";
|
||||
|
||||
const PartnerPage: React.FC = (): JSX.Element => {
|
||||
const { instance } = useMsal();
|
||||
const dispatch: AppDispatch = useDispatch();
|
||||
const [isPopupOpen, setIsPopupOpen] = useState(false);
|
||||
|
||||
/* 本実装の際に消す想定です。
|
||||
/* XXX 本実装の際に消す想定です。
|
||||
POデモ時に階層情報を表示するための実装です。 */
|
||||
const getUserTier = () => {
|
||||
const jwt = loadAccessToken(); // トークンを取得
|
||||
@ -29,64 +31,73 @@ const PartnerPage: React.FC = (): JSX.Element => {
|
||||
return "error!"; // 階層情報が見つからない場合はerror!を返す
|
||||
};
|
||||
|
||||
/* 本実装の際に消す想定です。
|
||||
/* XXX 本実装の際に消す想定です。
|
||||
ログインしているアカウントの階層を確認するために実装 */
|
||||
const userTier = getUserTier();
|
||||
// 第1~3階層にボタンを表示する
|
||||
const isVisible = isApproveTier([TIERS.TIER1, TIERS.TIER2, TIERS.TIER3]);
|
||||
|
||||
const onOpen = useCallback(() => {
|
||||
setIsPopupOpen(true);
|
||||
}, [setIsPopupOpen]);
|
||||
// HTML
|
||||
return (
|
||||
<div className={styles.wrap}>
|
||||
<Header userName="XXXXXX" />
|
||||
<UpdateTokenTimer />
|
||||
<main className={styles.main}>
|
||||
<ul className={styles.menuAction}>
|
||||
<li>
|
||||
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
|
||||
{isVisible && (
|
||||
<a
|
||||
className={`${styles.menuLink} ${styles.isActive}`}
|
||||
// onClick={}
|
||||
>
|
||||
<img src={postAdd} alt="" className={styles.menuIcon} />
|
||||
Add Account
|
||||
</a>
|
||||
)}
|
||||
</li>
|
||||
</ul>
|
||||
<form className={styles.form}>
|
||||
<dl className={`${styles.formList} ${styles.hasbg}`}>
|
||||
<dt className={styles.formTitle} />
|
||||
<dt />
|
||||
<dd className="">
|
||||
<input
|
||||
type="text"
|
||||
size={40}
|
||||
name=""
|
||||
value={`Tier:${userTier}`}
|
||||
maxLength={20}
|
||||
className={styles.formInput}
|
||||
/>
|
||||
</dd>
|
||||
</dl>
|
||||
</form>
|
||||
</main>
|
||||
<div>
|
||||
<button
|
||||
type="button"
|
||||
className={styles.buttonText}
|
||||
onClick={() => {
|
||||
instance.logout({ postLogoutRedirectUri: "/" });
|
||||
dispatch(clearToken());
|
||||
}}
|
||||
>
|
||||
sign out
|
||||
</button>
|
||||
<>
|
||||
<AddPartnerAccountPopup
|
||||
isOpen={isPopupOpen}
|
||||
onClose={() => {
|
||||
setIsPopupOpen(false);
|
||||
}}
|
||||
/>
|
||||
<div className={styles.wrap}>
|
||||
<Header userName="XXXXXX" />
|
||||
<UpdateTokenTimer />
|
||||
<main className={styles.main}>
|
||||
<ul className={styles.menuAction}>
|
||||
<li>
|
||||
{isVisible && (
|
||||
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
|
||||
<a
|
||||
className={`${styles.menuLink} ${styles.isActive}`}
|
||||
onClick={onOpen}
|
||||
>
|
||||
<img src={postAdd} alt="" className={styles.menuIcon} />
|
||||
Add Account
|
||||
</a>
|
||||
)}
|
||||
</li>
|
||||
</ul>
|
||||
<form className={styles.form}>
|
||||
<dl className={`${styles.formList} ${styles.hasbg}`}>
|
||||
<dt className={styles.formTitle} />
|
||||
<dt />
|
||||
<dd className="">
|
||||
<input
|
||||
type="text"
|
||||
size={40}
|
||||
name=""
|
||||
value={`Tier:${userTier}`}
|
||||
maxLength={20}
|
||||
className={styles.formInput}
|
||||
/>
|
||||
</dd>
|
||||
</dl>
|
||||
</form>
|
||||
</main>
|
||||
<div>
|
||||
<button
|
||||
type="button"
|
||||
className={styles.buttonText}
|
||||
onClick={() => {
|
||||
instance.logout({ postLogoutRedirectUri: "/" });
|
||||
dispatch(clearToken());
|
||||
}}
|
||||
>
|
||||
sign out
|
||||
</button>
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default PartnerPage;
|
||||
|
||||
@ -250,5 +250,26 @@
|
||||
"LicenseKeyNotExistError": "(de)入力されたライセンスキーは存在しません。ライセンスキーを再度お確かめください。",
|
||||
"LicenseKeyAlreadyActivatedError": "(de)入力されたライセンスキーは、既に有効化されています。ライセンスキーを再度お確かめください。"
|
||||
}
|
||||
},
|
||||
"addPartnerAccountPopupPage": {
|
||||
"message": {
|
||||
"addAccountSuccess": "(de)メールアドレス宛に認証用メールを送信しました。",
|
||||
"inputEmptyError": "(de)この項目の入力は必須です。入力してください。",
|
||||
"emailIncorrectError": "(de)メールアドレスの形式が不正です。正しいメールアドレスの形式で入力してください。",
|
||||
"emailConflictError": "(de)このメールアドレスは既に登録されています。他のメールアドレスで登録してください。"
|
||||
},
|
||||
"text": {
|
||||
"title": "(de)Add account",
|
||||
"accountInfoTitle": "(de)Register account information",
|
||||
"countryExplanation": "(de)Please select country or the nearest country.",
|
||||
"adminInfoTitle": "(de)Register primary administrator's information"
|
||||
},
|
||||
"label": {
|
||||
"company": "(de)Company Name",
|
||||
"country": "(de)Country",
|
||||
"adminName": "(de)Admin Name",
|
||||
"email": "(de)Email",
|
||||
"createAccountButton": "(de)Add account"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -250,5 +250,26 @@
|
||||
"LicenseKeyNotExistError": "入力されたライセンスキーは存在しません。ライセンスキーを再度お確かめください。",
|
||||
"LicenseKeyAlreadyActivatedError": "入力されたライセンスキーは、既に有効化されています。ライセンスキーを再度お確かめください。"
|
||||
}
|
||||
},
|
||||
"addPartnerAccountPopupPage": {
|
||||
"message": {
|
||||
"addAccountSuccess": "メールアドレス宛に認証用メールを送信しました。",
|
||||
"inputEmptyError": "この項目の入力は必須です。入力してください。",
|
||||
"emailIncorrectError": "メールアドレスの形式が不正です。正しいメールアドレスの形式で入力してください。",
|
||||
"emailConflictError": "このメールアドレスは既に登録されています。他のメールアドレスで登録してください。"
|
||||
},
|
||||
"text": {
|
||||
"title": "Add account",
|
||||
"accountInfoTitle": "Register account information",
|
||||
"countryExplanation": "Please select country or the nearest country.",
|
||||
"adminInfoTitle": "Register primary administrator's information"
|
||||
},
|
||||
"label": {
|
||||
"company": "Company Name",
|
||||
"country": "Country",
|
||||
"adminName": "Admin Name",
|
||||
"email": "Email",
|
||||
"createAccountButton": "Add account"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -250,5 +250,26 @@
|
||||
"LicenseKeyNotExistError": "(es)入力されたライセンスキーは存在しません。ライセンスキーを再度お確かめください。",
|
||||
"LicenseKeyAlreadyActivatedError": "(es)入力されたライセンスキーは、既に有効化されています。ライセンスキーを再度お確かめください。"
|
||||
}
|
||||
},
|
||||
"addPartnerAccountPopupPage": {
|
||||
"message": {
|
||||
"addAccountSuccess": "(es)メールアドレス宛に認証用メールを送信しました。",
|
||||
"inputEmptyError": "(es)この項目の入力は必須です。入力してください。",
|
||||
"emailIncorrectError": "(es)メールアドレスの形式が不正です。正しいメールアドレスの形式で入力してください。",
|
||||
"emailConflictError": "(es)このメールアドレスは既に登録されています。他のメールアドレスで登録してください。"
|
||||
},
|
||||
"text": {
|
||||
"title": "(es)Add account",
|
||||
"accountInfoTitle": "(es)Register account information",
|
||||
"countryExplanation": "(es)Please select country or the nearest country.",
|
||||
"adminInfoTitle": "(es)Register primary administrator's information"
|
||||
},
|
||||
"label": {
|
||||
"company": "(es)Company Name",
|
||||
"country": "(es)Country",
|
||||
"adminName": "(es)Admin Name",
|
||||
"email": "(es)Email",
|
||||
"createAccountButton": "(es)Add account"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -250,5 +250,26 @@
|
||||
"LicenseKeyNotExistError": "(fr)入力されたライセンスキーは存在しません。ライセンスキーを再度お確かめください。",
|
||||
"LicenseKeyAlreadyActivatedError": "(fr)入力されたライセンスキーは、既に有効化されています。ライセンスキーを再度お確かめください。"
|
||||
}
|
||||
},
|
||||
"addPartnerAccountPopupPage": {
|
||||
"message": {
|
||||
"addAccountSuccess": "(fr)メールアドレス宛に認証用メールを送信しました。",
|
||||
"inputEmptyError": "(fr)この項目の入力は必須です。入力してください。",
|
||||
"emailIncorrectError": "(fr)メールアドレスの形式が不正です。正しいメールアドレスの形式で入力してください。",
|
||||
"emailConflictError": "(fr)このメールアドレスは既に登録されています。他のメールアドレスで登録してください。"
|
||||
},
|
||||
"text": {
|
||||
"title": "(fr)Add account",
|
||||
"accountInfoTitle": "(fr)Register account information",
|
||||
"countryExplanation": "(fr)Please select country or the nearest country.",
|
||||
"adminInfoTitle": "(fr)Register primary administrator's information"
|
||||
},
|
||||
"label": {
|
||||
"company": "(fr)Company Name",
|
||||
"country": "(fr)Country",
|
||||
"adminName": "(fr)Admin Name",
|
||||
"email": "(fr)Email",
|
||||
"createAccountButton": "(fr)Add account"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user