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
|
2025-05-05 05:40:59 +00:00
|
|
|
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
|