| @@ -29,6 +29,7 @@ export const ApiId = { | |||
| // 駐車場関連 ---------------------------------- | |||
| 駐車場マスタ一覧取得: id++, | |||
| サービス券マスタ一覧取得: id++, | |||
| // 店舗関連関連 ---------------------------------- | |||
| 店舗一覧取得: id++, | |||
| @@ -37,8 +38,11 @@ export const ApiId = { | |||
| デポジットチャージ: id++, | |||
| 店舗設定: id++, | |||
| 店舗QR設定取得: id++, | |||
| 店舗QR設定認証設定新規登録: id++, | |||
| 店舗QR設定認証設定更新: id++, | |||
| 店舗QR設定認証設定追加: id++, | |||
| 店舗QR設定認証設定削除: id++, | |||
| 店舗QR設定認証設定全削除: id++, | |||
| 店舗QR設定取得設定変更: id++, | |||
| 店舗QR設定取得設定無効化: id++, | |||
| @@ -1,10 +1,14 @@ | |||
| import { APICommonResponse, ApiId, HttpMethod, request } from "api"; | |||
| import { APICommonResponse, ApiId, HttpMethod, makeParam, request } from "api"; | |||
| import { getUrl } from "./url"; | |||
| export type 駐車場マスタ = { | |||
| parking_management_code: string; | |||
| parking_name: string; | |||
| }; | |||
| export type サービス券マスタ = { | |||
| discount_ticket_code: number; | |||
| ticket_name: string; | |||
| }; | |||
| // -------駐車場マスタ一覧取得--------------- | |||
| export type 駐車場マスタ一覧取得Request = {}; | |||
| @@ -23,3 +27,23 @@ export const 駐車場マスタ一覧取得 = async ( | |||
| }); | |||
| return res; | |||
| }; | |||
| // -------サービス券マスタ一覧取得--------------- | |||
| export type サービス券マスタ一覧取得Request = { | |||
| parking_management_code: string; | |||
| }; | |||
| 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; | |||
| }; | |||
| @@ -12,9 +12,10 @@ export type 店舗 = { | |||
| }; | |||
| export type QRサービス券認証設定 = { | |||
| shop_no: number; | |||
| parking_management_code: string; | |||
| parking_name: string; | |||
| discount_ticket_code: number; | |||
| discount_ticket_code: number | null; | |||
| }; | |||
| export type QRサービス券取得設定 = { | |||
| qr_service_parking_group_id: string; | |||
| @@ -140,6 +141,95 @@ export const 店舗QR設定取得 = async (param: 店舗QR設定取得Request) = | |||
| return res; | |||
| }; | |||
| // -------店舗QR設定認証設定新規登録--------------- | |||
| export type 店舗QR設定認証設定新規登録Request = { | |||
| shop_id: string; | |||
| parking_management_code: string; | |||
| shop_no: 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 = { | |||
| shop_id: string; | |||
| parking_management_code: string; | |||
| shop_no: 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 = { | |||
| shop_id: string; | |||
| parking_management_code: string; | |||
| discount_ticket_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 = { | |||
| shop_id: string; | |||
| parking_management_code: string; | |||
| discount_ticket_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 = { | |||
| shop_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 = { | |||
| shop_id: string; | |||
| @@ -24,6 +24,7 @@ const urls = { | |||
| // 駐車場関連 ---------------------------------- | |||
| [A.駐車場マスタ一覧取得]: "parking/list", | |||
| [A.サービス券マスタ一覧取得]: "parking/discount-ticket/list", | |||
| // 店舗関連関連 ---------------------------------- | |||
| [A.店舗一覧取得]: "shop/list", | |||
| @@ -33,8 +34,11 @@ const urls = { | |||
| [A.店舗設定]: "shop/config", | |||
| [A.店舗設定]: "shop/config", | |||
| [A.店舗QR設定取得]: "shop/config/detail", | |||
| [A.店舗QR設定認証設定新規登録]: "shop/config/certification/register", | |||
| [A.店舗QR設定認証設定更新]: "shop/config/certification/update", | |||
| [A.店舗QR設定認証設定追加]: "shop/config/certification/add", | |||
| [A.店舗QR設定認証設定削除]: "shop/config/certification/remove", | |||
| [A.店舗QR設定認証設定全削除]: "shop/config/certification/delete", | |||
| [A.店舗QR設定取得設定変更]: "shop/config/acquisition/enable", | |||
| [A.店舗QR設定取得設定無効化]: "shop/config/acquisition/disable", | |||
| @@ -1,4 +1,5 @@ | |||
| import { HasChildren } from "@types"; | |||
| import { 駐車場マスタ } from "api/parking"; | |||
| import { | |||
| QRサービス券取得設定, | |||
| QRサービス券認証設定, | |||
| @@ -15,11 +16,13 @@ import { PageID, TabID } from "pages"; | |||
| import { createContext, useContext, useEffect, useState } from "react"; | |||
| import { useParams } from "react-router-dom"; | |||
| import { getPath } from "routes/path"; | |||
| import 駐車場マスタストア from "storage/cache/駐車場マスタ"; | |||
| type Context = { | |||
| shop: 店舗 | null; | |||
| certificationSetting: QRサービス券認証設定[]; | |||
| acquisitionSetting: QRサービス券取得設定 | null; | |||
| parkings: 駐車場マスタ[]; | |||
| fetch: () => Promise<void>; | |||
| moveToMain: VoidFunction; | |||
| }; | |||
| @@ -28,6 +31,7 @@ export const 店舗詳細Context = createContext<Context>({ | |||
| shop: null, | |||
| certificationSetting: [], | |||
| acquisitionSetting: null, | |||
| parkings: [], | |||
| fetch: async () => {}, | |||
| moveToMain: () => {}, | |||
| }); | |||
| @@ -37,6 +41,7 @@ function 店舗詳細ContextProvider({ children }: Props) { | |||
| const { shopId: paramShopId } = useParams(); | |||
| const [shop, setShop] = useState<店舗 | null>(null); | |||
| const [parkings, setParkings] = useState<駐車場マスタ[]>([]); | |||
| const [certificationSetting, setCertificationSetting] = useState< | |||
| QRサービス券認証設定[] | |||
| >([]); | |||
| @@ -105,12 +110,19 @@ function 店舗詳細ContextProvider({ children }: Props) { | |||
| fetch(); | |||
| }, []); | |||
| useEffect(() => { | |||
| 駐車場マスタストア.get().then((parkings) => { | |||
| setParkings(parkings); | |||
| }); | |||
| }, []); | |||
| return ( | |||
| <店舗詳細Context.Provider | |||
| value={{ | |||
| shop, | |||
| certificationSetting, | |||
| acquisitionSetting, | |||
| parkings, | |||
| fetch, | |||
| moveToMain, | |||
| }} | |||
| @@ -3,19 +3,22 @@ import { 店舗詳細Context } from "contexts/page/dashboard/shop/店舗詳細Co | |||
| import useDashboard from "hooks/useDashBoard"; | |||
| import { PageID, TabID } from "pages"; | |||
| import { useContext } from "react"; | |||
| import 駐車場一覧 from "./駐車場一覧"; | |||
| import 駐車場追加 from "./駐車場追加"; | |||
| import AddParking from "./駐車場追加"; | |||
| import ParkingList from "./駐車場一覧"; | |||
| export default function Page() { | |||
| const {} = useDashboard(PageID.店舗詳細, TabID.店舗詳細_QR認証設定); | |||
| const {} = useContext(店舗詳細Context); | |||
| const { shop } = useContext(店舗詳細Context); | |||
| if (!shop) { | |||
| return null; | |||
| } | |||
| return ( | |||
| <Box> | |||
| <Stack spacing={2}> | |||
| <駐車場一覧 /> | |||
| <駐車場追加 /> | |||
| <AddParking /> | |||
| <ParkingList /> | |||
| </Stack> | |||
| </Box> | |||
| ); | |||
| @@ -1,99 +0,0 @@ | |||
| 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,98 @@ | |||
| import { Box, Card, Stack, Typography } from "@mui/material"; | |||
| import { QRサービス券認証設定, 店舗QR設定認証設定全削除 } from "api/shop"; | |||
| import { 店舗詳細Context } from "contexts/page/dashboard/shop/店舗詳細Context"; | |||
| import useAPICall from "hooks/useAPICall"; | |||
| import { useDialog } from "hooks/useDialog"; | |||
| import useSnackbarCustom from "hooks/useSnackbarCustom"; | |||
| import { has } from "lodash"; | |||
| import { useContext, useEffect, useMemo, useState } from "react"; | |||
| import RowData from "./駐車場設定"; | |||
| type 駐車場ごと設定 = { | |||
| [parking_management_code: string]: QRサービス券認証設定[]; | |||
| }; | |||
| export default function Page() { | |||
| const { shop, fetch, certificationSetting } = useContext(店舗詳細Context); | |||
| const { success, error } = useSnackbarCustom(); | |||
| const 駐車場ごと設定: 駐車場ごと設定 = useMemo(() => { | |||
| const ret: 駐車場ごと設定 = {}; | |||
| certificationSetting.forEach((ele) => { | |||
| if (has(ret, ele.parking_management_code)) { | |||
| ret[ele.parking_management_code].push(ele); | |||
| } else { | |||
| ret[ele.parking_management_code] = [ele]; | |||
| } | |||
| }); | |||
| return ret; | |||
| }, [certificationSetting]); | |||
| const { callAPI: call店舗QR設定認証設定全削除 } = useAPICall({ | |||
| apiMethod: 店舗QR設定認証設定全削除, | |||
| backDrop: true, | |||
| onSuccess: () => { | |||
| fetch(); | |||
| success("削除しました"); | |||
| }, | |||
| onFailed: () => { | |||
| error("失敗しました"); | |||
| }, | |||
| }); | |||
| const [ | |||
| tmpDeleteTargetParkingMangementCode, | |||
| setTmpDeleteTargetParkingMangementCode, | |||
| ] = useState(""); | |||
| const deleteParkingSetting = (parkingManagementCode: string) => { | |||
| setTmpDeleteTargetParkingMangementCode(parkingManagementCode); | |||
| OpenDeleteConfirmDialog(); | |||
| }; | |||
| const { | |||
| isAgree, | |||
| element: dialog, | |||
| open: OpenDeleteConfirmDialog, | |||
| } = useDialog({ | |||
| message: "削除しますか", | |||
| }); | |||
| useEffect(() => { | |||
| if ( | |||
| isAgree === true && | |||
| tmpDeleteTargetParkingMangementCode && | |||
| shop !== null | |||
| ) { | |||
| call店舗QR設定認証設定全削除({ | |||
| shop_id: shop.shop_id, | |||
| parking_management_code: tmpDeleteTargetParkingMangementCode, | |||
| }); | |||
| } | |||
| }, [isAgree, tmpDeleteTargetParkingMangementCode, shop]); | |||
| return ( | |||
| <Card sx={{ p: 2 }} elevation={1}> | |||
| <Stack spacing={2}> | |||
| <Typography variant="h6">駐車場ごと設定</Typography> | |||
| <Box> | |||
| {Object.keys(駐車場ごと設定).map((parkingManagementCode) => { | |||
| const setting = 駐車場ごと設定[parkingManagementCode]; | |||
| return ( | |||
| <RowData | |||
| key={parkingManagementCode} | |||
| settings={setting} | |||
| deleteParkingSetting={deleteParkingSetting} | |||
| /> | |||
| ); | |||
| })} | |||
| {Object.keys(駐車場ごと設定).length === 0 && ( | |||
| <Typography>データなし</Typography> | |||
| )} | |||
| </Box> | |||
| </Stack> | |||
| {dialog} | |||
| </Card> | |||
| ); | |||
| } | |||
| @@ -0,0 +1,76 @@ | |||
| import { Button, Grid, Typography } from "@mui/material"; | |||
| import { サービス券マスタ } from "api/parking"; | |||
| import { QRサービス券認証設定, 店舗QR設定認証設定削除 } from "api/shop"; | |||
| import { 店舗詳細Context } from "contexts/page/dashboard/shop/店舗詳細Context"; | |||
| import useAPICall from "hooks/useAPICall"; | |||
| import useSnackbarCustom from "hooks/useSnackbarCustom"; | |||
| import { useContext, useMemo } from "react"; | |||
| import { sprintf } from "sprintf-js"; | |||
| type DiscountTicketProps = { | |||
| setting: QRサービス券認証設定; | |||
| discountTickets: サービス券マスタ[]; | |||
| }; | |||
| export default function Page({ | |||
| setting, | |||
| discountTickets, | |||
| }: DiscountTicketProps) { | |||
| const { shop, fetch } = useContext(店舗詳細Context); | |||
| const { success, error } = useSnackbarCustom(); | |||
| const { callAPI: call店舗QR設定認証設定削除 } = useAPICall({ | |||
| apiMethod: 店舗QR設定認証設定削除, | |||
| backDrop: true, | |||
| onSuccess: () => { | |||
| fetch(); | |||
| success("削除しました"); | |||
| }, | |||
| onFailed: () => { | |||
| error("失敗しました"); | |||
| }, | |||
| }); | |||
| const discountTikcetName = useMemo(() => { | |||
| const target = discountTickets.find((ele) => { | |||
| return ele.discount_ticket_code === setting.discount_ticket_code; | |||
| }); | |||
| return sprintf( | |||
| "%s(%d)", | |||
| target?.ticket_name ?? "", | |||
| setting.discount_ticket_code | |||
| ); | |||
| }, [discountTickets, setting]); | |||
| const handleRemove = () => { | |||
| if (shop === null) return; | |||
| call店舗QR設定認証設定削除({ | |||
| shop_id: String(shop.shop_id), | |||
| parking_management_code: setting.parking_management_code, | |||
| discount_ticket_code: String(setting.discount_ticket_code), | |||
| }); | |||
| }; | |||
| if (setting.discount_ticket_code === null) { | |||
| return null; | |||
| } | |||
| return ( | |||
| <Grid | |||
| container | |||
| sx={{ | |||
| borderBottom: "solid 0.5px", | |||
| borderBottomColor: "#a9a9a9", | |||
| }} | |||
| > | |||
| <Grid item xs={9}> | |||
| <Typography>{discountTikcetName}</Typography> | |||
| </Grid> | |||
| <Grid item xs={3}> | |||
| <Button color="error" onClick={handleRemove}> | |||
| 削除 | |||
| </Button> | |||
| </Grid> | |||
| </Grid> | |||
| ); | |||
| } | |||
| @@ -0,0 +1,205 @@ | |||
| import DeleteForeverIcon from "@mui/icons-material/DeleteForever"; | |||
| import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; | |||
| import { | |||
| Accordion, | |||
| AccordionDetails, | |||
| AccordionSummary, | |||
| Box, | |||
| Button, | |||
| Grid, | |||
| IconButton, | |||
| Stack, | |||
| Typography, | |||
| } from "@mui/material"; | |||
| import { サービス券マスタ, サービス券マスタ一覧取得 } from "api/parking"; | |||
| import { | |||
| QRサービス券認証設定, | |||
| 店舗QR設定認証設定更新, | |||
| 店舗QR設定認証設定追加, | |||
| } from "api/shop"; | |||
| import { FormProvider, RHFTextField } from "components/hook-form"; | |||
| import RHFAutoComplete, { | |||
| AutoCompleteOption, | |||
| AutoCompleteOptionType, | |||
| getValue, | |||
| } from "components/hook-form/RHFAutoComplete"; | |||
| import { 店舗詳細Context } from "contexts/page/dashboard/shop/店舗詳細Context"; | |||
| import useAPICall from "hooks/useAPICall"; | |||
| import useSnackbarCustom from "hooks/useSnackbarCustom"; | |||
| import { useContext, useEffect, useMemo, useState } from "react"; | |||
| import { useForm } from "react-hook-form"; | |||
| import { sprintf } from "sprintf-js"; | |||
| import DiscountTicket from "./サービス券"; | |||
| type FormProps = { | |||
| shop_no: string; | |||
| discount_ticket_code: AutoCompleteOptionType; | |||
| }; | |||
| type RowProps = { | |||
| settings: QRサービス券認証設定[]; | |||
| deleteParkingSetting: (parkingManagementCode: string) => void; | |||
| }; | |||
| export default function Page({ settings, deleteParkingSetting }: RowProps) { | |||
| const { shop, fetch } = useContext(店舗詳細Context); | |||
| const { success, error } = useSnackbarCustom(); | |||
| const { parking_name, parking_management_code, shop_no } = settings[0]; | |||
| const [サービス券マスタ, setサービス券マスタ] = useState<サービス券マスタ[]>( | |||
| [] | |||
| ); | |||
| const form = useForm<FormProps>({ | |||
| defaultValues: { | |||
| shop_no: String(shop_no), | |||
| discount_ticket_code: null, | |||
| }, | |||
| }); | |||
| const { callAPI: callサービス券マスタ一覧取得 } = useAPICall({ | |||
| apiMethod: サービス券マスタ一覧取得, | |||
| onSuccess: ({ data }) => { | |||
| setサービス券マスタ(data.list); | |||
| }, | |||
| }); | |||
| const { callAPI: call店舗QR設定認証設定更新 } = useAPICall({ | |||
| apiMethod: 店舗QR設定認証設定更新, | |||
| form, | |||
| backDrop: true, | |||
| onSuccess: () => { | |||
| fetch(); | |||
| success("変更しました"); | |||
| }, | |||
| onFailed: () => { | |||
| error("失敗しました"); | |||
| }, | |||
| }); | |||
| const { callAPI: call店舗QR設定認証設定追加 } = useAPICall({ | |||
| apiMethod: 店舗QR設定認証設定追加, | |||
| form, | |||
| backDrop: true, | |||
| onSuccess: () => { | |||
| fetch(); | |||
| success("追加しました"); | |||
| form.setValue("discount_ticket_code", null); | |||
| }, | |||
| onFailed: () => { | |||
| error("失敗しました"); | |||
| }, | |||
| }); | |||
| const options: AutoCompleteOption[] = useMemo(() => { | |||
| return サービス券マスタ | |||
| .filter( | |||
| (ele) => | |||
| !settings.find( | |||
| (s) => s.discount_ticket_code === ele.discount_ticket_code | |||
| ) | |||
| ) | |||
| .map((ele) => ({ | |||
| label: sprintf("%s(%d)", ele.ticket_name, ele.discount_ticket_code), | |||
| value: String(ele.discount_ticket_code), | |||
| })); | |||
| }, [サービス券マスタ, settings]); | |||
| const handleUpdate = () => { | |||
| if (shop === null) return; | |||
| call店舗QR設定認証設定更新({ | |||
| ...form.getValues(), | |||
| shop_id: String(shop.shop_id), | |||
| parking_management_code, | |||
| }); | |||
| }; | |||
| const handleAdd = () => { | |||
| if (shop === null) return; | |||
| call店舗QR設定認証設定追加({ | |||
| shop_id: String(shop.shop_id), | |||
| parking_management_code, | |||
| discount_ticket_code: getValue(form.getValues("discount_ticket_code")), | |||
| }); | |||
| }; | |||
| const handleDelete = () => { | |||
| deleteParkingSetting(parking_management_code); | |||
| }; | |||
| useEffect(() => { | |||
| callサービス券マスタ一覧取得({ | |||
| parking_management_code: parking_management_code, | |||
| }); | |||
| }, []); | |||
| return ( | |||
| <FormProvider methods={form}> | |||
| <Accordion square={true}> | |||
| <AccordionSummary | |||
| expandIcon={<ExpandMoreIcon />} | |||
| aria-controls="panel2-content" | |||
| id="panel2-header" | |||
| sx={{ backgroundColor: "#b0e0e6" }} | |||
| > | |||
| {parking_name} | |||
| <IconButton | |||
| size="small" | |||
| sx={{ marginLeft: "auto" }} | |||
| onClick={(event) => { | |||
| event.stopPropagation(); | |||
| handleDelete(); | |||
| }} | |||
| > | |||
| <DeleteForeverIcon /> | |||
| </IconButton> | |||
| </AccordionSummary> | |||
| <AccordionDetails> | |||
| <Grid container columnSpacing={2}> | |||
| <Grid item xs={7}> | |||
| <Stack spacing={1}> | |||
| <Box> | |||
| <Typography>店舗コード</Typography> | |||
| <Grid container columnSpacing={1}> | |||
| <Grid item xs={8}> | |||
| <RHFTextField name="shop_no" /> | |||
| </Grid> | |||
| <Grid item xs={4}> | |||
| <Button onClick={handleUpdate}>更新</Button> | |||
| </Grid> | |||
| </Grid> | |||
| </Box> | |||
| <Box> | |||
| <Typography>サービス券コード</Typography> | |||
| <Grid container columnSpacing={1}> | |||
| <Grid item xs={8}> | |||
| <RHFAutoComplete | |||
| size="small" | |||
| name="discount_ticket_code" | |||
| options={options} | |||
| /> | |||
| </Grid> | |||
| <Grid item xs={4}> | |||
| <Button onClick={handleAdd}>追加</Button> | |||
| </Grid> | |||
| </Grid> | |||
| </Box> | |||
| </Stack> | |||
| </Grid> | |||
| <Grid item xs={5}> | |||
| <Stack> | |||
| {settings | |||
| .filter((ele) => ele.discount_ticket_code !== null) | |||
| .map((ele, index) => ( | |||
| <DiscountTicket | |||
| key={index} | |||
| setting={ele} | |||
| discountTickets={サービス券マスタ} | |||
| /> | |||
| ))} | |||
| </Stack> | |||
| </Grid> | |||
| </Grid> | |||
| </AccordionDetails> | |||
| </Accordion> | |||
| </FormProvider> | |||
| ); | |||
| } | |||
| @@ -1,49 +1,57 @@ | |||
| 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 { 駐車場マスタ } from "api/parking"; | |||
| import { 店舗QR設定認証設定新規登録 } from "api/shop"; | |||
| import { | |||
| FormProvider, | |||
| RHFAutoComplete, | |||
| RHFTextField, | |||
| } 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 { 店舗詳細Context } from "contexts/page/dashboard/shop/店舗詳細Context"; | |||
| import useAPICall from "hooks/useAPICall"; | |||
| import useSnackbarCustom from "hooks/useSnackbarCustom"; | |||
| import { useContext, useMemo } from "react"; | |||
| import { useContext, useEffect, useMemo, useState } from "react"; | |||
| import { useForm } from "react-hook-form"; | |||
| import { object } from "yup"; | |||
| import { number, object } from "yup"; | |||
| type FormProps = { | |||
| parking_management_code: AutoCompleteOptionType; | |||
| shop_no: string; | |||
| }; | |||
| export default function 駐車場追加() { | |||
| const { fetch, selectedGroup, parkings } = useContext( | |||
| QRサービス券駐車場グループ管理Context | |||
| ); | |||
| const { shop, fetch, moveToMain, certificationSetting, parkings } = | |||
| useContext(店舗詳細Context); | |||
| const { success, error } = useSnackbarCustom(); | |||
| const form = useForm<FormProps>({ | |||
| defaultValues: { | |||
| parking_management_code: null, | |||
| shop_no: "", | |||
| }, | |||
| resolver: yupResolver( | |||
| object().shape({ | |||
| parking_management_code: object().required("必須項目です"), | |||
| shop_no: number().typeError("数値を入力してください"), | |||
| }) | |||
| ), | |||
| }); | |||
| const { callAPI: callQRサービス券駐車場グループ駐車場追加登録 } = useAPICall({ | |||
| apiMethod: QRサービス券駐車場グループ駐車場追加登録, | |||
| const { callAPI: call店舗QR設定認証設定新規登録 } = useAPICall({ | |||
| apiMethod: 店舗QR設定認証設定新規登録, | |||
| backDrop: true, | |||
| form, | |||
| onSuccess: () => { | |||
| success("追加しました"); | |||
| success("登録しました"); | |||
| fetch(); | |||
| form.setValue("parking_management_code", null); | |||
| form.setValue("shop_no", ""); | |||
| }, | |||
| onFailed: () => { | |||
| error("失敗しました"); | |||
| @@ -54,7 +62,7 @@ export default function 駐車場追加() { | |||
| return parkings | |||
| .filter( | |||
| (p) => | |||
| !selectedGroup?.parkings.find( | |||
| !certificationSetting.find( | |||
| (ele) => ele.parking_management_code === p.parking_management_code | |||
| ) | |||
| ) | |||
| @@ -62,14 +70,14 @@ export default function 駐車場追加() { | |||
| label: p.parking_name, | |||
| value: p.parking_management_code, | |||
| })); | |||
| }, [parkings, selectedGroup]); | |||
| }, [parkings, certificationSetting]); | |||
| const handleSubmit = (data: FormProps) => { | |||
| if (selectedGroup === null) return; | |||
| const parkingManagementCode = getValue(data.parking_management_code); | |||
| callQRサービス券駐車場グループ駐車場追加登録({ | |||
| id: selectedGroup.id, | |||
| parking_management_code: parkingManagementCode, | |||
| if (shop === null) return; | |||
| call店舗QR設定認証設定新規登録({ | |||
| ...data, | |||
| parking_management_code: getValue(data.parking_management_code), | |||
| shop_id: shop?.shop_id, | |||
| }); | |||
| }; | |||
| @@ -80,7 +88,7 @@ export default function 駐車場追加() { | |||
| <Stack spacing={2}> | |||
| <Typography variant="h6">駐車場追加</Typography> | |||
| <StackRow> | |||
| <Grid container columnGap={2}> | |||
| <Grid container columnSpacing={2}> | |||
| <Grid item xs={12} md={6}> | |||
| <Typography>駐車場</Typography> | |||
| <StackRow> | |||
| @@ -93,6 +101,16 @@ export default function 駐車場追加() { | |||
| </Grid> | |||
| </Grid> | |||
| </StackRow> | |||
| <StackRow> | |||
| <Grid container columnSpacing={2}> | |||
| <Grid item xs={12} md={6}> | |||
| <Typography>店舗番号</Typography> | |||
| <StackRow> | |||
| <RHFTextField type="number" name="shop_no" /> | |||
| </StackRow> | |||
| </Grid> | |||
| </Grid> | |||
| </StackRow> | |||
| <StackRow> | |||
| <Button type="submit" variant="contained"> | |||
| 追加 | |||