Merge pull request #90 from ChanX21/frontend-updates

Frontend updates
This commit is contained in:
Apurv Borhade 2025-05-12 22:05:58 +05:30 committed by GitHub
commit 683f8493ec
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 67 additions and 18 deletions

View file

@ -13,8 +13,8 @@ export default function Upload() {
<>
<Header />
<main className="flex flex-col w-full min-h-screen pt-24 px-4 md:px-10 mb-12 ">
{step == 0 && <ImageUploadShowcase setStep={setStep} setStepLoading={setStepLoading}/>}
{step == 1 && <NftMintedDetails setStep={setStep} />}
{step == 0 && <ImageUploadShowcase setStep={setStep} setStepLoading={setStepLoading} />}
{step == 1 && <NftMintedDetails step={step} setStep={setStep} />}
</main>
<Footer />
</>

View file

@ -5,7 +5,7 @@ import { Button } from "../ui/button";
import { toast } from "sonner";
import { useEffect, useState } from "react";
import { IoMdCloudUpload } from "react-icons/io";
import { CheckCircle2, Shield, UploadCloud } from "lucide-react";
import { AlertCircle, CheckCircle2, Shield, UploadCloud } from "lucide-react";
import { initSocket } from "@/lib/socket";
import { GoDownload } from "react-icons/go";
import { Card } from "../ui/card";
@ -14,7 +14,8 @@ import { GiWalrusHead } from "react-icons/gi";
import OptimizedImage from "../shared/OptimizedImage";
interface NFTDetailsProps {
compact?: boolean;
step: number;
compact?: boolean;
setStep: (step: number) => void;
}
const statusSteps = [
@ -41,7 +42,7 @@ const statusSteps = [
label: "Tokenizing Image",
description: "Tokenizing the image as an NFT on the blockchain.",
icon: <Shield className="w-8 h-8" />,
},
},
{
key: "softListed",
label: "Soft Listing on Marketplace",
@ -57,12 +58,13 @@ const stepProgress = {
"image:softListed": 100,
};
export const NFTDetails = ({ compact = false, setStep }: NFTDetailsProps) => {
export const NFTDetails = ({ step, compact = false, setStep }: NFTDetailsProps) => {
const { sessionId: token } = useImageAuthStore() as AuthState;
const error = useImageAuthStore((s) => s.error);
const [status, setStatus] = useState('')
const [statusStep, setStatusStep] = useState(0)
const [completed, setCompleted] = useState<boolean>(false);
const [requestFailed, setRequestFailed] = useState(false)
const [progress, setProgress] = useState(0);
const [details, setDetails] = useState<
{ label: string; value: string | undefined }[]
@ -123,6 +125,14 @@ export const NFTDetails = ({ compact = false, setStep }: NFTDetailsProps) => {
return [...prev, newDetail];
});
});
socket.on("image:failed", (data) => {
console.log("Failed: ", data?.message)
setRequestFailed(true)
handleProgress("image:authenticate")
setStatusStep(0)
useImageAuthStore.getState().setError(null)
socket.disconnect();
});
socket.on("image:uploaded", (data) => {
handleProgress("image:uploaded")
@ -182,6 +192,11 @@ export const NFTDetails = ({ compact = false, setStep }: NFTDetailsProps) => {
}
}, [error])
useEffect(() => {
setRequestFailed(false);
}, [step]);
const handleCopy = async (text: string, label: string) => {
if (!text) return;
await navigator.clipboard.writeText(text);
@ -195,8 +210,35 @@ export const NFTDetails = ({ compact = false, setStep }: NFTDetailsProps) => {
link.target = "_blank"
link.click();
};
if (requestFailed) {
return (
<Card className="flex md:min-h-[30vh] flex-col items-center justify-center md:max-w-[30%] px-10 py-16 relative">
<AnimatePresence mode="wait">
<motion.div
key={status}
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 flex items-center justify-center">
<AlertCircle className="w-16 h-16" />
</div>
</div>
<h3 className="text-lg font-medium mt-6 mb-2">Whoops, something broke.</h3>
<p className="text-[#616161] text-center">Hang tight Walrus will be back in a bit!</p>
</motion.div>
</AnimatePresence>
<Button onClick={() => {
setStep(0)
}}>Try Again</Button>
</Card >
)
}
return !completed ? (
return !completed && !requestFailed ? (
<Card className="flex md:min-h-[60vh] flex-col items-center justify-center md:max-w-[30%] px-10 py-16 relative">
<AnimatePresence mode="wait">
<motion.div
@ -226,7 +268,7 @@ export const NFTDetails = ({ compact = false, setStep }: NFTDetailsProps) => {
/>
</motion.div>
</Card >
) : (
) : !requestFailed && (
<>
<div className="w-full max-w-4xl border border-gray-300 rounded-lg shadow-sm p-0 flex flex-col md:flex-row bg-white mt-2">
<div className="flex flex-col items-start w-full md:w-[55%] p-8 pb-4">

View file

@ -7,8 +7,10 @@ import { AuthState, useImageAuthStore } from "@/store/useImageAuthStore";
import { NFTDetails } from "./NFTDetails";
export function NftMintedDetails({
step,
setStep,
}: {
step:number;
setStep: (step: number) => void;
}) {
const { result } = useImageAuthStore() as AuthState
@ -29,7 +31,7 @@ export function NftMintedDetails({
</div>
{/* NFT Details */}
<NFTDetails setStep={setStep}/>
<NFTDetails step={step} setStep={setStep}/>

View file

@ -121,7 +121,7 @@ export default function NftAuctionCard({ nft }: NFTCardFeaturedProps) {
/>
{/* Timer overlay */}
<div className="absolute bottom-4 left-1/2 transform -translate-x-1/2 w-[160px] h-[40px] rounded-[16px] border border-white/30 bg-white/30 shadow-[0_4px_30px_rgba(0,0,0,0.1)] backdrop-blur-[5px] flex items-center justify-center">
<span className="text-white text-xs font-semibold">
<span className="text-white text-xs font-semibold mix-blend-difference">
{timeRemaining === "No deadline"
? "loading..."
: timeRemaining}

View file

@ -1,5 +1,5 @@
import { Button } from '@/components/ui/button'
import { ChevronRight, Clock, Download, FileWarning, History, Share2, Shield, User, X, Check, Copy } from 'lucide-react'
import { ChevronRight, Clock, Download, FileWarning, History, Share2, Shield, User, X, Check, Copy, View, ExternalLink } from 'lucide-react'
import Image from 'next/image'
import React, { useEffect, useState } from 'react'
import { motion } from "framer-motion"
@ -11,6 +11,7 @@ import BeforeAfterSlide from './BeforeAfterSlide'
import axios from 'axios'
import { UserAvatar } from './UserAvatar'
import { displayNftEvents } from '@/utils/blockchainServices'
import Link from 'next/link'
interface VerificationProps {
image: string | null
@ -86,14 +87,14 @@ const Verification = ({ image, verificationError, verificationData, isVerifying,
return response.data
}
useEffect(() => {
if (verificationData && verificationData.verifications) {
console.log(verificationData)
fetchMetadata().then((res) => {
setAuthenticImage(res.image)
displayNftEvents(verificationData.verifications[0].blockchain.tokenId).then(res => {
setProvenance(res)
})
}).catch(err => {
@ -298,14 +299,18 @@ const Verification = ({ image, verificationError, verificationData, isVerifying,
</div>
<div className="flex gap-4 pt-4 border-t border-[#f1f3f5]">
<Button className="md:flex-1 w-[50%] px-3 bg-[#000] hover:bg-gray-950 rounded-none text-white gap-2 md:py-6 py-3">
<Download className="w-4 h-4" />
Download Report
</Button>
<Button variant="outline" className="md:flex-1 w-[50%] px-3 gap-2 md:py-6 py-3 border-[#000] text-[#000] rounded-none">
<Link href={`https://sigillum.digital/detail/${verificationData.verifications[0]._id}`} target='_blank' className='w-[50%] flex'>
<Button className="md:flex-1 px-3 bg-[#000] hover:bg-gray-950 rounded-none text-white gap-2 md:py-6 py-3 border border-black">
<ExternalLink className="w-4 h-4" />
View Lisitng
</Button>
</Link>
<Button variant="outline" className="md:flex-1 w-[50%] px-3 gap-2 md:py-6 py-3 border-[#000] text-[#000] rounded-none ">
<Share2 className="w-4 h-4" />
Share Results
</Button>
</div>
</div>
) : verificationError ? (