| @@ -27,6 +27,9 @@ export const ApiId = { | |||||
| // 顧客関連 ---------------------------------- | // 顧客関連 ---------------------------------- | ||||
| 顧客マスタ一覧取得: id++, | 顧客マスタ一覧取得: id++, | ||||
| // 駐車場関連 ---------------------------------- | |||||
| 駐車場マスタ一覧取得: id++, | |||||
| // 店舗関連関連 ---------------------------------- | // 店舗関連関連 ---------------------------------- | ||||
| 店舗一覧取得: id++, | 店舗一覧取得: id++, | ||||
| 店舗新規登録: id++, | 店舗新規登録: id++, | ||||
| @@ -35,6 +38,10 @@ export const ApiId = { | |||||
| 店舗設定: id++, | 店舗設定: id++, | ||||
| // QRサービス券関連------------------------------- | // QRサービス券関連------------------------------- | ||||
| QRサービス券駐車場グループ一覧取得: id++, | |||||
| QRサービス券駐車場グループ新規登録: id++, | |||||
| QRサービス券駐車場グループ駐車場追加登録: id++, | |||||
| QRサービス券駐車場グループ駐車場削除登録: id++, | |||||
| QRサービス券取得: id++, | QRサービス券取得: id++, | ||||
| } as const; | } as const; | ||||
| export type ApiId = (typeof ApiId)[keyof typeof ApiId]; | export type ApiId = (typeof ApiId)[keyof typeof ApiId]; | ||||
| @@ -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; | |||||
| }; | |||||
| @@ -1,5 +1,13 @@ | |||||
| import { APICommonResponse, ApiId, HttpMethod, request } from "api"; | |||||
| import { APICommonResponse, ApiId, HttpMethod, makeParam, request } from "api"; | |||||
| import { getUrl } from "./url"; | import { getUrl } from "./url"; | ||||
| import { string } from "yup"; | |||||
| import { 駐車場マスタ } from "./parking"; | |||||
| export type QRサービス券駐車場グループ = { | |||||
| id: string; | |||||
| name: string; | |||||
| parkings: 駐車場マスタ[]; | |||||
| }; | |||||
| // -------QRサービス券取得--------------- | // -------QRサービス券取得--------------- | ||||
| export type QRサービス券取得Request = { | export type QRサービス券取得Request = { | ||||
| @@ -20,3 +28,77 @@ export const QRサービス券取得 = async (param: QRサービス券取得Requ | |||||
| }); | }); | ||||
| return res; | 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; | |||||
| }; | |||||
| @@ -22,6 +22,9 @@ const urls = { | |||||
| // 顧客関連 ---------------------------------- | // 顧客関連 ---------------------------------- | ||||
| [A.顧客マスタ一覧取得]: "customer/list", | [A.顧客マスタ一覧取得]: "customer/list", | ||||
| // 駐車場関連 ---------------------------------- | |||||
| [A.駐車場マスタ一覧取得]: "parking/list", | |||||
| // 店舗関連関連 ---------------------------------- | // 店舗関連関連 ---------------------------------- | ||||
| [A.店舗一覧取得]: "shop/list", | [A.店舗一覧取得]: "shop/list", | ||||
| [A.店舗新規登録]: "shop/register", | [A.店舗新規登録]: "shop/register", | ||||
| @@ -30,6 +33,12 @@ const urls = { | |||||
| [A.店舗設定]: "shop/config", | [A.店舗設定]: "shop/config", | ||||
| // QRサービス券関連------------------------------- | // 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", | [A.QRサービス券取得]: "qr-service/get-ticket", | ||||
| }; | }; | ||||
| @@ -26,6 +26,7 @@ const 認可別許可ルート: { | |||||
| P.店舗一覧, | P.店舗一覧, | ||||
| P.店舗新規登録, | P.店舗新規登録, | ||||
| P.店舗詳細, | P.店舗詳細, | ||||
| P.QRサービス券駐車場グループ管理, | |||||
| ], | ], | ||||
| [UserRole.SHOP]: [ | [UserRole.SHOP]: [ | ||||
| @@ -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; | |||||
| @@ -4,7 +4,7 @@ import useAPICall from "hooks/useAPICall"; | |||||
| import useDashboard from "hooks/useDashBoard"; | import useDashboard from "hooks/useDashBoard"; | ||||
| import useNavigateCustom from "hooks/useNavigateCustom"; | import useNavigateCustom from "hooks/useNavigateCustom"; | ||||
| import useSnackbarCustom from "hooks/useSnackbarCustom"; | 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 { PageID, TabID } from "pages"; | ||||
| import { createContext, useContext, useEffect, useState } from "react"; | import { createContext, useContext, useEffect, useState } from "react"; | ||||
| import { useParams } from "react-router-dom"; | import { useParams } from "react-router-dom"; | ||||
| @@ -6,7 +6,7 @@ import { | |||||
| DialogContentText, | DialogContentText, | ||||
| DialogTitle, | DialogTitle, | ||||
| } from "@mui/material"; | } from "@mui/material"; | ||||
| import { ReactNode, useState } from "react"; | |||||
| import { ReactNode, useEffect, useState } from "react"; | |||||
| type Props = { | type Props = { | ||||
| message?: string; | message?: string; | ||||
| @@ -17,9 +17,10 @@ type Props = { | |||||
| export type UseDialogReturn = { | export type UseDialogReturn = { | ||||
| show: boolean; | show: boolean; | ||||
| isAgree: boolean; | |||||
| isDisAgree: boolean; | |||||
| open: VoidFunction; | open: VoidFunction; | ||||
| close: VoidFunction; | close: VoidFunction; | ||||
| setShow: (show: boolean) => void; | |||||
| element: ReactNode; | element: ReactNode; | ||||
| }; | }; | ||||
| @@ -30,6 +31,8 @@ export function useDialog({ | |||||
| onDisagree, | onDisagree, | ||||
| }: Props = {}): UseDialogReturn { | }: Props = {}): UseDialogReturn { | ||||
| const [show, setShow] = useState(false); | const [show, setShow] = useState(false); | ||||
| const [isAgree, setIsAgree] = useState(false); | |||||
| const [isDisAgree, setIsDisAgree] = useState(false); | |||||
| const open = () => { | const open = () => { | ||||
| setShow(true); | setShow(true); | ||||
| @@ -47,6 +50,7 @@ export function useDialog({ | |||||
| onAgree(); | onAgree(); | ||||
| } | } | ||||
| setShow(false); | setShow(false); | ||||
| setIsAgree(true); | |||||
| }; | }; | ||||
| const disagree = () => { | const disagree = () => { | ||||
| @@ -54,8 +58,16 @@ export function useDialog({ | |||||
| onDisagree(); | onDisagree(); | ||||
| } | } | ||||
| setShow(false); | setShow(false); | ||||
| setIsDisAgree(true); | |||||
| }; | }; | ||||
| useEffect(() => { | |||||
| if (show === false) { | |||||
| setIsAgree(false); | |||||
| setIsDisAgree(false); | |||||
| } | |||||
| }, [show]); | |||||
| const element = ( | const element = ( | ||||
| <Dialog open={show} onClose={close}> | <Dialog open={show} onClose={close}> | ||||
| <DialogTitle>確認</DialogTitle> | <DialogTitle>確認</DialogTitle> | ||||
| @@ -74,6 +86,8 @@ export function useDialog({ | |||||
| return { | return { | ||||
| // param | // param | ||||
| show, | show, | ||||
| isAgree, | |||||
| isDisAgree, | |||||
| // Element | // Element | ||||
| element, | element, | ||||
| @@ -81,6 +95,5 @@ export function useDialog({ | |||||
| open, | open, | ||||
| close, | close, | ||||
| setShow, | |||||
| }; | }; | ||||
| } | } | ||||
| @@ -1,7 +1,6 @@ | |||||
| import { ExpandLess, ExpandMore } from "@mui/icons-material"; | import { ExpandLess, ExpandMore } from "@mui/icons-material"; | ||||
| import AccountCircleIcon from "@mui/icons-material/AccountCircle"; | import AccountCircleIcon from "@mui/icons-material/AccountCircle"; | ||||
| import ArticleIcon from "@mui/icons-material/Article"; | import ArticleIcon from "@mui/icons-material/Article"; | ||||
| import PersonIcon from "@mui/icons-material/Person"; | |||||
| import SettingsIcon from "@mui/icons-material/Settings"; | import SettingsIcon from "@mui/icons-material/Settings"; | ||||
| import { Collapse, Typography } from "@mui/material"; | import { Collapse, Typography } from "@mui/material"; | ||||
| import Box from "@mui/material/Box"; | import Box from "@mui/material/Box"; | ||||
| @@ -12,14 +11,13 @@ import ListItem from "@mui/material/ListItem"; | |||||
| import ListItemButton from "@mui/material/ListItemButton"; | import ListItemButton from "@mui/material/ListItemButton"; | ||||
| import ListItemIcon from "@mui/material/ListItemIcon"; | import ListItemIcon from "@mui/material/ListItemIcon"; | ||||
| import ListItemText from "@mui/material/ListItemText"; | import ListItemText from "@mui/material/ListItemText"; | ||||
| import { UserRole } from "auth/UserRole"; | |||||
| import { ページアクセス許可判定 } from "auth/route"; | import { ページアクセス許可判定 } from "auth/route"; | ||||
| import useAuth from "hooks/useAuth"; | import useAuth from "hooks/useAuth"; | ||||
| import useNavigateCustom from "hooks/useNavigateCustom"; | import useNavigateCustom from "hooks/useNavigateCustom"; | ||||
| import usePage from "hooks/usePage"; | import usePage from "hooks/usePage"; | ||||
| import { PageID, TabID } from "pages"; | import { PageID, TabID } from "pages"; | ||||
| import * as React from "react"; | import * as React from "react"; | ||||
| import { PathKey, PathOption, getPath } from "routes/path"; | |||||
| import { PathKey, PathOption, getPageId, getPath } from "routes/path"; | |||||
| type Group = { | type Group = { | ||||
| label: string; | label: string; | ||||
| children: SubGroup[]; | children: SubGroup[]; | ||||
| @@ -32,12 +30,12 @@ type SubGroup = { | |||||
| whenIsSwitched?: boolean; | whenIsSwitched?: boolean; | ||||
| // 子要素を持たない場合は設定 | // 子要素を持たない場合は設定 | ||||
| id?: PageID; | |||||
| id?: PathKey; | |||||
| option?: PathOption; | option?: PathOption; | ||||
| }; | }; | ||||
| type Child = { | type Child = { | ||||
| label: string; | |||||
| label: string | React.ReactNode; | |||||
| id: PathKey; | id: PathKey; | ||||
| option?: PathOption; | 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サービス券", | label: "QRサービス券", | ||||
| children: [ | children: [ | ||||
| @@ -166,7 +183,10 @@ function Group(group: Group) { | |||||
| const { label, children } = group; | const { label, children } = group; | ||||
| const elements = children | const elements = children | ||||
| .filter(({ id }) => ページアクセス許可判定(currentRole, id ?? -1)) | |||||
| .filter( | |||||
| ({ id }) => | |||||
| !id || ページアクセス許可判定(currentRole, getPageId(id) ?? -1) | |||||
| ) | |||||
| .filter(({ whenIsSwitched }) => whenIsSwitched !== true || isSwitched) | .filter(({ whenIsSwitched }) => whenIsSwitched !== true || isSwitched) | ||||
| .map((ele, index) => <SubGroup {...ele} key={index} />); | .map((ele, index) => <SubGroup {...ele} key={index} />); | ||||
| @@ -223,7 +243,7 @@ function SubGroup({ icon, label, id, children, option }: SubGroup) { | |||||
| navigateWhenChanged(path, undefined, { reload: true }); | navigateWhenChanged(path, undefined, { reload: true }); | ||||
| } | } | ||||
| }; | }; | ||||
| const selected = id === pageId; | |||||
| const selected = getPageId(id) === pageId; | |||||
| return ( | return ( | ||||
| <ListItemButton onClick={handleClick} selected={selected} sx={item}> | <ListItemButton onClick={handleClick} selected={selected} sx={item}> | ||||
| <ListItemIcon>{icon}</ListItemIcon> | <ListItemIcon>{icon}</ListItemIcon> | ||||
| @@ -244,7 +264,7 @@ function useContents(children: Child[]) { | |||||
| const elements = React.useMemo(() => { | const elements = React.useMemo(() => { | ||||
| setShouldOpen(false); | setShouldOpen(false); | ||||
| return children.map(({ label, id, option }, index) => { | return children.map(({ label, id, option }, index) => { | ||||
| const selected = id === pageId; | |||||
| const selected = getPageId(id) === pageId; | |||||
| if (selected) { | if (selected) { | ||||
| setShouldOpen(true); | setShouldOpen(true); | ||||
| } | } | ||||
| @@ -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> | |||||
| ), | |||||
| }; | |||||
| } | |||||
| @@ -1,14 +1,12 @@ | |||||
| import { PageID, TabID } from "pages"; | |||||
| import usePage from "hooks/usePage"; | import usePage from "hooks/usePage"; | ||||
| import { useEffect, useMemo } from "react"; | |||||
| import { TabID } from "pages"; | |||||
| import { useMemo } from "react"; | |||||
| import { Tab } from "."; | import { Tab } from "."; | ||||
| import { getPath } from "routes/path"; | |||||
| import userEvent from "@testing-library/user-event"; | |||||
| export type TabProps = { | export type TabProps = { | ||||
| label: string; | label: string; | ||||
| tabId: TabID; | tabId: TabID; | ||||
| path: string; | |||||
| path?: string; | |||||
| }; | }; | ||||
| export function useTab(tabs: TabProps[]) { | export function useTab(tabs: TabProps[]) { | ||||
| @@ -1,11 +1,11 @@ | |||||
| import { Tabs } from "@mui/material"; | import { Tabs } from "@mui/material"; | ||||
| import { TabProps, useTab } from "./tabutil"; | |||||
| import { 店舗詳細Context } from "contexts/page/dashboard/shop/店舗詳細Context"; | |||||
| import { PageID, TabID } from "pages"; | import { PageID, TabID } from "pages"; | ||||
| import { useContext, useMemo } from "react"; | |||||
| import { getPath } from "routes/path"; | 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 { shop } = useContext(店舗詳細Context); | ||||
| const tabs: TabProps[] = useMemo(() => { | const tabs: TabProps[] = useMemo(() => { | ||||
| @@ -46,7 +46,7 @@ export default function TableBox({ table }: CommonProps) { | |||||
| return ( | return ( | ||||
| <> | <> | ||||
| <TableContainer> | <TableContainer> | ||||
| <Table sx={{ minWidth: 1200 }} size="small"> | |||||
| <Table sx={{ minWidth: 800 }} size="small"> | |||||
| <TableHeadCustom | <TableHeadCustom | ||||
| order={order} | order={order} | ||||
| orderBy={sort} | orderBy={sort} | ||||
| @@ -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> | |||||
| ); | |||||
| } | |||||
| @@ -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> | |||||
| ); | |||||
| } | |||||
| @@ -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> | |||||
| ); | |||||
| } | |||||
| @@ -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> | |||||
| ); | |||||
| } | |||||
| @@ -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> | |||||
| ); | |||||
| } | |||||
| @@ -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> | |||||
| ); | |||||
| } | |||||
| @@ -7,12 +7,10 @@ import { | |||||
| TablePagination, | TablePagination, | ||||
| TableRow, | TableRow, | ||||
| } from "@mui/material"; | } from "@mui/material"; | ||||
| import { 運営会社ログインユーザ } from "api/login-user"; | |||||
| import { 店舗 } from "api/shop"; | import { 店舗 } from "api/shop"; | ||||
| import TableHeadCustom, { | import TableHeadCustom, { | ||||
| HeadLabelProps, | HeadLabelProps, | ||||
| } from "components/table/TableHeadCustom"; | } from "components/table/TableHeadCustom"; | ||||
| import useAuth from "hooks/useAuth"; | |||||
| import useNavigateCustom from "hooks/useNavigateCustom"; | import useNavigateCustom from "hooks/useNavigateCustom"; | ||||
| import useSnackbarCustom from "hooks/useSnackbarCustom"; | import useSnackbarCustom from "hooks/useSnackbarCustom"; | ||||
| import { UseTableReturn } from "hooks/useTable"; | import { UseTableReturn } from "hooks/useTable"; | ||||
| @@ -51,7 +49,7 @@ export default function TableBox({ table }: CommonProps) { | |||||
| return ( | return ( | ||||
| <> | <> | ||||
| <TableContainer> | <TableContainer> | ||||
| <Table sx={{ minWidth: 1200 }} size="small"> | |||||
| <Table sx={{ minWidth: 800 }} size="small"> | |||||
| <TableHeadCustom | <TableHeadCustom | ||||
| order={order} | order={order} | ||||
| orderBy={sort} | orderBy={sort} | ||||
| @@ -1,16 +1,10 @@ | |||||
| import { Box, Stack } from "@mui/material"; | import { Box, Stack } from "@mui/material"; | ||||
| import { 店舗詳細Context } from "contexts/page/dashboard/shop/店舗詳細Context"; | |||||
| import useDashboard from "hooks/useDashBoard"; | import useDashboard from "hooks/useDashBoard"; | ||||
| import ShopTabs from "layouts/dashbord/tab/ShopTabs"; | |||||
| import { PageID, TabID } from "pages"; | import { PageID, TabID } from "pages"; | ||||
| import { useContext, useEffect } from "react"; | |||||
| import 設定 from "./設定"; | import 設定 from "./設定"; | ||||
| export default function 店舗詳細設定() { | export default function 店舗詳細設定() { | ||||
| const { setHeaderTitle, setTabs } = useDashboard( | |||||
| PageID.店舗詳細, | |||||
| TabID.店舗詳細_設定 | |||||
| ); | |||||
| const {} = useDashboard(PageID.店舗詳細, TabID.店舗詳細_設定); | |||||
| return <Page />; | return <Page />; | ||||
| } | } | ||||
| @@ -20,6 +20,9 @@ export const PageID = { | |||||
| ログインユーザ_店舗一覧: id++, | ログインユーザ_店舗一覧: id++, | ||||
| ログインユーザ_店舗新規登録: id++, | ログインユーザ_店舗新規登録: id++, | ||||
| // QRサービス券駐車場グループ管理 | |||||
| QRサービス券駐車場グループ管理: id++, | |||||
| // 店舗管理 | // 店舗管理 | ||||
| 店舗一覧: id++, | 店舗一覧: id++, | ||||
| 店舗新規登録: id++, | 店舗新規登録: id++, | ||||
| @@ -43,6 +46,10 @@ export const TabID = { | |||||
| 店舗詳細_メイン: id++, | 店舗詳細_メイン: id++, | ||||
| 店舗詳細_設定: id++, | 店舗詳細_設定: id++, | ||||
| QRサービス券駐車場グループ管理_一覧: id++, | |||||
| QRサービス券駐車場グループ管理_新規登録: id++, | |||||
| QRサービス券駐車場グループ管理_詳細: id++, | |||||
| } as const; | } as const; | ||||
| export type TabID = (typeof TabID)[keyof typeof TabID]; | export type TabID = (typeof TabID)[keyof typeof TabID]; | ||||
| @@ -12,7 +12,7 @@ const makePathKey = (arg: PathKey): string => { | |||||
| } | } | ||||
| }; | }; | ||||
| const getPageId = (key: PathKey): PageID => { | |||||
| export const getPageId = (key: PathKey): PageID => { | |||||
| if (isArray(key)) { | if (isArray(key)) { | ||||
| return key[0]; | return key[0]; | ||||
| } else { | } else { | ||||
| @@ -20,7 +20,7 @@ const getPageId = (key: PathKey): PageID => { | |||||
| } | } | ||||
| }; | }; | ||||
| const getTabId = (key: PathKey): TabID => { | |||||
| export const getTabId = (key: PathKey): TabID => { | |||||
| if (isArray(key)) { | if (isArray(key)) { | ||||
| return key[1] ?? TabID.NONE; | return key[1] ?? TabID.NONE; | ||||
| } else { | } else { | ||||
| @@ -40,9 +40,21 @@ const PATHS_DASHBOARD = { | |||||
| [makePathKey(PageID.ログインユーザ_店舗新規登録)]: | [makePathKey(PageID.ログインユーザ_店舗新規登録)]: | ||||
| "/dashboard/login-user/shop/register", | "/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/list", | ||||
| [makePathKey(PageID.店舗新規登録)]: "/dashboard/shop/register", | [makePathKey(PageID.店舗新規登録)]: "/dashboard/shop/register", | ||||
| [makePathKey([PageID.店舗詳細])]: "/dashboard/shop/detail/:shopId", | |||||
| [makePathKey([PageID.店舗詳細, TabID.店舗詳細_メイン])]: | [makePathKey([PageID.店舗詳細, TabID.店舗詳細_メイン])]: | ||||
| "/dashboard/shop/detail/:shopId", | "/dashboard/shop/detail/:shopId", | ||||
| [makePathKey([PageID.店舗詳細, TabID.店舗詳細_設定])]: | [makePathKey([PageID.店舗詳細, TabID.店舗詳細_設定])]: | ||||
| @@ -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, | |||||
| }, | |||||
| ]; | |||||
| } | |||||
| @@ -1,4 +1,5 @@ | |||||
| import { ページアクセス許可判定 } from "auth/route"; | import { ページアクセス許可判定 } from "auth/route"; | ||||
| import QRサービス券駐車場グループ管理ContextProvider from "contexts/page/dashboard/parking/QRサービス券駐車場グループ管理Context"; | |||||
| import 店舗詳細ContextProvider from "contexts/page/dashboard/shop/店舗詳細Context"; | import 店舗詳細ContextProvider from "contexts/page/dashboard/shop/店舗詳細Context"; | ||||
| import AuthGuard from "guards/AuthGuard"; | import AuthGuard from "guards/AuthGuard"; | ||||
| import useAuth from "hooks/useAuth"; | import useAuth from "hooks/useAuth"; | ||||
| @@ -20,10 +21,26 @@ export default function DashboardRoutes(): RouteObject[] { | |||||
| ); | ); | ||||
| const サービス券発行用QRコード = Loadable( | const サービス券発行用QRコード = Loadable( | ||||
| lazy(() => import("pages/dashboard/qrcode/サービス券発行用QRコード")) | |||||
| lazy(() => import("pages/dashboard/qr-service/サービス券発行用QRコード")) | |||||
| ); | ); | ||||
| const サービス券利用履歴 = Loadable( | 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( | const 顧客ログインユーザ一覧 = Loadable( | ||||
| lazy(() => import("pages/dashboard/login-user/顧客ログインユーザ一覧")) | 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 | return allChildren | ||||