import { PaymentsSettingsMap } from '@addons/../assets/js/back-end/types'; import { AlertDialog, AlertDialogBody, AlertDialogContent, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, Box, Button, Collapse, Flex, FormLabel, Icon, Input, InputGroup, InputRightAddon, Stack, Switch, Text, Textarea, VStack, chakra, useClipboard, useDisclosure, } from '@chakra-ui/react'; import { useMutation } from '@tanstack/react-query'; import apiFetch from '@wordpress/api-fetch'; import { __ } from '@wordpress/i18n'; import { addQueryArgs } from '@wordpress/url'; import React, { useEffect, useRef, useState } from 'react'; import { Controller, useFormContext, useWatch } from 'react-hook-form'; import { BiHide, BiShow } from 'react-icons/bi'; import { useSearchParams } from 'react-router-dom'; import FormControlTwoCol from '../../../assets/js/back-end/components/common/FormControlTwoCol'; import ToolTip from '../../../assets/js/back-end/screens/settings/components/ToolTip'; import localized from '../../../assets/js/back-end/utils/global'; interface StripePaymentsSettingsMap extends PaymentsSettingsMap { stripe?: { enable: boolean; title: string; description: string; sandbox: boolean; test_publishable_key: string; test_secret_key: string; live_publishable_key: string; live_secret_key: string; webhook_secret: string; webhook_endpoint: string; account: Record | null; method: 'connect' | 'manual'; nonce: string; }; } interface Props { paymentsData?: StripePaymentsSettingsMap; } const StripeGlobalSettings: React.FC = (props) => { const { paymentsData } = props; const { register, control, formState, getValues } = useFormContext(); const [show, setShow] = useState({ liveSandboxKey: false, webhookKey: false, }); const showStripeOptions = useWatch({ name: 'payments.stripe.enable', defaultValue: paymentsData?.stripe?.enable, control, }); const showStripeSandBoxOptions = useWatch({ name: 'payments.stripe.sandbox', defaultValue: paymentsData?.stripe?.sandbox, control, }); const { hasCopied, onCopy } = useClipboard( paymentsData?.stripe?.webhook_endpoint || '', ); // Opened synchronously in the click handler; a window.open() after the ajax // round trip has lost the user gesture and every popup blocker kills it. const popupTabRef = useRef(null); const closePopupTab = () => { if (popupTabRef.current) { popupTabRef.current.close(); popupTabRef.current = null; } }; const connectionMutation = useMutation({ mutationKey: ['stripeConnection'], mutationFn: async ( data: Partial>, ) => { const formData = new FormData(); formData.append('action', 'masteriyo_stripe_connect'); if ('stripe_nonce' in localized) { formData.append('nonce', localized.stripe_nonce as string); } formData.append('current_page_uri', window.location.href); formData.append( 'type', paymentsData?.stripe?.account ? 'disconnect' : 'connect', ); formData.append('state', JSON.stringify(data)); return apiFetch<{ data: | { data: string; type: 'connect'; } | { type: 'disconnect'; }; success: boolean; }>({ url: localized.ajax_url, body: formData, method: 'POST', }); }, onSuccess(data) { // wp_send_json_error() answers HTTP 200, so a backend failure lands here // as { success: false } rather than in onError. Without this guard the // disconnect branch reloaded the page and orphaned the blank tab. if (!data?.success) { closePopupTab(); return; } if (data.data.type == 'connect') { const tab = popupTabRef.current; if (tab) { tab.location.href = data.data.data; } else { window.location.href = data.data.data; } popupTabRef.current = null; } else { window.location.reload(); } }, onError() { closePopupTab(); }, }); const { isOpen, onOpen, onClose } = useDisclosure(); const cancelRef = useRef(null); const [searchParams] = useSearchParams(); useEffect(() => { const mode = searchParams.get('mode'); const accountId = searchParams.get('accountId'); if (!mode || !accountId) return; window.location.href = addQueryArgs(localized.adminUrl + 'admin.php', { page: 'masteriyo', mode, accountId, nonce: 'stripe_nonce' in localized ? (localized.stripe_nonce as string) : null, }); }, []); return ( {__('Connection Status', 'learning-management-system')} {__('Title', 'learning-management-system')} {__('Description', 'learning-management-system')}