diff --git a/assets/js/dashboard/components/form-elements.tsx b/assets/js/dashboard/components/form-elements.tsx index 99dd69528fe3..b916f26750d4 100644 --- a/assets/js/dashboard/components/form-elements.tsx +++ b/assets/js/dashboard/components/form-elements.tsx @@ -74,6 +74,32 @@ export const TypeSelector = ({ ) } +export type OptionDisabledMessageType = + | 'upgrade-subscription-yourself' + | 'upgrade-subscription-reach-out' + | 'no-permissions' + +export const getOptionDisabledMessage = ({ + optionAvailable, + userHasOptionPermissions, + userCanUpgradeSubscription +}: { + optionAvailable: boolean + userHasOptionPermissions: boolean + userCanUpgradeSubscription: boolean +}): null | OptionDisabledMessageType => { + if (!userHasOptionPermissions) { + return 'no-permissions' + } + if (!optionAvailable) { + if (userCanUpgradeSubscription) { + return 'upgrade-subscription-yourself' + } + return 'upgrade-subscription-reach-out' + } + return null +} + export const TypeDisabledMessage = ({ message }: { diff --git a/assets/js/dashboard/segments/segment-modals.tsx b/assets/js/dashboard/segments/segment-modals.tsx index 14caccd83b03..63cd230038c2 100644 --- a/assets/js/dashboard/segments/segment-modals.tsx +++ b/assets/js/dashboard/segments/segment-modals.tsx @@ -1,4 +1,4 @@ -import React, { ReactNode, useCallback, useState } from 'react' +import React, { ReactNode, useState } from 'react' import { ModalLayout, ModalFooter, @@ -31,7 +31,9 @@ import { useSiteContext } from '../site-context' import { Button, buttonClassName } from '../components/button' import { Checkbox, + getOptionDisabledMessage, LabeledTextInput, + OptionDisabledMessageType, TypeDisabledMessage, TypeSelector } from '../components/form-elements' @@ -41,22 +43,6 @@ const inModalSectionLabelClassName = 'text-sm font-semibold dark:text-gray-100' const nameInputProps = { id: 'name', label: 'Segment name' } -const segmentTypeSelectorProps = { - idPrefix: 'segment-type', - options: [ - { - type: SegmentType.personal, - name: SEGMENT_TYPE_LABELS[SegmentType.personal], - description: 'Visible only to you' - }, - { - type: SegmentType.site, - name: SEGMENT_TYPE_LABELS[SegmentType.site], - description: 'Visible to others on the site' - } - ] -} - interface ApiRequestProps { status: MutationStatus error?: unknown @@ -98,12 +84,13 @@ export const CreateSegmentModal = ({ const [type, setType] = useState(defaultType) - const { disabled, disabledMessage, onSegmentTypeChange } = - useSegmentTypeDisabledState({ - siteSegmentsAvailable, - user, - setType - }) + const disabledMessage = + type === SegmentType.site + ? getSiteSegmentDisabledMessage({ + siteSegmentsAvailable, + user + }) + : null return ( @@ -113,18 +100,17 @@ export const CreateSegmentModal = ({ onChange={setName} placeholder={namePlaceholder} /> - - {...segmentTypeSelectorProps} - value={type} - onChange={onSegmentTypeChange} + - {disabled && } { const trimmedName = name.trim() const saveableName = trimmedName.length @@ -287,60 +273,83 @@ const RelatedSharedLinks = ({ sharedLinks }: { sharedLinks: string[] }) => { ) } -const useSegmentTypeDisabledState = ({ +const getSiteSegmentDisabledMessage = ({ siteSegmentsAvailable, - user, - setType + user }: { siteSegmentsAvailable: boolean user: UserContextValue - setType: (type: SegmentType) => void -}) => { - const [disabled, setDisabled] = useState(false) - const [disabledMessage, setDisabledMessage] = useState(null) - - const userIsOwner = user.role === Role.owner - const canSelectSiteSegment = hasSiteSegmentPermission(user) - - const onSegmentTypeChange = useCallback( - (type: SegmentType) => { - setType(type) +}) => + getOptionDisabledMessage({ + optionAvailable: siteSegmentsAvailable, + userHasOptionPermissions: hasSiteSegmentPermission(user), + userCanUpgradeSubscription: user.role === Role.owner + }) - if (type === SegmentType.site && !canSelectSiteSegment) { - setDisabled(true) - setDisabledMessage( - <> - {"You don't have enough permissions to change segment to this type"} - - ) - } else if (type === SegmentType.site && !siteSegmentsAvailable) { - setDisabled(true) - setDisabledMessage( - <> - To use this segment type, - {userIsOwner ? ( - - please upgrade your subscription - - ) : ( - <> - please reach out to a team owner to upgrade their subscription. - - )} - - ) - } else { - setDisabled(false) - setDisabledMessage(null) - } - }, - [setType, siteSegmentsAvailable, userIsOwner, canSelectSiteSegment] - ) +const SegmentTypeSelector = ({ + type, + setType, + optionDisabledMessage +}: { + type: SegmentType + setType: (type: SegmentType) => void + optionDisabledMessage: OptionDisabledMessageType | null +}) => ( + <> + + idPrefix="segment-type" + options={[ + { + type: SegmentType.personal, + name: SEGMENT_TYPE_LABELS[SegmentType.personal], + description: 'Visible only to you' + }, + { + type: SegmentType.site, + name: SEGMENT_TYPE_LABELS[SegmentType.site], + description: 'Visible to others on the site' + } + ]} + value={type} + onChange={setType} + /> + {optionDisabledMessage !== null && ( + + } + /> + )} + +) - return { - disabled, - disabledMessage, - onSegmentTypeChange +const SegmentTypeDisabledMessage = ({ + messageType +}: { + messageType: OptionDisabledMessageType +}): Exclude => { + switch (messageType) { + case 'no-permissions': { + return "You don't have enough permissions to change segment to this type" + } + case 'upgrade-subscription-yourself': { + return ( + <> + To use this segment type,{' '} + + please upgrade your subscription + + + ) + } + case 'upgrade-subscription-reach-out': { + return ( + <> + To use this segment type, please reach out to a team owner to upgrade + their subscription + + ) + } } } @@ -362,12 +371,13 @@ export const UpdateSegmentModal = ({ const [name, setName] = useState(segment.name) const [type, setType] = useState(segment.type) - const { disabled, disabledMessage, onSegmentTypeChange } = - useSegmentTypeDisabledState({ - siteSegmentsAvailable, - user, - setType - }) + const disabledMessage = + type === SegmentType.site + ? getSiteSegmentDisabledMessage({ + siteSegmentsAvailable, + user + }) + : null return ( @@ -377,18 +387,17 @@ export const UpdateSegmentModal = ({ onChange={setName} placeholder={namePlaceholder} /> - - {...segmentTypeSelectorProps} - value={type} - onChange={onSegmentTypeChange} + - {disabled && } { const trimmedName = name.trim() const saveableName = trimmedName.length