/* @component-map * App — Main container, tab navigation [app.jsx] * BrowseTools — Browse neighbor tools with search/filter [components/BrowseTools.jsx] * MyTools — Manage your own tool listings [components/MyTools.jsx] * BorrowRequests — View and manage borrow requests [components/BorrowRequests.jsx] * @end-component-map */ // DEPLOY_CONFIG: {"triggers": [{"name": "borrow_request_owner_email_notification", "on": "collection.add", "collection": "borrow_requests", "actions": [{"type": "email", "to": "{{tool_owner_email}}", "subject": "New borrow request submitted", "body": "A new borrow request was submitted.\n\nRequest details:\n- Request ID: {{id}}\n- Borrower: {{borrower_name}}\n- Tool: {{tool_name}}\n- Requested dates: {{start_date}} to {{end_date}}\n- Message: {{message}}\n\nPlease review the request in the Deplixo app."}]}, {"name": "borrower_due_date_reminder", "on": "collection.add", "collection": "borrow_requests", "actions": [{"type": "email", "to": "{{borrower_email}}", "subject": "Reminder: tool due tomorrow", "body": "Hi {{borrower_name}},\n\nThis is a reminder that your borrowed tool, {{tool_name}}, is due on {{end_date}}.\n\nPlease return it by the due date to avoid any issues.\n\nBorrow request ID: {{id}}"}]}], "cron": [{"name": "overdue_tool_alerts", "schedule": "0 9 * * *", "action": "event", "config": {"event_type": "overdue_tool_scan"}}]} import { useEffect, useMemo, useRef, useState } from 'react'; import { useAuth, useCollection, renderMap } from '@deplixo/sdk'; import { BrowseTools } from './components/BrowseTools.jsx'; import { MyTools } from './components/MyTools.jsx'; import { BorrowRequests } from './components/BorrowRequests.jsx'; function EventMap({ markers = [], height = '360px' }) { const containerRef = useRef(null); useEffect(() => { if (!containerRef.current) return; const safeMarkers = markers .filter(m => Number.isFinite(m.lat) && Number.isFinite(m.lng)) .map(m => ({ lat: m.lat, lng: m.lng, popup: `${String(m.title || 'Tool').replace(//g, '>')}
${String(m.description || '').replace(//g, '>')}
`, })); if (safeMarkers.length === 0) return; const first = safeMarkers[0]; renderMap(containerRef.current, { center: [first.lat, first.lng], zoom: safeMarkers.length > 1 ? 11 : 13, markers: safeMarkers, }); }, [markers]); return ; } function App() { const { user, loading, login, logout } = useAuth(); const [tab, setTab] = useState('browse'); const { items: browseTools } = useCollection('tools'); const { items: myTools } = useCollection('tools', { personal: true }); const isVerifiedMember = Boolean(user?.verified || user?.isVerified || user?.memberVerified); const verifiedLabel = isVerifiedMember ? 'Verified neighborhood member' : 'Unverified member'; const userDisplayName = user?.name || user?.displayName || user?.email?.split?.('@')?.[0] || 'Neighbor'; const mapMarkers = useMemo(() => { const tools = (browseTools?.length ? browseTools : myTools || []); return tools .map(tool => { const lat = Number(tool?.lat ?? tool?.latitude ?? tool?.location?.lat); const lng = Number(tool?.lng ?? tool?.longitude ?? tool?.location?.lng); if (!Number.isFinite(lat) || !Number.isFinite(lng)) return null; return { lat, lng, title: tool?.name || tool?.toolName || 'Tool', description: `${tool?.category || 'Tool'}${tool?.ownerName ? ` • ${tool.ownerName}` : ''}`, }; }) .filter(Boolean); }, [browseTools, myTools]); if (loading) { return (Sign in with Google to continue. Access is restricted to verified neighborhood members.