A full-stack web application for clothing retailers to bulk upload deadstock inventory, auto-price items using dynamic multipliers, and list them to distribution partners.
π Quick Start β’ π€ Upload Guide β’ π° Pricing Logic β’ π§ͺ Tests
- π Secure Authentication β Email/password login with Supabase Auth
- π Bulk CSV Upload β Drag-and-drop inventory uploads with real-time progress
- β Smart Validation β Row-by-row validation with clear, actionable error messages
- π° Dynamic Pricing β Automatic resale price calculation based on condition & category
- π Inventory Dashboard β Filter, search, and manage items with bulk actions
- π Listing Workflow β Select items and list to distribution partners in one click
- β‘ Real-time Updates β Live processing status via Supabase Realtime
| Tool | Version | Purpose |
|---|---|---|
| Node.js | 24+ | JavaScript runtime |
| pnpm | Latest | Package manager |
| Supabase CLI | v1.0+ | Local backend development |
| Docker | Latest | Supabase local services |
You can sign in using either:
- Google SSO - Quick and secure login with your Google account
- Email & Password - Use your credentials and check your email for confirmation
# Clone the repository
git clone https://github.com/odhiambo-ed/ReUbuntu.git
cd ReUbuntu
# Install frontend dependencies
cd frontend
pnpm install# Navigate to backend
cd backend/supabase
# Start Supabase local services
supabase start
# Apply migrations (runs automatically, or reset with):
supabase db resetπ For detailed backend setup, see Backend README
# In frontend directory
cp .env.example .env.localUpdate .env.local:
NEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321
NEXT_PUBLIC_SUPABASE_ANON_KEY=<your-local-anon-key>cd frontend
pnpm devπ Open http://localhost:3000
- Login β Use test credentials above
- Navigate β Click "Upload Inventory" in sidebar
- Select File β Drag & drop or click "Browse Files"
- Process β Click "Upload & Process"
- Review β View success/error summary with details
- Explore β Click "View Inventory" to see imported items
| Column | Required | Valid Values | Example |
|---|---|---|---|
merchant_id |
β | Non-empty string | MERCHANT001 |
sku |
β | Unique per merchant | SKU-12345 |
title |
β | Product name | Blue Denim Jacket |
brand |
β | Brand name | Levi's |
category |
β | See categories below | Jackets |
condition |
β | new, like_new, good, fair |
good |
original_price |
β | Positive number | 899.00 |
currency |
β | Currency code | ZAR |
quantity |
β | Positive integer (default: 1) | 5 |
Valid Categories: Tops, Bottoms, Outerwear, Jackets, Dresses, Knitwear, Shoes, Accessories, Activewear
merchant_id,sku,title,brand,category,condition,original_price,currency,quantity
MERCHANT001,SKU-001,Blue Denim Jacket,Levi's,Jackets,good,899.00,ZAR,1
MERCHANT001,SKU-002,White Cotton T-Shirt,H&M,Tops,new,199.00,ZAR,3
MERCHANT001,SKU-003,Black Running Shoes,Nike,Shoes,like_new,1299.00,ZAR,1Resale prices are automatically calculated using database triggers:
resale_price = original_price Γ condition_multiplier Γ category_multiplier
| Condition | Multiplier | Description |
|---|---|---|
new |
0.70 | Brand new with tags |
like_new |
0.60 | Like new, minimal wear |
good |
0.50 | Good condition |
fair |
0.35 | Fair, visible wear |
| Category | Multiplier | Category | Multiplier | |
|---|---|---|---|---|
| Outerwear | 1.10 | Knitwear | 0.90 | |
| Jackets | 1.05 | Bottoms | 0.85 | |
| Dresses | 1.00 | Tops | 0.80 | |
| Shoes | 0.95 | Accessories | 0.75 |
Item: Blue Denim Jacket
Price: R899.00
Condition: good (Γ0.50)
Category: Jackets (Γ1.05)
βββββββββββββββββββββββββββββ
Resale: R899 Γ 0.50 Γ 1.05 = R471.98
cd frontend
npm test # Run all tests
npm test -- --coverage # With coverage report
npm test -- --watch # Watch modecd backend/supabase/functions/process-csv-upload
deno test --allow-read # Run Edge Function tests| Area | Tests | Coverage |
|---|---|---|
| CSV Validation | β | Required fields, value validation, format checks |
| Pricing Logic | β | Multiplier calculations, rounding, edge cases |
| Upload Hooks | β | API calls, state management, error handling |
| Inventory Actions | β | Bulk operations, status updates |
muna-deadstock-portal/
βββ π frontend/ # Next.js 14 Application
β βββ app/ # App Router pages
β β βββ auth/ # Login/Register
β β βββ dashboard/ # Protected routes
β βββ components/ # Reusable UI components
β βββ features/ # Feature modules
β β βββ inventory/ # Inventory management
β β βββ uploads/ # CSV upload logic
β β βββ pricing/ # Pricing utilities
β βββ lib/ # Supabase client, utils
β βββ __tests__/ # Jest test suites
β
βββ π backend/
β βββ supabase/
β βββ functions/ # Edge Functions
β β βββ process-csv-upload/ # CSV processor
β βββ migrations/ # Database schema
β
βββ π prds/ # Technical documentation
βββ π sample-data/ # Sample CSV files
π Frontend README | Backend README
| Assumption | Implication |
|---|---|
| Single Currency (ZAR) | Currency stored but not converted; multi-currency is future enhancement |
| SKU Unique per Merchant | Same SKU allowed for different merchants; constraint on (user_id, merchant_id, sku) |
| Listing = Status Change | "Listing" simulated as internal status update, not external API call |
| Browser Support | Modern browsers only (Chrome, Firefox, Safari, Edge - latest 2 versions) |
| Decision | Tradeoff | Reasoning |
|---|---|---|
| Async Edge Function Processing | More complex than sync | Non-blocking UX; handles large files without timeout |
| Strict Category Validation | No custom categories | Ensures consistent pricing; category management can be added |
| Database-Level Price Triggers | Logic in DB | Single source of truth; auto-recalculates on updates |
| Partial Success Processing | More complex UI | One bad row shouldn't block 999 good ones |
- β Row Level Security (RLS) on all tables
- β
User data isolation by
user_id - β Supabase Auth for authentication
- β File validation for type (CSV only) and size (5MB limit)
- β Middleware protection on all API routes
| Layer | Technology |
|---|---|
| Frontend | Next.js 14, React 18, TypeScript |
| Styling | Tailwind CSS, shadcn/ui, Lucide Icons |
| Backend | Supabase (PostgreSQL, Auth, Storage) |
| Edge Functions | Deno, Supabase Edge Functions |
| Validation | Zod (client & server) |
| Testing | Jest, React Testing Library, Deno Test |
Edward Odhiambo
Contributions, issues, and feature requests are welcome!
Feel free to check the issues page
Give a βοΈ if you like this project!
This project is MIT licensed.
Built with β€οΈ for Muna Deadstock Assessment
January 2026
