233 lines
7.0 KiB
TypeScript
233 lines
7.0 KiB
TypeScript
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 {
|
|
changePoNumber,
|
|
changeNewOrder,
|
|
selectPoNumber,
|
|
selectNewOrder,
|
|
selectInputValidationErrors,
|
|
orderLicenseAsync,
|
|
cleanupApps,
|
|
selectIsLoading,
|
|
} from "features/license/licenseOrder";
|
|
import {
|
|
clearHierarchicalElement,
|
|
getMyAccountAsync,
|
|
} from "features/license/partnerLicense";
|
|
import close from "../../assets/images/close.svg";
|
|
import progress_activit from "../../assets/images/progress_activit.svg";
|
|
|
|
interface LicenseOrderPopupProps {
|
|
onClose: () => void;
|
|
}
|
|
|
|
export const LicenseOrderPopup: React.FC<LicenseOrderPopupProps> = (props) => {
|
|
const { onClose } = props;
|
|
const dispatch: AppDispatch = useDispatch();
|
|
const { t } = useTranslation();
|
|
const initCount = useSelector(selectNewOrder);
|
|
const [count, setCount] = useState<number>(initCount);
|
|
const [poNumberInputValue, setpoNumberInputValue] = useState<string>();
|
|
|
|
const isLoading = useSelector(selectIsLoading);
|
|
|
|
useEffect(
|
|
() => () => {
|
|
// useEffectのreturnとしてcleanupAppsを実行することで、ポップアップのアンマウント時に初期化を行う
|
|
dispatch(cleanupApps());
|
|
},
|
|
[dispatch]
|
|
);
|
|
|
|
// ポップアップを閉じる処理
|
|
const closePopup = useCallback(() => {
|
|
if (isLoading) return;
|
|
setIsPushOrderButton(false);
|
|
onClose();
|
|
}, [isLoading, onClose]);
|
|
|
|
// 画面からのパラメータ
|
|
const poNumber = useSelector(selectPoNumber);
|
|
const orderCount = useSelector(selectNewOrder);
|
|
|
|
const [isPushOrderButton, setIsPushOrderButton] = useState<boolean>(false);
|
|
|
|
// エラー宣言
|
|
const {
|
|
hasErrorEmptyPoNumber,
|
|
hasErrorIncorrectPoNumber,
|
|
hasErrorIncorrectNewOrder,
|
|
} = useSelector(selectInputValidationErrors);
|
|
|
|
// 注文ボタン押下時
|
|
const onOrderLicense = useCallback(async () => {
|
|
setIsPushOrderButton(true);
|
|
// エラーチェックを実施
|
|
if (
|
|
hasErrorEmptyPoNumber ||
|
|
hasErrorIncorrectPoNumber ||
|
|
hasErrorIncorrectNewOrder
|
|
) {
|
|
return;
|
|
}
|
|
|
|
// ダイアログ確認
|
|
if (
|
|
/* eslint-disable-next-line no-alert */
|
|
!window.confirm(
|
|
t(getTranslationID("licenseOrderPage.message.confirmOrder"))
|
|
)
|
|
) {
|
|
return;
|
|
}
|
|
|
|
// 注文APIの呼び出し
|
|
const { meta } = await dispatch(
|
|
orderLicenseAsync({
|
|
poNumber,
|
|
orderCount,
|
|
})
|
|
);
|
|
setIsPushOrderButton(false);
|
|
|
|
if (meta.requestStatus === "fulfilled") {
|
|
dispatch(getMyAccountAsync());
|
|
dispatch(clearHierarchicalElement());
|
|
closePopup();
|
|
}
|
|
}, [
|
|
dispatch,
|
|
closePopup,
|
|
t,
|
|
hasErrorEmptyPoNumber,
|
|
hasErrorIncorrectPoNumber,
|
|
hasErrorIncorrectNewOrder,
|
|
poNumber,
|
|
orderCount,
|
|
]);
|
|
|
|
// HTML
|
|
return (
|
|
<div className={`${styles.modal} ${styles.isShow}`}>
|
|
<div className={styles.modalBox}>
|
|
<p className={styles.modalTitle}>
|
|
{t(getTranslationID("licenseOrderPage.label.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} />
|
|
<dt>{t(getTranslationID("licenseOrderPage.label.licenses"))}</dt>
|
|
<dd>
|
|
<input
|
|
type="text"
|
|
size={40}
|
|
name=""
|
|
value={t(
|
|
getTranslationID("licenseOrderPage.label.licenseTypeText")
|
|
)}
|
|
maxLength={16}
|
|
className={styles.formInput}
|
|
readOnly
|
|
/>
|
|
</dd>
|
|
<dt>{t(getTranslationID("licenseOrderPage.label.poNumber"))}</dt>
|
|
<dd>
|
|
<input
|
|
type="text"
|
|
size={40}
|
|
name="poNumber"
|
|
value={poNumberInputValue}
|
|
maxLength={50}
|
|
className={styles.formInput}
|
|
onChange={(e) => {
|
|
const input = e.target.value.toUpperCase();
|
|
setpoNumberInputValue(input);
|
|
}}
|
|
onBlur={(e) => {
|
|
dispatch(changePoNumber({ poNumber: e.target.value }));
|
|
}}
|
|
/>
|
|
{isPushOrderButton && hasErrorEmptyPoNumber && (
|
|
<span className={styles.formError}>
|
|
{t(
|
|
getTranslationID("licenseOrderPage.message.inputEmptyError")
|
|
)}
|
|
</span>
|
|
)}
|
|
{isPushOrderButton && hasErrorIncorrectPoNumber && (
|
|
<span className={styles.formError}>
|
|
{t(
|
|
getTranslationID(
|
|
"licenseOrderPage.message.poNumberIncorrectError"
|
|
)
|
|
)}
|
|
</span>
|
|
)}
|
|
</dd>
|
|
<dt>{t(getTranslationID("licenseOrderPage.label.newOrder"))}</dt>
|
|
<dd>
|
|
<input
|
|
type="number"
|
|
size={4}
|
|
name="newOrder"
|
|
value={count}
|
|
min={1}
|
|
max={9999}
|
|
step={1}
|
|
maxLength={4}
|
|
className={styles.formInput}
|
|
onChange={(e) => {
|
|
const input = Number(
|
|
e.target.value.replace(/[-.]/g, "").substring(0, 4)
|
|
);
|
|
setCount(input);
|
|
}}
|
|
onBlur={(e) => {
|
|
dispatch(
|
|
changeNewOrder({ newOrder: Number(e.target.value) })
|
|
);
|
|
}}
|
|
/>
|
|
{isPushOrderButton && hasErrorIncorrectNewOrder && (
|
|
<span className={styles.formError}>
|
|
{t(
|
|
getTranslationID(
|
|
"licenseOrderPage.message.newOrderIncorrectError"
|
|
)
|
|
)}
|
|
</span>
|
|
)}
|
|
</dd>
|
|
<dd className={`${styles.full} ${styles.alignCenter}`}>
|
|
<input
|
|
type="button"
|
|
name="submit"
|
|
value={t(
|
|
getTranslationID("licenseOrderPage.label.orderButton")
|
|
)}
|
|
className={`${styles.formSubmit} ${styles.marginBtm1} ${
|
|
!isLoading ? styles.isActive : ""
|
|
}`}
|
|
onClick={onOrderLicense}
|
|
/>
|
|
<img
|
|
style={{ display: isLoading ? "inline" : "none" }}
|
|
src={progress_activit}
|
|
className={styles.icLoading}
|
|
alt="Loading"
|
|
/>
|
|
</dd>
|
|
</dl>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|