/* @component-map * App — Main container, role selection, tab navigation [app.jsx] * SubmitRequest — Tenant request submission form [components/SubmitRequest.jsx] * MyRequests — Tenant view of their submitted requests [components/MyRequests.jsx] * ManagerDashboard — Manager dashboard with all requests sorted by urgency [components/ManagerDashboard.jsx] * RequestDetail — Detailed view modal for a single request [components/RequestDetail.jsx] * StatsBar — Overview statistics header [components/StatsBar.jsx] * @end-component-map */ // DEPLOY_CONFIG: {"triggers": [{"name": "notify_managers_on_urgent_request", "on": "collection.update", "collection": "requests", "actions": [{"type": "email", "to": "managers", "subject": "Urgent request marked", "body": "A request has been marked urgent. Please review it as soon as possible."}]}, {"name": "notify_tenant_on_request_status_update", "on": "collection.update", "collection": "requests", "actions": [{"type": "email", "to": "tenant", "subject": "Your request status has been updated", "body": "Your request status has changed. Please check the latest update in the app."}]}, {"name": "escalate_open_request_after_48_hours", "on": "collection.update", "collection": "requests", "actions": [{"type": "email", "to": "managers", "subject": "Request escalated after 48 hours open", "body": "A request has remained open for 48 hours and has been escalated to higher/urgent priority. Please review it immediately."}]}]} import { useEffect, useMemo, useState } from 'react'; import { useAuth } from '@deplixo/sdk'; import { SubmitRequest } from './components/SubmitRequest.jsx'; import { MyRequests } from './components/MyRequests.jsx'; import { ManagerDashboard } from './components/ManagerDashboard.jsx'; // PROGRESS:sc_001:complete:Setting up the maintenance request system const ROLE_COLLECTION = 'app_user_roles'; function App() { const { user, loading, login, logout } = useAuth(); const [role, setRole] = useState(null); const [tab, setTab] = useState('submit'); const [roleLoading, setRoleLoading] = useState(true); const [roleError, setRoleError] = useState(''); const authMethods = useMemo(() => ['google'], []); useEffect(() => { let cancelled = false; async function loadRole() { if (!user) { if (!cancelled) { setRole(null); setRoleLoading(false); } return; } setRoleLoading(true); setRoleError(''); try { const res = await fetch(`/api/collections/${ROLE_COLLECTION}?personal=true`); if (!res.ok) throw new Error('Unable to load role'); const data = await res.json(); const match = Array.isArray(data?.items) ? data.items.find((item) => item.userId === user.id || item.email === user.email) : null; if (!cancelled) { setRole(match?.role || null); setRoleLoading(false); setTab('submit'); } } catch (err) { if (!cancelled) { setRole(null); setRoleError('Could not load your saved role.'); setRoleLoading(false); } } } loadRole(); return () => { cancelled = true; }; }, [user]); const saveRole = async (nextRole) => { if (!user) return; setRoleError(''); setRole(nextRole); try { const res = await fetch(`/api/collections/${ROLE_COLLECTION}?personal=true`); const data = res.ok ? await res.json() : { items: [] }; const existing = Array.isArray(data?.items) ? data.items.find((item) => item.userId === user.id || item.email === user.email) : null; if (existing?.id) { await fetch(`/api/collections/${ROLE_COLLECTION}/${existing.id}?personal=true`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ role: nextRole, userId: user.id, email: user.email, name: user.name }), }); } else { await fetch(`/api/collections/${ROLE_COLLECTION}?personal=true`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ role: nextRole, userId: user.id, email: user.email, name: user.name }), }); } } catch (err) { setRoleError('Role saved locally, but could not sync right now.'); } }; if (loading || roleLoading) { return
Signing in...
; } if (!user) { return (
🏢

Maintenance Hub

Apartment Building Maintenance Request System

); } if (!role) { return (
🏢

Maintenance Hub

Choose how you want to use the app

{roleError ?

{roleError}

: null}
); } if (role === 'manager') { return ; } return (

🏢 Maintenance Hub

Tenant
{tab === 'submit' && setTab('my')} />} {tab === 'my' && }
); } ReactDOM.createRoot(document.getElementById("root")).render();