# Upload UI Components

Beautiful, accessible upload components for the Banatie landing app demo page.

## Components Overview

### 1. FileDropZone

A drag-and-drop file upload component with click-to-browse fallback.

**Features:**
- Drag-and-drop with visual feedback
- Click to browse files
- Image preview thumbnail
- File validation (type, size)
- Clear/remove file button
- Keyboard accessible
- WCAG 2.1 AA compliant

**Usage:**
```tsx
import { FileDropZone } from '@/components/demo/upload';

<FileDropZone
  onFileSelect={(file) => handleFile(file)}
  accept="image/jpeg,image/png,image/webp,image/gif"
  maxSizeMB={5}
  disabled={uploading}
/>
```

**Props:**
- `onFileSelect: (file: File) => void` - Callback when valid file selected
- `accept?: string` - Accepted file types (default: image types)
- `maxSizeMB?: number` - Max file size in MB (default: 5)
- `disabled?: boolean` - Disable interaction

**States:**
- Empty: Default state with upload icon
- Drag over: Highlighted when dragging file over
- File selected: Shows preview thumbnail and file info
- Error: Displays validation error message

---

### 2. UploadProgressBar

Animated progress bar with timer and status indicators.

**Features:**
- Smooth progress animation
- Upload duration timer
- Status-based colors (uploading/processing/success/error)
- Percentage display
- Animated gradient effect
- Screen reader friendly

**Usage:**
```tsx
import { UploadProgressBar } from '@/components/demo/upload';

<UploadProgressBar
  progress={uploadProgress}
  status={uploadStatus}
  error={errorMessage}
/>
```

**Props:**
- `progress: number` - Progress percentage (0-100)
- `status: 'uploading' | 'processing' | 'success' | 'error'` - Current status
- `error?: string` - Error message (only shown when status='error')

**Status Colors:**
- `uploading`: Amber gradient (from-amber-600 to-orange-600)
- `processing`: Purple gradient (from-purple-600 to-cyan-600)
- `success`: Green gradient (from-green-600 to-emerald-600)
- `error`: Red gradient (from-red-600 to-rose-600)

---

### 3. UploadResultCard

Result card displaying uploaded image with metadata and actions.

**Features:**
- Large image preview
- Click to zoom
- Download button
- Copy URL to clipboard
- File metadata badges (size, type, dimensions)
- Expandable details section
- Upload duration display
- Hover effects

**Usage:**
```tsx
import { UploadResultCard } from '@/components/demo/upload';

<UploadResultCard
  result={uploadResult}
  onZoom={(url) => setZoomedImage(url)}
  onDownload={(url, filename) => downloadFile(url, filename)}
/>
```

**Props:**
- `result: UploadResult` - Upload result data
- `onZoom: (url: string) => void` - Callback for zooming image
- `onDownload: (url: string, filename: string) => void` - Callback for download

**UploadResult Interface:**
```tsx
interface UploadResult {
  id: string;
  timestamp: Date;
  originalFile: {
    name: string;
    size: number;
    type: string;
  };
  uploadedImage: {
    url: string;
    width?: number;
    height?: number;
    size?: number;
  };
  durationMs?: number;
}
```

---

## Integration Example

Here's a complete example of how to use all three components together:

```tsx
'use client';

import { useState } from 'react';
import {
  FileDropZone,
  UploadProgressBar,
  UploadResultCard,
  UploadResult,
} from '@/components/demo/upload';

export default function UploadDemoPage() {
  const [file, setFile] = useState<File | null>(null);
  const [uploading, setUploading] = useState(false);
  const [progress, setProgress] = useState(0);
  const [status, setStatus] = useState<'uploading' | 'processing' | 'success' | 'error'>('uploading');
  const [results, setResults] = useState<UploadResult[]>([]);
  const [zoomedImage, setZoomedImage] = useState<string | null>(null);

  const handleFileSelect = async (selectedFile: File) => {
    setFile(selectedFile);
    setUploading(true);
    setProgress(0);
    setStatus('uploading');

    const startTime = Date.now();

    try {
      // Simulate upload progress
      for (let i = 0; i <= 100; i += 10) {
        await new Promise(resolve => setTimeout(resolve, 100));
        setProgress(i);
      }

      setStatus('processing');

      // Call your upload API here
      const formData = new FormData();
      formData.append('file', selectedFile);

      const response = await fetch('/api/upload', {
        method: 'POST',
        headers: { 'X-API-Key': apiKey },
        body: formData,
      });

      const data = await response.json();

      setStatus('success');
      setProgress(100);

      // Add result
      const newResult: UploadResult = {
        id: Date.now().toString(),
        timestamp: new Date(),
        originalFile: {
          name: selectedFile.name,
          size: selectedFile.size,
          type: selectedFile.type,
        },
        uploadedImage: {
          url: data.url,
          width: data.width,
          height: data.height,
        },
        durationMs: Date.now() - startTime,
      };

      setResults(prev => [newResult, ...prev]);
    } catch (error) {
      setStatus('error');
    } finally {
      setTimeout(() => setUploading(false), 2000);
    }
  };

  const handleDownload = async (url: string, filename: string) => {
    const response = await fetch(url);
    const blob = await response.blob();
    const blobUrl = URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = blobUrl;
    link.download = filename;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    URL.revokeObjectURL(blobUrl);
  };

  return (
    <div className="max-w-7xl mx-auto px-6 py-12">
      {/* Upload Section */}
      <section className="mb-8">
        <FileDropZone
          onFileSelect={handleFileSelect}
          disabled={uploading}
        />
      </section>

      {/* Progress Section */}
      {uploading && (
        <section className="mb-8">
          <UploadProgressBar
            progress={progress}
            status={status}
          />
        </section>
      )}

      {/* Results Section */}
      {results.length > 0 && (
        <section className="space-y-6">
          <h2 className="text-2xl font-bold text-white">Upload History</h2>
          {results.map(result => (
            <UploadResultCard
              key={result.id}
              result={result}
              onZoom={setZoomedImage}
              onDownload={handleDownload}
            />
          ))}
        </section>
      )}

      {/* Zoom Modal */}
      {zoomedImage && (
        <div
          className="fixed inset-0 z-50 bg-black/90 flex items-center justify-center p-4"
          onClick={() => setZoomedImage(null)}
        >
          <button
            onClick={() => setZoomedImage(null)}
            className="absolute top-4 right-4 w-10 h-10 rounded-full bg-white/10 hover:bg-white/20 text-white flex items-center justify-center"
          >
            ✕
          </button>
          <img
            src={zoomedImage}
            alt="Zoomed"
            className="max-w-full max-h-full object-contain"
          />
        </div>
      )}
    </div>
  );
}
```

---

## Design System Adherence

All components follow the Banatie design system:

**Colors:**
- Backgrounds: `bg-slate-950`, `bg-slate-900/80`, `bg-slate-800`
- Borders: `border-slate-700`, `border-slate-600`
- Text: `text-white`, `text-gray-300`, `text-gray-400`
- Primary gradient: `from-purple-600 to-cyan-600`
- Admin gradient: `from-amber-600 to-orange-600`

**Typography:**
- Consistent font sizes and weights
- Inter font family

**Spacing:**
- Padding: `p-4`, `p-5`, `p-6`, `p-8`
- Gaps: `gap-2`, `gap-3`, `gap-4`, `gap-6`
- Rounded corners: `rounded-lg`, `rounded-xl`, `rounded-2xl`

**Animations:**
- `animate-fade-in` - Fade in on mount
- `animate-gradient` - Gradient shift effect
- `transition-all`, `transition-colors` - Smooth transitions

---

## Accessibility Features

All components meet WCAG 2.1 AA standards:

1. **Semantic HTML**
   - Proper roles and ARIA attributes
   - Logical heading hierarchy

2. **Keyboard Navigation**
   - All interactive elements keyboard accessible
   - Visible focus indicators (`focus:ring-2`)
   - Tab order follows visual flow

3. **Screen Reader Support**
   - Descriptive `aria-label` attributes
   - Progress bars with `role="progressbar"`
   - Error messages with `role="alert"`
   - State announcements (`aria-expanded`, `aria-pressed`)

4. **Visual Accessibility**
   - Color contrast meets 4.5:1 minimum
   - Focus indicators clearly visible
   - Error states clearly indicated
   - Icons paired with text labels

5. **Touch Targets**
   - Minimum 44x44px touch targets
   - Adequate spacing between interactive elements

---

## Responsive Design

Components are mobile-first and responsive:

**Breakpoints:**
- Base: < 768px (mobile)
- md: >= 768px (tablet)
- lg: >= 1024px (desktop)

**Responsive Features:**
- FileDropZone: Adapts layout for mobile/desktop
- UploadResultCard: Stacks vertically on mobile, horizontal on desktop
- All components: Touch-friendly on mobile, optimized for desktop

---

## Performance Considerations

1. **Image Optimization**
   - Uses Next.js Image component for automatic optimization
   - Proper sizing attributes
   - Lazy loading for below-fold images

2. **Event Cleanup**
   - Preview URLs revoked on unmount
   - Event listeners properly cleaned up
   - Timers cleared on component unmount

3. **Efficient Rendering**
   - Minimal re-renders
   - Optimized state updates
   - CSS transitions over JavaScript animations

---

## Browser Compatibility

Tested and working on:
- Chrome 90+
- Firefox 88+
- Safari 14+
- Edge 90+

---

## Notes for Frontend Lead

These components are ready for integration into `/apps/landing/src/app/demo/upload/page.tsx`.

**To integrate:**

1. Import components from `@/components/demo/upload`
2. Use FileDropZone for file selection
3. Show UploadProgressBar during upload
4. Display UploadResultCard for each successful upload
5. Add zoom modal for full-size image viewing

**API Integration Points:**
- `onFileSelect` in FileDropZone - trigger upload API call
- Update progress state during upload
- Create UploadResult from API response
- Handle errors appropriately

The components handle all UI concerns - you just need to wire up the API calls and state management.
