You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

300 lines
7.9KB

  1. import { AxiosError, AxiosResponse } from "axios";
  2. import { format } from "date-fns";
  3. import { Dictionary, get } from "lodash";
  4. import { DataUrl } from "@types";
  5. import { setFormErrorMessages } from "components/hook-form";
  6. import axios from "utils/axios";
  7. let id = 0;
  8. export const ApiId = {
  9. // 共通---------------------------------------
  10. CSRF_TOKEN: id++,
  11. // 認証関連 ----------------------------------
  12. ME: id++,
  13. LOGIN: id++,
  14. LOGOUT: id++,
  15. 顧客成り代わり開始: id++,
  16. 店舗成り代わり開始: id++,
  17. 成り代わり終了: id++,
  18. // ログインユーザ関連 ----------------------------------
  19. 顧客ログインユーザ新規登録: id++,
  20. 店舗ログインユーザ新規登録: id++,
  21. 店舗ログインユーザ一覧取得: id++,
  22. 顧客ログインユーザ一覧取得: id++,
  23. // 顧客関連 ----------------------------------
  24. 顧客マスタ一覧取得: id++,
  25. // 駐車場関連 ----------------------------------
  26. 駐車場マスタ一覧取得: id++,
  27. サービス券マスタ一覧取得: id++,
  28. // 店舗関連関連 ----------------------------------
  29. 店舗一覧取得: id++,
  30. 店舗新規登録: id++,
  31. デポジット情報取得: id++,
  32. デポジットチャージ: id++,
  33. 店舗設定: id++,
  34. 店舗QR設定取得: id++,
  35. 店舗QR設定認証設定新規登録: id++,
  36. 店舗QR設定認証設定更新: id++,
  37. 店舗QR設定認証設定追加: id++,
  38. 店舗QR設定認証設定削除: id++,
  39. 店舗QR設定認証設定全削除: id++,
  40. 店舗QR設定取得設定変更: id++,
  41. 店舗QR設定取得設定無効化: id++,
  42. // QRサービス券関連-------------------------------
  43. QRサービス券駐車場グループ一覧取得: id++,
  44. QRサービス券駐車場グループ新規登録: id++,
  45. QRサービス券駐車場グループ駐車場追加登録: id++,
  46. QRサービス券駐車場グループ駐車場削除登録: id++,
  47. QRサービス券取得用トークン取得: id++,
  48. QRサービス券取得用トークンリフレッシュ: id++,
  49. QRサービス券取得: id++,
  50. QRサービス券承認チェック: id++,
  51. QRサービス券承認: id++,
  52. } as const;
  53. export type ApiId = (typeof ApiId)[keyof typeof ApiId];
  54. export const HttpMethod = {
  55. GET: "get",
  56. POST: "post",
  57. } as const;
  58. export type HttpMethod = (typeof HttpMethod)[keyof typeof HttpMethod];
  59. export const ResultCode = {
  60. SUCCESS: 0,
  61. FAILED: 1,
  62. UNAUTHORIZED: 2,
  63. EXCLUSIVE_ERROR: 3,
  64. };
  65. export type ResultCode = (typeof ResultCode)[keyof typeof ResultCode];
  66. export interface TimestampRequest {
  67. timestamp: string;
  68. }
  69. export type ListRequest = {
  70. sort?: string;
  71. order?: string;
  72. };
  73. export interface APICommonResponse {
  74. result: ResultCode;
  75. messages: {
  76. errors?: Dictionary<string>;
  77. general?: string;
  78. email_id?: number;
  79. };
  80. }
  81. export type ImagesResponse = {
  82. data: {
  83. images: DataUrl[];
  84. };
  85. } & APICommonResponse;
  86. export const makeParam = <T extends object>(data: T): Dictionary<string> => {
  87. const res: Dictionary<string> = {};
  88. Object.keys(data).map((key) => {
  89. const val = get(data, key);
  90. if (typeof val === "string" && val.length !== 0) {
  91. res[key] = val;
  92. } else if (typeof val === "number") {
  93. res[key] = String(val);
  94. } else if (typeof val === "boolean") {
  95. res[key] = val ? "1" : "0";
  96. } else if (val instanceof Date) {
  97. res[key] = format(val, "yyyy-MM-dd");
  98. }
  99. });
  100. return res;
  101. };
  102. export const makeFormData = <T extends object>(data: T): FormData => {
  103. const res = new FormData();
  104. Object.keys(data).map((key) => {
  105. const val = get(data, key);
  106. if (typeof val === "string" && val.length !== 0) {
  107. res.append(key, val);
  108. } else if (typeof val === "number") {
  109. res.append(key, String(val));
  110. } else if (typeof val === "boolean") {
  111. res.append(key, val ? "1" : "0");
  112. } else if (val instanceof Date) {
  113. res.append(key, format(val, "yyyy-MM-dd"));
  114. } else if (val instanceof File) {
  115. res.append(key, val);
  116. } else if (Array.isArray(val)) {
  117. val.forEach((v) => {
  118. res.append(key + "[]", v);
  119. });
  120. } else {
  121. console.log("undefined data", key, val);
  122. }
  123. });
  124. return res;
  125. };
  126. const isAxiosError = (error: any): error is AxiosError => {
  127. return !!error.isAxiosError;
  128. };
  129. type RequestArgument = {
  130. url: string;
  131. method: HttpMethod;
  132. data?: URLSearchParams | FormData | object;
  133. multipart?: boolean;
  134. };
  135. export const request = async <T extends APICommonResponse>({
  136. url,
  137. method,
  138. data,
  139. multipart,
  140. }: RequestArgument): Promise<T | null> => {
  141. let response: AxiosResponse<T | any> | null = null;
  142. if (data instanceof URLSearchParams) {
  143. data.sort();
  144. }
  145. try {
  146. if (multipart && data instanceof FormData) {
  147. response = await axios({
  148. url,
  149. method: "post",
  150. data,
  151. headers: {
  152. "content-type": "multipart/form-data",
  153. },
  154. });
  155. console.log("RESPONSE", url, "multipart", data, response?.data);
  156. } else if (method === HttpMethod.GET) {
  157. let searchUrl = url;
  158. if (data instanceof URLSearchParams) {
  159. searchUrl += "?" + data.toString();
  160. }
  161. response = await axios.get<T>(searchUrl);
  162. console.log(new Date(), "RESPONSE", searchUrl, method, response?.data);
  163. } else if (method === HttpMethod.POST) {
  164. response = await axios.post<T>(url, data);
  165. let sendData: Dictionary<String> = {};
  166. if (data instanceof URLSearchParams) {
  167. data.forEach((val, key) => {
  168. sendData[key] = val;
  169. });
  170. } else if (typeof data === "object" && !(data instanceof FormData)) {
  171. Object.keys(data).forEach((key) => {
  172. sendData[key] = get(data, key);
  173. });
  174. }
  175. console.log("RESPONSE", url, method, sendData, response?.data);
  176. } else {
  177. return null;
  178. }
  179. if (response && response.data.result === ResultCode.SUCCESS) {
  180. return response.data;
  181. }
  182. return response?.data;
  183. } catch (e) {
  184. if (isAxiosError(e)) {
  185. if (e.response?.status === 401 || e.response?.status === 419) {
  186. window.location.reload();
  187. return null;
  188. }
  189. }
  190. if (typeof e === "object") {
  191. const message = get(e, "message");
  192. if (message === "Unauthenticated.") {
  193. console.log("401!!!");
  194. window.location.reload();
  195. return null;
  196. }
  197. if (message === "CSRF token mismatch.") {
  198. console.log("419!!!");
  199. window.location.reload();
  200. return null;
  201. }
  202. if (message === "Service Unavailable") {
  203. console.log("503!!!");
  204. window.location.reload();
  205. return null;
  206. }
  207. }
  208. throw e;
  209. }
  210. };
  211. export async function apiRequest<
  212. T extends APICommonResponse,
  213. U extends object
  214. >({
  215. apiMethod,
  216. sendData,
  217. onSuccess,
  218. onFailed,
  219. onFinaly,
  220. errorSetter,
  221. setSending,
  222. }: {
  223. apiMethod: (sendData: U) => Promise<T | null>;
  224. sendData: U;
  225. onSuccess?: (res: T, sendData: U) => void;
  226. onFailed?: (res: APICommonResponse | null) => void;
  227. onFinaly?: (res: APICommonResponse | null) => void;
  228. errorSetter?: any;
  229. setSending?: (sending: boolean) => void;
  230. }) {
  231. if (setSending) {
  232. setSending(true);
  233. }
  234. try {
  235. const res = await apiMethod(sendData);
  236. if (setSending) {
  237. setSending(false);
  238. }
  239. if (res?.result === ResultCode.SUCCESS) {
  240. if (onSuccess) {
  241. onSuccess(res, sendData);
  242. }
  243. } else {
  244. if (res?.messages.errors) {
  245. if (errorSetter) {
  246. const errorCount = setFormErrorMessages(
  247. sendData,
  248. errorSetter,
  249. res.messages.errors
  250. );
  251. console.log("FormErrorCount", errorCount);
  252. }
  253. }
  254. if (onFailed) {
  255. onFailed(res);
  256. }
  257. if (onFinaly) {
  258. onFinaly(res);
  259. }
  260. }
  261. return res;
  262. } catch (e) {
  263. if (setSending) {
  264. setSending(false);
  265. }
  266. console.error(e);
  267. if (onFailed) {
  268. onFailed(null);
  269. }
  270. if (onFinaly) {
  271. onFinaly(null);
  272. }
  273. return null;
  274. }
  275. }