Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge Develop to Staging v24.31.0 #8210

Merged
merged 5 commits into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cypress/e2e/patient_spec/patient_discharge.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ describe("Patient Discharge based on multiple reason", () => {
patientDischarge.clickDischarge();
patientDischarge.selectDischargeReason(patientDischargeReason4);
cy.submitButton("Confirm Discharge");
cy.submitButton("Acknowledge & Submit");
cy.verifyNotification("Patient Discharged Successfully");
cy.closeNotification();
// Verify the consultation dashboard reflection
Expand All @@ -53,6 +54,7 @@ describe("Patient Discharge based on multiple reason", () => {
patientDischarge.typeDischargeNote(patientDeathCause);
patientDischarge.typeDoctorName(doctorName);
cy.submitButton("Confirm Discharge");
cy.submitButton("Acknowledge & Submit");
cy.verifyNotification("Patient Discharged Successfully");
cy.closeNotification();
// Verify the consultation dashboard reflection
Expand All @@ -77,6 +79,7 @@ describe("Patient Discharge based on multiple reason", () => {
patientDischarge.typeReferringFacility(referringFreetextFacility);
cy.wait(2000);
cy.submitButton("Confirm Discharge");
cy.submitButton("Acknowledge & Submit");
cy.wait(2000);
cy.verifyNotification("Patient Discharged Successfully");
cy.closeNotification();
Expand Down Expand Up @@ -108,6 +111,7 @@ describe("Patient Discharge based on multiple reason", () => {
cy.closeNotification();
// submit the discharge pop-up
cy.submitButton("Confirm Discharge");
cy.submitButton("Acknowledge & Submit");
cy.wait(2000);
cy.verifyNotification("Patient Discharged Successfully");
cy.closeNotification();
Expand Down
2 changes: 1 addition & 1 deletion src/CAREUI/display/NetworkSignal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export default function NetworkSignal({ strength, children }: Props) {
i === 2 && "h-[15px]",

// Whether to infill with strength color or not
strength > i ? "bg-current" : "bg-zinc-600",
strength > i ? "bg-current" : "bg-zinc-500/30",
)}
/>
))
Expand Down
42 changes: 28 additions & 14 deletions src/CAREUI/interactive/KeyboardShortcut.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,50 @@ import useKeyboardShortcut from "use-keyboard-shortcut";
import { classNames, isAppleDevice } from "../../Utils/utils";

interface Props {
children: React.ReactNode;
children?: React.ReactNode;
shortcut: string[];
altShortcuts?: string[][];
onTrigger: () => void;
shortcutSeperator?: string;
helpText?: string;
tooltipClassName?: string;
}

export default function KeyboardShortcut(props: Props) {
useKeyboardShortcut(props.shortcut, props.onTrigger, {
overrideSystem: true,
});
useKeyboardShortcut(props.shortcut, props.onTrigger);

if (!props.children) {
return null;
}

return (
<div className="tooltip">
{props.children}
<span
className={classNames(
"tooltip-text flex items-center gap-0.5 text-xs",
"tooltip-text space-x-1 text-xs",
props.tooltipClassName || "tooltip-bottom",
)}
>
<span className="px-1 font-bold">{props.helpText}</span>
<kbd className="hidden items-center px-1.5 font-sans font-medium text-zinc-300 shadow md:inline-flex">
{getShortcutKeyDescription(props.shortcut).join(" + ")}
</kbd>
{props.helpText && (
<span className="pl-1 font-bold">{props.helpText}</span>
)}
{(props.altShortcuts || [props.shortcut]).map((shortcut, idx, arr) => (
<>
<kbd className="hidden items-center px-1.5 font-sans font-medium text-zinc-300 shadow lg:inline-flex">
{shortcut.map((key, idx, keys) => (
<>
{SHORTCUT_KEY_MAP[key] || key}
{idx !== keys.length - 1 && (
<span className="px-1 text-zinc-300/60"> + </span>
)}
</>
))}
</kbd>
{idx !== arr.length - 1 && (
<span className="text-zinc-300/60">or</span>
)}
</>
))}
</span>
</div>
);
Expand All @@ -43,7 +61,3 @@ const SHORTCUT_KEY_MAP = {
ArrowLeft: "←",
ArrowRight: "→",
} as Record<string, string>;

export const getShortcutKeyDescription = (shortcut: string[]) => {
return shortcut.map((key) => SHORTCUT_KEY_MAP[key] || key);
};
9 changes: 9 additions & 0 deletions src/Common/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ export const USER_TYPE_OPTIONS = [
{ id: "StateAdmin", role: "State Admin", readOnly: false },
] as const;

export const USER_LAST_ACTIVE_OPTIONS = [
{ id: 1, text: "24 hours" },
{ id: 7, text: "7 days" },
{ id: 30, text: "30 days" },
{ id: 90, text: "90 days" },
{ id: 365, text: "1 Year" },
{ id: "never", text: "Never" },
];

export type UserRole = (typeof USER_TYPE_OPTIONS)[number]["id"];

export const USER_TYPES = USER_TYPE_OPTIONS.map((o) => o.id);
Expand Down
17 changes: 17 additions & 0 deletions src/Common/hooks/useConfirmedAction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useState } from "react";

export default function useConfirmedAction(action: () => Promise<void>) {
const [showConfirmation, setShowConfirmation] = useState(false);

return {
requestConfirmation: () => setShowConfirmation(true),
submit: action,

confirmationProps: {
onClose: () => setShowConfirmation(false),
show: showConfirmation,
onConfirm: action,
action: "Submit",
},
};
}
83 changes: 45 additions & 38 deletions src/Components/CameraFeed/AssetBedSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ import { AssetBedModel } from "../Assets/AssetTypes";
import { Listbox, Transition } from "@headlessui/react";
import CareIcon from "../../CAREUI/icons/CareIcon";
import { classNames } from "../../Utils/utils";
import { dropdownOptionClassNames } from "../Form/MultiSelectMenuV2";
import ButtonV2 from "../Common/components/ButtonV2";

interface Props {
disabled?: boolean;
options: AssetBedModel[];
value?: AssetBedModel;
label?: (value: AssetBedModel) => string;
Expand All @@ -15,34 +18,44 @@ export default function CameraPresetSelect(props: Props) {
const label = props.label ?? defaultLabel;
return (
<>
<div className="hidden gap-4 whitespace-nowrap pr-2 lg:flex lg:gap-2">
{/* Desktop View */}
{/* Desktop View */}
<div className="hidden gap-4 whitespace-nowrap pr-2 lg:flex lg:gap-1.5">
{props.options
.slice(0, props.options.length > 5 ? 4 : 5)
.map((option) => (
<button
className={classNames(
"min-w-16 max-w-40 overflow-hidden text-ellipsis whitespace-nowrap rounded-lg border-2 px-2 py-0.5 text-base transition-all duration-200 ease-in-out hover:bg-zinc-600",
props.value?.id === option.id
? "border-white bg-zinc-100 font-bold text-black"
: "border-zinc-700 font-medium text-zinc-300",
)}
onClick={() => props.onChange?.(option)}
>
{label(option)}
</button>
))}
.map((option) => {
const selected = props.value?.id === option.id;

return (
<ButtonV2
key={option.id}
variant={selected ? "primary" : "secondary"}
className="min-w-16 max-w-40 text-ellipsis text-sm"
onClick={() => props.onChange?.(option)}
border
size="small"
>
{label(option)}
{selected && (
<CareIcon
icon="l-check"
className="rounded-full bg-primary-500 text-base text-white"
/>
)}
</ButtonV2>
);
})}
{props.options.length > 5 && (
<CameraPresetDropdown
{...props}
placeholder="More preset"
placeholder="More presets"
options={props.options.slice(4)}
value={props.options.slice(4).find((o) => o.id === props.value?.id)}
/>
)}
</div>

{/* Mobile View */}
<div className="w-full lg:hidden">
{/* Mobile View */}
<CameraPresetDropdown {...props} placeholder="Select preset" />
</div>
</>
Expand All @@ -62,15 +75,15 @@ export const CameraPresetDropdown = (
<Listbox
value={selected}
onChange={props.onChange}
disabled={options.length === 0}
disabled={options.length === 0 || props.disabled}
>
<div className="relative flex-1">
<Listbox.Button
className={classNames(
"relative min-w-32 max-w-40 overflow-hidden text-ellipsis whitespace-nowrap rounded-lg border-2 px-2 py-1 pr-8 text-left text-sm font-medium transition-all duration-200 ease-in-out hover:bg-zinc-600 focus:outline-none disabled:cursor-not-allowed disabled:bg-transparent disabled:text-zinc-700 md:py-0.5 md:text-base",
"button-size-small button-shape-square relative inline-flex h-min min-w-32 cursor-pointer items-center gap-2 whitespace-pre pr-12 text-left text-sm font-medium shadow outline-offset-1 transition-all duration-200 ease-in-out enabled:hover:shadow-md disabled:cursor-not-allowed disabled:bg-secondary-200 disabled:text-secondary-500 md:min-w-40",
selected
? "border-zinc-700 bg-zinc-700/50 text-white md:font-bold"
: "border-zinc-700 text-zinc-300",
? "button-primary-default button-primary-border"
: "button-secondary-default button-secondary-border",
)}
>
<span className="block truncate">
Expand All @@ -80,38 +93,32 @@ export const CameraPresetDropdown = (
? label(selected)
: props.placeholder}
</span>
{selected && (
<CareIcon
icon="l-check"
className="absolute inset-y-0 right-7 mt-1.5 rounded-full bg-primary-500 text-base text-white"
/>
)}
<span className="pointer-events-none absolute inset-y-0 right-0 mr-1 mt-1 flex items-center">
<CareIcon icon="l-angle-down" className="text-xl text-zinc-400" />
</span>
</Listbox.Button>
<Transition
as={Fragment}
leave="transition ease-in duration-100"
leave="transition ease-in duration-300"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Listbox.Options className="absolute z-20 mt-1 max-h-48 w-full overflow-auto rounded-b-lg bg-zinc-900/75 py-1 text-base shadow-lg ring-1 ring-white/5 backdrop-blur-sm focus:outline-none md:max-h-60">
<Listbox.Options className="absolute z-20 max-h-48 w-full overflow-auto rounded-b-lg bg-white py-1 text-base shadow-lg ring-1 ring-gray-500 focus:outline-none md:max-h-60">
{options?.map((obj) => (
<Listbox.Option
key={obj.id}
className={({ active }) =>
`relative cursor-default select-none px-2 py-1 ${
active ? "bg-zinc-700 text-white" : "text-zinc-400"
}`
className={(args) =>
classNames(dropdownOptionClassNames(args), "px-2 py-1.5")
}
value={obj}
>
{({ selected }) => (
<>
<span
className={`block truncate text-sm md:text-base ${
selected ? "font-bold text-white" : "font-normal"
}`}
>
{label(obj)}
</span>
</>
)}
<span>{label(obj)}</span>
</Listbox.Option>
))}
</Listbox.Options>
Expand Down
Loading
Loading