Browse Source

QRサービス券駐車場グループ管理修正整備

develop
sosuke.iwabuchi 1 year ago
parent
commit
2d171e37b2
27 changed files with 903 additions and 162 deletions
  1. +7
    -0
      src/api/index.ts
  2. +25
    -0
      src/api/parking.ts
  3. +83
    -1
      src/api/qr-service.ts
  4. +9
    -0
      src/api/url.ts
  5. +1
    -0
      src/auth/route.ts
  6. +141
    -0
      src/contexts/page/dashboard/parking/QRサービス券駐車場グループ管理Context.tsx
  7. +1
    -1
      src/contexts/page/dashboard/shop/店舗詳細Context.tsx
  8. +16
    -3
      src/hooks/useDialog.tsx
  9. +28
    -8
      src/layouts/dashbord/navigator.tsx
  10. +58
    -0
      src/layouts/dashbord/tab/QRサービス券駐車場グループ管理Tabs.tsx
  11. +3
    -5
      src/layouts/dashbord/tab/tabutil.tsx
  12. +4
    -4
      src/layouts/dashbord/tab/店舗管理Tabs.tsx
  13. +1
    -1
      src/pages/dashboard/login-user/顧客ログインユーザ一覧/TableBox.tsx
  14. +110
    -0
      src/pages/dashboard/qr-service/QRサービス券駐車場管理/一覧/TableBox.tsx
  15. +30
    -0
      src/pages/dashboard/qr-service/QRサービス券駐車場管理/一覧/index.tsx
  16. +76
    -0
      src/pages/dashboard/qr-service/QRサービス券駐車場管理/新規登録/index.tsx
  17. +29
    -0
      src/pages/dashboard/qr-service/QRサービス券駐車場管理/詳細/index.tsx
  18. +99
    -0
      src/pages/dashboard/qr-service/QRサービス券駐車場管理/詳細/駐車場一覧.tsx
  19. +106
    -0
      src/pages/dashboard/qr-service/QRサービス券駐車場管理/詳細/駐車場追加.tsx
  20. +0
    -0
      src/pages/dashboard/qr-service/サービス券利用履歴.tsx
  21. +0
    -0
      src/pages/dashboard/qr-service/サービス券発行用QRコード.tsx
  22. +1
    -3
      src/pages/dashboard/shop/店舗一覧/TableBox.tsx
  23. +1
    -7
      src/pages/dashboard/shop/店舗詳細/設定/index.tsx
  24. +7
    -0
      src/pages/index.ts
  25. +15
    -3
      src/routes/path.ts
  26. +0
    -124
      src/routes/sub/________dashboard.tsx
  27. +52
    -2
      src/routes/sub/dashboard.tsx

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

@@ -27,6 +27,9 @@ export const ApiId = {
// 顧客関連 ----------------------------------
顧客マスタ一覧取得: id++,

// 駐車場関連 ----------------------------------
駐車場マスタ一覧取得: id++,

// 店舗関連関連 ----------------------------------
店舗一覧取得: id++,
店舗新規登録: id++,
@@ -35,6 +38,10 @@ export const ApiId = {
店舗設定: id++,

// QRサービス券関連-------------------------------
QRサービス券駐車場グループ一覧取得: id++,
QRサービス券駐車場グループ新規登録: id++,
QRサービス券駐車場グループ駐車場追加登録: id++,
QRサービス券駐車場グループ駐車場削除登録: id++,
QRサービス券取得: id++,
} as const;
export type ApiId = (typeof ApiId)[keyof typeof ApiId];


+ 25
- 0
src/api/parking.ts View File

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

export type 駐車場マスタ = {
parking_management_code: string;
parking_name: string;
};

// -------駐車場マスタ一覧取得---------------
export type 駐車場マスタ一覧取得Request = {};
export type 駐車場マスタ一覧取得Response = {
data: {
list: 駐車場マスタ[];
};
} & APICommonResponse;
export const 駐車場マスタ一覧取得 = async (
param: 駐車場マスタ一覧取得Request
) => {
const res = await request<駐車場マスタ一覧取得Response>({
url: getUrl(ApiId.駐車場マスタ一覧取得),
method: HttpMethod.GET,
data: new URLSearchParams(param),
});
return res;
};

+ 83
- 1
src/api/qr-service.ts View File

@@ -1,5 +1,13 @@
import { APICommonResponse, ApiId, HttpMethod, request } from "api";
import { APICommonResponse, ApiId, HttpMethod, makeParam, request } from "api";
import { getUrl } from "./url";
import { string } from "yup";
import { 駐車場マスタ } from "./parking";

export type QRサービス券駐車場グループ = {
id: string;
name: string;
parkings: 駐車場マスタ[];
};

// -------QRサービス券取得---------------
export type QRサービス券取得Request = {
@@ -20,3 +28,77 @@ export const QRサービス券取得 = async (param: QRサービス券取得Requ
});
return res;
};

// -------QRサービス券駐車場グループ一覧取得---------------
export type QRサービス券駐車場グループ一覧取得Request = {};
export type QRサービス券駐車場グループ一覧取得Response = {
data: {
list: QRサービス券駐車場グループ[];
};
} & APICommonResponse;
export const QRサービス券駐車場グループ一覧取得 = async (
param: QRサービス券駐車場グループ一覧取得Request
) => {
const res = await request<QRサービス券駐車場グループ一覧取得Response>({
url: getUrl(ApiId.QRサービス券駐車場グループ一覧取得),
method: HttpMethod.GET,
data: new URLSearchParams(param),
});
return res;
};

// -------QRサービス券駐車場グループ新規登録---------------
export type QRサービス券駐車場グループ新規登録Request = {
name: string;
};
export type QRサービス券駐車場グループ新規登録Response = {
data: {
id: string;
};
} & APICommonResponse;
export const QRサービス券駐車場グループ新規登録 = async (
param: QRサービス券駐車場グループ新規登録Request
) => {
const res = await request<QRサービス券駐車場グループ新規登録Response>({
url: getUrl(ApiId.QRサービス券駐車場グループ新規登録),
method: HttpMethod.POST,
data: makeParam(param),
});
return res;
};

// -------QRサービス券駐車場グループ駐車場追加登録---------------
export type QRサービス券駐車場グループ駐車場追加登録Request = {
id: string;
parking_management_code: string;
};
export type QRサービス券駐車場グループ駐車場追加登録Response =
{} & APICommonResponse;
export const QRサービス券駐車場グループ駐車場追加登録 = async (
param: QRサービス券駐車場グループ駐車場追加登録Request
) => {
const res = await request<QRサービス券駐車場グループ駐車場追加登録Response>({
url: getUrl(ApiId.QRサービス券駐車場グループ駐車場追加登録),
method: HttpMethod.POST,
data: makeParam(param),
});
return res;
};

// -------QRサービス券駐車場グループ駐車場削除登録---------------
export type QRサービス券駐車場グループ駐車場削除登録Request = {
id: string;
parking_management_code: string;
};
export type QRサービス券駐車場グループ駐車場削除登録Response =
{} & APICommonResponse;
export const QRサービス券駐車場グループ駐車場削除登録 = async (
param: QRサービス券駐車場グループ駐車場削除登録Request
) => {
const res = await request<QRサービス券駐車場グループ駐車場削除登録Response>({
url: getUrl(ApiId.QRサービス券駐車場グループ駐車場削除登録),
method: HttpMethod.POST,
data: makeParam(param),
});
return res;
};

+ 9
- 0
src/api/url.ts View File

@@ -22,6 +22,9 @@ const urls = {
// 顧客関連 ----------------------------------
[A.顧客マスタ一覧取得]: "customer/list",

// 駐車場関連 ----------------------------------
[A.駐車場マスタ一覧取得]: "parking/list",

// 店舗関連関連 ----------------------------------
[A.店舗一覧取得]: "shop/list",
[A.店舗新規登録]: "shop/register",
@@ -30,6 +33,12 @@ const urls = {
[A.店舗設定]: "shop/config",

// QRサービス券関連-------------------------------
[A.QRサービス券駐車場グループ一覧取得]: "qr-service/parking-group/list",
[A.QRサービス券駐車場グループ新規登録]: "qr-service/parking-group/register",
[A.QRサービス券駐車場グループ駐車場追加登録]:
"qr-service/parking-group/parking/add",
[A.QRサービス券駐車場グループ駐車場削除登録]:
"qr-service/parking-group/parking/remove",
[A.QRサービス券取得]: "qr-service/get-ticket",
};



+ 1
- 0
src/auth/route.ts View File

@@ -26,6 +26,7 @@ const 認可別許可ルート: {
P.店舗一覧,
P.店舗新規登録,
P.店舗詳細,
P.QRサービス券駐車場グループ管理,
],

[UserRole.SHOP]: [


+ 141
- 0
src/contexts/page/dashboard/parking/QRサービス券駐車場グループ管理Context.tsx View File

@@ -0,0 +1,141 @@
import { HasChildren } from "@types";
import { 駐車場マスタ, 駐車場マスタ一覧取得 } from "api/parking";
import {
QRサービス券駐車場グループ,
QRサービス券駐車場グループ一覧取得,
} from "api/qr-service";
import useAPICall from "hooks/useAPICall";
import useDashboard from "hooks/useDashBoard";
import useNavigateCustom from "hooks/useNavigateCustom";
import useSnackbarCustom from "hooks/useSnackbarCustom";
import useQRサービス券駐車場グループ管理Tabs from "layouts/dashbord/tab/QRサービス券駐車場グループ管理Tabs";
import { PageID, TabID } from "pages";
import { createContext, useEffect, useMemo, useState } from "react";
import { useParams } from "react-router-dom";
import { getPath } from "routes/path";

type Context = {
parkings: 駐車場マスタ[];
groups: QRサービス券駐車場グループ[];
selectedGroup: QRサービス券駐車場グループ | null;
fetch: () => Promise<void>;
moveToList: VoidFunction;
moveToDetail: (id: string) => void;
};

export const QRサービス券駐車場グループ管理Context = createContext<Context>({
parkings: [],
groups: [],
selectedGroup: null,
fetch: async () => {},
moveToList: () => {},
moveToDetail: (id: string) => {},
});

type Props = HasChildren;
function QRサービス券駐車場グループ管理ContextProvider({ children }: Props) {
const { id: paramId } = useParams();

const [parkings, setParkings] = useState<駐車場マスタ[]>([]);
const [groups, setGroups] = useState<QRサービス券駐車場グループ[]>([]);
const { success, error } = useSnackbarCustom();
const { navigateWhenChanged } = useNavigateCustom();

const selectedGroup = useMemo(() => {
return groups.find((g) => g.id === paramId) ?? null;
}, [groups, paramId]);

const { callAPI: callQRサービス券駐車場グループ一覧取得 } = useAPICall({
apiMethod: QRサービス券駐車場グループ一覧取得,
backDrop: true,
onSuccess: ({ data }) => {
setGroups(data.list);
},
onFailed: () => {
error("データ取得失敗");
},
});
const { callAPI: call駐車場マスタ一覧取得 } = useAPICall({
apiMethod: 駐車場マスタ一覧取得,
backDrop: true,
onSuccess: ({ data }) => {
setParkings(data.list);
},
onFailed: () => {
error("データ取得失敗");
},
});

const fetch = async () => {
await callQRサービス券駐車場グループ一覧取得({});
};

const moveToList = () => {
navigateWhenChanged(
getPath(
[
PageID.QRサービス券駐車場グループ管理,
TabID.QRサービス券駐車場グループ管理_一覧,
],
{}
)
);
};
const moveToDetail = (id: string) => {
navigateWhenChanged(
getPath(
[
PageID.QRサービス券駐車場グループ管理,
TabID.QRサービス券駐車場グループ管理_詳細,
],
{
query: {
id,
},
}
)
);
};

const { setHeaderTitle } = useDashboard(
PageID.QRサービス券駐車場グループ管理
);

useEffect(() => {
setHeaderTitle("QRサービス券駐車場グループ管理");
}, []);

useEffect(() => {
fetch();
call駐車場マスタ一覧取得({});
}, []);

return (
<QRサービス券駐車場グループ管理Context.Provider
value={{
parkings,
groups,
selectedGroup,
fetch,
moveToList,
moveToDetail,
}}
>
<TabInit />
{children}
</QRサービス券駐車場グループ管理Context.Provider>
);
}

function TabInit() {
const { setTabs, tabId } = useDashboard();
const { element } = useQRサービス券駐車場グループ管理Tabs();

useEffect(() => {
setTabs(element);
}, [tabId]);

return null;
}

export default QRサービス券駐車場グループ管理ContextProvider;

+ 1
- 1
src/contexts/page/dashboard/shop/店舗詳細Context.tsx View File

@@ -4,7 +4,7 @@ import useAPICall from "hooks/useAPICall";
import useDashboard from "hooks/useDashBoard";
import useNavigateCustom from "hooks/useNavigateCustom";
import useSnackbarCustom from "hooks/useSnackbarCustom";
import useShopTabs from "layouts/dashbord/tab/ShopTabs";
import useShopTabs from "layouts/dashbord/tab/店舗管理Tabs";
import { PageID, TabID } from "pages";
import { createContext, useContext, useEffect, useState } from "react";
import { useParams } from "react-router-dom";


+ 16
- 3
src/hooks/useDialog.tsx View File

@@ -6,7 +6,7 @@ import {
DialogContentText,
DialogTitle,
} from "@mui/material";
import { ReactNode, useState } from "react";
import { ReactNode, useEffect, useState } from "react";

type Props = {
message?: string;
@@ -17,9 +17,10 @@ type Props = {

export type UseDialogReturn = {
show: boolean;
isAgree: boolean;
isDisAgree: boolean;
open: VoidFunction;
close: VoidFunction;
setShow: (show: boolean) => void;
element: ReactNode;
};

@@ -30,6 +31,8 @@ export function useDialog({
onDisagree,
}: Props = {}): UseDialogReturn {
const [show, setShow] = useState(false);
const [isAgree, setIsAgree] = useState(false);
const [isDisAgree, setIsDisAgree] = useState(false);

const open = () => {
setShow(true);
@@ -47,6 +50,7 @@ export function useDialog({
onAgree();
}
setShow(false);
setIsAgree(true);
};

const disagree = () => {
@@ -54,8 +58,16 @@ export function useDialog({
onDisagree();
}
setShow(false);
setIsDisAgree(true);
};

useEffect(() => {
if (show === false) {
setIsAgree(false);
setIsDisAgree(false);
}
}, [show]);

const element = (
<Dialog open={show} onClose={close}>
<DialogTitle>確認</DialogTitle>
@@ -74,6 +86,8 @@ export function useDialog({
return {
// param
show,
isAgree,
isDisAgree,

// Element
element,
@@ -81,6 +95,5 @@ export function useDialog({

open,
close,
setShow,
};
}

+ 28
- 8
src/layouts/dashbord/navigator.tsx View File

@@ -1,7 +1,6 @@
import { ExpandLess, ExpandMore } from "@mui/icons-material";
import AccountCircleIcon from "@mui/icons-material/AccountCircle";
import ArticleIcon from "@mui/icons-material/Article";
import PersonIcon from "@mui/icons-material/Person";
import SettingsIcon from "@mui/icons-material/Settings";
import { Collapse, Typography } from "@mui/material";
import Box from "@mui/material/Box";
@@ -12,14 +11,13 @@ import ListItem from "@mui/material/ListItem";
import ListItemButton from "@mui/material/ListItemButton";
import ListItemIcon from "@mui/material/ListItemIcon";
import ListItemText from "@mui/material/ListItemText";
import { UserRole } from "auth/UserRole";
import { ページアクセス許可判定 } from "auth/route";
import useAuth from "hooks/useAuth";
import useNavigateCustom from "hooks/useNavigateCustom";
import usePage from "hooks/usePage";
import { PageID, TabID } from "pages";
import * as React from "react";
import { PathKey, PathOption, getPath } from "routes/path";
import { PathKey, PathOption, getPageId, getPath } from "routes/path";
type Group = {
label: string;
children: SubGroup[];
@@ -32,12 +30,12 @@ type SubGroup = {
whenIsSwitched?: boolean;

// 子要素を持たない場合は設定
id?: PageID;
id?: PathKey;
option?: PathOption;
};

type Child = {
label: string;
label: string | React.ReactNode;
id: PathKey;
option?: PathOption;
};
@@ -109,6 +107,25 @@ export default function Navigator(props: DrawerProps) {
},
],
},
{
label: "駐車場管理",
children: [
{
// label: "QRサービス券駐車場グループ管理",
label: (
<Box>
<Typography variant="body2">QRサービス券</Typography>
<Typography variant="body2">駐車場グループ管理</Typography>
</Box>
),
icon: <ArticleIcon />,
id: [
PageID.QRサービス券駐車場グループ管理,
TabID.QRサービス券駐車場グループ管理_一覧,
],
},
],
},
{
label: "QRサービス券",
children: [
@@ -166,7 +183,10 @@ function Group(group: Group) {
const { label, children } = group;

const elements = children
.filter(({ id }) => ページアクセス許可判定(currentRole, id ?? -1))
.filter(
({ id }) =>
!id || ページアクセス許可判定(currentRole, getPageId(id) ?? -1)
)
.filter(({ whenIsSwitched }) => whenIsSwitched !== true || isSwitched)
.map((ele, index) => <SubGroup {...ele} key={index} />);

@@ -223,7 +243,7 @@ function SubGroup({ icon, label, id, children, option }: SubGroup) {
navigateWhenChanged(path, undefined, { reload: true });
}
};
const selected = id === pageId;
const selected = getPageId(id) === pageId;
return (
<ListItemButton onClick={handleClick} selected={selected} sx={item}>
<ListItemIcon>{icon}</ListItemIcon>
@@ -244,7 +264,7 @@ function useContents(children: Child[]) {
const elements = React.useMemo(() => {
setShouldOpen(false);
return children.map(({ label, id, option }, index) => {
const selected = id === pageId;
const selected = getPageId(id) === pageId;
if (selected) {
setShouldOpen(true);
}


+ 58
- 0
src/layouts/dashbord/tab/QRサービス券駐車場グループ管理Tabs.tsx View File

@@ -0,0 +1,58 @@
import { Tabs } from "@mui/material";
import { QRサービス券駐車場グループ管理Context } from "contexts/page/dashboard/parking/QRサービス券駐車場グループ管理Context";
import usePage from "hooks/usePage";
import { PageID, TabID } from "pages";
import { useContext, useMemo } from "react";
import { getPath } from "routes/path";
import { TabProps, useTab } from "./tabutil";

export default function useQRサービス券駐車場グループ管理Tabs() {
const {} = useContext(QRサービス券駐車場グループ管理Context);
const { tabId } = usePage();

const tabs: TabProps[] = useMemo(() => {
const list: TabProps[] = [
{
label: "一覧",
tabId: TabID.QRサービス券駐車場グループ管理_一覧,
path: getPath([
PageID.QRサービス券駐車場グループ管理,
TabID.QRサービス券駐車場グループ管理_一覧,
]),
},
{
label: "新規登録",
tabId: TabID.QRサービス券駐車場グループ管理_新規登録,
path: getPath([
PageID.QRサービス券駐車場グループ管理,
TabID.QRサービス券駐車場グループ管理_新規登録,
]),
},
];

if (tabId === TabID.QRサービス券駐車場グループ管理_詳細) {
list.push({
label: "詳細",
tabId: TabID.QRサービス券駐車場グループ管理_詳細,
});
}

return list;
}, [tabId]);

const { elements, getTabIndex } = useTab(tabs);

return {
element: (
<Tabs
value={getTabIndex}
textColor="inherit"
// scrollButtons
// allowScrollButtonsMobile
variant="scrollable"
>
{elements}
</Tabs>
),
};
}

+ 3
- 5
src/layouts/dashbord/tab/tabutil.tsx View File

@@ -1,14 +1,12 @@
import { PageID, TabID } from "pages";
import usePage from "hooks/usePage";
import { useEffect, useMemo } from "react";
import { TabID } from "pages";
import { useMemo } from "react";
import { Tab } from ".";
import { getPath } from "routes/path";
import userEvent from "@testing-library/user-event";

export type TabProps = {
label: string;
tabId: TabID;
path: string;
path?: string;
};

export function useTab(tabs: TabProps[]) {


src/layouts/dashbord/tab/ShopTabs.tsx → src/layouts/dashbord/tab/店舗管理Tabs.tsx View File

@@ -1,11 +1,11 @@
import { Tabs } from "@mui/material";
import { TabProps, useTab } from "./tabutil";
import { 店舗詳細Context } from "contexts/page/dashboard/shop/店舗詳細Context";
import { PageID, TabID } from "pages";
import { useContext, useMemo } from "react";
import { getPath } from "routes/path";
import { useContext, useEffect, useMemo } from "react";
import { 店舗詳細Context } from "contexts/page/dashboard/shop/店舗詳細Context";
import { TabProps, useTab } from "./tabutil";

export default function useShopTabs() {
export default function useA店舗管理Tabs() {
const { shop } = useContext(店舗詳細Context);

const tabs: TabProps[] = useMemo(() => {

+ 1
- 1
src/pages/dashboard/login-user/顧客ログインユーザ一覧/TableBox.tsx View File

@@ -46,7 +46,7 @@ export default function TableBox({ table }: CommonProps) {
return (
<>
<TableContainer>
<Table sx={{ minWidth: 1200 }} size="small">
<Table sx={{ minWidth: 800 }} size="small">
<TableHeadCustom
order={order}
orderBy={sort}


+ 110
- 0
src/pages/dashboard/qr-service/QRサービス券駐車場管理/一覧/TableBox.tsx View File

@@ -0,0 +1,110 @@
import {
Box,
Table,
TableBody,
TableCell,
TableContainer,
TablePagination,
TableRow,
} from "@mui/material";
import { QRサービス券駐車場グループ } from "api/qr-service";
import TableHeadCustom, {
HeadLabelProps,
} from "components/table/TableHeadCustom";
import { QRサービス券駐車場グループ管理Context } from "contexts/page/dashboard/parking/QRサービス券駐車場グループ管理Context";
import { UseTableReturn } from "hooks/useTable";
import { useContext, useEffect, useMemo } from "react";

type CommonProps = {
table: UseTableReturn<QRサービス券駐車場グループ>;
};
export default function TableBox({ table }: CommonProps) {
const TABLE_HEAD: HeadLabelProps[] = [
{ id: "name", label: "名前", align: "left", needSort: false },
{ id: "parkings", label: "登録駐車場", align: "left", needSort: false },
];
const {
order,
page,
sort,
rowsPerPage,
fetched,
fillteredRow,
isNotFound,
dataLength,
//
onSort,
onChangePage,
onChangeRowsPerPage,
//
setRowData,
//
ROWS_PER_PAGES,
} = table;

const { groups } = useContext(QRサービス券駐車場グループ管理Context);

useEffect(() => {
setRowData(groups);
}, [groups]);

return (
<>
<TableContainer>
<Table sx={{ minWidth: 800 }} 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: QRサービス券駐車場グループ;
};
function Row({ data: { id, name, parkings } }: RowProps) {
const { moveToDetail } = useContext(QRサービス券駐車場グループ管理Context);
const handleClick = () => {
moveToDetail(id);
};

const parkingNames = useMemo(() => {
const names = parkings.map((parking) => parking.parking_name).join(",");
if (60 < names.length) {
return names.substring(0, 50) + "...";
}
return names;
}, [parkings]);

return (
<TableRow hover sx={{ cursor: "pointer" }} onClick={handleClick}>
<TableCell>{name}</TableCell>
<TableCell>{parkingNames}</TableCell>
</TableRow>
);
}

+ 30
- 0
src/pages/dashboard/qr-service/QRサービス券駐車場管理/一覧/index.tsx View File

@@ -0,0 +1,30 @@
import { Box } from "@mui/material";
import { QRサービス券駐車場グループ } from "api/qr-service";
import { SearchConditionContextProvider } from "contexts/SearchConditionContext";
import useDashboard from "hooks/useDashBoard";
import useTable from "hooks/useTable";
import { PageID, TabID } from "pages";
import TableBox from "./TableBox";

export default function 一覧() {
const {} = useDashboard(
PageID.QRサービス券駐車場グループ管理,
TabID.QRサービス券駐車場グループ管理_一覧
);

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

function Page() {
const table = useTable<QRサービス券駐車場グループ>();

return (
<Box>
<TableBox table={table} />
</Box>
);
}

+ 76
- 0
src/pages/dashboard/qr-service/QRサービス券駐車場管理/新規登録/index.tsx View File

@@ -0,0 +1,76 @@
import { yupResolver } from "@hookform/resolvers/yup";
import { Box, Button, Stack, Typography } from "@mui/material";
import { QRサービス券駐車場グループ新規登録 } from "api/qr-service";
import { FormProvider, RHFTextField } from "components/hook-form";
import StackRow from "components/stack/StackRow";
import { QRサービス券駐車場グループ管理Context } from "contexts/page/dashboard/parking/QRサービス券駐車場グループ管理Context";
import useAPICall from "hooks/useAPICall";
import useDashboard from "hooks/useDashBoard";
import useSnackbarCustom from "hooks/useSnackbarCustom";
import { PageID, TabID } from "pages";
import { useContext } from "react";
import { useForm } from "react-hook-form";
import { object, string } from "yup";

type FormProps = {
name: string;
};

export default function 新規登録() {
const {} = useDashboard(
PageID.QRサービス券駐車場グループ管理,
TabID.QRサービス券駐車場グループ管理_新規登録
);

const { success, error } = useSnackbarCustom();
const { fetch, moveToList } = useContext(
QRサービス券駐車場グループ管理Context
);

const form = useForm<FormProps>({
defaultValues: {
name: "",
},
resolver: yupResolver(
object().shape({
name: string().required("必須項目です"),
})
),
});

const { callAPI: callQRサービス券駐車場グループ新規登録 } = useAPICall({
apiMethod: QRサービス券駐車場グループ新規登録,
form,
backDrop: true,
onSuccess: () => {
success("登録しました");
fetch();
moveToList();
},
onFailed: () => {
error("失敗しました");
},
});

const handleSubmit = (data: FormProps) => {
callQRサービス券駐車場グループ新規登録({
...data,
});
};

return (
<FormProvider methods={form} onSubmit={form.handleSubmit(handleSubmit)}>
<Box>
<Stack>
<Box>
<Typography>名称</Typography>
<RHFTextField name="name" />
</Box>
<StackRow>
<Button type="submit">登録</Button>
</StackRow>
</Stack>
</Box>
</FormProvider>
);
}

+ 29
- 0
src/pages/dashboard/qr-service/QRサービス券駐車場管理/詳細/index.tsx View File

@@ -0,0 +1,29 @@
import { Box, Stack } from "@mui/material";
import { QRサービス券駐車場グループ管理Context } from "contexts/page/dashboard/parking/QRサービス券駐車場グループ管理Context";
import useDashboard from "hooks/useDashBoard";
import { PageID, TabID } from "pages";
import { useContext } from "react";
import 駐車場一覧 from "./駐車場一覧";
import 駐車場追加 from "./駐車場追加";

export default function 詳細() {
const {} = useDashboard(
PageID.QRサービス券駐車場グループ管理,
TabID.QRサービス券駐車場グループ管理_詳細
);

const { selectedGroup } = useContext(QRサービス券駐車場グループ管理Context);

if (!selectedGroup) {
return null;
}

return (
<Box>
<Stack spacing={2}>
<駐車場一覧 />
<駐車場追加 />
</Stack>
</Box>
);
}

+ 99
- 0
src/pages/dashboard/qr-service/QRサービス券駐車場管理/詳細/駐車場一覧.tsx View File

@@ -0,0 +1,99 @@
import { Box, Button, Card, Grid, Stack, Typography } from "@mui/material";
import { 駐車場マスタ } from "api/parking";
import { QRサービス券駐車場グループ駐車場削除登録 } from "api/qr-service";
import { QRサービス券駐車場グループ管理Context } from "contexts/page/dashboard/parking/QRサービス券駐車場グループ管理Context";
import useAPICall from "hooks/useAPICall";
import { useDialog } from "hooks/useDialog";
import useSnackbarCustom from "hooks/useSnackbarCustom";
import { useContext, useEffect, useState } from "react";

export default function 駐車場一覧() {
const { fetch, selectedGroup } = useContext(
QRサービス券駐車場グループ管理Context
);
const { success, error } = useSnackbarCustom();

const { callAPI: callQRサービス券駐車場グループ駐車場削除登録 } = useAPICall({
apiMethod: QRサービス券駐車場グループ駐車場削除登録,
backDrop: true,
onSuccess: () => {
success("削除しました");
fetch();
},
onFailed: () => {
error("失敗しました");
},
});

const [削除予定駐車場管理コード, set削除予定駐車場管理コード] = useState<
string | null
>(null);

const { element, open, isAgree } = useDialog({
message: "削除しますか?",
});

const deleteDataConfirm = (parkingManagementCode: string) => {
set削除予定駐車場管理コード(parkingManagementCode);
open();
};

useEffect(() => {
if (isAgree && selectedGroup && 削除予定駐車場管理コード) {
callQRサービス券駐車場グループ駐車場削除登録({
id: selectedGroup.id,
parking_management_code: 削除予定駐車場管理コード,
});
}
}, [isAgree]);

if (selectedGroup === null) {
return null;
}

return (
<Card sx={{ p: 2 }} elevation={1}>
<Box>
<Stack spacing={2}>
<Typography variant="h6">グループに含まれる駐車場</Typography>
<Stack spacing={1}>
{selectedGroup.parkings.map((p) => (
<Row
parking={p}
key={p.parking_management_code}
deleteData={deleteDataConfirm}
/>
))}
{selectedGroup.parkings.length === 0 && (
<Typography>登録なし</Typography>
)}
</Stack>
</Stack>
</Box>
{element}
</Card>
);
}

type RowProps = {
parking: 駐車場マスタ;
deleteData: (parkingManagementCode: string) => void;
};
function Row({ parking, deleteData }: RowProps) {
const handleClick = () => {
deleteData(parking.parking_management_code);
};

return (
<Grid container>
<Grid item xs={10}>
{parking.parking_name}({parking.parking_management_code})
</Grid>
<Grid item xs={2}>
<Button color="error" onClick={handleClick}>
削除
</Button>
</Grid>
</Grid>
);
}

+ 106
- 0
src/pages/dashboard/qr-service/QRサービス券駐車場管理/詳細/駐車場追加.tsx View File

@@ -0,0 +1,106 @@
import { yupResolver } from "@hookform/resolvers/yup";
import { Box, Button, Card, Grid, Stack, Typography } from "@mui/material";
import { QRサービス券駐車場グループ駐車場追加登録 } from "api/qr-service";
import { FormProvider, RHFAutoComplete } from "components/hook-form";
import {
AutoCompleteOption,
AutoCompleteOptionType,
getValue,
} from "components/hook-form/RHFAutoComplete";
import StackRow from "components/stack/StackRow";
import { QRサービス券駐車場グループ管理Context } from "contexts/page/dashboard/parking/QRサービス券駐車場グループ管理Context";
import useAPICall from "hooks/useAPICall";
import useSnackbarCustom from "hooks/useSnackbarCustom";
import { useContext, useMemo } from "react";
import { useForm } from "react-hook-form";
import { object } from "yup";

type FormProps = {
parking_management_code: AutoCompleteOptionType;
};

export default function 駐車場追加() {
const { fetch, selectedGroup, parkings } = useContext(
QRサービス券駐車場グループ管理Context
);
const { success, error } = useSnackbarCustom();

const form = useForm<FormProps>({
defaultValues: {
parking_management_code: null,
},
resolver: yupResolver(
object().shape({
parking_management_code: object().required("必須項目です"),
})
),
});

const { callAPI: callQRサービス券駐車場グループ駐車場追加登録 } = useAPICall({
apiMethod: QRサービス券駐車場グループ駐車場追加登録,
backDrop: true,
form,
onSuccess: () => {
success("追加しました");
fetch();
form.setValue("parking_management_code", null);
},
onFailed: () => {
error("失敗しました");
},
});

const options: AutoCompleteOption[] = useMemo(() => {
return parkings
.filter(
(p) =>
!selectedGroup?.parkings.find(
(ele) => ele.parking_management_code === p.parking_management_code
)
)
.map((p) => ({
label: p.parking_name,
value: p.parking_management_code,
}));
}, [parkings, selectedGroup]);

const handleSubmit = (data: FormProps) => {
if (selectedGroup === null) return;
const parkingManagementCode = getValue(data.parking_management_code);
callQRサービス券駐車場グループ駐車場追加登録({
id: selectedGroup.id,
parking_management_code: parkingManagementCode,
});
};

return (
<FormProvider methods={form} onSubmit={form.handleSubmit(handleSubmit)}>
<Card sx={{ p: 2 }} elevation={1}>
<Box>
<Stack spacing={2}>
<Typography variant="h6">駐車場追加</Typography>
<StackRow>
<Grid container columnGap={2}>
<Grid item xs={12} md={6}>
<Typography>駐車場</Typography>
<StackRow>
<RHFAutoComplete
name="parking_management_code"
options={options}
size="small"
/>
</StackRow>
</Grid>
</Grid>
</StackRow>
<StackRow>
<Button type="submit" variant="contained">
追加
</Button>
</StackRow>
</Stack>
</Box>
</Card>
</FormProvider>
);
}

src/pages/dashboard/qrcode/サービス券利用履歴.tsx → src/pages/dashboard/qr-service/サービス券利用履歴.tsx View File


src/pages/dashboard/qrcode/サービス券発行用QRコード.tsx → src/pages/dashboard/qr-service/サービス券発行用QRコード.tsx View File


+ 1
- 3
src/pages/dashboard/shop/店舗一覧/TableBox.tsx View File

@@ -7,12 +7,10 @@ import {
TablePagination,
TableRow,
} from "@mui/material";
import { 運営会社ログインユーザ } from "api/login-user";
import { 店舗 } from "api/shop";
import TableHeadCustom, {
HeadLabelProps,
} from "components/table/TableHeadCustom";
import useAuth from "hooks/useAuth";
import useNavigateCustom from "hooks/useNavigateCustom";
import useSnackbarCustom from "hooks/useSnackbarCustom";
import { UseTableReturn } from "hooks/useTable";
@@ -51,7 +49,7 @@ export default function TableBox({ table }: CommonProps) {
return (
<>
<TableContainer>
<Table sx={{ minWidth: 1200 }} size="small">
<Table sx={{ minWidth: 800 }} size="small">
<TableHeadCustom
order={order}
orderBy={sort}


+ 1
- 7
src/pages/dashboard/shop/店舗詳細/設定/index.tsx View File

@@ -1,16 +1,10 @@
import { Box, Stack } from "@mui/material";
import { 店舗詳細Context } from "contexts/page/dashboard/shop/店舗詳細Context";
import useDashboard from "hooks/useDashBoard";
import ShopTabs from "layouts/dashbord/tab/ShopTabs";
import { PageID, TabID } from "pages";
import { useContext, useEffect } from "react";
import 設定 from "./設定";

export default function 店舗詳細設定() {
const { setHeaderTitle, setTabs } = useDashboard(
PageID.店舗詳細,
TabID.店舗詳細_設定
);
const {} = useDashboard(PageID.店舗詳細, TabID.店舗詳細_設定);
return <Page />;
}



+ 7
- 0
src/pages/index.ts View File

@@ -20,6 +20,9 @@ export const PageID = {
ログインユーザ_店舗一覧: id++,
ログインユーザ_店舗新規登録: id++,

// QRサービス券駐車場グループ管理
QRサービス券駐車場グループ管理: id++,

// 店舗管理
店舗一覧: id++,
店舗新規登録: id++,
@@ -43,6 +46,10 @@ export const TabID = {

店舗詳細_メイン: id++,
店舗詳細_設定: id++,

QRサービス券駐車場グループ管理_一覧: id++,
QRサービス券駐車場グループ管理_新規登録: id++,
QRサービス券駐車場グループ管理_詳細: id++,
} as const;

export type TabID = (typeof TabID)[keyof typeof TabID];

+ 15
- 3
src/routes/path.ts View File

@@ -12,7 +12,7 @@ const makePathKey = (arg: PathKey): string => {
}
};

const getPageId = (key: PathKey): PageID => {
export const getPageId = (key: PathKey): PageID => {
if (isArray(key)) {
return key[0];
} else {
@@ -20,7 +20,7 @@ const getPageId = (key: PathKey): PageID => {
}
};

const getTabId = (key: PathKey): TabID => {
export const getTabId = (key: PathKey): TabID => {
if (isArray(key)) {
return key[1] ?? TabID.NONE;
} else {
@@ -40,9 +40,21 @@ const PATHS_DASHBOARD = {
[makePathKey(PageID.ログインユーザ_店舗新規登録)]:
"/dashboard/login-user/shop/register",

[makePathKey([
PageID.QRサービス券駐車場グループ管理,
TabID.QRサービス券駐車場グループ管理_一覧,
])]: "/dashboard/qr-service/group/list",
[makePathKey([
PageID.QRサービス券駐車場グループ管理,
TabID.QRサービス券駐車場グループ管理_新規登録,
])]: "/dashboard/qr-service/group/register",
[makePathKey([
PageID.QRサービス券駐車場グループ管理,
TabID.QRサービス券駐車場グループ管理_詳細,
])]: "/dashboard/qr-service/group/detail/:id",

[makePathKey(PageID.店舗一覧)]: "/dashboard/shop/list",
[makePathKey(PageID.店舗新規登録)]: "/dashboard/shop/register",
[makePathKey([PageID.店舗詳細])]: "/dashboard/shop/detail/:shopId",
[makePathKey([PageID.店舗詳細, TabID.店舗詳細_メイン])]:
"/dashboard/shop/detail/:shopId",
[makePathKey([PageID.店舗詳細, TabID.店舗詳細_設定])]:


+ 0
- 124
src/routes/sub/________dashboard.tsx View File

@@ -1,124 +0,0 @@
import { ページアクセス許可判定 } from "auth/route";
import AuthGuard from "guards/AuthGuard";
import useAuth from "hooks/useAuth";
import DashboardLayout from "layouts/dashbord";
import { PageID, TabID } from "pages";
import React, { lazy, useMemo } from "react";
import { RouteObject } from "react-router-dom";
import { Loadable } from "routes";
import { getRoute } from "routes/path";

export default function DashboardRoutes(): RouteObject[] {
const { currentRole } = useAuth();

const children: RouteObject[] = useMemo(() => {
const Enpty = Loadable(lazy(() => import("pages/dashboard/empty")));
const Dashboard = Loadable(lazy(() => import("pages/dashboard")));
const 成り代わり終了 = Loadable(
lazy(() => import("pages/dashboard/成り代わり終了"))
);

const サービス券発行用QRコード = Loadable(
lazy(() => import("pages/dashboard/qrcode/サービス券発行用QRコード"))
);
const サービス券利用履歴 = Loadable(
lazy(() => import("pages/dashboard/qrcode/サービス券利用履歴"))
);
const 顧客ログインユーザ一覧 = Loadable(
lazy(() => import("pages/dashboard/login-user/顧客ログインユーザ一覧"))
);
const 顧客ログインユーザ新規登録 = Loadable(
lazy(
() => import("pages/dashboard/login-user/顧客ログインユーザ新規登録")
)
);
const 店舗新規登録 = Loadable(
lazy(() => import("pages/dashboard/shop/店舗新規登録"))
);
const 店舗一覧 = Loadable(
lazy(() => import("pages/dashboard/shop/店舗一覧"))
);
const 店舗詳細 = Loadable(
lazy(() => import("pages/dashboard/shop/店舗詳細"))
);

const allChildren: {
pageId: PageID;
tabId?: TabID;
element: JSX.Element;
}[] = [
{
pageId: PageID.DASHBOARD_ENPTY,
element: <Enpty />,
},
{
pageId: PageID.DASHBOARD_OVERVIEW,
element: <Dashboard />,
},
{
pageId: PageID.成り代わり終了,
element: <成り代わり終了 />,
},
{
pageId: PageID.ログインユーザ_顧客一覧,
element: <顧客ログインユーザ一覧 />,
},
{
pageId: PageID.ログインユーザ_顧客新規登録,
element: <顧客ログインユーザ新規登録 />,
},
// {
// pageId: PageID.ログインユーザ_店舗一覧,
// element: <顧客ログインユーザ一覧 />,
// },
// {
// pageId: PageID.ログインユーザ_店舗新規登録,
// element: <顧客ログインユーザ新規登録 />,
// },
{
pageId: PageID.店舗新規登録,
element: <店舗新規登録 />,
},
{
pageId: PageID.店舗一覧,
element: <店舗一覧 />,
},
{
pageId: PageID.店舗詳細,
tabId: TabID.店舗詳細_メイン,
element: <店舗詳細 />,
},
{
pageId: PageID.サービス券発行用QRコード,
element: <サービス券発行用QRコード />,
},
{
pageId: PageID.サービス券利用履歴,
element: <サービス券利用履歴 />,
},
];

return allChildren
.filter(({ pageId }) => {
if (currentRole === null) {
return false;
}
return ページアクセス許可判定(currentRole, pageId);
})
.map(({ pageId, tabId, ...others }) => ({
...others,
path: getRoute([pageId, tabId]),
}));
}, [currentRole]);

return [
{
element: (
<AuthGuard>
<DashboardLayout />
</AuthGuard>
),
children: children,
},
];
}

+ 52
- 2
src/routes/sub/dashboard.tsx View File

@@ -1,4 +1,5 @@
import { ページアクセス許可判定 } from "auth/route";
import QRサービス券駐車場グループ管理ContextProvider from "contexts/page/dashboard/parking/QRサービス券駐車場グループ管理Context";
import 店舗詳細ContextProvider from "contexts/page/dashboard/shop/店舗詳細Context";
import AuthGuard from "guards/AuthGuard";
import useAuth from "hooks/useAuth";
@@ -20,10 +21,26 @@ export default function DashboardRoutes(): RouteObject[] {
);

const サービス券発行用QRコード = Loadable(
lazy(() => import("pages/dashboard/qrcode/サービス券発行用QRコード"))
lazy(() => import("pages/dashboard/qr-service/サービス券発行用QRコード"))
);
const サービス券利用履歴 = Loadable(
lazy(() => import("pages/dashboard/qrcode/サービス券利用履歴"))
lazy(() => import("pages/dashboard/qr-service/サービス券利用履歴"))
);
const QRサービス券駐車場管理一覧 = Loadable(
lazy(
() => import("pages/dashboard/qr-service/QRサービス券駐車場管理/一覧")
)
);
const QRサービス券駐車場管理新規登録 = Loadable(
lazy(
() =>
import("pages/dashboard/qr-service/QRサービス券駐車場管理/新規登録")
)
);
const QRサービス券駐車場管理詳細 = Loadable(
lazy(
() => import("pages/dashboard/qr-service/QRサービス券駐車場管理/詳細")
)
);
const 顧客ログインユーザ一覧 = Loadable(
lazy(() => import("pages/dashboard/login-user/顧客ログインユーザ一覧"))
@@ -127,6 +144,39 @@ export default function DashboardRoutes(): RouteObject[] {
],
},
},
{
pageId: PageID.QRサービス券駐車場グループ管理,
ele: {
element: (
<QRサービス券駐車場グループ管理ContextProvider>
<Outlet />
</QRサービス券駐車場グループ管理ContextProvider>
),
children: [
{
element: <QRサービス券駐車場管理一覧 />,
path: getPath([
PageID.QRサービス券駐車場グループ管理,
TabID.QRサービス券駐車場グループ管理_一覧,
]),
},
{
element: <QRサービス券駐車場管理新規登録 />,
path: getPath([
PageID.QRサービス券駐車場グループ管理,
TabID.QRサービス券駐車場グループ管理_新規登録,
]),
},
{
element: <QRサービス券駐車場管理詳細 />,
path: getPath([
PageID.QRサービス券駐車場グループ管理,
TabID.QRサービス券駐車場グループ管理_詳細,
]),
},
],
},
},
];

return allChildren


Loading…
Cancel
Save