import type { TSetting } from '@blocklet/payment-types'; import { useRequest } from 'ahooks'; import type { Axios } from 'axios'; import { createContext, useContext, useState } from 'react'; import Toast from '@arcblock/ux/lib/Toast'; import { useLocaleContext } from '@arcblock/ux/lib/Locale/context'; import { Button, Stack, Typography } from '@mui/material'; import api from '../libs/api'; import { formatError, getPaymentKitComponent, openDonationSettings } from '../libs/util'; import { CachedRequest } from '../libs/cached-request'; import ConfirmDialog from '../components/confirm'; import { usePaymentContext } from './payment'; export interface DonateConfigSettings { amount?: { presets?: string[]; preset?: string; custom: boolean; minimum?: string; maximum?: string; }; btnText?: string; historyType?: 'table' | 'avatar'; } export type DonateContextType = { settings: TSetting; refresh: (forceRefresh?: boolean) => void; updateSettings: (newSettings: DonateConfigSettings) => Promise; api: Axios; }; export type DonateContextProps = { mountLocation: string; description: string; defaultSettings?: DonateConfigSettings; children: any; active?: boolean; enableDonate?: boolean; }; // @ts-ignore const DonateContext = createContext({ api }); const { Provider, Consumer } = DonateContext; const fetchDonateSetting = ( params: { mountLocation: string; description: string; defaultSettings?: DonateConfigSettings; active?: boolean; componentDid?: string; }, forceRefresh = false ) => { const livemode = localStorage.getItem('livemode') !== 'false'; const cacheKey = `donate-settings-${params.mountLocation}-${livemode}`; const cachedRequest = new CachedRequest( cacheKey, () => api.post('/api/settings', { ...params, type: 'donate', livemode, settings: params.defaultSettings, }), { ttl: 1000 * 60 * 60, strategy: 'local', } ); return cachedRequest.fetch(forceRefresh); }; function DonateProvider({ mountLocation, description, defaultSettings = {}, children, active = true, enableDonate = false, }: DonateContextProps) { const { t } = useLocaleContext(); const [showConfirm, setShowConfirm] = useState(false); const { session } = usePaymentContext(); const isAdmin = ['owner', 'admin'].includes(session?.user?.role); const { data = { settings: {}, active: true, }, error, run, loading, } = useRequest( (forceRender) => fetchDonateSetting( { mountLocation, description, defaultSettings, active, componentDid: window.blocklet?.componentId?.split('/').pop(), }, forceRender ), { refreshDeps: [mountLocation], onError: (err) => { Toast.error(formatError(err)); }, } ); const updateSettings = async (newSettings: DonateConfigSettings) => { try { const livemode = localStorage.getItem('livemode') !== 'false'; await api.put(`/api/settings/${mountLocation}`, { livemode, settings: newSettings, }); run(true); Toast.success(t('common.saved')); } catch (err) { Toast.error(formatError(err)); throw err; } }; const supportPaymentKit = getPaymentKitComponent(); const handleEnable = async () => { if (!enableDonate || !data || (data as TSetting)?.active) return; try { await api.put(`/api/settings/${(data as TSetting).id}`, { active: true }); if (supportPaymentKit) { setShowConfirm(true); } else { Toast.success(t('payment.checkout.donation.enableSuccess')); run(true); } } catch (err) { Toast.error(formatError(err)); } }; if (loading || error) { return null; } return ( {(data as TSetting)?.active === false ? ( <> {enableDonate && isAdmin && ( {t('payment.checkout.donation.inactive')} )} {showConfirm && ( { setShowConfirm(false); run(true); }} color="primary" onConfirm={() => { run(true); openDonationSettings(false); setShowConfirm(false); }} /> )} ) : ( children )} ); } function useDonateContext() { const context = useContext(DonateContext); return context; } export const clearDonateCache = (mountLocation: string) => { const livemode = localStorage.getItem('livemode') !== 'false'; const cacheKey = `donate-settings-${mountLocation}-${livemode}`; localStorage.removeItem(cacheKey); }; export const clearDonateSettings = async (mountLocation: string) => { try { const livemode = localStorage.getItem('livemode') !== 'false'; await api.delete(`/api/settings/${mountLocation}`, { params: { livemode, }, }); clearDonateCache(mountLocation); } catch (err) { Toast.error(formatError(err)); } }; export { DonateContext, DonateProvider, Consumer as DonateConsumer, useDonateContext };