feat: implement recovery incident detail view with tabbed navigation and add application sidebar component
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
import { ClipboardText, CheckCircle } from '@phosphor-icons/react';
|
||||
import { ClipboardTextIcon, CheckCircleIcon } from '@phosphor-icons/react';
|
||||
|
||||
export default function AuditTrailTab() {
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="bg-white rounded-2xl p-6 border border-gray-100 shadow-sm flex flex-col gap-6">
|
||||
<div className="flex items-center gap-2">
|
||||
<ClipboardText size={20} weight="bold" className="text-[#143d30]" />
|
||||
<ClipboardTextIcon size={20} weight="bold" className="text-[#143d30]" />
|
||||
<h3 className="text-[13px] font-bold text-[#143d30] tracking-wider uppercase">Lifecycle Timeline & Audit Trail</h3>
|
||||
</div>
|
||||
|
||||
@@ -14,7 +14,7 @@ export default function AuditTrailTab() {
|
||||
<div className="relative pl-10 pb-8">
|
||||
<div className="absolute left-[7px] top-7 bottom-0 w-[2px] bg-[#1B9869]"></div>
|
||||
<div className="absolute left-[-4px] top-0.5 bg-white">
|
||||
<CheckCircle size={24} weight="fill" className="text-[#1B9869]" />
|
||||
<CheckCircleIcon size={24} weight="fill" className="text-[#1B9869]" />
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between items-start">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IdentificationCard, AirplaneTilt, WarningCircle } from '@phosphor-icons/react';
|
||||
import { IdentificationCardIcon, AirplaneTiltIcon, WarningCircleIcon } from '@phosphor-icons/react';
|
||||
|
||||
export default function CaseDetailsTab() {
|
||||
return (
|
||||
@@ -6,7 +6,7 @@ export default function CaseDetailsTab() {
|
||||
{/* PASSENGER INFORMATION */}
|
||||
<div className="bg-white rounded-2xl p-6 border border-gray-100 shadow-sm flex flex-col gap-6">
|
||||
<div className="flex items-center gap-2">
|
||||
<IdentificationCard size={20} weight="bold" className="text-gray-700" />
|
||||
<IdentificationCardIcon size={20} weight="bold" className="text-gray-700" />
|
||||
<h3 className="text-[13px] font-bold text-gray-800 tracking-wider">PASSENGER INFORMATION</h3>
|
||||
</div>
|
||||
|
||||
@@ -33,7 +33,7 @@ export default function CaseDetailsTab() {
|
||||
{/* FLIGHT JOURNEY */}
|
||||
<div className="bg-white rounded-2xl p-6 border border-gray-100 shadow-sm flex flex-col gap-6">
|
||||
<div className="flex items-center gap-2">
|
||||
<AirplaneTilt size={20} weight="bold" className="text-gray-700" />
|
||||
<AirplaneTiltIcon size={20} weight="bold" className="text-gray-700" />
|
||||
<h3 className="text-[13px] font-bold text-gray-800 tracking-wider">FLIGHT JOURNEY</h3>
|
||||
</div>
|
||||
|
||||
@@ -68,7 +68,7 @@ export default function CaseDetailsTab() {
|
||||
{/* DISRUPTION DETAILS */}
|
||||
<div className="bg-white rounded-2xl p-6 border border-gray-100 shadow-sm flex flex-col gap-6">
|
||||
<div className="flex items-center gap-2">
|
||||
<WarningCircle size={20} weight="bold" className="text-gray-700" />
|
||||
<WarningCircleIcon size={20} weight="bold" className="text-gray-700" />
|
||||
<h3 className="text-[13px] font-bold text-gray-800 tracking-wider">DISRUPTION DETAILS</h3>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CreditCard, Gift, HandHeart } from '@phosphor-icons/react';
|
||||
import { CreditCardIcon, GiftIcon, HandHeartIcon } from '@phosphor-icons/react';
|
||||
|
||||
export default function RecoveryPlanTab() {
|
||||
return (
|
||||
@@ -6,7 +6,7 @@ export default function RecoveryPlanTab() {
|
||||
{/* FINANCIAL REFUND */}
|
||||
<div className="bg-white rounded-2xl p-6 border border-gray-100 shadow-sm flex flex-col gap-6">
|
||||
<div className="flex items-center gap-2">
|
||||
<CreditCard size={20} weight="bold" className="text-[#143d30]" />
|
||||
<CreditCardIcon size={20} weight="bold" className="text-[#143d30]" />
|
||||
<h3 className="text-[13px] font-bold text-[#143d30] tracking-wider">FINANCIAL REFUND</h3>
|
||||
</div>
|
||||
|
||||
@@ -29,7 +29,7 @@ export default function RecoveryPlanTab() {
|
||||
{/* COMPENSATION & PERKS */}
|
||||
<div className="bg-white rounded-2xl p-6 border border-gray-100 shadow-sm flex flex-col gap-6">
|
||||
<div className="flex items-center gap-2">
|
||||
<Gift size={20} weight="bold" className="text-[#143d30]" />
|
||||
<GiftIcon size={20} weight="bold" className="text-[#143d30]" />
|
||||
<h3 className="text-[13px] font-bold text-[#143d30] tracking-wider">COMPENSATION & PERKS</h3>
|
||||
</div>
|
||||
|
||||
@@ -52,7 +52,7 @@ export default function RecoveryPlanTab() {
|
||||
{/* PASSENGER CARE */}
|
||||
<div className="bg-white rounded-2xl p-6 border border-gray-100 shadow-sm flex flex-col gap-6">
|
||||
<div className="flex items-center gap-2">
|
||||
<HandHeart size={20} weight="bold" className="text-[#143d30]" />
|
||||
<HandHeartIcon size={20} weight="bold" className="text-[#143d30]" />
|
||||
<h3 className="text-[13px] font-bold text-[#143d30] tracking-wider">PASSENGER CARE</h3>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Sparkle, User, ArrowRight } from '@phosphor-icons/react';
|
||||
import { CustomButton } from '../../../components/custom';
|
||||
import { SparkleIcon, UserIcon, ArrowRightIcon } from "@phosphor-icons/react";
|
||||
import { CustomButton } from "../../../components/custom";
|
||||
|
||||
export default function SummaryTab() {
|
||||
return (
|
||||
@@ -10,50 +10,73 @@ export default function SummaryTab() {
|
||||
<div className="absolute top-0 right-0 w-32 h-32 bg-[#1B9869]/5 rounded-full blur-2xl -mr-16 -mt-16 pointer-events-none"></div>
|
||||
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<span className="text-[#1B9869]"><Sparkle size={20} weight="fill" /></span>
|
||||
<h3 className="text-[13px] font-bold text-gray-800 tracking-wider">AI STRATEGIC ASSESSMENT</h3>
|
||||
<span className="text-[#1B9869]">
|
||||
<SparkleIcon size={20} weight="fill" />
|
||||
</span>
|
||||
<h3 className="text-[13px] font-bold text-gray-800 tracking-wider">
|
||||
AI STRATEGIC ASSESSMENT
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<p className="text-[15px] text-gray-700 italic leading-relaxed">
|
||||
"Analysis of JOHN WICK's history and the flight disruption suggest this is a high-retention opportunity. Automated settlement is recommended to maintain NPS within the Platinum segment."
|
||||
"Analysis of JOHN WICK's history and the flight disruption suggest
|
||||
this is a high-retention opportunity. Automated settlement is
|
||||
recommended to maintain NPS within the Platinum segment."
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Row of 3 Cards */}
|
||||
<div className="grid grid-cols-3 gap-6">
|
||||
|
||||
{/* INCIDENT ROOT */}
|
||||
<div className="bg-white rounded-2xl p-6 border border-gray-100 shadow-sm flex flex-col gap-5">
|
||||
<h3 className="text-[13px] font-bold text-[#1B9869] tracking-wider">INCIDENT ROOT</h3>
|
||||
<h3 className="text-[13px] font-bold text-[#1B9869] tracking-wider">
|
||||
INCIDENT ROOT
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
<span className="block text-[11px] font-bold text-[#1B9869] tracking-wider mb-1">Recovery Source</span>
|
||||
<span className="block text-[15px] font-semibold text-gray-900">Simulation Engine</span>
|
||||
<span className="block text-[11px] font-bold text-[#1B9869] tracking-wider mb-1">
|
||||
Recovery Source
|
||||
</span>
|
||||
<span className="block text-[15px] font-semibold text-gray-900">
|
||||
Simulation Engine
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span className="block text-[11px] font-bold text-[#1B9869] tracking-wider mb-1">Policy Applied</span>
|
||||
<span className="block text-[15px] font-semibold text-gray-900">Standard Policy</span>
|
||||
<span className="block text-[11px] font-bold text-[#1B9869] tracking-wider mb-1">
|
||||
Policy Applied
|
||||
</span>
|
||||
<span className="block text-[15px] font-semibold text-gray-900">
|
||||
Standard Policy
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span className="block text-[11px] font-bold text-[#1B9869] tracking-wider mb-1">Jurisdiction</span>
|
||||
<span className="block text-[15px] font-semibold text-gray-900">EU261</span>
|
||||
<span className="block text-[11px] font-bold text-[#1B9869] tracking-wider mb-1">
|
||||
Jurisdiction
|
||||
</span>
|
||||
<span className="block text-[15px] font-semibold text-gray-900">
|
||||
EU261
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* ASSIGNMENT */}
|
||||
<div className="bg-white rounded-2xl p-6 border border-gray-100 shadow-sm flex flex-col gap-5">
|
||||
<h3 className="text-[13px] font-bold text-[#1B9869] tracking-wider">ASSIGNMENT</h3>
|
||||
<h3 className="text-[13px] font-bold text-[#1B9869] tracking-wider">
|
||||
ASSIGNMENT
|
||||
</h3>
|
||||
|
||||
<div className="relative">
|
||||
<div className="absolute inset-0 bg-white/40 backdrop-blur-[2px] z-10 flex items-center justify-center">
|
||||
<h4 className="text-xl font-bold text-gray-900 italic">"Coming soon"</h4>
|
||||
<h4 className="text-xl font-bold text-gray-900 italic">
|
||||
"Coming soon"
|
||||
</h4>
|
||||
</div>
|
||||
<div className="opacity-30 pointer-events-none">
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<div className="w-10 h-10 rounded-full bg-gray-100 flex items-center justify-center text-gray-400">
|
||||
<User size={20} />
|
||||
<UserIcon size={20} />
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900">Emma Watson</div>
|
||||
@@ -62,7 +85,7 @@ export default function SummaryTab() {
|
||||
</div>
|
||||
<CustomButton
|
||||
variant="outlined"
|
||||
leftIcon={<ArrowRight size={16} />}
|
||||
leftIcon={<ArrowRightIcon size={16} />}
|
||||
className="w-full !border-gray-200 !text-gray-600 !font-semibold hover:!bg-gray-50"
|
||||
>
|
||||
Change Assignee
|
||||
@@ -73,18 +96,22 @@ export default function SummaryTab() {
|
||||
|
||||
{/* RECOVERY SCORE */}
|
||||
<div className="bg-white rounded-2xl p-6 border border-gray-100 shadow-sm flex flex-col gap-5">
|
||||
<h3 className="text-[13px] font-bold text-[#1B9869] tracking-wider">RECOVERY SCORE</h3>
|
||||
<h3 className="text-[13px] font-bold text-[#1B9869] tracking-wider">
|
||||
RECOVERY SCORE
|
||||
</h3>
|
||||
|
||||
<div className="flex items-baseline gap-1 mt-2 mb-2">
|
||||
<span className="text-[48px] font-bold text-gray-900 leading-none">75</span>
|
||||
<span className="text-[48px] font-bold text-gray-900 leading-none">
|
||||
75
|
||||
</span>
|
||||
<span className="text-xl text-gray-400 font-semibold">/ 100</span>
|
||||
</div>
|
||||
|
||||
<p className="text-sm text-gray-600 leading-relaxed">
|
||||
Manual review recommended. Aligns with standard EU261 recovery logic.
|
||||
Manual review recommended. Aligns with standard EU261 recovery
|
||||
logic.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { useState } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { ArrowsClockwise, User, AirplaneTilt, Checks, X, ClockCounterClockwise, Sparkle, ArrowLeft } from '@phosphor-icons/react';
|
||||
import {User, Checks, X, ClockCounterClockwiseIcon, ArrowLeftIcon, ArrowsClockwiseIcon, AirplaneTiltIcon } from '@phosphor-icons/react';
|
||||
import { CustomButton, CustomTabs, CustomBackButton, CustomStatus } from '../../../components/custom';
|
||||
import SummaryTab from './SummaryTab';
|
||||
import CaseDetailsTab from './CaseDetailsTab';
|
||||
import RecoveryPlanTab from './RecoveryPlanTab';
|
||||
import AuditTrailTab from './AuditTrailTab';
|
||||
import { SparkleIcon } from 'lucide-react';
|
||||
|
||||
export default function RecoveryIncidentTabs() {
|
||||
const { id } = useParams();
|
||||
@@ -48,11 +49,11 @@ export default function RecoveryIncidentTabs() {
|
||||
<div className="flex items-center gap-3 text-sm text-gray-500 ml-8">
|
||||
<div className="flex items-center gap-1.5"><User size={16} /> JOHN WICK</div>
|
||||
<span>•</span>
|
||||
<div className="flex items-center gap-1.5"><AirplaneTilt size={16} /> Q23SXD (FRA → JFK)</div>
|
||||
<div className="flex items-center gap-1.5"><AirplaneTiltIcon size={16} /> Q23SXD (FRA → JFK)</div>
|
||||
</div>
|
||||
</div>
|
||||
<CustomButton
|
||||
leftIcon={<ArrowsClockwise size={18} weight="bold" />}
|
||||
leftIcon={<ArrowsClockwiseIcon size={18} weight="bold" />}
|
||||
className="!bg-[#1B9869] hover:!bg-[#14704E] !text-white !font-semibold !rounded-lg !px-5 !py-2.5"
|
||||
>
|
||||
RE-RUN ENGINE
|
||||
@@ -104,7 +105,7 @@ export default function RecoveryIncidentTabs() {
|
||||
{/* Sidebar Content */}
|
||||
<div className="p-6 select-none pointer-events-none">
|
||||
<div className="flex items-center gap-2 mb-6">
|
||||
<span className="text-[#1B9869]"><Sparkle size={20} weight="fill" /></span>
|
||||
<span className="text-[#1B9869]"><SparkleIcon size={20} height="fill" /></span>
|
||||
<h3 className="text-[13px] font-bold text-gray-400 tracking-wider">AI RECOMMENDATION</h3>
|
||||
</div>
|
||||
|
||||
@@ -136,7 +137,7 @@ export default function RecoveryIncidentTabs() {
|
||||
|
||||
<CustomButton
|
||||
disabled
|
||||
rightIcon={<ArrowLeft size={16} weight="bold" className="rotate-180" />}
|
||||
rightIcon={<ArrowLeftIcon size={16} weight="bold" className="rotate-180" />}
|
||||
className="w-full !py-3 !bg-[#1B9869]/50 !text-white !font-semibold !rounded-lg"
|
||||
>
|
||||
EXECUTE RECOMMENDATION
|
||||
@@ -159,7 +160,7 @@ export default function RecoveryIncidentTabs() {
|
||||
</CustomButton>
|
||||
<CustomButton
|
||||
variant="text"
|
||||
leftIcon={<ClockCounterClockwise size={18} weight="bold" />}
|
||||
leftIcon={<ClockCounterClockwiseIcon size={18} weight="bold" />}
|
||||
className="!bg-[#FEF3C7] !text-[#B45309] !font-bold !rounded-lg !border !border-[#B45309] hover:!bg-[#FDE68A]"
|
||||
>
|
||||
MARK FOR REVIEW
|
||||
|
||||
+103
-49
@@ -1,27 +1,27 @@
|
||||
import { useState } from 'react';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import { useState } from "react";
|
||||
import { Link, useLocation } from "react-router-dom";
|
||||
import {
|
||||
ShieldCheck,
|
||||
Gear,
|
||||
ClockCounterClockwise,
|
||||
CaretDoubleRight,
|
||||
SquaresFour,
|
||||
Faders,
|
||||
ArrowsClockwise,
|
||||
UsersFour,
|
||||
CaretDoubleLeft,
|
||||
SignOut,
|
||||
Question
|
||||
} from '@phosphor-icons/react';
|
||||
SquaresFourIcon,
|
||||
FadersIcon,
|
||||
ArrowsClockwiseIcon,
|
||||
UsersFourIcon,
|
||||
CaretDoubleLeftIcon,
|
||||
QuestionIcon,
|
||||
SignOutIcon,
|
||||
GearIcon,
|
||||
ClockCounterClockwiseIcon,
|
||||
CaretDoubleRightIcon,
|
||||
} from "@phosphor-icons/react";
|
||||
import { ShieldCheckIcon } from "lucide-react";
|
||||
|
||||
const NAV_ITEMS = [
|
||||
{ label: 'Dashboard', path: '/', icon: SquaresFour },
|
||||
{ label: 'Simulation Engine', path: '/simulation', icon: Faders },
|
||||
{ label: 'Recovery Incidents', path: '/recovery', icon: ArrowsClockwise },
|
||||
{ label: 'Cohort Management', path: '/cohorts', icon: UsersFour },
|
||||
{ label: 'Policy Engine', path: '/policy-engine', icon: ShieldCheck },
|
||||
{ label: 'Configuration', path: '/config', icon: Gear },
|
||||
{ label: 'Audit Logs', path: '/audit', icon: ClockCounterClockwise },
|
||||
{ label: "Dashboard", path: "/", icon: SquaresFourIcon },
|
||||
{ label: "Simulation Engine", path: "/simulation", icon: FadersIcon },
|
||||
{ label: "Recovery Incidents", path: "/recovery", icon: ArrowsClockwiseIcon },
|
||||
{ label: "Cohort Management", path: "/cohorts", icon: UsersFourIcon },
|
||||
{ label: "Policy Engine", path: "/policy-engine", icon: ShieldCheckIcon },
|
||||
{ label: "Configuration", path: "/config", icon: GearIcon },
|
||||
{ label: "Audit Logs", path: "/audit", icon: ClockCounterClockwiseIcon },
|
||||
];
|
||||
|
||||
interface AppSidebarProps {
|
||||
@@ -44,38 +44,61 @@ export default function AppSidebar({ isOpen, onClose }: AppSidebarProps) {
|
||||
)}
|
||||
|
||||
<div
|
||||
className={`fixed inset-y-0 left-0 transform ${isOpen ? 'translate-x-0' : '-translate-x-full'} lg:relative lg:translate-x-0 z-50 ${isCollapsed ? 'w-[88px]' : 'w-[260px]'} h-screen flex flex-col bg-[#F4F7F6] font-sans transition-all duration-300 ease-in-out`}
|
||||
className={`fixed inset-y-0 left-0 transform ${isOpen ? "translate-x-0" : "-translate-x-full"} lg:relative lg:translate-x-0 z-50 ${isCollapsed ? "w-[88px]" : "w-[260px]"} h-screen flex flex-col bg-[#F4F7F6] font-sans transition-all duration-300 ease-in-out`}
|
||||
>
|
||||
{/* Logo Area */}
|
||||
<div className={`pt-6 pb-4 flex items-center ${isCollapsed ? 'px-0 justify-center flex-col gap-4' : 'px-5 justify-between'}`}>
|
||||
<div
|
||||
className={`pt-6 pb-4 flex items-center ${isCollapsed ? "px-0 justify-center flex-col gap-4" : "px-5 justify-between"}`}
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-[42px] h-[42px] bg-[#4B4B4B] rounded-[14px] flex flex-col items-center justify-center text-white shadow-sm shrink-0">
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" className="mb-0.5">
|
||||
<svg
|
||||
width="22"
|
||||
height="22"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className="mb-0.5"
|
||||
>
|
||||
<path d="M17.8 19.2 16 11l3.5-3.5C21 6 21.5 4 21 3c-1-.5-3 0-4.5 1.5L13 8 4.8 6.2c-.5-.1-.9.2-1.1.7l-1.2 3.3c-.2.5.1 1.1.6 1.2l6.9 1.7-2.9 2.9-3.6-.9c-.5-.1-.9.2-1.1.7l-1.3 3.5c-.2.5.1 1.1.6 1.2l12.4 3.1c.5.1.9-.2 1.1-.7l.8-2.3c.1-.5-.2-1.1-.7-1.2z" />
|
||||
</svg>
|
||||
<div className="w-[18px] h-[2px] bg-white rounded-full"></div>
|
||||
</div>
|
||||
{!isCollapsed && (
|
||||
<span className="text-[17px] font-extrabold text-[#111827] tracking-tight whitespace-nowrap">Aero Resolve</span>
|
||||
<span className="text-[17px] font-extrabold text-[#111827] tracking-tight whitespace-nowrap">
|
||||
Aero Resolve
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<button onClick={onClose} className="text-slate-400 hover:text-slate-600 transition-colors lg:hidden">
|
||||
<CaretDoubleLeft size={20} weight="bold" />
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="text-slate-400 hover:text-slate-600 transition-colors lg:hidden"
|
||||
>
|
||||
<CaretDoubleLeftIcon size={20} weight="bold" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setIsCollapsed(!isCollapsed)}
|
||||
className={`hidden lg:block text-slate-400 hover:text-slate-600 transition-colors ${isCollapsed ? '' : 'ml-auto'}`}
|
||||
className={`hidden lg:block text-slate-400 hover:text-slate-600 transition-colors ${isCollapsed ? "" : "ml-auto"}`}
|
||||
>
|
||||
{isCollapsed ? <CaretDoubleRight size={20} weight="bold" /> : <CaretDoubleLeft size={20} weight="bold" />}
|
||||
{isCollapsed ? (
|
||||
<CaretDoubleRightIcon size={20} weight="bold" />
|
||||
) : (
|
||||
<CaretDoubleLeftIcon size={20} weight="bold" />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{/* Navigation */}
|
||||
<nav className={`flex-1 py-3 space-y-1 overflow-y-auto overflow-x-hidden ${isCollapsed ? 'px-3' : 'px-4'}`}>
|
||||
<nav
|
||||
className={`flex-1 py-3 space-y-1 overflow-y-auto overflow-x-hidden ${isCollapsed ? "px-3" : "px-4"}`}
|
||||
>
|
||||
{NAV_ITEMS.map((item) => {
|
||||
const isActive = location.pathname === item.path || (item.path !== '/' && location.pathname.startsWith(item.path));
|
||||
const isActive =
|
||||
location.pathname === item.path ||
|
||||
(item.path !== "/" && location.pathname.startsWith(item.path));
|
||||
const Icon = item.icon;
|
||||
|
||||
return (
|
||||
@@ -86,15 +109,15 @@ export default function AppSidebar({ isOpen, onClose }: AppSidebarProps) {
|
||||
onClick={() => {
|
||||
if (window.innerWidth < 1024) onClose();
|
||||
}}
|
||||
className={`group flex items-center ${isCollapsed ? 'justify-center px-0 w-12 mx-auto' : 'gap-3 px-3.5'} py-[10px] rounded-[12px] text-[13px] transition-all duration-200 relative ${
|
||||
className={`group flex items-center ${isCollapsed ? "justify-center px-0 w-12 mx-auto" : "gap-3 px-3.5"} py-[10px] rounded-[12px] text-[13px] transition-all duration-200 relative ${
|
||||
isActive
|
||||
? 'bg-gradient-to-b from-primary to-primary-dark text-white shadow-md shadow-primary/20 font-semibold'
|
||||
: 'text-[#475569] font-medium hover:bg-slate-200/40 hover:text-slate-900'
|
||||
? "bg-gradient-to-b from-primary to-primary-dark text-white shadow-md shadow-primary/20 font-semibold"
|
||||
: "text-[#475569] font-medium hover:bg-slate-200/40 hover:text-slate-900"
|
||||
}`}
|
||||
>
|
||||
<Icon
|
||||
size={18}
|
||||
className={`${isActive ? 'text-white' : 'text-slate-600 group-hover:text-slate-800'} shrink-0`}
|
||||
className={`${isActive ? "text-white" : "text-slate-600 group-hover:text-slate-800"} shrink-0`}
|
||||
strokeWidth={isActive ? 2 : 1.5}
|
||||
/>
|
||||
|
||||
@@ -107,26 +130,57 @@ export default function AppSidebar({ isOpen, onClose }: AppSidebarProps) {
|
||||
</nav>
|
||||
|
||||
{/* Bottom Section Card */}
|
||||
<div className={`mb-2 mt-2 bg-gradient-to-br from-[#FAFCFB] to-[#E3EFE9] border border-white rounded-[24px] shadow-[0_4px_12px_-4px_rgba(0,0,0,0.05)] relative overflow-hidden transition-all duration-300 ${isCollapsed ? 'mx-2 p-2 flex flex-col items-center gap-3' : 'mx-4 p-3'}`}>
|
||||
<div
|
||||
className={`mb-2 mt-2 bg-gradient-to-br from-[#FAFCFB] to-[#E3EFE9] border border-white rounded-[24px] shadow-[0_4px_12px_-4px_rgba(0,0,0,0.05)] relative overflow-hidden transition-all duration-300 ${isCollapsed ? "mx-2 p-2 flex flex-col items-center gap-3" : "mx-4 p-3"}`}
|
||||
>
|
||||
{/* Soft decorative glow */}
|
||||
{!isCollapsed && <div className="absolute -top-10 -right-10 w-32 h-32 bg-white/60 rounded-full blur-2xl pointer-events-none" />}
|
||||
{!isCollapsed && (
|
||||
<div className="absolute -top-10 -right-10 w-32 h-32 bg-white/60 rounded-full blur-2xl pointer-events-none" />
|
||||
)}
|
||||
|
||||
<div className={`relative z-10 flex flex-col ${isCollapsed ? 'gap-2 w-full' : 'gap-0.5'}`}>
|
||||
<button title={isCollapsed ? "Sign Out" : undefined} className={`flex items-center ${isCollapsed ? 'justify-center px-0 h-10 w-full' : 'gap-3 px-3 py-2'} text-[13px] font-semibold text-[#E02424] hover:bg-red-50/50 rounded-[10px] transition-colors`}>
|
||||
<SignOut size={17} className="text-[#E02424] shrink-0" weight="bold" />
|
||||
{!isCollapsed && <span className="whitespace-nowrap">Sign Out</span>}
|
||||
<div
|
||||
className={`relative z-10 flex flex-col ${isCollapsed ? "gap-2 w-full" : "gap-0.5"}`}
|
||||
>
|
||||
<button
|
||||
title={isCollapsed ? "Sign Out" : undefined}
|
||||
className={`flex items-center ${isCollapsed ? "justify-center px-0 h-10 w-full" : "gap-3 px-3 py-2"} text-[13px] font-semibold text-[#E02424] hover:bg-red-50/50 rounded-[10px] transition-colors`}
|
||||
>
|
||||
<SignOutIcon
|
||||
size={17}
|
||||
className="text-[#E02424] shrink-0"
|
||||
weight="bold"
|
||||
/>
|
||||
{!isCollapsed && (
|
||||
<span className="whitespace-nowrap">Sign Out</span>
|
||||
)}
|
||||
</button>
|
||||
<button title={isCollapsed ? "Help Center" : undefined} className={`flex items-center ${isCollapsed ? 'justify-center px-0 h-10 w-full' : 'gap-3 px-3 py-2'} text-[13px] font-medium text-slate-700 hover:bg-white/40 rounded-[10px] transition-colors`}>
|
||||
<Question size={17} className="text-slate-700 shrink-0" weight="regular" />
|
||||
{!isCollapsed && <span className="whitespace-nowrap">Help center</span>}
|
||||
<button
|
||||
title={isCollapsed ? "Help Center" : undefined}
|
||||
className={`flex items-center ${isCollapsed ? "justify-center px-0 h-10 w-full" : "gap-3 px-3 py-2"} text-[13px] font-medium text-slate-700 hover:bg-white/40 rounded-[10px] transition-colors`}
|
||||
>
|
||||
<QuestionIcon
|
||||
size={17}
|
||||
className="text-slate-700 shrink-0"
|
||||
weight="regular"
|
||||
/>
|
||||
{!isCollapsed && (
|
||||
<span className="whitespace-nowrap">Help center</span>
|
||||
)}
|
||||
</button>
|
||||
|
||||
<div title={isCollapsed ? "Admin Demo" : undefined} className={`p-2 bg-white rounded-[16px] shadow-[0_2px_8px_-4px_rgba(0,0,0,0.08)] border border-white flex items-center cursor-pointer hover:shadow-md transition-shadow ${isCollapsed ? 'justify-center mt-1 w-full h-12' : 'gap-2.5 mt-2'}`}>
|
||||
<div
|
||||
title={isCollapsed ? "Admin Demo" : undefined}
|
||||
className={`p-2 bg-white rounded-[16px] shadow-[0_2px_8px_-4px_rgba(0,0,0,0.08)] border border-white flex items-center cursor-pointer hover:shadow-md transition-shadow ${isCollapsed ? "justify-center mt-1 w-full h-12" : "gap-2.5 mt-2"}`}
|
||||
>
|
||||
<div className="w-8 h-8 rounded-full bg-[#C2D1E0] flex-shrink-0" />
|
||||
{!isCollapsed && (
|
||||
<div className="flex flex-col justify-center overflow-hidden">
|
||||
<span className="text-[13px] font-bold text-[#111827] leading-tight truncate">Admin Demo</span>
|
||||
<span className="text-[10px] text-slate-500 font-medium mt-0.5 leading-tight truncate">System Administrator</span>
|
||||
<span className="text-[13px] font-bold text-[#111827] leading-tight truncate">
|
||||
Admin Demo
|
||||
</span>
|
||||
<span className="text-[10px] text-slate-500 font-medium mt-0.5 leading-tight truncate">
|
||||
System Administrator
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user