import { useEffect, useMemo, useState } from 'react'; import { useCollection, useReactions, share } from '@deplixo/sdk'; import { SpaceDirectory } from './components/SpaceDirectory.jsx'; import { SpaceMap } from './components/SpaceMap.jsx'; import { SpaceDetail } from './components/SpaceDetail.jsx'; import { AddSpaceForm } from './components/AddSpaceForm.jsx'; function App() { const [activeTab, setActiveTab] = useState('list'); const [selectedSpace, setSelectedSpace] = useState(null); const [showAddForm, setShowAddForm] = useState(false); const [filters, setFilters] = useState({ amenities: [], priceRange: 'all', search: '', nearMe: false, sortBy: 'relevance', favoritesOnly: false }); const [userLocation, setUserLocation] = useState(null); const [locationStatus, setLocationStatus] = useState('idle'); const [locationError, setLocationError] = useState(''); const [shareStatus, setShareStatus] = useState(''); const { items: favoriteItems, loading: favoritesLoading, add: addFavoriteRecord, remove: removeFavoriteRecord, search: searchFavorites, } = useCollection('space-favorites', { personal: true }); useEffect(() => { if (!navigator.geolocation) { setLocationStatus('unsupported'); return; } setLocationStatus('locating'); navigator.geolocation.getCurrentPosition( (position) => { const nextLocation = { lat: position.coords.latitude, lng: position.coords.longitude }; if (nextLocation && typeof nextLocation.lat === 'number' && typeof nextLocation.lng === 'number') { setUserLocation(nextLocation); setLocationStatus('ready'); setLocationError(''); } else { setLocationStatus('error'); setLocationError('Unable to determine your location.'); } }, (error) => { setLocationStatus('error'); setLocationError(error && error.message ? error.message : 'Unable to determine your location.'); }, { enableHighAccuracy: true, timeout: 10000, maximumAge: 300000 } ); }, []); const tabs = [ { id: 'list', label: '📋 Directory', icon: '📋' }, { id: 'map', label: '🗺️ Map View', icon: '🗺️' }, { id: 'favorites', label: '⭐ Favorites', icon: '⭐' }, ]; const favoriteIds = useMemo(() => { return new Set( (favoriteItems || []) .map((item) => item?.spaceId || item?.targetId || item?.id || item?.space?.id) .filter(Boolean) .map(String) ); }, [favoriteItems]); const isFavorite = (spaceId) => favoriteIds.has(String(spaceId)); const favoriteSpace = async (space) => { if (!space || !space.id || isFavorite(space.id)) return; await addFavoriteRecord({ spaceId: space.id, spaceSnapshot: space, createdAt: new Date().toISOString(), }); }; const unfavoriteSpace = async (space) => { if (!space || !space.id) return; const match = (favoriteItems || []).find((item) => String(item?.spaceId || item?.targetId || item?.space?.id || item?.id) === String(space.id)); if (match?.id) { await removeFavoriteRecord(match.id); return; } const bySearch = await searchFavorites(String(space.id)); const fallbackMatch = (bySearch || []).find((item) => String(item?.spaceId || item?.targetId || item?.space?.id || item?.id) === String(space.id)); if (fallbackMatch?.id) { await removeFavoriteRecord(fallbackMatch.id); } }; const handleToggleFavorite = async (space) => { if (isFavorite(space?.id)) { await unfavoriteSpace(space); } else { await favoriteSpace(space); } }; const favoriteSpaces = useMemo(() => { return (favoriteItems || []) .map((item) => item?.spaceSnapshot || item?.space || item) .filter((space) => space && space.id); }, [favoriteItems]); const buildSharePayload = (space) => { if (!space?.id) return null; const title = space.name || 'Recommended coworking space'; const url = typeof window !== 'undefined' ? `${window.location.origin}${window.location.pathname}?space=${encodeURIComponent(space.id)}` : `?space=${encodeURIComponent(space.id)}`; const summary = `${title}${space.address ? ` • ${space.address}` : ''}`; const payload = { title, text: summary, url, spaceId: space.id, space, }; return payload; }; const shareSpace = async (space) => { const payload = buildSharePayload(space); if (!payload) return; try { if (navigator.share) { await navigator.share({ title: payload.title, text: payload.text, url: payload.url, }); setShareStatus(`Shared ${payload.title}`); return; } const shareText = `${payload.title}\n${payload.text}\n${payload.url}`; if (navigator.clipboard?.writeText) { await navigator.clipboard.writeText(shareText); setShareStatus(`Share link copied for ${payload.title}`); return; } window.prompt('Copy this share link:', shareText); setShareStatus(`Share payload ready for ${payload.title}`); } catch (error) { setShareStatus(error?.message ? error.message : 'Unable to share this space right now.'); } }; const handleShareRecommended = async (spaces) => { const recommended = Array.isArray(spaces) ? spaces.filter(Boolean) : []; if (!recommended.length) return; if (recommended.length === 1) { await shareSpace(recommended[0]); return; } const topSpace = recommended[0]; const payload = { title: `Top recommended spaces: ${recommended.slice(0, 3).map((space) => space.name).filter(Boolean).join(', ')}`, text: recommended.slice(0, 3).map((space, index) => `${index + 1}. ${space.name || 'Untitled space'}${space.address ? ` — ${space.address}` : ''}`).join('\n'), url: typeof window !== 'undefined' ? `${window.location.origin}${window.location.pathname}?space=${encodeURIComponent(topSpace.id)}` : `?space=${encodeURIComponent(topSpace.id)}`, spaces: recommended.map((space) => ({ id: space.id, name: space.name, address: space.address })), }; try { if (navigator.share) { await navigator.share({ title: payload.title, text: payload.text, url: payload.url, }); setShareStatus('Shared recommended spaces'); return; } const shareText = `${payload.title}\n\n${payload.text}\n\n${payload.url}`; if (navigator.clipboard?.writeText) { await navigator.clipboard.writeText(shareText); setShareStatus('Recommended spaces share link copied'); return; } window.prompt('Copy this share payload:', shareText); setShareStatus('Recommended spaces share payload ready'); } catch (error) { setShareStatus(error?.message ? error.message : 'Unable to share recommendations right now.'); } }; return (
🏢

CoWork Finder

Your co-working space directory

{(locationStatus === 'locating' || locationStatus === 'unsupported' || locationStatus === 'error') && (
{locationStatus === 'locating' && 📍 Detecting your location to show nearby spaces…} {locationStatus === 'unsupported' && 📍 Geolocation isn’t supported in this browser, but you can still browse all spaces.} {locationStatus === 'error' && 📍 {locationError || 'Location unavailable.'} You can still browse all spaces.}
)} {shareStatus &&
🔗 {shareStatus}
} {activeTab === 'favorites' && (

Your Favorites

Saved spaces synced to your personal collection.

{favoritesLoading ? (
Loading your saved spaces…
) : favoriteSpaces.length > 0 ? ( ) : (

No favorites yet

Save spaces from cards or detail views to build your personal collection.

)}
)} {activeTab === 'list' && ( )} {activeTab === 'map' && ( )}
{selectedSpace && ( setSelectedSpace(null)} favoriteIds={favoriteIds} onToggleFavorite={handleToggleFavorite} onShareSpace={shareSpace} /> )} {showAddForm && ( setShowAddForm(false)} /> )}
); } function ReactionBar({ targetId, countsOverride = null, onReact = null, loading: externalLoading = false }) { const { counts, toggle, loading } = useReactions(targetId); const emojis = [ { emoji: '💻', label: 'Great wifi' }, { emoji: '🤫', label: 'Quiet' }, { emoji: '☕', label: 'Good coffee' }, ]; const safeCounts = countsOverride || counts || {}; const isLoading = externalLoading || loading; if (isLoading && !countsOverride) return null; return (
{emojis.map(({ emoji, label }) => ( ))}
); } ReactDOM.createRoot(document.getElementById("root")).render();