Skip to content

Commit f47b7cf

Browse files
committed
Update Page Detail
2 parents 7201019 + 3e6be3e commit f47b7cf

3 files changed

Lines changed: 234 additions & 127 deletions

File tree

app/marketplace/dataset/[id]/page.tsx

Lines changed: 43 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import confetti from 'canvas-confetti';
1212
export default function DatasetDetailPage() {
1313
const params = useParams();
1414
const id = params.id as string;
15-
15+
1616
const account = useCurrentAccount();
1717
const { data: listing, isLoading } = useListing(id);
1818
const { data: balance } = useAccountBalance();
@@ -24,6 +24,7 @@ export default function DatasetDetailPage() {
2424
const [isPurchasedState, setIsPurchasedState] = useState(false);
2525
const [purchaseTxDigest, setPurchaseTxDigest] = useState('');
2626
const [purchaseError, setPurchaseError] = useState<string | null>(null);
27+
const [isDownloading, setIsDownloading] = useState(false);
2728

2829
// Check if already purchased from blockchain data
2930
const existingPurchase = useMemo(() => {
@@ -37,37 +38,13 @@ export default function DatasetDetailPage() {
3738
const isOwner = listing && account?.address === listing.seller;
3839

3940
const fireConfetti = () => {
40-
// First burst
41-
confetti({
42-
particleCount: 100,
43-
spread: 70,
44-
origin: { y: 0.6 }
45-
});
46-
47-
// Side bursts
41+
confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } });
4842
setTimeout(() => {
49-
confetti({
50-
particleCount: 50,
51-
angle: 60,
52-
spread: 55,
53-
origin: { x: 0 }
54-
});
55-
confetti({
56-
particleCount: 50,
57-
angle: 120,
58-
spread: 55,
59-
origin: { x: 1 }
60-
});
43+
confetti({ particleCount: 50, angle: 60, spread: 55, origin: { x: 0 } });
44+
confetti({ particleCount: 50, angle: 120, spread: 55, origin: { x: 1 } });
6145
}, 150);
62-
63-
// Final celebration
6446
setTimeout(() => {
65-
confetti({
66-
particleCount: 100,
67-
spread: 100,
68-
origin: { y: 0.6 },
69-
colors: ['#ccff00', '#3B82F6', '#FF5C00', '#9747FF']
70-
});
47+
confetti({ particleCount: 100, spread: 100, origin: { y: 0.6 }, colors: ['#ccff00', '#3B82F6', '#FF5C00', '#9747FF'] });
7148
}, 300);
7249
};
7350

@@ -78,7 +55,7 @@ export default function DatasetDetailPage() {
7855
}
7956
setPurchaseError(null);
8057
purchase(
81-
listing,
58+
listing,
8259
(result) => {
8360
setIsPurchasedState(true);
8461
setPurchaseTxDigest(result.digest);
@@ -96,13 +73,9 @@ export default function DatasetDetailPage() {
9673
);
9774
};
9875

99-
const [isDownloading, setIsDownloading] = useState(false);
100-
10176
const handleDownloadClick = async () => {
10277
if (!account || !listing || !isPurchased) return;
103-
10478
setIsDownloading(true);
105-
10679
try {
10780
const payload = {
10881
dataset_id: listing.id,
@@ -112,25 +85,15 @@ export default function DatasetDetailPage() {
11285
mime_type: listing.mimeType || 'application/octet-stream',
11386
file_name: listing.fileName || 'data.bin',
11487
};
115-
116-
console.log('=== DOWNLOAD REQUEST ===');
117-
console.log('Payload:', JSON.stringify(payload, null, 2));
118-
11988
const response = await fetch('/api/nautilus/download', {
12089
method: 'POST',
121-
headers: {
122-
'Content-Type': 'application/json',
123-
},
90+
headers: { 'Content-Type': 'application/json' },
12491
body: JSON.stringify(payload),
12592
});
126-
12793
if (!response.ok) {
12894
const errorData = await response.json();
129-
console.error('Error response:', errorData);
13095
throw new Error(errorData.error || `Download failed: ${response.status}`);
13196
}
132-
133-
// Get the blob and trigger download
13497
const blob = await response.blob();
13598
const url = window.URL.createObjectURL(blob);
13699
const a = document.createElement('a');
@@ -140,10 +103,8 @@ export default function DatasetDetailPage() {
140103
a.click();
141104
window.URL.revokeObjectURL(url);
142105
document.body.removeChild(a);
143-
144-
console.log('=== DOWNLOAD SUCCESS ===');
145106
} catch (error) {
146-
console.error('=== DOWNLOAD ERROR ===', error);
107+
console.error('Download error:', error);
147108
alert('Failed to download. Please try again.');
148109
} finally {
149110
setIsDownloading(false);
@@ -186,8 +147,8 @@ export default function DatasetDetailPage() {
186147
{ version: 'v1.0', date: 'Sep 15, 2024', isCurrent: false },
187148
],
188149
reviews: [
189-
{ id: 'r1', user: 'CryptoWhale_99', initials: 'CW', rating: 5, date: '2 days ago', comment: 'Extremely high quality data. The JSON formatting is clean and required zero cleanup before ingestion into our analytics pipeline. Worth every SUI.', bgColor: 'bg-blue-500' },
190-
{ id: 'r2', user: 'AlphaLab Research', initials: 'AL', rating: 4, date: '5 days ago', comment: 'Solid dataset. The consumer behavior section is particularly detailed. Would recommend for DeFi analysis.', bgColor: 'bg-primary' },
150+
{ id: 'r1', user: 'CryptoWhale_99', initials: 'CW', rating: 5, date: '2 days ago', comment: 'Extremely high quality data. Worth every SUI.', bgColor: 'bg-blue-500' },
151+
{ id: 'r2', user: 'AlphaLab Research', initials: 'AL', rating: 4, date: '5 days ago', comment: 'Solid dataset. Would recommend for DeFi analysis.', bgColor: 'bg-primary' },
191152
],
192153
features: ['Verified on-chain data', 'Encrypted with Seal Protocol', 'Stored on Walrus'],
193154
};
@@ -200,7 +161,7 @@ export default function DatasetDetailPage() {
200161
<span className="material-symbols-outlined">arrow_back</span>
201162
Back to Marketplace
202163
</Link>
203-
164+
204165
<div className="flex flex-col gap-2 mt-4">
205166
<div className="flex gap-2 flex-wrap">
206167
<span className="inline-flex items-center gap-1 rounded-full border-2 border-ink bg-white px-3 py-1 text-xs font-black uppercase tracking-wider shadow-sm text-ink">
@@ -216,13 +177,19 @@ export default function DatasetDetailPage() {
216177
Your Listing
217178
</span>
218179
)}
180+
{isPurchased && !isOwner && (
181+
<span className="inline-flex items-center gap-1 rounded-full border-2 border-green-500 bg-green-500/10 px-3 py-1 text-xs font-black uppercase tracking-wider text-green-600">
182+
<span className="material-symbols-outlined text-[14px]">check_circle</span>
183+
Purchased
184+
</span>
185+
)}
219186
</div>
220187
<h2 className="text-3xl font-black leading-tight text-ink">{listing.name}</h2>
221188
<p className="text-sm font-bold text-ink opacity-80">Updated: {dummyData.updatedAt}</p>
222189
</div>
223-
190+
224191
<hr className="border-t-2 border-ink border-dashed opacity-50" />
225-
192+
226193
<div className="grid grid-cols-1 gap-4">
227194
<div className="flex items-center justify-between p-4 bg-white border-2 border-ink rounded-xl shadow-hard-sm">
228195
<span className="text-sm font-bold text-gray-500 uppercase">Storage Size</span>
@@ -244,14 +211,14 @@ export default function DatasetDetailPage() {
244211
<span className="text-xl font-black text-ink">{listing.mimeType || dummyData.formats.join(' / ')}</span>
245212
</div>
246213
</div>
247-
214+
248215
<div className="mt-auto flex flex-col gap-4">
249216
<div className="flex flex-col">
250217
<span className="text-sm font-bold uppercase tracking-widest text-ink opacity-60">Current Price</span>
251218
<span className="text-5xl font-black tracking-tighter text-ink">{formatPrice(listing.price)}</span>
252219
<span className="text-sm font-bold text-ink opacity-60">≈ ${(Number(listing.price) / 1e9 * 1.25).toFixed(2)} USD</span>
253220
</div>
254-
221+
255222
{isOwner ? (
256223
<div className="bg-white/50 border-2 border-ink rounded-xl p-4">
257224
<p className="font-bold text-ink flex items-center gap-2">
@@ -260,8 +227,8 @@ export default function DatasetDetailPage() {
260227
</p>
261228
</div>
262229
) : isPurchased ? (
263-
<button
264-
onClick={handleDownloadClick}
230+
<button
231+
onClick={handleDownloadClick}
265232
disabled={isDownloading}
266233
className="group w-full rounded-xl border-2 border-ink bg-ink py-4 text-white shadow-hard transition-all hover:-translate-y-1 hover:bg-primary hover:text-ink disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:translate-y-0"
267234
>
@@ -283,9 +250,15 @@ export default function DatasetDetailPage() {
283250
<button onClick={() => setIsBuyModalOpen(true)} disabled={isPurchasing || !account} className="group w-full rounded-xl border-2 border-ink bg-ink py-4 text-white shadow-hard transition-all hover:-translate-y-1 hover:bg-primary hover:text-ink disabled:opacity-50 disabled:cursor-not-allowed">
284251
<div className="flex items-center justify-center gap-3">
285252
{isPurchasing ? (
286-
<><span className="material-symbols-outlined text-2xl animate-spin">sync</span><span className="text-xl font-black uppercase tracking-wide">Processing...</span></>
253+
<>
254+
<span className="material-symbols-outlined text-2xl animate-spin">sync</span>
255+
<span className="text-xl font-black uppercase tracking-wide">Processing...</span>
256+
</>
287257
) : (
288-
<><span className="material-symbols-outlined text-2xl group-hover:animate-bounce">shopping_cart_checkout</span><span className="text-xl font-black uppercase tracking-wide">Buy Now</span></>
258+
<>
259+
<span className="material-symbols-outlined text-2xl group-hover:animate-bounce">shopping_cart_checkout</span>
260+
<span className="text-xl font-black uppercase tracking-wide">Buy Now</span>
261+
</>
289262
)}
290263
</div>
291264
</button>
@@ -297,28 +270,16 @@ export default function DatasetDetailPage() {
297270

298271
{/* RIGHT PANEL */}
299272
<div className="flex-1 bg-white overflow-y-auto relative">
300-
<div className="absolute right-0 top-0 h-64 w-64 bg-gray-50 rounded-bl-[100px] -z-0"></div>
273+
<div className="absolute right-0 top-0 h-64 w-64 bg-gray-50 rounded-bl-[100px] z-0"></div>
301274
<div className="max-w-5xl mx-auto p-6 lg:p-12 flex flex-col gap-12 relative z-10">
302-
303275
{/* Hero Image */}
304276
<section>
305-
<div className="relative w-full aspect-[2/1] rounded-2xl border-2 border-ink overflow-hidden shadow-hard-lg group">
277+
<div className="relative w-full aspect-2/1 rounded-2xl border-2 border-ink overflow-hidden shadow-hard-lg group">
306278
{listing.imageUrl ? (
307-
<img
308-
src={listing.imageUrl}
309-
alt={listing.name}
310-
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-500"
311-
/>
279+
<img src={listing.imageUrl} alt={listing.name} className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-500" />
312280
) : (
313281
<>
314-
<div className="absolute inset-0 bg-gradient-to-br from-gray-800 to-gray-900" />
315-
<div className="absolute inset-0 opacity-20">
316-
<svg className="w-full h-full" viewBox="0 0 100 100" preserveAspectRatio="none">
317-
<path d="M0,50 Q25,30 50,50 T100,50" stroke="currentColor" strokeWidth="0.5" fill="none" className="text-accent-lime" />
318-
<path d="M0,60 Q25,40 50,60 T100,60" stroke="currentColor" strokeWidth="0.5" fill="none" className="text-accent-lime" />
319-
<path d="M0,40 Q25,20 50,40 T100,40" stroke="currentColor" strokeWidth="0.5" fill="none" className="text-accent-lime" />
320-
</svg>
321-
</div>
282+
<div className="absolute inset-0 bg-linear-to-br from-gray-800 to-gray-900" />
322283
<div className="absolute inset-0 flex items-center justify-center">
323284
<span className="material-symbols-outlined text-[120px] text-gray-600">dataset</span>
324285
</div>
@@ -332,8 +293,8 @@ export default function DatasetDetailPage() {
332293
<button className="h-10 w-10 bg-white border-2 border-ink rounded-lg flex items-center justify-center hover:bg-accent-lime transition-colors shadow-hard-sm text-ink">
333294
<span className="material-symbols-outlined">fullscreen</span>
334295
</button>
335-
<button onClick={handleDownloadClick} className="h-10 w-10 bg-white border-2 border-ink rounded-lg flex items-center justify-center hover:bg-accent-lime transition-colors shadow-hard-sm text-ink">
336-
<span className="material-symbols-outlined">download</span>
296+
<button onClick={handleDownloadClick} disabled={!isPurchased || isDownloading} className="h-10 w-10 bg-white border-2 border-ink rounded-lg flex items-center justify-center hover:bg-accent-lime transition-colors shadow-hard-sm text-ink disabled:opacity-50">
297+
<span className={`material-symbols-outlined ${isDownloading ? 'animate-spin' : ''}`}>{isDownloading ? 'sync' : 'download'}</span>
337298
</button>
338299
</div>
339300
</div>
@@ -352,7 +313,7 @@ export default function DatasetDetailPage() {
352313
{dummyData.features.map((f, i) => <li key={i}>{f}</li>)}
353314
</ul>
354315
</div>
355-
316+
356317
{/* IDs Section */}
357318
<div className="flex flex-col gap-3 p-4 bg-gray-50 rounded-xl border border-gray-200">
358319
<div className="flex items-center gap-2 flex-wrap">
@@ -361,9 +322,6 @@ export default function DatasetDetailPage() {
361322
<a href={`https://suiscan.xyz/testnet/object/${listing.id}`} target="_blank" rel="noopener noreferrer" className="h-6 w-6 rounded bg-white hover:bg-gray-100 flex items-center justify-center border" title="SuiScan">
362323
<svg className="w-3.5 h-3.5" viewBox="0 0 234 234" fill="none"><path d="M0 100C0 65 0 47.5 6.8 33C12.7 21.3 22.3 11.8 34 5.8C47.3 0 64.7 0 99.5 0H133.8C168.6 0 186 0 199.3 6.8C211 12.8 220.6 22.3 226.5 34C233.3 47.4 233.3 64.9 233.3 99.8V134.2C233.3 169.1 233.3 186.6 226.5 199.9C220.6 211.6 211 221.2 199.3 227.2C186 234 168.6 234 133.8 234H99.5C64.7 234 47.3 234 34 227.2C22.3 221.2 12.7 211.7 6.8 200C0 186.6 0 169.1 0 134.2V100Z" fill="#4C72FF"/><path d="M177 87C178.7 85.9 180.8 85.6 182.4 86.3C183.2 86.6 183.9 87.1 184.3 87.8C184.7 88.5 185 89.4 184.9 90.2L181.4 148.2C181 155.7 178.2 163.4 173.6 170.4C160.4 190.4 133.2 200 112.8 191.8C107.1 189.5 102.5 186 99.2 181.7C100 181.8 100.8 181.7 101.5 181.7C122.4 181.7 143.5 170.3 155.1 152.7C160.7 144.1 164 134.7 164.6 125.6L166.5 93.3L177 87Z" fill="white"/><path d="M150 63.6C151.7 62.5 153.8 62.3 155.5 62.9C156.3 63.3 156.9 63.8 157.4 64.5C157.9 65.2 158.1 66.1 158 66.9L154.5 125C154 132.5 151.3 140.1 146.7 147.1C133.5 167.2 106.3 176.7 85.9 168.5C80.1 166.2 75.6 162.7 72.3 158.4C73.1 158.4 73.9 158.4 74.6 158.4C95.6 158.4 116.6 147.1 128.2 129.4C133.9 120.8 137.1 111.4 137.7 102.3L139.6 70L150 63.6Z" fill="white"/><path d="M123 40.3C124.7 39.2 126.8 39 128.5 39.6C129.2 39.9 129.9 40.5 130.3 41.2C130.8 41.9 131 42.7 130.9 43.5L127.4 101.6C127 109.1 124.2 116.7 119.6 123.7C106.4 143.8 79.2 153.3 58.8 145.1C38.5 136.9 32.7 114 45.9 93.9C50.5 86.9 57.1 80.7 64.6 76.1L123 40.3Z" fill="white"/></svg>
363324
</a>
364-
<a href={`https://testnet.suivision.xyz/object/${listing.id}`} target="_blank" rel="noopener noreferrer" className="h-6 w-6 rounded bg-white hover:bg-gray-100 flex items-center justify-center border" title="SuiVision">
365-
<svg className="w-3.5 h-3.5" viewBox="0 0 24 24" fill="none"><path d="M0 6C0 2.68629 2.68629 0 6 0H18C21.3137 0 24 2.68629 24 6V18C24 21.3137 21.3137 24 18 24H6C2.68629 24 0 21.3137 0 18V6Z" fill="#4DA2FF"/><path d="M6.99748 5.28362L6.99748 11.0148L8.71768 12.0008L6.99731 12.987L6.99731 18.7182L11.9972 21.584L16.9971 18.7182L16.9971 12.9866L15.2769 12.0007L16.9973 11.0147L16.9973 5.28308L11.997 2.41732L6.99748 5.28362ZM11.6464 3.42366L11.6464 7.94789L7.69961 10.2105L7.69961 5.68623L11.6464 3.42366ZM12.3482 20.5781L12.3482 16.0535L16.2954 13.7912L16.2954 18.3159L12.3482 20.5781ZM15.9441 13.1879L11.9973 15.4501L8.05048 13.1879L9.41994 12.4031L11.9973 13.8803L14.575 12.4031L15.9441 13.1879ZM11.9973 10.1208L9.41964 11.5982L8.05048 10.8134L11.9973 8.55113L15.9445 10.8134L14.575 11.5982L11.9973 10.1208Z" fill="white"/></svg>
366-
</a>
367325
</div>
368326
<div className="flex items-center gap-2 flex-wrap">
369327
<span className="text-xs font-bold text-gray-500 uppercase w-20">Blob ID:</span>
@@ -372,7 +330,6 @@ export default function DatasetDetailPage() {
372330
<svg className="w-3.5 h-3.5" viewBox="0 0 24 24" fill="none"><circle cx="12" cy="10" r="8" fill="#36B5A8"/><ellipse cx="12" cy="22" rx="6" ry="2" fill="#36B5A8" opacity="0.5"/><circle cx="9" cy="8" r="1.5" fill="white"/><circle cx="15" cy="8" r="1.5" fill="white"/><path d="M9 13C9 13 10.5 15 12 15C13.5 15 15 13 15 13" stroke="white" strokeWidth="1.5" strokeLinecap="round"/></svg>
373331
</a>
374332
</div>
375-
{/* Purchase TX - only show if purchased */}
376333
{isPurchased && displayTxDigest && (
377334
<div className="flex items-center gap-2 flex-wrap pt-2 border-t border-gray-200 mt-1">
378335
<span className="text-xs font-bold text-green-600 uppercase w-20 flex items-center gap-1">
@@ -428,9 +385,7 @@ export default function DatasetDetailPage() {
428385
<div key={review.id} className="rounded-xl border-2 border-ink bg-white p-6 shadow-hard-sm hover:shadow-hard transition-shadow">
429386
<div className="flex justify-between items-start mb-4">
430387
<div className="flex items-center gap-3">
431-
<div className={`h-10 w-10 rounded-full border-2 border-ink flex items-center justify-center font-bold text-white shadow-sm ${review.bgColor}`}>
432-
{review.initials}
433-
</div>
388+
<div className={`h-10 w-10 rounded-full border-2 border-ink flex items-center justify-center font-bold text-white shadow-sm ${review.bgColor}`}>{review.initials}</div>
434389
<div className="flex flex-col">
435390
<span className="font-bold text-sm text-ink">{review.user}</span>
436391
<div className="flex text-accent-orange">
@@ -462,7 +417,7 @@ export default function DatasetDetailPage() {
462417
{isBuyModalOpen && (
463418
<div className="fixed inset-0 z-50 flex items-center justify-center bg-ink/50 backdrop-blur-sm p-4">
464419
<div className="w-full max-w-md bg-white rounded-2xl border-2 border-ink shadow-hard-lg p-6 relative">
465-
<button onClick={() => setIsBuyModalOpen(false)} className="absolute top-4 right-4 h-8 w-8 flex items-center justify-center rounded-lg hover:bg-gray-100">
420+
<button onClick={() => { setIsBuyModalOpen(false); setPurchaseError(null); }} className="absolute top-4 right-4 h-8 w-8 flex items-center justify-center rounded-lg hover:bg-gray-100">
466421
<span className="material-symbols-outlined text-ink">close</span>
467422
</button>
468423
<div className="flex flex-col gap-4">
@@ -501,7 +456,7 @@ export default function DatasetDetailPage() {
501456
</div>
502457
)}
503458

504-
{/* Preview Modal with Decryption Animation */}
459+
{/* Preview Modal */}
505460
<DecryptionPreviewModal
506461
isOpen={isPreviewModalOpen}
507462
onClose={() => setIsPreviewModalOpen(false)}
@@ -511,8 +466,7 @@ export default function DatasetDetailPage() {
511466
previewBytes={Number(listing.previewSize)}
512467
requesterAddress={account?.address || ''}
513468
mimeType={listing.mimeType || 'application/octet-stream'}
514-
fileName={listing.fileName || 'download'}
515469
/>
516470
</div>
517471
);
518-
}
472+
}

0 commit comments

Comments
 (0)