From d180ff928c3b21803fc17770d6ce8719078ac613 Mon Sep 17 00:00:00 2001 From: "sosuke.iwabuchi" Date: Wed, 19 Jul 2023 13:26:36 +0900 Subject: [PATCH] =?UTF-8?q?=E5=88=A9=E7=94=A8=E8=A6=8F=E7=B4=84=E7=AD=89?= =?UTF-8?q?=E3=81=AE=E6=9A=AB=E5=AE=9A=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/app/receipt-issuing-order.ts | 22 ++- src/api/index.ts | 1 + src/api/url.ts | 2 + src/codes/page.ts | 1 + src/pages/app/ReceiptIssuingOrder.tsx | 39 ++++-- src/pages/app/hooks/useAcceptPolicies.tsx | 158 ++++++++++++++++++++++ src/pages/common/PrivacyPolicy.tsx | 22 +++ src/routes/index.tsx | 16 ++- src/routes/path.ts | 1 + src/utils/page.ts | 3 + 10 files changed, 248 insertions(+), 17 deletions(-) create mode 100644 src/pages/app/hooks/useAcceptPolicies.tsx create mode 100644 src/pages/common/PrivacyPolicy.tsx create mode 100644 src/utils/page.ts diff --git a/src/api/app/receipt-issuing-order.ts b/src/api/app/receipt-issuing-order.ts index b4fbbfa..9572b32 100644 --- a/src/api/app/receipt-issuing-order.ts +++ b/src/api/app/receipt-issuing-order.ts @@ -17,10 +17,30 @@ export type AppReceiptIssuingOrder = { status_order_mail_datetime?: string; status_mail_post_date?: string; + accept_privacy_policy?: boolean; + accept_correct_entry?: boolean; + accept_site_policy?: boolean; + updated_at: string; }; +// ポリシーへの同意 ------------------------------- +export type AcceptPolicies = { + access_token: string; + accept_privacy_policy: boolean; + accept_correct_entry: boolean; + accept_site_policy: boolean; +} & TimestampRequest; + +export const acceptPolicies = async (data: AcceptPolicies) => { + const res = await request({ + url: getUrl(ApiId.RECEIPT_ISSUING_ORDER_ACCEPT_POLICIES), + method: HttpMethod.POST, + data: makeParam(data), + }); + return res; +}; -// 領収証確定 +// 領収証確定 ------------------------------- export type ConfirmRequest = { access_token: string; receipt_name: string; diff --git a/src/api/index.ts b/src/api/index.ts index d9e6d1b..a47480e 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -16,6 +16,7 @@ export const ApiId = { // APP向け------------------------------------ APP_TOKEN_CHECK: id++, + RECEIPT_ISSUING_ORDER_ACCEPT_POLICIES: id++, RECEIPT_ISSUING_ORDER_CONFIRM: id++, DOWNLOAD_RECEIPT: id++, RECEIPT_ISSUING_ORDER_MAIL_ORDER: id++, diff --git a/src/api/url.ts b/src/api/url.ts index 1c3f793..dc7134e 100644 --- a/src/api/url.ts +++ b/src/api/url.ts @@ -9,6 +9,8 @@ const urls = { [A.CHANGE_CONTRACT]: "change-contract", [A.APP_TOKEN_CHECK]: "app-token-check", + [A.RECEIPT_ISSUING_ORDER_ACCEPT_POLICIES]: + "receipt-issuing-order/accept/policies", [A.RECEIPT_ISSUING_ORDER_CONFIRM]: "receipt-issuing-order/confirm", [A.DOWNLOAD_RECEIPT]: "receipt/download", [A.RECEIPT_ISSUING_ORDER_MAIL_ORDER]: "receipt-issuing-order/mail-order", diff --git a/src/codes/page.ts b/src/codes/page.ts index 83f352f..f7e2cc3 100644 --- a/src/codes/page.ts +++ b/src/codes/page.ts @@ -9,6 +9,7 @@ export const PageID = { APP_RECEIPT_ISSUING_ORDER_INDEX: id++, APP_RECEIPT_ISSUING_ORDER_MAIL_ORDER: id++, APP_RECEIPT_ISSUING_ORDER_EMAIL_ORDER: id++, + APP_PRIVACY_POLICY: id++, DASHBOARD_OVERVIEW: id++, diff --git a/src/pages/app/ReceiptIssuingOrder.tsx b/src/pages/app/ReceiptIssuingOrder.tsx index 7ad24d2..68c25b5 100644 --- a/src/pages/app/ReceiptIssuingOrder.tsx +++ b/src/pages/app/ReceiptIssuingOrder.tsx @@ -1,29 +1,19 @@ import { Box, - Button, Paper, Stack, Table, TableBody, TableCell, - TableHead, TableRow, - TextField, Typography, - styled, } from "@mui/material"; import { HasChildren } from "@types"; -import { ApiId } from "api"; -import { confirm } from "api/app/receipt-issuing-order"; -import { getFullUrl } from "api/url"; -import useAPICall from "hooks/useAPICall"; import useApp from "hooks/useApp"; -import { useDialog } from "hooks/useDialog"; -import useSnackbarCustom from "hooks/useSnackbarCustom"; -import React, { ReactNode, useEffect, useMemo, useRef, useState } from "react"; -import { useParams } from "react-router-dom"; +import { useMemo } from "react"; import { sprintf } from "sprintf-js"; import { formatDateStr, formatDateTimeStr } from "utils/datetime"; +import useAcceptPolicies from "./hooks/useAcceptPolicies"; import useReceiptIssuingOrderConfirm from "./hooks/useReceiptIssuingOrderConfirm"; import useReceiptIssuingOrderSelectHowToGet from "./hooks/useReceiptIssuingOrderSelectHowToGet"; @@ -64,8 +54,18 @@ const Section = ({ title, subtitle, children }: SectionProps) => { export default function ReceiptIssuingOrder() { const { tokenResult, receiptIssuingOrder: order } = useApp(); + const acceptedPolicies = useMemo(() => { + if (!order) return false; + return ( + !!order.accept_privacy_policy && + !!order.accept_correct_entry && + !!order.accept_site_policy + ); + }, [order]); + const confirm = useReceiptIssuingOrderConfirm(); const selectHowToGet = useReceiptIssuingOrderSelectHowToGet(); + const acceptPolicies = useAcceptPolicies(); const tokenExpiresAtStr = useMemo(() => { if (order) { @@ -89,6 +89,9 @@ export default function ReceiptIssuingOrder() { return 不正なアクセス; } + if (acceptedPolicies === false) { + } + return ( <> @@ -131,7 +134,13 @@ export default function ReceiptIssuingOrder() { - {order?.status_order_mail_datetime && ( + {acceptedPolicies === false && ( +
+ {acceptPolicies.element} +
+ )} + + {!!acceptedPolicies && order?.status_order_mail_datetime && (
@@ -142,11 +151,11 @@ export default function ReceiptIssuingOrder() { )} - {confirm.shouldShow && ( + {!!acceptedPolicies && confirm.shouldShow && (
{confirm.element}
)} - {selectHowToGet.shouldShow && ( + {!!acceptedPolicies && selectHowToGet.shouldShow && (
{selectHowToGet.element}
diff --git a/src/pages/app/hooks/useAcceptPolicies.tsx b/src/pages/app/hooks/useAcceptPolicies.tsx new file mode 100644 index 0000000..5addff1 --- /dev/null +++ b/src/pages/app/hooks/useAcceptPolicies.tsx @@ -0,0 +1,158 @@ +import { yupResolver } from "@hookform/resolvers/yup"; +import { Box, Button, Stack, Typography } from "@mui/material"; +import { acceptPolicies, confirm } from "api/app/receipt-issuing-order"; +import { PageID } from "codes/page"; +import { FormProvider, RHFCheckbox, RHFTextField } from "components/hook-form"; +import useAPICall from "hooks/useAPICall"; +import useApp from "hooks/useApp"; +import useBackDrop from "hooks/useBackDrop"; +import { useDialog } from "hooks/useDialog"; +import useSnackbarCustom from "hooks/useSnackbarCustom"; +import { useEffect, useMemo } from "react"; +import { useForm } from "react-hook-form"; +import { getPath } from "routes/path"; +import { sprintf } from "sprintf-js"; +import { scrollToTop } from "utils/page"; +import * as Yup from "yup"; + +type FormProps = { + accept_privacy_policy: boolean; + accept_correct_entry: boolean; + accept_site_policy: boolean; +}; + +const schema = Yup.object().shape({ + accept_privacy_policy: Yup.boolean().test( + "accept", + "同意が必要です", + function (value) { + return !!value; + } + ), + accept_correct_entry: Yup.boolean().test( + "accept", + "同意が必要です", + function (value) { + return !!value; + } + ), + accept_site_policy: Yup.boolean().test( + "accept", + "同意が必要です", + function (value) { + return !!value; + } + ), +}); + +export default function useAcceptPolicies() { + const { receiptIssuingOrder: order, fetch, token } = useApp(); + const { success, error } = useSnackbarCustom(); + + const form = useForm({ + defaultValues: { + accept_privacy_policy: false, + accept_correct_entry: false, + accept_site_policy: false, + }, + resolver: yupResolver(schema), + }); + + const acceptPrivacyPolicy = form.watch("accept_privacy_policy"); + const acceptCorrectEntry = form.watch("accept_correct_entry"); + const acceptSitePolicy = form.watch("accept_site_policy"); + + const canSubmit = useMemo(() => { + return acceptPrivacyPolicy && acceptCorrectEntry && acceptSitePolicy; + }, [acceptPrivacyPolicy, acceptCorrectEntry, acceptSitePolicy]); + + const shouldShow = useMemo(() => { + return !order?.confirmed; + }, [order]); + + const { callAPI } = useAPICall({ + apiMethod: acceptPolicies, + backDrop: true, + onSuccess: () => { + fetch(); + scrollToTop(); + }, + onFailed: () => { + error("失敗しました"); + }, + }); + + const privacyPolicyUrl: string = useMemo(() => { + return getPath(PageID.APP_PRIVACY_POLICY); + }, []); + + const handleSubmit = () => { + if (!order) return; + callAPI({ + ...form.getValues(), + access_token: token, + timestamp: order.updated_at, + }); + }; + + const element = ( + { + console.log({ e }); + })} + > + + + + + + + 個人情報保護方針 + + への同意 + + + + + + <注意事項> + + ・申込内容に誤りがある場合は、恐れ入りますが改めて発行依頼申込を行ってください。 + + + ・WEB上で領収証PDFをダウンロード可能です。 + + + ・郵送を希望する場合、到着までに時間を要します。お急ぎの場合はダウンロードやEmail送付をご利用ください。 + + + + + 申請内容に虚偽・誤りが無いことへの同意 + + } + name="accept_correct_entry" + /> + + + + + + + ); + + return { + element, + shouldShow, + }; +} diff --git a/src/pages/common/PrivacyPolicy.tsx b/src/pages/common/PrivacyPolicy.tsx new file mode 100644 index 0000000..591199d --- /dev/null +++ b/src/pages/common/PrivacyPolicy.tsx @@ -0,0 +1,22 @@ +import { Box, Stack, Typography } from "@mui/material"; + +export default function PrivacyPolicy() { + return ( + + + + 個人情報保護方針 + + + + 1.個人譲歩の取得/利用/提供 + + + お客さまの個人情報の取得は、適法かつ公正な手段によってこれを行い、個人情報の利用目的等の必要事項について取得時に明示するか、当社ウェブサイト等にて告知します。適正な手続きのもと、利用目的の範囲で個人情報の取り扱いをいたします。 + また、個人情報を第三者に提供・開示等する場合は、法令の定める手続きに則って行います。 + + + + + ); +} diff --git a/src/routes/index.tsx b/src/routes/index.tsx index bbbf911..3ff435d 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -1,5 +1,4 @@ import { PageID } from "codes/page"; -import { UserRole } from "codes/user"; import LoadingScreen from "components/LoadingScreen"; import { AppContextProvider } from "contexts/AppContext"; import useAuth from "hooks/useAuth"; @@ -17,6 +16,16 @@ const Loadable = (Component: ElementType) => (props: any) => { ); }; +const CommonRoutes = (): RouteObject => ({ + element: , + children: [ + { + path: getRoute(PageID.APP_PRIVACY_POLICY), + element: , + }, + ], +}); + const AuthRoutes = (): RouteObject => ({ element: , children: [ @@ -133,6 +142,7 @@ const DashboardRoutes = (): RouteObject => { export function Routes() { const { initialized } = useAuth(); return useRoutes([ + CommonRoutes(), AuthRoutes(), AppRoutes(), DashboardRoutes(), @@ -214,5 +224,9 @@ const ChangePassword = Loadable( ); // その他 --------------------------------- + +const PrivacyPolicy = Loadable( + lazy(() => import("pages/common/PrivacyPolicy")) +); const Page403 = Loadable(lazy(() => import("pages/common/Page403"))); const Page404 = Loadable(lazy(() => import("pages/common/Page404"))); diff --git a/src/routes/path.ts b/src/routes/path.ts index 52185b3..38ce0cf 100644 --- a/src/routes/path.ts +++ b/src/routes/path.ts @@ -45,6 +45,7 @@ const PATHS = { "/app/receipt-issuing-order/mail", [makePathKey(PageID.APP_RECEIPT_ISSUING_ORDER_EMAIL_ORDER)]: "/app/receipt-issuing-order/email", + [makePathKey(PageID.APP_PRIVACY_POLICY)]: "/app/privacy-policy", // 契約関連 [makePathKey(PageID.DASHBOARD_CONTRACT_LIST)]: diff --git a/src/utils/page.ts b/src/utils/page.ts new file mode 100644 index 0000000..f9c9976 --- /dev/null +++ b/src/utils/page.ts @@ -0,0 +1,3 @@ +export const scrollToTop = () => { + window.scroll({ top: 0, behavior: "smooth" }); +};