import { getImageUrlOrFile } from '@/utils/image'; import { TrashIcon, PhotoIcon, XMarkIcon, ChevronLeftIcon, ChevronRightIcon, MagnifyingGlassIcon, } from '@heroicons/react/24/outline'; import Image from 'next/image'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { useState, useEffect } from 'react'; import Loader from '@/components/Loader'; import { cn } from '@/lib/utils'; import { useTranslations } from 'next-intl'; type UnsplashImage = { id: string; description: string | null; user: { name: string; username: string }; urls: { small: string; regular: string; thumb: string }; links: { download: string }; }; type ImageSectionProps = { currentImageUrl?: string | null; onImageFileChange: (file?: File) => void; onImageUrlChange: (url: string) => void; onDeleteImage?: () => Promise; isUnsplashAllowed?: boolean; altText: string; }; export default function ImageSection({ currentImageUrl, onImageFileChange, onImageUrlChange, onDeleteImage, isUnsplashAllowed = false, altText, }: ImageSectionProps) { const t = useTranslations('ImageSection'); const [previewUrl, setPreviewUrl] = useState(null); const [selectedFileName, setSelectedFileName] = useState(null); const [isUnsplashMode, setIsUnsplashMode] = useState(false); const [isDeleting, setIsDeleting] = useState(false); // Unsplash States const [images, setImages] = useState([]); const [loading, setLoading] = useState(false); const [keyword, setKeyword] = useState(''); const [page, setPage] = useState(1); const [error, setError] = useState(null); const [debounceTimer, setDebounceTimer] = useState( null, ); useEffect(() => { if (isDeleting && !currentImageUrl && !previewUrl) { setIsDeleting(false); } }, [currentImageUrl, previewUrl, isDeleting]); const handleFileChange = (e: React.ChangeEvent) => { const file = e.target.files?.[0]; onImageFileChange(file); if (file) { setSelectedFileName(file.name); const url = URL.createObjectURL(file); setPreviewUrl(url); onImageUrlChange(''); setIsUnsplashMode(false); } else { setSelectedFileName(null); setPreviewUrl(null); } }; const handleUnsplashSelect = (url: string) => { onImageUrlChange(url); if (url) { setPreviewUrl(url); onImageFileChange(undefined); setSelectedFileName(null); } else { setPreviewUrl(null); } setIsUnsplashMode(false); }; const debounceSearch = ( keyword: string, page: number, time: number = 1000, ) => { if (debounceTimer) clearTimeout(debounceTimer); const timeout = setTimeout(async () => { await fetchImages(keyword, page); }, time); setDebounceTimer(timeout); }; const fetchImages = async (keyword: string, page: number) => { if (!keyword || keyword.length < 2) { setImages([]); setError(null); return; } setLoading(true); setError(null); try { const res = await fetch( `/api/v1/images/unsplash?keyword=${encodeURIComponent(keyword)}&page=${page}&per_page=12`, ); if (!res.ok) { const text = await res.text(); if (res.status === 500 && text.includes('UNSPLASH_ACCESS_KEY')) { setError(t('errors.unsplashKey')); } else { setError(t('errors.unsplashFetch')); } setImages([]); return; } const data = await res.json(); setImages(data.results || []); setKeyword(keyword); setPage(page); } catch (error) { console.error('Unsplash fetch error:', error); setError(t('errors.searchUnexpected')); } finally { setLoading(false); } }; const handleDeleteImage = async () => { if (!onDeleteImage) return; setIsDeleting(true); try { await onDeleteImage(); setPreviewUrl(null); setSelectedFileName(null); } catch (error) { console.error('Delete image error:', error); setIsDeleting(false); } }; const displayUrl = previewUrl || (currentImageUrl ? getImageUrlOrFile(currentImageUrl) : null); return (
{isUnsplashMode && ( )} {onDeleteImage && currentImageUrl && !previewUrl && !isUnsplashMode && ( )}
{isDeleting ? (
) : isUnsplashMode ? (
{ if (e.key === 'Enter') { e.preventDefault(); void fetchImages(e.currentTarget.value, 1); } }} onChange={(e) => debounceSearch(e.target.value, 1)} />
{loading ? (
) : error ? (

{t('searchFailed')}

{error}

) : images.length > 0 ? (
{images.map((image) => ( ))}
) : keyword ? (

{t('noResults', { keyword })}

) : (

{t('enterKeyword')}

)}
{images.length > 0 && (

{t('pageResults', { page })}

)}
) : displayUrl ? (
{altText}
{isUnsplashAllowed && ( )}
) : (
{isUnsplashAllowed && ( )}

{t('recommendation')}

)}
{selectedFileName && !isUnsplashMode && (
{selectedFileName}
)}
); }