diff --git a/packages/shared/src/components/ConditionalWrapper.tsx b/packages/shared/src/components/ConditionalWrapper.tsx index 839460162b..a309b6a6fe 100644 --- a/packages/shared/src/components/ConditionalWrapper.tsx +++ b/packages/shared/src/components/ConditionalWrapper.tsx @@ -13,3 +13,14 @@ const ConditionalWrapper = ({ condition ? wrapper(children) : (children as ReactElement); export default ConditionalWrapper; + +export const ConditionalRender = ({ + condition, + children, +}: Pick): ReactNode => { + if (!condition) { + return null; + } + + return children; +}; diff --git a/packages/shared/src/components/comments/CommentActionButtons.tsx b/packages/shared/src/components/comments/CommentActionButtons.tsx index a674c5ad58..3b01563066 100644 --- a/packages/shared/src/components/comments/CommentActionButtons.tsx +++ b/packages/shared/src/components/comments/CommentActionButtons.tsx @@ -52,7 +52,6 @@ import { ContentPreferenceType } from '../../graphql/contentPreference'; import { isFollowingContent } from '../../hooks/contentPreference/types'; import { useIsSpecialUser } from '../../hooks/auth/useIsSpecialUser'; import { GiftIcon } from '../icons/gift'; -import { usePaymentContext } from '../../contexts/PaymentContext'; export interface CommentActionProps { onComment: (comment: Comment, parentId: string | null) => void; @@ -89,7 +88,7 @@ export default function CommentActionButtons({ const { onMenuClick, isOpen, onHide } = useContextMenu({ id }); const { openModal } = useLazyModal(); const { displayToast } = useToastNotification(); - const { isPlusAvailable } = usePaymentContext(); + const { isValidRegion: isPlusAvailable } = useAuthContext(); const { logSubscriptionEvent } = usePlusSubscription(); const [voteState, setVoteState] = useState(() => { return { diff --git a/packages/shared/src/components/plus/GiftPlusModal.tsx b/packages/shared/src/components/plus/GiftPlusModal.tsx index fafaf60f1a..c90cfa9a8e 100644 --- a/packages/shared/src/components/plus/GiftPlusModal.tsx +++ b/packages/shared/src/components/plus/GiftPlusModal.tsx @@ -1,6 +1,7 @@ import type { ReactElement } from 'react'; import React, { useState } from 'react'; import { useQuery } from '@tanstack/react-query'; +import classNames from 'classnames'; import type { ModalProps } from '../modals/common/Modal'; import { Modal } from '../modals/common/Modal'; import { @@ -29,12 +30,24 @@ import { ArrowKey, KeyboardCommand } from '../../lib/element'; import { GiftingSelectedUser } from './GiftingSelectedUser'; import Link from '../utilities/Link'; import { useViewSize, ViewSize } from '../../hooks'; +import { Image } from '../image/Image'; +import { fallbackImages } from '../../lib/config'; +import { sizeClasses } from '../ProfilePicture'; +import { ConditionalRender } from '../ConditionalWrapper'; +import { Separator } from '../cards/common/common'; +import { IconSize } from '../Icon'; +import { ReputationUserBadge } from '../ReputationUserBadge'; +import classed from '../../lib/classed'; +import JoinedDate from '../profile/JoinedDate'; +import { webappUrl } from '../../lib/constants'; interface GiftPlusModalProps extends ModalProps { preselected?: UserShortProfile; onSelected?: (user: UserShortProfile) => void; } +const UserText = classed('span', 'flex flex-row items-center justify-center'); + export function GiftPlusModalComponent({ preselected, onSelected, @@ -54,6 +67,8 @@ export function GiftPlusModalComponent({ query, }); + setIndex(0); + return result.recommendedMentions; }, enabled: !!query?.length, @@ -65,6 +80,10 @@ export function GiftPlusModalComponent({ return; } + if (!users?.length) { + return; + } + e.preventDefault(); if (e.key === ArrowKey.Down) { @@ -117,7 +136,7 @@ export function GiftPlusModalComponent({ overlayRef={setOverlay} isDrawerOnMobile > - +
- + Gift daily.dev Plus 🎁 - {selected ? ( - setSelected(null)} +
+ - ) : ( -
- setQuery('')} - visible={isVisible} - showArrow={false} - interactive - content={ - user.isPlus} - disabledTooltip="This user already has daily.dev Plus" + {preselected && ( + <> + + + {preselected.name} + + - } - container={{ - className: 'shadow', - paddingClassName: 'p-0', - roundedClassName: 'rounded-16', - bgClassName: 'bg-accent-pepper-subtlest', - }} - > - } - inputId="search_user" - fieldType="tertiary" - autoComplete="off" - label="Select a recipient by name or handle" - onKeyDown={onKeyDown} - onChange={(e) => onSearch(e.currentTarget.value.trim())} - onFocus={(e) => setQuery(e.currentTarget.value.trim())} - /> - -
- )} -
+ + + + @{preselected.username} + + + + + + )} +
+ + {selected ? ( + setSelected(null)} + /> + ) : ( +
+ setQuery('')} + visible={isVisible} + showArrow={false} + interactive + content={ + user.isPlus} + disabledTooltip="This user already has daily.dev Plus" + /> + } + container={{ + className: 'shadow', + paddingClassName: 'p-0', + roundedClassName: 'rounded-16', + bgClassName: 'bg-accent-pepper-subtlest', + }} + > + } + inputId="search_user" + fieldType="tertiary" + autoComplete="off" + label="Select a recipient by name or handle" + onKeyDown={onKeyDown} + onChange={(e) => onSearch(e.currentTarget.value.trim())} + onFocus={(e) => setQuery(e.currentTarget.value.trim())} + /> + +
+ )} +
+
One-year plan - + {giftOneYear?.extraLabel && ( + + )} {giftOneYear?.price} {giftOneYear?.currencyCode} @@ -191,12 +248,12 @@ export function GiftPlusModalComponent({ payment is processed, they’ll be notified of your gift. This is a one-time purchase, not a recurring subscription. - + diff --git a/packages/shared/src/components/plus/GiftReceivedPlusModal.tsx b/packages/shared/src/components/plus/GiftReceivedPlusModal.tsx index 2d1feec4a4..6bc5bd1d16 100644 --- a/packages/shared/src/components/plus/GiftReceivedPlusModal.tsx +++ b/packages/shared/src/components/plus/GiftReceivedPlusModal.tsx @@ -22,6 +22,7 @@ import { ProfileImageSize, ProfilePicture } from '../ProfilePicture'; import Link from '../utilities/Link'; import { useAuthContext } from '../../contexts/AuthContext'; import { Loader } from '../Loader'; +import { webappUrl } from '../../lib/constants'; const GifterProfile = ({ gifter }: { gifter: UserShortProfile }) => ( @@ -104,7 +105,7 @@ export function GiftReceivedPlusModal(props: ModalProps): ReactElement {
diff --git a/packages/shared/src/components/plus/PlusTitle.tsx b/packages/shared/src/components/plus/PlusTitle.tsx index 586129ba71..78ff9d8f8e 100644 --- a/packages/shared/src/components/plus/PlusTitle.tsx +++ b/packages/shared/src/components/plus/PlusTitle.tsx @@ -24,7 +24,7 @@ export function PlusTitle( {...typography} className={classnames('flex flex-row items-center gap-0.5', className)} > - Plus + Plus ); } diff --git a/packages/shared/src/components/squads/SquadMemberMenu.tsx b/packages/shared/src/components/squads/SquadMemberMenu.tsx index 24e3f1879f..eb2f08a9bb 100644 --- a/packages/shared/src/components/squads/SquadMemberMenu.tsx +++ b/packages/shared/src/components/squads/SquadMemberMenu.tsx @@ -1,6 +1,6 @@ import type { ReactElement } from 'react'; import React, { useContext, useMemo } from 'react'; -import AuthContext from '../../contexts/AuthContext'; +import AuthContext, { useAuthContext } from '../../contexts/AuthContext'; import { reportSquadMember } from '../../lib/constants'; import { IconSize } from '../Icon'; import type { SourceMember, Squad } from '../../graphql/sources'; @@ -19,7 +19,6 @@ import { LazyModal } from '../modals/common/types'; import { GiftIcon } from '../icons/gift'; import { useLazyModal } from '../../hooks/useLazyModal'; import { LogEvent, TargetId } from '../../lib/log'; -import { usePaymentContext } from '../../contexts/PaymentContext'; interface SquadMemberMenuProps extends Pick { squad: Squad; @@ -129,7 +128,7 @@ export default function SquadMemberMenu({ const { user } = useContext(AuthContext); const { showPrompt } = usePrompt(); const { displayToast } = useToastNotification(); - const { isPlusAvailable } = usePaymentContext(); + const { isValidRegion: isPlusAvailable } = useAuthContext(); const { logSubscriptionEvent } = usePlusSubscription(); const onUpdateMember = async ( role: SourceMemberRole, diff --git a/packages/webapp/pages/account/invite.tsx b/packages/webapp/pages/account/invite.tsx index 0a16bbc0b3..10ca9e2823 100644 --- a/packages/webapp/pages/account/invite.tsx +++ b/packages/webapp/pages/account/invite.tsx @@ -47,7 +47,6 @@ import { import { GiftIcon } from '@dailydotdev/shared/src/components/icons/gift'; import { useLazyModal } from '@dailydotdev/shared/src/hooks/useLazyModal'; import { LazyModal } from '@dailydotdev/shared/src/components/modals/common/types'; -import { usePaymentContext } from '@dailydotdev/shared/src/contexts/PaymentContext'; import { useLogContext } from '@dailydotdev/shared/src/contexts/LogContext'; import AccountContentSection from '../../components/layouts/AccountLayout/AccountContentSection'; import { AccountPageContainer } from '../../components/layouts/AccountLayout/AccountPageContainer'; @@ -66,7 +65,7 @@ const AccountInvitePage = (): ReactElement => { const { url, referredUsersCount } = useReferralCampaign({ campaignKey: ReferralCampaignKey.Generic, }); - const { isPlusAvailable } = usePaymentContext(); + const { isValidRegion: isPlusAvailable } = useAuthContext(); const { logSubscriptionEvent } = usePlusSubscription(); const { logEvent } = useLogContext(); const inviteLink = url || link.referral.defaultUrl;