/** * Media Upload Component * Handles image and video uploads for itinerary entries */ import React from "react"; import { Upload, X, Video, Plus } from "lucide-react"; import { Button } from "./button"; import { Card, CardContent } from "./card"; import { __, sprintf } from "../../lib/i18n"; import { prepareWordPressMediaFrameOpen } from "../../lib/wp-media-open"; import { MediaItem } from "../trip-form/types"; interface MediaUploadProps { items: MediaItem[]; onChange: (items: MediaItem[]) => void; maxItems?: number; acceptTypes?: "images" | "videos" | "both"; title?: string; description?: string; className?: string; } export const MediaUpload: React.FC = ({ items = [], onChange, maxItems = 10, acceptTypes = "both", title = __("Media Gallery", "yatra"), description = __("Add images and videos to showcase this activity", "yatra"), className = "", }) => { const getMediaType = (acceptTypes: string): string => { switch (acceptTypes) { case "images": return "image"; case "videos": return "video"; default: return "image,video"; } }; const getMediaTitle = (acceptTypes: string): string => { switch (acceptTypes) { case "images": return __("Photo Gallery", "yatra"); case "videos": return __("Video Gallery", "yatra"); default: return title; } }; const getMediaDescription = (acceptTypes: string): string => { switch (acceptTypes) { case "images": return __("Upload images to showcase this activity", "yatra"); case "videos": return __("Add videos to showcase this activity", "yatra"); default: return description; } }; const handleMediaAdd = () => { if (items.length >= maxItems) { alert( sprintf( // translators: %d: maximum number of media items allowed. __("Maximum %d media items allowed", "yatra"), Number(maxItems) || 0, ), ); return; } // Use WordPress media library if (window.wp && window.wp.media) { const mediaUploader = window.wp.media({ title: __("Select Media", "yatra"), button: { text: __("Add Media", "yatra") }, multiple: true, // Allow multiple selection library: { type: getMediaType(acceptTypes) }, }); mediaUploader.on("select", () => { const selection = mediaUploader.state().get("selection"); const newItems: MediaItem[] = []; selection.each((attachment: any) => { const mediaType = attachment.get("type"); const mediaItem: MediaItem = { id: attachment.get("id").toString(), attachment_id: attachment.get("id"), url: attachment.get("url"), type: mediaType as "image" | "video", alt_text: attachment.get("alt") || "", caption: attachment.get("caption") || "", }; if (mediaType === "image") { const sizes = attachment.get("sizes"); mediaItem.thumbnail_url = sizes?.medium?.url || sizes?.thumbnail?.url || attachment.get("url"); } newItems.push(mediaItem); }); if (newItems.length > 0) { onChange([...items, ...newItems]); } }); prepareWordPressMediaFrameOpen(); mediaUploader.open(); } else { // Fallback for non-WordPress environments const input = document.createElement("input"); input.type = "file"; input.multiple = true; input.accept = acceptTypes === "videos" ? "video/*" : acceptTypes === "images" ? "image/*" : "image/*,video/*"; input.onchange = (e) => { const files = Array.from((e.target as HTMLInputElement).files || []); const newItems: MediaItem[] = files .slice(0, maxItems - items.length) .map((file, index) => ({ id: `temp_${Date.now()}_${index}`, attachment_id: 0, // Temporary files don't have attachment IDs url: URL.createObjectURL(file), type: file.type.startsWith("video/") ? "video" : "image", alt_text: file.name, caption: file.name, })); onChange([...items, ...newItems]); }; input.click(); } }; const handleMediaRemove = (index: number) => { onChange(items.filter((_, i) => i !== index)); }; const isImage = (item: MediaItem) => item.type === "image"; return (

{getMediaTitle(acceptTypes)}

{getMediaDescription(acceptTypes)}

{items.length}/{maxItems}
{items.length > 0 && (
{items.map((item, index) => (
{isImage(item) ? ( { { console.error("Image load error:", e, "Item:", item); // Debug log // Fallback to placeholder or broken image icon (e.target as HTMLImageElement).style.display = "none"; const parent = (e.target as HTMLImageElement) .parentElement; if (parent) { parent.innerHTML = '
🖼️
' + __("Image not available", "yatra") + "
"; } }} onLoad={() => { // Image loaded successfully }} /> ) : (
)}
{/* Delete Button */}
{/* Caption */} {item.caption && (

{item.caption}

)}
))}
)} {/* Add Media Button */} {items.length < maxItems && (
)} {items.length === 0 && (

{__( "No media items yet. Click 'Add Media' to get started.", "yatra", )}

)}
); };