Browse Source

契約者単位の集計一覧機能 新規追加

develop
sosuke.iwabuchi 2 years ago
parent
commit
a2981a5f82
9 changed files with 331 additions and 2 deletions
  1. +1
    -0
      src/api/index.ts
  2. +2
    -2
      src/api/url.ts
  3. +38
    -0
      src/api/use-summary.ts
  4. +2
    -0
      src/codes/page.ts
  5. +4
    -0
      src/layouts/dashbord/navigator.tsx
  6. +269
    -0
      src/pages/dashboard/use-summary/list.tsx
  7. +4
    -0
      src/routes/auth.ts
  8. +7
    -0
      src/routes/index.tsx
  9. +4
    -0
      src/routes/path.ts

+ 1
- 0
src/api/index.ts View File

@@ -36,6 +36,7 @@ export const ApiId = {
CONTRACT_CREATE: id++,

USE_SUMMARY_YYYYMM: id++,
USE_SUMMARIES_BY_CONTRACT: id++,

LOGIN_USERS: id++,
LOGIN_USER_CREATE: id++,


+ 2
- 2
src/api/url.ts View File

@@ -1,6 +1,5 @@
import { env } from "process";
import { ApiId as A } from ".";
import { HOST_API } from "config";
import { ApiId as A } from ".";

const urls = {
[A.CSRF_TOKEN]: "sanctum/csrf-cookie",
@@ -27,6 +26,7 @@ const urls = {
[A.CONTRACT_CREATE]: "contract/create",

[A.USE_SUMMARY_YYYYMM]: "use-summary/yyyymm",
[A.USE_SUMMARIES_BY_CONTRACT]: "use-summary/list/by-contract",

[A.LOGIN_USERS]: "users",
[A.LOGIN_USER_CREATE]: "user/create",


+ 38
- 0
src/api/use-summary.ts View File

@@ -0,0 +1,38 @@
import { APICommonResponse, ApiId, HttpMethod, ListRequest, request } from ".";
import { getUrl } from "./url";

export type UseSummaryByContract = {
date_from: string;
date_to: string;

contract_id: string;
contract_name: string;

receipt_order_count: string;
mail_order_count: string;
sms_send_count: string;
};

// 利用実績一覧取得 -----------------------
export type UseSummariesByContradctRequest = {
date_from: string;
date_to: string;
contract_name?: string;
} & ListRequest;

export type UseSummariesByContractResponse = {
data: {
records: UseSummaryByContract[];
};
} & APICommonResponse;

export const getUseSummariesByContract = async (
data: UseSummariesByContradctRequest
) => {
const res = await request<UseSummariesByContractResponse>({
url: getUrl(ApiId.USE_SUMMARIES_BY_CONTRACT),
method: HttpMethod.GET,
data: new URLSearchParams(data),
});
return res;
};

+ 2
- 0
src/codes/page.ts View File

@@ -16,6 +16,8 @@ export const PageID = {
DASHBOARD_CONTRACT_DETAIL: id++,
DASHBOARD_CONTRACT_CREATE: id++,

DASHBOARD_USE_SUMMARY_LIST_BY_CONTRACT: id++,

DASHBOARD_RECEIPT_ISSUING_ORDER_CREATE_CUSTOM_HELLO_TECHNO: id++,
DASHBOARD_RECEIPT_ISSUING_ORDER_LIST_CUSTOM_HELLO_TECHNO: id++,
DASHBOARD_RECEIPT_ISSUING_ORDER_DETAIL_CUSTOM_HELLO_TECHNO: id++,


+ 4
- 0
src/layouts/dashbord/navigator.tsx View File

@@ -109,6 +109,10 @@ export default function Navigator(props: DrawerProps) {
id: PageID.DASHBOARD_USE_SUMMARY_LIST_CUSTOM_HELLO_TECHNO,
label: "一覧",
},
{
id: PageID.DASHBOARD_USE_SUMMARY_LIST_BY_CONTRACT,
label: "一覧",
},
],
},
{


+ 269
- 0
src/pages/dashboard/use-summary/list.tsx View File

@@ -0,0 +1,269 @@
import {
Box,
Button,
Grid,
Stack,
Table,
TableBody,
TableCell,
TableContainer,
TablePagination,
TableRow,
Typography,
} from "@mui/material";
import { ApiId } from "api";
import {
UseSummary,
getUseSummaries,
getUseSummaryYYYYMMs,
} from "api/custom/hello-techno/use-summary";
import { getFullUrl } from "api/url";
import {
UseSummaryByContract,
getUseSummariesByContract,
} from "api/use-summary";
import { PageID, TabID } from "codes/page";
import { FormProvider, RHFTextField } from "components/hook-form";
import RHFDatePicker from "components/hook-form/RHFDatePicker";
import RHFSelect, { SelectOptionProps } from "components/hook-form/RHFSelect";
import { TableHeadCustom } from "components/table";
import { HeadLabelProps } from "components/table/TableHeadCustom";
import { SearchConditionContextProvider } from "contexts/SearchConditionContext";
import useAPICall from "hooks/useAPICall";
import useDashboard from "hooks/useDashBoard";
import useNavigateCustom from "hooks/useNavigateCustom";
import useSearchConditionContext from "hooks/useSearchConditionContext";
import useTable, { UseTableReturn } from "hooks/useTable";
import { SearchParam } from "pages/dashboard/receipt-issuing-order/custom/hello-techno/list";
import { useEffect, useMemo, useState } from "react";
import { useForm } from "react-hook-form";
import { getPath } from "routes/path";
import { sprintf } from "sprintf-js";
import { dateParse, formatDateStr } from "utils/datetime";

export default function UseSummaryList() {
const { setHeaderTitle, setTabs } = useDashboard(
PageID.DASHBOARD_USE_SUMMARY_LIST_BY_CONTRACT,
TabID.NONE
);

const { navigateWhenChanged } = useNavigateCustom();

useEffect(() => {
setHeaderTitle("利用実績一覧");
setTabs(null);
}, []);

return (
<SearchConditionContextProvider>
<Page />
</SearchConditionContextProvider>
);
}

function Page() {
const table = useTable<UseSummaryByContract>();
return (
<Box>
<SearchBox table={table} />
<TableBox table={table} />
</Box>
);
}

type FormProps = {
date_from: Date | null;
date_to: Date | null;
contract_name: string;
};

type CommonProps = {
table: UseTableReturn<UseSummaryByContract>;
};
function SearchBox({ table }: CommonProps) {
const {
condition,
initialized,
get,
addCondition: add,
} = useSearchConditionContext();

const form = useForm<FormProps>({
defaultValues: {
date_from: null,
date_to: null,
contract_name: "",
},
});

const dateFrom = form.watch("date_from");
const dateTo = form.watch("date_to");

const { callAPI: callGetContracts } = useAPICall({
apiMethod: getUseSummariesByContract,
backDrop: true,
onSuccess: ({ data }) => {
table.setRowData(data.records);
},
});

const handleSubmit = async (data: FormProps) => {
addCondition(data);
};

const handleBlur = () => {
addCondition(form.getValues());
};

const addCondition = (data: FormProps) => {
add({
...data,
date_from: formatDateStr(data.date_from),
date_to: formatDateStr(data.date_to),
});
};

const fetch = async () => {
const dateFrom = form.getValues("date_from");
const dateTo = form.getValues("date_to");
if (!dateFrom || !dateTo) return;
const sendData = {
...form.getValues(),
date_from: formatDateStr(dateFrom),
date_to: formatDateStr(dateTo),
};
callGetContracts(sendData);
};

// 初期値設定
useEffect(() => {
if (initialized) {
form.setValue("date_from", dateParse(get("date_from")));
form.setValue("date_to", dateParse(get("date_to")));
form.setValue("contract_name", get("contract_name"));
}
}, [initialized]);

// Fetchアクション
useEffect(() => {
if (initialized) {
fetch();
}
}, [condition, initialized]);

useEffect(() => {
addCondition(form.getValues());
}, [dateFrom, dateTo]);

return (
<FormProvider methods={form} onSubmit={form.handleSubmit(handleSubmit)}>
<Box sx={{ p: 1, m: 1 }}>
<Grid container spacing={2}>
<Grid item xs={3} lg={2}>
<Typography>開始年月日</Typography>
<RHFDatePicker name="date_from" size="small" />
</Grid>
<Grid item xs={3} lg={2}>
<Typography>終了年月日</Typography>
<RHFDatePicker name="date_to" size="small" />
</Grid>
<Grid item xs={3} lg={2}>
<Typography>契約者名</Typography>
<RHFTextField
name="contract_name"
size="small"
onBlur={handleBlur}
/>
</Grid>
</Grid>
</Box>
</FormProvider>
);
}

function TableBox({ table }: CommonProps) {
const TABLE_HEAD: HeadLabelProps[] = [
{ id: "customer_name", label: "契約者名", align: "left" },
{ id: "receipt_order_count", label: "領収証発行件数", align: "left" },
{ id: "mail_order_count", label: "郵送依頼件数", align: "left" },
{ id: "sms_send_count", label: "SMS送信件数", align: "left" },
{ id: "actions", label: "アクション", align: "left", needSort: false },
];
const {
order,
page,
sort,
rowsPerPage,
fetched,
fillteredRow,
isNotFound,
dataLength,
//
onSort,
onChangePage,
onChangeRowsPerPage,
//
setRowData,
//
ROWS_PER_PAGES,
} = table;

return (
<>
<TableContainer
sx={{
// minWidth: 800,
position: "relative",
}}
>
<Table size="small">
<TableHeadCustom
order={order}
orderBy={sort}
headLabel={TABLE_HEAD}
rowCount={1}
numSelected={0}
onSort={onSort}
/>

<TableBody>
{fillteredRow.map((row, index) => (
<Row data={row} key={index} />
))}
</TableBody>
</Table>
</TableContainer>

<Box sx={{ position: "relative" }}>
<TablePagination
rowsPerPageOptions={ROWS_PER_PAGES}
component="div"
count={dataLength}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={onChangePage}
onRowsPerPageChange={onChangeRowsPerPage}
/>
</Box>
</>
);
}

type RowProps = {
data: UseSummaryByContract;
};
function Row({ data }: RowProps) {
return (
<TableRow>
<TableCell>{data.contract_name}</TableCell>
<TableCell>{data.receipt_order_count}件</TableCell>
<TableCell>{data.mail_order_count}件</TableCell>
<TableCell>{data.sms_send_count}件</TableCell>
<TableCell>
<Stack direction="row" spacing={2}>
<Box>-</Box>
</Stack>
</TableCell>
</TableRow>
);
}

+ 4
- 0
src/routes/auth.ts View File

@@ -28,6 +28,10 @@ export const AUTH = {
allowChangedContract: false,
}),

[P.DASHBOARD_USE_SUMMARY_LIST_BY_CONTRACT]: setAuth("eq", R.SUPER_ADMIN, {
allowChangedContract: false,
}),

[P.DASHBOARD_RECEIPT_ISSUING_ORDER_CREATE_CUSTOM_HELLO_TECHNO]: setAuth(
"ge",
R.NORMAL_ADMIN,


+ 7
- 0
src/routes/index.tsx View File

@@ -77,6 +77,10 @@ const DashboardRoutes = (): RouteObject => {
pageId: PageID.DASHBOARD_CONTRACT_CREATE,
element: <ContractCreate />,
},
{
pageId: PageID.DASHBOARD_USE_SUMMARY_LIST_BY_CONTRACT,
element: <UseSummaryByContractList />,
},
{
pageId: PageID.DASHBOARD_RECEIPT_ISSUING_ORDER_CREATE_CUSTOM_HELLO_TECHNO,
element: <ReceiptIssuingOrderCreateHelloTechno />,
@@ -188,6 +192,9 @@ const ReceiptIssuingOrderDetailHelloTechno = Loadable(
);

// 利用実績関連
const UseSummaryByContractList = Loadable(
lazy(() => import("pages/dashboard/use-summary/list"))
);
const UseSummaryListHelloTechno = Loadable(
lazy(() => import("pages/dashboard/use-summary/custom/hello-techno/list"))
);


+ 4
- 0
src/routes/path.ts View File

@@ -53,6 +53,10 @@ const PATHS = {
"/dashboard/contract/detail/:id",
[makePathKey(PageID.DASHBOARD_CONTRACT_CREATE)]: "/dashboard/contract/create",

// 利用実績関連
[makePathKey(PageID.DASHBOARD_USE_SUMMARY_LIST_BY_CONTRACT)]:
"/dashboard/use-summary/list",

// 領収証発行依頼関連
[makePathKey(
PageID.DASHBOARD_RECEIPT_ISSUING_ORDER_CREATE_CUSTOM_HELLO_TECHNO


Loading…
Cancel
Save