Sigillum/Frontend/MainApp/components/nft/ListNFTButton.tsx

129 lines
5.5 KiB
TypeScript
Raw Normal View History

2025-04-16 09:43:48 +00:00
'use client'
2025-05-11 10:35:56 +00:00
import { Button } from '@/components/ui/button';
2025-04-16 09:43:48 +00:00
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
2025-05-11 10:35:56 +00:00
DialogHeader,
DialogTitle,
2025-04-16 09:43:48 +00:00
DialogTrigger,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { useWallet } from '@suiet/wallet-kit';
2025-05-11 10:42:23 +00:00
import { useState } from 'react';
2025-04-16 09:43:48 +00:00
2025-04-25 17:08:28 +00:00
import { useUpdateNftDets } from '@/hooks/useUpdateNftDets';
2025-05-11 10:35:56 +00:00
import { MARKETPLACE_ID, MODULE_NAME, PACKAGE_ID } from '@/lib/suiConfig';
2025-04-27 06:03:03 +00:00
import { listNft } from '@/utils/blockchainServices';
2025-05-11 10:35:56 +00:00
import { useQueryClient } from '@tanstack/react-query';
import { toast } from 'sonner';
import { AnimatePresence, motion } from 'framer-motion';
2025-05-11 10:42:23 +00:00
import { Rocket } from 'lucide-react';
2025-04-16 09:43:48 +00:00
2025-04-25 17:08:28 +00:00
const ListNFTButton = ({ listingId, tokenId, nftId }: { listingId: string, tokenId: string, nftId: string }) => {
2025-04-16 09:43:48 +00:00
const [listPrice, setlistPrice] = useState<string>('')
2025-04-27 06:03:03 +00:00
const { signAndExecuteTransaction, address } = useWallet()
2025-04-25 17:40:07 +00:00
const queryClient = useQueryClient()
2025-05-11 10:35:56 +00:00
const [loading, setLoading] = useState(false); // Loading state
const { mutate: updateNftDet } = useUpdateNftDets()
2025-05-11 10:35:56 +00:00
const [dialogOpen, setDialogOpen] = useState(false)
2025-04-16 09:43:48 +00:00
const handleListing = async () => {
2025-04-27 07:02:30 +00:00
const price = Math.floor(parseFloat(listPrice) * 10 ** 9)
2025-04-16 10:12:42 +00:00
if (!isNaN(price) && address) {
2025-05-11 10:35:56 +00:00
setLoading(true)
2025-04-27 06:03:03 +00:00
const { transaction } = await listNft(listingId, price, PACKAGE_ID, MODULE_NAME, MARKETPLACE_ID, tokenId)
try {
const result = await signAndExecuteTransaction({
transaction: transaction,
});
if (result) {
2025-04-30 17:21:57 +00:00
toast.success("Nft Listed Successfully!");
2025-04-27 06:03:03 +00:00
updateNftDet({ nftId })
queryClient.invalidateQueries({ queryKey: ['unlisted-nfts'], exact: false })
2025-05-11 10:35:56 +00:00
setLoading(false);
setDialogOpen(false)
2025-04-27 06:03:03 +00:00
}
} catch (txError: any) {
console.error("Transaction execution error:", txError);
toast.error("Transaction execution error")
}
2025-04-16 09:43:48 +00:00
} else {
2025-04-27 06:03:03 +00:00
toast.error("Please enter a valid price");
2025-05-11 10:35:56 +00:00
setLoading(false);
2025-04-16 09:43:48 +00:00
}
}
return (
2025-05-11 10:39:36 +00:00
<Dialog open={dialogOpen} onOpenChange={setDialogOpen}>
2025-05-11 10:35:56 +00:00
<DialogTrigger asChild className='border-t' onClick={() => setDialogOpen(true)}>
2025-04-16 09:43:48 +00:00
<Button
2025-05-02 09:55:08 +00:00
variant="default"
className="flex rounded-none flex-col items-center py-5 bg-black text-white hover:text-white text-xs"
2025-04-16 09:43:48 +00:00
>
2025-04-30 17:21:57 +00:00
New Listing
2025-04-16 09:43:48 +00:00
</Button>
</DialogTrigger>
2025-05-11 10:35:56 +00:00
{!loading ? (
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle>List NFT for Sale</DialogTitle>
<DialogDescription>
Enter the price at which you want to list this NFT.
</DialogDescription>
</DialogHeader>
<div className="grid gap-4 py-4">
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="price" className="text-right">
Price (SUI)
</Label>
<Input
id="price"
value={listPrice}
onChange={(e) => setlistPrice(e.target.value)}
placeholder="0.05"
className="col-span-3"
type="number"
min="0"
step="0.01"
/>
</div>
2025-04-16 09:43:48 +00:00
</div>
2025-05-11 10:35:56 +00:00
<DialogFooter>
<Button type="submit" className="w-full" onClick={handleListing}>
Confirm Listing
</Button>
</DialogFooter>
</DialogContent>
) : (
<DialogContent className="sm:max-w-md">
<AnimatePresence mode="wait">
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
transition={{ duration: 0.4 }}
className="flex flex-col items-center text-center"
>
<div className="relative w-20 h-20">
<div className="absolute inset-0 border-4 border-t-[#1b263b] border-[#f1f3f5] rounded-full animate-spin"></div>
<div className="absolute inset-0 flex items-center justify-center">
<Rocket />
</div>
</div>
<h3 className="text-lg font-semibold mt-6 mb-2">NFT Listing in Progress</h3>
<p className="text-[#616161] text-center">We are currently listing your NFT for sale. This may take a moment.</p>
</motion.div>
</AnimatePresence>
</DialogContent>
)}
2025-04-16 09:43:48 +00:00
</Dialog>
)
}
export default ListNFTButton