diff --git a/public/locale/en.json b/public/locale/en.json
index 2a485441d4f..910baca98cf 100644
--- a/public/locale/en.json
+++ b/public/locale/en.json
@@ -328,6 +328,7 @@
"add_new_patient": "Add New Patient",
"add_new_user": "Add New User",
"add_notes": "Add notes",
+ "add_patient_updates": "Add Patient Updates",
"add_policy": "Add Insurance Policy",
"add_prescription_medication": "Add Prescription Medication",
"add_prescription_to_consultation_note": "Add a new prescription to this consultation.",
diff --git a/src/CAREUI/display/Callout.tsx b/src/CAREUI/display/Callout.tsx
index 0983d66f298..c1d4b05a88f 100644
--- a/src/CAREUI/display/Callout.tsx
+++ b/src/CAREUI/display/Callout.tsx
@@ -2,10 +2,8 @@ import React from "react";
import { cn } from "@/lib/utils";
-import { ButtonVariant } from "@/components/Common/ButtonV2";
-
interface CalloutProps {
- variant?: ButtonVariant;
+ variant?: "primary" | "secondary" | "warning" | "alert" | "danger";
className?: string;
badge: string;
children: React.ReactNode;
diff --git a/src/CAREUI/display/Chip.tsx b/src/CAREUI/display/Chip.tsx
deleted file mode 100644
index e501bf26f90..00000000000
--- a/src/CAREUI/display/Chip.tsx
+++ /dev/null
@@ -1,57 +0,0 @@
-import CareIcon, { IconName } from "@/CAREUI/icons/CareIcon";
-
-import { ButtonVariant } from "@/components/Common/ButtonV2";
-
-import { classNames } from "@/Utils/utils";
-
-interface Props {
- size?: "small" | "medium" | "large";
- hideBorder?: boolean;
- variant?: ButtonVariant | "custom";
- startIcon?: IconName;
- endIcon?: IconName;
- text: string;
- tooltip?: string;
- className?: string;
- id?: string;
-}
-
-export default function Chip({
- size = "medium",
- hideBorder = false,
- variant = "primary",
- ...props
-}: Props) {
- return (
-
- {props.startIcon && }
- {props.text}
- {props.endIcon && }
-
- );
-}
diff --git a/src/CAREUI/display/PopupModal.tsx b/src/CAREUI/display/PopupModal.tsx
deleted file mode 100644
index 6410addbcc2..00000000000
--- a/src/CAREUI/display/PopupModal.tsx
+++ /dev/null
@@ -1,151 +0,0 @@
-import { ReactNode, useEffect, useRef, useState } from "react";
-import { useTranslation } from "react-i18next";
-
-import { Cancel, Submit } from "@/components/Common/ButtonV2";
-import DialogModal from "@/components/Common/Dialog";
-
-import useBreakpoints from "@/hooks/useBreakpoints";
-
-import { classNames } from "@/Utils/utils";
-
-type Props = {
- show: boolean;
- onHide: () => void;
- children: ReactNode;
- anchorRef: React.RefObject;
- className?: string;
- onSubmit?: () => void;
-};
-
-type Position =
- | { left: number; top: number }
- | { right: number; bottom: number }
- | { left: number; bottom: number }
- | { right: number; top: number };
-
-export default function PopupModal(props: Props) {
- const { t } = useTranslation();
- const isMobile = useBreakpoints({ default: true, lg: false });
-
- if (!isMobile) {
- return ;
- }
-
- return (
-
-
- {props.children}
-
-
- {props.onSubmit && (
-
- )}
-
-
-
- );
-}
-
-const DesktopView = (props: Props) => {
- const { t } = useTranslation();
- const [position, setPosition] = useState({ left: 0, top: 0 });
- const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });
- const modal = useRef(null);
- const [children, setChildren] = useState(props.children);
-
- useEffect(() => {
- // just to make sure the animation runs smoothly
- if (props.show) {
- setChildren(props.children);
- }
- }, [props.children, props.show]);
-
- useEffect(() => {
- const handleOutsideClick = (e: MouseEvent) => {
- const isModalClicked =
- modal.current && modal.current.contains(e.target as Node);
- if (!isModalClicked) {
- props.onHide();
- }
- };
-
- if (props.show) {
- const currentMousePosition = mousePosition;
- const modalHeight = modal.current?.clientHeight || 0;
- const modalWidth = modal.current?.clientWidth || 0;
- const clickX = currentMousePosition.x;
- const clickY = currentMousePosition.y;
- const windowHeight = window.innerHeight;
- const windowWidth = window.innerWidth;
-
- const anchorPosition = props.anchorRef.current?.getBoundingClientRect();
- const anchorX = anchorPosition?.x || 0;
- const anchorY = anchorPosition?.y || 0;
- const verticalCenter = windowHeight / 2;
- const horizontalCenter = windowWidth / 2;
- const mountLeft = clickX - anchorX;
- const mountTop = clickY - anchorY;
-
- let position;
- if (clickX > horizontalCenter) {
- position = { left: mountLeft - modalWidth };
- } else {
- position = { left: mountLeft };
- }
- if (clickY > verticalCenter) {
- position = { ...position, top: mountTop - modalHeight };
- } else {
- position = { ...position, top: mountTop };
- }
- setPosition(position);
- }
-
- document.addEventListener("mousedown", handleOutsideClick);
- return () => {
- document.removeEventListener("mousedown", handleOutsideClick);
- };
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [props.show]);
-
- useEffect(() => {
- const handleMouseMove = (e: MouseEvent) => {
- setMousePosition({ x: e.clientX, y: e.clientY });
- };
- document.addEventListener("mousemove", handleMouseMove);
- return () => {
- document.removeEventListener("mousemove", handleMouseMove);
- };
- }, []);
-
- const positionAttributes = Object.entries(position).reduce(
- (acc, [key, value]) => {
- return { ...acc, [key]: `${value}px` };
- },
- {},
- );
-
- return (
-
- {children}
-
-
- {props.onSubmit && (
-
- )}
-
-
- );
-};
diff --git a/src/CAREUI/interactive/FiltersSlideover.tsx b/src/CAREUI/interactive/FiltersSlideover.tsx
index 6e4feeaf852..b3c11fcd035 100644
--- a/src/CAREUI/interactive/FiltersSlideover.tsx
+++ b/src/CAREUI/interactive/FiltersSlideover.tsx
@@ -6,8 +6,6 @@ import SlideOver from "@/CAREUI/interactive/SlideOver";
import { Button } from "@/components/ui/button";
-import ButtonV2 from "@/components/Common/ButtonV2";
-
import useFilters from "@/hooks/useFilters";
type AdvancedFilter = ReturnType["advancedFilter"];
@@ -35,18 +33,17 @@ export default function FiltersSlideover({
{t("filters")}
-
+
-
+
+
+
}
diff --git a/src/CAREUI/interactive/Zoom.tsx b/src/CAREUI/interactive/Zoom.tsx
index 0d6513efbba..d97300d36cb 100644
--- a/src/CAREUI/interactive/Zoom.tsx
+++ b/src/CAREUI/interactive/Zoom.tsx
@@ -2,7 +2,7 @@ import { ReactNode, createContext, useContext, useState } from "react";
import CareIcon from "@/CAREUI/icons/CareIcon";
-import ButtonV2 from "@/components/Common/ButtonV2";
+import { Button } from "@/components/ui/button";
type ProviderValue = {
scale: number;
@@ -69,31 +69,25 @@ export const ZoomControls = (props: { disabled?: boolean }) => {
return (
-
-
+
{Math.round(ctx.scale * 100)}%
-
-
+
);
};
diff --git a/src/CAREUI/misc/PaginatedList.tsx b/src/CAREUI/misc/PaginatedList.tsx
index 6379b8b7ad8..9cefca73aac 100644
--- a/src/CAREUI/misc/PaginatedList.tsx
+++ b/src/CAREUI/misc/PaginatedList.tsx
@@ -2,7 +2,8 @@ import { createContext, useContext, useEffect, useState } from "react";
import CareIcon from "@/CAREUI/icons/CareIcon";
-import ButtonV2, { CommonButtonProps } from "@/components/Common/ButtonV2";
+import { Button, ButtonProps } from "@/components/ui/button";
+
import Pagination from "@/components/Common/Pagination";
import { PaginatedResponse, QueryRoute } from "@/Utils/request/types";
@@ -118,13 +119,16 @@ const WhenLoading = (props: WhenEmptyProps) => {
PaginatedList.WhenLoading = WhenLoading;
+interface CommonButtonProps extends ButtonProps {
+ label?: string;
+}
+
const Refresh = ({ label = "Refresh", ...props }: CommonButtonProps) => {
const { loading, refetch } = useContextualized
@@ -261,8 +263,12 @@ const ExcelViewer = ({
>
-
-
+ {t("close")}
+
+
+
);
diff --git a/src/components/Common/FilePreviewDialog.tsx b/src/components/Common/FilePreviewDialog.tsx
index 95155fcc9d9..4d6709d427d 100644
--- a/src/components/Common/FilePreviewDialog.tsx
+++ b/src/components/Common/FilePreviewDialog.tsx
@@ -14,12 +14,12 @@ import { useTranslation } from "react-i18next";
import CareIcon, { IconName } from "@/CAREUI/icons/CareIcon";
-import ButtonV2, { Cancel } from "@/components/Common/ButtonV2";
+import { Button } from "@/components/ui/button";
+
import CircularProgress from "@/components/Common/CircularProgress";
import DialogModal from "@/components/Common/Dialog";
import { StateInterface } from "@/components/Files/FileUpload";
-
-import { FileUploadModel } from "../Patient/models";
+import { FileUploadModel } from "@/components/Patient/models";
const PDFViewer = lazy(() => import("@/components/Common/PDFViewer"));
@@ -211,24 +211,27 @@ const FilePreviewDialog = (props: FilePreviewProps) => {
{uploadedFiles && uploadedFiles.length > 1 && (
-
handleNext(index - 1)}
disabled={index <= 0}
aria-label="Previous file"
@@ -237,7 +240,7 @@ const FilePreviewDialog = (props: FilePreviewProps) => {
}
>
-
+
)}
{file_state.isImage ? (
@@ -279,8 +282,9 @@ const FilePreviewDialog = (props: FilePreviewProps) => {
{uploadedFiles && uploadedFiles.length > 1 && (
-
handleNext(index + 1)}
disabled={index >= uploadedFiles.length - 1}
aria-label="Next file"
@@ -289,7 +293,7 @@ const FilePreviewDialog = (props: FilePreviewProps) => {
}
>
-
+
)}
@@ -330,9 +334,8 @@ const FilePreviewDialog = (props: FilePreviewProps) => {
false,
],
].map((button, index) => (
-
void}
className="z-50 rounded bg-white/60 px-4 py-2 text-black backdrop-blur transition hover:bg-white/70"
@@ -345,7 +348,7 @@ const FilePreviewDialog = (props: FilePreviewProps) => {
/>
)}
{button[0] as string}
-
+
))}
>
)}
@@ -366,9 +369,8 @@ const FilePreviewDialog = (props: FilePreviewProps) => {
page === numPages,
],
].map((button, index) => (
-
void}
className="z-50 rounded bg-white/60 px-4 py-2 text-black backdrop-blur transition hover:bg-white/70"
@@ -381,7 +383,7 @@ const FilePreviewDialog = (props: FilePreviewProps) => {
/>
)}
{button[0] as string}
-
+
))}
>
)}
diff --git a/src/components/Common/Menu.tsx b/src/components/Common/Menu.tsx
index aa647a3dedb..6568e5b143c 100644
--- a/src/components/Common/Menu.tsx
+++ b/src/components/Common/Menu.tsx
@@ -3,7 +3,7 @@ import { DetailedHTMLProps, HTMLAttributes, ReactNode } from "react";
import CareIcon from "@/CAREUI/icons/CareIcon";
-import { ButtonSize, ButtonVariant } from "@/components/Common/ButtonV2";
+import { buttonVariants } from "@/components/ui/button";
import { useIsAuthorized } from "@/hooks/useIsAuthorized";
@@ -13,8 +13,6 @@ import { classNames } from "@/Utils/utils";
interface DropdownMenuProps {
id?: string;
title: string;
- variant?: ButtonVariant;
- size?: ButtonSize;
icon?: JSX.Element | undefined;
children: ReactNode | ReactNode[];
disabled?: boolean | undefined;
@@ -23,11 +21,11 @@ interface DropdownMenuProps {
containerClassName?: string | undefined;
}
-export default function DropdownMenu({
- variant = "primary",
- size = "default",
- ...props
-}: DropdownMenuProps) {
+/**
+ * @deprecated This component will be replaced with ShadCN's dropdown.
+ */
+
+export default function DropdownMenu({ ...props }: DropdownMenuProps) {
return (
-
+
{props.icon}
{props.title || "Dropdown"}
-
+
-
- {icon}
-
+ {icon}
{children}
diff --git a/src/components/Common/Pagination.tsx b/src/components/Common/Pagination.tsx
index fb12ff66efa..6db267ed9c7 100644
--- a/src/components/Common/Pagination.tsx
+++ b/src/components/Common/Pagination.tsx
@@ -2,7 +2,7 @@ import { useState } from "react";
import CareIcon from "@/CAREUI/icons/CareIcon";
-import ButtonV2 from "@/components/Common/ButtonV2";
+import { Button } from "@/components/ui/button";
import { statusType, useAbortableEffect } from "@/common/utils";
@@ -171,18 +171,17 @@ interface NavButtonProps {
const NavButton = (props: NavButtonProps) => {
return (
-
{props.children}
{props.tooltip}
-
+
);
};
diff --git a/src/components/Common/UpdatableApp.tsx b/src/components/Common/UpdatableApp.tsx
index d27c778830f..c623c2c10a3 100644
--- a/src/components/Common/UpdatableApp.tsx
+++ b/src/components/Common/UpdatableApp.tsx
@@ -3,7 +3,7 @@ import { ReactNode, useEffect, useState } from "react";
import CareIcon from "@/CAREUI/icons/CareIcon";
-import ButtonV2 from "@/components/Common/ButtonV2";
+import { Button } from "@/components/ui/button";
import { classNames } from "@/Utils/utils";
@@ -136,14 +136,9 @@ const UpdateAppPopup = ({ onUpdate }: UpdateAppPopupProps) => {
A new version of CARE is available
-
+
+
diff --git a/src/components/Facility/FacilityHome.tsx b/src/components/Facility/FacilityHome.tsx
index 7f33dec2b1b..3eba20f4765 100644
--- a/src/components/Facility/FacilityHome.tsx
+++ b/src/components/Facility/FacilityHome.tsx
@@ -190,7 +190,7 @@ export const FacilityHome = ({ facilityId }: Props) => {
}
action="Delete"
- variant="danger"
+ variant="destructive"
show={openDeleteDialog}
onClose={handleDeleteClose}
onConfirm={handleDeleteSubmit}
diff --git a/src/components/Files/CameraCaptureDialog.tsx b/src/components/Files/CameraCaptureDialog.tsx
index f81d854c559..0a9e3fc39ad 100644
--- a/src/components/Files/CameraCaptureDialog.tsx
+++ b/src/components/Files/CameraCaptureDialog.tsx
@@ -4,7 +4,8 @@ import Webcam from "react-webcam";
import CareIcon from "@/CAREUI/icons/CareIcon";
-import ButtonV2, { Submit } from "@/components/Common/ButtonV2";
+import { Button } from "@/components/ui/button";
+
import DialogModal from "@/components/Common/Dialog";
import useBreakpoints from "@/hooks/useBreakpoints";
@@ -134,9 +135,13 @@ export default function CameraCaptureDialog(props: CameraCaptureDialogProps) {
{!previewImage ? (
-
+
+
) : (
<>>
)}
@@ -145,20 +150,22 @@ export default function CameraCaptureDialog(props: CameraCaptureDialogProps) {
{!previewImage ? (
<>
- {
captureImage();
}}
className="m-2"
>
{t("capture")}
-
+
>
) : (
<>
- {
setPreviewImage(null);
onResetCapture();
@@ -166,8 +173,9 @@ export default function CameraCaptureDialog(props: CameraCaptureDialogProps) {
className="m-2"
>
{t("retake")}
-
-
+
+
>
)}
- {
setPreviewImage(null);
onResetCapture();
@@ -191,16 +199,16 @@ export default function CameraCaptureDialog(props: CameraCaptureDialogProps) {
className="m-2"
>
{t("close")}
-
+
{/* buttons for laptop screens */}
-
+
+
@@ -208,42 +216,45 @@ export default function CameraCaptureDialog(props: CameraCaptureDialogProps) {
{!previewImage ? (
<>
- {
captureImage();
}}
>
{t("capture")}
-
+
>
) : (
<>
- {
setPreviewImage(null);
onResetCapture();
}}
>
{t("retake")}
-
-
+
+
>
)}
-
{
setPreviewImage(null);
onResetCapture();
@@ -251,7 +262,7 @@ export default function CameraCaptureDialog(props: CameraCaptureDialogProps) {
}}
>
{`${t("close")} ${t("camera")}`}
-
+
diff --git a/src/components/Files/FileBlock.tsx b/src/components/Files/FileBlock.tsx
index 5015a67e2e1..46b6f680889 100644
--- a/src/components/Files/FileBlock.tsx
+++ b/src/components/Files/FileBlock.tsx
@@ -3,7 +3,8 @@ import { t } from "i18next";
import CareIcon, { IconName } from "@/CAREUI/icons/CareIcon";
-import ButtonV2 from "@/components/Common/ButtonV2";
+import { Button } from "@/components/ui/button";
+
import { FileUploadModel } from "@/components/Patient/models";
import { FileManagerResult } from "@/hooks/useFileManager";
@@ -90,35 +91,37 @@ export default function FileBlock(props: FileBlockProps) {
)}
{!file.is_archived &&
(fileManager.isPreviewable(file) ? (
- fileManager.viewFile(file, associating_id)}
className="w-full md:w-auto"
>
{t("view")}
-
+
) : (
- fileManager.downloadFile(file, associating_id)}
className="w-full md:w-auto"
>
{t("download")}
-
+
))}
{!file.is_archived && editable && (
- fileManager.editFile(file, associating_id)}
className="flex-1 md:flex-auto"
>
{t("rename")}
-
+
)}
{(file.is_archived || editable) && archivable && (
- fileManager.archiveFile(file, associating_id)}
className="flex-1 md:flex-auto"
@@ -127,7 +130,7 @@ export default function FileBlock(props: FileBlockProps) {
icon={file.is_archived ? "l-info-circle" : "l-archive"}
/>
{file.is_archived ? t("more_info") : t("archive")}
-
+
)}
diff --git a/src/components/Files/FileUpload.tsx b/src/components/Files/FileUpload.tsx
index e28c99ce513..7a4798c5320 100644
--- a/src/components/Files/FileUpload.tsx
+++ b/src/components/Files/FileUpload.tsx
@@ -1,10 +1,12 @@
+import { Loader2 } from "lucide-react";
import { ReactNode, useState } from "react";
import { useTranslation } from "react-i18next";
import CareIcon, { IconName } from "@/CAREUI/icons/CareIcon";
import AuthorizedChild from "@/CAREUI/misc/AuthorizedChild";
-import ButtonV2 from "@/components/Common/ButtonV2";
+import { Button } from "@/components/ui/button";
+
import Pagination from "@/components/Common/Pagination";
import Tabs from "@/components/Common/Tabs";
import FileBlock from "@/components/Files/FileBlock";
@@ -291,25 +293,30 @@ export const FileUpload = (props: FileUploadProps) => {
error={fileUpload.error || undefined}
/>
-
fileUpload.handleFileUpload(associatedId)
}
- loading={fileUpload.uploading}
- className="w-full"
+ disabled={fileUpload.uploading} // Disable the button when loading
+ className={`w-full ${fileUpload.uploading ? "opacity-50" : ""}`}
id="upload_file_button"
>
-
+ {fileUpload.uploading ? (
+
+ ) : (
+
+ )}
{t("upload")}
-
-
+
+
{!!fileUpload.progress && (
diff --git a/src/components/Form/Form.tsx b/src/components/Form/Form.tsx
index 97f424f69d7..38a4cb0818b 100644
--- a/src/components/Form/Form.tsx
+++ b/src/components/Form/Form.tsx
@@ -1,6 +1,7 @@
import { useEffect, useMemo, useRef, useState } from "react";
-import { Cancel, Submit } from "@/components/Common/ButtonV2";
+import { Button } from "@/components/ui/button";
+
import { FieldValidator } from "@/components/Form/FieldValidators";
import {
FormContextValue,
@@ -142,19 +143,20 @@ const Form = ({
{(!hideCancelButton || !hideSubmitButton) && (
{!hideCancelButton && (
-
+
)}
{!hideSubmitButton && (
-
+ >
+ {props.submitLabel ?? "Submit"}
+
)}
)}
diff --git a/src/components/Patient/PatientConsentRecordBlock.tsx b/src/components/Patient/PatientConsentRecordBlock.tsx
index f46648c0bae..0378ba95819 100644
--- a/src/components/Patient/PatientConsentRecordBlock.tsx
+++ b/src/components/Patient/PatientConsentRecordBlock.tsx
@@ -1,6 +1,8 @@
+import { t } from "i18next";
import { useEffect, useState } from "react";
-import ButtonV2 from "@/components/Common/ButtonV2";
+import { Button } from "@/components/ui/button";
+
import { PatientConsentModel } from "@/components/Facility/models";
import FileBlock from "@/components/Files/FileBlock";
import { SelectFormField } from "@/components/Form/FormFields/SelectFormField";
@@ -86,15 +88,16 @@ export default function PatientConsentRecordBlockGroup(props: {
required
error="Please select a patient code status type"
/>
- {
handlePCSUpdate(patientCodeStatus);
}}
disabled={patientCodeStatus === consentRecord.patient_code_status}
className="h-[46px]"
>
- Update
-
+ {t("update")}
+
)}
{files?.map((file: FileUploadModel, i: number) => (
diff --git a/src/components/Patient/PatientConsentRecords.tsx b/src/components/Patient/PatientConsentRecords.tsx
index 55ced7435ed..7d33487c730 100644
--- a/src/components/Patient/PatientConsentRecords.tsx
+++ b/src/components/Patient/PatientConsentRecords.tsx
@@ -1,9 +1,10 @@
import { t } from "i18next";
+import { Loader2 } from "lucide-react";
import { useState } from "react";
import CareIcon from "@/CAREUI/icons/CareIcon";
-import ButtonV2 from "@/components/Common/ButtonV2";
+import { Button, buttonVariants } from "@/components//ui/button";
import ConfirmDialog from "@/components/Common/ConfirmDialog";
import Page from "@/components/Common/Page";
import Tabs from "@/components/Common/Tabs";
@@ -126,7 +127,7 @@ export default function PatientConsentRecords(props: {
setShowPCSChangeModal(null);
}}
action="Change Patient Code Status"
- variant="danger"
+ variant="destructive"
description={`Consent records exist with the "${CONSENT_PATIENT_CODE_STATUS_CHOICES.find((c) => consentRecords?.find((c) => c.type === 2 && !c.archived)?.patient_code_status === c.id)?.text}" patient code status. Adding a new record for a different type will archive the existing records. Are you sure you want to proceed?`}
title="Archive Previous Records"
className="w-auto"
@@ -177,7 +178,8 @@ export default function PatientConsentRecords(props: {
{fileUpload.files[0] ? (
<>
-
{
const diffPCS = consentRecords?.find(
(record) =>
@@ -193,31 +195,33 @@ export default function PatientConsentRecords(props: {
handleUpload();
}
}}
- loading={fileUpload.uploading}
disabled={
- newConsent.type === 2 &&
- newConsent.patient_code_status === 0
+ fileUpload.uploading ||
+ (newConsent.type === 2 &&
+ newConsent.patient_code_status === 0)
}
- className="flex-1"
+ className={`flex-1 ${fileUpload.uploading ? "opacity-50" : ""}`}
>
-
- Upload
-
-
+ ) : (
+
+ )}
+ {t("upload")}
+
+
>
) : (
<>
diff --git a/src/components/Patient/PatientIndex.tsx b/src/components/Patient/PatientIndex.tsx
index afdd9d1e92b..64b3480f925 100644
--- a/src/components/Patient/PatientIndex.tsx
+++ b/src/components/Patient/PatientIndex.tsx
@@ -156,7 +156,7 @@ export default function PatientIndex({ facilityId }: { facilityId: string }) {
return (
-
+
diff --git a/src/components/Resource/ResourceCommentSection.tsx b/src/components/Resource/ResourceCommentSection.tsx
index 8b80bd6a27a..777284b7c7f 100644
--- a/src/components/Resource/ResourceCommentSection.tsx
+++ b/src/components/Resource/ResourceCommentSection.tsx
@@ -2,7 +2,8 @@ import { useState } from "react";
import PaginatedList from "@/CAREUI/misc/PaginatedList";
-import ButtonV2 from "@/components/Common/ButtonV2";
+import { Button } from "@/components/ui/button";
+
import CircularProgress from "@/components/Common/CircularProgress";
import TextAreaFormField from "@/components/Form/FormFields/TextAreaFormField";
@@ -51,14 +52,15 @@ const CommentSection = (props: { id: string }) => {
/>
- {
await onSubmitComment();
query.refetch();
}}
>
Post Your Comment
-
+
diff --git a/src/components/Resource/ResourceCreate.tsx b/src/components/Resource/ResourceCreate.tsx
index d8c7e25ea97..e0f199af7ad 100644
--- a/src/components/Resource/ResourceCreate.tsx
+++ b/src/components/Resource/ResourceCreate.tsx
@@ -6,7 +6,8 @@ import { useTranslation } from "react-i18next";
import Card from "@/CAREUI/display/Card";
import CareIcon from "@/CAREUI/icons/CareIcon";
-import { Cancel, Submit } from "@/components/Common/ButtonV2";
+import { Button } from "@/components/ui/button";
+
import { FacilitySelect } from "@/components/Common/FacilitySelect";
import Loading from "@/components/Common/Loading";
import Page from "@/components/Common/Page";
@@ -316,8 +317,12 @@ export default function ResourceCreate(props: resourceProps) {
/>
- goBack()} />
-
+ goBack()}>
+ {t("cancel")}
+
+
+ {t("submit")}
+
diff --git a/src/components/Resource/ResourceDetailsUpdate.tsx b/src/components/Resource/ResourceDetailsUpdate.tsx
index e78f002e8a0..edeb252d7e0 100644
--- a/src/components/Resource/ResourceDetailsUpdate.tsx
+++ b/src/components/Resource/ResourceDetailsUpdate.tsx
@@ -1,9 +1,11 @@
+import { t } from "i18next";
import { navigate, useQueryParams } from "raviger";
import { useReducer, useState } from "react";
import Card from "@/CAREUI/display/Card";
-import { Cancel, Submit } from "@/components/Common/ButtonV2";
+import { Button } from "@/components/ui/button";
+
import CircularProgress from "@/components/Common/CircularProgress";
import { FacilitySelect } from "@/components/Common/FacilitySelect";
import Loading from "@/components/Common/Loading";
@@ -280,8 +282,12 @@ export const ResourceDetailsUpdate = (props: resourceProps) => {
- goBack()} />
-
+ goBack()}>
+ {t("cancel")}
+
+
+ {t("submit")}
+
diff --git a/src/components/Resource/ResourceList.tsx b/src/components/Resource/ResourceList.tsx
index f2f663184c8..bdcf0929701 100644
--- a/src/components/Resource/ResourceList.tsx
+++ b/src/components/Resource/ResourceList.tsx
@@ -1,10 +1,10 @@
import { Link, navigate } from "raviger";
import { useTranslation } from "react-i18next";
-import Chip from "@/CAREUI/display/Chip";
import CareIcon from "@/CAREUI/icons/CareIcon";
import { AdvancedFilterButton } from "@/CAREUI/interactive/FiltersSlideover";
+import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { ExportButton } from "@/components/Common/Export";
@@ -90,34 +90,38 @@ export default function ListView() {
{resource.status === "TRANSPORTATION TO BE ARRANGED" ? (
-
+ >
+
+
+
+ {t(`${resource.status}`)}
+
) : (
-
+ >
+
+
+
+ {t(`${resource.status}`)}
+
)}
diff --git a/src/components/Users/ConfirmFacilityModal.tsx b/src/components/Users/ConfirmFacilityModal.tsx
index 289e576aa54..851f685fbb9 100644
--- a/src/components/Users/ConfirmFacilityModal.tsx
+++ b/src/components/Users/ConfirmFacilityModal.tsx
@@ -69,7 +69,7 @@ const ConfirmFacilityModal = ({
action={action}
onClose={handleCancel}
onConfirm={handleOk}
- variant="danger"
+ variant="destructive"
>
{body}
diff --git a/src/components/Users/UnlinkFacilityDialog.tsx b/src/components/Users/UnlinkFacilityDialog.tsx
index ff729150fbf..f0ba9c65704 100644
--- a/src/components/Users/UnlinkFacilityDialog.tsx
+++ b/src/components/Users/UnlinkFacilityDialog.tsx
@@ -32,7 +32,7 @@ const UnlinkFacilityDialog = (props: ConfirmDialogProps) => {
onClose={handleCancel}
onConfirm={handleSubmit}
disabled={disable}
- variant="danger"
+ variant="destructive"
>
diff --git a/src/components/Users/UserAvatar.tsx b/src/components/Users/UserAvatar.tsx
index 74bd0789d35..e6493e526ca 100644
--- a/src/components/Users/UserAvatar.tsx
+++ b/src/components/Users/UserAvatar.tsx
@@ -2,9 +2,11 @@ import careConfig from "@careConfig";
import { useState } from "react";
import { useTranslation } from "react-i18next";
+import { Button } from "@/components/ui/button";
+import { TooltipComponent } from "@/components/ui/tooltip";
+
import { Avatar } from "@/components/Common/Avatar";
import AvatarEditModal from "@/components/Common/AvatarEditModal";
-import ButtonV2 from "@/components/Common/ButtonV2";
import Loading from "@/components/Common/Loading";
import useAuthUser from "@/hooks/useAuthUser";
@@ -99,21 +101,32 @@ export default function UserAvatar({
className="h-20 w-20"
/>
-
setEditAvatar(!editAvatar)}
- type="button"
- id="change-avatar"
- className="border border-gray-200 bg-gray-50 text-black hover:bg-gray-100"
- shadow={false}
- disabled={!showAvatarEdit(authUser, userData)}
- tooltip={
- !showAvatarEdit(authUser, userData)
- ? t("edit_avatar_permission_error")
- : undefined
- }
- >
- {t("change_avatar")}
-
+ {!showAvatarEdit(authUser, userData) ? (
+
+ setEditAvatar(!editAvatar)}
+ type="button"
+ id="change-avatar"
+ disabled
+ >
+ {t("change_avatar")}
+
+
+ ) : (
+
setEditAvatar(!editAvatar)}
+ type="button"
+ id="change-avatar"
+ >
+ {t("change_avatar")}
+
+ )}
+
{t("change_avatar_note")}
diff --git a/src/components/Users/UserDeleteDialog.tsx b/src/components/Users/UserDeleteDialog.tsx
index 665b2ef0b4a..5a2becefe3d 100644
--- a/src/components/Users/UserDeleteDialog.tsx
+++ b/src/components/Users/UserDeleteDialog.tsx
@@ -16,7 +16,7 @@ const UserDeleteDialog = (props: ConfirmDialogProps) => {
}
action="Delete"
- variant="danger"
+ variant="destructive"
show
onConfirm={props.handleOk}
onClose={props.handleCancel}
diff --git a/src/components/Users/UserResetPassword.tsx b/src/components/Users/UserResetPassword.tsx
index 5807ecd129b..2ceae7314ae 100644
--- a/src/components/Users/UserResetPassword.tsx
+++ b/src/components/Users/UserResetPassword.tsx
@@ -3,6 +3,8 @@ import { useTranslation } from "react-i18next";
import CareIcon from "@/CAREUI/icons/CareIcon";
+import { Button } from "@/components/ui/button";
+
import Form from "@/components/Form/Form";
import TextFormField from "@/components/Form/FormFields/TextFormField";
import { validateRule } from "@/components/Users/UserFormValidations";
@@ -13,8 +15,6 @@ import routes from "@/Utils/request/api";
import request from "@/Utils/request/request";
import { UserBase } from "@/types/user/user";
-import ButtonV2 from "../Common/ButtonV2";
-
interface PasswordForm {
username: string;
old_password: string;
@@ -192,16 +192,18 @@ export default function UserResetPassword({
const editButton = () => (
- setIsEditing(!isEditing)}
type="button"
id="change-edit-password-button"
- className="flex items-center gap-2 rounded-sm border border-gray-100 bg-white px-3 py-1.5 text-sm text-[#009D48] shadow-sm hover:bg-gray-50"
- shadow={false}
>
-
+
{isEditing ? t("cancel") : t("change_password")}
-
+
);
diff --git a/src/components/Users/UserSummary.tsx b/src/components/Users/UserSummary.tsx
index 870c5f19739..397396abc8e 100644
--- a/src/components/Users/UserSummary.tsx
+++ b/src/components/Users/UserSummary.tsx
@@ -3,8 +3,8 @@ import { useState } from "react";
import { useTranslation } from "react-i18next";
import CareIcon from "@/CAREUI/icons/CareIcon";
+import AuthorizedChild from "@/CAREUI/misc/AuthorizedChild";
-import ButtonV2 from "@/components/Common/ButtonV2";
import LanguageSelector from "@/components/Common/LanguageSelector";
import UserColumns from "@/components/Common/UserColumns";
import UserAvatar from "@/components/Users/UserAvatar";
@@ -29,6 +29,8 @@ import routes from "@/Utils/request/api";
import request from "@/Utils/request/request";
import { UserBase } from "@/types/user/user";
+import { Button } from "../ui/button";
+
export default function UserSummaryTab({
userData,
refetchUserData,
@@ -172,17 +174,20 @@ export default function UserSummaryTab({
-
deletePermitted}
- onClick={() => setshowDeleteDialog(true)}
- variant="danger"
- data-testid="user-delete-button"
- className="my-1 inline-flex"
- disabled={isDeleting}
- >
-
- {t("delete_account_btn")}
-
+
deletePermitted}>
+ {({ isAuthorized }) => (
+ setshowDeleteDialog(true)}
+ variant="destructive"
+ data-testid="user-delete-button"
+ className="my-1 inline-flex"
+ disabled={isDeleting || !isAuthorized}
+ >
+
+ {t("delete_account_btn")}
+
+ )}
+
)}
diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx
index 60973469121..b794b6a99fb 100644
--- a/src/components/ui/button.tsx
+++ b/src/components/ui/button.tsx
@@ -28,6 +28,10 @@ const buttonVariants = cva(
"text-white border border-primary-900 rounded-lg font-medium relative overflow-hidden bg-gradient-to-b from-primary-700 to-primary-800 hover:from-primary-800 hover:to-primary-900 shadow-lg",
white:
"bg-white border border-secondary-400 text-gray-900 shadow-sm hover:bg-gray-100 hover:text-gray-900 dark:bg-gray-800 dark:text-gray-50 dark:hover:bg-gray-800/80",
+ warning:
+ "bg-warning-100 text-warning-900 border border-warning-300 shadow-sm hover:bg-warning-100/80 dark:bg-warning-900 dark:text-warning-50 dark:hover:bg-warning-900/80",
+ alert:
+ "bg-alert-100 text-alert-900 border border-alert-300 shadow-sm hover:bg-alert-100/80 dark:bg-alert-900 dark:text-alert-50 dark:hover:bg-alert-900/80",
},
size: {
default: "h-9 px-4 py-2",
@@ -44,6 +48,19 @@ const buttonVariants = cva(
},
);
+export type ButtonVariant =
+ | "primary"
+ | "outline"
+ | "secondary"
+ | "destructive"
+ | "primary_gradient"
+ | "ghost"
+ | "link"
+ | "white"
+ | "alert"
+ | "warning"
+ | "outline_primary";
+
export interface ButtonProps
extends React.ButtonHTMLAttributes
,
VariantProps {
diff --git a/src/hooks/useFileManager.tsx b/src/hooks/useFileManager.tsx
index b1efeaf5082..3c1660e3674 100644
--- a/src/hooks/useFileManager.tsx
+++ b/src/hooks/useFileManager.tsx
@@ -1,9 +1,11 @@
import { useMutation, useQueryClient } from "@tanstack/react-query";
+import { t } from "i18next";
import { useState } from "react";
import CareIcon from "@/CAREUI/icons/CareIcon";
-import { Cancel, Submit } from "@/components/Common/ButtonV2";
+import { Button } from "@/components/ui/button";
+
import DialogModal from "@/components/Common/Dialog";
import FilePreviewDialog from "@/components/Common/FilePreviewDialog";
import { StateInterface } from "@/components/Files/FileUpload";
@@ -306,8 +308,16 @@ export default function useFileManager(
/>
- setArchiveDialogueOpen(null)} />
-
+ setArchiveDialogueOpen(null)}
+ >
+ {t("cancel")}
+
+
+ {t("proceed")}
+
@@ -384,7 +394,13 @@ export default function useFileManager(
))}
- setArchiveDialogueOpen(null)} />
+ setArchiveDialogueOpen(null)}
+ >
+ {t("cancel")}
+
- setEditDialogueOpen(null)} />
- setEditDialogueOpen(null)}
+ >
+ {t("cancel")}
+
+
+ >
+ {t("proceed")}
+
diff --git a/src/pages/Encounters/tabs/EncounterFeedTab.tsx b/src/pages/Encounters/tabs/EncounterFeedTab.tsx
index 5f5a75ee210..648ab9159fe 100644
--- a/src/pages/Encounters/tabs/EncounterFeedTab.tsx
+++ b/src/pages/Encounters/tabs/EncounterFeedTab.tsx
@@ -14,7 +14,6 @@
// import useOperateCamera, {
// PTZPayload,
// } from "@/components/CameraFeed/useOperateCamera";
-// import ButtonV2 from "@/components/Common/ButtonV2";
// import ConfirmDialog from "@/components/Common/ConfirmDialog";
// import Loading from "@/components/Common/Loading";
// import { ConsultationTabProps } from "@/components/Facility/ConsultationDetails/index";
@@ -226,7 +225,7 @@
// className="animate-spin text-base text-zinc-300 md:mx-2"
// />
// ) : (
-//
setShowPresetSaveConfirmation(true)}
// >
//
-//
+//
// )}
// >
// ) : (
diff --git a/src/pages/FacilityOrganization/FacilityOrganizationIndex.tsx b/src/pages/FacilityOrganization/FacilityOrganizationIndex.tsx
index 38baf3787d1..9efa21e64ae 100644
--- a/src/pages/FacilityOrganization/FacilityOrganizationIndex.tsx
+++ b/src/pages/FacilityOrganization/FacilityOrganizationIndex.tsx
@@ -62,7 +62,7 @@ export default function FacilityOrganizationIndex({
if (!data?.results?.length) {
return (
-
+
@@ -90,7 +90,7 @@ export default function FacilityOrganizationIndex({
return (
-
+
diff --git a/src/pages/FacilityOrganization/components/CreateFacilityOrganizationSheet.tsx b/src/pages/FacilityOrganization/components/CreateFacilityOrganizationSheet.tsx
index 4e45160b495..6350a613622 100644
--- a/src/pages/FacilityOrganization/components/CreateFacilityOrganizationSheet.tsx
+++ b/src/pages/FacilityOrganization/components/CreateFacilityOrganizationSheet.tsx
@@ -93,7 +93,7 @@ export default function CreateFacilityOrganizationSheet({
return (
-
+
Create Organization
diff --git a/src/style/CAREUI.css b/src/style/CAREUI.css
index e65c2c5554e..893d16c2e4e 100644
--- a/src/style/CAREUI.css
+++ b/src/style/CAREUI.css
@@ -99,69 +99,12 @@
@apply h-full md:h-[300px] w-full
}
-.button-primary-default { @apply accent-primary-500 bg-primary-500 hover:bg-primary-400 text-white !important }
-.button-primary-ghost { @apply accent-primary-500 hover:bg-primary-100 text-primary-500 !important }
-.button-primary-border { @apply border border-primary-500 }
-
-.button-secondary-default { @apply accent-secondary-200 bg-white hover:bg-secondary-200 text-secondary-800 !important }
-.button-secondary-ghost { @apply accent-secondary-300 hover:bg-secondary-400 text-secondary-700 !important }
-.button-secondary-border { @apply border border-secondary-300 }
-
-.button-danger-default { @apply accent-danger-500 bg-danger-500 hover:bg-danger-400 text-white !important }
-.button-danger-ghost { @apply accent-danger-500 hover:bg-danger-100 text-danger-500 !important }
-.button-danger-border { @apply border border-danger-500 }
-
-.button-warning-default { @apply accent-warning-500 bg-warning-500 hover:bg-warning-400 text-white !important }
-.button-warning-ghost { @apply accent-warning-500 hover:bg-warning-100 text-warning-500 !important }
-.button-warning-border { @apply border border-warning-500 }
-
-.button-alert-default { @apply accent-alert-600 bg-alert-600 hover:bg-alert-500 text-white !important }
-.button-alert-ghost { @apply accent-alert-600 hover:bg-alert-100 text-alert-600 !important }
-.button-alert-border { @apply border border-alert-600 }
-
-.button-shape-square { @apply rounded }
-.button-shape-circle { @apply rounded-full }
-
-.button-size-small { @apply px-2 py-1 text-xs }
-.button-size-default { @apply py-2 px-4 text-sm }
-.button-size-large { @apply py-3 px-5 text-base }
-
.dropdown-item-primary { @apply accent-primary-500 hover:bg-primary-100 text-black hover:text-primary-500 }
.dropdown-item-secondary { @apply accent-secondary-200 hover:bg-secondary-200 text-secondary-700 }
.dropdown-item-danger { @apply accent-danger-500 hover:bg-danger-100 text-danger-500 }
.dropdown-item-warning { @apply accent-warning-500 hover:bg-warning-100 text-warning-500 }
.dropdown-item-alert { @apply accent-alert-600 hover:bg-alert-100 text-alert-600 }
-a.button-primary-default { @apply hover:bg-primary-400 }
-a.button-primary-ghost { @apply hover:bg-primary-100 }
-
-a.button-secondary-default { @apply hover:bg-secondary-200 }
-a.button-secondary-ghost { @apply hover:bg-secondary-100 }
-
-a.button-danger-default { @apply hover:bg-danger-400 }
-a.button-danger-ghost { @apply hover:bg-danger-100 }
-
-a.button-warning-default { @apply hover:bg-warning-400 }
-a.button-warning-ghost { @apply hover:bg-warning-100 }
-
-a.button-alert-default { @apply hover:bg-alert-500 }
-a.button-alert-ghost { @apply hover:bg-alert-100 }
-
-button.button-primary-default { @apply enabled:hover:bg-primary-400 }
-button.button-primary-ghost { @apply enabled:hover:bg-primary-100 }
-
-button.button-secondary-default { @apply enabled:hover:bg-secondary-200 }
-button.button-secondary-ghost { @apply enabled:hover:bg-secondary-100 }
-
-button.button-danger-default { @apply enabled:hover:bg-danger-400 }
-button.button-danger-ghost { @apply enabled:hover:bg-danger-100 }
-
-button.button-warning-default { @apply enabled:hover:bg-warning-400 }
-button.button-warning-ghost { @apply enabled:hover:bg-warning-100 }
-
-button.button-alert-default { @apply enabled:hover:bg-alert-500 }
-button.button-alert-ghost { @apply enabled:hover:bg-alert-100 }
-
.cui-form-button-group {
@apply flex flex-col-reverse md:flex-row md:justify-end gap-2 w-full md:w-auto
}