From fd740a99c33e53eaf0a70e375c072e8f767d9927 Mon Sep 17 00:00:00 2001 From: pahmiudahgede Date: Wed, 9 Jul 2025 07:33:19 +0700 Subject: [PATCH] feat: logout session --- app/components/layoutpengelola/header.tsx | 391 +++++------ app/routes/_landing.tsx | 135 +++- app/routes/action.logout.ts | 26 + ...gelola.completingcompanyprofile._index.tsx | 621 ++++++++++-------- .../authpengelola.createanewpin._index.tsx | 573 ++++++++-------- ...pengelola.requestotpforregister._index.tsx | 174 +++-- ...thpengelola.verifyotptoregister._index.tsx | 151 +++-- ...aitingapprovalfromadministrator._index.tsx | 573 +++++++++------- 8 files changed, 1521 insertions(+), 1123 deletions(-) create mode 100644 app/routes/action.logout.ts diff --git a/app/components/layoutpengelola/header.tsx b/app/components/layoutpengelola/header.tsx index 08eaede..31447b0 100644 --- a/app/components/layoutpengelola/header.tsx +++ b/app/components/layoutpengelola/header.tsx @@ -1,5 +1,5 @@ import { useState } from "react"; -import { Form } from "@remix-run/react"; +import { Form, useNavigation } from "@remix-run/react"; import { Avatar, AvatarFallback, AvatarImage } from "~/components/ui/avatar"; import { Button } from "~/components/ui/button"; import { Input } from "~/components/ui/input"; @@ -13,6 +13,16 @@ import { DropdownMenuTrigger } from "~/components/ui/dropdown-menu"; import { Sheet, SheetContent, SheetTrigger } from "~/components/ui/sheet"; +import { + AlertDialog, + AlertDialogAction, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogTitle +} from "~/components/ui/alert-dialog"; import { Menu, Search, @@ -25,7 +35,8 @@ import { ChevronDown, MoreHorizontal, PanelLeftClose, - PanelLeft + PanelLeft, + Loader2 } from "lucide-react"; import { SessionData } from "~/sessions.server"; // Import SessionData type @@ -42,7 +53,9 @@ export function PengelolaHeader({ isMobile, user // Add user prop }: PengelolaHeaderProps) { - // const [isDark, setIsDark] = useState(false); + const [showLogoutDialog, setShowLogoutDialog] = useState(false); + const navigation = useNavigation(); + const isLoggingOut = navigation.formAction === "/action/logout"; // Get user initials for avatar fallback const getUserInitials = (name: string) => { @@ -55,204 +68,214 @@ export function PengelolaHeader({ }; return ( -
-
- {/* Mobile header */} -
- {/* Hamburger menu button */} - + <> +
+
+ {/* Mobile header */} +
+ {/* Hamburger menu button */} + - {/* Mobile logo */} -
-
- LOGO -
-
- - {/* Mobile more menu */} - - - - - -
- - -
-
-
- - {/* Desktop search - Commented out for now */} - {/*
-
- - -
- - ⌘K - + {/* Mobile logo */} +
+
+ LOGO
-
*/} -
- {/* Desktop header actions */} -
-
- {/* Theme toggle */} - - - {/* Notifications */} - - - - - -
-

+ + +
+

-
-
-

- New user registered -

-

- 2 minutes ago -

-
-
-

- System update available -

-

- 1 hour ago -

-
-
-

- New message received -

-

- 3 hours ago -

-
-
- +
-
-
+ + +
- {/* User menu */} - - - + + -
- - - - {getUserInitials("User")} - - -
-
- {user.sessionId || "User"} +
+

+ Notifications + + 3 new + +

+
+
+

+ New user registered +

+

+ 2 minutes ago +

-
- {user.role || "Pengelola"} +
+

+ System update available +

+

+ 1 hour ago +

+
+
+

+ New message received +

+

+ 3 hours ago +

- +
- - - -
-
{user.phone || "User"}
-
- {user.email || "user@example.com"} + + + + {/* User menu */} + + + + + +
+
{user.phone || "User"}
+
+ {user.email || "user@example.com"} +
-
- - - - Profile - - - - Settings - - - -
- -
-
- - + + + + Profile + + + + Settings + + + setShowLogoutDialog(true)} + > + + Sign out + + + +
-
-
+
+ + {/* Logout Confirmation Dialog */} + + + + Konfirmasi Logout + + Apakah Anda yakin ingin keluar dari akun? Anda perlu login kembali + untuk mengakses dashboard. + + + + Batal +
+ + {isLoggingOut ? ( + <> + + Logging out... + + ) : ( + "Ya, Logout" + )} + +
+
+
+
+ ); } diff --git a/app/routes/_landing.tsx b/app/routes/_landing.tsx index ef08956..b9a3732 100644 --- a/app/routes/_landing.tsx +++ b/app/routes/_landing.tsx @@ -12,9 +12,12 @@ import { Linkedin, Instagram, Recycle, - ArrowUp + ArrowUp, + ArrowRight, + User } from "lucide-react"; import { ModeToggle } from "~/components/ui/dark-mode-toggle"; +import { getUserSession } from "~/sessions.server"; export const meta: MetaFunction = () => { return [ @@ -44,10 +47,15 @@ export async function loader({ request }: LoaderFunctionArgs) { { name: "Instagram", icon: "instagram", href: "#" } ]; + // Get real user session + const userSession = await getUserSession(request); + const authData = { - isAuthenticated: false, - isRegistrationComplete: false, - userRole: null as string | null + isAuthenticated: !!userSession, + isRegistrationComplete: userSession?.registrationStatus === "complete", + userRole: userSession?.role || null, + userPhone: userSession?.phone || null, + userEmail: userSession?.email || null }; return json({ @@ -65,7 +73,13 @@ export default function LandingLayout() { const [isScrolled, setIsScrolled] = useState(false); const [showBackToTop, setShowBackToTop] = useState(false); - const { isAuthenticated, isRegistrationComplete, userRole } = authData; + const { + isAuthenticated, + isRegistrationComplete, + userRole, + userPhone, + userEmail + } = authData; useEffect(() => { const handleScroll = () => { @@ -100,39 +114,58 @@ export default function LandingLayout() { } }; - const getRedirectPath = () => { + const getDashboardPath = () => { if (userRole === "administrator") { return "/sys-rijig-adminpanel/dashboard"; } return "/pengelola/dashboard"; }; - const handleGetStarted = () => { + const handleMainAction = () => { if (isAuthenticated && isRegistrationComplete) { - const dashboardPath = - userRole === "administrator" - ? "/sys-rijig-adminpanel/dashboard" - : "/pengelola/dashboard"; - navigate(dashboardPath); + // User sudah login dan registrasi complete → Go to Dashboard + navigate(getDashboardPath()); } else if (isAuthenticated && !isRegistrationComplete) { - const redirectPath = getRedirectPath(); - navigate(redirectPath); + // User sudah login tapi registrasi belum complete → Redirect ke step berikutnya + navigate(getDashboardPath()); } else { - navigate("/pengelola/register"); + // User belum login → Get Started (redirect ke authpengelola) + navigate("/authpengelola"); } }; - const handleAdminLogin = () => { - navigate("/sys-rijig-adminpanel/login"); - }; - const getButtonText = () => { if (isAuthenticated && isRegistrationComplete) { return "Go to Dashboard"; + } else if (isAuthenticated && !isRegistrationComplete) { + return "Continue Setup"; } return "Get Started"; }; + const getButtonIcon = () => { + if (isAuthenticated) { + return ; + } + return ; + }; + + // Format phone display + const formatPhone = (phone: string) => { + if (phone.length <= 2) return phone; + if (phone.length <= 5) + return `${phone.substring(0, 2)} ${phone.substring(2)}`; + if (phone.length <= 9) + return `${phone.substring(0, 2)} ${phone.substring( + 2, + 5 + )} ${phone.substring(5)}`; + return `${phone.substring(0, 2)} ${phone.substring(2, 5)} ${phone.substring( + 5, + 9 + )} ${phone.substring(9)}`; + }; + return (
{/* Header dengan glassmorphism effect */} @@ -213,6 +246,26 @@ export default function LandingLayout() { {/* Right Side Actions */}
+ {/* User Info (if authenticated) */} + {isAuthenticated && ( +
+
+
+ {userRole === "administrator" ? "Admin" : "Pengelola"} +
+
+ {userPhone ? formatPhone(userPhone) : userEmail} +
+
+
+ )} +
+
@@ -251,6 +306,35 @@ export default function LandingLayout() { }`} > @@ -361,14 +446,6 @@ export default function LandingLayout() { > -