saito.k deb3431d74 Merged PR 531: 画面実装(代行操作)
## 概要
[Task2909: 画面実装(代行操作)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2909)

- ディーラーユーザーが代行操作用トークンを取得して、第五階層ユーザーの代行操作ができる実装をしました。
  - 代行後に各対象タブが代行操作デザインで表示され、代行対象として操作できるようになっています。
    - 各APIの呼び出しについて代行操作用トークンがあればそちらを使うように実装しています。
 - 代行操作のタブ、ページ移動時に代行操作を維持するために遷移をリンクから`useNavigate`に変更しました。

## レビューポイント
- 代行操作用トークンの取り扱いについて
  - APIからのトークン取得後、`store.auth`に代行操作用トークンを保存し、利用時には関数を使って間接的に呼でいますが構成として不自然な点はないでしょうか?
    - トークン取得関数では代行操作用トークンがあればそれを、なければ通常のトークンを取得するようにしています。
      - これはAPIのトークンを設定する際にトークンを取得側では代行操作中か意識せずに一つの関数を呼べばいいようにするためです。
  - 代行操作用トークンの保存は通常のトークン保存と同様に`operation`から`Slice`に設定したSet関数を呼ぶことでstateに保存していますが、使い方として気になることはないでしょうか?

※代行操作中に表示するタブの制限と代行操作トークンの更新処理は別タスクでの実施予定です。

## UIの変更
- [Task2909](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/Task2909?csf=1&web=1&e=TnwgOb)

## 動作確認状況
- ローカルで確認
2023-11-06 08:28:40 +00:00

119 lines
3.2 KiB
TypeScript

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 { getAccessToken } from "features/auth";
import {
AccountsApi,
CreatePartnerAccountRequest,
GetPartnersResponse,
} 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 } = state.auth;
const accessToken = getAccessToken(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 });
}
});
// パートナー一覧取得APIからパートナーのアカウント情報をもらう
export const getPartnerInfoAsync = createAsyncThunk<
// 正常時の戻り値の型
GetPartnersResponse,
{
// パラメータ
limit: number;
offset: number;
},
{
// rejectした時の返却値の型
rejectValue: {
error: ErrorObject;
};
}
>("partner/getPartnerInfoAsync", async (args, thunkApi) => {
const { limit, offset } = args;
const { getState } = thunkApi;
const state = getState() as RootState;
const { configuration } = state.auth;
const accessToken = getAccessToken(state.auth);
const config = new Configuration(configuration);
const accountsApi = new AccountsApi(config);
try {
const res = await accountsApi.getPartners(limit, offset, {
headers: { authorization: `Bearer ${accessToken}` },
});
const ret = {
partners: res.data.partners,
total: res.data.total,
};
return ret;
} catch (e) {
const error = createErrorObject(e);
const errorMessage = getTranslationID("common.message.internalServerError");
thunkApi.dispatch(
openSnackbar({
level: "error",
message: errorMessage,
})
);
return thunkApi.rejectWithValue({ error });
}
});