Skip to content

Latest commit

Β 

History

148 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🏷️ Muna Deadstock Intake & Listing Portal

Empowering Clothing Retailers in the Secondary Market

Next.js Supabase TypeScript TailwindCSS


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


πŸ“Έ Sneak Peek

Application Preview


✨ Features

  • πŸ” 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

πŸš€ Quick Start

Prerequisites

Tool Version Purpose
Node.js 24+ JavaScript runtime
pnpm Latest Package manager
Supabase CLI v1.0+ Local backend development
Docker Latest Supabase local services

πŸ”‘ Login Options

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

πŸ“‹ Setup Instructions

1. Clone & Install

# Clone the repository
git clone https://github.com/odhiambo-ed/ReUbuntu.git
cd ReUbuntu

# Install frontend dependencies
cd frontend
pnpm install

2. Backend Setup

# 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

3. Environment Configuration

# In frontend directory
cp .env.example .env.local

Update .env.local:

NEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321
NEXT_PUBLIC_SUPABASE_ANON_KEY=<your-local-anon-key>

4. Launch Application

cd frontend
pnpm dev

🌐 Open http://localhost:3000


πŸ“€ How to Upload CSV

Step-by-Step Guide

  1. Login β†’ Use test credentials above
  2. Navigate β†’ Click "Upload Inventory" in sidebar
  3. Select File β†’ Drag & drop or click "Browse Files"
  4. Process β†’ Click "Upload & Process"
  5. Review β†’ View success/error summary with details
  6. Explore β†’ Click "View Inventory" to see imported items

πŸ“„ CSV Format Specification

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

Sample CSV

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,1

πŸ’° Pricing Logic

Resale prices are automatically calculated using database triggers:

resale_price = original_price Γ— condition_multiplier Γ— category_multiplier

Condition Multipliers

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 Multipliers

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

πŸ“Š Example Calculation

Item:        Blue Denim Jacket
Price:       R899.00
Condition:   good (Γ—0.50)
Category:    Jackets (Γ—1.05)
─────────────────────────────
Resale:      R899 Γ— 0.50 Γ— 1.05 = R471.98

πŸ§ͺ Running Tests

Frontend Tests

cd frontend
npm test                 # Run all tests
npm test -- --coverage   # With coverage report
npm test -- --watch      # Watch mode

Backend Tests

cd backend/supabase/functions/process-csv-upload
deno test --allow-read   # Run Edge Function tests

Test Coverage

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

πŸ“ Project Structure

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


πŸ“ Key Assumptions & Tradeoffs

Assumptions

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)

Technical Tradeoffs

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

πŸ”’ Security

  • βœ… 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

πŸ› οΈ Tech Stack

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

πŸ‘¨β€πŸ’» Author

Edward

Edward Odhiambo

GitHub Twitter LinkedIn Portfolio


🀝 Contributing

Contributions, issues, and feature requests are welcome!

Feel free to check the issues page


⭐ Show Your Support

Give a ⭐️ if you like this project!


πŸ“ License

This project is MIT licensed.


Built with ❀️ for Muna Deadstock Assessment

January 2026

About

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.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages