mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-22 13:11:16 -05:00
Implement photo upload enhancements
This commit is contained in:
@@ -7,6 +7,7 @@ import { Button } from '@/components/ui/button';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { Separator } from '@/components/ui/separator';
|
||||
import { UppyPhotoUpload } from './UppyPhotoUpload';
|
||||
import { PhotoCaptionEditor, PhotoWithCaption } from './PhotoCaptionEditor';
|
||||
import { supabase } from '@/integrations/supabase/client';
|
||||
import { useAuth } from '@/hooks/useAuth';
|
||||
import { useToast } from '@/hooks/use-toast';
|
||||
@@ -24,14 +25,28 @@ export function UppyPhotoSubmissionUpload({
|
||||
rideId,
|
||||
}: UppyPhotoSubmissionUploadProps) {
|
||||
const [title, setTitle] = useState('');
|
||||
const [caption, setCaption] = useState('');
|
||||
const [uploadedUrls, setUploadedUrls] = useState<string[]>([]);
|
||||
const [description, setDescription] = useState('');
|
||||
const [photos, setPhotos] = useState<PhotoWithCaption[]>([]);
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
const { user } = useAuth();
|
||||
const { toast } = useToast();
|
||||
|
||||
const handleUploadComplete = (urls: string[]) => {
|
||||
setUploadedUrls(urls);
|
||||
// Convert URLs to photo objects with empty captions
|
||||
const newPhotos: PhotoWithCaption[] = urls.map((url, index) => ({
|
||||
url,
|
||||
caption: '',
|
||||
order: photos.length + index,
|
||||
}));
|
||||
setPhotos(prev => [...prev, ...newPhotos]);
|
||||
};
|
||||
|
||||
const handlePhotosChange = (updatedPhotos: PhotoWithCaption[]) => {
|
||||
setPhotos(updatedPhotos);
|
||||
};
|
||||
|
||||
const handleRemovePhoto = (index: number) => {
|
||||
setPhotos(prev => prev.filter((_, i) => i !== index));
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
@@ -44,7 +59,7 @@ export function UppyPhotoSubmissionUpload({
|
||||
return;
|
||||
}
|
||||
|
||||
if (uploadedUrls.length === 0) {
|
||||
if (photos.length === 0) {
|
||||
toast({
|
||||
variant: 'destructive',
|
||||
title: 'No Photos',
|
||||
@@ -70,9 +85,11 @@ export function UppyPhotoSubmissionUpload({
|
||||
submission_type: 'photo',
|
||||
content: {
|
||||
title: title.trim(),
|
||||
caption: caption.trim(),
|
||||
photos: uploadedUrls.map((url, index) => ({
|
||||
url,
|
||||
description: description.trim(),
|
||||
photos: photos.map((photo, index) => ({
|
||||
url: photo.url,
|
||||
caption: photo.caption.trim(),
|
||||
title: photo.title?.trim(),
|
||||
order: index,
|
||||
})),
|
||||
context: {
|
||||
@@ -97,8 +114,8 @@ export function UppyPhotoSubmissionUpload({
|
||||
|
||||
// Reset form
|
||||
setTitle('');
|
||||
setCaption('');
|
||||
setUploadedUrls([]);
|
||||
setDescription('');
|
||||
setPhotos([]);
|
||||
onSubmissionComplete?.();
|
||||
} catch (error) {
|
||||
console.error('Submission error:', error);
|
||||
@@ -172,29 +189,29 @@ export function UppyPhotoSubmissionUpload({
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="caption" className="text-base font-medium">
|
||||
Caption
|
||||
<Label htmlFor="description" className="text-base font-medium">
|
||||
Description
|
||||
</Label>
|
||||
<Textarea
|
||||
id="caption"
|
||||
value={caption}
|
||||
onChange={(e) => setCaption(e.target.value)}
|
||||
placeholder="Add a description or story about these photos..."
|
||||
id="description"
|
||||
value={description}
|
||||
onChange={(e) => setDescription(e.target.value)}
|
||||
placeholder="Add a general description about these photos..."
|
||||
maxLength={500}
|
||||
rows={3}
|
||||
className="transition-all duration-200 focus:ring-2 focus:ring-primary/20 resize-none"
|
||||
/>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{caption.length}/500 characters
|
||||
{description.length}/500 characters
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<Label className="text-base font-medium">Photos *</Label>
|
||||
{uploadedUrls.length > 0 && (
|
||||
{photos.length > 0 && (
|
||||
<Badge variant="secondary" className="text-xs">
|
||||
{uploadedUrls.length} photo{uploadedUrls.length !== 1 ? 's' : ''} selected
|
||||
{photos.length} photo{photos.length !== 1 ? 's' : ''} selected
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
@@ -204,17 +221,30 @@ export function UppyPhotoSubmissionUpload({
|
||||
maxSizeMB={25}
|
||||
metadata={metadata}
|
||||
variant="public"
|
||||
showPreview={true}
|
||||
showPreview={false}
|
||||
size="default"
|
||||
enableDragDrop={true}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{photos.length > 0 && (
|
||||
<>
|
||||
<Separator />
|
||||
<PhotoCaptionEditor
|
||||
photos={photos}
|
||||
onPhotosChange={handlePhotosChange}
|
||||
onRemovePhoto={handleRemovePhoto}
|
||||
maxCaptionLength={200}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
<Separator />
|
||||
|
||||
<div className="space-y-4">
|
||||
<Button
|
||||
onClick={handleSubmit}
|
||||
disabled={isSubmitting || !title.trim() || uploadedUrls.length === 0}
|
||||
disabled={isSubmitting || !title.trim() || photos.length === 0}
|
||||
className="w-full h-12 text-base font-medium photo-upload-trigger"
|
||||
size="lg"
|
||||
>
|
||||
@@ -226,7 +256,7 @@ export function UppyPhotoSubmissionUpload({
|
||||
) : (
|
||||
<div className="flex items-center gap-2">
|
||||
<CheckCircle className="w-5 h-5" />
|
||||
Submit {uploadedUrls.length} Photo{uploadedUrls.length !== 1 ? 's' : ''}
|
||||
Submit {photos.length} Photo{photos.length !== 1 ? 's' : ''}
|
||||
</div>
|
||||
)}
|
||||
</Button>
|
||||
|
||||
Reference in New Issue
Block a user