@exxatdesignux/ui 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +701 -6
- package/README.md +138 -0
- package/bin/init.mjs +134 -31
- package/consumer-extras/cursor-rules/exxat-board-cards.mdc +1 -1
- package/consumer-extras/cursor-rules/exxat-centralized-list-dataset.mdc +2 -2
- package/consumer-extras/cursor-rules/exxat-collaboration-access.mdc +1 -1
- package/consumer-extras/cursor-rules/exxat-data-tables.mdc +2 -0
- package/consumer-extras/cursor-rules/exxat-dedicated-search-surfaces.mdc +1 -1
- package/consumer-extras/cursor-rules/exxat-ds-agents.mdc +3 -3
- package/consumer-extras/cursor-rules/exxat-library-hub-header.mdc +28 -0
- package/consumer-extras/cursor-rules/exxat-mono-ids.mdc +1 -1
- package/consumer-extras/cursor-rules/exxat-person-identity-display.mdc +1 -1
- package/consumer-extras/cursor-rules/exxat-primary-nav-secondary-panel.mdc +6 -6
- package/consumer-extras/cursor-rules/exxat-reuse-before-custom.mdc +1 -1
- package/consumer-extras/cursor-skills/exxat-board-cards/SKILL.md +2 -2
- package/consumer-extras/cursor-skills/exxat-centralized-list-dataset/SKILL.md +1 -1
- package/consumer-extras/cursor-skills/exxat-collaboration-access/SKILL.md +3 -3
- package/consumer-extras/cursor-skills/exxat-dedicated-search-surfaces/SKILL.md +2 -2
- package/consumer-extras/cursor-skills/exxat-ds-skill/SKILL.md +7 -7
- package/consumer-extras/cursor-skills/exxat-kpi-flat-band/SKILL.md +1 -1
- package/consumer-extras/cursor-skills/exxat-list-page-view-shells/SKILL.md +1 -1
- package/consumer-extras/cursor-skills/exxat-mono-ids/SKILL.md +4 -4
- package/consumer-extras/cursor-skills/exxat-primary-nav-secondary-panel/SKILL.md +8 -8
- package/consumer-extras/cursor-skills/exxat-token-economy/SKILL.md +277 -0
- package/consumer-extras/handbook/HANDBOOK.md +2 -0
- package/consumer-extras/handbook/glossary.md +2 -1
- package/consumer-extras/handbook/reference-implementations.md +31 -4
- package/consumer-extras/patterns/collaboration-access-pattern.md +7 -7
- package/consumer-extras/patterns/data-views-pattern.md +18 -16
- package/consumer-extras/patterns/kpi-flat-band-pattern.md +2 -2
- package/dist/components/data-table/index.js +2 -2
- package/dist/components/data-table/index.js.map +1 -1
- package/dist/components/data-table/pagination.js +3 -3
- package/dist/components/data-table/pagination.js.map +1 -1
- package/dist/components/data-table/use-table-state.d.ts +1 -1
- package/dist/components/data-table/use-table-state.js.map +1 -1
- package/dist/components/data-views/data-row-list.js.map +1 -1
- package/dist/components/data-views/finder-panel-view.d.ts +1 -1
- package/dist/components/data-views/finder-panel-view.js.map +1 -1
- package/dist/components/data-views/hub-table.d.ts +9 -3
- package/dist/components/data-views/hub-table.js +262 -40
- package/dist/components/data-views/hub-table.js.map +1 -1
- package/dist/components/data-views/index.js +262 -40
- package/dist/components/data-views/index.js.map +1 -1
- package/dist/components/data-views/list-page-split-hub-tokens.d.ts +2 -2
- package/dist/components/data-views/list-page-split-hub-tokens.js.map +1 -1
- package/dist/components/data-views/list-page-tree-column-header.d.ts +1 -1
- package/dist/components/data-views/list-page-tree-column-header.js.map +1 -1
- package/dist/components/data-views/list-page-tree-panel-shell.js.map +1 -1
- package/dist/components/data-views/os-folder-glyph.d.ts +1 -1
- package/dist/components/data-views/os-folder-glyph.js.map +1 -1
- package/dist/components/ui/avatar.d.ts +1 -1
- package/dist/components/ui/key-metrics.js.map +1 -1
- package/dist/index.js +136 -39
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/src/components/data-table/index.tsx +2 -2
- package/src/components/data-table/pagination.tsx +5 -1
- package/src/components/data-table/use-table-state.ts +1 -1
- package/src/components/data-views/data-row-list.tsx +1 -1
- package/src/components/data-views/finder-panel-view.tsx +2 -2
- package/src/components/data-views/hub-table.tsx +149 -41
- package/src/components/data-views/list-page-split-hub-tokens.ts +2 -2
- package/src/components/data-views/list-page-tree-column-header.tsx +1 -1
- package/src/components/data-views/os-folder-glyph.tsx +1 -1
- package/src/components/ui/key-metrics.tsx +1 -1
- package/template/.claude/skills/exxat-ds-skill/SKILL.md +8 -7
- package/template/.cursor/rules/exxat-accessibility.mdc +1 -1
- package/template/.cursor/rules/exxat-command-menu.mdc +1 -1
- package/template/.cursor/rules/exxat-dashboard-view-charts.mdc +6 -6
- package/template/.cursor/rules/exxat-data-tables.mdc +3 -3
- package/template/.cursor/rules/exxat-kbd-shortcuts.mdc +5 -5
- package/template/.cursor/rules/exxat-mono-ids.mdc +1 -1
- package/template/.cursor/rules/exxat-page-vs-drawer.mdc +1 -1
- package/template/.cursor/rules/exxat-table-properties-drawer.mdc +1 -1
- package/template/AGENTS.md +43 -37
- package/template/app/(app)/columns/page.tsx +11 -0
- package/template/app/(app)/library/all/page.tsx +11 -0
- package/template/app/(app)/library/find/page.tsx +12 -0
- package/template/app/(app)/{question-bank → library}/layout.tsx +16 -16
- package/template/app/(app)/library/list/page.tsx +12 -0
- package/template/app/(app)/{question-bank → library}/new/page.tsx +10 -10
- package/template/app/(app)/library/page.tsx +11 -0
- package/template/app/(app)/tokens-themes/page.tsx +11 -0
- package/template/components/ask-leo-composer.tsx +2 -2
- package/template/components/columns-client.tsx +158 -0
- package/template/components/columns-showcase.tsx +541 -0
- package/template/components/data-views/index.ts +32 -6
- package/template/components/data-views/{question-bank-folder-tree-branch.tsx → library-folder-tree-branch.tsx} +19 -19
- package/template/components/data-views/table-cells.tsx +673 -0
- package/template/components/folder-details-shell.tsx +11 -11
- package/template/components/hub-tree-panel-view.tsx +24 -24
- package/template/components/{question-bank-board-view.tsx → library-board-view.tsx} +44 -44
- package/template/components/{question-bank-client.tsx → library-client.tsx} +82 -82
- package/template/components/{question-bank-dashboard-charts.tsx → library-dashboard-charts.tsx} +14 -14
- package/template/components/{question-bank-favorite-button.tsx → library-favorite-button.tsx} +7 -7
- package/template/components/{question-bank-hub-client.tsx → library-hub-client.tsx} +43 -43
- package/template/components/{question-bank-new-folder-sheet.tsx → library-new-folder-sheet.tsx} +14 -14
- package/template/components/{question-bank-os-folder-view.tsx → library-os-folder-view.tsx} +31 -31
- package/template/components/{question-bank-page-header.tsx → library-page-header.tsx} +6 -6
- package/template/components/library-panel-activator.tsx +8 -0
- package/template/components/{question-bank-secondary-nav.tsx → library-secondary-nav.tsx} +60 -60
- package/template/components/{question-bank-table.tsx → library-table.tsx} +97 -97
- package/template/components/list-hub-status-badge.tsx +2 -2
- package/template/components/{new-question-composer.tsx → new-library-item-form.tsx} +37 -37
- package/template/components/sidebar/app-sidebar.tsx +61 -5
- package/template/components/sidebar/secondary-panel.tsx +109 -56
- package/template/components/sidebar/sidebar-auto-collapse.tsx +2 -2
- package/template/components/sidebar/sidebar-auto-open.tsx +2 -1
- package/template/components/table-properties/types.ts +1 -1
- package/template/components/templates/discovery-hub-template.tsx +1 -1
- package/template/components/templates/new-focus-template.tsx +2 -2
- package/template/components/templates/secondary-panel-hub-template.tsx +1 -1
- package/template/components/tokens-secondary-nav.tsx +192 -0
- package/template/components/tokens-themes-client.tsx +476 -0
- package/template/components/tokens-themes-section.tsx +386 -0
- package/template/docs/HANDBOOK.md +187 -0
- package/template/docs/blueprints/README.md +1 -1
- package/template/docs/blueprints/board-card.md +1 -1
- package/template/docs/blueprints/data-table.md +2 -2
- package/template/docs/blueprints/list-page-template.md +3 -3
- package/template/docs/blueprints/page-header.md +4 -4
- package/template/docs/collaboration-access-pattern.md +7 -7
- package/template/docs/component-selection-guide.md +1 -1
- package/template/docs/data-views-pattern.md +18 -16
- package/template/docs/glossary.md +58 -0
- package/template/docs/kpi-flat-band-pattern.md +3 -3
- package/template/docs/kpi-trend-pattern.md +18 -3
- package/template/docs/large-dataset-strategy.md +155 -0
- package/template/docs/library-hub-header-pattern.md +25 -0
- package/template/docs/migrations/_template.md +1 -1
- package/template/docs/reference-implementations.md +151 -0
- package/template/docs/token-taxonomy.md +1 -1
- package/template/docs/voice-and-tone.md +262 -0
- package/template/eslint.config.mjs +9 -39
- package/template/hooks/use-secondary-panel-hub-nav.ts +10 -10
- package/template/lib/ask-leo-route-context.ts +6 -18
- package/template/lib/coach-mark-registry.ts +0 -16
- package/template/lib/command-menu-config.ts +5 -12
- package/template/lib/command-menu-search-data.ts +8 -39
- package/template/lib/{question-bank-authoring.ts → library-authoring.ts} +89 -88
- package/template/lib/library-dedicated-search.ts +19 -0
- package/template/lib/library-hub-search.ts +90 -0
- package/template/lib/library-nav.ts +477 -0
- package/template/lib/library-recent-searches.ts +22 -0
- package/template/lib/{placements-supported-views.ts → library-supported-views.ts} +2 -2
- package/template/lib/list-status-badges.ts +16 -104
- package/template/lib/mock/dashboard.ts +1 -1
- package/template/lib/mock/{question-bank-folders.ts → library-folders.ts} +30 -30
- package/template/lib/mock/library-header-collaborators.ts +54 -0
- package/template/lib/mock/{question-bank-inspector.ts → library-inspector.ts} +29 -29
- package/template/lib/mock/{question-bank-kpi.ts → library-kpi.ts} +20 -20
- package/template/lib/mock/library.ts +249 -0
- package/template/lib/mock/navigation.tsx +32 -26
- package/template/lib/table-state-lifecycle.ts +1 -1
- package/template/next.config.mjs +7 -4
- package/template/package.json +0 -1
- package/tokens/hooks-index.json +2874 -0
- package/consumer-extras/cursor-rules/exxat-question-bank-hub-header.mdc +0 -28
- package/template/app/(app)/examples/page.tsx +0 -41
- package/template/app/(app)/question-bank/find/page.tsx +0 -12
- package/template/app/(app)/question-bank/library/page.tsx +0 -11
- package/template/app/(app)/question-bank/list/page.tsx +0 -12
- package/template/app/(app)/question-bank/page.tsx +0 -11
- package/template/components/compliance-board-view.tsx +0 -142
- package/template/components/compliance-client.tsx +0 -92
- package/template/components/compliance-page-header.tsx +0 -89
- package/template/components/compliance-table.tsx +0 -468
- package/template/components/data-view-dashboard-charts-compliance.tsx +0 -963
- package/template/components/data-view-dashboard-charts-team.tsx +0 -971
- package/template/components/data-view-dashboard-charts.tsx +0 -1503
- package/template/components/new-placement-back-btn.tsx +0 -28
- package/template/components/new-placement-form.tsx +0 -942
- package/template/components/placement-board-card.tsx +0 -250
- package/template/components/placement-detail.tsx +0 -438
- package/template/components/placements-board-view.tsx +0 -397
- package/template/components/placements-client.tsx +0 -220
- package/template/components/placements-list-view.tsx +0 -124
- package/template/components/placements-page-header.tsx +0 -166
- package/template/components/placements-table-cells.test.tsx +0 -22
- package/template/components/placements-table-cells.tsx +0 -173
- package/template/components/placements-table-columns.tsx +0 -210
- package/template/components/placements-table.tsx +0 -934
- package/template/components/question-bank-panel-activator.tsx +0 -8
- package/template/components/rotations-empty-state.tsx +0 -50
- package/template/components/rotations-panel-activator.tsx +0 -8
- package/template/components/sites-board-view.tsx +0 -67
- package/template/components/sites-client.tsx +0 -154
- package/template/components/sites-table.tsx +0 -249
- package/template/components/team-board-view.tsx +0 -122
- package/template/components/team-client.tsx +0 -100
- package/template/components/team-page-header.tsx +0 -92
- package/template/components/team-table.tsx +0 -553
- package/template/docs/question-bank-hub-header-pattern.md +0 -25
- package/template/lib/compliance-supported-views.ts +0 -10
- package/template/lib/data-view-dashboard-placements-layout.ts +0 -215
- package/template/lib/mock/compliance-kpi.ts +0 -61
- package/template/lib/mock/compliance.ts +0 -146
- package/template/lib/mock/placements-kpi.ts +0 -134
- package/template/lib/mock/placements.ts +0 -176
- package/template/lib/mock/question-bank-header-collaborators.ts +0 -54
- package/template/lib/mock/question-bank.ts +0 -249
- package/template/lib/mock/sites-directory.ts +0 -16
- package/template/lib/mock/sites-kpi.ts +0 -25
- package/template/lib/mock/team-kpi.ts +0 -60
- package/template/lib/mock/team.ts +0 -118
- package/template/lib/placement-board-card-layout.ts +0 -79
- package/template/lib/question-bank-dedicated-search.ts +0 -19
- package/template/lib/question-bank-hub-search.ts +0 -90
- package/template/lib/question-bank-nav.ts +0 -477
- package/template/lib/question-bank-recent-searches.ts +0 -22
- package/template/lib/question-bank-supported-views.ts +0 -12
- package/template/lib/sites-supported-views.ts +0 -10
- package/template/lib/team-supported-views.ts +0 -10
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2
|
-
// Mock data — Placements
|
|
3
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
4
|
-
|
|
5
|
-
export type Status = "confirmed" | "pending" | "under-review" | "rejected" | "completed"
|
|
6
|
-
|
|
7
|
-
/** Which lifecycle tab owns this row (All shows every row). */
|
|
8
|
-
export type PlacementPhase = "upcoming" | "ongoing" | "completed"
|
|
9
|
-
|
|
10
|
-
export interface Placement extends Record<string, unknown> {
|
|
11
|
-
id: number
|
|
12
|
-
student: string
|
|
13
|
-
email: string
|
|
14
|
-
initials: string
|
|
15
|
-
program: string
|
|
16
|
-
site: string
|
|
17
|
-
siteAddress: string
|
|
18
|
-
status: Status
|
|
19
|
-
start: string
|
|
20
|
-
duration: string
|
|
21
|
-
supervisor: string
|
|
22
|
-
placementPhase: PlacementPhase
|
|
23
|
-
/** Display title for internship column */
|
|
24
|
-
internship: string
|
|
25
|
-
specialization: string
|
|
26
|
-
/** Upcoming */
|
|
27
|
-
compliance: string
|
|
28
|
-
daysUntilStart: number
|
|
29
|
-
readiness: string
|
|
30
|
-
/** Ongoing */
|
|
31
|
-
progressWeeksDone: number
|
|
32
|
-
progressWeeksTotal: number
|
|
33
|
-
endDate: string
|
|
34
|
-
lastCheckin: string
|
|
35
|
-
/** Completed */
|
|
36
|
-
completionDate: string
|
|
37
|
-
finalStatus: string
|
|
38
|
-
rating: number
|
|
39
|
-
suggestedToHire: string
|
|
40
|
-
/** Visual indicator — row has new activity or was recently updated */
|
|
41
|
-
isNew?: boolean
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export const ALL_PLACEMENTS: Placement[] = [
|
|
45
|
-
{
|
|
46
|
-
id: 1, student: "Sarah Johnson", email: "s.johnson@college.edu", initials: "SJ", program: "Nursing", site: "City Medical Center",
|
|
47
|
-
siteAddress: "1400 N Lake Shore Dr, Chicago, IL", status: "confirmed", start: "03/15/2026", duration: "12 wks", supervisor: "Dr. Patel",
|
|
48
|
-
placementPhase: "ongoing", internship: "Med-Surg Clinical I", specialization: "Adult Health", compliance: "Complete", daysUntilStart: 0,
|
|
49
|
-
readiness: "Ready", progressWeeksDone: 5, progressWeeksTotal: 12, endDate: "06/07/2026", lastCheckin: "03/22/2026",
|
|
50
|
-
completionDate: "—", finalStatus: "—", rating: 0, suggestedToHire: "—", isNew: true,
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
id: 2, student: "Mike Chen", email: "m.chen@university.edu", initials: "MC", program: "Physical Therapy", site: "Metro Rehab",
|
|
54
|
-
siteAddress: "250 E Superior St, Chicago, IL", status: "pending", start: "04/01/2026", duration: "8 wks", supervisor: "Dr. Kim",
|
|
55
|
-
placementPhase: "upcoming", internship: "Outpatient PT Rotation", specialization: "Orthopedics", compliance: "In progress", daysUntilStart: 8,
|
|
56
|
-
readiness: "Ready", progressWeeksDone: 0, progressWeeksTotal: 8, endDate: "05/27/2026", lastCheckin: "—",
|
|
57
|
-
completionDate: "—", finalStatus: "—", rating: 0, suggestedToHire: "—",
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
id: 3, student: "Amy Park", email: "a.park@school.edu", initials: "AP", program: "Occupational Therapy", site: "Bay Area Health",
|
|
61
|
-
siteAddress: "3100 Telegraph Ave, Oakland, CA", status: "under-review", start: "03/28/2026", duration: "10 wks", supervisor: "Unassigned",
|
|
62
|
-
placementPhase: "upcoming", internship: "Acute Care OT", specialization: "Hand Therapy", compliance: "Pending documents", daysUntilStart: 4,
|
|
63
|
-
readiness: "At risk", progressWeeksDone: 0, progressWeeksTotal: 10, endDate: "06/06/2026", lastCheckin: "—",
|
|
64
|
-
completionDate: "—", finalStatus: "—", rating: 0, suggestedToHire: "—", isNew: true,
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
id: 4, student: "James Williams", email: "j.williams@college.edu", initials: "JW", program: "Nursing", site: "Sunrise Hospital",
|
|
68
|
-
siteAddress: "5775 Wayzata Blvd, Minneapolis, MN", status: "confirmed", start: "04/07/2026", duration: "12 wks", supervisor: "Dr. Torres",
|
|
69
|
-
placementPhase: "ongoing", internship: "ICU Practicum", specialization: "Critical Care", compliance: "Complete", daysUntilStart: 0,
|
|
70
|
-
readiness: "Ready", progressWeeksDone: 2, progressWeeksTotal: 12, endDate: "06/30/2026", lastCheckin: "03/21/2026",
|
|
71
|
-
completionDate: "—", finalStatus: "—", rating: 0, suggestedToHire: "—",
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
id: 5, student: "Emily Davis", email: "e.davis@university.edu", initials: "ED", program: "Social Work", site: "Community Care",
|
|
75
|
-
siteAddress: "220 S State St, Chicago, IL", status: "rejected", start: "—", duration: "—", supervisor: "—",
|
|
76
|
-
placementPhase: "upcoming", internship: "Community SW Field", specialization: "Behavioral Health", compliance: "Incomplete", daysUntilStart: 0,
|
|
77
|
-
readiness: "Blocked", progressWeeksDone: 0, progressWeeksTotal: 10, endDate: "—", lastCheckin: "—",
|
|
78
|
-
completionDate: "—", finalStatus: "—", rating: 0, suggestedToHire: "—",
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
id: 6, student: "Carlos Rivera", email: "c.rivera@school.edu", initials: "CR", program: "Physical Therapy", site: "Summit Sports Med",
|
|
82
|
-
siteAddress: "900 N Michigan Ave, Chicago, IL", status: "pending", start: "04/14/2026", duration: "8 wks", supervisor: "Dr. Lee",
|
|
83
|
-
placementPhase: "upcoming", internship: "Sports Medicine PT", specialization: "Sports Rehab", compliance: "Complete", daysUntilStart: 21,
|
|
84
|
-
readiness: "Ready", progressWeeksDone: 0, progressWeeksTotal: 8, endDate: "06/09/2026", lastCheckin: "—",
|
|
85
|
-
completionDate: "—", finalStatus: "—", rating: 0, suggestedToHire: "—",
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
id: 7, student: "Priya Sharma", email: "p.sharma@college.edu", initials: "PS", program: "Nursing", site: "Harbor Medical",
|
|
89
|
-
siteAddress: "1200 W Harrison St, Chicago, IL", status: "confirmed", start: "03/22/2026", duration: "12 wks", supervisor: "Dr. Patel",
|
|
90
|
-
placementPhase: "ongoing", internship: "Pediatric Nursing", specialization: "Pediatrics", compliance: "Complete", daysUntilStart: 0,
|
|
91
|
-
readiness: "Ready", progressWeeksDone: 7, progressWeeksTotal: 12, endDate: "06/14/2026", lastCheckin: "03/23/2026",
|
|
92
|
-
completionDate: "—", finalStatus: "—", rating: 0, suggestedToHire: "—", isNew: true,
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
id: 8, student: "Tom Bradley", email: "t.bradley@university.edu", initials: "TB", program: "Occupational Therapy", site: "Valley Health",
|
|
96
|
-
siteAddress: "4646 N Marine Dr, Chicago, IL", status: "under-review", start: "04/03/2026", duration: "10 wks", supervisor: "Dr. Wong",
|
|
97
|
-
placementPhase: "upcoming", internship: "Rehabilitation OT", specialization: "Neuro", compliance: "Review", daysUntilStart: 10,
|
|
98
|
-
readiness: "In review", progressWeeksDone: 0, progressWeeksTotal: 10, endDate: "06/12/2026", lastCheckin: "—",
|
|
99
|
-
completionDate: "—", finalStatus: "—", rating: 0, suggestedToHire: "—",
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
id: 9, student: "Lena Fischer", email: "l.fischer@school.edu", initials: "LF", program: "Nursing", site: "Westside Clinic",
|
|
103
|
-
siteAddress: "2525 S Michigan Ave, Chicago, IL", status: "confirmed", start: "03/18/2026", duration: "12 wks", supervisor: "Dr. Santos",
|
|
104
|
-
placementPhase: "ongoing", internship: "Primary Care RN", specialization: "Family Practice", compliance: "Complete", daysUntilStart: 0,
|
|
105
|
-
readiness: "Ready", progressWeeksDone: 8, progressWeeksTotal: 12, endDate: "06/10/2026", lastCheckin: "03/24/2026",
|
|
106
|
-
completionDate: "—", finalStatus: "—", rating: 0, suggestedToHire: "—",
|
|
107
|
-
},
|
|
108
|
-
{
|
|
109
|
-
id: 10, student: "Omar Hassan", email: "o.hassan@college.edu", initials: "OH", program: "Physical Therapy", site: "Metro Rehab",
|
|
110
|
-
siteAddress: "250 E Superior St, Chicago, IL", status: "pending", start: "04/21/2026", duration: "8 wks", supervisor: "Dr. Kim",
|
|
111
|
-
placementPhase: "upcoming", internship: "Neurologic PT", specialization: "Neuro Rehab", compliance: "Pending", daysUntilStart: 28,
|
|
112
|
-
readiness: "Ready", progressWeeksDone: 0, progressWeeksTotal: 8, endDate: "06/16/2026", lastCheckin: "—",
|
|
113
|
-
completionDate: "—", finalStatus: "—", rating: 0, suggestedToHire: "—",
|
|
114
|
-
},
|
|
115
|
-
{
|
|
116
|
-
id: 11, student: "Nina Patel", email: "n.patel@university.edu", initials: "NP", program: "Social Work", site: "Hope Community Ctr",
|
|
117
|
-
siteAddress: "3517 W Arthington St, Chicago, IL", status: "confirmed", start: "03/25/2026", duration: "10 wks", supervisor: "Ms. Torres",
|
|
118
|
-
placementPhase: "ongoing", internship: "School Social Work", specialization: "Youth Services", compliance: "Complete", daysUntilStart: 0,
|
|
119
|
-
readiness: "Ready", progressWeeksDone: 4, progressWeeksTotal: 10, endDate: "06/03/2026", lastCheckin: "03/19/2026",
|
|
120
|
-
completionDate: "—", finalStatus: "—", rating: 0, suggestedToHire: "—",
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
id: 12, student: "David Okonkwo", email: "d.okonkwo@school.edu", initials: "DO", program: "Nursing", site: "Lakeside Hospital",
|
|
124
|
-
siteAddress: "4440 N Clark St, Chicago, IL", status: "under-review", start: "04/10/2026", duration: "12 wks", supervisor: "Unassigned",
|
|
125
|
-
placementPhase: "upcoming", internship: "Emergency Dept RN", specialization: "Emergency", compliance: "Pending", daysUntilStart: 17,
|
|
126
|
-
readiness: "At risk", progressWeeksDone: 0, progressWeeksTotal: 12, endDate: "07/03/2026", lastCheckin: "—",
|
|
127
|
-
completionDate: "—", finalStatus: "—", rating: 0, suggestedToHire: "—",
|
|
128
|
-
},
|
|
129
|
-
{
|
|
130
|
-
id: 13, student: "Alex Morgan", email: "a.morgan@college.edu", initials: "AM", program: "Nursing", site: "City Medical Center",
|
|
131
|
-
siteAddress: "1400 N Lake Shore Dr, Chicago, IL", status: "completed", start: "01/06/2026", duration: "12 wks", supervisor: "Dr. Patel",
|
|
132
|
-
placementPhase: "completed", internship: "Med-Surg Clinical II", specialization: "Adult Health", compliance: "Complete", daysUntilStart: 0,
|
|
133
|
-
readiness: "Ready", progressWeeksDone: 12, progressWeeksTotal: 12, endDate: "03/30/2026", lastCheckin: "03/28/2026",
|
|
134
|
-
completionDate: "03/30/2026", finalStatus: "Passed", rating: 4.8, suggestedToHire: "Yes",
|
|
135
|
-
},
|
|
136
|
-
{
|
|
137
|
-
id: 14, student: "Jordan Lee", email: "j.lee@university.edu", initials: "JL", program: "Physical Therapy", site: "Metro Rehab",
|
|
138
|
-
siteAddress: "250 E Superior St, Chicago, IL", status: "completed", start: "11/04/2025", duration: "8 wks", supervisor: "Dr. Kim",
|
|
139
|
-
placementPhase: "completed", internship: "Inpatient PT", specialization: "Acute Care", compliance: "Complete", daysUntilStart: 0,
|
|
140
|
-
readiness: "Ready", progressWeeksDone: 8, progressWeeksTotal: 8, endDate: "12/30/2025", lastCheckin: "12/28/2025",
|
|
141
|
-
completionDate: "12/30/2025", finalStatus: "Passed", rating: 4.2, suggestedToHire: "Yes",
|
|
142
|
-
},
|
|
143
|
-
{
|
|
144
|
-
id: 15, student: "Sam Rivera", email: "s.rivera@school.edu", initials: "SR", program: "Occupational Therapy", site: "Bay Area Health",
|
|
145
|
-
siteAddress: "3100 Telegraph Ave, Oakland, CA", status: "completed", start: "10/01/2025", duration: "10 wks", supervisor: "Dr. Nguyen",
|
|
146
|
-
placementPhase: "completed", internship: "Hand Therapy OT", specialization: "Hand Therapy", compliance: "Complete", daysUntilStart: 0,
|
|
147
|
-
readiness: "Ready", progressWeeksDone: 10, progressWeeksTotal: 10, endDate: "12/10/2025", lastCheckin: "12/08/2025",
|
|
148
|
-
completionDate: "12/10/2025", finalStatus: "Incomplete", rating: 3.5, suggestedToHire: "No",
|
|
149
|
-
},
|
|
150
|
-
{
|
|
151
|
-
id: 16, student: "Taylor Brooks", email: "t.brooks@college.edu", initials: "TB", program: "Nursing", site: "Sunrise Hospital",
|
|
152
|
-
siteAddress: "5775 Wayzata Blvd, Minneapolis, MN", status: "completed", start: "09/02/2025", duration: "12 wks", supervisor: "Dr. Torres",
|
|
153
|
-
placementPhase: "completed", internship: "Labor & Delivery", specialization: "Women's Health", compliance: "Complete", daysUntilStart: 0,
|
|
154
|
-
readiness: "Ready", progressWeeksDone: 12, progressWeeksTotal: 12, endDate: "11/25/2025", lastCheckin: "11/22/2025",
|
|
155
|
-
completionDate: "11/25/2025", finalStatus: "Passed", rating: 5, suggestedToHire: "Yes",
|
|
156
|
-
},
|
|
157
|
-
]
|
|
158
|
-
|
|
159
|
-
/** Distinct sorted values for filter dropdowns (list UI) on text-like columns. */
|
|
160
|
-
export function uniquePlacementFieldOptions(
|
|
161
|
-
key: keyof Placement,
|
|
162
|
-
): { value: string; label: string }[] {
|
|
163
|
-
const set = new Set<string>()
|
|
164
|
-
for (const r of ALL_PLACEMENTS) {
|
|
165
|
-
const raw = r[key]
|
|
166
|
-
if (raw === undefined || raw === null) continue
|
|
167
|
-
const v = typeof raw === "number" ? String(raw) : String(raw).trim()
|
|
168
|
-
if (!v || v === "—") continue
|
|
169
|
-
set.add(v)
|
|
170
|
-
}
|
|
171
|
-
return [...set].sort((a, b) => a.localeCompare(b)).map(v => ({ value: v, label: v }))
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
export function getPlacementById(id: number): Placement | undefined {
|
|
175
|
-
return ALL_PLACEMENTS.find(p => p.id === id)
|
|
176
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Demo collaborators for Question bank collaboration header (stacked faces).
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { stockPortraitUrl } from "@/lib/stock-portrait"
|
|
6
|
-
import type { PageHeaderCollaborator } from "@/components/page-header"
|
|
7
|
-
|
|
8
|
-
export const QUESTION_BANK_HEADER_COLLABORATORS: PageHeaderCollaborator[] = [
|
|
9
|
-
{
|
|
10
|
-
id: "1",
|
|
11
|
-
name: "Alex Morgan",
|
|
12
|
-
email: "alex.morgan@example.com",
|
|
13
|
-
imageUrl: stockPortraitUrl("qb-collab-alex"),
|
|
14
|
-
initials: "AM",
|
|
15
|
-
access: "owner",
|
|
16
|
-
roles: ["Director", "Faculty"],
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
id: "2",
|
|
20
|
-
name: "Jordan Lee",
|
|
21
|
-
email: "jordan.lee@example.com",
|
|
22
|
-
imageUrl: stockPortraitUrl("qb-collab-jordan"),
|
|
23
|
-
initials: "JL",
|
|
24
|
-
access: "editor",
|
|
25
|
-
roles: ["Program coordinator"],
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
id: "3",
|
|
29
|
-
name: "Sam Rivera",
|
|
30
|
-
email: "sam.rivera@example.com",
|
|
31
|
-
imageUrl: stockPortraitUrl("qb-collab-sam"),
|
|
32
|
-
initials: "SR",
|
|
33
|
-
access: "editor",
|
|
34
|
-
roles: ["Faculty"],
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
id: "4",
|
|
38
|
-
name: "Taylor Kim",
|
|
39
|
-
email: "taylor.kim@example.com",
|
|
40
|
-
imageUrl: stockPortraitUrl("qb-collab-taylor"),
|
|
41
|
-
initials: "TK",
|
|
42
|
-
access: "commenter",
|
|
43
|
-
roles: ["Faculty"],
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
id: "5",
|
|
47
|
-
name: "Riley Patel",
|
|
48
|
-
email: "riley.patel@example.com",
|
|
49
|
-
imageUrl: stockPortraitUrl("qb-collab-riley"),
|
|
50
|
-
initials: "RP",
|
|
51
|
-
access: "viewer",
|
|
52
|
-
roles: ["Program coordinator"],
|
|
53
|
-
},
|
|
54
|
-
]
|
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mock question bank items — replace with API in production.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
export type QuestionBankType = "multiple_choice" | "true_false" | "short_answer"
|
|
6
|
-
export type QuestionBankDifficulty = "easy" | "medium" | "hard"
|
|
7
|
-
|
|
8
|
-
/** Bloom taxonomy label for bank inspector / analytics (optional on mock rows). */
|
|
9
|
-
export type QuestionBankBloomLevel =
|
|
10
|
-
| "Remember"
|
|
11
|
-
| "Understand"
|
|
12
|
-
| "Apply"
|
|
13
|
-
| "Analyze"
|
|
14
|
-
| "Evaluate"
|
|
15
|
-
| "Create"
|
|
16
|
-
|
|
17
|
-
export interface QuestionBankItem extends Record<string, unknown> {
|
|
18
|
-
id: string
|
|
19
|
-
/** Stable human-facing identifier (catalog, search, citations). */
|
|
20
|
-
questionId: string
|
|
21
|
-
/** Short preview / stem */
|
|
22
|
-
stem: string
|
|
23
|
-
topic: string
|
|
24
|
-
type: QuestionBankType
|
|
25
|
-
difficulty: QuestionBankDifficulty
|
|
26
|
-
author: string
|
|
27
|
-
/** Work email for the primary author (demo; optional when API omits). */
|
|
28
|
-
authorEmail?: string
|
|
29
|
-
updatedAt: string
|
|
30
|
-
/** Folder tree id (`lib/mock/question-bank-folders.ts`). */
|
|
31
|
-
folderId: string
|
|
32
|
-
/** Multiple choice options (only for type: "multiple_choice") */
|
|
33
|
-
options?: {
|
|
34
|
-
text: string
|
|
35
|
-
isCorrect?: boolean
|
|
36
|
-
}[]
|
|
37
|
-
/** Stable bank code for lists / inspector (e.g. PH-ANA-001). */
|
|
38
|
-
itemCode?: string
|
|
39
|
-
bloomLevel?: QuestionBankBloomLevel | string
|
|
40
|
-
/** Topic-style tags for inspector (# displayed in UI). */
|
|
41
|
-
tags?: string[]
|
|
42
|
-
/** ISO-ish created date (inspector “Creator & history”). */
|
|
43
|
-
createdAt?: string
|
|
44
|
-
/** Display name for “Created by” when different from `author`. */
|
|
45
|
-
createdBy?: string
|
|
46
|
-
/** Last editor display name (inspector copy). */
|
|
47
|
-
lastEditedBy?: string
|
|
48
|
-
/** Precomposed “Last edited” line; overrides derived copy when set. */
|
|
49
|
-
lastEditedSummary?: string
|
|
50
|
-
/** Revision label e.g. v4 */
|
|
51
|
-
version?: string
|
|
52
|
-
examUsageCount?: number
|
|
53
|
-
/** Point-biserial index (psychometrics preview). */
|
|
54
|
-
pbi?: number
|
|
55
|
-
/** Mean percent correct when used in assessments. */
|
|
56
|
-
avgScoreCorrectPct?: number
|
|
57
|
-
/** Where / when the item was last used on an exam. */
|
|
58
|
-
lastUsedLabel?: string
|
|
59
|
-
/** Starred outside the Favorites folder (list landing demo). */
|
|
60
|
-
isStarred?: boolean
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/** New mock rows — assign a unique `questionId` when creating client-side. */
|
|
64
|
-
export function newQuestionBankQuestionId(): string {
|
|
65
|
-
return `QB-NEW-${Date.now().toString(36).toUpperCase()}`
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export const QUESTION_BANK_ITEMS: QuestionBankItem[] = [
|
|
69
|
-
{
|
|
70
|
-
id: "q1",
|
|
71
|
-
questionId: "QB-ANA-001",
|
|
72
|
-
stem: "Which nerve roots contribute to the brachial plexus?",
|
|
73
|
-
topic: "Anatomy",
|
|
74
|
-
type: "multiple_choice",
|
|
75
|
-
difficulty: "medium",
|
|
76
|
-
author: "Dr. Chen",
|
|
77
|
-
authorEmail: "mei.chen@demo.exxat.io",
|
|
78
|
-
updatedAt: "2026-03-28",
|
|
79
|
-
folderId: "fld-favorites",
|
|
80
|
-
itemCode: "QB-ANA-001",
|
|
81
|
-
bloomLevel: "Apply",
|
|
82
|
-
tags: ["Brachial plexus", "Peripheral nerves", "Spine"],
|
|
83
|
-
createdAt: "2024-11-02",
|
|
84
|
-
createdBy: "Dr. Sarah Thompson",
|
|
85
|
-
lastEditedBy: "Dr. James Patel",
|
|
86
|
-
lastEditedSummary: "14 months ago · Dr. James Patel",
|
|
87
|
-
version: "v4",
|
|
88
|
-
examUsageCount: 22,
|
|
89
|
-
pbi: 0.48,
|
|
90
|
-
avgScoreCorrectPct: 88,
|
|
91
|
-
lastUsedLabel: "Midterm 2024 · 14 months ago",
|
|
92
|
-
options: [
|
|
93
|
-
{ text: "C5, C6, C7, C8, T1", isCorrect: true },
|
|
94
|
-
{ text: "C3, C4, C5, C6", isCorrect: false },
|
|
95
|
-
{ text: "C6, C7, C8, T1, T2", isCorrect: false },
|
|
96
|
-
{ text: "C4, C5, C6, C7", isCorrect: false },
|
|
97
|
-
],
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
id: "q2",
|
|
101
|
-
questionId: "QB-CNL-002",
|
|
102
|
-
stem: "Document baseline vitals before administering contrast.",
|
|
103
|
-
topic: "Clinical skills",
|
|
104
|
-
type: "true_false",
|
|
105
|
-
difficulty: "easy",
|
|
106
|
-
author: "Jordan Lee",
|
|
107
|
-
authorEmail: "jordan.lee@demo.exxat.io",
|
|
108
|
-
updatedAt: "2026-03-27",
|
|
109
|
-
folderId: "fld-skills-lab",
|
|
110
|
-
isStarred: true,
|
|
111
|
-
pbi: 0.55,
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
id: "q3",
|
|
115
|
-
questionId: "QB-NEU-003",
|
|
116
|
-
stem: "List three red flags for cauda equina syndrome.",
|
|
117
|
-
topic: "Neurology",
|
|
118
|
-
type: "short_answer",
|
|
119
|
-
difficulty: "hard",
|
|
120
|
-
author: "Alex Rivera",
|
|
121
|
-
authorEmail: "alex.rivera@demo.exxat.io",
|
|
122
|
-
updatedAt: "2026-03-26",
|
|
123
|
-
folderId: "fld-science",
|
|
124
|
-
isStarred: true,
|
|
125
|
-
pbi: 0.14,
|
|
126
|
-
},
|
|
127
|
-
{
|
|
128
|
-
id: "q4",
|
|
129
|
-
questionId: "QB-ETH-004",
|
|
130
|
-
stem: "HIPAA permits disclosure to family without consent when…",
|
|
131
|
-
topic: "Ethics & law",
|
|
132
|
-
type: "multiple_choice",
|
|
133
|
-
difficulty: "medium",
|
|
134
|
-
author: "Sam Patel",
|
|
135
|
-
authorEmail: "sam.patel@demo.exxat.io",
|
|
136
|
-
updatedAt: "2026-03-25",
|
|
137
|
-
folderId: "fld-ethics",
|
|
138
|
-
isStarred: true,
|
|
139
|
-
pbi: 0.19,
|
|
140
|
-
options: [
|
|
141
|
-
{ text: "Patient is incapacitated and disclosure is in their best interest", isCorrect: true },
|
|
142
|
-
{ text: "Family member requests the information", isCorrect: false },
|
|
143
|
-
{ text: "Patient has not explicitly prohibited disclosure", isCorrect: false },
|
|
144
|
-
{ text: "Disclosure would benefit hospital operations", isCorrect: false },
|
|
145
|
-
],
|
|
146
|
-
},
|
|
147
|
-
{
|
|
148
|
-
id: "q5",
|
|
149
|
-
questionId: "QB-ASM-005",
|
|
150
|
-
stem: "Calculate BMI given height and weight (metric).",
|
|
151
|
-
topic: "Assessment",
|
|
152
|
-
type: "short_answer",
|
|
153
|
-
difficulty: "easy",
|
|
154
|
-
author: "Dr. Chen",
|
|
155
|
-
authorEmail: "mei.chen@demo.exxat.io",
|
|
156
|
-
updatedAt: "2026-03-24",
|
|
157
|
-
folderId: "fld-favorites",
|
|
158
|
-
},
|
|
159
|
-
{
|
|
160
|
-
id: "q6",
|
|
161
|
-
questionId: "QB-ICO-006",
|
|
162
|
-
stem: "Sterile field must be prepared before which step?",
|
|
163
|
-
topic: "Infection control",
|
|
164
|
-
type: "multiple_choice",
|
|
165
|
-
difficulty: "medium",
|
|
166
|
-
author: "Morgan Lee",
|
|
167
|
-
authorEmail: "morgan.lee@demo.exxat.io",
|
|
168
|
-
updatedAt: "2026-03-23",
|
|
169
|
-
folderId: "fld-ops",
|
|
170
|
-
options: [
|
|
171
|
-
{ text: "Gloving and gowning", isCorrect: true },
|
|
172
|
-
{ text: "Hand sanitization", isCorrect: false },
|
|
173
|
-
{ text: "Equipment gathering", isCorrect: false },
|
|
174
|
-
{ text: "Workspace cleaning", isCorrect: false },
|
|
175
|
-
],
|
|
176
|
-
},
|
|
177
|
-
{
|
|
178
|
-
id: "q7",
|
|
179
|
-
questionId: "QB-DOC-007",
|
|
180
|
-
stem: "SOAP note: subjective section documents patient-reported data only.",
|
|
181
|
-
topic: "Documentation",
|
|
182
|
-
type: "true_false",
|
|
183
|
-
difficulty: "easy",
|
|
184
|
-
author: "Casey Nguyen",
|
|
185
|
-
authorEmail: "casey.nguyen@demo.exxat.io",
|
|
186
|
-
updatedAt: "2026-03-22",
|
|
187
|
-
folderId: "fld-clinical",
|
|
188
|
-
},
|
|
189
|
-
{
|
|
190
|
-
id: "q8",
|
|
191
|
-
questionId: "QB-RAD-008",
|
|
192
|
-
stem: "Contrast MRI safety screening includes renal function when…",
|
|
193
|
-
topic: "Radiology",
|
|
194
|
-
type: "multiple_choice",
|
|
195
|
-
difficulty: "hard",
|
|
196
|
-
author: "Riley Johnson",
|
|
197
|
-
authorEmail: "riley.johnson@demo.exxat.io",
|
|
198
|
-
updatedAt: "2026-03-21",
|
|
199
|
-
folderId: "fld-science",
|
|
200
|
-
},
|
|
201
|
-
{
|
|
202
|
-
id: "q9",
|
|
203
|
-
questionId: "QB-COM-009",
|
|
204
|
-
stem: "Therapeutic communication: reflect feelings before offering solutions.",
|
|
205
|
-
topic: "Communication",
|
|
206
|
-
type: "true_false",
|
|
207
|
-
difficulty: "medium",
|
|
208
|
-
author: "Quinn Martinez",
|
|
209
|
-
authorEmail: "quinn.martinez@demo.exxat.io",
|
|
210
|
-
updatedAt: "2026-03-20",
|
|
211
|
-
folderId: "fld-clinical",
|
|
212
|
-
},
|
|
213
|
-
{
|
|
214
|
-
id: "q10",
|
|
215
|
-
questionId: "QB-PHA-010",
|
|
216
|
-
stem: "Pediatric dose calculation uses body surface area when…",
|
|
217
|
-
topic: "Pharmacology",
|
|
218
|
-
type: "short_answer",
|
|
219
|
-
difficulty: "hard",
|
|
220
|
-
author: "Dr. Chen",
|
|
221
|
-
authorEmail: "mei.chen@demo.exxat.io",
|
|
222
|
-
updatedAt: "2026-03-19",
|
|
223
|
-
folderId: "fld-science",
|
|
224
|
-
},
|
|
225
|
-
{
|
|
226
|
-
id: "q11",
|
|
227
|
-
questionId: "QB-SAF-011",
|
|
228
|
-
stem: "Fall risk assessment should be repeated after medication changes.",
|
|
229
|
-
topic: "Safety",
|
|
230
|
-
type: "true_false",
|
|
231
|
-
difficulty: "easy",
|
|
232
|
-
author: "Taylor Brooks",
|
|
233
|
-
authorEmail: "taylor.brooks@demo.exxat.io",
|
|
234
|
-
updatedAt: "2026-03-18",
|
|
235
|
-
folderId: "fld-ops",
|
|
236
|
-
},
|
|
237
|
-
{
|
|
238
|
-
id: "q12",
|
|
239
|
-
questionId: "QB-ICO-012",
|
|
240
|
-
stem: "Describe hand hygiene moments (WHO five moments).",
|
|
241
|
-
topic: "Infection control",
|
|
242
|
-
type: "short_answer",
|
|
243
|
-
difficulty: "medium",
|
|
244
|
-
author: "Jordan Lee",
|
|
245
|
-
authorEmail: "jordan.lee@demo.exxat.io",
|
|
246
|
-
updatedAt: "2026-03-17",
|
|
247
|
-
folderId: "fld-ops",
|
|
248
|
-
},
|
|
249
|
-
]
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { NAV_PRIMARY } from "@/lib/mock/navigation"
|
|
2
|
-
|
|
3
|
-
/** Clinical site row — same source as legacy Sites nav children. */
|
|
4
|
-
export interface SiteDirectoryRow extends Record<string, unknown> {
|
|
5
|
-
id: string
|
|
6
|
-
name: string
|
|
7
|
-
url: string
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export const SITES_DIRECTORY: SiteDirectoryRow[] = (NAV_PRIMARY.find(i => i.key === "sites")?.children ?? []).map(
|
|
11
|
-
c => ({
|
|
12
|
-
id: c.key,
|
|
13
|
-
name: c.title,
|
|
14
|
-
url: c.url,
|
|
15
|
-
}),
|
|
16
|
-
)
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { MetricInsight, MetricItem } from "@/components/key-metrics"
|
|
2
|
-
|
|
3
|
-
export function sitesKpiMetrics(count: number): MetricItem[] {
|
|
4
|
-
const active = Math.max(0, count - 3)
|
|
5
|
-
const pending = Math.min(count, 3)
|
|
6
|
-
return [
|
|
7
|
-
{
|
|
8
|
-
id: "total-sites",
|
|
9
|
-
label: "Total sites",
|
|
10
|
-
value: count,
|
|
11
|
-
delta: "+4",
|
|
12
|
-
trend: "up",
|
|
13
|
-
href: "#",
|
|
14
|
-
metricVariant: "hero",
|
|
15
|
-
},
|
|
16
|
-
{ id: "active", label: "Active", value: active, delta: "+3", trend: "up", href: "#" },
|
|
17
|
-
{ id: "pending", label: "Pending", value: pending, delta: "—", trend: "neutral", href: "#" },
|
|
18
|
-
{ id: "archived", label: "Archived", value: 0, delta: "—", trend: "neutral", href: "#" },
|
|
19
|
-
]
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export const SITES_KPI_INSIGHT: MetricInsight = {
|
|
23
|
-
title: "4 new sites added this month",
|
|
24
|
-
description: "Most recent additions are affiliated with the Nursing program.",
|
|
25
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2
|
-
// Team page — KPI strip (mirrors placements-kpi pattern for primary list template)
|
|
3
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
4
|
-
|
|
5
|
-
import type { MetricInsight, MetricItem } from "@/components/key-metrics"
|
|
6
|
-
import type { TeamMember } from "@/lib/mock/team"
|
|
7
|
-
|
|
8
|
-
export function teamKpiMetrics(members: TeamMember[]): MetricItem[] {
|
|
9
|
-
const active = members.filter(m => m.status === "active").length
|
|
10
|
-
const away = members.filter(m => m.status === "away").length
|
|
11
|
-
const invited = members.filter(m => m.status === "invited").length
|
|
12
|
-
return [
|
|
13
|
-
{
|
|
14
|
-
id: "total-members",
|
|
15
|
-
label: "Total members",
|
|
16
|
-
value: members.length,
|
|
17
|
-
delta: "+2",
|
|
18
|
-
trend: "up",
|
|
19
|
-
href: "#",
|
|
20
|
-
metricVariant: "hero",
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
id: "active",
|
|
24
|
-
label: "Active",
|
|
25
|
-
value: active,
|
|
26
|
-
delta: "—",
|
|
27
|
-
trend: "neutral",
|
|
28
|
-
href: "#",
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
id: "away",
|
|
32
|
-
label: "Away",
|
|
33
|
-
value: away,
|
|
34
|
-
delta: "—",
|
|
35
|
-
trend: "neutral",
|
|
36
|
-
href: "#",
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
id: "invited",
|
|
40
|
-
label: "Invited",
|
|
41
|
-
value: invited,
|
|
42
|
-
delta: invited > 0 ? "+1" : "—",
|
|
43
|
-
trend: invited > 0 ? "up" : "neutral",
|
|
44
|
-
href: "#",
|
|
45
|
-
},
|
|
46
|
-
]
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function teamKpiInsight(members: TeamMember[]): MetricInsight {
|
|
50
|
-
const invited = members.filter(m => m.status === "invited").length
|
|
51
|
-
return {
|
|
52
|
-
title: "Pending invites",
|
|
53
|
-
description:
|
|
54
|
-
invited > 0
|
|
55
|
-
? `${invited} invitation(s) outstanding. Resend or revoke from the roster.`
|
|
56
|
-
: "No pending invitations.",
|
|
57
|
-
severity: invited > 0 ? "warning" : "info",
|
|
58
|
-
actionLabel: "Ask Leo",
|
|
59
|
-
}
|
|
60
|
-
}
|