// Woodbury Operator — Reports & Analytics. Registers window.ReportsScreen.
(function () {
const NS = window.WoodburyPropertiesDesignSystem_7290ca;
const { Card, CardHeader, Button, Badge, StatCard, IconTile, Modal, Select, Eyebrow, ProgressBar } = NS;
function BarChart() {
const bars = [
{ label: "Lashibi TH", v: 56 }, { label: "Lashibi Exec", v: 88 }, { label: "Mirage", v: 92 },
{ label: "Onehive", v: 78 }, { label: "Hamlet", v: 100 }, { label: "Cant. City", v: 90 },
];
return (
{bars.map((b) => (
{b.v}%
= 95 ? "var(--success)" : "var(--brand)" }} />
{b.label}
))}
);
}
// Simple SVG line chart — occupancy trend over 6 months.
function TrendChart() {
const pts = [86, 88, 87, 90, 91, 92];
const labels = ["Mar", "Apr", "May", "Jun", "Jul", "Aug"];
const W = 320, H = 150, pad = 10;
const min = 82, max = 96;
const x = (i) => pad + (i * (W - pad * 2)) / (pts.length - 1);
const y = (v) => H - pad - ((v - min) / (max - min)) * (H - pad * 2);
const d = pts.map((v, i) => (i ? "L" : "M") + x(i).toFixed(1) + " " + y(v).toFixed(1)).join(" ");
const area = d + ` L ${x(pts.length - 1)} ${H - pad} L ${x(0)} ${H - pad} Z`;
return (
{labels.map((l) => {l})}
);
}
// Report catalog grouped by category — the reports admins actually run.
const CATALOG = [
{ group: "Occupancy & Leasing", tone: "brand", items: [
{ name: "Occupancy & Vacancy Summary", desc: "Occupied vs vacant units per estate, with trend.", icon: "building-2", scope: "both" },
{ name: "Lease Expiry & Renewal Pipeline", desc: "Leases ending in 30/60/90 days and renewal status.", icon: "calendar-clock", scope: "both" },
{ name: "Tenant Turnover & Retention", desc: "Move-ins, move-outs, and retention rate by site.", icon: "repeat", scope: "both" },
]},
{ group: "Maintenance & Facilities", tone: "accent", items: [
{ name: "Maintenance Performance", desc: "Tickets opened/closed, avg resolution, by category.", icon: "wrench", scope: "both" },
{ name: "Vendor SLA & Performance", desc: "Response time, jobs completed, and rating by vendor.", icon: "hard-hat", scope: "both" },
{ name: "Recurring Issues Analysis", desc: "Most frequent fault types by unit and estate.", icon: "chart-column", scope: "super" },
]},
{ group: "Screening & Compliance", tone: "success", items: [
{ name: "Applications Funnel", desc: "Applicants → verified → approved, with turnaround.", icon: "shield-check", scope: "both" },
{ name: "Inspections & Compliance", desc: "Inspections done/overdue and certificate expiries.", icon: "clipboard-check", scope: "both" },
{ name: "Communications Log", desc: "Broadcasts and resident notices sent, by site.", icon: "megaphone", scope: "both" },
]},
{ group: "Portfolio Oversight", tone: "sunken", items: [
{ name: "Cross-Site Portfolio Scorecard", desc: "All estates compared on occupancy, tickets, SLA.", icon: "layout-grid", scope: "super" },
{ name: "Staff Activity & Audit Summary", desc: "Actions per user and role across the portfolio.", icon: "scroll-text", scope: "super" },
]},
];
const RECENT = [
{ name: "Q1 2026 Occupancy Summary", meta: "Generated 01 Apr · PDF", icon: "trending-up", tone: "brand" },
{ name: "Maintenance Performance — Accra", meta: "Generated 28 Mar · PDF", icon: "wrench", tone: "accent" },
{ name: "Lease Expiry Forecast", meta: "Generated 02 Mar · XLSX", icon: "calendar-clock", tone: "success" },
];
function ReportsScreen() {
const isSuper = (window.WB_ACTIVE_ROLE || "super") === "super";
const [period, setPeriod] = React.useState("This Quarter");
const [pick, setPick] = React.useState(false);
const [gen, setGen] = React.useState(null); // null | {name} preselected
const catalog = CATALOG.map((c) => ({ ...c, items: c.items.filter((it) => it.scope === "both" || (it.scope === "super" && isSuper)) })).filter((c) => c.items.length);
const allTypes = catalog.flatMap((c) => c.items.map((it) => it.name));
return (
} />
window.WBNavigate && window.WBNavigate("Properties")} label="Portfolio Occupancy" value="92%" icon="building-2" iconTone="success" emphasis="success" delta="+1.2%" />
window.WBNavigate && window.WBNavigate("Maintenance")} label="Avg. Resolution" value="1.4d" icon="clock" iconTone="accent" />
window.WBNavigate && window.WBNavigate("Leases")} label="Renewals Due" value="5" icon="calendar-clock" iconTone="brand" />
{/* Charts */}
{/* Maintenance breakdown */}
{[["Plumbing", 34, "brand"], ["HVAC / Cooling", 28, "accent"], ["Electrical", 19, "success"], ["Structural / Roofing", 12, "sunken"], ["Access & Gates", 5, "brand"], ["Appliances", 2, "accent"]].map(([label, v, tone]) => (
))}
{/* Report library */}
Report Library
{allTypes.length} report types
{catalog.map((cat) => (
{cat.group}
{cat.items.map((it) => (
))}
))}
{/* Recent */}
{RECENT.map((r, i) => (
))}
{/* Period picker */}
setPick(false)} icon="calendar" title="Reporting Period" subtitle="Choose the time range for analytics." width={420}>
{["This Month", "This Quarter", "Year to Date", "Last 12 Months"].map((p) => (
))}
{/* Generate report */}
setGen(null)} icon="file-chart-column" title="Generate Report" subtitle="Build a new analytics export."
footer={}>
{gen && (
)}
);
}
window.ReportsScreen = ReportsScreen;
})();