Browse Source

feat(auth): implement LocalAlert component to notify users about session storage and update layout for better user experience
fix(auth): refactor logout functionality to use router for redirection and invalidate session queries after logout
chore(auth): remove unused imports and clean up layout code for improved readability

Mathias 1 month ago
parent
commit
312381915b

+ 0 - 9
app/[locale]/auth/(auth-layout)/layout.tsx

@@ -1,10 +1,7 @@
 import { redirect } from "next/navigation";
-import Link from "next/link";
-import Image from "next/image";
 import { headers } from "next/headers";
 
 import { getI18n } from "locales/server";
-import Logo from "@public/logo.png";
 import { paths } from "@/shared/constants/paths";
 import { auth } from "@/features/auth/lib/better-auth";
 import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
@@ -27,12 +24,6 @@ export default async function AuthLayout(props: LayoutParams<{}>) {
   return (
     <>
       <div>
-        <div className="flex justify-center gap-2">
-          <Link className="flex items-center gap-2 font-medium" href={`/${paths.root}`}>
-            <Image alt="workout cool logo" className="w-16" height={64} src={Logo} width={64} />
-          </Link>
-        </div>
-
         {searchParams.error && (
           <Alert className="mb-4" variant="error">
             <AlertTitle>{translatedError}</AlertTitle>

+ 4 - 1
app/[locale]/profile/page.tsx

@@ -6,6 +6,8 @@ import { useI18n } from "locales/client";
 import { useWorkoutSessionService } from "@/shared/lib/workout-session/use-workout-session.service";
 import { WorkoutSessionList } from "@/features/workout-session/ui/workout-session-list";
 import { WorkoutSessionHeatmap } from "@/features/workout-session/ui/workout-session-heatmap";
+import { useSession } from "@/features/auth/lib/auth-client";
+import { LocalAlert } from "@/components/ui/local-alert";
 import { Button } from "@/components/ui/button";
 
 import type { WorkoutSession } from "@/shared/lib/workout-session/types/workout-session";
@@ -15,7 +17,7 @@ export default function ProfilePage() {
   const t = useI18n();
   const [sessions, setSessions] = useState<WorkoutSession[]>([]);
   const { getAll } = useWorkoutSessionService();
-
+  const { data: session } = useSession();
   useEffect(() => {
     const loadSessions = async () => {
       const loadedSessions = await getAll();
@@ -36,6 +38,7 @@ export default function ProfilePage() {
 
   return (
     <div>
+      {!session && <LocalAlert />}
       <WorkoutSessionHeatmap until={until} values={values} />
       <WorkoutSessionList />
       <div className="mt-8 flex justify-center">

+ 29 - 0
src/components/ui/local-alert.tsx

@@ -0,0 +1,29 @@
+import React from "react";
+import Link from "next/link";
+
+import { cn } from "@/shared/lib/utils";
+import { paths } from "@/shared/constants/paths";
+import { Alert, AlertDescription } from "@/components/ui/alert";
+
+interface LocalAlertProps {
+  className?: string;
+}
+
+export const LocalAlert = ({ className }: LocalAlertProps) => {
+  return (
+    <Alert className={cn("bg-blue-100 border-0 text-black", className)} variant="info">
+      <AlertDescription className="flex flex-wrap items-center gap-1 italic text-base">
+        Your progress is stored in your browser.
+        <br className="sm:hidden" />
+        <Link className="ml-1 mr-1 font-medium text-blue-700 underline" href={paths.signUp}>
+          Create an account
+        </Link>
+        or
+        <Link className="ml-1 font-medium text-purple-700 underline" href={paths.signIn}>
+          Log-in
+        </Link>
+        to ensure it is not getting lost
+      </AlertDescription>
+    </Alert>
+  );
+};

+ 12 - 10
src/features/auth/model/useLogout.ts

@@ -1,19 +1,21 @@
 "use client";
 
-import { redirect } from "next/navigation";
-import { useMutation } from "@tanstack/react-query";
+import { useRouter } from "next/navigation";
+import { useMutation, useQueryClient } from "@tanstack/react-query";
 
+import { useI18n } from "locales/client";
 import { authClient } from "@/features/auth/lib/auth-client";
 
 export const useLogout = (redirectUrl: string = "/") => {
+  const t = useI18n();
+  const router = useRouter();
+  const queryClient = useQueryClient();
+
   return useMutation({
-    mutationFn: async () =>
-      await authClient.signOut({
-        fetchOptions: {
-          onSuccess: () => {
-            redirect(redirectUrl);
-          },
-        },
-      }),
+    mutationFn: async () => {
+      await authClient.signOut();
+      router.push(redirectUrl);
+      queryClient.invalidateQueries({ queryKey: ["session"] });
+    },
   });
 };

+ 2 - 2
src/features/layout/authenticated-header.tsx

@@ -101,7 +101,7 @@ export const AuthenticatedHeader = () => {
   const user = useCurrentUser();
   const { data: sessionData, isPending: isSessionLoading } = useSession();
   const { toggleSidebar } = useSidebarToggle();
-  const logout = useLogout();
+  const logout = useLogout(paths.root);
   const [mounted, setMounted] = useState(false);
 
   useEffect(() => {
@@ -212,7 +212,7 @@ export const AuthenticatedHeader = () => {
                 <DropdownMenuItem className="p-0">
                   <Button
                     className={`flex items-center gap-1.5 rounded-lg px-3 py-2 ${pathName === "/login" && "!bg-gray-400 !text-black dark:!bg-white/5 dark:!text-white"}`}
-                    onClick={() => logout.mutateAsync()}
+                    onClick={() => logout.mutate()}
                     variant={null}
                   >
                     <LogOut className="size-[18px] shrink-0" />