@@ -11,18 +11,22 @@ import type { IKpi, IIKpiResultBeforeAfter } from "../../types";
1111import { BeforeAndAfterDates , LivingLabKpiResultsForm } from "./form" ;
1212import { KpiTypeBadge } from "./KpiTypeBadge" ;
1313import { KpiMetricTypeBadge } from "./KpiMetricTypeBadge" ;
14- import { Badge } from "./ui" ;
14+ import { Badge , ExpansionPanel } from "./ui" ;
15+ import type { ICategory } from "../../types/Category" ;
16+ import { tr } from "motion/react-client" ;
1517
1618type Props = {
1719 kpis : IKpi [ ] ;
1820 livingLabId : number ;
1921 kpiResults : IIKpiResultBeforeAfter [ ] ;
22+ categories : ICategory [ ] ;
2023} ;
2124
2225export function LivingLabKPIs ( {
2326 kpis = [ ] ,
2427 livingLabId,
2528 kpiResults : livingLabKpis = [ ] ,
29+ categories = [ ] ,
2630} : Props ) {
2731 if ( ! kpis || kpis . length === 0 ) {
2832 return < div > No KPIs available.</ div > ;
@@ -34,63 +38,99 @@ export function LivingLabKPIs({
3438 const [ beforeDate , setBeforeDate ] = useState < string > ( today ) ;
3539 const [ afterDate , setAfterDate ] = useState < string > ( today ) ;
3640
41+ const getKpiRow = ( kpiId : number ) => {
42+ let kpi = kpis . find ( ( k ) => k . id === kpiId ) ;
43+ const hasChildren = kpis . some ( ( k ) => k . parent_kpi_id === kpiId ) ;
44+ const idChild = kpi ?. parent_kpi_id ? true : false ;
45+
46+ if ( ! kpi ) return null ;
47+ return (
48+ < TableRow
49+ key = { kpiId }
50+ className = { hasChildren || ! idChild ? "border-t-2 border-info/30" : "" }
51+ >
52+ < TableCell className = "flex flex-col w-22" >
53+ { kpi . kpi_number }
54+ < KpiTypeBadge type = { kpi . type } />
55+ </ TableCell >
56+ < TableCell className = "whitespace-pre-line break-words" >
57+ { kpi . name }
58+ < Badge tooltip = { kpi . description } size = "sm" color = "info" />
59+ </ TableCell >
60+ < TableCell >
61+ { ! hasChildren && (
62+ < div className = "flex flex-col text-xs" >
63+ < KpiMetricTypeBadge type = { kpi . metric } />
64+ { kpi . metric_description ?. length &&
65+ kpi . metric_description ?. length > 0 && (
66+ < strong > { kpi . metric_description } </ strong >
67+ ) }
68+ { typeof kpi . min_value === "number" && (
69+ < span > Min: { kpi . min_value } </ span >
70+ ) }
71+ { typeof kpi . max_value === "number" && (
72+ < span > Max: { kpi . max_value } </ span >
73+ ) }
74+ </ div >
75+ ) }
76+ </ TableCell >
77+ < TableCell className = "w-20" >
78+ { ! hasChildren && (
79+ < LivingLabKpiResultsForm
80+ livingLabId = { livingLabId }
81+ kpiId = { kpi . id }
82+ kpiMetric = { kpi . metric }
83+ initialBefore = { livingLabKpiMap . get ( kpi . id ) ?. result_before }
84+ initialAfter = { livingLabKpiMap . get ( kpi . id ) ?. result_after }
85+ defaultBeforeDate = { beforeDate }
86+ defaultAfterDate = { afterDate }
87+ />
88+ ) }
89+ </ TableCell >
90+ </ TableRow >
91+ ) ;
92+ } ;
93+
3794 return (
3895 < div className = "flex flex-col gap-8 mx-auto" >
3996 < BeforeAndAfterDates
4097 onChangeBeforeDate = { setBeforeDate }
4198 onChangeAfterDate = { setAfterDate }
4299 />
43- < Table dense striped className = "lg:min-w-3xl max-w-5xl" >
44- < TableHead >
45- < TableRow >
46- < TableHeader > KPI Number</ TableHeader >
47- < TableHeader > Name</ TableHeader >
48- < TableHeader > Metric unit</ TableHeader >
49- < TableHeader > Value Before vs After</ TableHeader >
50- </ TableRow >
51- </ TableHead >
100+ { categories . map ( ( { id, name, kpis } , index ) => (
101+ < ExpansionPanel
102+ key = { id }
103+ header = {
104+ < div className = "flex flex-row justify-center items-center gap-2 rounded-2xl border-info bg-info px-2 py-1" >
105+ < h5 > { name } </ h5 >
106+ < Badge
107+ color = "light"
108+ size = "sm"
109+ tooltip = "Number of KPIs in this category"
110+ displayTooltipIcon = { false }
111+ >
112+ { kpis ?. length || 0 } KPIs
113+ </ Badge >
114+ </ div >
115+ }
116+ arrow
117+ open = { index === 0 }
118+ content = {
119+ < Table dense className = "lg:min-w-3xl max-w-5xl" >
120+ < TableHead >
121+ < TableRow >
122+ < TableHeader > KPI Number</ TableHeader >
123+ < TableHeader > Name</ TableHeader >
124+ < TableHeader > Metric unit</ TableHeader >
125+ < TableHeader > Value Before vs After</ TableHeader >
126+ </ TableRow >
127+ </ TableHead >
52128
53- < TableBody >
54- { kpis . map ( ( kpi , idx ) => (
55- < TableRow key = { kpi . kpi_number ?? idx } >
56- < TableCell className = "flex flex-col w-22" >
57- { kpi . kpi_number }
58- < KpiTypeBadge type = { kpi . type } />
59- </ TableCell >
60- < TableCell className = "whitespace-pre-line break-words" >
61- { kpi . name }
62- < Badge tooltip = { kpi . description } size = "sm" color = "info" />
63- </ TableCell >
64- < TableCell >
65- < div className = "flex flex-col text-xs" >
66- < KpiMetricTypeBadge type = { kpi . metric } />
67- { kpi . metric_description ?. length &&
68- kpi . metric_description ?. length > 0 && (
69- < strong > { kpi . metric_description } </ strong >
70- ) }
71- { typeof kpi . min_value === "number" && (
72- < span > Min: { kpi . min_value } </ span >
73- ) }
74- { typeof kpi . max_value === "number" && (
75- < span > Max: { kpi . max_value } </ span >
76- ) }
77- </ div >
78- </ TableCell >
79- < TableCell className = "w-20" >
80- < LivingLabKpiResultsForm
81- livingLabId = { livingLabId }
82- kpiId = { kpi . id }
83- kpiMetric = { kpi . metric }
84- initialBefore = { livingLabKpiMap . get ( kpi . id ) ?. result_before }
85- initialAfter = { livingLabKpiMap . get ( kpi . id ) ?. result_after }
86- defaultBeforeDate = { beforeDate }
87- defaultAfterDate = { afterDate }
88- />
89- </ TableCell >
90- </ TableRow >
91- ) ) }
92- </ TableBody >
93- </ Table >
129+ < TableBody > { kpis ?. map ( ( { id } ) => getKpiRow ( id ) ) } </ TableBody >
130+ </ Table >
131+ }
132+ />
133+ ) ) }
94134 </ div >
95135 ) ;
96136}
0 commit comments