import { AxiosError, AxiosResponse } from "axios"; import { format } from "date-fns"; import { Dictionary, get } from "lodash"; import { DataUrl } from "@types"; import { setFormErrorMessages } from "components/hook-form"; import axios from "utils/axios"; let id = 0; export const ApiId = { // 共通--------------------------------------- CSRF_TOKEN: id++, // 認証関連 ---------------------------------- ME: id++, LOGIN: id++, LOGOUT: id++, 顧客成り代わり開始: id++, 店舗成り代わり開始: id++, 成り代わり終了: id++, // ログインユーザ関連 ---------------------------------- 顧客ログインユーザ新規登録: id++, 店舗ログインユーザ新規登録: id++, 店舗ログインユーザ一覧取得: id++, 顧客ログインユーザ一覧取得: id++, // 顧客関連 ---------------------------------- 顧客マスタ一覧取得: id++, // 駐車場関連 ---------------------------------- 駐車場マスタ一覧取得: id++, サービス券マスタ一覧取得: id++, // 店舗関連関連 ---------------------------------- 店舗一覧取得: id++, 店舗新規登録: id++, デポジット情報取得: id++, デポジットチャージ: id++, 店舗設定: id++, 店舗QR設定取得: id++, 店舗QR設定認証設定新規登録: id++, 店舗QR設定認証設定更新: id++, 店舗QR設定認証設定追加: id++, 店舗QR設定認証設定削除: id++, 店舗QR設定認証設定全削除: id++, 店舗QR設定取得設定変更: id++, 店舗QR設定取得設定無効化: id++, // QRサービス券関連------------------------------- QRサービス券駐車場グループ一覧取得: id++, QRサービス券駐車場グループ新規登録: id++, QRサービス券駐車場グループ駐車場追加登録: id++, QRサービス券駐車場グループ駐車場削除登録: id++, QRサービス券取得用トークン取得: id++, QRサービス券取得用トークンリフレッシュ: id++, QRサービス券取得: id++, QRサービス券承認チェック: id++, QRサービス券承認: id++, } as const; export type ApiId = (typeof ApiId)[keyof typeof ApiId]; export const HttpMethod = { GET: "get", POST: "post", } as const; export type HttpMethod = (typeof HttpMethod)[keyof typeof HttpMethod]; export const ResultCode = { SUCCESS: 0, FAILED: 1, UNAUTHORIZED: 2, EXCLUSIVE_ERROR: 3, }; export type ResultCode = (typeof ResultCode)[keyof typeof ResultCode]; export interface TimestampRequest { timestamp: string; } export type ListRequest = { sort?: string; order?: string; }; export interface APICommonResponse { result: ResultCode; messages: { errors?: Dictionary; general?: string; email_id?: number; }; } export type ImagesResponse = { data: { images: DataUrl[]; }; } & APICommonResponse; export const makeParam = (data: T): Dictionary => { const res: Dictionary = {}; Object.keys(data).map((key) => { const val = get(data, key); if (typeof val === "string" && val.length !== 0) { res[key] = val; } else if (typeof val === "number") { res[key] = String(val); } else if (typeof val === "boolean") { res[key] = val ? "1" : "0"; } else if (val instanceof Date) { res[key] = format(val, "yyyy-MM-dd"); } }); return res; }; export const makeFormData = (data: T): FormData => { const res = new FormData(); Object.keys(data).map((key) => { const val = get(data, key); if (typeof val === "string" && val.length !== 0) { res.append(key, val); } else if (typeof val === "number") { res.append(key, String(val)); } else if (typeof val === "boolean") { res.append(key, val ? "1" : "0"); } else if (val instanceof Date) { res.append(key, format(val, "yyyy-MM-dd")); } else if (val instanceof File) { res.append(key, val); } else if (Array.isArray(val)) { val.forEach((v) => { res.append(key + "[]", v); }); } else { console.log("undefined data", key, val); } }); return res; }; const isAxiosError = (error: any): error is AxiosError => { return !!error.isAxiosError; }; type RequestArgument = { url: string; method: HttpMethod; data?: URLSearchParams | FormData | object; multipart?: boolean; }; export const request = async ({ url, method, data, multipart, }: RequestArgument): Promise => { let response: AxiosResponse | null = null; if (data instanceof URLSearchParams) { data.sort(); } try { if (multipart && data instanceof FormData) { response = await axios({ url, method: "post", data, headers: { "content-type": "multipart/form-data", }, }); console.log("RESPONSE", url, "multipart", data, response?.data); } else if (method === HttpMethod.GET) { let searchUrl = url; if (data instanceof URLSearchParams) { searchUrl += "?" + data.toString(); } response = await axios.get(searchUrl); console.log(new Date(), "RESPONSE", searchUrl, method, response?.data); } else if (method === HttpMethod.POST) { response = await axios.post(url, data); let sendData: Dictionary = {}; if (data instanceof URLSearchParams) { data.forEach((val, key) => { sendData[key] = val; }); } else if (typeof data === "object" && !(data instanceof FormData)) { Object.keys(data).forEach((key) => { sendData[key] = get(data, key); }); } console.log("RESPONSE", url, method, sendData, response?.data); } else { return null; } if (response && response.data.result === ResultCode.SUCCESS) { return response.data; } return response?.data; } catch (e) { if (isAxiosError(e)) { if (e.response?.status === 401 || e.response?.status === 419) { window.location.reload(); return null; } } if (typeof e === "object") { const message = get(e, "message"); if (message === "Unauthenticated.") { console.log("401!!!"); window.location.reload(); return null; } if (message === "CSRF token mismatch.") { console.log("419!!!"); window.location.reload(); return null; } if (message === "Service Unavailable") { console.log("503!!!"); window.location.reload(); return null; } } throw e; } }; export async function apiRequest< T extends APICommonResponse, U extends object >({ apiMethod, sendData, onSuccess, onFailed, onFinaly, errorSetter, setSending, }: { apiMethod: (sendData: U) => Promise; sendData: U; onSuccess?: (res: T, sendData: U) => void; onFailed?: (res: APICommonResponse | null) => void; onFinaly?: (res: APICommonResponse | null) => void; errorSetter?: any; setSending?: (sending: boolean) => void; }) { if (setSending) { setSending(true); } try { const res = await apiMethod(sendData); if (setSending) { setSending(false); } if (res?.result === ResultCode.SUCCESS) { if (onSuccess) { onSuccess(res, sendData); } } else { if (res?.messages.errors) { if (errorSetter) { const errorCount = setFormErrorMessages( sendData, errorSetter, res.messages.errors ); console.log("FormErrorCount", errorCount); } } if (onFailed) { onFailed(res); } if (onFinaly) { onFinaly(res); } } return res; } catch (e) { if (setSending) { setSending(false); } console.error(e); if (onFailed) { onFailed(null); } if (onFinaly) { onFinaly(null); } return null; } }