developed ui for pos
This commit is contained in:
@@ -1214,113 +1214,156 @@ export default function InventoryView({
|
||||
</div>
|
||||
) : activeTab === 'requests' ? (
|
||||
<div className="flex-1 overflow-y-auto mt-4 pr-2 custom-scrollbar animate-in fade-in duration-300">
|
||||
<div className="flex justify-between items-center mb-6">
|
||||
<div>
|
||||
<h2 className="text-xl font-black text-slate-900 tracking-tight flex items-center gap-2">
|
||||
<Inbox size={22} className="text-[#662582]" /> Pending Stock Requests
|
||||
</h2>
|
||||
<p className="text-xs font-bold text-slate-500 mt-1 uppercase tracking-widest">Store Branch Inventory Requests</p>
|
||||
<div className="flex flex-col lg:flex-row lg:justify-between lg:items-end gap-4 mb-8">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-12 h-12 rounded-2xl bg-gradient-to-br from-purple-50 to-indigo-50 border border-purple-100 flex items-center justify-center shadow-[0_2px_10px_-3px_rgba(102,37,130,0.15)] shrink-0">
|
||||
<Inbox size={24} className="text-[#662582]" strokeWidth={2.5} />
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="text-2xl font-black text-slate-900 tracking-tight mb-1">
|
||||
Pending Stock Requests
|
||||
</h2>
|
||||
<div className="text-sm font-semibold text-slate-500 flex items-center gap-2">
|
||||
Store Branch Inventory Requests
|
||||
<span className="px-2 py-0.5 rounded-md bg-slate-100 text-slate-600 text-[10px] font-bold tracking-wider uppercase border border-slate-200 shadow-sm">
|
||||
{flattenedRequests.length} Total
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-3">
|
||||
<select
|
||||
value={requestStoreFilter}
|
||||
onChange={(e) => setRequestStoreFilter(e.target.value)}
|
||||
className="bg-white border border-slate-200 text-slate-700 px-4 py-2 rounded-xl text-xs font-bold shadow-sm outline-none cursor-pointer focus:border-purple-300 transition-colors"
|
||||
>
|
||||
<option value="All Stores">All Stores</option>
|
||||
{requestingStores.map(store => (
|
||||
<option key={store} value={store}>{store}</option>
|
||||
))}
|
||||
</select>
|
||||
<div className="relative group">
|
||||
<select
|
||||
value={requestStoreFilter}
|
||||
onChange={(e) => setRequestStoreFilter(e.target.value)}
|
||||
className="appearance-none bg-white border border-slate-200 text-slate-700 pl-4 pr-10 py-2.5 rounded-xl text-sm font-semibold shadow-sm outline-none cursor-pointer hover:border-[#662582]/40 hover:shadow-md transition-all focus:border-[#662582] focus:ring-2 focus:ring-[#662582]/20"
|
||||
>
|
||||
<option value="All Stores">All Stores</option>
|
||||
{requestingStores.map(store => (
|
||||
<option key={store} value={store}>{store}</option>
|
||||
))}
|
||||
</select>
|
||||
<div className="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none text-slate-400 group-hover:text-[#662582] transition-colors">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="m6 9 6 6 6-6"/></svg>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setActiveTab('catalog')}
|
||||
className="flex items-center gap-1.5 bg-white border border-slate-200 text-slate-600 hover:bg-slate-50 px-4 py-2 rounded-xl text-sm font-bold shadow-sm cursor-pointer transition-colors"
|
||||
className="flex items-center gap-2 bg-white border border-slate-200 text-slate-700 hover:text-slate-900 hover:bg-slate-50 px-4 py-2.5 rounded-xl text-sm font-bold shadow-sm hover:shadow-md cursor-pointer transition-all active:scale-95"
|
||||
>
|
||||
← Back to Catalogue
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="m15 18-6-6 6-6"/></svg>
|
||||
Back to Catalogue
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{flattenedRequests.length === 0 ? (
|
||||
<div className="flex flex-col items-center justify-center h-64 bg-white/40 border border-slate-200 rounded-2xl">
|
||||
<Inbox size={48} className="text-slate-300 mb-4" />
|
||||
<h3 className="text-lg font-bold text-slate-500">No Pending Requests</h3>
|
||||
<p className="text-xs text-slate-400">All store stock requests have been processed.</p>
|
||||
<div className="flex flex-col items-center justify-center h-80 bg-gradient-to-b from-white to-slate-50 border border-slate-200/60 border-dashed rounded-2xl shadow-sm">
|
||||
<div className="w-20 h-20 rounded-full bg-slate-100/80 flex items-center justify-center mb-6 shadow-inner">
|
||||
<Inbox size={32} className="text-slate-400" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-slate-700 tracking-tight">No Pending Requests</h3>
|
||||
<p className="text-sm font-medium text-slate-400 mt-2 text-center max-w-sm leading-relaxed">
|
||||
You're all caught up! All store stock requests have been processed and there is currently no pending action required.
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="bg-white border rounded-2xl overflow-hidden" style={{ borderColor: BORDER }}>
|
||||
<div className="bg-white rounded-2xl border border-slate-200 shadow-[0_4px_20px_-4px_rgba(0,0,0,0.05)] overflow-hidden">
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full" style={{ minWidth: 960 }}>
|
||||
<table className="w-full text-left border-collapse" style={{ minWidth: 960 }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<tr className="bg-slate-50/80 border-b border-slate-200">
|
||||
{['Requested At', 'Store', 'Product', 'Qty', 'Status', 'Resolved At', ''].map((h, i) => (
|
||||
<th key={i} className="px-3 py-2.5 text-left" style={TH_STYLE}>{h}</th>
|
||||
<th key={i} className="px-5 py-4 text-[10px] font-black uppercase tracking-widest text-slate-500 whitespace-nowrap">{h}</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tbody className="divide-y divide-slate-100">
|
||||
{flattenedRequests.map((req, idx) => {
|
||||
const isApproved = req.pickData.status === 'Approved';
|
||||
const isRejected = req.pickData.status === 'Rejected';
|
||||
const isPending = req.pickData.status === 'Pending';
|
||||
const isCancelled = req.pickData.status === 'Cancelled';
|
||||
const color = isApproved ? '#10b981' : isRejected ? '#f43f5e' : isCancelled ? '#94a3b8' : '#f59e0b';
|
||||
const DIVIDER_C = '#f1f5f9';
|
||||
|
||||
return (
|
||||
<tr key={`${req.locationid}-${req.productid}-${idx}`} className="transition-colors" style={{ borderBottom: `1px solid ${DIVIDER_C}`, background: 'transparent' }}
|
||||
onMouseEnter={(e) => { e.currentTarget.style.background = SURFACE_ALT; }} onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; }}>
|
||||
<td className="px-3 py-2.5">
|
||||
<span className="text-xs font-mono" style={{ color: TEXT_3 }}>
|
||||
{req.pickData.requestedAt ? new Date(req.pickData.requestedAt).toLocaleString('en-IN', { dateStyle: 'medium', timeStyle: 'short' }) : '—'}
|
||||
</span>
|
||||
<tr
|
||||
key={`${req.locationid}-${req.productid}-${idx}`}
|
||||
className="transition-all duration-200 hover:bg-slate-50/80 group cursor-pointer"
|
||||
onClick={() => setSelectedRequest(req)}
|
||||
>
|
||||
<td className="px-5 py-4 whitespace-nowrap">
|
||||
<div className="flex flex-col">
|
||||
<span className="text-sm font-semibold text-slate-900">
|
||||
{req.pickData.requestedAt ? new Date(req.pickData.requestedAt).toLocaleDateString('en-IN', { day: 'numeric', month: 'short' }) : '—'}
|
||||
</span>
|
||||
<span className="text-xs font-medium text-slate-500">
|
||||
{req.pickData.requestedAt ? new Date(req.pickData.requestedAt).toLocaleTimeString('en-IN', { hour: '2-digit', minute: '2-digit' }) : ''}
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-3 py-2.5">
|
||||
<span className="inline-flex items-center gap-1 font-bold text-[12px]" style={{ color: BRAND }}>
|
||||
<Store size={11} /> {req.locationname}
|
||||
</span>
|
||||
<td className="px-5 py-4 whitespace-nowrap">
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1.5 rounded-lg bg-indigo-50/50 text-indigo-700 border border-indigo-100/50 transition-colors group-hover:bg-indigo-100/50">
|
||||
<Store size={14} className="text-indigo-500" />
|
||||
<span className="font-bold text-xs">{req.locationname}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-3 py-2.5">
|
||||
<td className="px-5 py-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<img src={req.product?.image} alt={req.product?.name} className="w-8 h-8 rounded-md object-cover border" style={{ borderColor: BORDER }} />
|
||||
<div>
|
||||
<p className="font-bold text-[12px] truncate max-w-[200px]" style={{ color: TEXT }}>{req.product?.name}</p>
|
||||
<p className="text-[10px] truncate max-w-[200px]" style={{ color: TEXT_2 }}>{req.product?.sku}</p>
|
||||
<div className="relative w-10 h-10 rounded-xl overflow-hidden border border-slate-200 bg-white shadow-sm shrink-0 group-hover:shadow transition-shadow">
|
||||
<img src={req.product?.image} alt={req.product?.name} className="w-full h-full object-cover" />
|
||||
</div>
|
||||
<div className="min-w-0 flex-1">
|
||||
<p className="font-bold text-sm text-slate-900 truncate group-hover:text-indigo-700 transition-colors">{req.product?.name}</p>
|
||||
<p className="text-xs font-medium text-slate-500 truncate mt-0.5">{req.product?.sku}</p>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-3 py-2.5 font-mono text-[12px]" style={{ color: TEXT }}>
|
||||
{req.pickData.qty || '—'}
|
||||
<td className="px-5 py-4 whitespace-nowrap">
|
||||
<span className="inline-flex items-center justify-center min-w-[2rem] px-2 py-1 rounded-md bg-slate-100 text-slate-700 font-bold text-sm border border-slate-200/60">
|
||||
{req.pickData.qty || '—'}
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-3 py-2.5">
|
||||
<StatusChip label={req.pickData.status || '—'} color={color} />
|
||||
<td className="px-5 py-4 whitespace-nowrap">
|
||||
<span className={`inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-bold border ${
|
||||
isApproved ? 'bg-emerald-50 text-emerald-700 border-emerald-200' :
|
||||
isRejected ? 'bg-rose-50 text-rose-700 border-rose-200' :
|
||||
isCancelled ? 'bg-slate-50 text-slate-700 border-slate-200' :
|
||||
'bg-amber-50 text-amber-700 border-amber-200'
|
||||
}`}>
|
||||
<span className={`w-1.5 h-1.5 rounded-full ${
|
||||
isApproved ? 'bg-emerald-500' :
|
||||
isRejected ? 'bg-rose-500' :
|
||||
isCancelled ? 'bg-slate-400' :
|
||||
'bg-amber-500 animate-pulse'
|
||||
}`} />
|
||||
{req.pickData.status || '—'}
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-3 py-2.5">
|
||||
<span className="text-xs font-mono" style={{ color: TEXT_3 }}>
|
||||
<td className="px-5 py-4 whitespace-nowrap">
|
||||
<span className="text-xs font-medium text-slate-500">
|
||||
{req.pickData.resolvedAt ? new Date(req.pickData.resolvedAt).toLocaleString('en-IN', { dateStyle: 'medium', timeStyle: 'short' }) : '—'}
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-3 py-2.5 text-right">
|
||||
<td className="px-5 py-4 whitespace-nowrap text-right">
|
||||
{isPending ? (
|
||||
<div className="flex items-center justify-end gap-2">
|
||||
<div className="flex items-center justify-end gap-2 opacity-0 group-hover:opacity-100 transition-opacity">
|
||||
<button
|
||||
onClick={(e) => { e.stopPropagation(); updateProductRequestStatus(req.locationid, req.productid, 'Approved'); }}
|
||||
className="rounded-full font-extrabold cursor-pointer transition-colors text-white"
|
||||
style={{ padding: '4px 12px', fontSize: 11, background: '#10b981', border: '1px solid #059669' }}
|
||||
title="Approve"
|
||||
className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-bold text-emerald-700 bg-emerald-50 hover:bg-emerald-100 hover:text-emerald-800 border border-emerald-200 transition-all active:scale-95"
|
||||
title="Approve Request"
|
||||
>
|
||||
Approve
|
||||
<CheckCircle size={14} /> Approve
|
||||
</button>
|
||||
<button
|
||||
onClick={(e) => { e.stopPropagation(); updateProductRequestStatus(req.locationid, req.productid, 'Rejected'); }}
|
||||
className="rounded-full font-extrabold cursor-pointer transition-colors"
|
||||
style={{ padding: '4px 12px', fontSize: 11, color: '#f43f5e', background: tint('#f43f5e'), border: `1px solid ${edge('#f43f5e')}` }}
|
||||
title="Reject"
|
||||
className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-bold text-rose-700 bg-rose-50 hover:bg-rose-100 hover:text-rose-800 border border-rose-200 transition-all active:scale-95"
|
||||
title="Reject Request"
|
||||
>
|
||||
Reject
|
||||
<X size={14} /> Reject
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<span className="text-[10px] font-bold text-slate-400 uppercase tracking-widest">
|
||||
<span className="text-[10px] font-bold text-slate-300 uppercase tracking-widest">
|
||||
Processed
|
||||
</span>
|
||||
)}
|
||||
|
||||
1280
src/components/PosView.tsx
Normal file
1280
src/components/PosView.tsx
Normal file
File diff suppressed because it is too large
Load Diff
@@ -540,40 +540,45 @@ export default function StoreCatalogView({ locationid, storeName = 'your store',
|
||||
sub="Browse the catalogue and add items to your store to request stock."
|
||||
/>
|
||||
) : (
|
||||
<div className="bg-white border rounded-2xl overflow-hidden" style={{ borderColor: BORDER }}>
|
||||
<div className="bg-white rounded-2xl border border-slate-200 shadow-[0_4px_20px_-4px_rgba(0,0,0,0.05)] overflow-hidden">
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full" style={{ minWidth: 800 }}>
|
||||
<table className="w-full text-left border-collapse" style={{ minWidth: 800 }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<tr className="bg-slate-50/80 border-b border-slate-200">
|
||||
{['Requested At', 'Product', 'Qty', 'Status', 'Resolved At'].map((h, i) => (
|
||||
<th key={i} className="px-3 py-2.5 text-left" style={TH_STYLE}>{h}</th>
|
||||
<th key={i} className="px-5 py-4 text-[10px] font-black uppercase tracking-widest text-slate-500 whitespace-nowrap">{h}</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tbody className="divide-y divide-slate-100">
|
||||
{Object.entries(picks).map(([pid, data]: [string, any]) => {
|
||||
const prod = products.find(p => p.id === pid);
|
||||
const isApproved = data.status === 'Approved';
|
||||
const isRejected = data.status === 'Rejected';
|
||||
const color = isApproved ? '#10b981' : isRejected ? '#f43f5e' : data.status === 'Cancelled' ? '#94a3b8' : '#f59e0b';
|
||||
const DIVIDER_C = '#f1f5f9';
|
||||
const isCancelled = data.status === 'Cancelled';
|
||||
|
||||
return (
|
||||
<tr key={pid} className="transition-colors" style={{ borderBottom: `1px solid ${DIVIDER_C}`, background: 'transparent' }}
|
||||
onMouseEnter={(e) => { e.currentTarget.style.background = SURFACE_ALT; }} onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; }}>
|
||||
<td className="px-3 py-2.5">
|
||||
<span className="text-xs font-mono" style={{ color: TEXT_3 }}>
|
||||
{data.requestedAt ? new Date(data.requestedAt).toLocaleString('en-IN', { dateStyle: 'medium', timeStyle: 'short' }) : '—'}
|
||||
</span>
|
||||
<tr key={pid} className="transition-all duration-200 hover:bg-slate-50/80 group">
|
||||
<td className="px-5 py-4 whitespace-nowrap">
|
||||
<div className="flex flex-col">
|
||||
<span className="text-sm font-semibold text-slate-900">
|
||||
{data.requestedAt ? new Date(data.requestedAt).toLocaleDateString('en-IN', { day: 'numeric', month: 'short' }) : '—'}
|
||||
</span>
|
||||
<span className="text-xs font-medium text-slate-500">
|
||||
{data.requestedAt ? new Date(data.requestedAt).toLocaleTimeString('en-IN', { hour: '2-digit', minute: '2-digit' }) : ''}
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-3 py-2.5">
|
||||
<td className="px-5 py-4">
|
||||
<div className="flex items-center gap-3">
|
||||
{prod ? (
|
||||
<>
|
||||
<img src={prod.image} alt={prod.name} className="w-8 h-8 rounded-md object-cover border" style={{ borderColor: BORDER }} />
|
||||
<div>
|
||||
<p className="font-bold text-[12px] truncate max-w-[200px]" style={{ color: TEXT }}>{prod.name}</p>
|
||||
<p className="text-[10px] truncate max-w-[200px]" style={{ color: TEXT_2 }}>{prod.sku}</p>
|
||||
<div className="relative w-10 h-10 rounded-xl overflow-hidden border border-slate-200 bg-white shadow-sm shrink-0 group-hover:shadow transition-shadow">
|
||||
<img src={prod.image} alt={prod.name} className="w-full h-full object-cover" />
|
||||
</div>
|
||||
<div className="min-w-0 flex-1">
|
||||
<p className="font-bold text-sm text-slate-900 truncate group-hover:text-indigo-700 transition-colors">{prod.name}</p>
|
||||
<p className="text-xs font-medium text-slate-500 truncate mt-0.5">{prod.sku}</p>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
@@ -581,14 +586,29 @@ export default function StoreCatalogView({ locationid, storeName = 'your store',
|
||||
)}
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-3 py-2.5 font-mono text-[12px]" style={{ color: TEXT }}>
|
||||
{data.qty || '—'}
|
||||
<td className="px-5 py-4 whitespace-nowrap">
|
||||
<span className="inline-flex items-center justify-center min-w-[2rem] px-2 py-1 rounded-md bg-slate-100 text-slate-700 font-bold text-sm border border-slate-200/60">
|
||||
{data.qty || '—'}
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-3 py-2.5">
|
||||
<StatusChip label={data.status || '—'} color={color} />
|
||||
<td className="px-5 py-4 whitespace-nowrap">
|
||||
<span className={`inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-bold border ${
|
||||
isApproved ? 'bg-emerald-50 text-emerald-700 border-emerald-200' :
|
||||
isRejected ? 'bg-rose-50 text-rose-700 border-rose-200' :
|
||||
isCancelled ? 'bg-slate-50 text-slate-700 border-slate-200' :
|
||||
'bg-amber-50 text-amber-700 border-amber-200'
|
||||
}`}>
|
||||
<span className={`w-1.5 h-1.5 rounded-full ${
|
||||
isApproved ? 'bg-emerald-500' :
|
||||
isRejected ? 'bg-rose-500' :
|
||||
isCancelled ? 'bg-slate-400' :
|
||||
'bg-amber-500 animate-pulse'
|
||||
}`} />
|
||||
{data.status || '—'}
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-3 py-2.5">
|
||||
<span className="text-xs font-mono" style={{ color: TEXT_3 }}>
|
||||
<td className="px-5 py-4 whitespace-nowrap">
|
||||
<span className="text-xs font-medium text-slate-500">
|
||||
{data.resolvedAt ? new Date(data.resolvedAt).toLocaleString('en-IN', { dateStyle: 'medium', timeStyle: 'short' }) : '—'}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
@@ -34,6 +34,7 @@ import StoreCatalogView from './StoreCatalogView';
|
||||
import DispatchHubView from './DispatchHubView';
|
||||
import DeliveryReportsView from './DeliveryReportsView';
|
||||
import StoreQRView from './StoreQRView';
|
||||
import PosView from './PosView';
|
||||
import UserStoreSidebar, { type UserNavItem } from './UserStoreSidebar';
|
||||
import ComparisonModal from './ComparisonModal';
|
||||
interface UserStorePageProps {
|
||||
@@ -48,6 +49,7 @@ interface UserStorePageProps {
|
||||
const NAV_ITEMS: UserNavItem[] = [
|
||||
{ id: 'console', label: 'Store Console', icon: LayoutDashboard },
|
||||
{ id: 'inventory', label: 'Products', icon: Layers },
|
||||
{ id: 'pos', label: 'POS Terminal', icon: ShoppingBag },
|
||||
{ id: 'customers', label: 'Customers', icon: Users },
|
||||
{ id: 'dispatch', label: 'Dispatch', icon: Route },
|
||||
{ id: 'reports', label: 'Reports', icon: ClipboardList },
|
||||
@@ -191,6 +193,7 @@ export default function UserStorePage({ onLogout, user }: UserStorePageProps) {
|
||||
|
||||
// Logistics console — scoped to this user's store. These views own their
|
||||
// loading/error states, so they don't need the store-console load gating below.
|
||||
if (activeSection === 'pos') return <PosView locationid={resolvedLocationId || undefined} tenantId={tenantId} />;
|
||||
if (activeSection === 'dispatch') return <DispatchHubView locationid={resolvedLocationId || undefined} tenantId={tenantId} />;
|
||||
if (activeSection === 'reports') return <DeliveryReportsView tenantId={tenantId} locationid={resolvedLocationId || undefined} />;
|
||||
// Inventory & Catalog is its own page: the manager-curated catalog the user
|
||||
@@ -278,6 +281,8 @@ export default function UserStorePage({ onLogout, user }: UserStorePageProps) {
|
||||
? storeName
|
||||
: activeSection === 'inventory'
|
||||
? 'Products'
|
||||
: activeSection === 'pos'
|
||||
? 'POS Terminal'
|
||||
: activeSection === 'account'
|
||||
? 'My Account'
|
||||
: activeSection.charAt(0).toUpperCase() + activeSection.slice(1),
|
||||
@@ -285,6 +290,8 @@ export default function UserStorePage({ onLogout, user }: UserStorePageProps) {
|
||||
? LayoutDashboard
|
||||
: activeSection === 'inventory'
|
||||
? Layers
|
||||
: activeSection === 'pos'
|
||||
? ShoppingBag
|
||||
: activeSection === 'customers'
|
||||
? Users
|
||||
: activeSection === 'dispatch'
|
||||
@@ -307,10 +314,10 @@ export default function UserStorePage({ onLogout, user }: UserStorePageProps) {
|
||||
className={`flex-1 min-w-0 transition-all duration-300 ${
|
||||
// Dispatch is a full-bleed cockpit — fill the area exactly (no page
|
||||
// padding) so it sits flush under the header. Other pages stay padded.
|
||||
activeSection === 'dispatch' ? 'h-[calc(100vh-64px)] overflow-hidden' : 'min-h-[calc(100vh-64px)]'
|
||||
activeSection === 'dispatch' || activeSection === 'pos' ? 'h-[calc(100vh-64px)] overflow-hidden' : 'min-h-[calc(100vh-64px)]'
|
||||
} ${sidebarOpen ? 'md:pl-64' : 'md:pl-20'}`}
|
||||
>
|
||||
{activeSection === 'dispatch' ? (
|
||||
{activeSection === 'dispatch' || activeSection === 'pos' ? (
|
||||
<div className="w-full h-full">{renderSection()}</div>
|
||||
) : (
|
||||
<div className="w-full p-container-margin md:p-xl space-y-lg transition-all duration-300">
|
||||
|
||||
Reference in New Issue
Block a user