Skip to content

Commit

Permalink
Merge pull request #520 from WatchItDev/app/unset/pricing
Browse files Browse the repository at this point in the history
feat: added alert on profile to notify when a user has subscription policy not configured
  • Loading branch information
geolffreym authored Feb 2, 2025
2 parents 31d5a36 + 37abe06 commit fdd775d
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 78 deletions.
45 changes: 26 additions & 19 deletions src/components/subscribe-to-unlock-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useGetPolicyTerms } from '@src/hooks/use-get-policy-terms.ts';
import { Address } from 'viem';
import LoadingButton from '@mui/lab/LoadingButton';
import { GLOBAL_CONSTANTS } from '@src/config-global.ts';
import { useIsPolicyAuthorized } from '@src/hooks/use-is-policy-authorized.ts';

interface Props {
post: any;
Expand All @@ -18,10 +19,12 @@ export const SubscribeToUnlockCard = ({
loadingSubscribe,
post,
}: Props) => {
const ownerAddress = post?.by?.ownedBy?.address as Address
const { terms } = useGetPolicyTerms(
GLOBAL_CONSTANTS.SUBSCRIPTION_POLICY_ADDRESS as Address,
post?.by?.ownedBy?.address as Address
ownerAddress
);
const { isAuthorized } = useIsPolicyAuthorized(GLOBAL_CONSTANTS.SUBSCRIPTION_POLICY_ADDRESS, ownerAddress);
const durationDays = 30; // a month
const totalCostWei = terms?.amount ? terms?.amount * BigInt(durationDays) : 0; // Calculate total cost in Wei: DAILY_COST_WEI * durationDays
const totalCostMMC = ethers.formatUnits(totalCostWei, 18); // Converts Wei to MMC
Expand Down Expand Up @@ -50,24 +53,28 @@ export const SubscribeToUnlockCard = ({
This content is exclusively for members. Become part of our growing community to access
behind-the-scenes content, exclusive posts, and much more!
</Typography>
<LoadingButton
variant="contained"
color="primary"
sx={{ width: '100%', py: 1.5 }}
onClick={onSubscribe}
loading={loadingSubscribe}
// disabled={subscribeDisabled}
>
<IconPlayerPlay size={20} style={{ marginRight: 5 }} />
Join
</LoadingButton>
<Box sx={{ mt: 3, borderRadius: 1 }}>
<Typography variant="body2" color="textSecondary">
Join now for just <strong>{totalCostMMC} MMC/month</strong> and access to{' '}
<strong>{post?.by?.stats?.posts}</strong> exclusive posts from{' '}
<strong>{post?.by?.metadata?.displayName ?? post?.handle?.localName}!</strong>
</Typography>
</Box>
{isAuthorized && (
<>
<LoadingButton
variant="contained"
color="primary"
sx={{ width: '100%', py: 1.5 }}
onClick={onSubscribe}
loading={loadingSubscribe}
// disabled={subscribeDisabled}
>
<IconPlayerPlay size={20} style={{ marginRight: 5 }} />
Join
</LoadingButton>
<Box sx={{ mt: 3, borderRadius: 1 }}>
<Typography variant="body2" color="textSecondary">
Join now for just <strong>{totalCostMMC} MMC/month</strong> and access to{' '}
<strong>{post?.by?.stats?.posts}</strong> exclusive posts from{' '}
<strong>{post?.by?.metadata?.displayName ?? post?.handle?.localName}!</strong>
</Typography>
</Box>
</>
)}
</CardContent>
</Card>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const FinanceDisplayProfileInfo: FC<FinanceDisplayNameProps> = ({initialList, ca
{
mode === 'profile' ?
(<Box component="span" sx={{ flexGrow: 1, typography: 'subtitle1' }}>
{selectedProfile?.metadata?.displayName ?? 'No profile selected'}
{selectedProfile?.metadata?.displayName ?? selectedProfile?.handle?.localName ?? 'No profile selected'}
</Box>) : null
}
{
Expand Down
77 changes: 46 additions & 31 deletions src/sections/finance/components/finance-quick-transfer-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,18 @@ function FinanceQuickTransferModal({
const { sendNotification } = useNotifications();
const [message, setMessage] = useState('');

// For transfer button is clicked in some profile
// For the transfer button when using user input
const MAX_AMOUNT = useSelector((state: any) => state.auth.balance);
const [value, setValue] = useState(0);
const [canContinue, setCanContinue] = useState(true);

// Check if we have a valid profile or not
// Check if we have a valid profile
const hasProfile = !!contactInfo;

// Check if the passed address matches the profile's address
const isSame =
hasProfile && contactInfo?.ownedBy?.address?.toLowerCase() === address?.toLowerCase();
hasProfile &&
contactInfo?.ownedBy?.address?.toLowerCase() === address?.toLowerCase();

// If no valid profile, show "Destination wallet", else use profile’s displayName
const displayName = hasProfile
Expand Down Expand Up @@ -107,9 +108,14 @@ function FinanceQuickTransferModal({
}
}

// Define the transfer amount: if a positive 'amount' is passed, use it; otherwise, use the entered value
const transferAmount = amount > 0 ? amount : value;
// Validation: if 'amount' is passed, assume it's valid; otherwise, ensure that the value is greater than 0 and input validation (canContinue) passes.
const isTransferValid = transferAmount > 0 && (amount > 0 || canContinue);

const handleConfirmTransfer = async () => {
try {
await transfer({ amount: amount > 0 ? amount: value, recipient: address ?? '' });
await transfer({ amount: transferAmount, recipient: address ?? '' });

onFinish();

Expand All @@ -120,57 +126,65 @@ function FinanceQuickTransferModal({
'TRANSFER',
{
id: isSame ? (contactInfo?.id ?? '') : (address ?? ''),
displayName: isSame ? (contactInfo?.metadata?.displayName ?? 'No name') : 'External wallet',
displayName: isSame
? (contactInfo?.metadata?.displayName ?? 'No name')
: 'External wallet',
avatar: (contactInfo?.metadata?.picture as any)?.optimized?.uri ?? '',
},
{
rawDescription: `${sessionData?.profile?.metadata?.displayName ?? address} sent you ${amount} MMC`,
rawDescription: `${sessionData?.profile?.metadata?.displayName ?? address} sent you ${transferAmount} MMC`,
message,
}
);

// Store transaction in supabase
// Store transaction in Supabase
await storeTransactionInSupabase(contactInfo?.id ?? address, senderId, {
address: contactInfo?.ownedBy?.address ?? address,
amount: amount > 0 ? amount : value,
amount: transferAmount,
message,
...notificationPayload,
});

// Send notification to lens profile or address
// Send notification to the Lens profile or address
await sendNotification(
contactInfo?.id ?? address ?? '',
sessionData?.profile?.id,
notificationPayload
);

notifySuccess(SUCCESS.TRANSFER_CREATED_SUCCESSFULLY, {
destination: isSame ? contactInfo?.metadata?.displayName : truncateAddress(address ?? ''),
destination: isSame
? contactInfo?.metadata?.displayName ?? contactInfo?.handle?.localName
: truncateAddress(address ?? ''),
});
} catch (err: any) {
notifyError(ERRORS.TRANSFER_FAILED_ERROR);
}
};

const handleChangeInput = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
const value = Number(event.target.value);
handleAmountConstraints({value, MAX_AMOUNT, MAX_POOL, setAmount: setValue, setCanContinue});
}, [MAX_AMOUNT]);

const handleChangeInput = useCallback(
(event: React.ChangeEvent<HTMLInputElement>) => {
const value = Number(event.target.value);
handleAmountConstraints({ value, MAX_AMOUNT, MAX_POOL, setAmount: setValue, setCanContinue });
},
[MAX_AMOUNT]
);

const handleBlur = useCallback(() => {
handleAmountConstraints({value, MAX_AMOUNT, MAX_POOL, setAmount: setValue, setCanContinue});
handleAmountConstraints({ value, MAX_AMOUNT, MAX_POOL, setAmount: setValue, setCanContinue });
}, [value, MAX_AMOUNT]);

const RainbowEffect = transferLoading ? NeonPaper : Box;

return (
<Dialog open={open} fullWidth maxWidth="xs" onClose={onClose}>
<DialogTitle sx={{
borderBottom: `dashed 1px ${theme.palette.divider}`,
padding: '16px 24px',
marginBottom: '8px'
}}>
<DialogTitle
sx={{
borderBottom: `dashed 1px ${theme.palette.divider}`,
padding: '16px 24px',
marginBottom: '8px',
}}
>
Send to
</DialogTitle>
<Stack direction="column" spacing={3} sx={{ px: 3 }}>
Expand All @@ -190,19 +204,20 @@ function FinanceQuickTransferModal({
</Stack>

<Stack direction="column" spacing={0} sx={{ py: 2, flexGrow: 1 }}>
{amount > 0 ? (

{amount > 0 ? (
<ListItemText
primary="Amount:"
secondary={`${amount} MMC`}
secondaryTypographyProps={{ component: 'span', mt: 0.5 }}
/>
) : <InputAmount
max={MAX_POOL}
amount={value}
onBlur={handleBlur}
onChange={handleChangeInput}
/>}
) : (
<InputAmount
max={MAX_POOL}
amount={value}
onBlur={handleBlur}
onChange={handleChangeInput}
/>
)}
</Stack>
</Stack>

Expand All @@ -219,7 +234,7 @@ function FinanceQuickTransferModal({
sx={{
borderTop: `dashed 1px ${theme.palette.divider}`,
padding: '16px 24px',
marginTop: '24px'
marginTop: '24px',
}}
>
<Button onClick={onClose}>Cancel</Button>
Expand All @@ -236,7 +251,7 @@ function FinanceQuickTransferModal({
variant="contained"
sx={{ backgroundColor: '#fff' }}
onClick={handleConfirmTransfer}
disabled={transferLoading || !canContinue || value <= 0}
disabled={transferLoading || !isTransferValid}
loading={transferLoading}
>
Confirm
Expand Down
11 changes: 4 additions & 7 deletions src/sections/finance/components/finance-quick-transfer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export default function FinanceQuickTransfer({

// 3) Move the carousel right now
carousel.setCurrentIndex(finalIndex);
setCurrentIndex(finalIndex);

// 4) Update the wallet address & Redux
setWalletAddress(profile.ownedBy?.address ?? '');
Expand Down Expand Up @@ -254,9 +255,6 @@ export default function FinanceQuickTransfer({
}
}, [showRainbow, currentIndex, carousel]);

// We pick the contactInfo to pass to the modal. If currentIndex is -1, there's no matched profile
const contactInfoToPass = currentIndex === -1 ? undefined : getContactInfo;

// Render the carousel of profiles
const renderCarousel = (
<Box sx={{ position: 'relative', mb: 3 }}>
Expand Down Expand Up @@ -374,7 +372,6 @@ export default function FinanceQuickTransfer({

const Wrapper = showRainbow ? NeonPaper : Box;

console.log(list);
return (
<>
<Wrapper
Expand All @@ -400,9 +397,9 @@ export default function FinanceQuickTransfer({

{/* Content */}
<Stack sx={{ p: 3 }}>
<FinanceDisplayProfileInfo mode={'profile'} initialList={initialList} carousel={carousel} />
<FinanceDisplayProfileInfo mode={'profile'} initialList={list} carousel={carousel} />
{list?.length > 0 ? renderCarousel : <FinanceNoFollowingsQuickTransfer />}
<FinanceDisplayProfileInfo mode={'wallet'} initialList={initialList} carousel={carousel} />
<FinanceDisplayProfileInfo mode={'wallet'} initialList={list} carousel={carousel} />
{renderInput}
</Stack>
</Stack>
Expand All @@ -417,7 +414,7 @@ export default function FinanceQuickTransfer({
address={walletAddress}
onClose={confirm.onFalse}
onFinish={handleTransferFinish}
contactInfo={contactInfoToPass} // If currentIndex is -1, this is undefined
contactInfo={getContactInfo}
onChange={handleChangeInput}
/>
</>
Expand Down
45 changes: 25 additions & 20 deletions src/sections/publication/view/publication-details-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import LoadingButton from '@mui/lab/LoadingButton';
import { useDispatch, useSelector } from 'react-redux';
import { openLoginModal } from '@redux/auth';
import { appId, PublicationType, usePublications } from '@lens-protocol/react-web';
import { useIsPolicyAuthorized } from '@src/hooks/use-is-policy-authorized.ts';
import { GLOBAL_CONSTANTS } from '@src/config-global.ts';

const MAX_LINES = 5;

Expand Down Expand Up @@ -68,6 +70,7 @@ export default function PublicationDetailsView({ id }: Props) {
fetching: accessFetchingLoading,
refetch: refetchAccess,
} = useHasAccess(ownerAddress);
const { isAuthorized } = useIsPolicyAuthorized(GLOBAL_CONSTANTS.SUBSCRIPTION_POLICY_ADDRESS, ownerAddress);

const getMediaUri = (cid: string): string => `${cid}`;

Expand Down Expand Up @@ -223,26 +226,28 @@ export default function PublicationDetailsView({ id }: Props) {
}}
/>

<LoadingButton
variant="contained"
sx={{
color: '#1E1F22',
background: '#FFFFFF',
height: '35px',
bottom: 16,
left: 16,
position: 'absolute',
zIndex: 2,
}}
onClick={handleSubscribe}
// disabled={accessLoading || hasAccess || accessFetchingLoading}
loading={accessLoading || accessFetchingLoading}
>
<IconPlayerPlay fontSize="large" size={18} />
<Typography variant="body2" sx={{ lineHeight: 1, fontWeight: '700', ml: 1 }}>
Join
</Typography>
</LoadingButton>
{isAuthorized && (
<LoadingButton
variant="contained"
sx={{
color: '#1E1F22',
background: '#FFFFFF',
height: '35px',
bottom: 16,
left: 16,
position: 'absolute',
zIndex: 2,
}}
onClick={handleSubscribe}
// disabled={accessLoading || hasAccess || accessFetchingLoading}
loading={accessLoading || accessFetchingLoading}
>
<IconPlayerPlay fontSize="large" size={18} />
<Typography variant="body2" sx={{ lineHeight: 1, fontWeight: '700', ml: 1 }}>
Join
</Typography>
</LoadingButton>
)}
</Box>
)}

Expand Down
Loading

0 comments on commit fdd775d

Please sign in to comment.