Skip to content
This repository has been archived by the owner on Jan 9, 2023. It is now read-only.

Commit

Permalink
feat(toolbar): basic button toolbar
Browse files Browse the repository at this point in the history
  • Loading branch information
jackcmeyer committed Feb 20, 2020
1 parent 0db0724 commit af22ce0
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 60 deletions.
120 changes: 63 additions & 57 deletions src/HospitalRun.tsx
Expand Up @@ -5,6 +5,8 @@ import { Toaster } from '@hospitalrun/components'
import Appointments from 'scheduling/appointments/Appointments'
import NewAppointment from 'scheduling/appointments/new/NewAppointment'
import ViewAppointment from 'scheduling/appointments/view/ViewAppointment'
import { ButtonBarProvider } from 'page-header/button-bar-context'
import ButtonToolBar from 'page-header/ButtonToolBar'
import Sidebar from './components/Sidebar'
import Permissions from './model/Permissions'
import Dashboard from './dashboard/Dashboard'
Expand All @@ -19,68 +21,72 @@ import PrivateRoute from './components/PrivateRoute'
const HospitalRun = () => {
const { title } = useSelector((state: RootState) => state.title)
const { permissions } = useSelector((state: RootState) => state.user)

return (
<div>
<Navbar />
<div className="container-fluid">
<Sidebar />
<div className="row">
<main role="main" className="col-md-9 ml-sm-auto col-lg-10 px-4">
<div className="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 className="h2">{title}</h1>
</div>
<div>
<Switch>
<Route exact path="/" component={Dashboard} />
<PrivateRoute
isAuthenticated={permissions.includes(Permissions.ReadPatients)}
exact
path="/patients"
component={Patients}
/>
<PrivateRoute
isAuthenticated={permissions.includes(Permissions.WritePatients)}
exact
path="/patients/new"
component={NewPatient}
/>
<PrivateRoute
isAuthenticated={
permissions.includes(Permissions.WritePatients) &&
permissions.includes(Permissions.ReadPatients)
}
exact
path="/patients/edit/:id"
component={EditPatient}
/>
<PrivateRoute
isAuthenticated={permissions.includes(Permissions.ReadPatients)}
path="/patients/:id"
component={ViewPatient}
/>
<PrivateRoute
isAuthenticated={permissions.includes(Permissions.ReadAppointments)}
exact
path="/appointments"
component={Appointments}
/>
<PrivateRoute
isAuthenticated={permissions.includes(Permissions.WriteAppointments)}
exact
path="/appointments/new"
component={NewAppointment}
/>
<PrivateRoute
isAuthenticated={permissions.includes(Permissions.ReadAppointments)}
exact
path="/appointments/:id"
component={ViewAppointment}
/>
</Switch>
</div>
<Toaster autoClose={5000} hideProgressBar draggable />
</main>
</div>
<ButtonBarProvider>
<div className="row">
<main role="main" className="col-md-9 ml-sm-auto col-lg-10 px-4">
<div className="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 className="h2">{title}</h1>
<ButtonToolBar />
</div>
<div>
<Switch>
<Route exact path="/" component={Dashboard} />
<PrivateRoute
isAuthenticated={permissions.includes(Permissions.ReadPatients)}
exact
path="/patients"
component={Patients}
/>
<PrivateRoute
isAuthenticated={permissions.includes(Permissions.WritePatients)}
exact
path="/patients/new"
component={NewPatient}
/>
<PrivateRoute
isAuthenticated={
permissions.includes(Permissions.WritePatients) &&
permissions.includes(Permissions.ReadPatients)
}
exact
path="/patients/edit/:id"
component={EditPatient}
/>
<PrivateRoute
isAuthenticated={permissions.includes(Permissions.ReadPatients)}
path="/patients/:id"
component={ViewPatient}
/>
<PrivateRoute
isAuthenticated={permissions.includes(Permissions.ReadAppointments)}
exact
path="/appointments"
component={Appointments}
/>
<PrivateRoute
isAuthenticated={permissions.includes(Permissions.WriteAppointments)}
exact
path="/appointments/new"
component={NewAppointment}
/>
<PrivateRoute
isAuthenticated={permissions.includes(Permissions.ReadAppointments)}
exact
path="/appointments/:id"
component={ViewAppointment}
/>
</Switch>
</div>
<Toaster autoClose={5000} hideProgressBar draggable />
</main>
</div>
</ButtonBarProvider>
</div>
</div>
)
Expand Down
9 changes: 9 additions & 0 deletions src/page-header/ButtonToolBar.tsx
@@ -0,0 +1,9 @@
import React from 'react'
import { useButtons } from './button-bar-context'

const ButtonToolBar = () => {
const buttons = useButtons()
return <>{buttons.map((button) => button)}</>
}

export default ButtonToolBar
36 changes: 36 additions & 0 deletions src/page-header/button-bar-context.tsx
@@ -0,0 +1,36 @@
import React, { useState } from 'react'

type Props = {
children: React.ReactNode
}

type ButtonUpdater = (buttons: React.ReactNode[]) => void

const ButtonBarStateContext = React.createContext<React.ReactNode[]>([])
const ButtonBarUpdateContext = React.createContext<ButtonUpdater>(() => {})

function ButtonBarProvider(props: Props) {
const { children } = props
const [state, setState] = useState<React.ReactNode[]>([])
return (
<ButtonBarStateContext.Provider value={state}>
<ButtonBarUpdateContext.Provider value={setState}>{children}</ButtonBarUpdateContext.Provider>
</ButtonBarStateContext.Provider>
)
}
function useButtons() {
const context = React.useContext(ButtonBarStateContext)
if (context === undefined) {
throw new Error('useCountState must be used within a CountProvider')
}
return context
}
function useButtonToolbarSetter() {
const context = React.useContext(ButtonBarUpdateContext)
if (context === undefined) {
throw new Error('useCountDispatch must be used within a CountProvider')
}
return context
}

export { ButtonBarProvider, useButtons, useButtonToolbarSetter }
19 changes: 18 additions & 1 deletion src/patients/list/Patients.tsx
Expand Up @@ -3,6 +3,7 @@ import { useSelector, useDispatch } from 'react-redux'
import { useHistory } from 'react-router'
import { useTranslation } from 'react-i18next'
import { Spinner, TextInput, Button, List, ListItem, Container, Row } from '@hospitalrun/components'
import { useButtonToolbarSetter } from 'page-header/button-bar-context'
import { RootState } from '../../store'
import { fetchPatients, searchPatients } from '../patients-slice'
import useTitle from '../../page-header/useTitle'
Expand All @@ -14,11 +15,27 @@ const Patients = () => {
const dispatch = useDispatch()
const { patients, isLoading } = useSelector((state: RootState) => state.patients)

const setButtonToolBar = useButtonToolbarSetter()
setButtonToolBar([
<Button
outlined
color="success"
icon="patient-add"
onClick={() => history.push('/patients/new')}
>
{t('patients.newPatient')}
</Button>,
])

const [searchText, setSearchText] = useState<string>('')

useEffect(() => {
dispatch(fetchPatients())
}, [dispatch])

return () => {
setButtonToolBar([])
}
}, [dispatch, setButtonToolBar])

if (isLoading) {
return <Spinner color="blue" loading size={[10, 25]} type="ScaleLoader" />
Expand Down
20 changes: 18 additions & 2 deletions src/scheduling/appointments/Appointments.tsx
@@ -1,11 +1,12 @@
import React, { useEffect, useState } from 'react'
import { Calendar } from '@hospitalrun/components'
import { Calendar, Button } from '@hospitalrun/components'
import useTitle from 'page-header/useTitle'
import { useTranslation } from 'react-i18next'
import { useSelector, useDispatch } from 'react-redux'
import { RootState } from 'store'
import { useHistory } from 'react-router'
import PatientRepository from 'clients/db/PatientRepository'
import { useButtonToolbarSetter } from 'page-header/button-bar-context'
import { fetchAppointments } from './appointments-slice'

interface Event {
Expand All @@ -23,10 +24,25 @@ const Appointments = () => {
const dispatch = useDispatch()
const { appointments } = useSelector((state: RootState) => state.appointments)
const [events, setEvents] = useState<Event[]>([])
const setButtonToolBar = useButtonToolbarSetter()
setButtonToolBar([
<Button
outlined
color="success"
icon="appointment-add"
onClick={() => history.push('/appointments/new')}
>
New Appointment
</Button>,
])

useEffect(() => {
dispatch(fetchAppointments())
}, [dispatch])

return () => {
setButtonToolBar([])
}
}, [dispatch, setButtonToolBar])

useEffect(() => {
const getAppointments = async () => {
Expand Down

0 comments on commit af22ce0

Please sign in to comment.