# Project export: Yourdrobe

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: Cal Hacks 12.0
- Tagline: Your digital wardrobe
- Devpost: https://devpost.com/software/yourdrobe-dto481
- GitHub: http://github.com/4aidan/yourdrobe
- Team: 2 GitHub contributor(s) — 4aidan (3 commits), StevenAD-code (3 commits)

## Devpost submission (written by the team)

### Inspiration

Both of us have creative backgrounds and exploring tech, wanted to create a tool that helps us. It created a digital wardrobe from pictures of your clothing and you select daily what clothes you will wear, and over time the app can see what clothes you are NOT wearing and suggest to sell the clothes on ecommerce cites like depop/grailed and it uses AI to generate descriptions-tags-title for you and uploads to the said website.

## README (from the GitHub repository)

# YourDrobe - Digital Wardrobe Management

A full-stack application for managing your wardrobe, creating outfits, and tracking clothing usage.

## 🏗️ Architecture

- **Frontend**: React + TypeScript + Vite + TailwindCSS
- **Backend**: FastAPI (Python 3.13)
- **Database**: MongoDB Atlas
- **Authentication**: JWT-based

## 📋 Prerequisites

- Python 3.13+
- Node.js 18+
- MongoDB Atlas account (free tier available)

## 🚀 Quick Start

### 1. Backend Setup

```bash
# Navigate to backend directory
cd backend

# Create virtual environment
python3.13 -m venv venv

# Activate virtual environment
# On macOS/Linux:
source venv/bin/activate
# On Windows:
# venv\Scripts\activate

# Install dependencies
pip install -r requirements.txt

# Create .env file from example
cp .env.example .env

# Edit .env and add your MongoDB Atlas URI and other settings
# Get MongoDB URI from: https://cloud.mongodb.com
```

**Required Environment Variables** (in `backend/.env`):
```
APP_ENV=development
PORT=8000
MONGODB_URI=mongodb+srv://user:pass@cluster.mongodb.net/yourdrobe?retryWrites=true&w=majority
JWT_SECRET=your-super-secret-key-min-32-characters-long
JWT_EXPIRES_IN=604800
CORS_ORIGINS=http://localhost:5173,http://localhost:3000
```

**Start the backend server:**
```bash
uvicorn main:app --reload --port 8000
```

The backend will be available at `http://localhost:8000`

### 2. Frontend Setup

```bash
# Navigate to frontend directory
cd frontend

# Install dependencies
npm install

# Start development server
npm run dev
```

The frontend will be available at `http://localhost:5173`

## 🗄️ MongoDB Atlas Setup

1. Create account at [https://cloud.mongodb.com](https://cloud.mongodb.com)
2. Create a new cluster (free tier M0 is sufficient)
3. Create a database user with read/write permissions
4. Whitelist your IP address (or use `0.0.0.0/0` for development)
5. Get your connection string from the "Connect" button
6. Add the connection string to `backend/.env` as `MONGODB_URI`

## 🧪 Testing the Application

### Backend Health Check

Visit `http://localhost:8000/healthz` to verify:
- Backend is running
- Database connection is established

Expected response:
```json
{
  "status": "healthy",
  "database": "connected"
}
```

### API Documentation

FastAPI provides automatic interactive API documentation:
- Swagger UI: `http://localhost:8000/docs`
- ReDoc: `http://localhost:8000/redoc`

## 📁 Project Structure

```
yourdrobe/
├── backend/
│   ├── main.py              # FastAPI application entry point
│   ├── config.py            # Settings management with Pydantic
│   ├── database.py          # MongoDB connection with Motor
│   ├── requirements.txt     # Python dependencies
│   ├── .env.example         # Environment variables template
│   └── .env                 # Your environment variables (not in git)
├── frontend/
│   ├── src/
│   │   ├── components/      # React components
│   │   ├── config/
│   │   │   └── api.ts       # API configuration
│   │   ├── pages/           # Page components
│   │   ├── types/           # TypeScript types
│   │   └── utils/           # Utility functions
│   ├── package.json
│   └── vite.config.ts
├── .gitignore
└── README.md
```

## 🎯 Sprint 0 Status - ✅ COMPLETED

Sprint 0 has been completed with the following deliverables:

- ✅ FastAPI backend structure created
- ✅ MongoDB connection implemented with Motor
- ✅ `/healthz` endpoint with database health check
- ✅ CORS middleware configured for frontend
- ✅ Frontend API configuration created
- ✅ Git repository initialized with proper `.gitignore`
- ✅ Initial commit pushed to `main` branch

## 🔜 Next Steps (Sprint 1)

Sprint 1 will implement:
- User registration (signup)
- User login with JWT tokens
- User logout
- Protected routes and authentication middleware

## 🛠️ Development Workflow

1. Create a `.env` file in the `backend/` directory (copy from `.env.example`)
2. Start the backend server: `uvicorn backend.main:app --reload`
3. Start the frontend dev server: `npm run dev` (in `frontend/` directory)
4. Make changes and test via the frontend UI
5. Commit changes to the `main` branch after testing

## 📝 Notes

- The backend uses async/await with Motor for MongoDB operations
- All passwords will be hashed with Argon2 (Sprint 1+)
- JWT tokens expire after 7 days by default
- CORS is configured to allow requests from the frontend

## 🐛 Troubleshooting

**Backend won't start:**
- Verify Python 3.13+ is installed: `python3 --version`
- Ensure virtual environment is activated
- Check that all dependencies are installed: `pip list`
- Verify `.env` file exists with correct values

**Database connection fails:**
- Verify MongoDB Atlas URI is correct
- Check that your IP is whitelisted in MongoDB Atlas
- Ensure database user has proper permissions
- Test connection in MongoDB Compass

**Frontend can't connect to backend:**
- Verify backend is running on port 8000
- Check CORS settings in `backend/main.py`
- Verify `API_BASE_URL` in `frontend/src/config/api.ts`

## 📄 License

This project is part of the YourDrobe application development.# yourdrobe


## Detected evidence (automated analysis)

Indexed codebase: 86 recognized source files, 475 KB.
- CSS (language) — detected in the code
- FastAPI (technology) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code

## Codebase structure (from repository index)

### Files (95 of 95)

```
Backend-dev-plan.md
backend/config.py
backend/database.py
backend/main.py
backend/requirements.txt
desktop.ini
frontend/AI_RULES.md
frontend/components.json
frontend/eslint.config.js
frontend/index.html
frontend/package.json
frontend/postcss.config.js
frontend/PRD-Template.md
frontend/PRD.md
frontend/public/robots.txt
frontend/README.md
frontend/src/App.css
frontend/src/App.tsx
frontend/src/components/AnalyticsView.tsx
frontend/src/components/CalendarView.tsx
frontend/src/components/made-with-dyad.tsx
frontend/src/components/OutfitBuilder.tsx
frontend/src/components/ui/accordion.tsx
frontend/src/components/ui/alert-dialog.tsx
frontend/src/components/ui/alert.tsx
frontend/src/components/ui/aspect-ratio.tsx
frontend/src/components/ui/avatar.tsx
frontend/src/components/ui/badge.tsx
frontend/src/components/ui/breadcrumb.tsx
frontend/src/components/ui/button.tsx
frontend/src/components/ui/calendar.tsx
frontend/src/components/ui/card.tsx
frontend/src/components/ui/carousel.tsx
frontend/src/components/ui/chart.tsx
frontend/src/components/ui/checkbox.tsx
frontend/src/components/ui/collapsible.tsx
frontend/src/components/ui/command.tsx
frontend/src/components/ui/context-menu.tsx
frontend/src/components/ui/dialog.tsx
frontend/src/components/ui/drawer.tsx
frontend/src/components/ui/dropdown-menu.tsx
frontend/src/components/ui/form.tsx
frontend/src/components/ui/hover-card.tsx
frontend/src/components/ui/input-otp.tsx
frontend/src/components/ui/input.tsx
frontend/src/components/ui/label.tsx
frontend/src/components/ui/menubar.tsx
frontend/src/components/ui/navigation-menu.tsx
frontend/src/components/ui/pagination.tsx
frontend/src/components/ui/popover.tsx
frontend/src/components/ui/progress.tsx
frontend/src/components/ui/radio-group.tsx
frontend/src/components/ui/resizable.tsx
frontend/src/components/ui/scroll-area.tsx
frontend/src/components/ui/select.tsx
frontend/src/components/ui/separator.tsx
frontend/src/components/ui/sheet.tsx
frontend/src/components/ui/sidebar.tsx
frontend/src/components/ui/skeleton.tsx
frontend/src/components/ui/slider.tsx
frontend/src/components/ui/sonner.tsx
frontend/src/components/ui/switch.tsx
frontend/src/components/ui/table.tsx
frontend/src/components/ui/tabs.tsx
frontend/src/components/ui/textarea.tsx
frontend/src/components/ui/toast.tsx
frontend/src/components/ui/toaster.tsx
frontend/src/components/ui/toggle-group.tsx
frontend/src/components/ui/toggle.tsx
frontend/src/components/ui/tooltip.tsx
frontend/src/components/ui/use-toast.ts
frontend/src/components/UploadView.tsx
frontend/src/components/WardrobeView.tsx
frontend/src/config/api.ts
frontend/src/globals.css
frontend/src/hooks/use-mobile.tsx
frontend/src/hooks/use-toast.ts
frontend/src/lib/utils.ts
frontend/src/main.tsx
frontend/src/pages/Index.tsx
frontend/src/pages/NotFound.tsx
frontend/src/types/wardrobe.ts
frontend/src/utils/aiOutfitGenerator.ts
frontend/src/utils/storage.ts
frontend/src/utils/toast.ts
frontend/src/vite-env.d.ts
frontend/tailwind.config.ts
frontend/tsconfig.app.json
frontend/tsconfig.json
frontend/tsconfig.node.json
frontend/vercel.json
frontend/vite.config.ts
netlify.toml
README.md
Test-Plan.md
```

### Dependencies

- backend/requirements.txt: fastapi, motor, pydantic@>=2.0, pydantic-settings, python-multipart, uvicorn[standard]
- frontend/package.json: @dyad-sh/react-vite-component-tagger@^0.8.0, @eslint/js@^9.9.0, @hookform/resolvers@^3.9.0, @radix-ui/react-accordion@^1.2.0, @radix-ui/react-alert-dialog@^1.1.1, @radix-ui/react-aspect-ratio@^1.1.0, @radix-ui/react-avatar@^1.1.0, @radix-ui/react-checkbox@^1.1.1, @radix-ui/react-collapsible@^1.1.0, @radix-ui/react-context-menu@^2.2.1, @radix-ui/react-dialog@^1.1.2, @radix-ui/react-dropdown-menu@^2.1.1, @radix-ui/react-hover-card@^1.1.1, @radix-ui/react-label@^2.1.0, @radix-ui/react-menubar@^1.1.1, @radix-ui/react-navigation-menu@^1.2.0, @radix-ui/react-popover@^1.1.1, @radix-ui/react-progress@^1.1.0, @radix-ui/react-radio-group@^1.2.0, @radix-ui/react-scroll-area@^1.1.0, @radix-ui/react-select@^2.1.1, @radix-ui/react-separator@^1.1.0, @radix-ui/react-slider@^1.2.0, @radix-ui/react-slot@^1.1.0, @radix-ui/react-switch@^1.1.0, @radix-ui/react-tabs@^1.1.0, @radix-ui/react-toast@^1.2.1, @radix-ui/react-toggle@^1.1.0, @radix-ui/react-toggle-group@^1.1.0, @radix-ui/react-tooltip@^1.1.4, @tailwindcss/typography@^0.5.15, @tanstack/react-query@^5.56.2, @types/node@^22.5.5, @types/react@^18.3.3, @types/react-dom@^18.3.0, @vitejs/plugin-react-swc@^3.9.0, autoprefixer@^10.4.20, class-variance-authority@^0.7.1, clsx@^2.1.1, cmdk@^1.0.0, date-fns@^3.6.0, embla-carousel-react@^8.3.0, eslint@^9.9.0, eslint-plugin-react-hooks@^5.1.0-rc.0, eslint-plugin-react-refresh@^0.4.9, gh-pages@^6.3.0, globals@^15.9.0, input-otp@^1.2.4, lucide-react@^0.462.0, next-themes@^0.3.0, postcss@^8.4.47, react@^18.3.1, react-day-picker@^8.10.1, react-dom@^18.3.1, react-hook-form@^7.53.0, react-resizable-panels@^2.1.3, react-router-dom@^6.26.2, recharts@^2.12.7, sonner@^1.5.0, tailwind-merge@^2.5.2, tailwindcss@^3.4.11, tailwindcss-animate@^1.0.7, typescript@^5.5.3, typescript-eslint@^8.0.1, vaul@^0.9.3, vite@^6.3.4, zod@^3.23.8

### Recent commits (newest first)

- Merge pull request #1 from 4aidan/description-generator
- Add Netlify deployment configuration
- Update AnalyticsView component
- Finalize description generator tool
- Add AI fashion describer tool files
- Add files via upload

## Key source files (fetched from GitHub, selected and truncated for size)

### Test-Plan.md

```markdown
# YourDrobe Application Test Plan

## 1. Introduction

This document outlines the testing strategy for the YourDrobe application. The purpose of this test plan is to provide a comprehensive approach to ensure the quality, reliability, and functionality of both the frontend and backend components of the application. This plan covers the scope of testing, various testing types, high-level test cases, recommended tools, a proposed schedule, and roles and responsibilities for the testing process.

## 2. Scope of Testing

### 2.1. In Scope

The following features and functionalities are in scope for testing:

*   **Frontend (React Application):**
    *   User Authentication (Login/Registration)
    *   Wardrobe View (Displaying, filtering, and searching for clothing items)
    *   Outfit Builder (Creating, editing, and deleting outfits)
    *   Upload View (Adding new clothing items with image uploads)
    *   Analytics View (Displaying wardrobe statistics)
    *   Calendar View (Scheduling and viewing outfits)
    *   Responsive design and cross-browser compatibility (Chrome, Firefox, Safari).
*   **Backend (FastAPI Application):**
    *   All RESTful API endpoints as defined in the Backend Development Plan.
    *   CRUD operations for clothing items and outfits.
    *   Data validation and error handling.
    *   Database interactions with MongoDB.
    *   API endpoint for analytics data.

### 2.2. Out of Scope

The following are considered out of scope for the initial testing phase:

*   Third-party integrations (e.g., social media sharing, external analytics services).
*   Performance, load, and stress testing.
*   Formal security vulnerability scanning (beyond basic best practices).
*   Usability and accessibility testing (will be addressed in a separate phase).
*   Testing on mobile operating systems (iOS, Android) beyond responsive web design.

## 3. Testing Types

### 3.1. Unit Testing

*   **Objective:** To test individual components and functions in isolation.
*   **Frontend:** Each React component will have unit tests to verify its rendering and behavior based on props. Utility functions and hooks will also be tested.
*   **Backend:** Each API endpoint's logic, utility functions, and service modules will be tested in isolation. Database interactions will be mocked.

### 3.2. Integration Testing

*   **Objective:** To test the interaction between different components of the application.
*   **Frontend:** Test the integration between multiple components, such as the interaction between the `WardrobeView` and the `UploadView`.
*   **Backend:** Test the integration between different API endpoints and the database. For example, creating an item and then fetching it.

### 3.3. End-to-End (E2E) Testing

*   **Objective:** To test the complete application flow from the user's perspective.
*   **Methodology:** Simulate user workflows such as registering, adding a clothing item, creating an outfit, and viewing analytics. These tests will cover the en
[truncated — 4769 more characters]
```

### frontend/AI_RULES.md

```markdown
# Tech Stack

- You are building a React application.
- Use TypeScript.
- Use React Router. KEEP the routes in src/App.tsx
- Always put source code in the src folder.
- Put pages into src/pages/
- Put components into src/components/
- The main page (default page) is src/pages/Index.tsx
- UPDATE the main page to include the new components. OTHERWISE, the user can NOT see any components!
- ALWAYS try to use the shadcn/ui library.
- Tailwind CSS: always use Tailwind CSS for styling components. Utilize Tailwind classes extensively for layout, spacing, colors, and other design aspects.

Available packages and libraries:

- The lucide-react package is installed for icons.
- You ALREADY have ALL the shadcn/ui components and their dependencies installed. So you don't need to install them again.
- You have ALL the necessary Radix UI components installed.
- Use prebuilt components from the shadcn/ui library after importing them. Note that these files shouldn't be edited, so make new components if you need to change them.

```

### backend/requirements.txt

```
fastapi
uvicorn[standard]
motor
pydantic>=2.0
pydantic-settings
python-multipart
```

### frontend/package.json

```
{
  "name": "vite_react_shadcn_ts",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "build:dev": "vite build --mode development",
    "lint": "eslint .",
    "preview": "vite preview",
    "predeploy": "npm run build",
    "deploy": "gh-pages -d dist"
  },
  "dependencies": {
    "@hookform/resolvers": "^3.9.0",
    "@radix-ui/react-accordion": "^1.2.0",
    "@radix-ui/react-alert-dialog": "^1.1.1",
    "@radix-ui/react-aspect-ratio": "^1.1.0",
    "@radix-ui/react-avatar": "^1.1.0",
    "@radix-ui/react-checkbox": "^1.1.1",
    "@radix-ui/react-collapsible": "^1.1.0",
    "@radix-ui/react-context-menu": "^2.2.1",
    "@radix-ui/react-dialog": "^1.1.2",
    "@radix-ui/react-dropdown-menu": "^2.1.1",
    "@radix-ui/react-hover-card": "^1.1.1",
    "@radix-ui/react-label": "^2.1.0",
    "@radix-ui/react-menubar": "^1.1.1",
    "@radix-ui/react-navigation-menu": "^1.2.0",
    "@radix-ui/react-popover": "^1.1.1",
    "@radix-ui/react-progress": "^1.1.0",
    "@radix-ui/react-radio-group": "^1.2.0",
    "@radix-ui/react-scroll-area": "^1.1.0",
    "@radix-ui/react-select": "^2.1.1",
    "@radix-ui/react-separator": "^1.1.0",
    "@radix-ui/react-slider": "^1.2.0",
    "@radix-ui/react-slot": "^1.1.0",
    "@radix-ui/react-switch": "^1.1.0",
    "@radix-ui/react-tabs": "^1.1.0",
    "@radix-ui/react-toast": "^1.2.1",
    "@radix-ui/react-toggle": "^1.1.0",
    "@radix-ui/react-toggle-group": "^1.1.0",
    "@radix-ui/react-tooltip": "^1.1.4",
    "@tanstack/react-query": "^5.56.2",
    "class-variance-authority": "^0.7.1",
    "clsx": "^2.1.1",
    "cmdk": "^1.0.0",
    "date-fns": "^3.6.0",
    "embla-carousel-react": "^8.3.0",
    "input-otp": "^1.2.4",
    "lucide-react": "^0.462.0",
    "next-themes": "^0.3.0",
    "react": "^18.3.1",
    "react-day-picker": "^8.10.1",
    "react-dom": "^18.3.1",
    "react-hook-form": "^7.53.0",
    "react-resizable-panels": "^2.1.3",
    "react-router-dom": "^6.26.2",
    "recharts": "^2.12.7",
    "sonner": "^1.5.0",
    "tailwind-merge": "^2.5.2",
    "tailwindcss-animate": "^1.0.7",
    "vaul": "^0.9.3",
    "zod": "^3.23.8"
  },
  "devDependencies": {
    "@dyad-sh/react-vite-component-tagger": "^0.8.0",
    "@eslint/js": "^9.9.0",
    "@tailwindcss/typography": "^0.5.15",
    "@types/node": "^22.5.5",
    "@types/react": "^18.3.3",
    "@types/react-dom": "^18.3.0",
    "@vitejs/plugin-react-swc": "^3.9.0",
    "autoprefixer": "^10.4.20",
    "eslint": "^9.9.0",
    "eslint-plugin-react-hooks": "^5.1.0-rc.0",
    "eslint-plugin-react-refresh": "^0.4.9",
    "gh-pages": "^6.3.0",
    "globals": "^15.9.0",
    "postcss": "^8.4.47",
    "tailwindcss": "^3.4.11",
    "typescript": "^5.5.3",
    "typescript-eslint": "^8.0.1",
    "vite": "^6.3.4"
  },
  "packageManager": "pnpm@10.19.0+sha512.c9fc7236e92adf5c8af42fd5bf1612df99c2ceb62f27047032f4720b33f8eacdde311865e91c411f2774f618d82f320808ecb51718bfa82c060c4ba7c76a32b8"
}

```

### backend/main.py

```python
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from contextlib import asynccontextmanager

from config import settings
from database import connect_to_mongo, close_mongo_connection, get_database


@asynccontextmanager
async def lifespan(app: FastAPI):
    # Startup
    await connect_to_mongo()
    yield
    # Shutdown
    await close_mongo_connection()


app = FastAPI(
    title="YourDrobe API",
    version="1.0.0",
    lifespan=lifespan
)

# Configure CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=settings.CORS_ORIGINS,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Include routers
# (No routers currently registered)


@app.get("/healthz")
async def health_check():
    """Health check endpoint that verifies database connection."""
    try:
        db = await get_database()
        # Ping the database to verify connection
        await db.command("ping")
        return {
            "status": "healthy",
            "database": "connected"
        }
    except Exception as e:
        return {
            "status": "unhealthy",
            "database": "disconnected",
            "error": str(e)
        }


@app.get("/")
async def root():
    """Root endpoint."""
    return {
        "message": "YourDrobe API",
        "version": "1.0.0",
        "docs": "/docs"
    }
```

### frontend/src/main.tsx

```typescript
import { createRoot } from "react-dom/client";
import App from "./App.tsx";
import "./globals.css";

createRoot(document.getElementById("root")!).render(<App />);

```

### frontend/src/App.tsx

```typescript
import { Toaster } from "@/components/ui/toaster";
import { Toaster as Sonner } from "@/components/ui/sonner";
import { TooltipProvider } from "@/components/ui/tooltip";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Index from "./pages/Index";
import NotFound from "./pages/NotFound";

const queryClient = new QueryClient();

const App = () => (
  <QueryClientProvider client={queryClient}>
    <TooltipProvider>
      <Toaster />
      <Sonner />
      <BrowserRouter>
        <Routes>
          <Route path="/" element={<Index />} />
          {/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */}
          <Route path="*" element={<NotFound />} />
        </Routes>
      </BrowserRouter>
    </TooltipProvider>
  </QueryClientProvider>
);

export default App;

```

### frontend/src/pages/Index.tsx

```typescript
import { useState, useEffect } from "react";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { WardrobeView } from "@/components/WardrobeView";
import { AnalyticsView } from "@/components/AnalyticsView";
import { UploadView } from "@/components/UploadView";
import { OutfitBuilder } from "@/components/OutfitBuilder";
import { Upload, Shirt, BarChart3, Calendar } from "lucide-react";
import { ClothingItem, Outfit } from "@/types/wardrobe";
import { loadClothes, saveClothes, loadOutfits, saveOutfits } from "@/utils/storage";
import { toast } from "sonner";

const Index = () => {
  const [clothes, setClothes] = useState<ClothingItem[]>([]);
  const [outfits, setOutfits] = useState<Outfit[]>([]);
  const [activeTab, setActiveTab] = useState("wardrobe");

  useEffect(() => {
    setClothes(loadClothes());
    setOutfits(loadOutfits());
  }, []);

  useEffect(() => {
    if (clothes.length > 0) {
      saveClothes(clothes);
    }
  }, [clothes]);

  useEffect(() => {
    if (outfits.length > 0) {
      saveOutfits(outfits);
    }
  }, [outfits]);

  const addClothingItem = (item: ClothingItem) => {
    setClothes([...clothes, item]);
    toast.success("Item added! View it in your wardrobe");
    setActiveTab("wardrobe");
  };

  const removeClothingItem = (id: string) => {
    setClothes(clothes.filter((item) => item.id !== id));
    setOutfits(
      outfits.map((outfit) => ({
        ...outfit,
        items: outfit.items.filter((item) => item.id !== id),
      }))
    );
  };

  const updateClothingItem = (updatedItem: ClothingItem) => {
    setClothes(clothes.map((item) => (item.id === updatedItem.id ? updatedItem : item)));
  };

  const saveOutfit = (outfit: Outfit) => {
    setOutfits([...outfits, outfit]);
  };

  const deleteOutfit = (id: string) => {
    setOutfits(outfits.filter((outfit) => outfit.id !== id));
  };

  const markOutfitWorn = (outfitId: string) => {
    const today = new Date().toISOString().split("T")[0];
    
    setOutfits(
      outfits.map((outfit) => {
        if (outfit.id === outfitId) {
          const updatedClothes = clothes.map((item) => {
            if (outfit.items.some((outfitItem) => outfitItem.id === item.id)) {
              return {
                ...item,
                timesWorn: item.timesWorn + 1,
                lastWorn: today,
              };
            }
            return item;
          });
          setClothes(updatedClothes);

          return {
            ...outfit,
            timesWorn: outfit.timesWorn + 1,
            lastWorn: today,
          };
        }
        return outfit;
      })
    );
  };

  return (
    <div className="min-h-screen bg-white pb-28">
      {/* Header */}
      <header className="border-b-4 border-black sticky top-0 z-10 bg-white shadow-brutal-sm">
        <div className="container mx-auto px-6 py-6">
          <div className="flex items-center gap-4">
            <div className="w-12 h-12 border-2 border-black bg-white flex items-center justify-center">
              <Shirt className="w-6 h-6" />
            </div>
            <h1 className="text-3xl font-bold tracking-tight">yourdrobe</h1>
          </div>
        </div>
      </header>

      {/* Main Content */}
      <main className="container mx-auto px-6 py-8">
        <Tabs value={activeTab} onValueChange={setActiveTab} className="w-full">
          <TabsContent value="wardrobe" className="mt-0">
            <WardrobeView
              clothes={clothes}
              onRemove={removeClothingItem}
              onUpdate={updateClothingItem}
            />
          </TabsContent>

          <TabsContent value="outfits" className="mt-0">
            <OutfitBuilder
              clothes={clothes}
              outfits={outfits}
              onSaveOutfit={saveOutfit}
              onDeleteOutfit={deleteOutfit}
              onMarkWorn={markOutfitWorn}
            />
          </TabsContent>

          <TabsContent value="analytics" className="mt-0">
            <AnalyticsView clothes={clothes} onRemove={removeClothingItem} />
          </TabsContent>

          <TabsContent value="upload" className="mt-0">
            <UploadView onUpload={addClothingItem} />
          </TabsContent>

          {/* Bottom Navigation */}
          <TabsList className="fixed bottom-6 left-1/2 transform -translate-x-1/2 border-4 border-black p-2 h-auto z-50 bg-white shadow-brutal">
            <TabsTrigger
              value="wardrobe"
              className="px-8 py-4 data-[state=active]:bg-black data-[state=active]:text-white transition-all font-bold flex flex-col items-center gap-1"
            >
              <Shirt className="w-5 h-5" />
              <span className="text-xs">Wardrobe</span>
            </TabsTrigger>
            <TabsTrigger
              value="outfits"
              className="px-8 py-4 data-[state=active]:bg-black data-[state=active]:text-white transition-all font-bold flex flex-col items-center gap-1"
            >
              <Calendar className="w-5 h-5" />
              <span className="text-xs">Outfits</span>
            </TabsTrigger>
            <TabsTrigger
              value="analytics"
              className="px-8 py-4 data-[state=active]:bg-black data-[state=active]:text-white transition-all font-bold flex flex-col items-center gap-1"
            >
              <BarChart3 className="w-5 h-5" />
              <span className="text-xs">Analytics</span>
            </TabsTrigger>
            <TabsTrigger
              value="upload"
              className="px-8 py-4 data-[state=active]:bg-black data-[state=active]:text-white transition-all font-bold flex flex-col items-center gap-1"
            >
              <Upload className="w-5 h-5" />
              <span className="text-xs">Upload</span>
            </TabsTrigger>
          </TabsList>
        </Tabs>
      </main>
    </div>
  );
};

export default Index;
```

### frontend/postcss.config.js

```javascript
export default {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
};

```

### frontend/index.html

```html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>snapdev-generated-app</title>
  </head>

  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>

```

[75 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]