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: add collect module for hey nft #4519

Merged
merged 7 commits into from
Jan 11, 2024
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
103 changes: 103 additions & 0 deletions apps/web/src/components/Home/Sidebar/HeyMembershipNft/Mint.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import type { Post } from '@hey/lens';
import type { FC } from 'react';

import CollectAction from '@components/Publication/LensOpenActions/CollectModule/CollectAction';
import Loader from '@components/Shared/Loader';
import { Errors } from '@hey/data';
import { APP_NAME, IS_MAINNET } from '@hey/data/constants';
import { usePublicationQuery } from '@hey/lens';
import { ErrorMessage } from '@hey/ui';
import cn from '@hey/ui/cn';
import { signatureFont } from '@lib/fonts';
import Link from 'next/link';

interface MintProps {
onCollectSuccess: () => void;
}

const Mint: FC<MintProps> = ({ onCollectSuccess }) => {
const { data, error, loading } = usePublicationQuery({
variables: {
request: { forId: IS_MAINNET ? '0x020b69-0x01' : '0x06-0x05' }
}
});

if (loading) {
return (
<div className="m-5">
<Loader message="Loading NFT" />
</div>
);
}

if (!data?.publication || error) {
return (
<ErrorMessage
className="m-5"
error={
error || {
message: Errors.SomethingWentWrong,
name: 'Failed to load NFT'
}
}
title="Failed to load NFT"
/>
);
}

const publication = data?.publication as Post;
const openAction = publication.openActionModules[0];

return (
<div className="p-5">
<img
className="mb-4 h-[250px] w-full rounded-xl border object-cover dark:border-gray-700"
src="https://ipfs.decentralized-content.com/ipfs/bafybeib6infyovvtawokys4ejjr4r3qk4soy7jqriejp2wbmttedupsy64"
/>
<div className="linkify mt-5 space-y-3 font-serif">
<b>Thanks for Being a {APP_NAME} Member!</b>
<div>
Your journey with us has been invaluable. By supporting "{APP_NAME}",
you're not just a part of our story, but you're also fueling the
vibrant future of{' '}
<Link
className="font-bold"
href="https://github.com/heyxyz/hey"
target="_blank"
>
open-source
</Link>{' '}
development. Here's to more innovation and collaboration ahead!
</div>
<div
className={cn(
'flex items-center space-x-2 pt-3 text-2xl',
signatureFont.className
)}
>
<div>-</div>
<img className="size-6" src="/logo.png" />
<div>Team Hey</div>
</div>
</div>
<div className="mt-6">
<CollectAction
buttonTitle="Collect for 5 MATIC"
className="!mt-0 w-full justify-center"
countOpenActions={0}
forceShowCollect
noBalanceErrorMessages={
<span>
You need <b>5 MATIC</b> to collect this {APP_NAME} NFT
</span>
}
onCollectSuccess={onCollectSuccess}
openAction={openAction}
publication={publication}
/>
</div>
</div>
);
};

export default Mint;
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import type { FC } from 'react';

import Mint from '@components/Publication/HeyOpenActions/Nft/ZoraNft/Mint';
import { CursorArrowRaysIcon } from '@heroicons/react/24/outline';
import { HEY_API_URL, ZERO_PUBLICATION_ID } from '@hey/data/constants';
import { APP_NAME, HEY_API_URL } from '@hey/data/constants';
import { MISCELLANEOUS, PUBLICATION } from '@hey/data/tracking';
import { Button, Card, Modal } from '@hey/ui';
import getAuthApiHeaders from '@lib/getAuthApiHeaders';
import { Leafwatch } from '@lib/leafwatch';
import axios from 'axios';
import { memo, useState } from 'react';
import toast from 'react-hot-toast';
import useZoraNft from 'src/hooks/zora/useZoraNft';
import { usePreferencesStore } from 'src/store/non-persisted/usePreferencesStore';

import Mint from './Mint';

const HeyMembershipNft: FC = () => {
const hasDismissedOrMintedMembershipNft = usePreferencesStore(
(state) => state.hasDismissedOrMintedMembershipNft
Expand All @@ -22,32 +22,25 @@ const HeyMembershipNft: FC = () => {
);
const [showMintModal, setShowMintModal] = useState(false);

const { data: nft, loading } = useZoraNft({
address: '0x8fcfdad5ebdd1ce815aa769bbd7499091ac056d1',
chain: 'zora'
});

if (hasDismissedOrMintedMembershipNft) {
return null;
}

const updateHeyMemberNftStatus = async () => {
try {
toast.promise(
axios.post(`${HEY_API_URL}/preferences/updateNftStatus`, undefined, {
headers: getAuthApiHeaders()
}),
{
error: 'Error updating.',
loading: 'Updating...',
success: () => {
setHasDismissedOrMintedMembershipNft(true);
setShowMintModal(false);
return 'Updated!';
}
toast.promise(
axios.post(`${HEY_API_URL}/preferences/updateNftStatus`, undefined, {
headers: getAuthApiHeaders()
}),
{
error: 'Error updating.',
loading: 'Updating...',
success: () => {
setHasDismissedOrMintedMembershipNft(true);
setShowMintModal(false);
return 'Updated!';
}
);
} catch {}
}
);
};

return (
Expand All @@ -71,10 +64,9 @@ const HeyMembershipNft: FC = () => {
<div className="flex flex-col items-center space-y-1.5">
<Button
className="w-full"
disabled={loading}
onClick={() => {
setShowMintModal(true);
Leafwatch.track(PUBLICATION.OPEN_ACTIONS.ZORA_NFT.OPEN_MINT, {
Leafwatch.track(PUBLICATION.COLLECT_MODULE.OPEN_COLLECT, {
from: 'mint_membership_nft'
});
}}
Expand All @@ -85,14 +77,9 @@ const HeyMembershipNft: FC = () => {
icon={<CursorArrowRaysIcon className="text-brand-500 size-5" />}
onClose={() => setShowMintModal(false)}
show={showMintModal}
title="Mint"
title={`Special ${APP_NAME} NFT`}
>
<Mint
nft={nft}
onCompleted={updateHeyMemberNftStatus}
publicationId={ZERO_PUBLICATION_ID}
zoraLink="https://zora.co/collect/zora:0x8fcfdad5ebdd1ce815aa769bbd7499091ac056d1"
/>
<Mint onCollectSuccess={updateHeyMemberNftStatus} />
</Modal>
<button
className="text-sm underline"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type {
LegacyCollectRequest,
OpenActionModule
} from '@hey/lens';
import type { FC } from 'react';
import type { FC, ReactNode } from 'react';

import { useApolloClient } from '@apollo/client';
import AllowanceButton from '@components/Settings/Allowance/Button';
Expand All @@ -30,6 +30,7 @@ import getOpenActionActOnKey from '@hey/lib/getOpenActionActOnKey';
import getSignature from '@hey/lib/getSignature';
import { isMirrorPublication } from '@hey/lib/publicationHelpers';
import { Button, Spinner, WarningMessage } from '@hey/ui';
import cn from '@hey/ui/cn';
import errorToast from '@lib/errorToast';
import getCurrentSession from '@lib/getCurrentSession';
import { Leafwatch } from '@lib/leafwatch';
Expand All @@ -48,17 +49,25 @@ import {
} from 'wagmi';

interface CollectActionProps {
buttonTitle?: string;
className?: string;
countOpenActions: number;
forceShowCollect?: boolean;
noBalanceErrorMessages?: ReactNode;
onCollectSuccess?: () => void;
openAction: OpenActionModule;
publication: AnyPublication;
setCountOpenActions: (count: number) => void;
}

const CollectAction: FC<CollectActionProps> = ({
buttonTitle = 'Collect now',
className = '',
countOpenActions,
forceShowCollect = false,
noBalanceErrorMessages,
onCollectSuccess = () => {},
openAction,
publication,
setCountOpenActions
publication
}) => {
const currentProfile = useProfileStore((state) => state.currentProfile);
const { isSuspended } = useProfileRestriction();
Expand Down Expand Up @@ -117,8 +126,9 @@ const CollectAction: FC<CollectActionProps> = ({
const canUseManager =
canUseLensManager && !collectModule?.followerOnly && isFreeCollectModule;

const canCollect =
!hasActed || (!isFreeCollectModule && !isSimpleFreeCollectModule);
const canCollect = forceShowCollect
? true
: !hasActed || (!isFreeCollectModule && !isSimpleFreeCollectModule);

const updateCache = () => {
cache.modify({
Expand Down Expand Up @@ -154,7 +164,7 @@ const CollectAction: FC<CollectActionProps> = ({

setHasActed(true);
setIsLoading(false);
setCountOpenActions(countOpenActions + 1);
onCollectSuccess?.();
updateCache();
toast.success('Collected successfully!');
Leafwatch.track(PUBLICATION.COLLECT_MODULE.COLLECT, {
Expand Down Expand Up @@ -384,22 +394,23 @@ const CollectAction: FC<CollectActionProps> = ({
}

if (allowanceLoading) {
return <div className="shimmer mt-5 h-[34px] w-28 rounded-lg" />;
return (
<div className={cn('shimmer mt-5 h-[34px] w-28 rounded-lg', className)} />
);
}

if (!allowed) {
return (
<span className="mt-5">
<AllowanceButton
allowed={allowed}
module={
allowanceData
?.approvedModuleAllowanceAmount[0] as ApprovedAllowanceAmountResult
}
setAllowed={setAllowed}
title="Allow collect module"
/>
</span>
<AllowanceButton
allowed={allowed}
className={cn('mt-5', className)}
module={
allowanceData
?.approvedModuleAllowanceAmount[0] as ApprovedAllowanceAmountResult
}
setAllowed={setAllowed}
title="Allow collect module"
/>
);
}

Expand All @@ -413,14 +424,19 @@ const CollectAction: FC<CollectActionProps> = ({
return (
<WarningMessage
className="mt-5 w-full"
message={<NoBalanceError moduleAmount={openAction.amount} />}
message={
<NoBalanceError
errorMessage={noBalanceErrorMessages}
moduleAmount={openAction.amount}
/>
}
/>
);
}

return (
<Button
className="mt-5"
className={cn('mt-5', className)}
disabled={isLoading}
icon={
isLoading ? (
Expand All @@ -431,7 +447,7 @@ const CollectAction: FC<CollectActionProps> = ({
}
onClick={createCollect}
>
Collect now
{buttonTitle}
</Button>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,9 @@ const CollectModule: FC<CollectModuleProps> = ({ openAction, publication }) => {
<div className="flex items-center space-x-2">
<CollectAction
countOpenActions={countOpenActions}
onCollectSuccess={() => setCountOpenActions(countOpenActions + 1)}
openAction={openAction}
publication={publication}
setCountOpenActions={setCountOpenActions}
/>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ const OpenAction: FC<OpenActionProps> = ({ publication, showCount }) => {
)}
onClick={() => {
setShowOpenActionModal(true);
Leafwatch.track(PUBLICATION.COLLECT_MODULE.OPEN_COLLECT);
Leafwatch.track(PUBLICATION.COLLECT_MODULE.OPEN_COLLECT, {
publication_id: publication.id
});
}}
whileTap={{ scale: 0.9 }}
>
Expand Down
4 changes: 4 additions & 0 deletions apps/web/src/components/Settings/Allowance/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ import { useSendTransaction, useWaitForTransactionReceipt } from 'wagmi';

interface AllowanceButtonProps {
allowed: boolean;
className?: string;
module: ApprovedAllowanceAmountResult;
setAllowed: Dispatch<SetStateAction<boolean>>;
title?: string;
}

const AllowanceButton: FC<AllowanceButtonProps> = ({
allowed,
className = '',
module,
setAllowed,
title = 'Allow'
Expand Down Expand Up @@ -105,6 +107,7 @@ const AllowanceButton: FC<AllowanceButtonProps> = ({

return allowed ? (
<Button
className={className}
icon={
queryLoading || transactionLoading || waitLoading ? (
<Spinner size="xs" variant="warning" />
Expand All @@ -126,6 +129,7 @@ const AllowanceButton: FC<AllowanceButtonProps> = ({
) : (
<>
<Button
className={className}
icon={<PlusIcon className="size-4" />}
onClick={() => setShowWarningModal(!showWarningModal)}
>
Expand Down
Loading
Loading