updates
This commit is contained in:
@@ -129,6 +129,9 @@ const BusinessDashboardPage: React.FC = () => {
|
||||
if (response.status === 'success' && response.data) {
|
||||
let invoiceList = response.data.invoices || [];
|
||||
|
||||
// Client-side filtering for search (only on current page results)
|
||||
// Note: This is a limitation - search only works on current page
|
||||
// For full search functionality, backend needs to support search parameter
|
||||
if (invoiceFilters.search) {
|
||||
invoiceList = invoiceList.filter((inv) =>
|
||||
inv.invoice_number.toLowerCase().includes(invoiceFilters.search.toLowerCase()) ||
|
||||
@@ -138,8 +141,15 @@ const BusinessDashboardPage: React.FC = () => {
|
||||
}
|
||||
|
||||
setInvoices(invoiceList);
|
||||
setInvoicesTotalPages(response.data.total_pages || 1);
|
||||
setInvoicesTotalItems(response.data.total || 0);
|
||||
// Only update pagination if not searching (to avoid incorrect counts)
|
||||
if (!invoiceFilters.search) {
|
||||
setInvoicesTotalPages(response.data.total_pages || 1);
|
||||
setInvoicesTotalItems(response.data.total || 0);
|
||||
} else {
|
||||
// When searching, keep original pagination but show filtered count
|
||||
setInvoicesTotalPages(response.data.total_pages || 1);
|
||||
setInvoicesTotalItems(response.data.total || 0);
|
||||
}
|
||||
}
|
||||
} catch (error: any) {
|
||||
toast.error(error.response?.data?.message || 'Unable to load invoices');
|
||||
@@ -354,28 +364,28 @@ const BusinessDashboardPage: React.FC = () => {
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-white to-slate-50">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8 space-y-10 animate-fade-in">
|
||||
<div className="max-w-7xl mx-auto px-2 sm:px-3 md:px-4 lg:px-6 xl:px-8 py-2 sm:py-4 md:py-6 lg:py-8 space-y-3 sm:space-y-4 md:space-y-6 lg:space-y-8 animate-fade-in">
|
||||
{}
|
||||
<div className="relative">
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-emerald-400/5 via-transparent to-purple-600/5 rounded-3xl blur-3xl"></div>
|
||||
<div className="relative bg-white/80 backdrop-blur-xl rounded-3xl shadow-2xl border border-emerald-200/30 p-8 md:p-10">
|
||||
<div className="flex flex-col md:flex-row md:items-center md:justify-between gap-8">
|
||||
<div className="flex items-start gap-5">
|
||||
<div className="relative">
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-emerald-400 to-purple-600 rounded-2xl blur-lg opacity-50"></div>
|
||||
<div className="relative p-4 rounded-2xl bg-gradient-to-br from-emerald-500 via-emerald-500 to-purple-600 shadow-xl border border-emerald-400/50">
|
||||
<FileText className="w-8 h-8 text-white" />
|
||||
<div className="absolute -top-1 -right-1 w-4 h-4 bg-gradient-to-br from-green-300 to-emerald-500 rounded-full shadow-lg animate-pulse"></div>
|
||||
<div className="relative bg-white/80 backdrop-blur-xl rounded-xl sm:rounded-2xl md:rounded-3xl shadow-2xl border border-emerald-200/30 p-3 sm:p-4 md:p-6 lg:p-8">
|
||||
<div className="flex flex-col md:flex-row md:items-center md:justify-between gap-4 sm:gap-6 md:gap-8">
|
||||
<div className="flex items-start gap-3 sm:gap-4 md:gap-5">
|
||||
<div className="relative flex-shrink-0">
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-emerald-400 to-purple-600 rounded-xl sm:rounded-2xl blur-lg opacity-50"></div>
|
||||
<div className="relative p-2.5 sm:p-3 md:p-4 rounded-xl sm:rounded-2xl bg-gradient-to-br from-emerald-500 via-emerald-500 to-purple-600 shadow-xl border border-emerald-400/50">
|
||||
<FileText className="w-5 h-5 sm:w-6 sm:h-6 md:w-8 md:h-8 text-white" />
|
||||
<div className="absolute -top-1 -right-1 w-3 h-3 sm:w-4 sm:h-4 bg-gradient-to-br from-green-300 to-emerald-500 rounded-full shadow-lg animate-pulse"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-3 flex-1">
|
||||
<div className="flex items-center gap-3">
|
||||
<h1 className="text-4xl md:text-5xl font-extrabold bg-gradient-to-r from-slate-900 via-emerald-700 to-slate-900 bg-clip-text text-transparent">
|
||||
<div className="space-y-2 sm:space-y-3 flex-1">
|
||||
<div className="flex items-center gap-2 sm:gap-3 flex-wrap">
|
||||
<h1 className="text-2xl sm:text-3xl md:text-3xl font-extrabold bg-gradient-to-r from-slate-900 via-emerald-700 to-slate-900 bg-clip-text text-transparent">
|
||||
Business Dashboard
|
||||
</h1>
|
||||
<Sparkles className="w-6 h-6 text-emerald-500 animate-pulse" />
|
||||
<Sparkles className="w-4 h-4 sm:w-5 sm:h-5 text-emerald-500 animate-pulse" />
|
||||
</div>
|
||||
<p className="text-gray-600 text-base md:text-lg max-w-2xl leading-relaxed">
|
||||
<p className="text-gray-600 text-xs sm:text-sm md:text-sm max-w-2xl leading-relaxed">
|
||||
Manage invoices, payments, and promotional campaigns
|
||||
</p>
|
||||
</div>
|
||||
@@ -383,36 +393,38 @@ const BusinessDashboardPage: React.FC = () => {
|
||||
</div>
|
||||
|
||||
{}
|
||||
<div className="mt-10 pt-8 border-t border-gradient-to-r from-transparent via-emerald-200/30 to-transparent">
|
||||
<div className="flex flex-wrap gap-3">
|
||||
{tabs.map((tab) => {
|
||||
const Icon = tab.icon;
|
||||
const isActive = activeTab === tab.id;
|
||||
return (
|
||||
<button
|
||||
key={tab.id}
|
||||
onClick={() => setActiveTab(tab.id)}
|
||||
className={`
|
||||
group relative flex items-center gap-3 px-6 py-3.5 rounded-xl font-semibold text-sm
|
||||
transition-all duration-300 overflow-hidden
|
||||
${
|
||||
isActive
|
||||
? 'bg-gradient-to-r from-emerald-500 via-emerald-500 to-purple-600 text-white shadow-xl shadow-emerald-500/40 scale-105'
|
||||
: 'bg-white/80 text-gray-700 border border-gray-200/60 hover:border-emerald-300/60 hover:bg-gradient-to-r hover:from-emerald-50/50 hover:to-purple-50/30 hover:shadow-lg hover:scale-102'
|
||||
}
|
||||
`}
|
||||
>
|
||||
{isActive && (
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/20 to-transparent animate-shimmer"></div>
|
||||
)}
|
||||
<Icon className={`w-5 h-5 transition-transform duration-300 ${isActive ? 'text-white' : 'text-gray-600 group-hover:text-emerald-600 group-hover:scale-110'}`} />
|
||||
<span className="relative z-10">{tab.label}</span>
|
||||
{isActive && (
|
||||
<div className="absolute bottom-0 left-0 right-0 h-1 bg-gradient-to-r from-green-300 via-emerald-400 to-purple-400"></div>
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
<div className="mt-4 sm:mt-6 md:mt-8 lg:mt-10 pt-4 sm:pt-6 md:pt-8 border-t border-gradient-to-r from-transparent via-emerald-200/30 to-transparent">
|
||||
<div className="overflow-x-auto -mx-2 sm:-mx-3 px-2 sm:px-3 scrollbar-hide">
|
||||
<div className="flex gap-2 sm:gap-3 min-w-max sm:min-w-0 sm:flex-wrap">
|
||||
{tabs.map((tab) => {
|
||||
const Icon = tab.icon;
|
||||
const isActive = activeTab === tab.id;
|
||||
return (
|
||||
<button
|
||||
key={tab.id}
|
||||
onClick={() => setActiveTab(tab.id)}
|
||||
className={`
|
||||
group relative flex items-center gap-1.5 sm:gap-2 md:gap-3 px-3 sm:px-4 md:px-6 py-2 sm:py-2.5 md:py-3.5 rounded-lg sm:rounded-xl font-semibold text-xs sm:text-sm flex-shrink-0
|
||||
transition-all duration-300 overflow-hidden
|
||||
${
|
||||
isActive
|
||||
? 'bg-gradient-to-r from-emerald-500 via-emerald-500 to-purple-600 text-white shadow-xl shadow-emerald-500/40 scale-105'
|
||||
: 'bg-white/80 text-gray-700 border border-gray-200/60 hover:border-emerald-300/60 hover:bg-gradient-to-r hover:from-emerald-50/50 hover:to-purple-50/30 hover:shadow-lg hover:scale-102'
|
||||
}
|
||||
`}
|
||||
>
|
||||
{isActive && (
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/20 to-transparent animate-shimmer"></div>
|
||||
)}
|
||||
<Icon className={`w-3.5 h-3.5 sm:w-4 sm:h-4 md:w-5 md:h-5 transition-transform duration-300 flex-shrink-0 ${isActive ? 'text-white' : 'text-gray-600 group-hover:text-emerald-600 group-hover:scale-110'}`} />
|
||||
<span className="relative z-10 whitespace-nowrap">{tab.label}</span>
|
||||
{isActive && (
|
||||
<div className="absolute bottom-0 left-0 right-0 h-0.5 sm:h-1 bg-gradient-to-r from-green-300 via-emerald-400 to-purple-400"></div>
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -420,7 +432,7 @@ const BusinessDashboardPage: React.FC = () => {
|
||||
|
||||
{}
|
||||
{activeTab === 'overview' && (
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 lg:gap-8">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 sm:gap-5 md:gap-6 lg:gap-8">
|
||||
<div
|
||||
onClick={() => setActiveTab('invoices')}
|
||||
className="group relative bg-white/90 backdrop-blur-xl rounded-2xl shadow-xl border border-blue-100/50 p-8 cursor-pointer transition-all duration-300 hover:shadow-2xl hover:scale-105 hover:border-blue-300/60 overflow-hidden"
|
||||
|
||||
Reference in New Issue
Block a user