root = Card([header, healthSummary, controls, activeProjects, overdueMilestones, budgetSection, teamUtilization, risksSection, upcomingDeadlines, paceSection, blockedSection, resourceRequest])
header = CardHeader("Portfolio Review", "Q3 FY2024 · 12 active projects")
healthSummary = Callout("success", "Portfolio healthy", "On track with 2 at risk; delivery pace stable and budget within tolerance.")
controls = Card([quarterForm, exportArchive], "sunk", "row", "l")
quarterForm = Form("quarter-select", quarterButtons, [quarterField])
quarterField = FormControl("Quarter", quarterSelect)
quarterSelect = Select("quarter", [q1, q2, q3, q4], "Select quarter", null, "Q3 2024")
q1 = SelectItem("Q1 2024", "Q1 2024")
q2 = SelectItem("Q2 2024", "Q2 2024")
q3 = SelectItem("Q3 2024", "Q3 2024")
q4 = SelectItem("Q4 2024", "Q4 2024")
quarterButtons = Buttons([applyQuarter])
applyQuarter = Button("Apply Quarter")
exportArchive = Buttons([exportBtn, archiveLink])
exportBtn = Button("Export Review")
archiveLink = Button("Archive finished project", null, "secondary")
activeProjects = Card([activeHeading, projectsTable], "sunk")
activeHeading = Heading("Active Projects", "h2")
projectsTable = Table([projectCol, ownerCol, deadlineCol, healthCol])
projectCol = Col("Project", ["Atlas Platform", "Nimbus CRM", "Orion Mobile", "Vega Analytics", "Pulsar API"])
ownerCol = Col("Owner", ["A. Chen", "M. Okafor", "L. Rossi", "S. Johansson", "D. Kim"])
deadlineCol = Col("Deadline", ["2024-11-15", "2024-12-01", "2024-10-30", "2025-01-20", "2024-11-28"])
healthCol = Col("Health", ["On track", "At risk", "On track", "At risk", "On track"])
overdueMilestones = Card([overdueHeading, overdueList], "sunk")
overdueHeading = Heading("Overdue Milestones", "h2")
overdueList = ListBlock([m1, m2, m3, m4], "number")
m1 = ListItem("Beta sign-off", "Atlas Platform · due Oct 12")
m2 = ListItem("Data migration", "Vega Analytics · due Oct 8")
m3 = ListItem("API v2 freeze", "Pulsar API · due Oct 15")
m4 = ListItem("App store submission", "Orion Mobile · due Oct 5")
budgetSection = Card([budgetHeading, budgetChart], "sunk")
budgetHeading = Heading("Budget: Spent vs Allocation", "h2")
budgetChart = HorizontalBarChart(["Atlas", "Nimbus", "Orion", "Vega", "Pulsar"], [spentSeries, allocSeries], "grouped", "Amount ($K)", "Project")
spentSeries = Series("Spent", [640, 420, 310, 580, 260])
allocSeries = Series("Allocation", [800, 500, 400, 750, 300])
teamUtilization = Card([utilHeading, utilChart], "sunk")
utilHeading = Heading("Team Utilization", "h2")
utilChart = HorizontalBarChart(["A. Chen", "M. Okafor", "L. Rossi", "S. Johansson", "D. Kim"], [utilSeries], "grouped", "Utilization %", "Team member")
utilSeries = Series("Utilization", [85, 92, 78, 95, 70])
risksSection = Card([risksHeading, risksTable], "sunk")
risksHeading = Heading("Risks", "h2")
risksTable = Table([riskCol, severityCol, ownerCol2, mitigationCol])
riskCol = Col("Risk", ["Vendor delay on Atlas", "Data migration scope creep", "Mobile crash rate spike", "API key security audit"])
severityCol = Col("Severity", ["High", "Medium", "High", "Low"])
ownerCol2 = Col("Owner", ["A. Chen", "S. Johansson", "L. Rossi", "D. Kim"])
mitigationCol = Col("Mitigation", ["Escalated to vendor", "Freeze scope", "Hotfix in review", "Audit scheduled"])
upcomingDeadlines = Card([deadlinesHeading, deadlinesTable], "sunk")
deadlinesHeading = Heading("Deadlines: Next 2 Weeks", "h2")
deadlinesTable = Table([deadlineProjectCol, deadlineMilestoneCol, deadlineDateCol])
deadlineProjectCol = Col("Project", ["Pulsar API", "Orion Mobile", "Atlas Platform", "Nimbus CRM"])
deadlineMilestoneCol = Col("Milestone", ["API v2 release", "RC candidate", "Infra cutover", "CRM onboarding"])
deadlineDateCol = Col("Due", ["Oct 22", "Oct 24", "Oct 27", "Oct 29"])
paceSection = Card([paceHeading, paceChart], "sunk")
paceHeading = Heading("Delivery Pace (Last 6 Sprints)", "h2")
paceChart = LineChart(["S1", "S2", "S3", "S4", "S5", "S6"], [committedSeries, deliveredSeries], "natural", "Sprint", "Story points")
committedSeries = Series("Committed", [120, 130, 110, 140, 125, 135])
deliveredSeries = Series("Delivered", [110, 125, 115, 120, 130, 140])
blockedSection = Card([blockedHeading, blockedTable], "sunk")
blockedHeading = Heading("Blocked Work Items", "h2")
blockedTable = Table([blockedItemCol, blockedProjectCol, blockedReasonCol, blockedSinceCol])
blockedItemCol = Col("Item", ["Payment webhook", "Export job", "Login flow", "Report scheduler"])
blockedProjectCol = Col("Project", ["Atlas Platform", "Vega Analytics", "Nimbus CRM", "Pulsar API"])
blockedReasonCol = Col("Reason", ["Awaiting vendor", "Data missing", "Bug in auth service", "DB lock"])
blockedSinceCol = Col("Since", ["Oct 14", "Oct 12", "Oct 16", "Oct 10"])
resourceRequest = DialogBlock("Request more people", "Request Additional Headcount", "Select a project and tell us what you need.", [resourceForm], "secondary")
resourceForm = Form("resource-request", resourceButtons, [resourceProject, resourceRole, resourceNote])
resourceProject = FormControl("Project", resourceProjectSelect)
resourceProjectSelect = Select("project", [rp1, rp2, rp3, rp4, rp5], "Select project")
rp1 = SelectItem("atlas", "Atlas Platform")
rp2 = SelectItem("nimbus", "Nimbus CRM")
rp3 = SelectItem("orion", "Orion Mobile")
rp4 = SelectItem("vega", "Vega Analytics")
rp5 = SelectItem("pulsar", "Pulsar API")
resourceRole = FormControl("Role needed", resourceRoleSelect)
resourceRoleSelect = Select("role", [roleEng, roleDesign, roleData], "Select role")
roleEng = SelectItem("engineer", "Engineer")
roleDesign = SelectItem("designer", "Designer")
roleData = SelectItem("data_scientist", "Data Scientist")
resourceNote = FormControl("Notes", resourceNoteInput, "e.g. 2 engineers for 3 weeks")
resourceNoteInput = Input("notes", "Describe the need")
resourceButtons = Buttons([sendRequest])
sendRequest = Button("Send Request", null, "primary")