@@ -8,23 +8,22 @@ import Link from 'next/link'
88import {
99 Avatar ,
1010 Dialog ,
11+ Expandable ,
1112 ExpansionIcon ,
1213 IconButton ,
13- MarkdownInterpreter ,
14- Menu ,
15- MenuItem ,
14+ LoadingContainer ,
15+ MarkdownInterpreter , Menu , MenuItem ,
1616 SolidButton ,
1717 useLocalStorage
1818} from '@helpwave/hightide'
1919import { getConfig } from '@/utils/config'
2020import { useTasksTranslation } from '@/i18n/useTasksTranslation'
2121import clsx from 'clsx'
22- import { BellIcon , CircleCheck , Grid2X2PlusIcon , SettingsIcon , User , Building2 , Users } from 'lucide-react'
23- import { usePathname } from 'next/navigation'
22+ import { BellIcon , Building2 , CircleCheck , Grid2X2PlusIcon , SettingsIcon , User , Users } from 'lucide-react'
2423import { TasksLogo } from '@/components/TasksLogo'
2524import { useRouter } from 'next/router'
26- import { useGlobalContext } from '@/context/GlobalContext '
27- import { logout } from '@/api/auth/authService '
25+ import { useTasksContext } from '@/hooks/useTasksContext '
26+ import { useAuth } from '@/hooks/useAuth '
2827
2928export const StagingDisclaimerDialog = ( ) => {
3029 const config = getConfig ( )
@@ -77,10 +76,14 @@ export const StagingDisclaimerDialog = () => {
7776
7877type HeaderProps = HTMLAttributes < HTMLHeadElement >
7978
79+ /**
80+ * The basic header for most pages
81+ */
8082export const Header = ( { ...props } : HeaderProps ) => {
81- const router = useRouter ( )
82- const { user } = useGlobalContext ( )
8383 const translation = useTasksTranslation ( )
84+ const { user } = useTasksContext ( )
85+ const router = useRouter ( )
86+ const { logout } = useAuth ( )
8487
8588 return (
8689 < header
@@ -134,72 +137,36 @@ export const Header = ({ ...props }: HeaderProps) => {
134137
135138type SidebarLinkProps = AnchorHTMLAttributes < HTMLAnchorElement > & {
136139 href : string ,
137- route ?: string ,
138- isActive ?: boolean ,
139140}
140141
141- const SidebarLink = ( { children, route, isActive, className, ...props } : SidebarLinkProps ) => {
142- const active = isActive !== undefined ? isActive : ( route === props . href )
142+ const SidebarLink = ( { children, ...props } : SidebarLinkProps ) => {
143+ const { route } = useTasksContext ( )
144+
143145 return (
144146 < Link
145147 { ...props }
146148 className = { clsx (
147149 'flex-row-1.5 w-full px-2.5 py-1.5 items-center rounded-md hover:bg-black/30' ,
148- { 'text-primary font-bold bg-black/10 ' : active } ,
149- className
150+ { 'text-primary font-bold' : route === props . href } ,
151+ props . className
150152 ) }
151153 >
152154 { children }
153155 </ Link >
154156 )
155157}
156158
157- type SidebarGroupProps = {
158- title : string ,
159- icon : React . ReactNode ,
160- children : React . ReactNode ,
161- initiallyExpanded ?: boolean ,
162- }
163-
164- const SidebarGroup = ( { title, icon, children, initiallyExpanded = false } : SidebarGroupProps ) => {
165- const [ isExpanded , setIsExpanded ] = useState ( initiallyExpanded )
166-
167- return (
168- < div className = "flex-col-1" >
169- < button
170- onClick = { ( ) => setIsExpanded ( ! isExpanded ) }
171- className = { clsx (
172- 'flex-row-1.5 w-full px-2.5 py-1.5 items-center rounded-md hover:bg-black/30 text-left transition-colors' ,
173- { 'text-primary font-bold bg-black/10' : isExpanded }
174- ) }
175- >
176- { icon }
177- < span className = "flex grow" > { title } </ span >
178- < ExpansionIcon isExpanded = { isExpanded } />
179- </ button >
180- { isExpanded && (
181- < div className = "flex-col-1 animate-in fade-in slide-in-from-top-1 duration-200" >
182- { children }
183- </ div >
184- ) }
185- </ div >
186- )
187- }
188159
189160type SidebarProps = HTMLAttributes < HTMLDivElement >
190161
162+ /**
163+ * The basic sidebar for most pages
164+ */
191165export const Sidebar = ( { ...props } : SidebarProps ) => {
192166 const translation = useTasksTranslation ( )
193- const route = usePathname ( )
194- const {
195- wards,
196- teams,
197- selectedLocation,
198- setSelectedLocation,
199- stats
200- } = useGlobalContext ( )
201-
202- const isPatientsRoute = route === '/patients'
167+ const wardsRoute = '/wards'
168+ const teamsRoute = '/teams'
169+ const context = useTasksContext ( )
203170
204171 return (
205172 < aside
@@ -214,71 +181,81 @@ export const Sidebar = ({ ...props }: SidebarProps) => {
214181 < TasksLogo />
215182 < span className = "typography-title-md whitespace-nowrap" > { 'helpwave tasks' } </ span >
216183 </ Link >
217-
218- < SidebarLink href = "/" route = { route } >
219- < Grid2X2PlusIcon className = "-rotate-90 size-5" />
184+ < SidebarLink href = "/" >
185+ < Grid2X2PlusIcon className = "-rotate-90 size-5" />
220186 < span className = "flex grow" > { translation ( 'dashboard' ) } </ span >
221187 </ SidebarLink >
222-
223- < SidebarLink href = "/tasks" route = { route } >
224- < CircleCheck className = "size-5" />
188+ < SidebarLink href = "/tasks" >
189+ < CircleCheck className = "size-5" />
225190 < span className = "flex grow" > { translation ( 'myTasks' ) } </ span >
226- { stats . myOpenTasksCount > 0 && ( < span className = "text-description" > { stats . myOpenTasksCount } </ span > ) }
191+ { context ?. myTasksCount !== undefined && ( < span className = "text-description" > { context . myTasksCount } </ span > ) }
227192 </ SidebarLink >
228-
229- < SidebarLink
230- href = "/patients"
231- isActive = { isPatientsRoute && selectedLocation === null }
232- onClick = { ( ) => setSelectedLocation ( null ) }
233- >
234- < User className = "size-5" />
193+ < SidebarLink href = "/patients" >
194+ < User className = "size-5" />
235195 < span className = "flex grow" > { translation ( 'patients' ) } </ span >
236- < span className = "text-description" > { stats . totalPatientsCount } </ span >
237196 </ SidebarLink >
238197
239- { /* Teams Group */ }
240- { teams . length > 0 && (
241- < SidebarGroup
242- title = { translation ( 'teams' ) }
243- icon = { < Users className = "size-5" /> }
244- initiallyExpanded = { isPatientsRoute && teams . some ( t => t . id === selectedLocation ) }
245- >
246- { teams . map ( team => (
247- < SidebarLink
248- key = { team . id }
249- href = "/patients"
250- className = "pl-9"
251- isActive = { isPatientsRoute && selectedLocation === team . id }
252- onClick = { ( ) => setSelectedLocation ( team . id ) }
253- >
254- < span className = "flex grow truncate" > { team . title } </ span >
255- </ SidebarLink >
256- ) ) }
257- </ SidebarGroup >
258- ) }
259-
260- { /* Wards Group */ }
261- { wards . length > 0 && (
262- < SidebarGroup
263- title = { translation ( 'wards' ) }
264- icon = { < Building2 className = "size-5" /> }
265- initiallyExpanded = { isPatientsRoute && wards . some ( w => w . id === selectedLocation ) }
266- >
267- { wards . map ( ward => (
268- < SidebarLink
269- key = { ward . id }
270- href = "/patients"
271- className = "pl-9"
272- isActive = { isPatientsRoute && selectedLocation === ward . id }
273- onClick = { ( ) => setSelectedLocation ( ward . id ) }
274- >
275- < span className = "flex grow truncate" > { ward . title } </ span >
276- </ SidebarLink >
277- ) ) }
278- </ SidebarGroup >
279- ) }
280-
198+ < Expandable
199+ label = { (
200+ < div className = "flex-row-2" >
201+ < Users className = "size-5" />
202+ { translation ( 'teams' ) }
203+ </ div >
204+ ) }
205+ headerClassName = "!px-2.5 !py-1.5 hover:bg-black/30"
206+ contentClassName = "!px-0"
207+ className = "!shadow-none"
208+ isExpanded = { context . sidebar . isShowingTeams }
209+ onChange = { isExpanded => context . update ( prevState => ( {
210+ ...prevState ,
211+ sidebar : {
212+ ...prevState . sidebar ,
213+ isShowingTeams : isExpanded ,
214+ }
215+ } ) ) }
216+ >
217+ < SidebarLink href = { teamsRoute } className = "pl-9.5" >
218+ { translation ( 'overview' ) }
219+ </ SidebarLink >
220+ { ! context ?. teams ? (
221+ < LoadingContainer className = "w-full h-10" />
222+ ) : context . teams . map ( ward => (
223+ < SidebarLink key = { ward . id } href = { `${ teamsRoute } /${ ward . id } ` } className = "pl-9.5" >
224+ { ward . title }
225+ </ SidebarLink >
226+ ) ) }
227+ </ Expandable >
281228
229+ < Expandable
230+ label = { (
231+ < div className = "flex-row-2" >
232+ < Building2 className = "size-5" />
233+ { translation ( 'wards' ) }
234+ </ div >
235+ ) }
236+ headerClassName = "!px-2.5 !py-1.5 hover:bg-black/30"
237+ contentClassName = "!px-0"
238+ className = "!shadow-none"
239+ isExpanded = { context . sidebar . isShowingWards }
240+ onChange = { isExpanded => context . update ( prevState => ( {
241+ ...prevState ,
242+ sidebar : {
243+ ...prevState . sidebar ,
244+ isShowingWards : isExpanded ,
245+ }
246+ } ) ) }
247+ >
248+ < SidebarLink href = { wardsRoute } className = "pl-9.5" >
249+ { translation ( 'overview' ) }
250+ </ SidebarLink >
251+ { ! context ?. wards ? (
252+ < LoadingContainer className = "w-full h-10" />
253+ ) : context . wards . map ( ward => (
254+ < SidebarLink key = { ward . id } href = { `${ wardsRoute } /${ ward . id } ` } className = "pl-9.5" >
255+ { ward . title }
256+ </ SidebarLink >
257+ ) ) }
258+ </ Expandable >
282259 </ nav >
283260 </ aside >
284261 )
0 commit comments