Suspension realtime added
This commit is contained in:
@@ -149,11 +149,11 @@ const Header = () => {
|
|||||||
<header className="h-16 bg-white/80 backdrop-blur-md border-b border-[#e2e8f0] px-8 flex items-center justify-between sticky top-0 z-50">
|
<header className="h-16 bg-white/80 backdrop-blur-md border-b border-[#e2e8f0] px-8 flex items-center justify-between sticky top-0 z-50">
|
||||||
<div className="flex items-center gap-4 flex-1">
|
<div className="flex items-center gap-4 flex-1">
|
||||||
<div className="relative group w-full max-w-md" ref={searchRef}>
|
<div className="relative group w-full max-w-md" ref={searchRef}>
|
||||||
<Search className="absolute left-3 top-1/2 -translate-y-1/2 text-[#64748b] group-focus-within:text-[#0f4475] transition-colors" size={18} />
|
<Search className="absolute left-3 top-1/2 -translate-y-1/2 text-[#64748b] group-focus-within:text-[#003317] transition-colors" size={18} />
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Search pages, settings, or analytics..."
|
placeholder="Search pages, settings, or analytics..."
|
||||||
className="w-full bg-gray-50 border border-transparent rounded-lg py-2 pl-10 pr-4 text-sm focus:outline-none focus:bg-white focus:border-[#0f4475]/30 transition-all shadow-sm"
|
className="w-full bg-gray-50 border border-transparent rounded-lg py-2 pl-10 pr-4 text-sm focus:outline-none focus:bg-white focus:border-[#003317]/30 transition-all shadow-sm"
|
||||||
value={searchTerm}
|
value={searchTerm}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setSearchTerm(e.target.value);
|
setSearchTerm(e.target.value);
|
||||||
@@ -180,14 +180,14 @@ const Header = () => {
|
|||||||
key={page.path}
|
key={page.path}
|
||||||
onClick={() => handleNavigate(page.path)}
|
onClick={() => handleNavigate(page.path)}
|
||||||
onMouseEnter={() => setSelectedIndex(index)}
|
onMouseEnter={() => setSelectedIndex(index)}
|
||||||
className={`w-full px-4 py-2.5 flex items-center justify-between transition-colors ${index === selectedIndex ? 'bg-[#0f4475]/5' : ''}`}
|
className={`w-full px-4 py-2.5 flex items-center justify-between transition-colors ${index === selectedIndex ? 'bg-[#003317]/5' : ''}`}
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className={`p-1.5 rounded-lg transition-colors ${index === selectedIndex ? 'bg-[#0f4475] text-white' : 'bg-gray-100 text-gray-400'}`}>
|
<div className={`p-1.5 rounded-lg transition-colors ${index === selectedIndex ? 'bg-[#003317] text-white' : 'bg-gray-100 text-gray-400'}`}>
|
||||||
{page.icon}
|
{page.icon}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-left">
|
<div className="text-left">
|
||||||
<div className={`text-sm font-bold ${index === selectedIndex ? 'text-[#0f4475]' : 'text-slate-700'}`}>
|
<div className={`text-sm font-bold ${index === selectedIndex ? 'text-[#003317]' : 'text-slate-700'}`}>
|
||||||
{page.label}
|
{page.label}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-[10px] uppercase tracking-widest font-black opacity-40">
|
<div className="text-[10px] uppercase tracking-widest font-black opacity-40">
|
||||||
@@ -221,7 +221,7 @@ const Header = () => {
|
|||||||
<div className="relative" ref={notificationRef}>
|
<div className="relative" ref={notificationRef}>
|
||||||
<button
|
<button
|
||||||
onClick={() => setShowNotifications(!showNotifications)}
|
onClick={() => setShowNotifications(!showNotifications)}
|
||||||
className={`relative p-2 rounded-lg transition-all group ${showNotifications ? 'bg-indigo-50 text-[#0f4475]' : 'text-[#64748b] hover:text-[#1e293b] hover:bg-gray-100'}`}
|
className={`relative p-2 rounded-lg transition-all group ${showNotifications ? 'bg-indigo-50 text-[#003317]' : 'text-[#64748b] hover:text-[#1e293b] hover:bg-gray-100'}`}
|
||||||
>
|
>
|
||||||
<Bell size={20} />
|
<Bell size={20} />
|
||||||
{notifications.length > 0 && (
|
{notifications.length > 0 && (
|
||||||
@@ -285,7 +285,7 @@ const Header = () => {
|
|||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Link to="/settings" className="p-2 text-[#64748b] hover:text-[#0f4475] hover:bg-indigo-50 rounded-lg transition-all">
|
<Link to="/settings" className="p-2 text-[#64748b] hover:text-[#003317] hover:bg-indigo-50 rounded-lg transition-all">
|
||||||
<Settings size={20} />
|
<Settings size={20} />
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
|
|||||||
@@ -229,14 +229,14 @@ const Sidebar = () => {
|
|||||||
className={cn(
|
className={cn(
|
||||||
"w-full flex items-center justify-between p-2.5 rounded-xl text-sm font-semibold transition-all duration-200 group",
|
"w-full flex items-center justify-between p-2.5 rounded-xl text-sm font-semibold transition-all duration-200 group",
|
||||||
openMenus.includes(item.title)
|
openMenus.includes(item.title)
|
||||||
? "text-[#0f4475] bg-[#0f4475]/5"
|
? "text-[#003317] bg-[#003317]/5"
|
||||||
: "text-[#475569] hover:bg-gray-50 hover:text-[#1e293b]"
|
: "text-[#475569] hover:bg-gray-50 hover:text-[#1e293b]"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<item.icon size={18} strokeWidth={2} className={cn(
|
<item.icon size={18} strokeWidth={2} className={cn(
|
||||||
"transition-colors",
|
"transition-colors",
|
||||||
openMenus.includes(item.title) ? "text-[#0f4475]" : "text-[#64748b] group-hover:text-[#475569]"
|
openMenus.includes(item.title) ? "text-[#003317]" : "text-[#64748b] group-hover:text-[#475569]"
|
||||||
)} />
|
)} />
|
||||||
<span className="tracking-tight">{item.title}</span>
|
<span className="tracking-tight">{item.title}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -265,13 +265,13 @@ const Sidebar = () => {
|
|||||||
onClick={() => toggleNestedMenu(sub.title)}
|
onClick={() => toggleNestedMenu(sub.title)}
|
||||||
className={cn(
|
className={cn(
|
||||||
"w-full flex items-center justify-between py-2 px-4 rounded-lg text-[13px] font-medium transition-all group",
|
"w-full flex items-center justify-between py-2 px-4 rounded-lg text-[13px] font-medium transition-all group",
|
||||||
openNestedMenus.includes(sub.title) ? "text-[#0f4475] bg-[#0f4475]/5" : "text-[#64748b] hover:text-[#1e293b]"
|
openNestedMenus.includes(sub.title) ? "text-[#003317] bg-[#003317]/5" : "text-[#64748b] hover:text-[#1e293b]"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className={cn(
|
<div className={cn(
|
||||||
"w-1.5 h-1.5 rounded-full",
|
"w-1.5 h-1.5 rounded-full",
|
||||||
openNestedMenus.includes(sub.title) ? "bg-[#0f4475]" : "bg-gray-300"
|
openNestedMenus.includes(sub.title) ? "bg-[#003317]" : "bg-gray-300"
|
||||||
)} />
|
)} />
|
||||||
<span>{sub.title}</span>
|
<span>{sub.title}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -295,7 +295,7 @@ const Sidebar = () => {
|
|||||||
to={nested.path!}
|
to={nested.path!}
|
||||||
className={({ isActive }) => cn(
|
className={({ isActive }) => cn(
|
||||||
"flex items-center gap-3 py-1.5 px-4 rounded-lg text-[12px] font-medium transition-all",
|
"flex items-center gap-3 py-1.5 px-4 rounded-lg text-[12px] font-medium transition-all",
|
||||||
isActive ? "text-[#0f4475] bg-white shadow-sm" : "text-[#64748b] hover:text-[#1e293b]"
|
isActive ? "text-[#003317] bg-white shadow-sm" : "text-[#64748b] hover:text-[#1e293b]"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="w-1 h-1 rounded-full bg-gray-300" />
|
<div className="w-1 h-1 rounded-full bg-gray-300" />
|
||||||
@@ -314,7 +314,7 @@ const Sidebar = () => {
|
|||||||
className={({ isActive }) => cn(
|
className={({ isActive }) => cn(
|
||||||
"flex items-center gap-3 py-2 px-4 rounded-lg text-[13px] font-medium transition-all group relative",
|
"flex items-center gap-3 py-2 px-4 rounded-lg text-[13px] font-medium transition-all group relative",
|
||||||
isActive
|
isActive
|
||||||
? "text-white bg-[#0f4475] shadow-md shadow-[#0f4475]/10"
|
? "text-white bg-[#003317] shadow-md shadow-[#003317]/10"
|
||||||
: "text-[#64748b] hover:text-[#1e293b] hover:translate-x-1"
|
: "text-[#64748b] hover:text-[#1e293b] hover:translate-x-1"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@@ -322,13 +322,13 @@ const Sidebar = () => {
|
|||||||
<>
|
<>
|
||||||
<div className={cn(
|
<div className={cn(
|
||||||
"w-1.5 h-1.5 rounded-full transition-all duration-300",
|
"w-1.5 h-1.5 rounded-full transition-all duration-300",
|
||||||
isActive ? "bg-[#0f4475] scale-125" : "bg-gray-300 group-hover:bg-gray-400"
|
isActive ? "bg-[#003317] scale-125" : "bg-gray-300 group-hover:bg-gray-400"
|
||||||
)} />
|
)} />
|
||||||
<span>{sub.title}</span>
|
<span>{sub.title}</span>
|
||||||
{isActive && (
|
{isActive && (
|
||||||
<motion.div
|
<motion.div
|
||||||
layoutId="activeSubMenu"
|
layoutId="activeSubMenu"
|
||||||
className="absolute left-[-1.5px] top-1/4 bottom-1/4 w-[3px] bg-[#0f4475] rounded-full"
|
className="absolute left-[-1.5px] top-1/4 bottom-1/4 w-[3px] bg-[#003317] rounded-full"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
@@ -348,7 +348,7 @@ const Sidebar = () => {
|
|||||||
className={({ isActive }) => cn(
|
className={({ isActive }) => cn(
|
||||||
"flex items-center gap-3 p-2.5 rounded-xl text-sm font-semibold transition-all duration-200 group",
|
"flex items-center gap-3 p-2.5 rounded-xl text-sm font-semibold transition-all duration-200 group",
|
||||||
isActive
|
isActive
|
||||||
? "bg-[#0f4475] text-white shadow-lg shadow-[#0f4475]/15"
|
? "bg-[#003317] text-white shadow-lg shadow-[#003317]/15"
|
||||||
: "text-[#475569] hover:bg-gray-50 hover:text-[#1e293b]"
|
: "text-[#475569] hover:bg-gray-50 hover:text-[#1e293b]"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@@ -388,7 +388,8 @@ const Sidebar = () => {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style dangerouslySetInnerHTML={{ __html: `
|
<style dangerouslySetInnerHTML={{
|
||||||
|
__html: `
|
||||||
.custom-scrollbar::-webkit-scrollbar { width: 4px; }
|
.custom-scrollbar::-webkit-scrollbar { width: 4px; }
|
||||||
.custom-scrollbar::-webkit-scrollbar-track { background: transparent; }
|
.custom-scrollbar::-webkit-scrollbar-track { background: transparent; }
|
||||||
.custom-scrollbar::-webkit-scrollbar-thumb { background: #e2e8f0; border-radius: 10px; }
|
.custom-scrollbar::-webkit-scrollbar-thumb { background: #e2e8f0; border-radius: 10px; }
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ const Dashboard = () => {
|
|||||||
<motion.div
|
<motion.div
|
||||||
animate={{ scale: [1, 1.1, 1], opacity: [0.5, 1, 0.5] }}
|
animate={{ scale: [1, 1.1, 1], opacity: [0.5, 1, 0.5] }}
|
||||||
transition={{ repeat: Infinity, duration: 1.5 }}
|
transition={{ repeat: Infinity, duration: 1.5 }}
|
||||||
className="text-[#0f4475] font-black uppercase tracking-widest text-sm"
|
className="text-[#003317] font-black uppercase tracking-widest text-sm"
|
||||||
>
|
>
|
||||||
Loading Business Intelligence...
|
Loading Business Intelligence...
|
||||||
</motion.div>
|
</motion.div>
|
||||||
@@ -150,7 +150,7 @@ const Dashboard = () => {
|
|||||||
<button title="Navigate back to previous section" className="p-1.5 hover:bg-slate-100 rounded-lg transition-all">
|
<button title="Navigate back to previous section" className="p-1.5 hover:bg-slate-100 rounded-lg transition-all">
|
||||||
<ArrowRight className="rotate-180 text-slate-400" size={18} />
|
<ArrowRight className="rotate-180 text-slate-400" size={18} />
|
||||||
</button>
|
</button>
|
||||||
<h2 className="text-xs font-black text-[#0f4475] uppercase tracking-widest">Dashboard</h2>
|
<h2 className="text-xs font-black text-[#003317] uppercase tracking-widest">Dashboard</h2>
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-2xl font-black text-slate-800">
|
<h1 className="text-2xl font-black text-slate-800">
|
||||||
Good morning, {(() => {
|
Good morning, {(() => {
|
||||||
@@ -194,11 +194,11 @@ const Dashboard = () => {
|
|||||||
key={tab}
|
key={tab}
|
||||||
title={`View ${tab} analysis and trends`}
|
title={`View ${tab} analysis and trends`}
|
||||||
onClick={() => setActiveTab(tab)}
|
onClick={() => setActiveTab(tab)}
|
||||||
className={`pb-4 text-[11px] font-black uppercase tracking-widest transition-all relative ${activeTab === tab ? 'text-[#0f4475]' : 'text-slate-400 hover:text-slate-600'}`}
|
className={`pb-4 text-[11px] font-black uppercase tracking-widest transition-all relative ${activeTab === tab ? 'text-[#003317]' : 'text-slate-400 hover:text-slate-600'}`}
|
||||||
>
|
>
|
||||||
{tab}
|
{tab}
|
||||||
{activeTab === tab && (
|
{activeTab === tab && (
|
||||||
<motion.div layoutId="tabLineMain" className="absolute bottom-0 left-0 right-0 h-0.5 bg-[#0f4475]" />
|
<motion.div layoutId="tabLineMain" className="absolute bottom-0 left-0 right-0 h-0.5 bg-[#003317]" />
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
@@ -206,7 +206,7 @@ const Dashboard = () => {
|
|||||||
|
|
||||||
<div className="flex items-center justify-end mb-4 gap-4">
|
<div className="flex items-center justify-end mb-4 gap-4">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<div className="w-2.5 h-2.5 rounded-full border-2 border-[#0f4475]/30 bg-[#0f4475]/10" />
|
<div className="w-2.5 h-2.5 rounded-full border-2 border-[#003317]/30 bg-[#003317]/10" />
|
||||||
<span className="text-[10px] font-black text-slate-400 uppercase tracking-widest">{timeRange}'s Revenue</span>
|
<span className="text-[10px] font-black text-slate-400 uppercase tracking-widest">{timeRange}'s Revenue</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -285,7 +285,7 @@ const Dashboard = () => {
|
|||||||
key={range}
|
key={range}
|
||||||
title={`Analyze data from ${range.toLowerCase()}`}
|
title={`Analyze data from ${range.toLowerCase()}`}
|
||||||
onClick={() => setTimeRange(range)}
|
onClick={() => setTimeRange(range)}
|
||||||
className={`whitespace-nowrap px-3 py-2 text-[10px] font-black uppercase tracking-widest transition-all rounded-xl ${timeRange === range ? 'text-white bg-[#0f4475] shadow-md shadow-[#0f4475]/20' : 'text-slate-400 hover:text-slate-600'}`}
|
className={`whitespace-nowrap px-3 py-2 text-[10px] font-black uppercase tracking-widest transition-all rounded-xl ${timeRange === range ? 'text-white bg-[#003317] shadow-md shadow-[#003317]/20' : 'text-slate-400 hover:text-slate-600'}`}
|
||||||
>
|
>
|
||||||
{range}
|
{range}
|
||||||
</button>
|
</button>
|
||||||
@@ -297,21 +297,21 @@ const Dashboard = () => {
|
|||||||
type="date"
|
type="date"
|
||||||
value={customDates.from}
|
value={customDates.from}
|
||||||
onChange={(e) => setCustomDates({ ...customDates, from: e.target.value })}
|
onChange={(e) => setCustomDates({ ...customDates, from: e.target.value })}
|
||||||
className="flex-1 bg-white border border-slate-200 rounded-lg px-2 py-1.5 text-[10px] font-bold text-slate-600 outline-none focus:border-[#0f4475]"
|
className="flex-1 bg-white border border-slate-200 rounded-lg px-2 py-1.5 text-[10px] font-bold text-slate-600 outline-none focus:border-[#003317]"
|
||||||
/>
|
/>
|
||||||
<span className="text-slate-300 text-[10px] font-bold">to</span>
|
<span className="text-slate-300 text-[10px] font-bold">to</span>
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
value={customDates.to}
|
value={customDates.to}
|
||||||
onChange={(e) => setCustomDates({ ...customDates, to: e.target.value })}
|
onChange={(e) => setCustomDates({ ...customDates, to: e.target.value })}
|
||||||
className="flex-1 bg-white border border-slate-200 rounded-lg px-2 py-1.5 text-[10px] font-bold text-slate-600 outline-none focus:border-[#0f4475]"
|
className="flex-1 bg-white border border-slate-200 rounded-lg px-2 py-1.5 text-[10px] font-bold text-slate-600 outline-none focus:border-[#003317]"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Total Orders Card */}
|
{/* Total Orders Card */}
|
||||||
<div title="View detailed order volume and throughput" className="bg-white p-6 rounded-[24px] border border-slate-100 shadow-sm relative h-[180px] flex flex-col justify-between group hover:border-[#0f4475]/30 transition-all cursor-pointer">
|
<div title="View detailed order volume and throughput" className="bg-white p-6 rounded-[24px] border border-slate-100 shadow-sm relative h-[180px] flex flex-col justify-between group hover:border-[#003317]/30 transition-all cursor-pointer">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="p-2 bg-amber-50 text-amber-500 rounded-xl group-hover:scale-110 transition-transform">
|
<div className="p-2 bg-amber-50 text-amber-500 rounded-xl group-hover:scale-110 transition-transform">
|
||||||
<ShoppingBag size={20} />
|
<ShoppingBag size={20} />
|
||||||
@@ -325,9 +325,9 @@ const Dashboard = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Expenses Card */}
|
{/* Expenses Card */}
|
||||||
<div title="Track operational expenditures and overhead" className="bg-white p-6 rounded-[24px] border border-slate-100 shadow-sm h-[130px] flex flex-col justify-between group hover:border-[#0f4475]/30 transition-all cursor-pointer">
|
<div title="Track operational expenditures and overhead" className="bg-white p-6 rounded-[24px] border border-slate-100 shadow-sm h-[130px] flex flex-col justify-between group hover:border-[#003317]/30 transition-all cursor-pointer">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="p-2 bg-slate-50 text-[#0f4475] rounded-xl shadow-sm group-hover:bg-[#0f4475]/10 transition-colors">
|
<div className="p-2 bg-slate-50 text-[#003317] rounded-xl shadow-sm group-hover:bg-[#003317]/10 transition-colors">
|
||||||
<Wallet size={20} />
|
<Wallet size={20} />
|
||||||
</div>
|
</div>
|
||||||
<h4 className="text-[11px] font-black text-slate-400 uppercase tracking-widest leading-none">Total Expenses</h4>
|
<h4 className="text-[11px] font-black text-slate-400 uppercase tracking-widest leading-none">Total Expenses</h4>
|
||||||
@@ -410,7 +410,7 @@ const Dashboard = () => {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-8">
|
<div className="mt-8">
|
||||||
<button title="Refresh and sync comprehensive business insights" className="w-full py-3 border border-dashed border-slate-200 rounded-2xl text-[10px] font-black text-slate-400 uppercase tracking-widest hover:border-[#0f4475]/30 hover:text-[#0f4475] transition-all">
|
<button title="Refresh and sync comprehensive business insights" className="w-full py-3 border border-dashed border-slate-200 rounded-2xl text-[10px] font-black text-slate-400 uppercase tracking-widest hover:border-[#003317]/30 hover:text-[#003317] transition-all">
|
||||||
Generate More Insights
|
Generate More Insights
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -420,15 +420,15 @@ const Dashboard = () => {
|
|||||||
<div className="col-span-12 lg:col-span-7 bg-white rounded-[32px] border border-slate-100 shadow-sm p-8">
|
<div className="col-span-12 lg:col-span-7 bg-white rounded-[32px] border border-slate-100 shadow-sm p-8">
|
||||||
<div className="flex items-center justify-between mb-8">
|
<div className="flex items-center justify-between mb-8">
|
||||||
<h3 className="text-sm font-black text-slate-800 tracking-tight uppercase tracking-widest">Store Performance</h3>
|
<h3 className="text-sm font-black text-slate-800 tracking-tight uppercase tracking-widest">Store Performance</h3>
|
||||||
<button title="View detailed metrics for all geographic locations" className="text-[10px] font-black text-[#0f4475] uppercase tracking-widest hover:underline">View All Locations</button>
|
<button title="View detailed metrics for all geographic locations" className="text-[10px] font-black text-[#003317] uppercase tracking-widest hover:underline">View All Locations</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
{(storeOverview.length > 0 ? storeOverview : [{ name: 'No active sales currently', sale: 0, orders: 0, taxes: 0, purchase: 0 }]).map((store: any, idx: number) => (
|
{(storeOverview.length > 0 ? storeOverview : [{ name: 'No active sales currently', sale: 0, orders: 0, taxes: 0, purchase: 0 }]).map((store: any, idx: number) => (
|
||||||
<div key={idx} className="p-6 rounded-[28px] border border-slate-50 bg-slate-50/30 group hover:bg-white hover:shadow-lg hover:border-transparent transition-all border-l-4 border-l-[#0f4475]/30">
|
<div key={idx} className="p-6 rounded-[28px] border border-slate-50 bg-slate-50/30 group hover:bg-white hover:shadow-lg hover:border-transparent transition-all border-l-4 border-l-[#003317]/30">
|
||||||
<p className="text-xs font-black text-slate-800 mb-6 uppercase tracking-widest flex items-center justify-between">
|
<p className="text-xs font-black text-slate-800 mb-6 uppercase tracking-widest flex items-center justify-between">
|
||||||
{store.name}
|
{store.name}
|
||||||
<ArrowRight size={14} className="opacity-0 group-hover:opacity-100 transition-opacity text-[#0f4475]" />
|
<ArrowRight size={14} className="opacity-0 group-hover:opacity-100 transition-opacity text-[#003317]" />
|
||||||
</p>
|
</p>
|
||||||
<div className="grid grid-cols-4 gap-4">
|
<div className="grid grid-cols-4 gap-4">
|
||||||
<div className="space-y-1.5">
|
<div className="space-y-1.5">
|
||||||
@@ -453,7 +453,7 @@ const Dashboard = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-10 flex justify-center">
|
<div className="mt-10 flex justify-center">
|
||||||
<button title="Execute a granular comparison across different store cohorts" className="flex items-center gap-3 px-8 py-3 bg-[#0f4475] text-white text-[11px] font-black uppercase tracking-widest rounded-2xl shadow-xl shadow-[#0f4475]/20 hover:scale-105 transition-all group">
|
<button title="Execute a granular comparison across different store cohorts" className="flex items-center gap-3 px-8 py-3 bg-[#003317] text-white text-[11px] font-black uppercase tracking-widest rounded-2xl shadow-xl shadow-[#003317]/20 hover:scale-105 transition-all group">
|
||||||
Detailed Comparison
|
Detailed Comparison
|
||||||
<ArrowRight size={16} className="group-hover:translate-x-1 transition-transform" />
|
<ArrowRight size={16} className="group-hover:translate-x-1 transition-transform" />
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -95,22 +95,22 @@ const IntentDashboard: React.FC<IntentDashboardProps> = ({ title }) => {
|
|||||||
<div className="p-6 space-y-6 bg-[#f8fafc] min-h-screen font-inter">
|
<div className="p-6 space-y-6 bg-[#f8fafc] min-h-screen font-inter">
|
||||||
{/* Top Header & Filter */}
|
{/* Top Header & Filter */}
|
||||||
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4">
|
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4">
|
||||||
<h1 className="text-xl font-black text-[#0f4475] uppercase tracking-wider flex items-center gap-2">
|
<h1 className="text-xl font-black text-[#003317] uppercase tracking-wider flex items-center gap-2">
|
||||||
<LayoutGrid size={20} />
|
<LayoutGrid size={20} />
|
||||||
{title}
|
{title}
|
||||||
</h1>
|
</h1>
|
||||||
<div className="flex items-center gap-3 bg-white p-1.5 rounded-2xl border border-[#e2e8f0] shadow-sm">
|
<div className="flex items-center gap-3 bg-white p-1.5 rounded-2xl border border-[#e2e8f0] shadow-sm">
|
||||||
<button className="flex items-center gap-2 bg-[#0f4475] text-white px-4 py-2 rounded-xl text-xs font-bold hover:bg-[#1e4e8c] transition-all shadow-md shadow-[#0f4475]/10">
|
<button className="flex items-center gap-2 bg-[#003317] text-white px-4 py-2 rounded-xl text-xs font-bold hover:bg-[#1e4e8c] transition-all shadow-md shadow-[#003317]/10">
|
||||||
<Filter size={14} /> Filter
|
<Filter size={14} /> Filter
|
||||||
</button>
|
</button>
|
||||||
<div className="flex items-center gap-3 px-3 border-l border-[#e2e8f0]">
|
<div className="flex items-center gap-3 px-3 border-l border-[#e2e8f0]">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span className="text-[10px] font-bold text-[#94a3b8] uppercase">Start:</span>
|
<span className="text-[10px] font-bold text-[#94a3b8] uppercase">Start:</span>
|
||||||
<span className="text-xs font-bold text-[#0f4475] bg-[#0f4475]/5 px-2.5 py-1 rounded-lg">2026-03-10</span>
|
<span className="text-xs font-bold text-[#003317] bg-[#003317]/5 px-2.5 py-1 rounded-lg">2026-03-10</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span className="text-[10px] font-bold text-[#94a3b8] uppercase">End:</span>
|
<span className="text-[10px] font-bold text-[#94a3b8] uppercase">End:</span>
|
||||||
<span className="text-xs font-bold text-[#0f4475] bg-[#0f4475]/5 px-2.5 py-1 rounded-lg">2026-04-10</span>
|
<span className="text-xs font-bold text-[#003317] bg-[#003317]/5 px-2.5 py-1 rounded-lg">2026-04-10</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -118,7 +118,7 @@ const IntentDashboard: React.FC<IntentDashboardProps> = ({ title }) => {
|
|||||||
|
|
||||||
{/* Stats Grid */}
|
{/* Stats Grid */}
|
||||||
<div className="flex flex-wrap gap-4 relative">
|
<div className="flex flex-wrap gap-4 relative">
|
||||||
{loading && <div className="absolute inset-0 bg-white/50 backdrop-blur-[1px] z-10 rounded-2xl flex items-center justify-center"><RefreshCw className="animate-spin text-[#0f4475]" size={24} /></div>}
|
{loading && <div className="absolute inset-0 bg-white/50 backdrop-blur-[1px] z-10 rounded-2xl flex items-center justify-center"><RefreshCw className="animate-spin text-[#003317]" size={24} /></div>}
|
||||||
<StatCard icon={Clock} label="Open" value={stats?.openCount || 0} color="bg-cyan-500" />
|
<StatCard icon={Clock} label="Open" value={stats?.openCount || 0} color="bg-cyan-500" />
|
||||||
<StatCard icon={Boxes} label="Open Items" value={stats?.openItems || 0} color="bg-indigo-500" />
|
<StatCard icon={Boxes} label="Open Items" value={stats?.openItems || 0} color="bg-indigo-500" />
|
||||||
<StatCard icon={Wallet} label="Payable Amount" value={`₹${stats?.payableAmount?.toLocaleString() || 0}`} color="bg-amber-500" />
|
<StatCard icon={Wallet} label="Payable Amount" value={`₹${stats?.payableAmount?.toLocaleString() || 0}`} color="bg-amber-500" />
|
||||||
@@ -133,12 +133,12 @@ const IntentDashboard: React.FC<IntentDashboardProps> = ({ title }) => {
|
|||||||
<div className="flex items-center justify-between mb-8">
|
<div className="flex items-center justify-between mb-8">
|
||||||
<h3 className="text-sm font-black text-[#1e293b] flex items-center gap-2">
|
<h3 className="text-sm font-black text-[#1e293b] flex items-center gap-2">
|
||||||
Orders in the last 30 days
|
Orders in the last 30 days
|
||||||
<button onClick={fetchStats} className={`text-[#94a3b8] hover:text-[#0f4475] transition-colors ${loading ? 'animate-spin' : ''}`}><RefreshCw size={14} /></button>
|
<button onClick={fetchStats} className={`text-[#94a3b8] hover:text-[#003317] transition-colors ${loading ? 'animate-spin' : ''}`}><RefreshCw size={14} /></button>
|
||||||
</h3>
|
</h3>
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
{['Open', 'Closed', 'Total'].map((l, i) => (
|
{['Open', 'Closed', 'Total'].map((l, i) => (
|
||||||
<div key={l} className="flex items-center gap-1.5">
|
<div key={l} className="flex items-center gap-1.5">
|
||||||
<div className={`w-2.5 h-2.5 rounded-full ${i === 0 ? 'bg-amber-500' : i === 1 ? 'bg-rose-500' : 'bg-[#0f4475]'}`} />
|
<div className={`w-2.5 h-2.5 rounded-full ${i === 0 ? 'bg-amber-500' : i === 1 ? 'bg-rose-500' : 'bg-[#003317]'}`} />
|
||||||
<span className="text-[10px] font-bold text-[#64748b]">{l}</span>
|
<span className="text-[10px] font-bold text-[#64748b]">{l}</span>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@@ -155,7 +155,7 @@ const IntentDashboard: React.FC<IntentDashboardProps> = ({ title }) => {
|
|||||||
itemStyle={{ fontWeight: 'bold' }}
|
itemStyle={{ fontWeight: 'bold' }}
|
||||||
/>
|
/>
|
||||||
<Area type="monotone" dataKey="open" stroke="#f59e0b" fill="#f59e0b" fillOpacity={0.05} strokeWidth={2} />
|
<Area type="monotone" dataKey="open" stroke="#f59e0b" fill="#f59e0b" fillOpacity={0.05} strokeWidth={2} />
|
||||||
<Area type="monotone" dataKey="total" stroke="#0f4475" fill="#0f4475" fillOpacity={0.05} strokeWidth={2} />
|
<Area type="monotone" dataKey="total" stroke="#003317" fill="#003317" fillOpacity={0.05} strokeWidth={2} />
|
||||||
</AreaChart>
|
</AreaChart>
|
||||||
</ResponsiveContainer>
|
</ResponsiveContainer>
|
||||||
</div>
|
</div>
|
||||||
@@ -177,7 +177,7 @@ const IntentDashboard: React.FC<IntentDashboardProps> = ({ title }) => {
|
|||||||
<span className="text-[11px] font-black text-[#64748b] tracking-wider">{s.label}</span>
|
<span className="text-[11px] font-black text-[#64748b] tracking-wider">{s.label}</span>
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<span className="text-xs font-black text-[#1e293b]">{s.value}</span>
|
<span className="text-xs font-black text-[#1e293b]">{s.value}</span>
|
||||||
<button className="text-[#94a3b8] group-hover:text-[#0f4475] opacity-0 group-hover:opacity-100 transition-all"><ArrowRight size={14} /></button>
|
<button className="text-[#94a3b8] group-hover:text-[#003317] opacity-0 group-hover:opacity-100 transition-all"><ArrowRight size={14} /></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@@ -199,7 +199,7 @@ const IntentDashboard: React.FC<IntentDashboardProps> = ({ title }) => {
|
|||||||
<button
|
<button
|
||||||
key={t}
|
key={t}
|
||||||
onClick={() => setFilterTab(t)}
|
onClick={() => setFilterTab(t)}
|
||||||
className={`whitespace-nowrap px-3 py-1.5 rounded-lg text-[10px] font-bold transition-all ${filterTab === t ? 'bg-[#0f4475] text-white shadow-md shadow-[#0f4475]/20' : 'bg-[#f8fafc] text-[#64748b] hover:bg-[#f1f5f9]'}`}
|
className={`whitespace-nowrap px-3 py-1.5 rounded-lg text-[10px] font-bold transition-all ${filterTab === t ? 'bg-[#003317] text-white shadow-md shadow-[#003317]/20' : 'bg-[#f8fafc] text-[#64748b] hover:bg-[#f1f5f9]'}`}
|
||||||
>
|
>
|
||||||
{t}
|
{t}
|
||||||
</button>
|
</button>
|
||||||
@@ -228,8 +228,7 @@ const IntentDashboard: React.FC<IntentDashboardProps> = ({ title }) => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between items-end">
|
<div className="flex justify-between items-end">
|
||||||
<span className="text-[10px] font-semibold text-[#94a3b8]">{o.date ? format(new Date(o.date), 'MMM dd, yyyy HH:mm') : 'N/A'}</span>
|
<span className="text-[10px] font-semibold text-[#94a3b8]">{o.date ? format(new Date(o.date), 'MMM dd, yyyy HH:mm') : 'N/A'}</span>
|
||||||
<span className={`text-[9px] font-black px-1.5 py-0.5 rounded uppercase ${
|
<span className={`text-[9px] font-black px-1.5 py-0.5 rounded uppercase ${o.status === 'CLOSE' || o.status === 'CLOSED' ? 'text-rose-600 bg-rose-50' :
|
||||||
o.status === 'CLOSE' || o.status === 'CLOSED' ? 'text-rose-600 bg-rose-50' :
|
|
||||||
o.status === 'OPEN' ? 'text-amber-600 bg-amber-50' :
|
o.status === 'OPEN' ? 'text-amber-600 bg-amber-50' :
|
||||||
o.status === 'BILLED' ? 'text-indigo-600 bg-indigo-50' :
|
o.status === 'BILLED' ? 'text-indigo-600 bg-indigo-50' :
|
||||||
'text-emerald-700 bg-emerald-100'
|
'text-emerald-700 bg-emerald-100'
|
||||||
@@ -255,12 +254,12 @@ const IntentDashboard: React.FC<IntentDashboardProps> = ({ title }) => {
|
|||||||
className="w-full flex items-center justify-between p-3.5 bg-[#f8fafc] border border-[#f1f5f9] rounded-xl hover:bg-gray-50 transition-all group"
|
className="w-full flex items-center justify-between p-3.5 bg-[#f8fafc] border border-[#f1f5f9] rounded-xl hover:bg-gray-50 transition-all group"
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="p-2 bg-white rounded-lg shadow-sm text-[#94a3b8] group-hover:text-[#0f4475] transition-colors">
|
<div className="p-2 bg-white rounded-lg shadow-sm text-[#94a3b8] group-hover:text-[#003317] transition-colors">
|
||||||
<l.icon size={16} />
|
<l.icon size={16} />
|
||||||
</div>
|
</div>
|
||||||
<span className="text-xs font-bold text-[#64748b]">{l.label}</span>
|
<span className="text-xs font-bold text-[#64748b]">{l.label}</span>
|
||||||
</div>
|
</div>
|
||||||
<ChevronRight size={14} className="text-[#cbd5e1] group-hover:text-[#0f4475] transition-all" />
|
<ChevronRight size={14} className="text-[#cbd5e1] group-hover:text-[#003317] transition-all" />
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -127,19 +127,19 @@ const IntentList: React.FC<IntentListProps> = ({ title }) => {
|
|||||||
{/* Header Bar */}
|
{/* Header Bar */}
|
||||||
<div className="flex items-center justify-between mb-8 bg-white p-4 rounded-3xl border border-[#e2e8f0] shadow-sm">
|
<div className="flex items-center justify-between mb-8 bg-white p-4 rounded-3xl border border-[#e2e8f0] shadow-sm">
|
||||||
<div className="flex items-center gap-6">
|
<div className="flex items-center gap-6">
|
||||||
<button className="p-2.5 bg-gray-50 rounded-xl text-[#0f4475] hover:bg-[#0f4475] hover:text-white transition-all shadow-sm">
|
<button className="p-2.5 bg-gray-50 rounded-xl text-[#003317] hover:bg-[#003317] hover:text-white transition-all shadow-sm">
|
||||||
<ArrowLeft size={18} />
|
<ArrowLeft size={18} />
|
||||||
</button>
|
</button>
|
||||||
<h1 className="text-xl font-black text-[#0f4475] uppercase tracking-wider">{title}</h1>
|
<h1 className="text-xl font-black text-[#003317] uppercase tracking-wider">{title}</h1>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
{title === 'RECEIVES' && (
|
{title === 'RECEIVES' && (
|
||||||
<button className="bg-[#0f4475] text-white px-5 py-2.5 rounded-2xl text-xs font-black shadow-lg shadow-[#0f4475]/20 hover:bg-[#1e4e8c] transition-all">
|
<button className="bg-[#003317] text-white px-5 py-2.5 rounded-2xl text-xs font-black shadow-lg shadow-[#003317]/20 hover:bg-[#1e4e8c] transition-all">
|
||||||
Summary
|
Summary
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<select className="bg-gray-50 border border-[#e2e8f0] rounded-2xl px-5 py-2.5 text-xs font-bold text-[#64748b] outline-none appearance-none min-w-[150px] cursor-pointer focus:bg-white focus:ring-2 focus:ring-[#0f4475]/10">
|
<select className="bg-gray-50 border border-[#e2e8f0] rounded-2xl px-5 py-2.5 text-xs font-bold text-[#64748b] outline-none appearance-none min-w-[150px] cursor-pointer focus:bg-white focus:ring-2 focus:ring-[#003317]/10">
|
||||||
<option>Status</option>
|
<option>Status</option>
|
||||||
<option>Approved</option>
|
<option>Approved</option>
|
||||||
<option>Pending</option>
|
<option>Pending</option>
|
||||||
@@ -147,7 +147,7 @@ const IntentList: React.FC<IntentListProps> = ({ title }) => {
|
|||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
onClick={() => setShowAddModal(true)}
|
onClick={() => setShowAddModal(true)}
|
||||||
className="p-2.5 bg-[#0f4475] text-white rounded-xl shadow-lg shadow-[#0f4475]/20 hover:scale-105 transition-all"
|
className="p-2.5 bg-[#003317] text-white rounded-xl shadow-lg shadow-[#003317]/20 hover:scale-105 transition-all"
|
||||||
>
|
>
|
||||||
<Plus size={18} />
|
<Plus size={18} />
|
||||||
</button>
|
</button>
|
||||||
@@ -173,7 +173,7 @@ const IntentList: React.FC<IntentListProps> = ({ title }) => {
|
|||||||
{loading ? (
|
{loading ? (
|
||||||
<tr>
|
<tr>
|
||||||
<td colSpan={7} className="py-20 text-center">
|
<td colSpan={7} className="py-20 text-center">
|
||||||
<RefreshCw className="animate-spin text-[#0f4475] mx-auto mb-2" size={32} />
|
<RefreshCw className="animate-spin text-[#003317] mx-auto mb-2" size={32} />
|
||||||
<p className="text-sm font-bold text-[#64748b]">Fetching orders...</p>
|
<p className="text-sm font-bold text-[#64748b]">Fetching orders...</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -196,7 +196,7 @@ const IntentList: React.FC<IntentListProps> = ({ title }) => {
|
|||||||
<td className="px-8 py-6">
|
<td className="px-8 py-6">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span className="text-xs font-black text-[#1e293b]">{row.purchaseId || row.id}</span>
|
<span className="text-xs font-black text-[#1e293b]">{row.purchaseId || row.id}</span>
|
||||||
<ChevronsRight size={12} className="text-[#cbd5e1] group-hover:text-[#0f4475] transition-colors" />
|
<ChevronsRight size={12} className="text-[#cbd5e1] group-hover:text-[#003317] transition-colors" />
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td className="px-8 py-6 text-xs font-semibold text-[#64748b]">
|
<td className="px-8 py-6 text-xs font-semibold text-[#64748b]">
|
||||||
@@ -214,7 +214,7 @@ const IntentList: React.FC<IntentListProps> = ({ title }) => {
|
|||||||
</td>
|
</td>
|
||||||
<td className="px-8 py-6">
|
<td className="px-8 py-6">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<button className="p-2 text-[#94a3b8] hover:bg-[#0f4475] hover:text-white rounded-lg transition-all">
|
<button className="p-2 text-[#94a3b8] hover:bg-[#003317] hover:text-white rounded-lg transition-all">
|
||||||
<Eye size={16} />
|
<Eye size={16} />
|
||||||
</button>
|
</button>
|
||||||
<button className="p-2 text-[#94a3b8] hover:bg-gray-100 rounded-lg transition-all">
|
<button className="p-2 text-[#94a3b8] hover:bg-gray-100 rounded-lg transition-all">
|
||||||
@@ -250,7 +250,7 @@ const IntentList: React.FC<IntentListProps> = ({ title }) => {
|
|||||||
|
|
||||||
{/* Modern Add Order Modal */}
|
{/* Modern Add Order Modal */}
|
||||||
{showAddModal && (
|
{showAddModal && (
|
||||||
<div className="fixed inset-0 bg-[#0f4475]/30 backdrop-blur-md z-[100] flex items-center justify-center p-4">
|
<div className="fixed inset-0 bg-[#003317]/30 backdrop-blur-md z-[100] flex items-center justify-center p-4">
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, scale: 0.95, y: 20 }}
|
initial={{ opacity: 0, scale: 0.95, y: 20 }}
|
||||||
animate={{ opacity: 1, scale: 1, y: 0 }}
|
animate={{ opacity: 1, scale: 1, y: 0 }}
|
||||||
@@ -259,7 +259,7 @@ const IntentList: React.FC<IntentListProps> = ({ title }) => {
|
|||||||
{/* Modal Header */}
|
{/* Modal Header */}
|
||||||
<div className="px-10 py-8 border-b border-[#f1f5f9] flex justify-between items-center bg-gray-50/30">
|
<div className="px-10 py-8 border-b border-[#f1f5f9] flex justify-between items-center bg-gray-50/30">
|
||||||
<div className="flex items-center gap-5">
|
<div className="flex items-center gap-5">
|
||||||
<div className="w-14 h-14 bg-gradient-to-br from-[#0f4475] to-[#1e4e8c] rounded-2xl flex items-center justify-center text-white shadow-xl shadow-[#0f4475]/20">
|
<div className="w-14 h-14 bg-gradient-to-br from-[#003317] to-[#1e4e8c] rounded-2xl flex items-center justify-center text-white shadow-xl shadow-[#003317]/20">
|
||||||
<ShoppingCart size={24} />
|
<ShoppingCart size={24} />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -280,11 +280,11 @@ const IntentList: React.FC<IntentListProps> = ({ title }) => {
|
|||||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-8">
|
<div className="grid grid-cols-1 md:grid-cols-4 gap-8">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<label className="text-[10px] font-black text-[#94a3b8] uppercase tracking-widest ml-1">Order ID</label>
|
<label className="text-[10px] font-black text-[#94a3b8] uppercase tracking-widest ml-1">Order ID</label>
|
||||||
<input type="text" value={newOrder.purchaseId} readOnly className="w-full px-5 py-3.5 bg-gray-50 border border-[#e2e8f0] rounded-2xl text-sm font-black text-[#0f4475] outline-none" />
|
<input type="text" value={newOrder.purchaseId} readOnly className="w-full px-5 py-3.5 bg-gray-50 border border-[#e2e8f0] rounded-2xl text-sm font-black text-[#003317] outline-none" />
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<label className="text-[10px] font-black text-[#94a3b8] uppercase tracking-widest ml-1">Date</label>
|
<label className="text-[10px] font-black text-[#94a3b8] uppercase tracking-widest ml-1">Date</label>
|
||||||
<input type="date" value={newOrder.date} onChange={e => setNewOrder({...newOrder, date: e.target.value})} className="w-full px-5 py-3.5 bg-white border border-[#e2e8f0] rounded-2xl text-sm font-bold text-[#1e293b] outline-none focus:ring-4 focus:ring-[#0f4475]/5 focus:border-[#0f4475] transition-all" />
|
<input type="date" value={newOrder.date} onChange={e => setNewOrder({ ...newOrder, date: e.target.value })} className="w-full px-5 py-3.5 bg-white border border-[#e2e8f0] rounded-2xl text-sm font-bold text-[#1e293b] outline-none focus:ring-4 focus:ring-[#003317]/5 focus:border-[#003317] transition-all" />
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<label className="text-[10px] font-black text-[#94a3b8] uppercase tracking-widest ml-1">Select Vendor</label>
|
<label className="text-[10px] font-black text-[#94a3b8] uppercase tracking-widest ml-1">Select Vendor</label>
|
||||||
@@ -292,7 +292,7 @@ const IntentList: React.FC<IntentListProps> = ({ title }) => {
|
|||||||
required
|
required
|
||||||
value={newOrder.vendorId}
|
value={newOrder.vendorId}
|
||||||
onChange={e => setNewOrder({ ...newOrder, vendorId: e.target.value })}
|
onChange={e => setNewOrder({ ...newOrder, vendorId: e.target.value })}
|
||||||
className="w-full px-5 py-3.5 bg-white border border-[#e2e8f0] rounded-2xl text-sm font-bold text-[#1e293b] outline-none focus:ring-4 focus:ring-[#0f4475]/5 focus:border-[#0f4475] transition-all appearance-none cursor-pointer"
|
className="w-full px-5 py-3.5 bg-white border border-[#e2e8f0] rounded-2xl text-sm font-bold text-[#1e293b] outline-none focus:ring-4 focus:ring-[#003317]/5 focus:border-[#003317] transition-all appearance-none cursor-pointer"
|
||||||
>
|
>
|
||||||
<option value="">Choose Supplier</option>
|
<option value="">Choose Supplier</option>
|
||||||
{vendors.map(v => <option key={v.id} value={v.id}>{v.name}</option>)}
|
{vendors.map(v => <option key={v.id} value={v.id}>{v.name}</option>)}
|
||||||
@@ -311,7 +311,7 @@ const IntentList: React.FC<IntentListProps> = ({ title }) => {
|
|||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex items-center justify-between px-2">
|
<div className="flex items-center justify-between px-2">
|
||||||
<h3 className="text-xs font-black text-[#1e293b] uppercase tracking-[0.2em]">Order Line Items</h3>
|
<h3 className="text-xs font-black text-[#1e293b] uppercase tracking-[0.2em]">Order Line Items</h3>
|
||||||
<button type="button" onClick={handleAddItem} className="flex items-center gap-2 px-4 py-2 bg-[#0f4475]/5 text-[#0f4475] rounded-xl text-[11px] font-black hover:bg-[#0f4475] hover:text-white transition-all">
|
<button type="button" onClick={handleAddItem} className="flex items-center gap-2 px-4 py-2 bg-[#003317]/5 text-[#003317] rounded-xl text-[11px] font-black hover:bg-[#003317] hover:text-white transition-all">
|
||||||
<Plus size={14} /> Add Product
|
<Plus size={14} /> Add Product
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -340,7 +340,7 @@ const IntentList: React.FC<IntentListProps> = ({ title }) => {
|
|||||||
<input type="number" step="0.01" value={item.rate} onChange={e => handleItemChange(idx, 'rate', parseFloat(e.target.value))} className="w-full bg-transparent text-sm font-bold text-[#1e293b] outline-none" />
|
<input type="number" step="0.01" value={item.rate} onChange={e => handleItemChange(idx, 'rate', parseFloat(e.target.value))} className="w-full bg-transparent text-sm font-bold text-[#1e293b] outline-none" />
|
||||||
</td>
|
</td>
|
||||||
<td className="px-6 py-4">
|
<td className="px-6 py-4">
|
||||||
<span className="text-sm font-black text-[#0f4475]">₹{item.total.toLocaleString()}</span>
|
<span className="text-sm font-black text-[#003317]">₹{item.total.toLocaleString()}</span>
|
||||||
</td>
|
</td>
|
||||||
<td className="px-6 py-4">
|
<td className="px-6 py-4">
|
||||||
<button type="button" onClick={() => setNewOrder({ ...newOrder, items: newOrder.items.filter((_, i) => i !== idx) })} className="p-2 text-[#cbd5e1] hover:text-[#ef4444] transition-colors">
|
<button type="button" onClick={() => setNewOrder({ ...newOrder, items: newOrder.items.filter((_, i) => i !== idx) })} className="p-2 text-[#cbd5e1] hover:text-[#ef4444] transition-colors">
|
||||||
@@ -359,11 +359,11 @@ const IntentList: React.FC<IntentListProps> = ({ title }) => {
|
|||||||
<div className="md:col-span-7 space-y-6">
|
<div className="md:col-span-7 space-y-6">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<label className="text-[10px] font-black text-[#94a3b8] uppercase tracking-widest ml-1">Reference ID / PO Number</label>
|
<label className="text-[10px] font-black text-[#94a3b8] uppercase tracking-widest ml-1">Reference ID / PO Number</label>
|
||||||
<input type="text" value={newOrder.referenceId} onChange={e => setNewOrder({...newOrder, referenceId: e.target.value})} className="w-full px-5 py-4 bg-white border border-[#e2e8f0] rounded-2xl text-sm font-bold outline-none focus:border-[#0f4475] transition-all" placeholder="Enter external reference number if any..." />
|
<input type="text" value={newOrder.referenceId} onChange={e => setNewOrder({ ...newOrder, referenceId: e.target.value })} className="w-full px-5 py-4 bg-white border border-[#e2e8f0] rounded-2xl text-sm font-bold outline-none focus:border-[#003317] transition-all" placeholder="Enter external reference number if any..." />
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<label className="text-[10px] font-black text-[#94a3b8] uppercase tracking-widest ml-1">Special Instructions</label>
|
<label className="text-[10px] font-black text-[#94a3b8] uppercase tracking-widest ml-1">Special Instructions</label>
|
||||||
<textarea rows={3} value={newOrder.instruction} onChange={e => setNewOrder({...newOrder, instruction: e.target.value})} className="w-full px-5 py-4 bg-white border border-[#e2e8f0] rounded-2xl text-sm font-bold outline-none focus:border-[#0f4475] transition-all resize-none" placeholder="Add any specific delivery or quality requirements..." />
|
<textarea rows={3} value={newOrder.instruction} onChange={e => setNewOrder({ ...newOrder, instruction: e.target.value })} className="w-full px-5 py-4 bg-white border border-[#e2e8f0] rounded-2xl text-sm font-bold outline-none focus:border-[#003317] transition-all resize-none" placeholder="Add any specific delivery or quality requirements..." />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -407,7 +407,7 @@ const IntentList: React.FC<IntentListProps> = ({ title }) => {
|
|||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={isSaving}
|
disabled={isSaving}
|
||||||
className="flex-1 px-10 py-5 bg-gradient-to-r from-[#0f4475] to-[#1e4e8c] text-white font-black rounded-2xl shadow-2xl shadow-[#0f4475]/30 hover:scale-[1.02] active:scale-[0.98] transition-all flex items-center justify-center gap-4 uppercase tracking-[0.2em] text-[11px]"
|
className="flex-1 px-10 py-5 bg-gradient-to-r from-[#003317] to-[#1e4e8c] text-white font-black rounded-2xl shadow-2xl shadow-[#003317]/30 hover:scale-[1.02] active:scale-[0.98] transition-all flex items-center justify-center gap-4 uppercase tracking-[0.2em] text-[11px]"
|
||||||
>
|
>
|
||||||
{isSaving ? <Loader2 className="animate-spin" size={18} /> : (
|
{isSaving ? <Loader2 className="animate-spin" size={18} /> : (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ const ManageCoupons = () => {
|
|||||||
<motion.div
|
<motion.div
|
||||||
animate={{ scale: [1, 1.1, 1], opacity: [0.5, 1, 0.5] }}
|
animate={{ scale: [1, 1.1, 1], opacity: [0.5, 1, 0.5] }}
|
||||||
transition={{ repeat: Infinity, duration: 1.5 }}
|
transition={{ repeat: Infinity, duration: 1.5 }}
|
||||||
className="text-[#0f4475] font-black uppercase tracking-widest text-sm flex flex-col items-center gap-4"
|
className="text-[#003317] font-black uppercase tracking-widest text-sm flex flex-col items-center gap-4"
|
||||||
>
|
>
|
||||||
<Ticket size={32} className="animate-pulse" />
|
<Ticket size={32} className="animate-pulse" />
|
||||||
Synchronizing Coupon Network...
|
Synchronizing Coupon Network...
|
||||||
@@ -124,7 +124,7 @@ const ManageCoupons = () => {
|
|||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<div className="flex items-center gap-2 mb-1">
|
<div className="flex items-center gap-2 mb-1">
|
||||||
<h2 className="text-xs font-black text-[#0f4475] uppercase tracking-widest">Ritz Rewards</h2>
|
<h2 className="text-xs font-black text-[#003317] uppercase tracking-widest">Ritz Rewards</h2>
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-2xl font-black text-slate-800">Coupon Codes</h1>
|
<h1 className="text-2xl font-black text-slate-800">Coupon Codes</h1>
|
||||||
<p className="text-[10px] text-slate-400 font-medium flex items-center gap-1.5 uppercase tracking-wider">
|
<p className="text-[10px] text-slate-400 font-medium flex items-center gap-1.5 uppercase tracking-wider">
|
||||||
@@ -134,7 +134,7 @@ const ManageCoupons = () => {
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={() => setIsModalOpen(true)}
|
onClick={() => setIsModalOpen(true)}
|
||||||
className="flex items-center gap-2 bg-[#0f4475] text-white px-6 py-2.5 rounded-xl text-xs font-black uppercase tracking-widest hover:scale-105 transition-all shadow-lg shadow-[#0f4475]/20 active:scale-95"
|
className="flex items-center gap-2 bg-[#003317] text-white px-6 py-2.5 rounded-xl text-xs font-black uppercase tracking-widest hover:scale-105 transition-all shadow-lg shadow-[#003317]/20 active:scale-95"
|
||||||
>
|
>
|
||||||
<Plus size={18} />
|
<Plus size={18} />
|
||||||
Generate New Code
|
Generate New Code
|
||||||
@@ -143,9 +143,9 @@ const ManageCoupons = () => {
|
|||||||
|
|
||||||
{/* Analytics Summary */}
|
{/* Analytics Summary */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||||
<div className="bg-white p-6 rounded-[2rem] border border-slate-100 shadow-sm group hover:border-[#0f4475]/30 transition-all">
|
<div className="bg-white p-6 rounded-[2rem] border border-slate-100 shadow-sm group hover:border-[#003317]/30 transition-all">
|
||||||
<div className="flex justify-between items-start mb-4">
|
<div className="flex justify-between items-start mb-4">
|
||||||
<div className="p-3 bg-indigo-50 text-[#0f4475] rounded-xl">
|
<div className="p-3 bg-indigo-50 text-[#003317] rounded-xl">
|
||||||
<Tag size={20} />
|
<Tag size={20} />
|
||||||
</div>
|
</div>
|
||||||
<span className="text-[10px] font-black text-indigo-400 uppercase tracking-widest">Active Pool</span>
|
<span className="text-[10px] font-black text-indigo-400 uppercase tracking-widest">Active Pool</span>
|
||||||
@@ -197,9 +197,9 @@ const ManageCoupons = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex gap-6">
|
<div className="flex gap-6">
|
||||||
<div className={`w-24 h-24 rounded-3xl flex flex-col items-center justify-center border-2 border-dashed ${coupon.isActive ? 'bg-indigo-50/50 border-[#0f4475]/20' : 'bg-slate-100 border-slate-300'}`}>
|
<div className={`w-24 h-24 rounded-3xl flex flex-col items-center justify-center border-2 border-dashed ${coupon.isActive ? 'bg-indigo-50/50 border-[#003317]/20' : 'bg-slate-100 border-slate-300'}`}>
|
||||||
<Ticket size={24} className={coupon.isActive ? 'text-[#0f4475]' : 'text-slate-400'} />
|
<Ticket size={24} className={coupon.isActive ? 'text-[#003317]' : 'text-slate-400'} />
|
||||||
<span className={`text-[10px] font-black mt-2 uppercase tracking-tight ${coupon.isActive ? 'text-[#0f4475]' : 'text-slate-500'}`}>Redeem</span>
|
<span className={`text-[10px] font-black mt-2 uppercase tracking-tight ${coupon.isActive ? 'text-[#003317]' : 'text-slate-500'}`}>Redeem</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
@@ -241,7 +241,7 @@ const ManageCoupons = () => {
|
|||||||
<motion.div
|
<motion.div
|
||||||
initial={{ width: 0 }}
|
initial={{ width: 0 }}
|
||||||
animate={{ width: `${(coupon.currentClaims / coupon.maxClaims) * 100}%` }}
|
animate={{ width: `${(coupon.currentClaims / coupon.maxClaims) * 100}%` }}
|
||||||
className={`h-full rounded-full ${coupon.isActive ? 'bg-[#0f4475]' : 'bg-slate-400'}`}
|
className={`h-full rounded-full ${coupon.isActive ? 'bg-[#003317]' : 'bg-slate-400'}`}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -277,7 +277,7 @@ const ManageCoupons = () => {
|
|||||||
animate={{ opacity: 1 }}
|
animate={{ opacity: 1 }}
|
||||||
exit={{ opacity: 0 }}
|
exit={{ opacity: 0 }}
|
||||||
onClick={() => setIsModalOpen(false)}
|
onClick={() => setIsModalOpen(false)}
|
||||||
className="absolute inset-0 bg-[#0f4475]/40 backdrop-blur-md"
|
className="absolute inset-0 bg-[#003317]/40 backdrop-blur-md"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<motion.div
|
<motion.div
|
||||||
@@ -288,7 +288,7 @@ const ManageCoupons = () => {
|
|||||||
>
|
>
|
||||||
<div className="flex justify-between items-center mb-8">
|
<div className="flex justify-between items-center mb-8">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="p-2 bg-indigo-50 text-[#0f4475] rounded-xl">
|
<div className="p-2 bg-indigo-50 text-[#003317] rounded-xl">
|
||||||
<Ticket size={24} />
|
<Ticket size={24} />
|
||||||
</div>
|
</div>
|
||||||
<h2 className="text-xl font-black text-slate-800 uppercase tracking-tight">Generate Code</h2>
|
<h2 className="text-xl font-black text-slate-800 uppercase tracking-tight">Generate Code</h2>
|
||||||
@@ -308,7 +308,7 @@ const ManageCoupons = () => {
|
|||||||
placeholder="e.g. WELCOME50"
|
placeholder="e.g. WELCOME50"
|
||||||
value={newCoupon.code}
|
value={newCoupon.code}
|
||||||
onChange={(e) => setNewCoupon({ ...newCoupon, code: e.target.value.toUpperCase() })}
|
onChange={(e) => setNewCoupon({ ...newCoupon, code: e.target.value.toUpperCase() })}
|
||||||
className="w-full bg-slate-50 border border-slate-100 rounded-2xl px-4 py-3 text-sm font-bold text-slate-800 outline-none focus:border-[#0f4475] transition-all"
|
className="w-full bg-slate-50 border border-slate-100 rounded-2xl px-4 py-3 text-sm font-bold text-slate-800 outline-none focus:border-[#003317] transition-all"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-1.5">
|
<div className="space-y-1.5">
|
||||||
@@ -319,7 +319,7 @@ const ManageCoupons = () => {
|
|||||||
placeholder="Amount"
|
placeholder="Amount"
|
||||||
value={newCoupon.rewardAmount}
|
value={newCoupon.rewardAmount}
|
||||||
onChange={(e) => setNewCoupon({ ...newCoupon, rewardAmount: e.target.value })}
|
onChange={(e) => setNewCoupon({ ...newCoupon, rewardAmount: e.target.value })}
|
||||||
className="w-full bg-slate-50 border border-slate-100 rounded-2xl px-4 py-3 text-sm font-bold text-slate-800 outline-none focus:border-[#0f4475] transition-all"
|
className="w-full bg-slate-50 border border-slate-100 rounded-2xl px-4 py-3 text-sm font-bold text-slate-800 outline-none focus:border-[#003317] transition-all"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -332,7 +332,7 @@ const ManageCoupons = () => {
|
|||||||
type="date"
|
type="date"
|
||||||
value={newCoupon.expiryDate}
|
value={newCoupon.expiryDate}
|
||||||
onChange={(e) => setNewCoupon({ ...newCoupon, expiryDate: e.target.value })}
|
onChange={(e) => setNewCoupon({ ...newCoupon, expiryDate: e.target.value })}
|
||||||
className="w-full bg-slate-50 border border-slate-100 rounded-2xl px-4 py-3 text-sm font-bold text-slate-800 outline-none focus:border-[#0f4475] transition-all"
|
className="w-full bg-slate-50 border border-slate-100 rounded-2xl px-4 py-3 text-sm font-bold text-slate-800 outline-none focus:border-[#003317] transition-all"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-1.5">
|
<div className="space-y-1.5">
|
||||||
@@ -343,7 +343,7 @@ const ManageCoupons = () => {
|
|||||||
placeholder="Inventory Limit"
|
placeholder="Inventory Limit"
|
||||||
value={newCoupon.maxClaims}
|
value={newCoupon.maxClaims}
|
||||||
onChange={(e) => setNewCoupon({ ...newCoupon, maxClaims: e.target.value })}
|
onChange={(e) => setNewCoupon({ ...newCoupon, maxClaims: e.target.value })}
|
||||||
className="w-full bg-slate-50 border border-slate-100 rounded-2xl px-4 py-3 text-sm font-bold text-slate-800 outline-none focus:border-[#0f4475] transition-all"
|
className="w-full bg-slate-50 border border-slate-100 rounded-2xl px-4 py-3 text-sm font-bold text-slate-800 outline-none focus:border-[#003317] transition-all"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -355,13 +355,13 @@ const ManageCoupons = () => {
|
|||||||
rows={3}
|
rows={3}
|
||||||
value={newCoupon.description}
|
value={newCoupon.description}
|
||||||
onChange={(e) => setNewCoupon({ ...newCoupon, description: e.target.value })}
|
onChange={(e) => setNewCoupon({ ...newCoupon, description: e.target.value })}
|
||||||
className="w-full bg-slate-50 border border-slate-100 rounded-2xl px-4 py-3 text-sm font-bold text-slate-800 outline-none focus:border-[#0f4475] transition-all resize-none"
|
className="w-full bg-slate-50 border border-slate-100 rounded-2xl px-4 py-3 text-sm font-bold text-slate-800 outline-none focus:border-[#003317] transition-all resize-none"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="w-full bg-[#0f4475] text-white py-4 rounded-2xl text-xs font-black uppercase tracking-widest shadow-xl shadow-[#0f4475]/20 hover:scale-[1.02] active:scale-[0.98] transition-all mt-4 flex items-center justify-center gap-3"
|
className="w-full bg-[#003317] text-white py-4 rounded-2xl text-xs font-black uppercase tracking-widest shadow-xl shadow-[#003317]/20 hover:scale-[1.02] active:scale-[0.98] transition-all mt-4 flex items-center justify-center gap-3"
|
||||||
>
|
>
|
||||||
Confirm Generation
|
Confirm Generation
|
||||||
<ChevronRight size={18} />
|
<ChevronRight size={18} />
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ const ManageWallets = () => {
|
|||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<div className="flex items-center gap-2 mb-1">
|
<div className="flex items-center gap-2 mb-1">
|
||||||
<h2 className="text-xs font-black text-[#0f4475] uppercase tracking-widest">Ritz Section</h2>
|
<h2 className="text-xs font-black text-[#003317] uppercase tracking-widest">Ritz Section</h2>
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-2xl font-black text-slate-800">Manage Wallets</h1>
|
<h1 className="text-2xl font-black text-slate-800">Manage Wallets</h1>
|
||||||
<p className="text-[10px] text-slate-400 font-medium flex items-center gap-1.5 mt-1">
|
<p className="text-[10px] text-slate-400 font-medium flex items-center gap-1.5 mt-1">
|
||||||
@@ -114,7 +114,7 @@ const ManageWallets = () => {
|
|||||||
placeholder="Search user or mobile..."
|
placeholder="Search user or mobile..."
|
||||||
value={searchQuery}
|
value={searchQuery}
|
||||||
onChange={(e) => setSearchQuery(e.target.value)}
|
onChange={(e) => setSearchQuery(e.target.value)}
|
||||||
className="bg-white border border-slate-200 rounded-xl pl-10 pr-4 py-2 text-sm outline-none focus:border-[#0f4475] transition-all w-64 shadow-sm"
|
className="bg-white border border-slate-200 rounded-xl pl-10 pr-4 py-2 text-sm outline-none focus:border-[#003317] transition-all w-64 shadow-sm"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -140,7 +140,7 @@ const ManageWallets = () => {
|
|||||||
<motion.div
|
<motion.div
|
||||||
animate={{ scale: [1, 1.05, 1], opacity: [0.5, 1, 0.5] }}
|
animate={{ scale: [1, 1.05, 1], opacity: [0.5, 1, 0.5] }}
|
||||||
transition={{ repeat: Infinity, duration: 1.5 }}
|
transition={{ repeat: Infinity, duration: 1.5 }}
|
||||||
className="text-[10px] font-black text-[#0f4475] uppercase tracking-widest"
|
className="text-[10px] font-black text-[#003317] uppercase tracking-widest"
|
||||||
>
|
>
|
||||||
Loading Wallet Data...
|
Loading Wallet Data...
|
||||||
</motion.div>
|
</motion.div>
|
||||||
@@ -158,7 +158,7 @@ const ManageWallets = () => {
|
|||||||
<td className="px-8 py-5 text-sm font-black text-slate-400 tabular-nums">#{user.id}</td>
|
<td className="px-8 py-5 text-sm font-black text-slate-400 tabular-nums">#{user.id}</td>
|
||||||
<td className="px-8 py-5">
|
<td className="px-8 py-5">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="w-10 h-10 rounded-xl bg-[#0f4475]/5 flex items-center justify-center text-[#0f4475]">
|
<div className="w-10 h-10 rounded-xl bg-[#003317]/5 flex items-center justify-center text-[#003317]">
|
||||||
<UserIcon size={18} />
|
<UserIcon size={18} />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -185,7 +185,7 @@ const ManageWallets = () => {
|
|||||||
setSelectedUser(user);
|
setSelectedUser(user);
|
||||||
setIsModalOpen(true);
|
setIsModalOpen(true);
|
||||||
}}
|
}}
|
||||||
className="bg-[#0f4475] text-white px-4 py-2 rounded-xl text-[10px] font-black uppercase tracking-widest hover:scale-105 transition-all shadow-lg shadow-[#0f4475]/10 active:scale-95"
|
className="bg-[#003317] text-white px-4 py-2 rounded-xl text-[10px] font-black uppercase tracking-widest hover:scale-105 transition-all shadow-lg shadow-[#003317]/10 active:scale-95"
|
||||||
>
|
>
|
||||||
Credit Wallet
|
Credit Wallet
|
||||||
</button>
|
</button>
|
||||||
@@ -218,7 +218,7 @@ const ManageWallets = () => {
|
|||||||
<div className="p-8">
|
<div className="p-8">
|
||||||
<div className="flex items-center justify-between mb-8">
|
<div className="flex items-center justify-between mb-8">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="p-2 bg-[#0f4475]/10 text-[#0f4475] rounded-xl">
|
<div className="p-2 bg-[#003317]/10 text-[#003317] rounded-xl">
|
||||||
<Plus size={20} />
|
<Plus size={20} />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-lg font-black text-slate-800">Credit Ritz Tokens</h3>
|
<h3 className="text-lg font-black text-slate-800">Credit Ritz Tokens</h3>
|
||||||
@@ -244,13 +244,13 @@ const ManageWallets = () => {
|
|||||||
<div>
|
<div>
|
||||||
<label className="text-[10px] font-black text-slate-400 uppercase tracking-widest ml-1 mb-2 block">Token Amount (Ritz)</label>
|
<label className="text-[10px] font-black text-slate-400 uppercase tracking-widest ml-1 mb-2 block">Token Amount (Ritz)</label>
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<div className="absolute left-4 top-1/2 -translate-y-1/2 font-black text-[#0f4475] text-lg">R</div>
|
<div className="absolute left-4 top-1/2 -translate-y-1/2 font-black text-[#003317] text-lg">R</div>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
value={amount}
|
value={amount}
|
||||||
onChange={(e) => setAmount(e.target.value)}
|
onChange={(e) => setAmount(e.target.value)}
|
||||||
placeholder="0.00"
|
placeholder="0.00"
|
||||||
className="w-full bg-slate-50 border border-slate-100 rounded-2xl pl-10 pr-4 py-4 text-2xl font-black text-slate-800 outline-none focus:bg-white focus:border-[#0f4475]/30 transition-all"
|
className="w-full bg-slate-50 border border-slate-100 rounded-2xl pl-10 pr-4 py-4 text-2xl font-black text-slate-800 outline-none focus:bg-white focus:border-[#003317]/30 transition-all"
|
||||||
required
|
required
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
@@ -271,7 +271,7 @@ const ManageWallets = () => {
|
|||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={isProcessing || !amount}
|
disabled={isProcessing || !amount}
|
||||||
className="w-full bg-[#0f4475] text-white py-4 rounded-2xl font-black uppercase tracking-widest shadow-xl shadow-[#0f4475]/20 hover:scale-[1.02] transition-all flex items-center justify-center gap-2 group disabled:opacity-50 disabled:hover:scale-100"
|
className="w-full bg-[#003317] text-white py-4 rounded-2xl font-black uppercase tracking-widest shadow-xl shadow-[#003317]/20 hover:scale-[1.02] transition-all flex items-center justify-center gap-2 group disabled:opacity-50 disabled:hover:scale-100"
|
||||||
>
|
>
|
||||||
{isProcessing ? (
|
{isProcessing ? (
|
||||||
<div className="w-5 h-5 border-2 border-white/30 border-t-white rounded-full animate-spin" />
|
<div className="w-5 h-5 border-2 border-white/30 border-t-white rounded-full animate-spin" />
|
||||||
|
|||||||
@@ -5,32 +5,32 @@ const NotFound = () => {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-[#f8fafc] flex items-center justify-center p-6 font-sans selection:bg-[#0f4475]/10">
|
<div className="min-h-screen bg-[#f8fafc] flex items-center justify-center p-6 font-sans selection:bg-[#003317]/10">
|
||||||
<div className="max-w-4xl w-full">
|
<div className="max-w-4xl w-full">
|
||||||
<div className="grid lg:grid-cols-2 gap-12 items-center">
|
<div className="grid lg:grid-cols-2 gap-12 items-center">
|
||||||
{/* Visual Section */}
|
{/* Visual Section */}
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
{/* Background Decorative Circles */}
|
{/* Background Decorative Circles */}
|
||||||
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-80 h-80 bg-[#0f4475]/5 rounded-full blur-3xl" />
|
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-80 h-80 bg-[#003317]/5 rounded-full blur-3xl" />
|
||||||
<div className="absolute top-1/4 left-1/4 w-32 h-32 bg-indigo-500/10 rounded-full blur-2xl" />
|
<div className="absolute top-1/4 left-1/4 w-32 h-32 bg-indigo-500/10 rounded-full blur-2xl" />
|
||||||
|
|
||||||
{/* 404 Main Text */}
|
{/* 404 Main Text */}
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<h1 className="text-[180px] font-black leading-none tracking-tighter text-[#0f4475] opacity-20 select-none">
|
<h1 className="text-[180px] font-black leading-none tracking-tighter text-[#003317] opacity-20 select-none">
|
||||||
404
|
404
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
{/* Detailed Icon Stack */}
|
{/* Detailed Icon Stack */}
|
||||||
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 flex items-center justify-center">
|
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 flex items-center justify-center">
|
||||||
<div className="p-8 bg-white rounded-[40px] shadow-2xl border border-white/50 backdrop-blur-xl relative z-10">
|
<div className="p-8 bg-white rounded-[40px] shadow-2xl border border-white/50 backdrop-blur-xl relative z-10">
|
||||||
<Search size={80} className="text-[#0f4475]" strokeWidth={1.5} />
|
<Search size={80} className="text-[#003317]" strokeWidth={1.5} />
|
||||||
|
|
||||||
{/* Small Floating Icons */}
|
{/* Small Floating Icons */}
|
||||||
<div className="absolute -top-4 -right-4 p-3 bg-white rounded-2xl shadow-lg border border-white">
|
<div className="absolute -top-4 -right-4 p-3 bg-white rounded-2xl shadow-lg border border-white">
|
||||||
<HelpCircle size={24} className="text-indigo-500" />
|
<HelpCircle size={24} className="text-indigo-500" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="absolute -bottom-6 -left-6 p-4 bg-[#0f4475] rounded-3xl shadow-xl border-4 border-white text-white">
|
<div className="absolute -bottom-6 -left-6 p-4 bg-[#003317] rounded-3xl shadow-xl border-4 border-white text-white">
|
||||||
<span className="text-sm font-black tracking-widest uppercase">Lost?</span>
|
<span className="text-sm font-black tracking-widest uppercase">Lost?</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -48,7 +48,7 @@ const NotFound = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 className="text-4xl lg:text-5xl font-black text-[#1e293b] mb-6 leading-tight">
|
<h2 className="text-4xl lg:text-5xl font-black text-[#1e293b] mb-6 leading-tight">
|
||||||
Well, this is <span className="text-transparent bg-clip-text bg-gradient-to-r from-[#0f4475] to-indigo-600">awkward.</span>
|
Well, this is <span className="text-transparent bg-clip-text bg-gradient-to-r from-[#003317] to-indigo-600">awkward.</span>
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<p className="text-[#64748b] text-lg mb-10 leading-relaxed font-medium">
|
<p className="text-[#64748b] text-lg mb-10 leading-relaxed font-medium">
|
||||||
@@ -58,7 +58,7 @@ const NotFound = () => {
|
|||||||
<div className="flex flex-col sm:flex-row items-center gap-4 justify-center lg:justify-start">
|
<div className="flex flex-col sm:flex-row items-center gap-4 justify-center lg:justify-start">
|
||||||
<button
|
<button
|
||||||
onClick={() => navigate('/dashboard')}
|
onClick={() => navigate('/dashboard')}
|
||||||
className="group px-8 py-4 bg-[#0f4475] text-white rounded-2xl font-bold flex items-center gap-3 shadow-xl shadow-[#0f4475]/20 hover:bg-[#1a5a92] transition-all hover:-translate-y-1 active:translate-y-0"
|
className="group px-8 py-4 bg-[#003317] text-white rounded-2xl font-bold flex items-center gap-3 shadow-xl shadow-[#003317]/20 hover:bg-[#1a5a92] transition-all hover:-translate-y-1 active:translate-y-0"
|
||||||
>
|
>
|
||||||
<Home size={18} className="group-hover:scale-110 transition-transform" />
|
<Home size={18} className="group-hover:scale-110 transition-transform" />
|
||||||
Return to Safety
|
Return to Safety
|
||||||
@@ -81,9 +81,9 @@ const NotFound = () => {
|
|||||||
<button
|
<button
|
||||||
key={item}
|
key={item}
|
||||||
onClick={() => navigate(`/${item.toLowerCase()}`)}
|
onClick={() => navigate(`/${item.toLowerCase()}`)}
|
||||||
className="text-xs font-bold text-[#64748b] hover:text-[#0f4475] transition-colors flex items-center gap-1 group"
|
className="text-xs font-bold text-[#64748b] hover:text-[#003317] transition-colors flex items-center gap-1 group"
|
||||||
>
|
>
|
||||||
<div className="w-1 h-1 rounded-full bg-[#e2e8f0] group-hover:bg-[#0f4475] transition-colors" />
|
<div className="w-1 h-1 rounded-full bg-[#e2e8f0] group-hover:bg-[#003317] transition-colors" />
|
||||||
{item}
|
{item}
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ const PurchaseAnalytics = () => {
|
|||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return (
|
return (
|
||||||
<div className="h-full flex flex-col items-center justify-center gap-4">
|
<div className="h-full flex flex-col items-center justify-center gap-4">
|
||||||
<Loader2 className="animate-spin text-[#0f4475]" size={40} />
|
<Loader2 className="animate-spin text-[#003317]" size={40} />
|
||||||
<p className="text-sm font-bold text-slate-500 uppercase tracking-widest">Calculating Market Analytics...</p>
|
<p className="text-sm font-bold text-slate-500 uppercase tracking-widest">Calculating Market Analytics...</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -181,12 +181,12 @@ const PurchaseAnalytics = () => {
|
|||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4">
|
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4">
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-2xl font-black text-[#0f4475] tracking-tight uppercase">Purchase Analytics</h1>
|
<h1 className="text-2xl font-black text-[#003317] tracking-tight uppercase">Purchase Analytics</h1>
|
||||||
<div className="flex items-center gap-2 mt-1">
|
<div className="flex items-center gap-2 mt-1">
|
||||||
<span className="bg-[#0f4475]/10 text-[#0f4475] text-[10px] font-bold px-2 py-0.5 rounded-full uppercase">
|
<span className="bg-[#003317]/10 text-[#003317] text-[10px] font-bold px-2 py-0.5 rounded-full uppercase">
|
||||||
Start: {format(dateRange.start, 'yyyy-MM-dd')}
|
Start: {format(dateRange.start, 'yyyy-MM-dd')}
|
||||||
</span>
|
</span>
|
||||||
<span className="bg-[#0f4475]/10 text-[#0f4475] text-[10px] font-bold px-2 py-0.5 rounded-full uppercase">
|
<span className="bg-[#003317]/10 text-[#003317] text-[10px] font-bold px-2 py-0.5 rounded-full uppercase">
|
||||||
End: {format(dateRange.end, 'yyyy-MM-dd')}
|
End: {format(dateRange.end, 'yyyy-MM-dd')}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -194,7 +194,7 @@ const PurchaseAnalytics = () => {
|
|||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<button
|
<button
|
||||||
onClick={() => setFilterType('all')}
|
onClick={() => setFilterType('all')}
|
||||||
className={`px-4 py-2 rounded-xl text-xs font-bold uppercase transition-all ${filterType === 'all' ? 'bg-[#0f4475] text-white shadow-lg' : 'bg-white border text-slate-500 border-slate-200 hover:bg-slate-50'}`}
|
className={`px-4 py-2 rounded-xl text-xs font-bold uppercase transition-all ${filterType === 'all' ? 'bg-[#003317] text-white shadow-lg' : 'bg-white border text-slate-500 border-slate-200 hover:bg-slate-50'}`}
|
||||||
>
|
>
|
||||||
Show All
|
Show All
|
||||||
</button>
|
</button>
|
||||||
@@ -231,7 +231,7 @@ const PurchaseAnalytics = () => {
|
|||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Search products..."
|
placeholder="Search products..."
|
||||||
className="pl-9 pr-4 py-2 border border-[#e2e8f0] rounded-xl text-xs outline-none focus:border-[#0f4475]/30 transition-all font-medium"
|
className="pl-9 pr-4 py-2 border border-[#e2e8f0] rounded-xl text-xs outline-none focus:border-[#003317]/30 transition-all font-medium"
|
||||||
value={searchTerm}
|
value={searchTerm}
|
||||||
onChange={(e) => setSearchTerm(e.target.value)}
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
/>
|
/>
|
||||||
@@ -254,7 +254,7 @@ const PurchaseAnalytics = () => {
|
|||||||
) : (
|
) : (
|
||||||
filteredAnalytics.map((item, idx) => (
|
filteredAnalytics.map((item, idx) => (
|
||||||
<tr key={idx} className="hover:bg-gray-50/50 transition-colors group">
|
<tr key={idx} className="hover:bg-gray-50/50 transition-colors group">
|
||||||
<td className="px-6 py-4"><p className="text-xs font-bold text-[#1e293b] group-hover:text-[#0f4475]">{item.product}</p></td>
|
<td className="px-6 py-4"><p className="text-xs font-bold text-[#1e293b] group-hover:text-[#003317]">{item.product}</p></td>
|
||||||
<td className="px-6 py-4 text-xs font-bold text-[#475569]">{item.qty}</td>
|
<td className="px-6 py-4 text-xs font-bold text-[#475569]">{item.qty}</td>
|
||||||
<td className="px-6 py-4 text-xs font-bold text-[#475569] text-right">₹{item.basePrice.toFixed(2)}</td>
|
<td className="px-6 py-4 text-xs font-bold text-[#475569] text-right">₹{item.basePrice.toFixed(2)}</td>
|
||||||
<td className="px-6 py-4 text-right">
|
<td className="px-6 py-4 text-right">
|
||||||
@@ -286,7 +286,7 @@ const PurchaseAnalytics = () => {
|
|||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<button
|
<button
|
||||||
onClick={() => setFilterType('up')}
|
onClick={() => setFilterType('up')}
|
||||||
className={`p-4 rounded-2xl flex flex-col items-center justify-center gap-2 transition-all cursor-pointer hover:border-[#0f4475]/50 border-2 ${filterType === 'up' ? 'bg-[#0f4475] text-white border-[#0f4475]' : 'bg-gray-50 text-slate-400 border-transparent hover:bg-slate-100'}`}
|
className={`p-4 rounded-2xl flex flex-col items-center justify-center gap-2 transition-all cursor-pointer hover:border-[#003317]/50 border-2 ${filterType === 'up' ? 'bg-[#003317] text-white border-[#003317]' : 'bg-gray-50 text-slate-400 border-transparent hover:bg-slate-100'}`}
|
||||||
>
|
>
|
||||||
<TrendingUp size={20} />
|
<TrendingUp size={20} />
|
||||||
<span className="text-[10px] font-bold uppercase tracking-wider">Inflation</span>
|
<span className="text-[10px] font-bold uppercase tracking-wider">Inflation</span>
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ const PurchaseSummary = () => {
|
|||||||
<motion.div
|
<motion.div
|
||||||
animate={{ scale: [1, 1.05, 1] }}
|
animate={{ scale: [1, 1.05, 1] }}
|
||||||
transition={{ repeat: Infinity, duration: 2 }}
|
transition={{ repeat: Infinity, duration: 2 }}
|
||||||
className="text-[#0f4475] font-black uppercase tracking-widest text-xs"
|
className="text-[#003317] font-black uppercase tracking-widest text-xs"
|
||||||
>
|
>
|
||||||
Compiling Fiscal Intelligence...
|
Compiling Fiscal Intelligence...
|
||||||
</motion.div>
|
</motion.div>
|
||||||
@@ -79,7 +79,7 @@ const PurchaseSummary = () => {
|
|||||||
<button title="Back" className="p-1.5 hover:bg-slate-100 rounded-lg transition-all">
|
<button title="Back" className="p-1.5 hover:bg-slate-100 rounded-lg transition-all">
|
||||||
<ArrowRight className="rotate-180 text-slate-400" size={18} />
|
<ArrowRight className="rotate-180 text-slate-400" size={18} />
|
||||||
</button>
|
</button>
|
||||||
<h2 className="text-xs font-black text-[#0f4475] uppercase tracking-widest">Purchases</h2>
|
<h2 className="text-xs font-black text-[#003317] uppercase tracking-widest">Purchases</h2>
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-2xl font-black text-slate-800">Summary</h1>
|
<h1 className="text-2xl font-black text-slate-800">Summary</h1>
|
||||||
</div>
|
</div>
|
||||||
@@ -89,7 +89,7 @@ const PurchaseSummary = () => {
|
|||||||
<button
|
<button
|
||||||
key={range}
|
key={range}
|
||||||
onClick={() => setActiveRange(range)}
|
onClick={() => setActiveRange(range)}
|
||||||
className={`px-4 py-2 text-[10px] font-black uppercase tracking-widest transition-all rounded-xl ${activeRange === range ? 'text-white bg-[#0f4475] shadow-md shadow-[#0f4475]/20' : 'text-slate-400 hover:text-slate-600'}`}
|
className={`px-4 py-2 text-[10px] font-black uppercase tracking-widest transition-all rounded-xl ${activeRange === range ? 'text-white bg-[#003317] shadow-md shadow-[#003317]/20' : 'text-slate-400 hover:text-slate-600'}`}
|
||||||
>
|
>
|
||||||
{range}
|
{range}
|
||||||
</button>
|
</button>
|
||||||
@@ -119,7 +119,7 @@ const PurchaseSummary = () => {
|
|||||||
</motion.div>
|
</motion.div>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
<div className="col-span-2 bg-[#0f4475] p-6 rounded-[32px] shadow-lg shadow-[#0f4475]/20 text-white relative overflow-hidden group">
|
<div className="col-span-2 bg-[#003317] p-6 rounded-[32px] shadow-lg shadow-[#003317]/20 text-white relative overflow-hidden group">
|
||||||
<div className="absolute -right-8 -top-8 w-32 h-32 bg-white/10 rounded-full blur-3xl" />
|
<div className="absolute -right-8 -top-8 w-32 h-32 bg-white/10 rounded-full blur-3xl" />
|
||||||
<div className="relative z-10 flex items-end justify-between">
|
<div className="relative z-10 flex items-end justify-between">
|
||||||
<div>
|
<div>
|
||||||
@@ -174,7 +174,7 @@ const PurchaseSummary = () => {
|
|||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<Search className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-400" size={14} />
|
<Search className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-400" size={14} />
|
||||||
<input type="text" title="Search" placeholder="Filter bills..." className="pl-9 pr-4 py-2 bg-slate-50 border border-slate-100 rounded-xl text-xs font-bold outline-none focus:border-[#0f4475] transition-all" />
|
<input type="text" title="Search" placeholder="Filter bills..." className="pl-9 pr-4 py-2 bg-slate-50 border border-slate-100 rounded-xl text-xs font-bold outline-none focus:border-[#003317] transition-all" />
|
||||||
</div>
|
</div>
|
||||||
<button title="Filter" className="p-2.5 bg-slate-50 rounded-xl text-slate-500 border border-slate-100"><Filter size={16} /></button>
|
<button title="Filter" className="p-2.5 bg-slate-50 rounded-xl text-slate-500 border border-slate-100"><Filter size={16} /></button>
|
||||||
</div>
|
</div>
|
||||||
@@ -206,7 +206,7 @@ const PurchaseSummary = () => {
|
|||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td className="px-6 py-5 text-right text-xs font-black text-rose-500">₹{(bill.balance ?? 0).toLocaleString()}</td>
|
<td className="px-6 py-5 text-right text-xs font-black text-rose-500">₹{(bill.balance ?? 0).toLocaleString()}</td>
|
||||||
<td className="px-6 py-5 text-right text-xs font-black text-[#0f4475]">₹{(bill.amount ?? 0).toLocaleString()}</td>
|
<td className="px-6 py-5 text-right text-xs font-black text-[#003317]">₹{(bill.amount ?? 0).toLocaleString()}</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ const StoreDashboard = () => {
|
|||||||
<motion.div
|
<motion.div
|
||||||
animate={{ scale: [1, 1.1, 1], opacity: [0.5, 1, 0.5] }}
|
animate={{ scale: [1, 1.1, 1], opacity: [0.5, 1, 0.5] }}
|
||||||
transition={{ repeat: Infinity, duration: 1.5 }}
|
transition={{ repeat: Infinity, duration: 1.5 }}
|
||||||
className="text-[#0f4475] font-black uppercase tracking-widest text-sm"
|
className="text-[#003317] font-black uppercase tracking-widest text-sm"
|
||||||
>
|
>
|
||||||
Analyzing Store Data...
|
Analyzing Store Data...
|
||||||
</motion.div>
|
</motion.div>
|
||||||
@@ -169,7 +169,7 @@ const StoreDashboard = () => {
|
|||||||
<button title="Return to previous screen" className="p-1.5 hover:bg-slate-100 rounded-lg transition-all">
|
<button title="Return to previous screen" className="p-1.5 hover:bg-slate-100 rounded-lg transition-all">
|
||||||
<ArrowRight className="rotate-180 text-slate-400" size={18} />
|
<ArrowRight className="rotate-180 text-slate-400" size={18} />
|
||||||
</button>
|
</button>
|
||||||
<h2 className="text-xs font-black text-[#0f4475] uppercase tracking-widest">Store Dashboard</h2>
|
<h2 className="text-xs font-black text-[#003317] uppercase tracking-widest">Store Dashboard</h2>
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-2xl font-black text-slate-800">
|
<h1 className="text-2xl font-black text-slate-800">
|
||||||
Good morning, {(() => {
|
Good morning, {(() => {
|
||||||
@@ -194,11 +194,11 @@ const StoreDashboard = () => {
|
|||||||
key={tab}
|
key={tab}
|
||||||
title={`Visualize ${tab.toLowerCase()} throughput data`}
|
title={`Visualize ${tab.toLowerCase()} throughput data`}
|
||||||
onClick={() => setActiveTab(tab)}
|
onClick={() => setActiveTab(tab)}
|
||||||
className={`pb-4 text-[11px] font-black uppercase tracking-widest transition-all relative ${activeTab === tab ? 'text-[#0f4475]' : 'text-slate-400 hover:text-slate-600'}`}
|
className={`pb-4 text-[11px] font-black uppercase tracking-widest transition-all relative ${activeTab === tab ? 'text-[#003317]' : 'text-slate-400 hover:text-slate-600'}`}
|
||||||
>
|
>
|
||||||
{tab}
|
{tab}
|
||||||
{activeTab === tab && (
|
{activeTab === tab && (
|
||||||
<motion.div layoutId="tabLineStore" className="absolute bottom-0 left-0 right-0 h-0.5 bg-[#0f4475]" />
|
<motion.div layoutId="tabLineStore" className="absolute bottom-0 left-0 right-0 h-0.5 bg-[#003317]" />
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
@@ -270,18 +270,18 @@ const StoreDashboard = () => {
|
|||||||
key={range}
|
key={range}
|
||||||
title={`Filter metrics by ${range.toLowerCase()}`}
|
title={`Filter metrics by ${range.toLowerCase()}`}
|
||||||
onClick={() => setTimeRange(range)}
|
onClick={() => setTimeRange(range)}
|
||||||
className={`whitespace-nowrap px-2 py-2 text-[10px] font-black uppercase tracking-tighter transition-all relative ${timeRange === range ? 'text-[#0f4475]' : 'text-slate-400 hover:text-slate-600'}`}
|
className={`whitespace-nowrap px-2 py-2 text-[10px] font-black uppercase tracking-tighter transition-all relative ${timeRange === range ? 'text-[#003317]' : 'text-slate-400 hover:text-slate-600'}`}
|
||||||
>
|
>
|
||||||
{range}
|
{range}
|
||||||
{timeRange === range && (
|
{timeRange === range && (
|
||||||
<motion.div layoutId="rangeLineStore" className="absolute bottom-0 left-0 right-0 h-0.5 bg-[#0f4475]" />
|
<motion.div layoutId="rangeLineStore" className="absolute bottom-0 left-0 right-0 h-0.5 bg-[#003317]" />
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Total Orders Card */}
|
{/* Total Orders Card */}
|
||||||
<div title="View detailed store volume and throughput" className="bg-white p-6 rounded-[24px] border border-slate-100 shadow-sm relative h-[180px] flex flex-col justify-between group cursor-pointer hover:border-[#0f4475]/30 transition-all">
|
<div title="View detailed store volume and throughput" className="bg-white p-6 rounded-[24px] border border-slate-100 shadow-sm relative h-[180px] flex flex-col justify-between group cursor-pointer hover:border-[#003317]/30 transition-all">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="p-2 bg-amber-50 text-amber-500 rounded-xl group-hover:scale-110 transition-transform">
|
<div className="p-2 bg-amber-50 text-amber-500 rounded-xl group-hover:scale-110 transition-transform">
|
||||||
<ShoppingBag size={20} />
|
<ShoppingBag size={20} />
|
||||||
@@ -308,9 +308,9 @@ const StoreDashboard = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Expenses Card */}
|
{/* Expenses Card */}
|
||||||
<div title="Monitor store operational expenditures" className="bg-white p-6 rounded-[24px] border border-slate-100 shadow-sm h-[130px] flex flex-col justify-between group cursor-pointer hover:border-[#0f4475]/30 transition-all">
|
<div title="Monitor store operational expenditures" className="bg-white p-6 rounded-[24px] border border-slate-100 shadow-sm h-[130px] flex flex-col justify-between group cursor-pointer hover:border-[#003317]/30 transition-all">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="p-2 bg-amber-100 text-[#0f4475] rounded-xl shadow-sm">
|
<div className="p-2 bg-amber-100 text-[#003317] rounded-xl shadow-sm">
|
||||||
<Wallet size={20} />
|
<Wallet size={20} />
|
||||||
</div>
|
</div>
|
||||||
<h4 className="text-[11px] font-black text-slate-400 uppercase tracking-widest leading-none">Expenses</h4>
|
<h4 className="text-[11px] font-black text-slate-400 uppercase tracking-widest leading-none">Expenses</h4>
|
||||||
@@ -360,7 +360,7 @@ const StoreDashboard = () => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-0.5">
|
<div className="space-y-0.5">
|
||||||
<p className="text-[9px] font-black text-[#0f4475] uppercase tracking-widest brightness-110">{item.category}</p>
|
<p className="text-[9px] font-black text-[#003317] uppercase tracking-widest brightness-110">{item.category}</p>
|
||||||
<p className="text-xs font-black text-slate-800 uppercase tracking-tight">{item.name}</p>
|
<p className="text-xs font-black text-slate-800 uppercase tracking-tight">{item.name}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -391,7 +391,7 @@ const StoreDashboard = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-8 flex justify-end">
|
<div className="mt-8 flex justify-end">
|
||||||
<button title="Analyze subsequent business cycles" className="flex items-center gap-2 px-6 py-2.5 bg-[#0f4475]/5 hover:bg-[#0f4475]/10 text-[#0f4475] text-[11px] font-black uppercase tracking-widest rounded-2xl transition-all group">
|
<button title="Analyze subsequent business cycles" className="flex items-center gap-2 px-6 py-2.5 bg-[#003317]/5 hover:bg-[#003317]/10 text-[#003317] text-[11px] font-black uppercase tracking-widest rounded-2xl transition-all group">
|
||||||
Next
|
Next
|
||||||
<ArrowRight size={14} className="group-hover:translate-x-1 transition-transform" />
|
<ArrowRight size={14} className="group-hover:translate-x-1 transition-transform" />
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -21,13 +21,6 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|||||||
const [user, setUser] = useState<User | null>(null);
|
const [user, setUser] = useState<User | null>(null);
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const savedUser = localStorage.getItem('user');
|
|
||||||
if (savedUser) {
|
|
||||||
setUser(JSON.parse(savedUser));
|
|
||||||
}
|
|
||||||
setIsLoading(false);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const checkUserExists = async (mobileNumber: string) => {
|
const checkUserExists = async (mobileNumber: string) => {
|
||||||
try {
|
try {
|
||||||
@@ -157,11 +150,12 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const refreshUser = async () => {
|
const refreshUser = async (userOverride?: User | null) => {
|
||||||
if (!user) return;
|
const targetUser = userOverride || user;
|
||||||
|
if (!targetUser) return;
|
||||||
try {
|
try {
|
||||||
const token = localStorage.getItem('token');
|
const token = localStorage.getItem('token');
|
||||||
const response = await fetch(`${API_BASE_URL}/user/${user.mobileNumber}`, {
|
const response = await fetch(`${API_BASE_URL}/user/${targetUser.mobileNumber}`, {
|
||||||
cache: 'no-store',
|
cache: 'no-store',
|
||||||
headers: {
|
headers: {
|
||||||
...(token ? { 'Authorization': `Bearer ${token}` } : {})
|
...(token ? { 'Authorization': `Bearer ${token}` } : {})
|
||||||
@@ -179,8 +173,12 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Update state and localStorage
|
// Update state and localStorage
|
||||||
|
if (updatedUser.isSuspended) {
|
||||||
|
logout();
|
||||||
|
} else {
|
||||||
setUser(updatedUser);
|
setUser(updatedUser);
|
||||||
localStorage.setItem('user', JSON.stringify(updatedUser));
|
localStorage.setItem('user', JSON.stringify(updatedUser));
|
||||||
|
}
|
||||||
} else if (response.status === 404 || response.status === 401 || response.status === 403) {
|
} else if (response.status === 404 || response.status === 401 || response.status === 403) {
|
||||||
logout();
|
logout();
|
||||||
}
|
}
|
||||||
@@ -189,6 +187,24 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const initAuth = async () => {
|
||||||
|
try {
|
||||||
|
const savedUser = localStorage.getItem('user');
|
||||||
|
if (savedUser) {
|
||||||
|
const parsedUser = JSON.parse(savedUser);
|
||||||
|
setUser(parsedUser);
|
||||||
|
await refreshUser(parsedUser);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error during initial auth load:', error);
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
initAuth();
|
||||||
|
}, []);
|
||||||
|
|
||||||
// Background status and balance sync
|
// Background status and balance sync
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!user) return;
|
if (!user) return;
|
||||||
|
|||||||
Reference in New Issue
Block a user