feat: implement sidebar notification drawer and update investor page padding layouts
This commit is contained in:
@@ -12,7 +12,7 @@ export default function InvestorDashboardPage() {
|
|||||||
const availableBalance = investor.totalEarnings - investor.totalWithdrawn - investor.withdrawalPending;
|
const availableBalance = investor.totalEarnings - investor.totalWithdrawn - investor.withdrawalPending;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen ">
|
<div className="min-h-screen lg:pt-6 pt-0">
|
||||||
<InvestorNotification isMobile />
|
<InvestorNotification isMobile />
|
||||||
<div className="pt-18 lg:pt-0 p-4 lg:p-6 max-w-8xl mx-auto mb-20 lg:mb-0">
|
<div className="pt-18 lg:pt-0 p-4 lg:p-6 max-w-8xl mx-auto mb-20 lg:mb-0">
|
||||||
<div className="flex flex-col lg:flex-row lg:items-center justify-between gap-4 mb-6">
|
<div className="flex flex-col lg:flex-row lg:items-center justify-between gap-4 mb-6">
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ export default function InvestorInvestmentDetailPage({ params }: { params: Promi
|
|||||||
const investmentTransactions = transactions.filter((t: any) => t.investorId === investor.id && t.type === 'investment_return');
|
const investmentTransactions = transactions.filter((t: any) => t.investorId === investor.id && t.type === 'investment_return');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen ">
|
<div className="min-h-screen lg:pt-6 pt-0 ">
|
||||||
<InvestorNotification isMobile />
|
<InvestorNotification isMobile />
|
||||||
<div className="pt-18 lg:pt-0 p-4 lg:p-6 max-w-6xl mx-auto mb-20 lg:mb-0">
|
<div className="pt-18 lg:pt-0 p-4 lg:p-6 max-w-6xl mx-auto mb-20 lg:mb-0">
|
||||||
<div className="flex flex-col lg:flex-row lg:items-center justify-between gap-4 mb-6">
|
<div className="flex flex-col lg:flex-row lg:items-center justify-between gap-4 mb-6">
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export default function MyInvestmentsPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen ">
|
<div className="min-h-screen lg:pt-6 pt-0">
|
||||||
<InvestorNotification isMobile />
|
<InvestorNotification isMobile />
|
||||||
<div className="pt-18 lg:pt-0 p-4 lg:p-6 max-w-8xl mx-auto mb-20 lg:mb-0">
|
<div className="pt-18 lg:pt-0 p-4 lg:p-6 max-w-8xl mx-auto mb-20 lg:mb-0">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ export default function InvestorProfilePage() {
|
|||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen">
|
<div className="min-h-screen lg:pt-6 pt-0">
|
||||||
<InvestorNotification isMobile />
|
<InvestorNotification isMobile />
|
||||||
<div className="pt-18 lg:pt-0 p-4 sm:p-5 bg-slate-50 min-h-screen">
|
<div className="pt-18 lg:pt-0 p-4 sm:p-5 bg-slate-50 min-h-screen">
|
||||||
<div className="max-w-8xl mx-auto">
|
<div className="max-w-8xl mx-auto">
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ export default function RentalHistoryPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen">
|
<div className="min-h-screen lg:pt-6 pt-0">
|
||||||
<InvestorNotification isMobile />
|
<InvestorNotification isMobile />
|
||||||
<div className="pt-18 lg:pt-0 p-4 sm:p-6 max-w-8xl mx-auto">
|
<div className="pt-18 lg:pt-0 p-4 sm:p-6 max-w-8xl mx-auto">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ export default function InvestorWithdrawPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen">
|
<div className="min-h-screen lg:pt-6 pt-0">
|
||||||
<InvestorNotification isMobile />
|
<InvestorNotification isMobile />
|
||||||
<div className="pt-18 lg:pt-0 p-4 lg:p-6 max-w-8xl mx-auto">
|
<div className="pt-18 lg:pt-0 p-4 lg:p-6 max-w-8xl mx-auto">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
|
|||||||
@@ -39,7 +39,9 @@ const ROLE_LABELS: Record<string, string> = {
|
|||||||
merchant: 'Merchant',
|
merchant: 'Merchant',
|
||||||
};
|
};
|
||||||
|
|
||||||
const adminNavItems = [
|
type NavItem = { label: string; href: string; icon: any; isNotification?: boolean };
|
||||||
|
|
||||||
|
const adminNavItems: NavItem[] = [
|
||||||
{ label: 'Dashboard', href: '/admin', icon: BarChart3 },
|
{ label: 'Dashboard', href: '/admin', icon: BarChart3 },
|
||||||
{ label: 'KYC Requests', href: '/admin/kyc', icon: Shield },
|
{ label: 'KYC Requests', href: '/admin/kyc', icon: Shield },
|
||||||
{ label: 'Rentals', href: '/admin/rentals', icon: FileText },
|
{ label: 'Rentals', href: '/admin/rentals', icon: FileText },
|
||||||
@@ -59,13 +61,13 @@ const adminNavItems = [
|
|||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const bikerNavItems = [
|
const bikerNavItems: NavItem[] = [
|
||||||
{ label: 'Biker Dashboard', href: '/', icon: Bike },
|
{ label: 'Biker Dashboard', href: '/', icon: Bike },
|
||||||
{ label: 'Rent Bike', href: '/rent', icon: Zap },
|
{ label: 'Rent Bike', href: '/rent', icon: Zap },
|
||||||
{ label: 'Browse EVs', href: '/bikes', icon: Battery },
|
{ label: 'Browse EVs', href: '/bikes', icon: Battery },
|
||||||
];
|
];
|
||||||
|
|
||||||
const investorNavItems = [
|
const investorNavItems: NavItem[] = [
|
||||||
{ label: 'Dashboard', href: '/investor/dashboard', icon: Bike },
|
{ label: 'Dashboard', href: '/investor/dashboard', icon: Bike },
|
||||||
{ label: 'My Investments', href: '/investor/plans', icon: Target },
|
{ label: 'My Investments', href: '/investor/plans', icon: Target },
|
||||||
{ label: 'Rental History', href: '/investor/rental-history', icon: History },
|
{ label: 'Rental History', href: '/investor/rental-history', icon: History },
|
||||||
@@ -74,7 +76,7 @@ const investorNavItems = [
|
|||||||
{ label: 'My Profile', href: '/investor/profile', icon: User },
|
{ label: 'My Profile', href: '/investor/profile', icon: User },
|
||||||
];
|
];
|
||||||
|
|
||||||
const shopNavItems = [
|
const shopNavItems: NavItem[] = [
|
||||||
{ label: 'Dashboard', href: '/shop', icon: Store },
|
{ label: 'Dashboard', href: '/shop', icon: Store },
|
||||||
{ label: 'Deliveries', href: '/shop/deliveries', icon: Truck },
|
{ label: 'Deliveries', href: '/shop/deliveries', icon: Truck },
|
||||||
{ label: 'Fleet', href: '/shop/fleet', icon: Bike },
|
{ label: 'Fleet', href: '/shop/fleet', icon: Bike },
|
||||||
@@ -84,6 +86,7 @@ export default function Sidebar() {
|
|||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const [mobileOpen, setMobileOpen] = useState(false);
|
const [mobileOpen, setMobileOpen] = useState(false);
|
||||||
const [expandedMenu, setExpandedMenu] = useState<string | null>(null);
|
const [expandedMenu, setExpandedMenu] = useState<string | null>(null);
|
||||||
|
const [notificationOpen, setNotificationOpen] = useState(false);
|
||||||
const [userName, setUserName] = useState('User');
|
const [userName, setUserName] = useState('User');
|
||||||
const [userRole, setUserRole] = useState('admin');
|
const [userRole, setUserRole] = useState('admin');
|
||||||
|
|
||||||
@@ -155,6 +158,23 @@ export default function Sidebar() {
|
|||||||
const isChild = item.href !== '/' && pathname.startsWith(item.href + '/');
|
const isChild = item.href !== '/' && pathname.startsWith(item.href + '/');
|
||||||
const isActive = isExact || isChild;
|
const isActive = isExact || isChild;
|
||||||
const Icon = item.icon;
|
const Icon = item.icon;
|
||||||
|
|
||||||
|
if (item.isNotification) {
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
key={item.label}
|
||||||
|
onClick={() => { setMobileOpen(false); setNotificationOpen(true); }}
|
||||||
|
className="w-full flex items-center justify-between gap-3 px-3 py-2.5 rounded-lg text-sm font-medium text-slate-600 hover:bg-slate-50 hover:text-slate-900 transition-all duration-200"
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<Icon className="w-5 h-5" />
|
||||||
|
<span>{item.label}</span>
|
||||||
|
</div>
|
||||||
|
<span className="px-2 py-0.5 bg-accent text-white text-xs font-bold rounded-full">2</span>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
key={item.href}
|
key={item.href}
|
||||||
@@ -175,8 +195,14 @@ export default function Sidebar() {
|
|||||||
})}
|
})}
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
{isInvestor && (
|
{isInvestor && notificationOpen && (
|
||||||
<div className="hidden lg:block p-3 border-t border-slate-100">
|
<div className="p-3 border-t border-slate-100">
|
||||||
|
<div className="flex items-center justify-between mb-2">
|
||||||
|
<span className="text-sm font-semibold text-slate-700">Notifications</span>
|
||||||
|
<button onClick={() => setNotificationOpen(false)} className="p-1 hover:bg-slate-100 rounded">
|
||||||
|
<X className="w-4 h-4 text-slate-400" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<InvestorNotification />
|
<InvestorNotification />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user