Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: plus page to allow gifting another user #4108

Open
wants to merge 45 commits into
base: MI-746-gifting-plus
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
4637cf2
feat: gift user modal
sshanzel Jan 21, 2025
b6701f1
Merge branch 'main' into MI-751
sshanzel Jan 22, 2025
707572f
feat: search user with mention
sshanzel Jan 22, 2025
3f53473
tmp: show modal
sshanzel Jan 22, 2025
7797626
fix: on change handler
sshanzel Jan 22, 2025
c9c4e2d
fix: debounce
sshanzel Jan 22, 2025
6649903
fix: keyboard navigation
sshanzel Jan 22, 2025
4c43d6c
fix: arrow and on focus
sshanzel Jan 22, 2025
f1c525b
feat: on hover, set selected
sshanzel Jan 22, 2025
84091c1
fix: ref
sshanzel Jan 22, 2025
bbc0c94
fix: index
sshanzel Jan 22, 2025
92d8ee2
fix: overlay append
sshanzel Jan 22, 2025
f577767
fix: interactivity
sshanzel Jan 22, 2025
663a58c
fix: on close
sshanzel Jan 22, 2025
f6c79ff
fix: selected ui
sshanzel Jan 22, 2025
84ab16b
fix: gap
sshanzel Jan 22, 2025
3924acb
fix: alignment
sshanzel Jan 22, 2025
a3c0455
fix: roundness
sshanzel Jan 22, 2025
7a3fd26
fix: TODO
sshanzel Jan 22, 2025
e24a2fb
fix: checking disabled
sshanzel Jan 22, 2025
720a6f1
Revert "tmp: show modal"
sshanzel Jan 22, 2025
3726a1b
fix: missing context provider
sshanzel Jan 22, 2025
72a8eab
Merge branch 'main' into MI-751
sshanzel Jan 22, 2025
dee522c
fix: modal pricing
sshanzel Jan 22, 2025
f25e989
fix: missing preselected user
sshanzel Jan 22, 2025
5b435c1
Merge branch 'main' into MI-751
sshanzel Jan 22, 2025
058f1de
Merge branch 'main' into MI-751
sshanzel Jan 23, 2025
4318c3b
fix: extra label
sshanzel Jan 23, 2025
e055a80
refactor: variable name
sshanzel Jan 23, 2025
066ad9f
fix: loop condition
sshanzel Jan 23, 2025
d9e0f03
refactor: usage of enums
sshanzel Jan 23, 2025
eaa4ae2
chore: cleanup
sshanzel Jan 23, 2025
837a213
Merge branch 'main' into MI-751
sshanzel Jan 23, 2025
df408f8
refactor: plus page to allow gifting user
sshanzel Jan 24, 2025
bdc423a
Merge branch 'MI-746-gifting-plus' into MI-753
sshanzel Jan 24, 2025
07efd9f
fix: naming convention
sshanzel Jan 24, 2025
513e218
Merge branch 'MI-746-gifting-plus' into MI-753
sshanzel Jan 24, 2025
bfde489
fix: missing gift icon
sshanzel Jan 24, 2025
e570498
refactor: modal to allow working on plus page
sshanzel Jan 24, 2025
fc7643d
fix: unnecessary line of codes
sshanzel Jan 24, 2025
6e53948
fix: updated ids
sshanzel Jan 24, 2025
985c3ad
fix: dont allow gifting a plus user
sshanzel Jan 24, 2025
51b7c7c
fix: naming convention
sshanzel Jan 24, 2025
13380d8
fix: missing SEO
sshanzel Jan 27, 2025
9cda1db
Merge branch 'MI-746-gifting-plus' into MI-753
sshanzel Jan 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 28 additions & 38 deletions packages/shared/src/components/plus/GiftPlusModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
} from '../typography/Typography';
import CloseButton from '../CloseButton';
import { ButtonSize, ButtonVariant } from '../buttons/common';
import type { AllowedTags, ButtonProps } from '../buttons/Button';
import { Button } from '../buttons/Button';
import { PlusTitle } from './PlusTitle';
import {
Expand All @@ -25,48 +26,23 @@ import { RecommendedMention } from '../RecommendedMention';
import { BaseTooltip } from '../tooltips/BaseTooltip';
import type { UserShortProfile } from '../../lib/user';
import useDebounceFn from '../../hooks/useDebounceFn';
import { ProfileImageSize, ProfilePicture } from '../ProfilePicture';
import { PlusLabelColor, PlusPlanExtraLabel } from './PlusPlanExtraLabel';
import { ArrowKey, KeyboardCommand } from '../../lib/element';

interface SelectedUserProps {
user: UserShortProfile;
onClose: () => void;
}

const SelectedUser = ({ user, onClose }: SelectedUserProps) => {
const { username, name } = user;

return (
<div className="flex w-full max-w-full flex-row items-center gap-2 rounded-10 bg-surface-float p-2">
<ProfilePicture user={user} size={ProfileImageSize.Medium} />
<span className="flex w-full flex-1 flex-row items-center gap-2 truncate">
<Typography bold type={TypographyType.Callout}>
{name}
</Typography>
<Typography
type={TypographyType.Footnote}
color={TypographyColor.Secondary}
>
{username}
</Typography>
</span>
<CloseButton type="button" onClick={onClose} size={ButtonSize.XSmall} />
</div>
);
};
import { GiftingSelectedUser } from './GiftingSelectedUser';

interface GiftPlusModalProps extends ModalProps {
preselected?: UserShortProfile;
onSubmit?: (user: UserShortProfile) => void;
}

export function GiftPlusModalComponent({
preselected,
onSubmit,
...props
}: GiftPlusModalProps): ReactElement {
const [overlay, setOverlay] = useState<HTMLElement>();
const { onRequestClose } = props;
const { oneTimePayment } = usePaymentContext();
const { giftOneYear } = usePaymentContext();
const [selected, setSelected] = useState(preselected);
const [index, setIndex] = useState(0);
const [query, setQuery] = useState('');
Expand Down Expand Up @@ -130,6 +106,18 @@ export function GiftPlusModalComponent({
setQuery('');
};

const submitProps: ButtonProps<AllowedTags> = onSubmit
? {
onClick: (event: React.MouseEvent) => {
onSubmit(selected);
onRequestClose(event);
},
}
: {
tag: 'a',
href: `${plusUrl}?giftToUserId=${selected?.id}`,
};

return (
<Modal
{...props}
Expand All @@ -151,7 +139,10 @@ export function GiftPlusModalComponent({
Gift daily.dev Plus 🎁
</Typography>
{selected ? (
<SelectedUser user={selected} onClose={() => setSelected(null)} />
<GiftingSelectedUser
user={selected}
onClose={() => setSelected(null)}
/>
) : (
<div className="flex flex-col">
<BaseTooltip
Expand Down Expand Up @@ -195,33 +186,32 @@ export function GiftPlusModalComponent({
</Typography>
<PlusPlanExtraLabel
color={PlusLabelColor.Success}
label={oneTimePayment.extraLabel}
label={giftOneYear?.extraLabel}
typographyProps={{ color: TypographyColor.StatusSuccess }}
/>
<Typography type={TypographyType.Body} className="ml-auto mr-1">
<strong className="mr-1">{oneTimePayment?.price}</strong>
{oneTimePayment?.currencyCode}
<strong className="mr-1">{giftOneYear?.price}</strong>
{giftOneYear?.currencyCode}
</Typography>
</div>
<Typography type={TypographyType.Callout}>
Gift one year of daily.dev Plus for {oneTimePayment?.price}. Once the
Gift one year of daily.dev Plus for {giftOneYear?.price}. Once the
payment is processed, they’ll be notified of your gift. This is a
one-time purchase, not a recurring subscription.
</Typography>
<Button
tag="a"
variant={ButtonVariant.Primary}
href={`${plusUrl}?giftToUserId=${selected?.id}`}
disabled={!selected}
{...submitProps}
>
Gift & Pay {oneTimePayment?.price}
Gift & Pay {giftOneYear?.price}
</Button>
</Modal.Body>
</Modal>
);
}

export function GiftPlusModal(props: ModalProps): ReactElement {
export function GiftPlusModal(props: GiftPlusModalProps): ReactElement {
return (
<PaymentContextProvider>
<GiftPlusModalComponent {...props} />
Expand Down
11 changes: 11 additions & 0 deletions packages/shared/src/components/plus/GiftUserContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { createContext, useContext } from 'react';
import type { UserShortProfile } from '../../lib/user';

interface GiftUserContextData {
giftingUser?: UserShortProfile;
onUserChange: (user: UserShortProfile) => void;
}
export const GiftUserContext = createContext<GiftUserContextData | null>(null);

export const useGiftUserContext = (): GiftUserContextData =>
useContext(GiftUserContext);
41 changes: 41 additions & 0 deletions packages/shared/src/components/plus/GiftingSelectedUser.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { ReactElement } from 'react';
import React from 'react';
import { ProfileImageSize, ProfilePicture } from '../ProfilePicture';
import {
Typography,
TypographyColor,
TypographyType,
} from '../typography/Typography';
import CloseButton from '../CloseButton';
import { ButtonSize } from '../buttons/common';
import type { UserShortProfile } from '../../lib/user';

interface GiftingSelectedUserProps {
user: UserShortProfile;
onClose: () => void;
}

export function GiftingSelectedUser({
user,
onClose,
}: GiftingSelectedUserProps): ReactElement {
const { username, name } = user;

return (
<div className="flex w-full max-w-full flex-row items-center gap-2 rounded-10 bg-surface-float p-2">
<ProfilePicture user={user} size={ProfileImageSize.Medium} />
<span className="flex w-full flex-1 flex-row items-center gap-2 truncate">
<Typography bold type={TypographyType.Callout}>
{name}
</Typography>
<Typography
type={TypographyType.Footnote}
color={TypographyColor.Secondary}
>
{username}
</Typography>
</span>
<CloseButton type="button" onClick={onClose} size={ButtonSize.XSmall} />
</div>
);
}
Loading
Loading