import React, { FC, useCallback, useState, useReducer, useEffect, Fragment, } from 'react' import { Button, Link, NavBar, PageTitle, ProfileCell, Spacer, } from '@app/components/general' import { Box } from '@a11ywatch/ui' import { TextSkeleton } from '@app/components/placeholders' import { AppManager } from '@app/managers' import { useUserData } from '@app/data' import { metaSetter } from '@app/utils' import type { PageProps } from '@app/types' // import { useBillingDisplay } from '@app/data/formatters' import { roleMap } from '@app/utils/role-map' import { CancelSubscriptionModal } from '@app/components/general/cancel-model' import { usePaymentsHook } from '@app/data/external/payments/use-payments' import { TextField } from '@app/components/general/text-field' import { outlineStyles } from '@app/styles/buttons/outline' import { getUsageLimitsMs } from '@a11ywatch/website-source-builder' interface PasswordState { newPassword?: string currentPassword?: string changePassword: boolean // display the change password form } const initialPasswordState: PasswordState = { newPassword: '', currentPassword: '', changePassword: false, } interface PasswordAction { payload?: string type: 'toggleVisiblility' | 'mutateCurrent' | 'mutateNew' | 'reset' } type PasswordReducer = ( state: PasswordState, action: PasswordAction ) => PasswordState const passwordReducer: PasswordReducer = (state, action) => { const { payload } = action switch (action.type) { case 'toggleVisiblility': { return { ...state, changePassword: !state.changePassword } } case 'mutateCurrent': { return { ...state, currentPassword: payload } } case 'mutateNew': { return { ...state, newPassword: payload } } case 'reset': { return { ...initialPasswordState } } default: { return state } } } // url to manage billing page const MANAGE_BILLING = process.env.NEXT_PUBLIC_MANAGE_BILLING_URL const classes = { row: 'flex place-items-center', submit: 'min-w-[175px]' } const Profile: FC = ({ name }) => { const { data, loading, updateUser, updateUserData } = useUserData( true, 'profile' ) const { onCancelConfirm } = usePaymentsHook(true) const [{ changePassword, currentPassword, newPassword }, dispatch] = useReducer(passwordReducer, Object.assign({}, initialPasswordState)) // todo: reducer const [changeEmail, setChangeEmail] = useState(false) const [newEmail, setNewEmail] = useState('') const [cancelModalOpen, setOpen] = useState(false) const { user } = data ?? { user: { invoice: null } } // const { invoice } = user ?? { invoice: null } // const { billingtitle, billingHeadDisplay } = useBillingDisplay(invoice) const onChangeCurrent = useCallback( (e: React.ChangeEvent) => { dispatch({ type: 'mutateCurrent', payload: e.target.value }) }, [dispatch] ) const onChangeNew = useCallback( (e: React.ChangeEvent) => { dispatch({ type: 'mutateNew', payload: e.target.value }) }, [dispatch] ) const onChangeEmail = useCallback( (e: React.ChangeEvent) => { setNewEmail(e.target.value) }, [setNewEmail] ) const updatePassword = useCallback( async (e: React.FormEvent) => { e.preventDefault() await updateUser({ variables: { password: currentPassword, newPassword, }, }).catch((e) => { console.error(e) }) }, [updateUser, currentPassword, newPassword] ) const updateEmail = useCallback( async (e: React.FormEvent) => { e.preventDefault() await updateUser({ variables: { email: newEmail, }, }).catch((e) => { console.error(e) }) }, [updateUser, newEmail] ) const togglePassword = useCallback(() => { dispatch({ type: 'toggleVisiblility' }) }, [dispatch]) const toggleEmail = useCallback(() => { setChangeEmail((p) => !p) }, [setChangeEmail]) useEffect(() => { if (updateUserData?.updateUser?.success) { AppManager.toggleSnack( true, updateUserData?.updateUser?.message, 'success' ) dispatch({ type: 'reset' }) setNewEmail('') setChangeEmail(false) } }, [updateUserData, dispatch, setNewEmail, setChangeEmail]) const email = updateUserData?.updateUser?.user?.email ?? user?.email // todo: add invoices in panel const onClose = () => { setOpen(false) } const onOpen = () => { setOpen(true) } // cancel the payment subscription const onCancelEvent = async () => { onClose() await onCancelConfirm() } const maxUsage = getUsageLimitsMs(user?.role || 0) const baseUsage = user?.scanInfo?.totalUptime ? (Number(user.scanInfo.totalUptime) / maxUsage) * 100 : 0 return ( {user?.passwordRequired ? (

Password reset required. Please change your password now

) : null}
{user && user.role ? ( ) : null} {user?.activeSubscription ? ( ) : null}
{!user && loading ? ( ) : ( <> {changePassword ? (
) : null} {changeEmail ? (
) : null} )}
{!changePassword ? ( ) : null} {!changeEmail ? ( ) : null}
{user?.activeSubscription && MANAGE_BILLING ? (
Manage Billing
) : null}
{user?.activeSubscription ? 'Upgrade / Downgrade' : 'Upgrade'}
{user?.activeSubscription ? (
) : null}
) } export default metaSetter( { Profile }, { gql: true, } )