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

feat: added alert on profile to notify when a user has subscription policy not configured #520

Merged
merged 3 commits into from
Feb 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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
Loading