localgreenchain/components/upload/ProgressBar.tsx
Claude d74128d3cd
Add Agent 3: File Upload & Storage System
Implements cloud-based file storage for plant photos, documents, and certificates:

Storage Layer:
- Multi-provider support (AWS S3, Cloudflare R2, MinIO, local filesystem)
- S3-compatible provider with presigned URL generation
- Local storage provider for development with signed URL verification
- Configurable via environment variables

Image Processing:
- Automatic thumbnail generation (150x150, 300x300, 600x600, 1200x1200)
- WebP conversion for optimized file sizes
- EXIF data extraction for image metadata
- Image optimization with Sharp

API Endpoints:
- POST /api/upload/image - Upload images with automatic processing
- POST /api/upload/document - Upload documents (PDF, DOC, DOCX)
- POST /api/upload/presigned - Get presigned URLs for direct uploads
- GET/DELETE /api/upload/[fileId] - File management

UI Components:
- ImageUploader - Drag & drop image upload with preview
- PhotoGallery - Grid gallery with lightbox view
- DocumentUploader - Document upload with file type icons
- ProgressBar - Animated upload progress indicator

Database:
- FileStore service with in-memory storage (Prisma schema ready for Agent 2)
- File metadata tracking with soft delete support
- Category-based file organization
2025-11-23 03:51:31 +00:00

63 lines
1.4 KiB
TypeScript

/**
* Progress Bar Component
* Agent 3: File Upload & Storage System
*
* Animated progress bar for uploads
*/
import React from 'react';
interface ProgressBarProps {
progress: number;
showPercentage?: boolean;
color?: 'green' | 'blue' | 'purple' | 'orange';
size?: 'sm' | 'md' | 'lg';
animated?: boolean;
className?: string;
}
const colorClasses = {
green: 'bg-green-500',
blue: 'bg-blue-500',
purple: 'bg-purple-500',
orange: 'bg-orange-500',
};
const sizeClasses = {
sm: 'h-1',
md: 'h-2',
lg: 'h-3',
};
export function ProgressBar({
progress,
showPercentage = false,
color = 'green',
size = 'md',
animated = true,
className = '',
}: ProgressBarProps) {
const clampedProgress = Math.min(100, Math.max(0, progress));
return (
<div className={className}>
<div className={`bg-gray-200 rounded-full overflow-hidden ${sizeClasses[size]}`}>
<div
className={`
${colorClasses[color]} ${sizeClasses[size]} rounded-full
transition-all duration-300 ease-out
${animated && clampedProgress < 100 ? 'animate-pulse' : ''}
`}
style={{ width: `${clampedProgress}%` }}
/>
</div>
{showPercentage && (
<p className="text-xs text-gray-500 mt-1 text-right">
{Math.round(clampedProgress)}%
</p>
)}
</div>
);
}
export default ProgressBar;