import { useState } from 'react'; import { Camera, Loader2, X } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Textarea } from '@/components/ui/textarea'; import { PhotoDropzone } from '@/components/PhotoDropzone'; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger, } from '@/components/ui/dialog'; import { useCurrentUser } from '@/hooks/useCurrentUser'; import { useNostrPublish } from '@/hooks/useNostrPublish'; import { useUploadFile } from '@/hooks/useUploadFile'; import { useToast } from '@/hooks/useToast'; import { useQueryClient } from '@tanstack/react-query'; import { PHOTO_CONTRIBUTION_KIND } from '@/hooks/useSpotContributions'; import { SKATE_SPOT_KIND } from '@/lib/types'; import { LoginArea } from '@/components/auth/LoginArea'; import { useTranslation } from '@/contexts/language'; interface AddPhotoToSpotProps { spotPubkey: string; spotIdentifier: string; spotTitle: string; } export function AddPhotoToSpot({ spotPubkey, spotIdentifier, spotTitle }: AddPhotoToSpotProps) { const { t } = useTranslation(); const { user } = useCurrentUser(); const { mutateAsync: publishEvent, isPending: isPublishing } = useNostrPublish(); const { mutateAsync: uploadFile, isPending: isUploading } = useUploadFile(); const { toast } = useToast(); const queryClient = useQueryClient(); const [open, setOpen] = useState(false); const [caption, setCaption] = useState(''); const [uploadedImage, setUploadedImage] = useState<{ url: string; mimeType?: string } | null>(null); const spotRef = `${SKATE_SPOT_KIND}:${spotPubkey}:${spotIdentifier}`; const handleFiles = async (files: File[]) => { const file = files[0]; if (!file) return; try { const tags = await uploadFile(file); const url = tags.find(([name]) => name === 'url')?.[1]; const mimeType = tags.find(([name]) => name === 'm')?.[1]; if (url) { setUploadedImage({ url, mimeType }); toast({ title: t('spotUi.photoUploaded'), description: t('spotUi.photoUploadedDesc'), }); } } catch (error) { toast({ title: t('spotUi.uploadFailed'), description: error instanceof Error ? error.message : t('spotUi.failedToUploadPhoto'), variant: 'destructive', }); } }; const handleSubmit = async () => { if (!uploadedImage) { toast({ title: t('spotUi.noPhoto'), description: t('spotUi.uploadPhotoFirst'), variant: 'destructive', }); return; } try { // Create kind 1063 file metadata event const eventTags: string[][] = [ ['url', uploadedImage.url], ['a', spotRef], ['alt', `Community photo for ${spotTitle}`], ]; if (uploadedImage.mimeType) { eventTags.push(['m', uploadedImage.mimeType]); } await publishEvent({ kind: PHOTO_CONTRIBUTION_KIND, content: caption.trim(), tags: eventTags, }); toast({ title: t('spotUi.photoContributed'), description: t('spotUi.photoContributedDesc'), }); // Reset and close setCaption(''); setUploadedImage(null); setOpen(false); // Invalidate the photos query queryClient.invalidateQueries({ queryKey: ['spot-photos', spotPubkey, spotIdentifier] }); } catch (error) { toast({ title: t('spotUi.failedToContribute'), description: error instanceof Error ? error.message : t('spotUi.somethingWentWrong'), variant: 'destructive', }); } }; const handleClose = () => { setOpen(false); setCaption(''); setUploadedImage(null); }; return ( {t('spotUi.addPhotoToSpot')} {t('spotUi.addPhotoDesc')} {!user ? (

{t('spotUi.logInToContributePhotos')}

) : (
{/* Photo upload area */} {uploadedImage ? (
{t('spotUi.uploadedAlt')}
) : ( )} {/* Caption */}