Skip to content

Commit

Permalink
Merge pull request #130 from RyanNerd/124-change-how-name-button-popo…
Browse files Browse the repository at this point in the history
…ver-works

Revamp the client name and DOB buttons
  • Loading branch information
RyanNerd authored Jun 15, 2021
2 parents 886cb5a + 6e3391b commit c94863e
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 39 deletions.
88 changes: 49 additions & 39 deletions src/components/App.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
import React, {useGlobal, useState} from 'reactn';
import React, {useGlobal, useState, useEffect} from 'reactn';

import {Popover, PopoverTitle} from "react-bootstrap";
import {ButtonGroup} from "react-bootstrap";

import About from "./Pages/Modals/About";
import ActiveResidentObserver from "../observers/ActiveResidentObserver";
import ApiKeyObserver from "../observers/ApiKeyObserver";
import AuthObserver from "../observers/AuthObserver";
import ClientButton from "./Buttons/ClientButton";
import ClientDobButton from "./Buttons/ClientDobButton";
import ClientObserver from "../observers/ClientObserver";
import ClientRoster from "./Pages/Modals/ClientRoster";
import DrugLogObserver from "../observers/DrugLogObserver";
import ErrorDetailsObserver from "../observers/ErrorDetailsObserver";
import LandingPage from "./Pages/LandingPage";
import MedicineObserver from "../observers/MedicineObserver";
import OtcMedicineObserver from "../observers/OtcMedicineObserver";
import PopoverButton from "./Buttons/PopoverButton";
import TooltipButton from "./Buttons/TooltipButton";
import {ReactComponent as RxIcon} from "../icons/prescription.svg";
import {clientDOB, clientFullName} from "../utility/common";
import ResidentEdit from "./Pages/Modals/ResidentEdit";
import {ReactComponent as RxIcon} from "../icons/prescription.svg";
import {ResidentRecord} from "../types/RecordTypes";

/**
Expand All @@ -28,13 +27,15 @@ import {ResidentRecord} from "../types/RecordTypes";
const App = () => {
const [, setClient] = useGlobal('__client');
const [activeClient, setActiveClient] = useGlobal('activeResident');
const [, setActiveTabKey] = useGlobal('activeTabKey');
const [development] = useGlobal('development');
const [mm] = useGlobal('medicineManager');
const [providers] = useGlobal('providers');
const [showClientEdit, setShowClientEdit] = useState(false);
const [showClientRoster, setShowClientRoster] = useState(false);
const [showAboutPage, setShowAboutPage] = useState(false);
const [signIn] = useGlobal('signIn');
const [hmisName, setHmisName] = useState('');

/**
* Initialize all the observers
Expand Down Expand Up @@ -81,17 +82,21 @@ const App = () => {
OtcMedicineObserver(mm); // Watching: __otcMedicine

/**
* Client notes popover attached to the active client DOB button at the top of the web page.
* Launch HMIS website when hmisName is populated, but first copy the name to the clipboard.
*/
const clientNotesPopover =
<Popover id="client-notes-popover">
<PopoverTitle>
Client Notes
</PopoverTitle>
<Popover.Content>
{activeClient && activeClient?.Notes}
</Popover.Content>
</Popover>
useEffect(() => {
if (hmisName?.trim().length > 0) {
const handleClipboardEvent = (e: ClipboardEvent) => {
e?.clipboardData?.setData('text/plain', (hmisName));
e.preventDefault();
}
document.addEventListener('copy', (e: ClipboardEvent) => handleClipboardEvent(e));
document.execCommand('copy');
window.open('https://www.clienttrack.net/utahhmis', '_blank');
setHmisName('');
return ()=> document.removeEventListener('copy', handleClipboardEvent);
}
}, [hmisName]);

return (
<>
Expand All @@ -111,32 +116,37 @@ const App = () => {

{activeClient &&
<h1
className="d-print-none"
className="d-print-none auto-center"
style={{textAlign: "center"}}
>
<TooltipButton
variant={development ? "outline-danger" : "outline-warning"}
placement="left"
tooltip="Print Medbox Labels"
disabled={showClientRoster}
onClick={() => setShowClientRoster(true)}
>
<span style={{fontStyle: development ? "italic" : "bold"}}>
{clientFullName(activeClient)}
</span>
</TooltipButton>
<ButtonGroup>
<ClientButton
className="mr-2"
clientRecord={activeClient}
development={development}
onSelect={(choice)=> {
switch (choice) {
case 'edit':
setShowClientEdit(true);
break;
case 'print':
setShowClientRoster(true);
break;
case 'hmis':
setHmisName(activeClient.LastName + ', ' + activeClient.FirstName);
break;
case 'switch':
setActiveTabKey('resident');
break;
}
}}
/>

<PopoverButton
defaultShow={!!activeClient.Notes}
onClick={() => setShowClientEdit(true)}
placement="bottom"
popover={activeClient.Notes ? clientNotesPopover : undefined}
variant={activeClient.Notes ? "danger" : "outline-dark"}
>
<span style={{fontStyle: "bold"}}>
<span>{clientDOB(activeClient)}</span> {activeClient.Notes && <span>🔔</span>}
</span>
</PopoverButton>
<ClientDobButton
clientRecord={activeClient}
development={development}
/>
</ButtonGroup>
</h1>
}

Expand Down
75 changes: 75 additions & 0 deletions src/components/Buttons/ClientButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import React from "reactn";
import {clientFullName} from "../../utility/common";
import {ResidentRecord} from "../../types/RecordTypes";
import {Dropdown, DropdownButton} from "react-bootstrap";

// @ts-ignore Some props are completely incompatible and even the type `any` doesn't make TS happy
interface IProps {
className?: any
clientRecord: ResidentRecord
development: boolean
onSelect?: (choice: string) => void
disabled?: boolean
[key: string]: any
}

const ClientButton = (props: IProps) => {
const {
clientRecord,
development = true,
onSelect,
className,
disabled
} = props;

const handleClick = (choice: string) => {
if (onSelect) {
onSelect(choice);
}
}

const clientName = (
<span style={{fontStyle: development ? "italic" : "bold"}}>
{clientFullName(clientRecord)}
</span>
);

/**
* Work-around so React 17 can be used
* @link https://github.com/react-bootstrap/react-bootstrap/issues/5409#issuecomment-718699584
*/
return (
<DropdownButton
variant="success"
title={clientName}
id="client-dropdown-button"
className={className}
onClick={(e: React.MouseEvent<HTMLElement>) => e.stopPropagation()}
disabled={disabled}
>
<Dropdown.Item
onClick={()=>handleClick('edit')}
>
Edit Client
</Dropdown.Item>
<Dropdown.Item
onClick={()=>handleClick('print')}
>
Print Medbox Labels
</Dropdown.Item>
<Dropdown.Item
onClick={()=>handleClick('hmis')}
>
Copy name to clipboard and launch HMIS
</Dropdown.Item>
<Dropdown.Divider/>
<Dropdown.Item
onClick={()=>handleClick('switch')}
>
Switch to a different client
</Dropdown.Item>
</DropdownButton>
)
}

export default ClientButton;
65 changes: 65 additions & 0 deletions src/components/Buttons/ClientDobButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React from "reactn";

import {Badge, Dropdown, DropdownButton} from "react-bootstrap";

import {clientDOB} from "../../utility/common";
import {ResidentRecord} from "../../types/RecordTypes";

// @ts-ignore Some props are completely incompatible and even the type `any` doesn't make TS happy
interface IProps {
className?: any
clientRecord: ResidentRecord
development: boolean
onSelect?: (choice: string) => void
disabled?: boolean
}

/**
* ClientDobButton is a dropdown button that displays the date of birth of the given client record
* The dropdown shows the client notes if they have any.
* @param {IProps} props
*/
const ClientDobButton = (props: IProps) => {
const {
clientRecord,
development = true,
className,
disabled
} = props;

const clientDobComponent = (
<span style={{fontStyle: development ? "italic" : "bold"}}>
{clientRecord.Notes && <Badge variant="light">🔔</Badge>}{" "}{clientDOB(clientRecord)}
</span>
);

/**
* CSS Style override for getting the Dropdown.ItemText to display correctly
* @link https://stackoverflow.com/a/17887494/4323201
* Work-around so React 17 can be used
* @link https://github.com/react-bootstrap/react-bootstrap/issues/5409#issuecomment-718699584
*/
return (
<DropdownButton
className={className}
disabled={disabled || clientRecord.Notes == null || clientRecord?.Notes?.trim().length === 0}
id="client-dob-dropdown-button"
onClick={(e: React.MouseEvent<HTMLElement>) => e.stopPropagation()}
title={clientDobComponent}
variant="outline-secondary"
>
<Dropdown.Item
style={{whiteSpace: "normal", width: "300px"}}
>
<Dropdown.Header>
<h5>Notes</h5>
</Dropdown.Header>
<Dropdown.ItemText>
{clientRecord.Notes}
</Dropdown.ItemText>
</Dropdown.Item>
</DropdownButton>
)
}

export default ClientDobButton;
4 changes: 4 additions & 0 deletions src/components/Pages/Modals/ResidentEdit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,11 @@ const ResidentEdit = (props: IProps): JSX.Element | null => {
value={residentInfo.Notes}
name="Notes"
onChange={(e) => handleOnChange(e)}
className={residentInfo?.Notes?.trim().length > 500 ? 'is-invalid' : ''}
/>
<div className="invalid-feedback">
Notes can only be 500 characters long. length={residentInfo?.Notes?.trim().length}
</div>
</Col>
</Form.Group>
</Form>
Expand Down

0 comments on commit c94863e

Please sign in to comment.