diff --git a/src/api/app.ts b/src/api/app.ts new file mode 100644 index 0000000..f8faf8e --- /dev/null +++ b/src/api/app.ts @@ -0,0 +1,15 @@ +import { ApiId, HttpMethod, request } from "."; +import { getUrl } from "./url"; + +export type CheckTokenRequest = { + access_token: string; +}; + +export const checkToken = async (data: CheckTokenRequest) => { + const res = await request({ + url: getUrl(ApiId.APP_TOKEN_CHECK), + method: HttpMethod.GET, + data: new URLSearchParams(data), + }); + return res; +}; diff --git a/src/api/custom/hello-techno/receipt-issuing-order.ts b/src/api/custom/hello-techno/receipt-issuing-order.ts index 7266397..eca8f1b 100644 --- a/src/api/custom/hello-techno/receipt-issuing-order.ts +++ b/src/api/custom/hello-techno/receipt-issuing-order.ts @@ -6,6 +6,7 @@ import { request, } from "api"; import { getUrl } from "api/url"; +import { ReceiptIssuingOrderStatus } from "codes/receipt-issuing-order"; export type HTCustomer = { customer_code: string; @@ -50,3 +51,39 @@ export const createReceiptIssuingOrder = async ( }); return res; }; + +export type ReceiptIssuingOrder = { + id: string; + order_datetime: string; + customer_code: string; + parking_management_code: string; + customer_name: string; + parking_name: string; + status: ReceiptIssuingOrderStatus; + handler_id: string; + handler_name: string; +}; + +export type ReceiptIssuingOrdersRequest = { + customer_code?: string; + customer_name?: string; + parking_management_code?: string; + parking_name?: string; +}; + +export type ReceiptIssuingOrdersResponse = { + data: { + records: ReceiptIssuingOrder[]; + }; +} & APICommonResponse; + +export const getReceiptIssuingOrders = async ( + data: ReceiptIssuingOrdersRequest +) => { + const res = await request({ + url: getUrl(ApiId.HT_CUSTOM_RECEIPT_ISSUING_ORDERS), + method: HttpMethod.GET, + data: new URLSearchParams(data), + }); + return res; +}; diff --git a/src/api/index.ts b/src/api/index.ts index c43eadc..c97ead0 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -13,6 +13,9 @@ export const ApiId = { LOGIN: id++, LOGOUT: id++, + APP_TOKEN_CHECK: id++, + DOWNLOAD_RECEIPT: id++, + RECEIPT_ISSUING_ORDERS: id++, RECEIPT_ISSUING_ORDER: id++, RECEIPT_ISSUING_ORDER_CREATE: id++, @@ -21,6 +24,7 @@ export const ApiId = { HT_CUSTOM_CUSTOMERS: id++, HT_CUSTOM_PARKINGS: id++, HT_CUSTOM_ADJUST_DATA: id++, + HT_CUSTOM_RECEIPT_ISSUING_ORDERS: id++, HT_CUSTOM_RECEIPT_ISSUING_ORDER_CREATE: id++, } as const; export type ApiId = (typeof ApiId)[keyof typeof ApiId]; diff --git a/src/api/url.ts b/src/api/url.ts index 8a2dec1..e18cb89 100644 --- a/src/api/url.ts +++ b/src/api/url.ts @@ -1,4 +1,6 @@ +import { env } from "process"; import { ApiId as A } from "."; +import { HOST_API } from "config"; const urls = { [A.CSRF_TOKEN]: "sanctum/csrf-cookie", @@ -6,18 +8,24 @@ const urls = { [A.LOGIN]: "login", [A.LOGOUT]: "logout", + [A.APP_TOKEN_CHECK]: "app-token-check", + [A.DOWNLOAD_RECEIPT]: "receipt/download", + [A.RECEIPT_ISSUING_ORDERS]: "receipt-issuing-orders", // FOR CUSTOM [A.HT_CUSTOM_CUSTOMERS]: "custom/hello-techno/customers", [A.HT_CUSTOM_PARKINGS]: "custom/hello-techno/parkings", [A.HT_CUSTOM_ADJUST_DATA]: "custom/hello-techno/adjust-data", + [A.HT_CUSTOM_RECEIPT_ISSUING_ORDERS]: + "custom/hello-techno/receipt-issuing-orders", [A.HT_CUSTOM_RECEIPT_ISSUING_ORDER_CREATE]: "custom/hello-techno/receipt-issuing-order/create", }; const prefixs = { [A.CSRF_TOKEN]: "", + [A.DOWNLOAD_RECEIPT]: "", }; const DEFAULT_API_URL_PREFIX = "api"; @@ -32,3 +40,7 @@ export const getUrl = (apiId: A) => { } return url + (urls[apiId] ?? ""); }; + +export const getFullUrl = (apiId: A) => { + return HOST_API + "/" + getUrl(apiId); +}; diff --git a/src/codes/page.ts b/src/codes/page.ts index 2875db3..f4ca1d3 100644 --- a/src/codes/page.ts +++ b/src/codes/page.ts @@ -5,6 +5,8 @@ export const PageID = { LOGIN: id++, LOGOUT: id++, + APP_RECEIPT_ISSUING_ORDER_INDEX: id++, + DASHBOARD_OVERVIEW: id++, DASHBOARD_CONTRACT_LIST: id++, diff --git a/src/codes/receipt-issuing-order.ts b/src/codes/receipt-issuing-order.ts index 492e8a6..8594bba 100644 --- a/src/codes/receipt-issuing-order.ts +++ b/src/codes/receipt-issuing-order.ts @@ -20,3 +20,21 @@ export const ReceiptIssuingOrderStatus = { export type ReceiptIssuingOrderStatus = (typeof ReceiptIssuingOrderStatus)[keyof typeof ReceiptIssuingOrderStatus]; + +const ReceiptIssuingOrderStatusName = { + [ReceiptIssuingOrderStatus.NONE]: "", + [ReceiptIssuingOrderStatus.CREATED]: "受付済み", + [ReceiptIssuingOrderStatus.SMS_SENDING]: "SMS送信中", + [ReceiptIssuingOrderStatus.SMS_RECEIVED]: "SMS送信完了", + [ReceiptIssuingOrderStatus.SMS_OPENED]: "SMS開封済み", + [ReceiptIssuingOrderStatus.MAIL_REQUEST]: "郵送依頼中", + [ReceiptIssuingOrderStatus.PREPARING_FOR_MAIL]: "郵送準備中", + [ReceiptIssuingOrderStatus.MAIL_DONE]: "郵送投函済み", + [ReceiptIssuingOrderStatus.EMAIL_SENDING]: "メール送信中", + [ReceiptIssuingOrderStatus.EMAIL_DONE]: "メール送信済み", + [ReceiptIssuingOrderStatus.DOWNLOAD_DONE]: "ダウンロード済み", +} as const; + +export function getStatusName(status: ReceiptIssuingOrderStatus): string { + return ReceiptIssuingOrderStatusName[status]; +} diff --git a/src/contexts/AppContext.tsx b/src/contexts/AppContext.tsx new file mode 100644 index 0000000..50bc41d --- /dev/null +++ b/src/contexts/AppContext.tsx @@ -0,0 +1,48 @@ +import { HasChildren } from "@types"; +import { checkToken } from "api/app"; +import useAPICall from "hooks/useAPICall"; +import { createContext, useState } from "react"; + +type App = { + token: string; + tokenResult: "cheking" | "ok" | "ng"; + setToken: (token: string) => void; +}; + +export const AppContext = createContext({ + token: "", + tokenResult: "cheking", + setToken: (token: string) => {}, +}); + +type Props = HasChildren; +export function AppContextProvider({ children }: Props) { + const [token, _setToken] = useState(""); + + const [tokenResult, setTokenResult] = useState<"cheking" | "ok" | "ng">( + "cheking" + ); + + const checkTokenAPI = useAPICall({ + apiMethod: checkToken, + onSuccess: (res, sendData) => { + setTokenResult("ok"); + _setToken(sendData.access_token); + }, + onFailed: () => { + setTokenResult("ng"); + }, + }); + + const setToken = (token: string) => { + checkTokenAPI.callAPI({ + access_token: token, + }); + }; + + return ( + + {children} + + ); +} diff --git a/src/contexts/SearchConditionContext.tsx b/src/contexts/SearchConditionContext.tsx index 10770c4..cf1850a 100644 --- a/src/contexts/SearchConditionContext.tsx +++ b/src/contexts/SearchConditionContext.tsx @@ -14,7 +14,9 @@ const initialState = { condition: _condition, get: (key: string): string => "", initializeCondition: () => {}, - addCondition: (condition: Dictionary) => {}, + addCondition: (condition: Dictionary) => { + console.log("not init SearchConditionContext"); + }, clearCondition: () => {}, }; @@ -45,7 +47,6 @@ export function SearchConditionContextProvider({ children }: Props) { } if (!isEqual(after, condition)) { - console.log("initialCondition", { before: condition, after }); setCondition(after, "initializeCondition"); } setInitialized(true); @@ -72,7 +73,6 @@ export function SearchConditionContextProvider({ children }: Props) { }); if (!isEqual(before, after)) { - console.log("addCondition", { additional, before, after }); setCondition(after, "addCondition"); } }; diff --git a/src/hooks/useApp.ts b/src/hooks/useApp.ts new file mode 100644 index 0000000..cea0b9b --- /dev/null +++ b/src/hooks/useApp.ts @@ -0,0 +1,8 @@ +import { AppContext } from "contexts/AppContext"; +import { useContext } from "react"; + +export default function useApp() { + const context = useContext(AppContext); + + return context; +} diff --git a/src/pages/app/ReceiptIssuingOrder.tsx b/src/pages/app/ReceiptIssuingOrder.tsx new file mode 100644 index 0000000..9d3b809 --- /dev/null +++ b/src/pages/app/ReceiptIssuingOrder.tsx @@ -0,0 +1,48 @@ +import { Box, Button, Paper, Stack, Typography } from "@mui/material"; +import { ApiId } from "api"; +import { getFullUrl } from "api/url"; +import useApp from "hooks/useApp"; +import { useEffect, useMemo } from "react"; +import { useParams } from "react-router-dom"; + +export default function ReceiptIssuingOrder() { + const { token: paramToken } = useParams(); + + const { token, setToken, tokenResult } = useApp(); + + const downloadUrl = useMemo(() => { + return getFullUrl(ApiId.DOWNLOAD_RECEIPT) + "?access_token=" + token; + }, [token]); + + useEffect(() => { + if (paramToken) { + setToken(paramToken); + console.log("render"); + } + }, []); + + if (tokenResult === "cheking") { + return null; + } + + if (tokenResult === "ng") { + return 不正なアクセス; + } + + return ( + + + 領収証発行依頼 + + + 状況 + + + + + + + ); +} diff --git a/src/pages/dashboard/receipt-issuing-order/list.tsx b/src/pages/dashboard/receipt-issuing-order/list.tsx index 1dac25a..dbeb6dc 100644 --- a/src/pages/dashboard/receipt-issuing-order/list.tsx +++ b/src/pages/dashboard/receipt-issuing-order/list.tsx @@ -7,26 +7,24 @@ import { TableContainer, TablePagination, TableRow, - TextField, } from "@mui/material"; import { Dictionary } from "@types"; import { ReceiptIssuingOrder, getReceiptIssuingOrders, -} from "api/receipt-issuing-order"; +} from "api/custom/hello-techno/receipt-issuing-order"; import { PageID, TabID } from "codes/page"; -import { ReceiptIssuingOrderStatus } from "codes/receipt-issuing-order"; +import { getStatusName } from "codes/receipt-issuing-order"; import { FormProvider, RHFTextField } from "components/hook-form"; import { TableHeadCustom } from "components/table"; import { SearchConditionContextProvider } from "contexts/SearchConditionContext"; import useAPICall from "hooks/useAPICall"; +import useBackDrop from "hooks/useBackDrop"; import useDashboard from "hooks/useDashBoard"; import useSearchConditionContext from "hooks/useSearchConditionContext"; import useTable, { UseTableReturn } from "hooks/useTable"; -import ContractTabs from "layouts/dashbord/tab/ContractTabs"; import { useEffect } from "react"; import { useForm } from "react-hook-form"; -import { Contract } from "types/contract"; export default function ReceiptIssuingOrderList() { const { setHeaderTitle, setTabs } = useDashboard( @@ -34,8 +32,6 @@ export default function ReceiptIssuingOrderList() { TabID.NONE ); - const table = useTable(); - useEffect(() => { setHeaderTitle("領収証発行依頼一覧"); setTabs(null); @@ -43,33 +39,14 @@ export default function ReceiptIssuingOrderList() { return ( - + ); } -type CommonProps = { - table: UseTableReturn; -}; -function Page({ table }: CommonProps) { - const { - order, - page, - sort, - rowsPerPage, - fetched, - fillteredRow, - isNotFound, - dataLength, - // - onSort, - onChangePage, - onChangeRowsPerPage, - // - setRowData, - // - ROWS_PER_PAGES, - } = table; +function Page() { + const table = useTable(); + return ( @@ -79,7 +56,11 @@ function Page({ table }: CommonProps) { } type FormProps = { - address: string; + customer_name: string; + parking_name: string; +}; +type CommonProps = { + table: UseTableReturn; }; function SearchBox({ table }: CommonProps) { const { @@ -89,13 +70,20 @@ function SearchBox({ table }: CommonProps) { addCondition: add, } = useSearchConditionContext(); + const { setShowBackDrop } = useBackDrop(); + const form = useForm({ defaultValues: { - address: "", + customer_name: "", + parking_name: "", }, }); - const { callAPI: calGetReceiptIssuingOrders, makeSendData } = useAPICall({ + const { + callAPI: calGetReceiptIssuingOrders, + makeSendData, + sending, + } = useAPICall({ apiMethod: getReceiptIssuingOrders, form, onSuccess: (res) => { @@ -111,6 +99,10 @@ function SearchBox({ table }: CommonProps) { add({ ...data }); }; + const handleBlur = () => { + addCondition(form.getValues()); + }; + const fetch = async (data: Dictionary) => { const sendData = makeSendData({ ...data, @@ -121,7 +113,8 @@ function SearchBox({ table }: CommonProps) { // 初期値設定 useEffect(() => { if (initialized) { - form.setValue("address", get("address")); + form.setValue("customer_name", get("customer_name")); + form.setValue("parking_name", get("parking_name")); } }, [initialized, condition]); @@ -132,38 +125,32 @@ function SearchBox({ table }: CommonProps) { } }, [condition, initialized]); + // バックドロップ + useEffect(() => { + setShowBackDrop(sending); + }, [sending]); + return ( - - - - - - - - - - - - - - - - - - - + @@ -173,9 +160,11 @@ function SearchBox({ table }: CommonProps) { function TableBox({ table }: CommonProps) { const TABLE_HEAD = [ - { id: "id", label: "ID", align: "left" }, - { id: "name", label: "名前", align: "left" }, - { id: "emply", label: "---", align: "left" }, + { id: "order_datetime", label: "受付時刻", align: "left" }, + { id: "customer_name", label: "運営会社名", align: "left" }, + { id: "parking_name", label: "駐車場名", align: "left" }, + { id: "status", label: "ステータス", align: "left" }, + { id: "handler_name", label: "担当者", align: "left" }, ]; const { order, @@ -196,13 +185,6 @@ function TableBox({ table }: CommonProps) { ROWS_PER_PAGES, } = table; - useEffect(() => { - setRowData([ - { id: "iwabuchi", status: ReceiptIssuingOrderStatus.NONE }, - { id: "iwabuchi", status: ReceiptIssuingOrderStatus.MAIL_DONE }, - ]); - }, []); - return ( <> - {data.id} - {data.status} + {data.order_datetime} + {data.customer_name} + {data.parking_name} + {getStatusName(data.status)} + {data.handler_name} ); } diff --git a/src/routes/index.tsx b/src/routes/index.tsx index 2a993c3..b0f9e8e 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -1,12 +1,13 @@ import { PageID } from "codes/page"; +import { UserRole } from "codes/user"; import LoadingScreen from "components/LoadingScreen"; +import { AppContextProvider } from "contexts/AppContext"; +import useAuth from "hooks/useAuth"; import DashboardLayout from "layouts/dashbord"; import SimpleLayout from "layouts/simple"; import { ElementType, Suspense, lazy, useMemo } from "react"; import { RouteObject, useRoutes } from "react-router-dom"; import { getRoute } from "./path"; -import useAuth from "hooks/useAuth"; -import { UserRole } from "codes/user"; const Loadable = (Component: ElementType) => (props: any) => { return ( @@ -30,6 +31,20 @@ const AuthRoutes = (): RouteObject => ({ ], }); +const AppRoutes = (): RouteObject => ({ + element: ( + + + + ), + children: [ + { + path: getRoute(PageID.APP_RECEIPT_ISSUING_ORDER_INDEX), + element: , + }, + ], +}); + const DashboardRoutes = (): RouteObject => { const { canAccess } = useAuth(); @@ -80,6 +95,7 @@ export function Routes() { const { initialized } = useAuth(); return useRoutes([ AuthRoutes(), + AppRoutes(), DashboardRoutes(), { path: "403", @@ -96,6 +112,11 @@ export function Routes() { const Login = Loadable(lazy(() => import("pages/auth/login"))); const Logout = Loadable(lazy(() => import("pages/auth/logout"))); +// App --------------------------- +const ReceiptIssuingOrder = Loadable( + lazy(() => import("pages/app/ReceiptIssuingOrder")) +); + //ダッシュボード ---------------------------- const Dashboard = Loadable(lazy(() => import("pages/dashboard"))); // 契約関連 diff --git a/src/routes/path.ts b/src/routes/path.ts index d604a83..594f93c 100644 --- a/src/routes/path.ts +++ b/src/routes/path.ts @@ -37,6 +37,10 @@ const PATHS = { [makePathKey(PageID.DASHBOARD_OVERVIEW)]: "/dashboard", + // APP + [makePathKey(PageID.APP_RECEIPT_ISSUING_ORDER_INDEX)]: + "/app/receipt-issuing-oreder/:token", + // 契約関連 [makePathKey(PageID.DASHBOARD_CONTRACT_LIST)]: "/dashboard/contract/list/:page", diff --git a/src/theme/index.tsx b/src/theme/index.tsx index 5ceacf7..501ef1e 100644 --- a/src/theme/index.tsx +++ b/src/theme/index.tsx @@ -153,7 +153,7 @@ theme = { styleOverrides: { root: { "&.Mui-disabled:before": { - "border-bottom-style": "none", + borderBottomStyle: "none", }, }, },