// Woodbury Resident Portal — shared data, header, toast, modal helpers. (function () { window.WBR = { resident: { name: "Kofi Mensah", first: "Kofi", email: "kofi.mensah@yahoo.com", phone: "+233 20 887 3341", avatar: "../../assets/images/av-kofi.jpg", property: "Lashibi Townhouses", unit: "House 1", emergency: "Akosua Mensah · +233 24 118 0092", moveIn: "01 Jun 2024", leaseEnds: "28 May 2026", leaseLeft: 28, term: "12 months", }, lease: { ref: "WB-LSE-2024-0417", type: "Assured Shorthold Tenancy", term: "12 months", bedrooms: 3, start: "01 Jun 2024", end: "28 May 2026", left: 28, total: 365, landlord: "Woodbury Properties Ltd", manager: "Lashibi Townhouses Office", terms: [ { icon: "calendar-days", label: "Tenancy term", value: "12 months (renewable)" }, { icon: "home", label: "Property", value: "Lashibi Townhouses · House 1" }, { icon: "bed", label: "Bedrooms", value: "3-bedroom townhouse" }, { icon: "paw-print", label: "Pets", value: "By written permission" }, { icon: "users", label: "Occupancy", value: "Up to 5 residents" }, { icon: "wrench", label: "Maintenance", value: "Landlord-covered (structural)" }, ], }, notifications: [ { id: "n1", icon: "user-check", tone: "accent", title: "Vendor assigned", body: "AirCool HVAC will attend your AC request (MR-2041).", time: "2h ago", unread: true, go: ["Requests", "MR-2041"] }, { id: "n2", icon: "droplet", tone: "accent", title: "Water maintenance", body: "Supply interrupted tomorrow 9am–12pm.", time: "5h ago", unread: true, go: ["Announcements"] }, { id: "n3", icon: "calendar", tone: "brand", title: "Inspection scheduled", body: "Routine unit inspection on 22 Aug, 11:00.", time: "1d ago", unread: true, go: ["Announcements"] }, { id: "n4", icon: "check-check", tone: "success", title: "Request resolved", body: "Your Wi-Fi router replacement is complete.", time: "3d ago", unread: false, go: ["Requests", "MR-1975"] }, ], requests: [ { id: "MR-2041", title: "AC not cooling", cat: "HVAC / Cooling", icon: "wind", stage: 1, priority: "Urgent", tone: "danger", desc: "Unit making a loud grinding noise and not cooling. Started overnight.", vendor: "AirCool HVAC Services", reported: "Today · 09:12", log: [ { icon: "user-check", tone: "accent", title: "Vendor assigned", body: "AirCool HVAC Services assigned.", time: "Today · 09:40" }, { icon: "wrench", tone: "danger", title: "Request submitted", body: "You reported this issue.", time: "Today · 09:12" } ] }, { id: "MR-1998", title: "Repaint living room wall", cat: "General", icon: "paintbrush", stage: 4, priority: "Low", tone: "success", desc: "Scuff marks on the north wall.", vendor: "Woodbury Facilities", reported: "08 Mar", log: [ { icon: "check-check", tone: "success", title: "Resolved", body: "Repaint completed and signed off.", time: "12 Mar · 16:40" }, { icon: "wrench", tone: "brand", title: "Request submitted", body: "You reported this issue.", time: "08 Mar · 10:00" } ] }, { id: "MR-1975", title: "Wi-Fi router replacement", cat: "Appliances", icon: "wifi", stage: 4, priority: "Medium", tone: "success", desc: "Router not holding connection.", vendor: "Accra Electricals Ltd", reported: "31 Jan", log: [ { icon: "check-check", tone: "success", title: "Resolved", body: "New router installed.", time: "02 Feb · 14:20" } ] }, ], stages: ["Submitted", "Assigned", "Scheduled", "In Progress", "Resolved"], announcements: [ { id: "a1", icon: "droplet", tone: "accent", title: "Scheduled water maintenance", body: "Water supply interrupted tomorrow 9am–12pm for pipe maintenance.", time: "2h ago", unread: true }, { id: "a2", icon: "shield-check", tone: "success", title: "Gate access upgrade complete", body: "Your new gate remote code is active. Contact the office for a physical fob.", time: "3d ago", unread: false }, { id: "a3", icon: "calendar", tone: "brand", title: "Quarterly inspection", body: "Routine unit inspection scheduled for 22 Aug, 11:00. No action needed.", time: "5d ago", unread: false }, ], documents: [ { name: "Signed Tenancy Agreement.pdf", meta: "248 KB · Signed 12 Apr", tag: "Lease", tone: "brand" }, { name: "House Rules & Community Guide.pdf", meta: "1.2 MB · Updated Jan 2026", tag: "Guide", tone: "neutral" }, { name: "ID Verification.pdf", meta: "512 KB · Verified 10 Apr", tag: "Screening", tone: "success" }, { name: "Move-in Inspection Report.pdf", meta: "890 KB · 01 Jun 2024", tag: "Inspection", tone: "accent" }, ], messages: [ { me: false, text: "Akwaaba Kofi! This is the Lashibi Townhouses office. How can we help?", time: "09:00" }, { me: true, text: "Hi, the AC in my unit is making a loud noise and not cooling.", time: "09:12" }, { me: false, text: "Sorry to hear that — I've logged it as urgent and assigned AirCool HVAC. You can track progress under Requests.", time: "09:31" }, ], }; // ========================================================================== // DEV BACKEND WIRING (WOO-19) — hydrate the resident portal from wb-dev-api. // Same-origin GET /api/resident/bootstrap (Caddy proxies /api/* -> :8090). // Synchronous so server data is in place before any screen renders; falls // back SILENTLY to the inline seed above if the API is unreachable. // ========================================================================== (function wireDevApi() { window.WBR_API_BASE = "/api/resident"; try { var xhr = new XMLHttpRequest(); xhr.open("GET", window.WBR_API_BASE + "/bootstrap", false); // sync: block until seeded xhr.withCredentials = true; xhr.send(null); if (xhr.status !== 200) throw new Error("HTTP " + xhr.status); var B = JSON.parse(xhr.responseText); var R = window.WBR; if (B.resident) R.resident = B.resident; if (B.lease) R.lease = B.lease; if (B.notifications) R.notifications = B.notifications; if (B.requests) R.requests = B.requests; if (B.stages) R.stages = B.stages; if (B.announcements) R.announcements = B.announcements; if (B.documents) R.documents = B.documents; if (B.messages) R.messages = B.messages; window.WBR_DATA_SOURCE = "dev.api"; } catch (e) { window.WBR_DATA_SOURCE = "inline-fallback"; if (window.console && console.warn) console.warn("[WOO-19] dev.api resident bootstrap unavailable — using inline seed:", e && e.message); } // Write-through: a submitted maintenance request also POSTs to dev.api, // where it surfaces to the operator portal (resident -> operator bridge). window.WBRsubmitRequest = function (payload) { try { var x = new XMLHttpRequest(); x.open("POST", window.WBR_API_BASE + "/requests", true); x.withCredentials = true; x.setRequestHeader("Content-Type", "application/json"); x.send(JSON.stringify(payload || {})); } catch (e) {} }; })(); window.WBRHeader = function ({ eyebrow, title, sub, actions }) { return (
{sub}
}{message}
} {action &&