Merged PR 252: 画面実装(パートナーライセンス一覧画面)(画面遷移・ページネーション周り)

## 概要
[Task2228: 画面実装(パートナーライセンス一覧画面)(画面遷移・ページネーション周り)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2228)

パートナー一覧画面の画面遷移・ページネーション周りを実装しました。
以下は対象外となります。
・「ViewDetails」を押下したときの挙動
・「Order History」を押下したときの画面の内容

## レビューポイント
なし

## 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/Task2228?csf=1&web=1&e=8Dup5q

## 動作確認状況
ローカルで動作確認済み

## 補足
なし
This commit is contained in:
oura.a 2023-08-01 02:34:29 +00:00
parent b5183994e1
commit 6fc9a2db64
7 changed files with 532 additions and 303 deletions

View File

@ -28,25 +28,21 @@ export const getMyAccountAsync = createAsyncThunk<
const { configuration, accessToken } = state.auth; const { configuration, accessToken } = state.auth;
const config = new Configuration(configuration); const config = new Configuration(configuration);
const accountsApi = new AccountsApi(config); const accountsApi = new AccountsApi(config);
try { try {
const getMyAccountResponse = await accountsApi.getMyAccount({ const getMyAccountResponse = await accountsApi.getMyAccount({
headers: { authorization: `Bearer ${accessToken}` }, headers: { authorization: `Bearer ${accessToken}` },
}); });
// accountIDを返す // accountIDを返す
return getMyAccountResponse.data.account; return getMyAccountResponse.data.account;
} catch (e) { } catch (e) {
// e ⇒ errorObjectに変換" // e ⇒ errorObjectに変換"
const error = createErrorObject(e); const error = createErrorObject(e);
thunkApi.dispatch( thunkApi.dispatch(
openSnackbar({ openSnackbar({
level: "error", level: "error",
message: getTranslationID("common.message.internalServerError"), message: getTranslationID("common.message.internalServerError"),
}) })
); );
return thunkApi.rejectWithValue({ error }); return thunkApi.rejectWithValue({ error });
} }
}); });
@ -59,7 +55,7 @@ export const getPartnerLicenseAsync = createAsyncThunk<
{ {
limit: number; limit: number;
offset: number; offset: number;
accountId: number; accountId: number | undefined;
}, },
{ {
// rejectした時の返却値の型 // rejectした時の返却値の型
@ -76,11 +72,18 @@ export const getPartnerLicenseAsync = createAsyncThunk<
const accountsApi = new AccountsApi(config); const accountsApi = new AccountsApi(config);
try { try {
const getMyAccountResponse = await accountsApi.getMyAccount({
headers: { authorization: `Bearer ${accessToken}` },
});
const accountId =
args.accountId ?? getMyAccountResponse.data.account.accountId;
const getPartnerLicenseResponse = await accountsApi.getPartnerLicenses( const getPartnerLicenseResponse = await accountsApi.getPartnerLicenses(
{ {
limit: args.limit, limit: args.limit,
offset: args.offset, offset: args.offset,
accountId: args.accountId, accountId,
}, },
{ headers: { authorization: `Bearer ${accessToken}` } } { headers: { authorization: `Bearer ${accessToken}` } }
); );

View File

@ -1,10 +1,11 @@
import { PayloadAction, createSlice } from "@reduxjs/toolkit"; import { PayloadAction, createSlice } from "@reduxjs/toolkit";
import { PartnerLicensesState } from "./state"; import { PartnerLicensesState, HierarchicalElement } from "./state";
import { PartnerLicenseInfo } from "../../../api/api";
import { getMyAccountAsync, getPartnerLicenseAsync } from "./operations"; import { getMyAccountAsync, getPartnerLicenseAsync } from "./operations";
import { ACCOUNTS_VIEW_LIMIT } from "./constants";
const initialState: PartnerLicensesState = { const initialState: PartnerLicensesState = {
domain: { domain: {
myAccountInfo: { accountId: 0 },
total: 0, total: 0,
ownPartnerLicense: { ownPartnerLicense: {
accountId: 0, accountId: 0,
@ -16,11 +17,14 @@ const initialState: PartnerLicensesState = {
issueRequesting: 0, issueRequesting: 0,
}, },
childrenPartnerLicenses: [], childrenPartnerLicenses: [],
acountInfo: { accountId: 0 }, totalPage: 0,
}, },
apps: { apps: {
limit: 1, limit: ACCOUNTS_VIEW_LIMIT,
offset: 0, offset: 0,
currentPage: 0,
hierarchicalElements: [],
isLoading: true,
}, },
}; };
@ -28,43 +32,70 @@ export const partnerLicenseSlice = createSlice({
name: "partnerLicense", name: "partnerLicense",
initialState, initialState,
reducers: { reducers: {
changeTotal: (state, action: PayloadAction<{ total: number }>) => { pushHierarchicalElement: (
const { total } = action.payload;
state.domain.total = total;
},
changeOwnPartnerLicense: (
state,
action: PayloadAction<{ ownPartnerLicense: PartnerLicenseInfo }>
) => {
const { ownPartnerLicense } = action.payload;
state.domain.ownPartnerLicense = ownPartnerLicense;
},
changeChildrenPartnerLicenses: (
state, state,
action: PayloadAction<{ action: PayloadAction<{
childrenPartnerLicenses: PartnerLicenseInfo[]; hierarchicalElement: HierarchicalElement;
}> }>
) => { ) => {
const { childrenPartnerLicenses } = action.payload; const { hierarchicalElement } = action.payload;
state.domain.childrenPartnerLicenses = childrenPartnerLicenses; state.apps.hierarchicalElements.push(hierarchicalElement);
},
popHierarchicalElement: (state) => {
state.apps.hierarchicalElements.pop();
},
spliceHierarchicalElement: (
state,
action: PayloadAction<{
deleteCount: number;
}>
) => {
const { deleteCount } = action.payload;
state.apps.hierarchicalElements.splice(-deleteCount);
},
savePageInfo: (
state,
action: PayloadAction<{
limit: number;
offset: number;
}>
) => {
const { limit, offset } = action.payload;
state.apps.limit = limit;
state.apps.offset = offset;
}, },
}, },
extraReducers: (builder) => { extraReducers: (builder) => {
builder.addCase(getMyAccountAsync.pending, (state) => {
state.apps.isLoading = true;
});
builder.addCase(getMyAccountAsync.fulfilled, (state, action) => { builder.addCase(getMyAccountAsync.fulfilled, (state, action) => {
state.domain.acountInfo = action.payload; state.domain.myAccountInfo = action.payload;
state.apps.isLoading = false;
});
builder.addCase(getMyAccountAsync.rejected, (state) => {
state.apps.isLoading = false;
});
builder.addCase(getPartnerLicenseAsync.pending, (state) => {
state.apps.isLoading = true;
}); });
builder.addCase(getPartnerLicenseAsync.fulfilled, (state, action) => { builder.addCase(getPartnerLicenseAsync.fulfilled, (state, action) => {
state.domain.total = action.payload.total; state.domain.total = action.payload.total;
state.domain.ownPartnerLicense = action.payload.ownPartnerLicense; state.domain.ownPartnerLicense = action.payload.ownPartnerLicense;
state.domain.childrenPartnerLicenses = state.domain.childrenPartnerLicenses =
action.payload.childrenPartnerLicenses; action.payload.childrenPartnerLicenses;
state.apps.isLoading = false;
});
builder.addCase(getPartnerLicenseAsync.rejected, (state) => {
state.apps.isLoading = false;
}); });
}, },
}); });
export const { export const {
changeTotal, pushHierarchicalElement,
changeOwnPartnerLicense, popHierarchicalElement,
changeChildrenPartnerLicenses, spliceHierarchicalElement,
savePageInfo,
} = partnerLicenseSlice.actions; } = partnerLicenseSlice.actions;
export default partnerLicenseSlice.reducer; export default partnerLicenseSlice.reducer;

View File

@ -1,10 +1,30 @@
import { ceil, floor } from "lodash";
import { RootState } from "../../../app/store"; import { RootState } from "../../../app/store";
import { ACCOUNTS_VIEW_LIMIT } from "./constants";
export const selectMyAccountInfo = (state: RootState) =>
state.partnerLicense.domain.myAccountInfo;
export const selectTotal = (state: RootState) => export const selectTotal = (state: RootState) =>
state.partnerLicense.domain.total; state.partnerLicense.domain.total;
export const selectOwnPartnerLicense = (state: RootState) => export const selectOwnPartnerLicense = (state: RootState) =>
state.partnerLicense.domain.ownPartnerLicense; state.partnerLicense.domain.ownPartnerLicense;
export const selectChildrenPartnerLicenses = (state: RootState) => export const selectChildrenPartnerLicenses = (state: RootState) =>
state.partnerLicense.domain.childrenPartnerLicenses; state.partnerLicense.domain.childrenPartnerLicenses;
export const selectAccountInfo = (state: RootState) => export const selectHierarchicalElements = (state: RootState) =>
state.partnerLicense.domain.acountInfo; state.partnerLicense.apps.hierarchicalElements;
export const selectTotalPage = (state: RootState) => {
const { total } = state.partnerLicense.domain;
const page = ceil(total / ACCOUNTS_VIEW_LIMIT);
return page;
};
export const selectIsLoading = (state: RootState) =>
state.partnerLicense.apps.isLoading;
export const selectLimit = (state: RootState) =>
state.partnerLicense.apps.limit;
export const selectOffset = (state: RootState) =>
state.partnerLicense.apps.offset;
export const selectCurrentPage = (state: RootState) => {
const { limit, offset } = state.partnerLicense.apps;
const page = floor(offset / limit) + 1;
return page;
};

View File

@ -6,13 +6,22 @@ export interface PartnerLicensesState {
} }
export interface Domain { export interface Domain {
myAccountInfo: Account;
total: number; total: number;
ownPartnerLicense: PartnerLicenseInfo; ownPartnerLicense: PartnerLicenseInfo;
childrenPartnerLicenses: PartnerLicenseInfo[]; childrenPartnerLicenses: PartnerLicenseInfo[];
acountInfo: Account; totalPage: number;
} }
export interface Apps { export interface Apps {
limit: number; limit: number;
offset: number; offset: number;
currentPage: number;
hierarchicalElements: HierarchicalElement[];
isLoading: boolean;
}
export interface HierarchicalElement {
accountId: number;
companyName: string;
} }

View File

@ -1,11 +1,24 @@
import React from "react"; import React, { useCallback } from "react";
import Footer from "components/footer"; import Footer from "components/footer";
import Header from "components/header"; import Header from "components/header";
import styles from "styles/app.module.scss"; import styles from "styles/app.module.scss";
import { UpdateTokenTimer } from "components/auth/updateTokenTimer"; import { UpdateTokenTimer } from "components/auth/updateTokenTimer";
const PartnerLicense: React.FC = (): JSX.Element => ( interface LicenseOrderHistoryProps {
onClose: () => void;
}
export const LicenseOrderHistory: React.FC<LicenseOrderHistoryProps> = (
props
): JSX.Element => {
const { onClose } = props;
// ポップアップを閉じる処理
const closeScreen = useCallback(() => {
onClose();
}, [onClose]);
// 表示確認用の仮画面 // 表示確認用の仮画面
return (
<div className={styles.wrap}> <div className={styles.wrap}>
<Header userName="XXXXXX" /> <Header userName="XXXXXX" />
<UpdateTokenTimer /> <UpdateTokenTimer />
@ -17,18 +30,16 @@ const PartnerLicense: React.FC = (): JSX.Element => (
</div> </div>
<ul className={styles.menuAction}> <ul className={styles.menuAction}>
<li> <li>
<a <button type="button" onClick={closeScreen}>
href="/license"
className={`${styles.menuLink} ${styles.isActive}`}
>
<img src="images/undo.svg" alt="" className={styles.menuIcon} /> <img src="images/undo.svg" alt="" className={styles.menuIcon} />
Return Return
</a> </button>
</li> </li>
</ul> </ul>
</main> </main>
<Footer /> <Footer />
</div> </div>
); );
};
export default PartnerLicense; export default LicenseOrderHistory;

View File

@ -1,32 +1,42 @@
import React, { useCallback, useState, useEffect } from "react"; import React, { useCallback, useState, useEffect } from "react";
import { useMsal } from "@azure/msal-react";
import Footer from "components/footer"; import Footer from "components/footer";
import Header from "components/header"; import Header from "components/header";
import styles from "styles/app.module.scss"; import styles from "styles/app.module.scss";
import { UpdateTokenTimer } from "components/auth/updateTokenTimer"; import { UpdateTokenTimer } from "components/auth/updateTokenTimer";
import { clearToken } from "features/auth";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { AppDispatch } from "app/store"; import { AppDispatch } from "app/store";
import { getTranslationID } from "translation"; import { getTranslationID } from "translation";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { PartnerLicenseInfo } from "api";
import { CardLicenseIssuePopup } from "./cardLicenseIssuePopup"; import { CardLicenseIssuePopup } from "./cardLicenseIssuePopup";
import postAdd from "../../assets/images/post_add.svg"; import postAdd from "../../assets/images/post_add.svg";
import history from "../../assets/images/history.svg"; import history from "../../assets/images/history.svg";
import returnLabel from "../../assets/images/undo.svg";
import { isApproveTier } from "../../features/auth/utils"; import { isApproveTier } from "../../features/auth/utils";
import { TIERS } from "../../components/auth/constants"; import { TIERS } from "../../components/auth/constants";
import { import {
getMyAccountAsync,
getPartnerLicenseAsync, getPartnerLicenseAsync,
ACCOUNTS_VIEW_LIMIT, ACCOUNTS_VIEW_LIMIT,
selectMyAccountInfo,
selectTotal, selectTotal,
selectOwnPartnerLicense, selectOwnPartnerLicense,
selectChildrenPartnerLicenses, selectChildrenPartnerLicenses,
selectAccountInfo, selectHierarchicalElements,
selectTotalPage,
selectIsLoading,
selectOffset,
selectCurrentPage,
pushHierarchicalElement,
popHierarchicalElement,
spliceHierarchicalElement,
savePageInfo,
getMyAccountAsync,
} from "../../features/license/partnerLicense"; } from "../../features/license/partnerLicense";
import { LicenseOrderPopup } from "./licenseOrderPopup"; import { LicenseOrderPopup } from "./licenseOrderPopup";
import LicenseSummary from "./licenseSummary";
import { LicenseOrderHistory } from "../LicenseOrderHistoryPage";
const PartnerLicense: React.FC = (): JSX.Element => { const PartnerLicense: React.FC = (): JSX.Element => {
const { instance } = useMsal();
const dispatch: AppDispatch = useDispatch(); const dispatch: AppDispatch = useDispatch();
const [t] = useTranslation(); const [t] = useTranslation();
@ -34,6 +44,8 @@ const PartnerLicense: React.FC = (): JSX.Element => {
const [isCardLicenseIssuePopupOpen, setIsCardLicenseIssuePopupOpen] = const [isCardLicenseIssuePopupOpen, setIsCardLicenseIssuePopupOpen] =
useState(false); useState(false);
const [islicenseOrderPopupOpen, setIslicenseOrderPopupOpen] = useState(false); const [islicenseOrderPopupOpen, setIslicenseOrderPopupOpen] = useState(false);
const [islicenseOrderHistoryOpen, setIslicenseOrderHistoryOpen] =
useState(false);
// 階層表示用 // 階層表示用
const tierNames: { [key: number]: string } = { const tierNames: { [key: number]: string } = {
@ -58,48 +70,138 @@ const PartnerLicense: React.FC = (): JSX.Element => {
}, [setIslicenseOrderPopupOpen]); }, [setIslicenseOrderPopupOpen]);
// apiからの値取得関係 // apiからの値取得関係
const myAccountInfo = useSelector(selectAccountInfo); const myAccountInfo = useSelector(selectMyAccountInfo);
const total = useSelector(selectTotal); const total = useSelector(selectTotal);
const totalPage = useSelector(selectTotalPage);
const ownPartnerLicenseInfo = useSelector(selectOwnPartnerLicense); const ownPartnerLicenseInfo = useSelector(selectOwnPartnerLicense);
const childrenPartnerLicensesInfo = useSelector( const childrenPartnerLicensesInfo = useSelector(
selectChildrenPartnerLicenses selectChildrenPartnerLicenses
); );
const hierarchicalElements = useSelector(selectHierarchicalElements);
const isLoading = useSelector(selectIsLoading);
// ページネーション制御用
const currentPage = useSelector(selectCurrentPage);
const offset = useSelector(selectOffset);
// ページネーションのボタンクリック時のアクション
const movePage = (targetOffset: number) => {
dispatch(
savePageInfo({ limit: ACCOUNTS_VIEW_LIMIT, offset: targetOffset })
);
};
// パンくずリスト内のアカウント押下時
const onClickBreadCrumbList = (id: number) => {
const clickLevel = hierarchicalElements.findIndex(
(param) => param.accountId === id
);
const nowLevel = hierarchicalElements.length - 1;
const deleteCount = nowLevel - clickLevel;
// 階層を上がった分だけ表示アカウント管理用の配列の最後からパラメータを削除する
if (deleteCount > 0) {
dispatch(spliceHierarchicalElement({ deleteCount }));
movePage(0);
}
};
// 行要素クリック時イベント
const handleRowClick = (value: PartnerLicenseInfo) => {
dispatch(
pushHierarchicalElement({
hierarchicalElement: {
accountId: value.accountId,
companyName: value.companyName,
},
})
);
movePage(0);
};
// returnボタンクリック時イベント
const returnClick = () => {
dispatch(popHierarchicalElement());
movePage(0);
};
// ログイン時に階層をチェック // ログイン時に階層をチェック
const isTier1 = isApproveTier([TIERS.TIER1]); const isTier1 = isApproveTier([TIERS.TIER1]);
const isTier2ToTier4 = isApproveTier([TIERS.TIER2, TIERS.TIER3, TIERS.TIER4]); const isTier2ToTier4 = isApproveTier([TIERS.TIER2, TIERS.TIER3, TIERS.TIER4]);
// パラメーターを入れておく空配列 // licenseDetailsボタン押下時
// eslint-disable-next-line react-hooks/exhaustive-deps // TODO 本PIBでは対象外のため、遷移先の内容の正しさは対象外
const hierarchicalElements: HierarchicalElements[] = []; const onClickViewDetails = () => <LicenseSummary />;
// orderHistoryボタン押下時
// TODO 本PIBでは画面遷移までで、遷移先の内容の正しさは対象外
const onClickOrderHistory = useCallback(() => {
setIslicenseOrderHistoryOpen(true);
}, [setIslicenseOrderHistoryOpen]);
// マウント時のみ実行 // マウント時のみ実行
useEffect(() => { useEffect(() => {
dispatch(getMyAccountAsync()); dispatch(getMyAccountAsync());
dispatch(
getPartnerLicenseAsync({
limit: ACCOUNTS_VIEW_LIMIT,
offset: 0,
accountId: myAccountInfo.accountId,
})
);
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, []);
// 画面遷移時に実行 // 自アカウントID取得時に実行
// TODO 仮実装なので挙動は未検証
useEffect(() => { useEffect(() => {
if (hierarchicalElements.length === 1) { if (myAccountInfo.accountId !== 0) {
dispatch(getMyAccountAsync());
}
dispatch( dispatch(
getPartnerLicenseAsync({ getPartnerLicenseAsync({
limit: ACCOUNTS_VIEW_LIMIT, limit: ACCOUNTS_VIEW_LIMIT,
offset: 0, offset,
accountId: myAccountInfo.accountId, accountId: myAccountInfo.accountId,
}) })
); );
}, [dispatch, hierarchicalElements, myAccountInfo]); }
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [myAccountInfo]);
// 現在の表示階層に合わせたボタン制御用
const [buttonLabel, setButtonLabel] = useState("");
// パンくずリスト用stateに自アカウントを追加
useEffect(() => {
if (
hierarchicalElements.length === 0 &&
ownPartnerLicenseInfo.accountId !== 0
) {
dispatch(
pushHierarchicalElement({
hierarchicalElement: {
accountId: ownPartnerLicenseInfo.accountId,
companyName: ownPartnerLicenseInfo.companyName,
},
})
);
}
// 表内のボタン表示判定
if (hierarchicalElements.length === 1 && ownPartnerLicenseInfo.tier !== 4) {
setButtonLabel(
t(getTranslationID("partnerLicense.label.orderHistoryButton"))
);
} else if (ownPartnerLicenseInfo.tier === 4) {
setButtonLabel(t(getTranslationID("partnerLicense.label.viewDetails")));
} else {
setButtonLabel("");
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ownPartnerLicenseInfo]);
// 表内の情報取得処理
useEffect(() => {
if (hierarchicalElements.length !== 0) {
dispatch(
getPartnerLicenseAsync({
limit: ACCOUNTS_VIEW_LIMIT,
offset,
accountId:
hierarchicalElements[hierarchicalElements.length - 1].accountId,
})
);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [hierarchicalElements, currentPage]);
return ( return (
<> <>
@ -119,7 +221,14 @@ const PartnerLicense: React.FC = (): JSX.Element => {
}} }}
/> />
)} )}
{islicenseOrderHistoryOpen && (
<LicenseOrderHistory
onClose={() => {
setIslicenseOrderHistoryOpen(false);
}}
/>
)}
{!islicenseOrderHistoryOpen && (
<div className={styles.wrap}> <div className={styles.wrap}>
<Header userName="XXXXXX" /> <Header userName="XXXXXX" />
<UpdateTokenTimer /> <UpdateTokenTimer />
@ -137,17 +246,22 @@ const PartnerLicense: React.FC = (): JSX.Element => {
<h2>{t(getTranslationID("partnerLicense.label.subTitle"))}</h2> <h2>{t(getTranslationID("partnerLicense.label.subTitle"))}</h2>
<ul className={styles.menuAction}> <ul className={styles.menuAction}>
<li> <li>
{hierarchicalElements.length > 1 && (
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
<a <a
href="license_partner.html"
className={`${styles.menuLink} ${styles.isActive}`} className={`${styles.menuLink} ${styles.isActive}`}
onClick={returnClick}
> >
<img <img
src="images/undo.svg" src={returnLabel}
alt="" alt=""
className={styles.menuIcon} className={styles.menuIcon}
/> />
{t(getTranslationID("partnerLicense.label.returnButton"))} {t(
getTranslationID("partnerLicense.label.returnButton")
)}
</a> </a>
)}
</li> </li>
<li> <li>
{isTier2ToTier4 && ( {isTier2ToTier4 && (
@ -167,9 +281,10 @@ const PartnerLicense: React.FC = (): JSX.Element => {
</li> </li>
<li> <li>
{isTier2ToTier4 && ( {isTier2ToTier4 && (
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
<a <a
href="license_history.html"
className={`${styles.menuLink} ${styles.isActive}`} className={`${styles.menuLink} ${styles.isActive}`}
onClick={onClickOrderHistory}
> >
<img src={history} alt="" className={styles.menuIcon} /> <img src={history} alt="" className={styles.menuIcon} />
{t( {t(
@ -197,29 +312,19 @@ const PartnerLicense: React.FC = (): JSX.Element => {
</a> </a>
)} )}
</li> </li>
<li>
<a
href="license_partner_card_history.html"
className={`${styles.menuLink} ${styles.isActive}`}
>
<img src={history} alt="" className={styles.menuIcon} />
{t(
getTranslationID(
"partnerLicense.label.displayCardHistoryButton"
)
)}
</a>
</li>
</ul> </ul>
{/* TODO パンくずリストの表示内容、リンク先は仮 */}
<ul className={styles.brCrumbLicense}> <ul className={styles.brCrumbLicense}>
<li> {hierarchicalElements.map((value) => (
<a href="">OMDS US</a> // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions
<li
key={value.accountId}
onClick={() => {
onClickBreadCrumbList(value.accountId);
}}
>
<a>{value.companyName}</a>
</li> </li>
<li> ))}
<a href="">BBBB inc.</a>
</li>
<li>ABCDEFGHIJKLM corp.</li>
</ul> </ul>
<table className={`${styles.table} ${styles.partner}`}> <table className={`${styles.table} ${styles.partner}`}>
<tr className={styles.tableHeader}> <tr className={styles.tableHeader}>
@ -234,7 +339,9 @@ const PartnerLicense: React.FC = (): JSX.Element => {
{t(getTranslationID("partnerLicense.label.stockLicense"))} {t(getTranslationID("partnerLicense.label.stockLicense"))}
</th> </th>
<th> <th>
{t(getTranslationID("partnerLicense.label.issueRequested"))} {t(
getTranslationID("partnerLicense.label.issueRequested")
)}
</th> </th>
<th> <th>
{t(getTranslationID("partnerLicense.label.shortage"))} {t(getTranslationID("partnerLicense.label.shortage"))}
@ -251,33 +358,41 @@ const PartnerLicense: React.FC = (): JSX.Element => {
<td>{ownPartnerLicenseInfo.companyName}</td> <td>{ownPartnerLicenseInfo.companyName}</td>
<td>{tierNames[ownPartnerLicenseInfo.tier]}</td> <td>{tierNames[ownPartnerLicenseInfo.tier]}</td>
<td>{ownPartnerLicenseInfo.accountId}</td> <td>{ownPartnerLicenseInfo.accountId}</td>
<td>{ownPartnerLicenseInfo.stockLicense}</td> <td>
{ownPartnerLicenseInfo.tier !== 1
? ownPartnerLicenseInfo.stockLicense
: "-"}
</td>
<td>{ownPartnerLicenseInfo.issuedRequested}</td> <td>{ownPartnerLicenseInfo.issuedRequested}</td>
<td>{ownPartnerLicenseInfo.shortage}</td> <td>
<td>{ownPartnerLicenseInfo.issueRequesting}</td> {ownPartnerLicenseInfo.tier !== 1
? ownPartnerLicenseInfo.shortage
: "-"}
</td>
<td>
{ownPartnerLicenseInfo.tier !== 1
? ownPartnerLicenseInfo.issueRequesting
: "-"}
</td>
<td> <td>
<ul <ul
className={`${styles.menuAction} ${styles.menuInTable}`} className={`${styles.menuAction} ${styles.menuInTable}`}
> >
<li> <li>{/* レイアウト維持用 */}</li>
{/* TODO リンク先は仮 ボタン表示制御未実装 */}
<a
href="license_partner_history.html"
className={styles.menuLink}
>
{t(
getTranslationID(
"partnerLicense.label.orderHistoryButton"
)
)}
</a>
</li>
</ul> </ul>
</td> </td>
</tr> </tr>
{childrenPartnerLicensesInfo.map((value) => ( {childrenPartnerLicensesInfo.map((value) => (
<tr key={value.accountId}> <tr key={value.accountId}>
<td title="">{value.companyName}</td> <td
onClick={() => {
if (value.tier !== 5) {
handleRowClick(value);
}
}}
>
{value.companyName}
</td>
<td>{tierNames[value.tier]}</td> <td>{tierNames[value.tier]}</td>
<td>{value.accountId}</td> <td>{value.accountId}</td>
<td>{value.stockLicense}</td> <td>{value.stockLicense}</td>
@ -285,18 +400,24 @@ const PartnerLicense: React.FC = (): JSX.Element => {
<td>{value.shortage}</td> <td>{value.shortage}</td>
<td>{value.issueRequesting}</td> <td>{value.issueRequesting}</td>
<td> <td>
<ul className={`${styles.menuAction} ${styles.inTable}`}> <ul
<li> className={`${styles.menuAction} ${styles.inTable}`}
{/* TODO リンク先は仮 ボタン表示制御未実装 */}
<a
href="license_partner_5.html"
className={`${styles.menuLink} ${styles.isActive}`}
> >
{t( <li>
getTranslationID( {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
"partnerLicense.label.viewDetails" <a
) className={`${styles.menuLink} ${
)} buttonLabel ? styles.isActive : ""
}`}
onClick={() => {
if (ownPartnerLicenseInfo.tier === 4) {
onClickViewDetails();
} else {
onClickOrderHistory();
}
}}
>
{buttonLabel}
</a> </a>
</li> </li>
</ul> </ul>
@ -311,13 +432,55 @@ const PartnerLicense: React.FC = (): JSX.Element => {
{total}{" "} {total}{" "}
{t(getTranslationID("partnerLicense.label.accounts"))} {t(getTranslationID("partnerLicense.label.accounts"))}
</span> </span>
{/* TODO ページ数は仮、ページ遷移、ボタン表示制御未実装 */} {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
<a href="">«</a> <a
<a href=""></a>1 of 2 onClick={() => {
<a href="" className={` ${styles.isActive}`}> movePage(0);
}}
className={` ${
!isLoading && currentPage !== 1 ? styles.isActive : ""
}`}
>
«
</a>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
<a
onClick={() => {
movePage((currentPage - 2) * ACCOUNTS_VIEW_LIMIT);
}}
className={`${
!isLoading && currentPage !== 1 ? styles.isActive : ""
}`}
>
</a>
{` ${total !== 0 ? currentPage : 0} of ${
total !== 0 ? totalPage : 0
} `}
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
<a
onClick={() => {
movePage(currentPage * ACCOUNTS_VIEW_LIMIT);
}}
className={`${
!isLoading && currentPage < totalPage
? styles.isActive
: ""
}`}
>
</a> </a>
<a href="" className={` ${styles.isActive}`}> {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
<a
onClick={() => {
movePage((totalPage - 1) * ACCOUNTS_VIEW_LIMIT);
}}
className={` ${
!isLoading && currentPage < totalPage
? styles.isActive
: ""
}`}
>
» »
</a> </a>
</nav> </nav>
@ -325,26 +488,12 @@ const PartnerLicense: React.FC = (): JSX.Element => {
</div> </div>
</section> </section>
</main> </main>
<div>
<button
type="button"
className={styles.buttonText}
onClick={() => {
instance.logout({ postLogoutRedirectUri: "/" });
dispatch(clearToken());
}}
>
sign out
</button>
</div>{" "}
<Footer /> <Footer />
</div> </div>
)}
;
</> </>
); );
}; };
export interface HierarchicalElements {
accountId: string;
companyName: string;
}
export default PartnerLicense; export default PartnerLicense;

View File

@ -384,12 +384,18 @@ h3 .brCrumb .tlIcon {
} }
.brCrumbLicense li { .brCrumbLicense li {
display: inline-block; display: inline-block;
padding-right: 1.4rem; max-width: calc(25% - 1.4rem);
font-size: 1.1rem; font-size: 1.1rem;
line-height: 1.4; line-height: 1.4;
letter-spacing: 0.04rem; letter-spacing: 0.04rem;
font-weight: normal; font-weight: normal;
position: relative; position: relative;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.brCrumbLicense li:not(:last-child) {
padding-right: 1.4rem;
} }
.brCrumbLicense li:not(:last-child)::after { .brCrumbLicense li:not(:last-child)::after {
content: ""; content: "";