A production-style web application for processing, validating, and managing inventory data. Built with React, TypeScript, Vite, and Supabase.
This application simulates a real internal business tool for inventory data processing and validation. Users can:
- Upload CSV or Excel inventory files
- Parse files client-side with PapaParse and SheetJS
- Validate data with Zod schemas and business rules
- Preview parsed data before submission
- Process valid rows into inventory movements
- Monitor dashboards, batch uploads, and error reports
- CSV parsing with PapaParse
- Excel (.xlsx, .xls) parsing with SheetJS
- Header mapping with common aliases
- Data normalization (trimming, case conversion, date formatting)
- Zod schema validation
- Business rule enforcement
- Duplicate detection
- Detailed error messages per row
- PostgreSQL with Supabase
- Staging table workflow
- Batch processing via RPC functions
- Auto-creation of products/warehouses
- Real-time inventory summary
- Low stock alerts
- Upload batch history
- Invalid row diagnostics
inventory-data-processing-platform/
├── public/
│ ├── sample-inventory.csv # Sample valid file for testing
│ └── sample-with-errors.csv # Sample file with invalid rows
├── src/
│ ├── components/ # Reusable UI components
│ │ ├── ui/ # Base components (LoadingSpinner, etc.)
│ │ ├── DataPreviewTable.tsx
│ │ ├── Layout.tsx
│ │ └── ValidationSummary.tsx
│ ├── lib/
│ │ └── supabase.ts # Supabase client configuration
│ ├── pages/
│ │ ├── BatchesPage.tsx # Upload history
│ │ ├── DashboardPage.tsx # Main dashboard
│ │ ├── ErrorsPage.tsx # Invalid row viewer
│ │ ├── InventoryPage.tsx # Stock levels
│ │ └── UploadPage.tsx # File upload
│ ├── services/
│ │ └── inventoryService.ts # Database operations
│ ├── types/
│ │ └── database.ts # TypeScript interfaces
│ ├── utils/
│ │ ├── formatters.ts # Display formatters
│ │ ├── normalizeRows.ts # Data normalization
│ │ ├── parseCsv.ts # CSV parsing
│ │ ├── parseExcel.ts # Excel parsing
│ │ └── validateRows.ts # Zod validation
│ ├── App.tsx
│ ├── index.css
│ └── main.tsx
├── supabase/
│ ├── migrations/
│ │ ├── 001_schema.sql # Database tables
│ │ └── 002_rpc_functions.sql # PostgreSQL functions
│ └── seed.sql # Sample data
├── package.json
├── tailwind.config.js
├── tsconfig.json
└── vite.config.ts
- Node.js 18+
- npm or yarn
- Supabase account (free tier works)
cd inventory-data-processing-platform
npm install-
Create a new project at supabase.com
-
Go to Settings > API and copy your:
- Project URL
- Anon public key
-
Create
.envfrom the example:
cp .env.example .env- Add your credentials to
.env:
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=your-anon-key- Go to SQL Editor in your Supabase dashboard
- Run the migrations in order:
- Copy and run
supabase/migrations/001_schema.sql - Copy and run
supabase/migrations/002_rpc_functions.sql
- Copy and run
- (Optional) Run
supabase/seed.sqlto add sample data
npm run devOpen http://localhost:3000 in your browser.
| Table | Description |
|---|---|
products |
Product catalog with SKU and min_stock |
warehouses |
Warehouse/location master data |
upload_batches |
File upload metadata and status |
staging_inventory_rows |
Raw parsed rows awaiting processing |
inventory_movements |
Validated IN/OUT transactions |
| Function | Description |
|---|---|
get_inventory_summary() |
Current stock by product (IN - OUT) |
get_low_stock_products() |
Products below min_stock threshold |
get_dashboard_metrics() |
Aggregated dashboard statistics |
process_staging_to_movements(batch_id) |
Move valid staging rows to movements |
get_batch_summary(batch_id) |
Detailed status for a specific batch |
sku,product_name,warehouse,movement_type,quantity,unit_cost,movement_date,reference
A100,Oil Filter,Main Warehouse,IN,50,120.50,2025-03-01,PO-1001
A100,Oil Filter,Main Warehouse,OUT,10,120.50,2025-03-02,SO-2001| Column | Required | Rules |
|---|---|---|
sku |
Yes | Non-empty string, max 50 chars |
product_name |
Yes | Non-empty string, max 255 chars |
warehouse |
Yes | Non-empty string, max 100 chars |
movement_type |
Yes | Must be IN or OUT |
quantity |
Yes | Positive integer |
unit_cost |
Yes | Non-negative decimal |
movement_date |
Yes | Valid date (YYYY-MM-DD or MM/DD/YYYY) |
reference |
No | PO/SO number, max 100 chars |
The parser supports common header variations:
sku,product_sku,item_skuproduct_name,name,item_namewarehouse,warehouse_name,locationmovement_type,typequantity,qty,amountunit_cost,cost,pricemovement_date,datereference,ref,po_number
- Download sample files from the
public/folder - Navigate to the Upload page
- Upload
sample-inventory.csvfor valid data - Upload
sample-with-errors.csvto test error handling - Check the Dashboard for updated metrics
- View Batches for upload history
- Check Errors page for invalid row details
npm run dev # Start dev server
npm run build # Production build
npm run preview # Preview production build
npm run lint # Run ESLint
npm run type-check # TypeScript type checking- Frontend: React 18, TypeScript 5, Vite 5
- Styling: Tailwind CSS 3
- Icons: Lucide React
- Routing: React Router 6
- File Parsing: PapaParse, SheetJS (xlsx)
- Validation: Zod
- Backend: Supabase (PostgreSQL + PostgREST)
- User authentication with Supabase Auth
- Row-Level Security (RLS) policies
- Audit logging for data changes
- Negative stock prevention in SQL
- Batch reprocessing workflow
- Export processed data to CSV
- Product/warehouse management UI
- Movement history per product
- Supabase Edge Functions for heavy processing
- Background job queue for large files
- Email notifications for low stock
- Scheduled inventory reports
- Dark mode support
- Mobile responsive navigation
- Real-time updates with Supabase subscriptions
- Data visualization charts
- Batch progress indicators
- CI/CD pipeline
- Environment-based configurations
- Error tracking (Sentry)
- Performance monitoring
MIT License - feel free to use this project as a portfolio piece or starting point for your own inventory system.
Contributions are welcome! Please feel free to submit issues and pull requests.
Built with ❤️ using React, TypeScript, and Supabase