Skip to content

Commit

Permalink
Merge branch 'develop' into issue/9683/userResetPassword_form_switch
Browse files Browse the repository at this point in the history
  • Loading branch information
AdityaJ2305 authored Jan 6, 2025
2 parents 6a21bca + 9a839bd commit 013faa8
Show file tree
Hide file tree
Showing 26 changed files with 395 additions and 822 deletions.
6 changes: 5 additions & 1 deletion public/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,7 @@
"cylinders": "Cylinders",
"cylinders_per_day": "Cylinders/day",
"daily_rounds": "Daily Rounds",
"dashboard": "Dashboard",
"date": "Date",
"date_and_time": "Date and Time",
"date_declared_positive": "Date of declaring positive",
Expand Down Expand Up @@ -1145,6 +1146,7 @@
"log_report": "Log Report",
"log_update": "Log Update",
"log_updates": "Log Updates",
"logged_in_as": "Logged in as",
"login": "Login",
"logout": "Log Out",
"longitude_invalid": "Longitude must be between -180 and 180",
Expand Down Expand Up @@ -1370,6 +1372,7 @@
"patient_consultation__treatment__summary__spo2": "SpO2",
"patient_consultation__treatment__summary__temperature": "Temperature",
"patient_created": "Patient Created",
"patient_dashboard": "Patient Dashboard",
"patient_details": "Patient Details",
"patient_details_incomplete": "Patient Details Incomplete",
"patient_face": "Patient Face",
Expand Down Expand Up @@ -1687,7 +1690,8 @@
"show_default_presets": "Show Default Presets",
"show_patient_presets": "Show Patient Presets",
"show_unread_notifications": "Show Unread",
"sign_out": "Sign Out",
"sign_in": "Sign in",
"sign_out": "Sign out",
"skill_add_error": "Error while adding skill",
"skill_added_successfully": "Skill added successfully",
"skills": "Skills",
Expand Down
2 changes: 1 addition & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const App = () => {
<PluginEngine>
<HistoryAPIProvider>
<AuthUserProvider
unauthorized={<Routers.SessionRouter />}
unauthorized={<Routers.PublicRouter />}
otpAuthorized={<Routers.PatientRouter />}
>
<FeatureFlagsProvider>
Expand Down
15 changes: 13 additions & 2 deletions src/Providers/AuthUserProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export default function AuthUserProvider({
queryKey: ["currentUser"],
queryFn: query(routes.currentUser, { silent: true }),
retry: false,
enabled: !!localStorage.getItem(LocalStorageKeys.accessToken),
});

const [isOTPAuthorized, setIsOTPAuthorized] = useState(false);
Expand Down Expand Up @@ -70,7 +71,7 @@ export default function AuthUserProvider({
localStorage.setItem(LocalStorageKeys.accessToken, query.data.access);
localStorage.setItem(LocalStorageKeys.refreshToken, query.data.refresh);

await queryClient.resetQueries({ queryKey: ["currentUser"] });
await queryClient.invalidateQueries({ queryKey: ["currentUser"] });

if (location.pathname === "/" || location.pathname === "/login") {
navigate(getRedirectOr("/"));
Expand Down Expand Up @@ -120,9 +121,19 @@ export default function AuthUserProvider({
return <Loading />;
}

const SelectedRouter = () => {
if (user) {
return children;
} else if (isOTPAuthorized) {
return otpAuthorized;
} else {
return unauthorized;
}
};

return (
<AuthUserContext.Provider value={{ signIn, signOut, user }}>
{!user ? (isOTPAuthorized ? otpAuthorized : unauthorized) : children}
<SelectedRouter />
</AuthUserContext.Provider>
);
}
Expand Down
4 changes: 2 additions & 2 deletions src/Routers/PatientRouter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { AppointmentSuccess } from "@/pages/Appoinments/Success";
import { FacilitiesPage } from "@/pages/Facility/FacilitiesPage";
import PatientIndex from "@/pages/Patient/index";

import SessionRouter from "./SessionRouter";
import PublicRouter from "./PublicRouter";

const PatientRoutes = {
"/nearby_facilities": () => <FacilitiesPage />,
Expand All @@ -39,7 +39,7 @@ export default function PatientRouter() {
const pages = useRoutes(PatientRoutes);

if (!pages) {
return <SessionRouter />;
return <PublicRouter />;
}

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,6 @@ export const routes = {
"/invalid-reset": () => <InvalidReset />,
};

export default function SessionRouter() {
export default function PublicRouter() {
return useRoutes(routes) || <Login />;
}
4 changes: 2 additions & 2 deletions src/Routers/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import AppRouter from "@/Routers/AppRouter";
import PatientRouter from "@/Routers/PatientRouter";
import SessionRouter from "@/Routers/SessionRouter";
import PublicRouter from "@/Routers/PublicRouter";

const routers = { PatientRouter, SessionRouter, AppRouter };
const routers = { PatientRouter, PublicRouter, AppRouter };

export default routers;
20 changes: 13 additions & 7 deletions src/components/Auth/Login.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import careConfig from "@careConfig";
import { useMutation } from "@tanstack/react-query";
import { Link } from "raviger";
import { Link, useQueryParams } from "raviger";
import { useEffect, useState } from "react";
import ReCaptcha from "react-google-recaptcha";
import { useTranslation } from "react-i18next";
Expand Down Expand Up @@ -46,6 +46,10 @@ interface LoginFormData {

type LoginMode = "staff" | "patient";

interface LoginProps {
forgot?: boolean;
}

interface OtpError {
type: string;
loc: string[];
Expand All @@ -63,7 +67,7 @@ interface OtpLoginData {
otp: string;
}

const Login = (props: { forgot?: boolean }) => {
const Login = (props: LoginProps) => {
const { signIn } = useAuthContext();
const { reCaptchaSiteKey, urls, stateLogo, customLogo, customLogoAlt } =
careConfig;
Expand All @@ -73,6 +77,8 @@ const Login = (props: { forgot?: boolean }) => {
password: "",
};
const { forgot } = props;
const [params] = useQueryParams();
const { mode } = params;
const initErr: any = {};
const [form, setForm] = useState(initForm);
const [errors, setErrors] = useState(initErr);
Expand All @@ -81,7 +87,9 @@ const Login = (props: { forgot?: boolean }) => {
// display spinner while login is under progress
const [loading, setLoading] = useState(false);
const [forgotPassword, setForgotPassword] = useState(forgot);
const [loginMode, setLoginMode] = useState<LoginMode>("staff");
const [loginMode, setLoginMode] = useState<LoginMode>(
mode === "patient" ? "patient" : "staff",
);
const [isOtpSent, setIsOtpSent] = useState(false);
const [phone, setPhone] = useState("");
const [otp, setOtp] = useState("");
Expand All @@ -96,6 +104,7 @@ const Login = (props: { forgot?: boolean }) => {
},
onSuccess: ({ res }) => {
setCaptcha(res?.status === 429);
window.location.href = "/";
},
});

Expand Down Expand Up @@ -153,10 +162,7 @@ const Login = (props: { forgot?: boolean }) => {
createdAt: new Date().toISOString(),
};
localStorage.setItem(CarePatientTokenKey, JSON.stringify(tokenData));
Notification.Success({ msg: t("verify_otp_success_login") });
setTimeout(() => {
window.location.href = "/patient/home";
}, 200);
window.location.href = "/patient/home";
}
},

Expand Down
7 changes: 7 additions & 0 deletions src/components/Common/Charts/ObservationChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ interface ObservationVisualizerProps {
codeGroups: CodeGroup[];
height?: number;
gridCols?: number;
encounterId: string;
}

interface ChartData {
Expand Down Expand Up @@ -98,6 +99,7 @@ const formatChartDate = (
export const ObservationVisualizer = ({
patientId,
codeGroups,
encounterId,
height = 300,
gridCols = 2,
}: ObservationVisualizerProps) => {
Expand All @@ -108,10 +110,14 @@ export const ObservationVisualizer = ({
queryKey: [
"observations",
patientId,
encounterId,
allCodes.map((c) => c.code).join(","),
],
queryFn: query(routes.observationsAnalyse, {
pathParams: { patientId },
queryParams: {
encounter: encounterId,
},
body: {
codes: allCodes,
},
Expand Down Expand Up @@ -380,6 +386,7 @@ export const ObservationVisualizer = ({
<TabsContent value="history">
<ObservationHistoryTable
patientId={patientId}
encounterId={encounterId}
codes={group.codes}
/>
</TabsContent>
Expand Down
3 changes: 3 additions & 0 deletions src/components/Common/Charts/ObservationHistoryTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ interface PaginatedResponse<T> {

interface ObservationHistoryTableProps {
patientId: string;
encounterId: string;
codes: Code[];
}

Expand All @@ -45,6 +46,7 @@ const formatDate = (dateString: string) => {

export const ObservationHistoryTable = ({
patientId,
encounterId,
codes,
}: ObservationHistoryTableProps) => {
const { ref, inView } = useInView();
Expand All @@ -57,6 +59,7 @@ export const ObservationHistoryTable = ({
const response = await query(routes.listObservations, {
pathParams: { patientId },
queryParams: {
encounter: encounterId,
limit: String(LIMIT),
codes: codes.map((c) => c.code).join(","),
offset: String(pageParam),
Expand Down
94 changes: 94 additions & 0 deletions src/components/Common/LoginHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import dayjs from "dayjs";
import { navigate } from "raviger";
import { useTranslation } from "react-i18next";

import CareIcon from "@/CAREUI/icons/CareIcon";

import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";

import { usePatientSignOut } from "@/hooks/usePatientSignOut";

import { LocalStorageKeys } from "@/common/constants";

import { TokenData } from "@/types/auth/otpToken";

export const LoginHeader = () => {
const { t } = useTranslation();
const signOut = usePatientSignOut();

const tokenData: TokenData = JSON.parse(
localStorage.getItem(LocalStorageKeys.patientTokenKey) || "{}",
);

const isLoggedIn =
tokenData.token &&
Object.keys(tokenData).length > 0 &&
dayjs(tokenData.createdAt).isAfter(dayjs().subtract(14, "minutes"));

if (isLoggedIn) {
const phoneNumber = tokenData.phoneNumber?.replace("+91", "") || "";
const initials = phoneNumber.slice(-2);

return (
<header className="w-full">
<div className="flex justify-end items-center gap-2">
<Button
variant="ghost"
className="text-sm font-medium hover:bg-gray-100 rounded-full px-6"
onClick={() => navigate("/patient/home")}
>
{t("dashboard")}
</Button>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
size="icon"
className="h-8 w-8 rounded-full p-0 hover:bg-gray-100 border-gray-400 border-2"
>
<Avatar className="h-8 w-8">
<AvatarFallback className="bg-primary-50 text-primary-600 text-xs">
{initials}
</AvatarFallback>
</Avatar>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem className="text-xs text-gray-500">
<span className="font-medium">{tokenData.phoneNumber}</span>
</DropdownMenuItem>
<DropdownMenuItem
className="text-red-600 focus:text-red-600 cursor-pointer"
onClick={signOut}
>
<CareIcon icon="l-signout" className="mr-2 h-4 w-4" />
{t("sign_out")}
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
</header>
);
}

return (
<header className="w-full">
<div className="flex justify-end items-center">
<Button
variant="ghost"
className="text-sm font-medium hover:bg-gray-100 rounded-full px-6"
onClick={() => navigate("/login?mode=patient")}
>
{t("sign_in")}
</Button>
</div>
</header>
);
};
6 changes: 3 additions & 3 deletions src/components/Encounter/CreateEncounterForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ export default function CreateEncounterForm({
},
});

const { mutate: createEncounter } = useMutation({
const { mutate: createEncounter, isPending } = useMutation({
mutationFn: mutate(routes.encounter.create),
onSuccess: (data: Encounter) => {
toast.success("Encounter created successfully");
Expand Down Expand Up @@ -318,8 +318,8 @@ export default function CreateEncounterForm({
}}
/>

<Button type="submit" className="w-full">
Create Encounter
<Button type="submit" className="w-full" disabled={isPending}>
{isPending ? "Creating..." : "Create Encounter"}
</Button>
</form>
</Form>
Expand Down
Loading

0 comments on commit 013faa8

Please sign in to comment.