refactor(ui): fix layout issues and temporarily disable auth features

- app & navbar: comment out login, register, and logout features.
- scan-page: align info cards vertically and reduce upload area padding.
- mobile-nav: implement React Portal to fix overlapping menu issue.
This commit is contained in:
seriouselly
2026-06-06 03:01:07 +07:00
parent 9f9098b91b
commit 450b2f9d97
4 changed files with 71 additions and 70 deletions
+8 -10
View File
@@ -5,7 +5,7 @@ import {
Navigate,
} from "react-router-dom";
import { AuthInitializer } from "@/components/auth-initializer";
import { AuthGuard } from "@/components/auth-guard";
// import { AuthGuard } from "@/components/auth-guard";
import { DashboardPage } from "@/pages/dashboard-page";
import { ScanPage } from "@/pages/scan-page";
import { LibraryPage } from "@/pages/library-page";
@@ -14,16 +14,16 @@ import { DiseaseDetailPage } from "@/pages/disease-detail-page";
import { DiagnosisDetailPage } from "@/pages/diagnosis-detail-page";
import { ExpertReviewsPage } from "@/pages/expert-reviews-page";
import { DiagnosesPage } from "@/pages/diagnoses-page";
import { LoginPage } from "@/pages/login-page";
import { RegisterPage } from "@/pages/register-page";
// import { LoginPage } from "@/pages/login-page";
// import { RegisterPage } from "@/pages/register-page";
import { MainLayout } from "@/components/layout/main-layout";
const queryClient = new QueryClient();
const router = createBrowserRouter([
{ path: "/", element: <Navigate to="/dashboard" replace /> },
{ path: "/login", element: <LoginPage /> },
{ path: "/register", element: <RegisterPage /> },
// { path: "/login", element: <LoginPage /> },
// { path: "/register", element: <RegisterPage /> },
{
path: "/dashboard",
element: (
@@ -67,11 +67,9 @@ const router = createBrowserRouter([
{
path: "/expert/reviews",
element: (
<AuthGuard requireExpert>
<MainLayout>
<ExpertReviewsPage />
</MainLayout>
</AuthGuard>
<MainLayout>
<ExpertReviewsPage />
</MainLayout>
),
},
{
+40 -28
View File
@@ -1,38 +1,58 @@
import { createPortal } from "react-dom";
import { Link, useLocation } from "react-router-dom";
import { X, Leaf } from "lucide-react";
type Props = {
open: boolean;
onClose: () => void;
userRole?: string | null;
};
const NAV_ITEMS = [
{ path: "/dashboard", label: "Dashboard" },
{ path: "/scan", label: "Scan Tanaman" },
{ path: "/diagnoses", label: "Diagnosa" },
{ path: "/catalog", label: "Pustaka" },
{ path: "/catalog", label: "Pustaka", altPath: "/library" },
];
export function MobileNav({ open, onClose, userRole }: Props) {
export function MobileNav({ open, onClose }: Props) {
const location = useLocation();
if (!open) return null;
const isActive = (path: string) => location.pathname === path;
return (
<div className="fixed inset-0 z-50 lg:hidden">
const navContent = (
<div
// 2. Ubah z-50 menjadi z-[999] agar levelnya mentok paling atas
className={`fixed inset-0 z-[999] lg:hidden transition-opacity duration-300 ease-in-out ${
open ? "opacity-100" : "opacity-0 pointer-events-none"
}`}
aria-hidden={!open}
>
{/* Backdrop */}
<div className="fixed inset-0 bg-black/40" onClick={onClose} />
<div
className="fixed inset-0 bg-black/60 backdrop-blur-sm"
onClick={onClose}
/>
{/* Panel */}
<div className="fixed inset-y-0 right-0 z-50 w-full max-w-sm bg-[#306D29] shadow-xl">
<div className="flex items-center justify-between px-6 h-20 border-b border-white/10">
<div
className={`fixed inset-y-0 right-0 z-[999] flex w-full max-w-sm flex-col bg-[#306D29] shadow-2xl transition-transform duration-300 ease-in-out ${
open ? "translate-x-0" : "translate-x-full"
}`}
>
{/* Header */}
<div className="flex items-center justify-between px-6 h-20 border-b border-white/10 shrink-0">
<div className="flex items-center gap-3 font-semibold text-white">
<div className="flex h-10 w-10 items-center justify-center rounded-2xl bg-[#48A111]">
<Leaf className="h-5 w-5" />
<Link to="/dashboard" onClick={onClose}>
<Leaf className="h-5 w-5" />
</Link>
</div>
<div className="leading-tight">
<div className="text-lg font-bold">ZeaVis Edu</div>
<div className="text-[13px] font-normal text-[#9AD872]">
Smart AI for Corn Disease Detection
</div>
</div>
<span className="text-lg font-bold">ZeaVis Edu</span>
</div>
<button
onClick={onClose}
@@ -43,9 +63,11 @@ export function MobileNav({ open, onClose, userRole }: Props) {
</button>
</div>
<nav className="flex flex-col gap-2 px-4 pt-6">
{/* Nav items */}
<nav className="flex flex-col gap-2 overflow-y-auto px-4 py-6 flex-1">
{NAV_ITEMS.map((item) => {
const active = isActive(item.path);
const active =
isActive(item.path) || (item.altPath && isActive(item.altPath));
return (
<Link
key={item.path}
@@ -61,22 +83,12 @@ export function MobileNav({ open, onClose, userRole }: Props) {
</Link>
);
})}
{userRole === "expert" && (
<Link
to="/expert/reviews"
onClick={onClose}
className={`rounded-full px-4 py-3 text-[16px] font-medium transition-colors ${
isActive("/expert/reviews")
? "bg-[#48A111] text-white shadow-sm"
: "text-white/85 hover:bg-white/10 hover:text-white"
}`}
>
Review
</Link>
)}
</nav>
</div>
</div>
);
return typeof document !== "undefined"
? createPortal(navContent, document.body)
: navContent;
}
+22 -31
View File
@@ -1,19 +1,12 @@
import { useState } from "react";
import { Link, useLocation, useNavigate } from "react-router-dom";
import { Link, useLocation } from "react-router-dom";
import { Leaf, Menu } from "lucide-react";
import { MobileNav } from "./mobile-nav";
import { Button } from "@/components/ui/button";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { useAuthStore } from "@/store/auth-store";
import { apiClient } from "@/lib/api-client";
export function Navbar() {
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
const location = useLocation();
const navigate = useNavigate();
const queryClient = useQueryClient();
const setUser = useAuthStore((state) => state.setUser);
const user = useAuthStore((state) => state.user);
//
const isActive = (path: string) => location.pathname === path;
@@ -25,17 +18,6 @@ export function Navbar() {
: "text-white/85 hover:bg-white/10 hover:text-white",
].join(" ");
const logoutMutation = useMutation({
mutationFn: async () => {
await apiClient.logout();
},
onSuccess: () => {
setUser(null);
queryClient.clear();
navigate("/login");
},
});
return (
<header className="sticky top-0 z-40 bg-[#306D29] text-white shadow-sm backdrop-blur">
<div className="mx-auto flex h-20 max-w-6xl items-center justify-between px-6">
@@ -54,26 +36,35 @@ export function Navbar() {
</div>
<nav className="hidden lg:flex items-center gap-2">
<Link to="/dashboard" className={navLinkClassName(isActive("/dashboard"))}>
<Link
to="/dashboard"
className={navLinkClassName(isActive("/dashboard"))}
>
Dashboard
</Link>
<Link to="/scan" className={navLinkClassName(isActive("/scan"))}>
Scan Tanaman
</Link>
<Link to="/diagnoses" className={navLinkClassName(isActive("/diagnoses"))}>
<Link
to="/diagnoses"
className={navLinkClassName(isActive("/diagnoses"))}
>
Diagnosa
</Link>
<Link to="/catalog" className={navLinkClassName(isActive("/catalog") || isActive("/library"))}>
<Link
to="/catalog"
className={navLinkClassName(
isActive("/catalog") || isActive("/library"),
)}
>
Pustaka
</Link>
{user?.role === "expert" && (
<Link
to="/expert/reviews"
className={navLinkClassName(isActive("/expert/reviews"))}
>
Review
</Link>
)}
<Link
to="/expert/reviews"
className={navLinkClassName(isActive("/expert/reviews"))}
>
Review
</Link>
</nav>
<button
+1 -1
View File
@@ -103,7 +103,7 @@ export function ScanPage() {
{!previewUrl ? (
<div className="space-y-3">
<div
className="w-full border-2 border-dashed border-green-300 rounded-md p-12 h-60 text-center cursor-pointer"
className="w-full border-2 border-dashed border-green-300 rounded-md p-10 h-60 text-center cursor-pointer"
onClick={() => inputRef.current?.click()}
>
<Upload className="mx-auto text-green-500 mb-3" size={48} />