import { useEffect, useMemo, useRef, useState } from 'react'; import { generatePDF, useAuth, useCollection } from '@deplixo/sdk'; import { StatsHeader } from './components/StatsHeader.jsx'; import { WishlistView } from './components/WishlistView.jsx'; import { AddItemModal } from './components/AddItemModal.jsx'; const COLLECTION_OPTIONS = [ { value: 'birthday', label: 'Birthday', emoji: 'πŸŽ‚' }, { value: 'holiday', label: 'Holiday', emoji: 'πŸŽ„' }, { value: 'self', label: 'Self', emoji: 'πŸ’–' }, ]; function App() { const { user, loading: authLoading, logout } = useAuth(); const [showModal, setShowModal] = useState(false); const [editItem, setEditItem] = useState(null); const [activeCollection, setActiveCollection] = useState('all'); const [isPublicView, setIsPublicView] = useState(false); const [publicShareId, setPublicShareId] = useState(''); const [shareLinkCopied, setShareLinkCopied] = useState(false); const [pdfExporting, setPdfExporting] = useState(false); const reportRef = useRef(null); const { items, loading, add, update, remove } = useCollection('wishlist', { personal: true }); useEffect(() => { const readModeFromLocation = () => { if (typeof window === 'undefined') return; const url = new URL(window.location.href); const share = url.searchParams.get('share'); const mode = url.searchParams.get('mode'); setPublicShareId(share || ''); setIsPublicView(Boolean(share || mode === 'shared')); }; readModeFromLocation(); window.addEventListener('popstate', readModeFromLocation); return () => window.removeEventListener('popstate', readModeFromLocation); }, []); useEffect(() => { setShowModal(false); setEditItem(null); }, [isPublicView]); const handleEdit = (item) => { if (isPublicView) return; setEditItem(item); setShowModal(true); }; const handleClose = () => { setShowModal(false); setEditItem(null); }; const handleSave = async (data) => { if (isPublicView) return; if (editItem) { await update(editItem.id, data); } else { await add(data); } handleClose(); }; const normalizedItems = useMemo(() => { return (items || []).map((item) => ({ ...item, collection: item.collection || 'self', })); }, [items]); const filteredItems = useMemo(() => { if (activeCollection === 'all') return normalizedItems; return normalizedItems.filter((item) => item.collection === activeCollection); }, [normalizedItems, activeCollection]); const groupedItems = useMemo(() => { return COLLECTION_OPTIONS.reduce((acc, option) => { acc[option.value] = normalizedItems.filter((item) => item.collection === option.value); return acc; }, {}); }, [normalizedItems]); const statsSummary = useMemo(() => { const totalWishlistValue = filteredItems.reduce((sum, item) => { const target = Number(item.target_price) || 0; return sum + target; }, 0); const readyToBuyCount = filteredItems.filter((item) => { const current = Number(item.current_price); const target = Number(item.target_price); return Number.isFinite(current) && Number.isFinite(target) && current <= target; }).length; const closestDeal = filteredItems.reduce((best, item) => { const current = Number(item.current_price); const target = Number(item.target_price); if (!Number.isFinite(current) || !Number.isFinite(target)) return best; const gap = Math.max(current - target, 0); if (!best || gap < best.gap) { return { name: item.name || 'Unnamed item', gap }; } return best; }, null); return { totalItems: filteredItems.length, totalWishlistValue, readyToBuyCount, closestDeal, }; }, [filteredItems]); const buildShareUrl = () => { if (typeof window === 'undefined') return ''; const url = new URL(window.location.href); url.searchParams.set('share', publicShareId || 'wishlist'); url.searchParams.set('mode', 'shared'); return url.toString(); }; const handleShare = async () => { const shareUrl = buildShareUrl(); if (!shareUrl) return; try { if (navigator?.clipboard?.writeText) { await navigator.clipboard.writeText(shareUrl); setShareLinkCopied(true); window.setTimeout(() => setShareLinkCopied(false), 2000); } } catch (error) { window.open(shareUrl, '_blank', 'noopener,noreferrer'); } }; const handleExportPDF = async () => { if (typeof window === 'undefined' || !reportRef.current || pdfExporting) return; try { setPdfExporting(true); await generatePDF(reportRef.current, { filename: 'wishlist.pdf', margin: 10, }); } finally { setPdfExporting(false); } }; if (authLoading) { return (
✨

Signing you in...

Please wait while we load your wishlist.

); } if (isPublicView) { return (
πŸ’

Shared Wishlist

Read-only view

This wishlist is publicly shared

Visitors can view items but cannot edit or add anything.

{COLLECTION_OPTIONS.map((option) => ( ))}

Shared Wishlist Report

Generated from the current filtered wishlist view.

{}} onAdd={() => {}} groupedItems={groupedItems} activeCollection={activeCollection} collectionOptions={COLLECTION_OPTIONS} readOnly={true} publicView={true} />
); } if (!user) { return (
πŸ’

My Wishlist

🎁

Sign in to manage your wishlist

Use Google sign-in to keep your wishlist personal and synced to your account.

You’ll be redirected to Deplixo’s login page to continue.
); } return (
πŸ’

My Wishlist

Welcome, {user.name}
{COLLECTION_OPTIONS.map((option) => ( ))}

My Wishlist Report

Export includes your current filtered items and summary stats.

setShowModal(true)} groupedItems={groupedItems} activeCollection={activeCollection} collectionOptions={COLLECTION_OPTIONS} readOnly={false} publicView={false} /> {showModal && ( )}
); } export default App; ReactDOM.createRoot(document.getElementById('root')).render();