import moment from "moment" ; import { useCallback , useState } from "react" ; import { useDispatch } from "react-redux" ; import { statusType , useAbortableEffect } from "../../../Common/utils" ; import { dailyRoundsAnalyse } from "../../../Redux/actions" ; import { LinePlot } from "./components/LinePlot" ; import ExpandMoreIcon from "@material-ui/icons/ExpandMore" ; import ExpandLessIcon from "@material-ui/icons/ExpandLess" ; import { StackedLinePlot } from "./components/StackedLinePlot" ; import Pagination from "../../Common/Pagination" ; import { PAGINATION_LIMIT } from "../../../Common/constants" ; export const NutritionPlots = ( props ) => { const { facilityId , patientId , consultationId } = props ; const dispatch = useDispatch ( ) ; const [ isLoading , setIsLoading ] = useState ( false ) ; const [ results , setResults ] = useState ( { } ) ; const [ showIO , setShowIO ] = useState ( true ) ; const [ showIntake , setShowIntake ] = useState ( false ) ; const [ showOutput , setShowOutput ] = useState ( false ) ; const [ currentPage , setCurrentPage ] = useState ( 1 ) ; const [ totalCount , setTotalCount ] = useState ( 0 ) ; const fetchDailyRounds = useCallback ( async ( status ) => { setIsLoading ( true ) ; const res = await dispatch ( dailyRoundsAnalyse ( { page : currentPage , fields : [ "infusions" , "iv_fluids" , "feeds" , "total_intake_calculated" , "total_output_calculated" , "output" , ] , } , { consultationId } ) ) ; if ( ! status . aborted ) { if ( res && res . data ) { setResults ( res . data . results ) ; setTotalCount ( res . data . count ) ; } setIsLoading ( false ) ; } } , [ consultationId , dispatch , currentPage ] ) ; useAbortableEffect ( ( status ) => { fetchDailyRounds ( status ) ; } , [ currentPage ] ) ; const handlePagination = ( page , limit ) => { setCurrentPage ( page ) ; } ; const dates = Object . keys ( results ) . map ( ( p ) => moment ( p ) . format ( "LLL" ) ) . reverse ( ) ; const yAxisData = ( name ) => { return Object . values ( results ) . map ( ( p ) => p [ name ] ) . reverse ( ) ; } ; const IOvalues = Object . values ( results ) . map ( ( p ) => p [ "total_intake_calculated" ] - p [ "total_output_calculated" ] ) . reverse ( ) ; const infusionList = [ ] ; Object . values ( results ) . map ( ( p ) => p . infusions . map ( ( x ) => infusionList . indexOf ( x . name ) === - 1 ? infusionList . push ( x . name ) : null ) ) ; let infusionsData = { } ; infusionList . map ( ( x ) => ( infusionsData [ x ] = { name : x , data : [ ... Array ( Object . keys ( results ) . length ) . fill ( undefined ) ] , } ) ) ; Object . values ( results ) . reverse ( ) . map ( ( p , i ) => { p . infusions . map ( ( infusion ) => { const item = infusionsData [ infusion . name ] ; item . data [ i ] = infusion . quantity ; } ) ; } ) ; const IVFluidsList = [ ] ; Object . values ( results ) . map ( ( p ) => p . iv_fluids . map ( ( x ) => IVFluidsList . indexOf ( x . name ) === - 1 ? IVFluidsList . push ( x . name ) : null ) ) ; let IVFluidsData = { } ; IVFluidsList . map ( ( x ) => ( IVFluidsData [ x ] = { name : x , data : [ ... Array ( Object . keys ( results ) . length ) . fill ( undefined ) ] , } ) ) ; Object . values ( results ) . reverse ( ) . map ( ( p , i ) => { p . iv_fluids . map ( ( iv_fluid ) => { const item = IVFluidsData [ iv_fluid . name ] ; item . data [ i ] = iv_fluid . quantity ; } ) ; } ) ; const FeedsList = [ ] ; Object . values ( results ) . map ( ( p ) => p . feeds . map ( ( x ) => FeedsList . indexOf ( x . name ) === - 1 ? FeedsList . push ( x . name ) : null ) ) ; let FeedsData = { } ; FeedsList . map ( ( x ) => ( FeedsData [ x ] = { name : x , data : [ ... Array ( Object . keys ( results ) . length ) . fill ( undefined ) ] , } ) ) ; Object . values ( results ) . reverse ( ) . map ( ( p , i ) => { p . feeds . map ( ( feed ) => { const item = FeedsData [ feed . name ] ; item . data [ i ] = feed . quantity ; } ) ; } ) ; const OutputList = [ ] ; Object . values ( results ) . map ( ( p ) => p . output . map ( ( x ) => OutputList . indexOf ( x . name ) === - 1 ? OutputList . push ( x . name ) : null ) ) ; let OutputData = { } ; OutputList . map ( ( x ) => ( OutputData [ x ] = { name : x , data : [ ... Array ( Object . keys ( results ) . length ) . fill ( undefined ) ] , } ) ) ; Object . values ( results ) . reverse ( ) . map ( ( p , i ) => { p . output . map ( ( x ) => { const item = OutputData [ x . name ] ; item . data [ i ] = x . quantity ; } ) ; } ) ; return ( < div > < section className = "rounded-lg shadow p-4 h-full space-y-2 text-gray-100 my-4 bg-white" > < div className = "flex justify-between border-b border-dashed text-gray-900 font-semibold text-left text-lg pb-2" onClick = { ( ) => setShowIO ( ! showIO ) } > < div > IO Balance Plots < /div> { showIO ? < ExpandLessIcon /> : <ExpandMoreIcon / > } < /div> < div className = { showIO ? "grid grid-row-1 md:grid-cols-2 gap-4" : "hidden" } > < div className = "pt-4 px-4 bg-white border rounded-lg  md:col-span-2" > < LinePlot title = "IO Balance" name = "IO Balance" xData = { dates } yData = { IOvalues } / > < /div> < div className = "pt-4 px-4 bg-white border rounded-lg " > < LinePlot title = "Total Intake" name = "Total Intake" xData = { dates } yData = { yAxisData ( "total_intake_calculated" ) } / > < /div> < div className = "pt-4 px-4 bg-white border rounded-lg " > < LinePlot title = "Total Output" name = "Total Output" xData = { dates } yData = { yAxisData ( "total_output_calculated" ) } / > < /div> < /div> < /section> < section className = "rounded-lg shadow p-4 h-full space-y-2 text-gray-100 my-4 bg-white" > < div className = "flex justify-between border-b border-dashed text-gray-900 font-semibold text-left text-lg pb-2" onClick = { ( ) => setShowIntake ( ! showIntake ) } > < div > Intake < /div> { showIntake ? < ExpandLessIcon /> : <ExpandMoreIcon / > } < /div> < div className = { showIntake ? "grid md:grid-cols-2 gap-4" : "hidden" } > < div className = "pt-4 px-4 bg-white border rounded-lg md:col-span-2" > < LinePlot title = "Total Intake" name = "Total Intake" xData = { dates } yData = { yAxisData ( "total_intake_calculated" ) } / > < /div> < div className = "pt-4 px-4 bg-white border rounded-lg " > < StackedLinePlot title = "Infusions" xData = { dates } yData = { Object . values ( infusionsData ) } / > < /div> < div className = "pt-4 px-4 bg-white border rounded-lg text-gray-900" > < h3 className = "text-lg" > Infusions : < /h3> < div className = "overflow-y-auto pb-2 h-72" > { Object . entries ( results ) . map ( ( obj ) => { if ( obj [ 1 ] . infusions && obj [ 1 ] . infusions . length > 0 ) { return ( < div > < h4 className = "text-sm" > - { moment ( obj [ 0 ] ) . format ( "LLL" ) } < /h4> < div className = "px-5 text-sm" > { obj [ 1 ] . infusions . map ( ( o ) => ( < div > { o . name } - { o . quantity } < /div>))} < /div> < /div>); } } ) } < /div> < /div> < div className = "pt-4 px-4 bg-white border rounded-lg" > < StackedLinePlot title = "IV Fluids" xData = { dates } yData = { Object . values ( IVFluidsData ) } / > < /div> < div className = "pt-4 px-4 bg-white border rounded-lg text-gray-900" > < h3 className = "text-lg" > IV Fluids : < /h3> < div className = "overflow-y-auto pb-2 h-72" > { Object . entries ( results ) . map ( ( obj ) => { if ( obj [ 1 ] . iv_fluids && obj [ 1 ] . iv_fluids . length > 0 ) { return ( < div > < h4 className = "text-sm" > - { moment ( obj [ 0 ] ) . format ( "LLL" ) } < /h4> < div className = "px-5 text-sm" > { obj [ 1 ] . iv_fluids . map ( ( o ) => ( < div > { o . name } - { o . quantity } < /div>))} < /div> < /div>); } } ) } < /div> < /div> < div className = "pt-4 px-4 bg-white border rounded-lg" > < StackedLinePlot title = "Feeds" xData = { dates } yData = { Object . values ( FeedsData ) } / > < /div> < div className = "pt-4 px-4 bg-white border rounded-lg text-gray-900" > < h3 className = "text-lg" > Feeds : < /h3> < div className = "overflow-y-auto pb-2 h-72" > { Object . entries ( results ) . map ( ( obj ) => { if ( obj [ 1 ] . feeds && obj [ 1 ] . feeds . length > 0 ) { return ( < div > < h4 className = "text-sm" > - { moment ( obj [ 0 ] ) . format ( "LLL" ) } < /h4> < div className = "px-5 text-sm" > { obj [ 1 ] . feeds . map ( ( o ) => ( < div > { o . name } - { o . quantity } < /div>))} < /div> < /div>); } } ) } < /div> < /div> < /div> < /section> < section className = "rounded-lg shadow p-4 h-full space-y-2 text-gray-100 my-4 bg-white" > < div className = "flex justify-between border-b border-dashed text-gray-900 font-semibold text-left text-lg pb-2" onClick = { ( ) => setShowOutput ( ! showOutput ) } > < div > Output < /div> { showOutput ? < ExpandLessIcon /> : <ExpandMoreIcon / > } < /div> < div className = { showOutput ? "grid grid-row-1 md:grid-cols-2 gap-4" : "hidden" } > < div className = "pt-4 px-4 bg-white border rounded-lg md:col-span-2" > < LinePlot title = "Total Output" name = "Total Output" xData = { dates } yData = { yAxisData ( "total_output_calculated" ) } / > < /div> < div className = "pt-4 px-4 bg-white border rounded-lg" > < StackedLinePlot title = "Output" xData = { dates } yData = { Object . values ( OutputData ) } / > < /div> < div className = "pt-4 px-4 bg-white border rounded-lg text-gray-900" > < h3 className = "text-lg" > Output : < /h3> < div className = "overflow-y-auto pb-2 h-72" > { Object . entries ( results ) . map ( ( obj ) => { if ( obj [ 1 ] . output && obj [ 1 ] . output . length > 0 ) { return ( < div > < h4 className = "text-sm" > - { moment ( obj [ 0 ] ) . format ( "LLL" ) } < /h4> < div className = "px-5 text-sm" > { obj [ 1 ] . output . map ( ( o ) => ( < div > { o . name } - { o . quantity } < /div>))} < /div> < /div>); } } ) } < /div> < /div> < /div> < /section> { totalCount > PAGINATION_LIMIT && ( < div className = "mt-4 flex w-full justify-center" > < Pagination cPage = { currentPage } defaultPerPage = { PAGINATION_LIMIT } data = { { totalCount } } onChange = { handlePagination } / > < /div>)} < /div>); } ;