offline sales upload

This commit is contained in:
2026-07-30 17:23:21 +05:30
parent eb6e750b6a
commit 9990355e19
7 changed files with 1316 additions and 3 deletions

View File

@@ -55,6 +55,7 @@ import AwaitingApi from './AwaitingApi';
import { SlideDrawer, Skeleton, TH_STYLE, SURFACE_ALT, TEXT, TEXT_2, TEXT_3, BORDER, BRAND, tint, edge, StatusChip } from './consoleUi';
import FMCGHoverOverlay from './FMCGHoverOverlay';
import CatalogueBrowser from './CatalogueBrowser';
import OfflineSalesUpload from './OfflineSalesUpload';
import { useCompare } from '../contexts/CompareContext';
@@ -79,6 +80,7 @@ export default function InventoryView({
const { setHideCompareBar } = useCompare();
const [searchTerm, setSearchTerm] = useState('');
const [showCatalogueModal, setShowCatalogueModal] = useState(false);
const [showOfflineSales, setShowOfflineSales] = useState(false);
const navigate = useNavigate();
// ── Live stock across every outlet (Fiesta) ───────────────────────────────
@@ -528,6 +530,13 @@ export default function InventoryView({
<span className="ml-1 bg-rose-500 text-white text-[8px] px-1 py-0.5 rounded-sm leading-none">{storeRequests.length}</span>
)}
</button>
<button
onClick={() => setShowOfflineSales(true)}
title="Upload an Excel sheet of counter sales to deduct stock and record the revenue"
className="flex items-center gap-1.5 bg-slate-50 hover:bg-slate-100 border border-slate-200 text-slate-700 px-2.5 py-1.5 rounded-lg text-[10px] font-bold transition-colors shadow-sm cursor-pointer h-[32px] whitespace-nowrap"
>
<UploadCloud size={12} /> Offline Sales
</button>
<button
onClick={() => setActiveTab('global_catalogue')}
className="flex items-center gap-1.5 bg-[#662582] hover:bg-purple-800 text-white px-2.5 py-1.5 rounded-lg text-[10px] font-bold transition-colors shadow-sm cursor-pointer h-[32px] whitespace-nowrap"
@@ -1098,6 +1107,18 @@ export default function InventoryView({
})()}
</SlideDrawer>
{/* Offline (counter) sales import. `locations` is passed so an admin picks
the branch the bills belong to — this view otherwise operates on the
tenant's first outlet, which would silently credit the wrong store. */}
{showOfflineSales && (
<OfflineSalesUpload
tenantId={tenantId}
locationId={primaryLocationId}
locations={locations.map(({ locationid, locationname }) => ({ locationid, locationname }))}
onClose={() => setShowOfflineSales(false)}
/>
)}
</div>
);
}