diff --git a/src/api/index.ts b/src/api/index.ts index f08ad44..cf56d04 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -16,6 +16,11 @@ export const ApiId = { SEASON_TICKET_CONTRACTS: id++, PAYMENT_PLANS: id++, + + STICKER_RE_ORDER: id++, + PARKING_CERTIFICATE_ORDER: id++, + SEASON_TICKET_CONTRACT_TERMINATE_ORDER: id++, + UPDATE_VEHICLE_INFO_ORDER: id++, } as const; export type ApiId = (typeof ApiId)[keyof typeof ApiId]; diff --git a/src/api/season-ticket-contract.ts b/src/api/season-ticket-contract.ts index 8d43fea..935b372 100644 --- a/src/api/season-ticket-contract.ts +++ b/src/api/season-ticket-contract.ts @@ -26,7 +26,6 @@ export type PaymentPlan = { type SeasonTicketContractsResponse = { data: SeasonTicketContract[]; } & APICommonResponse; - export const getSeasonTicketContracts = async () => { const res = await request({ url: getUrl(ApiId.SEASON_TICKET_CONTRACTS), @@ -39,11 +38,9 @@ export const getSeasonTicketContracts = async () => { type PaymentPlansRequest = { season_ticket_contract_record_no: string; }; - type PaymentPlansResponse = { data: PaymentPlan[]; } & APICommonResponse; - export const getPaymentPlans = async (data: PaymentPlansRequest) => { const res = await request({ url: getUrl(ApiId.PAYMENT_PLANS), @@ -52,3 +49,71 @@ export const getPaymentPlans = async (data: PaymentPlansRequest) => { }); return res; }; + +// -------シール再発行依頼------------------ +type StickerReOrderRequest = { + season_ticket_contract_record_no: string; +}; +export const reOrderSticker = async (data: StickerReOrderRequest) => { + const res = await request({ + url: getUrl(ApiId.STICKER_RE_ORDER), + method: HttpMethod.POST, + data: makeParam(data), + }); + return res; +}; + +// -------車庫証明発行依頼------------------ +type ParkingCertificateOrderRequest = { + season_ticket_contract_record_no: string; + date: Date; + reason: string; + reson_other: string; + opinion: string; + memo: string; +}; +export const orderParkingCertificate = async ( + data: ParkingCertificateOrderRequest +) => { + const res = await request({ + url: getUrl(ApiId.PARKING_CERTIFICATE_ORDER), + method: HttpMethod.POST, + data: makeParam(data), + }); + return res; +}; + +// -------解約依頼------------------ +type TerminateOrderRequest = { + season_ticket_contract_record_no: string; + date: Date; + reason: string; + other_reason: string; + opinion: string; + memo: string; +}; +export const orderSeasonTicketContractTerminate = async ( + data: TerminateOrderRequest +) => { + const res = await request({ + url: getUrl(ApiId.SEASON_TICKET_CONTRACT_TERMINATE_ORDER), + method: HttpMethod.POST, + data: makeParam(data), + }); + return res; +}; + +// -------車両情報変更依頼------------------ +type UpdateVehicleInfoOrderRequest = { + season_ticket_contract_record_no: string; +}; +export const orderUpdateVehicleInfo = async ( + data: UpdateVehicleInfoOrderRequest +) => { + const res = await request({ + url: getUrl(ApiId.UPDATE_VEHICLE_INFO_ORDER), + method: HttpMethod.POST, + data: makeParam(data), + }); + return res; +}; diff --git a/src/api/url.ts b/src/api/url.ts index 1859db4..d28d5f6 100644 --- a/src/api/url.ts +++ b/src/api/url.ts @@ -8,6 +8,13 @@ const urls = { [A.LOGOUT]: "logout", [A.SEASON_TICKET_CONTRACTS]: "season-ticket-contracts", [A.PAYMENT_PLANS]: "season-ticket-contract/payment-plans", + [A.STICKER_RE_ORDER]: "season-ticket-contract/sticker-re-order", + [A.PARKING_CERTIFICATE_ORDER]: + "season-ticket-contract/parking-certificate-order", + [A.SEASON_TICKET_CONTRACT_TERMINATE_ORDER]: + "season-ticket-contract/termination-order", + [A.UPDATE_VEHICLE_INFO_ORDER]: + "season-ticket-contract/update-vehicle-info-order", }; const prefixs = { diff --git a/src/components/hook-form/RHFCheckbox.tsx b/src/components/hook-form/RHFCheckbox.tsx index 4e6b462..8e921a4 100644 --- a/src/components/hook-form/RHFCheckbox.tsx +++ b/src/components/hook-form/RHFCheckbox.tsx @@ -6,6 +6,7 @@ import { FormControlLabel, FormGroup, FormControlLabelProps, + Typography, } from "@mui/material"; import { useMemo } from "react"; @@ -116,7 +117,7 @@ export function RHFMultiCheckbox({ onChange={() => field.onChange(onSelected(option.value))} /> } - label={option.label} + label={{option.label}} {...other} /> ))} diff --git a/src/pages/dashboard/contract/detail.tsx b/src/pages/dashboard/contract/detail.tsx index 80fb5ea..f0155ee 100644 --- a/src/pages/dashboard/contract/detail.tsx +++ b/src/pages/dashboard/contract/detail.tsx @@ -130,15 +130,37 @@ export default function ContractDetail() { 各種申請 - + - + - + diff --git a/src/pages/dashboard/contract/sticker-re-order.tsx b/src/pages/dashboard/contract/sticker-re-order.tsx new file mode 100644 index 0000000..f214208 --- /dev/null +++ b/src/pages/dashboard/contract/sticker-re-order.tsx @@ -0,0 +1,131 @@ +import { Box, Button, Stack, Typography } from "@mui/material"; +import { HasChildren } from "@types"; +import { reOrderSticker } from "api/season-ticket-contract"; +import { FormProvider, RHFTextField } from "components/hook-form"; +import { useSeasonTicketContractContext } from "contexts/dashboard/SeasonTicketContractContext"; +import useAPICall from "hooks/useAPICall"; +import useDashboard from "hooks/useDashBoard"; +import useNavigateCustom from "hooks/useNavigateCustom"; +import useSnackbarCustom from "hooks/useSnackbarCustom"; +import { PageID, TabID } from "pages"; +import { useEffect, useState } from "react"; +import { useForm } from "react-hook-form"; +import { getPath } from "routes/path"; + +type AreaBoxProps = { + label: string; +} & HasChildren; +function AreaBox({ label, children }: AreaBoxProps) { + return ( + + {label} + {children} + + ); +} + +type FormProps = {}; + +export default function StickerReOrder() { + const { setHeaderTitle, setTabs } = useDashboard( + PageID.DASHBOARD_SEASON_TICKET_CONTRACT_STICKER_RE_ORDER, + TabID.NONE + ); + + const form = useForm({}); + + const { navigateWhenChanged, navigate } = useNavigateCustom(); + + const { error } = useSnackbarCustom(); + + const { selectedseasonTicketContract } = useSeasonTicketContractContext(); + + const [done, setDone] = useState(false); + + const { callAPI: callReOrderSticker } = useAPICall({ + apiMethod: reOrderSticker, + backDrop: true, + onSuccess: () => { + setDone(true); + }, + onFailed: () => { + error("依頼失敗しました"); + }, + }); + + const handleSubmit = () => { + if (selectedseasonTicketContract === null) return; + callReOrderSticker({ + season_ticket_contract_record_no: + selectedseasonTicketContract.season_ticekt_contract_record_no ?? "", + }); + }; + + useEffect(() => { + setHeaderTitle("シール再発行依頼"); + setTabs(null); + }, [setHeaderTitle, setTabs]); + + useEffect(() => { + if (selectedseasonTicketContract === null) { + navigateWhenChanged( + getPath(PageID.DASHBOARD_SEASON_TICKET_CONTRACT_LIST) + ); + } + }, [selectedseasonTicketContract]); + + if (selectedseasonTicketContract === null) { + return null; + } + if (done) { + return ( + + + 依頼しました + + + + + + ); + } + + return ( + + + + + + + + + + + + + + + + + ); +} diff --git a/src/pages/dashboard/contract/terminate-order.tsx b/src/pages/dashboard/contract/terminate-order.tsx new file mode 100644 index 0000000..a170e8c --- /dev/null +++ b/src/pages/dashboard/contract/terminate-order.tsx @@ -0,0 +1,224 @@ +import { Box, Button, Stack, Typography } from "@mui/material"; +import { HasChildren } from "@types"; +import { + orderSeasonTicketContractTerminate, + reOrderSticker, +} from "api/season-ticket-contract"; +import RequireChip from "components/chip/RequireChip"; +import { + FormProvider, + RHFCheckbox, + RHFMultiCheckbox, + RHFSelect, + RHFTextField, +} from "components/hook-form"; +import RHFDatePicker from "components/hook-form/RHFDatePicker"; +import { SelectOptionProps } from "components/hook-form/RHFSelect"; +import StackRow from "components/stack/StackRow"; +import { useSeasonTicketContractContext } from "contexts/dashboard/SeasonTicketContractContext"; +import useAPICall from "hooks/useAPICall"; +import useDashboard from "hooks/useDashBoard"; +import useNavigateCustom from "hooks/useNavigateCustom"; +import useSnackbarCustom from "hooks/useSnackbarCustom"; +import { PageID, TabID } from "pages"; +import { useEffect, useMemo, useState } from "react"; +import { useForm } from "react-hook-form"; +import { getPath } from "routes/path"; + +type AreaBoxProps = { + label: string; + require?: boolean; +} & HasChildren; +function AreaBox({ label, children, require }: AreaBoxProps) { + return ( + + + 〇{label} + + + {children} + + ); +} + +type FormProps = { + date: Date | null; + reason: string[]; + other_reason: string; + opinion: string; + memo: string; +}; + +export default function TerminateOrder() { + const { setHeaderTitle, setTabs } = useDashboard( + PageID.DASHBOARD_SEASON_TICKET_CONTRACT_TERMINATE_ORDER, + TabID.NONE + ); + + const form = useForm({ + defaultValues: { + date: null, + reason: [], + other_reason: "", + opinion: "", + memo: "", + }, + }); + + const { navigateWhenChanged, navigate } = useNavigateCustom(); + + const { error } = useSnackbarCustom(); + + const { selectedseasonTicketContract } = useSeasonTicketContractContext(); + + const [done, setDone] = useState(false); + + const { callAPI: callOrderSeasonTicketContractTerminate } = useAPICall({ + apiMethod: orderSeasonTicketContractTerminate, + backDrop: true, + onSuccess: () => { + setDone(true); + }, + onFailed: () => { + error("依頼失敗しました"); + }, + }); + + const handleSubmit = (data: FormProps) => { + console.log(data); + + if (selectedseasonTicketContract === null) return; + const date = data.date; + if (date === null) return; + + callOrderSeasonTicketContractTerminate({ + ...data, + date, + season_ticket_contract_record_no: + selectedseasonTicketContract.season_ticekt_contract_record_no ?? "", + reason: data.reason.join(","), + }); + }; + + const reasons = useMemo(() => { + return [ + "転居/転勤のため", + "就職/進学/卒業のため", + "料金が高いため", + "支払いが困難なため", + "車/バイク/自転車に乗らなくなったため", + "より良い駐車場/駐輪場が見つかったため", + "駐車場/駐輪場に不満があるため(詳細)", + "その他(詳細)", + ].map((ele, index) => ({ + label: String(index + 1) + "." + String(ele), + value: ele, + })); + }, []); + + useEffect(() => { + setHeaderTitle("解約依頼申請"); + setTabs(null); + }, [setHeaderTitle, setTabs]); + + useEffect(() => { + if (selectedseasonTicketContract === null) { + navigateWhenChanged( + getPath(PageID.DASHBOARD_SEASON_TICKET_CONTRACT_LIST) + ); + } + }, [selectedseasonTicketContract]); + + if (selectedseasonTicketContract === null) { + return null; + } + if (done) { + return ( + + + 依頼しました + + + + + + ); + } + + return ( + + + + + + + + + + + + + 解約の理由についてお聞かせ下さい(複数選択可) + + + + + + + 前質問 7・8を選択された方 詳細を詳しくお聞かせください。 + + + + + + 今後の管理運営に生かすため、ご意見がありましたらご記入ください。 + + + + + + ご不明点等がございましたらご入力ください。お電話またはメールにて回答させていただきます。 + + + + + + + + + + + ); +} diff --git a/src/pages/index.ts b/src/pages/index.ts index 6997749..9e7aa3a 100644 --- a/src/pages/index.ts +++ b/src/pages/index.ts @@ -10,6 +10,10 @@ export const PageID = { DASHBOARD_SEASON_TICKET_CONTRACT_ENTRY: id++, DASHBOARD_SEASON_TICKET_CONTRACT_LIST: id++, DASHBOARD_SEASON_TICKET_CONTRACT_DETAIL: id++, + DASHBOARD_SEASON_TICKET_CONTRACT_STICKER_RE_ORDER: id++, + DASHBOARD_SEASON_TICKET_CONTRACT_PARKING_CERTIFICATE_ORDER: id++, + DASHBOARD_SEASON_TICKET_CONTRACT_TERMINATE_ORDER: id++, + DASHBOARD_SEASON_TICKET_CONTRACT_UPDATE_VEHICLE_INFO_ORDER: id++, DASHBOARD_RECEIPT_DOWNLOAD: id++, diff --git a/src/routes/path.ts b/src/routes/path.ts index 3b17e00..d9c51f4 100644 --- a/src/routes/path.ts +++ b/src/routes/path.ts @@ -37,6 +37,16 @@ const PATHS_DASHBOARD = { "/dashboard/contract/list/:page", [makePathKey(PageID.DASHBOARD_SEASON_TICKET_CONTRACT_DETAIL)]: "/dashboard/contract/detail/:id", + [makePathKey(PageID.DASHBOARD_SEASON_TICKET_CONTRACT_STICKER_RE_ORDER)]: + "/dashboard/contract/sticker-re-order", + [makePathKey( + PageID.DASHBOARD_SEASON_TICKET_CONTRACT_PARKING_CERTIFICATE_ORDER + )]: "/dashboard/contract/parking-certificate-order", + [makePathKey(PageID.DASHBOARD_SEASON_TICKET_CONTRACT_TERMINATE_ORDER)]: + "/dashboard/contract/terminate-order", + [makePathKey( + PageID.DASHBOARD_SEASON_TICKET_CONTRACT_UPDATE_VEHICLE_INFO_ORDER + )]: "/dashboard/contract/update-vehicle-info-order", [makePathKey(PageID.DASHBOARD_RECEIPT_DOWNLOAD)]: "/dashboard/receipt/download", [makePathKey(PageID.DASHBOARD_USER_DETAIL)]: "/dashboard/user/detail", diff --git a/src/routes/sub/dashboard.tsx b/src/routes/sub/dashboard.tsx index aead618..85ffe19 100644 --- a/src/routes/sub/dashboard.tsx +++ b/src/routes/sub/dashboard.tsx @@ -62,6 +62,12 @@ export default function DashboardRoutes(): RouteObject[] { const ContractDetail = Loadable( lazy(() => import("pages/dashboard/contract/detail")) ); + const StickerReOrder = Loadable( + lazy(() => import("pages/dashboard/contract/sticker-re-order")) + ); + const TerminateOrder = Loadable( + lazy(() => import("pages/dashboard/contract/terminate-order")) + ); const allChildren = [ { @@ -72,6 +78,14 @@ export default function DashboardRoutes(): RouteObject[] { pageId: PageID.DASHBOARD_SEASON_TICKET_CONTRACT_DETAIL, element: , }, + { + pageId: PageID.DASHBOARD_SEASON_TICKET_CONTRACT_STICKER_RE_ORDER, + element: , + }, + { + pageId: PageID.DASHBOARD_SEASON_TICKET_CONTRACT_TERMINATE_ORDER, + element: , + }, ]; return allChildren.map(({ pageId, ...others }) => ({ ...others,