Skip to content

Commit

Permalink
logout addedd
Browse files Browse the repository at this point in the history
  • Loading branch information
sinanptm committed Aug 31, 2024
1 parent 1298481 commit 7929d99
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 32 deletions.
9 changes: 5 additions & 4 deletions client/app/(patient)/signin/otp-verification/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import { Banners } from "@/constants";
import Link from "next/link";
import Image from "next/image";
import OtpVerificationSection from "@/components/forms/patient/OtpForms";
import { useQuery } from "@tanstack/react-query";
import { getPatientProfile } from "@/services/api/patientProtectedApis";
import UniversalSkelton from "@/components/skeletons/Universal";
import { useAuth } from "@/lib/hooks/useAuth";

Expand All @@ -18,7 +16,9 @@ const OtpVerificationPage = () => {
const { mutate: validateOtp, isPending } = useValidateOtpPatient();
const { toast } = useToast();
const navigate = useRouter();
const [isLoading,setLoading]= useState(true)
const [isLoading,setLoading]= useState(true);
const {setCredentials} = useAuth()


const {patientToken} = useAuth()

Expand All @@ -35,7 +35,7 @@ const OtpVerificationPage = () => {
validateOtp(
{ email: "[email protected]", otp: parseInt(otp) },
{
onSuccess: () => {
onSuccess: ({accessToken}) => {
toast({
title: "Otp Verification Success ✅",
description: "Authentication Completed!. let's book your first appointment",
Expand All @@ -47,6 +47,7 @@ const OtpVerificationPage = () => {
),
});
navigate.push("/");
setCredentials("patientToken",accessToken)
},
onError: (error) => {
toast({
Expand Down
70 changes: 55 additions & 15 deletions client/components/layout/NavBar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"use client";

import Link from "next/link";
import { Sheet, SheetTrigger, SheetContent, SheetTitle } from "@/components/ui/sheet";
import { Button } from "@/components/ui/button";
Expand All @@ -12,33 +13,60 @@ import {
DropdownMenuSeparator,
DropdownMenuItem,
} from "@/components/ui/dropdown-menu";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import Image from "next/image";
import { NavLinks } from "@/constants";
import { usePathname, useRouter } from "next/navigation";
import { useAuth } from "@/lib/hooks/useAuth";
import { useLogoutMutation } from "@/lib/hooks/usePatientAuth";
import { toast } from "../ui/use-toast";
import { useState } from "react";

export const NavBar = () => {
const path = usePathname();
const { patientToken,adminToken,doctorToken } = useAuth();
const {mutate:logout} = useLogoutMutation();
const { patientToken, adminToken, doctorToken, logout } = useAuth();
const { mutate: logoutFunc } = useLogoutMutation();
const route = useRouter();
const [isLogoutDialogOpen, setIsLogoutDialogOpen] = useState(false);

if (path.includes("signup") || path.includes("admin") || path.includes("signin")) {
return null;
}
const handleLogout = () => {
logout(null,{
onSuccess:({message})=>{

const handleLogoutClick = () => {
setIsLogoutDialogOpen(true);
};

const handleLogoutConfirm = () => {
logoutFunc(null, {
onSuccess: () => {
toast({
title: "Logout Successful",
description: "We hope to see you again soon!",
variant: "info",
});
localStorage.setItem("auth", JSON.stringify({ patientToken: "", adminToken, doctorToken }));
route.push("/");
},
onError: () => {
toast({
title:"Logout Successful",
description:"Sorry for our inconvenience"
title: "Logout Failed",
description: "An error occurred during logout. Please try again.",
variant: "destructive",
});
localStorage.setItem('auth',JSON.stringify({patientToken:"",adminToken,doctorToken}));
route.push('/');
}
})
logout("patientToken");
},
});
setIsLogoutDialogOpen(false);
};

return (
Expand Down Expand Up @@ -129,20 +157,32 @@ export const NavBar = () => {
<Link href={"/profile"}>My Account</Link>
</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem onClick={handleLogout}>
<Link href={"#"}>Logout</Link>
</DropdownMenuItem>
<DropdownMenuItem onSelect={handleLogoutClick}>Logout</DropdownMenuItem>
</>
) : (
<>
<DropdownMenuItem>
<Link href={"/signin"}>SingIn</Link>
<Link href={"/signin"}>Sign In</Link>
</DropdownMenuItem>
</>
)}
</DropdownMenuContent>
</DropdownMenu>
</div>
<AlertDialog open={isLogoutDialogOpen} onOpenChange={setIsLogoutDialogOpen}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Are you sure you want to log out?</AlertDialogTitle>
<AlertDialogDescription>
You will be redirected to the home page after logging out.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction onClick={handleLogoutConfirm}>Log out</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</header>
);
};
Expand Down
29 changes: 22 additions & 7 deletions client/components/ui/toast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ const ToastViewport = React.forwardRef<
ToastViewport.displayName = ToastPrimitives.Viewport.displayName

const toastVariants = cva(
"group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full",
"group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-lg border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full",
{
variants: {
variant: {
default: "border bg-[rgba(30,30,30,0.85)] text-foreground", // Adjust this to your desired color
destructive:
"destructive group border-destructive bg-[rgba(55,0,0,0.85)] text-destructive-foreground", // Adjust for destructive variant
default: "border-primary/10 bg-gradient-to-br from-primary/10 to-primary/5 backdrop-blur-sm text-foreground shadow-glow",
destructive: "destructive group border-destructive/10 bg-gradient-to-br from-destructive/10 to-destructive/5 backdrop-blur-sm text-destructive-foreground shadow-glow-destructive",
success: "border-green-500/10 bg-gradient-to-br from-green-500/10 to-green-500/5 backdrop-blur-sm text-green-700 dark:text-green-300 shadow-glow-success",
warning: "border-yellow-500/10 bg-gradient-to-br from-yellow-500/10 to-yellow-500/5 backdrop-blur-sm text-yellow-700 dark:text-yellow-300 shadow-glow-warning",
info: "border-blue-500/10 bg-gradient-to-br from-blue-500/10 to-blue-500/5 backdrop-blur-sm text-blue-700 dark:text-blue-300 shadow-glow-info",
},
},
defaultVariants: {
Expand All @@ -40,7 +42,6 @@ const toastVariants = cva(
}
)


const Toast = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Root>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> &
Expand Down Expand Up @@ -79,6 +80,7 @@ const ToastClose = React.forwardRef<
ref={ref}
className={cn(
"absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600",
"hover:bg-primary/10 hover:text-primary-foreground",
className
)}
toast-close=""
Expand All @@ -95,7 +97,7 @@ const ToastTitle = React.forwardRef<
>(({ className, ...props }, ref) => (
<ToastPrimitives.Title
ref={ref}
className={cn("text-sm font-semibold", className)}
className={cn("text-sm font-semibold leading-none tracking-tight", className)}
{...props}
/>
))
Expand All @@ -107,7 +109,7 @@ const ToastDescription = React.forwardRef<
>(({ className, ...props }, ref) => (
<ToastPrimitives.Description
ref={ref}
className={cn("text-sm opacity-90", className)}
className={cn("text-sm opacity-90 leading-relaxed", className)}
{...props}
/>
))
Expand All @@ -128,3 +130,16 @@ export {
ToastClose,
ToastAction,
}

export default function Component() {
return (
<ToastProvider>
<Toast>
<ToastTitle>Title</ToastTitle>
<ToastDescription>Description</ToastDescription>
<ToastClose />
</Toast>
<ToastViewport />
</ToastProvider>
)
}
35 changes: 29 additions & 6 deletions client/lib/hooks/useAuth.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

"use client";
import React, { createContext, useContext, useState, useEffect, ReactNode } from "react";

Expand All @@ -8,7 +7,12 @@ interface AuthState {
adminToken: string;
}

const persistedAuthState: AuthState =
interface AuthContextProps extends AuthState {
setCredentials: (tokenType: keyof AuthState, token: string) => void;
logout: (tokenType: keyof AuthState) => void;
}

const persistedAuthState: AuthState =
typeof window !== "undefined" ? JSON.parse(localStorage.getItem("auth") || "{}") : {};

const initialState: AuthState = {
Expand All @@ -17,29 +21,48 @@ const initialState: AuthState = {
adminToken: persistedAuthState.adminToken || "",
};

const AuthContext = createContext<AuthState | undefined>(undefined);
const AuthContext = createContext<AuthContextProps | undefined>(undefined);

export const AuthProvider = ({ children }: { children: ReactNode }) => {
const [authState, setAuthState] = useState<AuthState>(initialState);

useEffect(() => {
if (typeof window !== "undefined") {
const storedAuthState = JSON.parse(localStorage.getItem("auth") || "{}");
setAuthState(storedAuthState);
setAuthState((prevState) => ({
...prevState,
...storedAuthState,
}));
}
}, []);

const setCredentials = (tokenType: keyof AuthState, token: string) => {
const newAuthState = { ...authState, [tokenType]: token };
setAuthState(newAuthState);
if (typeof window !== "undefined") {
localStorage.setItem("auth", JSON.stringify(newAuthState));
}
};

const logout = (tokenType: keyof AuthState) => {
const newAuthState = { ...authState, [tokenType]: "" };
setAuthState(newAuthState);
if (typeof window !== "undefined") {
localStorage.setItem("auth", JSON.stringify(newAuthState));
}
};

return (
<AuthContext.Provider value={authState}>
<AuthContext.Provider value={{ ...authState, setCredentials, logout }}>
{children}
</AuthContext.Provider>
);
};

export const useAuth = () => {
const context = useContext(AuthContext);
if (!context) {
throw new Error("useAuth must be used within an AuthProvider");
}
return context;
};

1 comment on commit 7929d99

@vercel
Copy link

@vercel vercel bot commented on 7929d99 Aug 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.