import { Button, Spinner } from '@ifrc-go/ui';
import styles from '../../pages/UploadPage/UploadPage.module.css';
interface FullSizeImageModalProps {
isOpen: boolean;
imageUrl: string | null;
preview: string | null;
selectedImageData?: { file: File; index: number } | null;
onClose: () => void;
isLoading?: boolean;
}
export function FullSizeImageModal({ isOpen, imageUrl, preview, selectedImageData, onClose, isLoading = false }: FullSizeImageModalProps) {
if (!isOpen) return null;
// Determine which image to show
let imageSrc: string | undefined;
let imageAlt: string;
if (selectedImageData) {
// Show specific image from multi-upload
imageSrc = URL.createObjectURL(selectedImageData.file);
imageAlt = `Image ${selectedImageData.index + 1}: ${selectedImageData.file.name}`;
} else {
// Show single image (backward compatibility)
imageSrc = imageUrl || preview || undefined;
imageAlt = "Full size map";
}
return (
e.stopPropagation()}>
✕
{isLoading ? (
) : (
)}
);
}
interface RatingWarningModalProps {
isOpen: boolean;
onClose: () => void;
}
export function RatingWarningModal({ isOpen, onClose }: RatingWarningModalProps) {
if (!isOpen) return null;
return (
e.stopPropagation()}>
Please Confirm Your Ratings
You must confirm your performance ratings before submitting. Please go back to the rating section and click "Confirm Ratings".
Close
);
}
interface DeleteConfirmModalProps {
isOpen: boolean;
onConfirm: () => void;
onCancel: () => void;
}
export function DeleteConfirmModal({ isOpen, onConfirm, onCancel }: DeleteConfirmModalProps) {
if (!isOpen) return null;
return (
e.stopPropagation()}>
Delete Image?
This action cannot be undone. Are you sure you want to delete this uploaded image?
Delete
Cancel
);
}
interface NavigationConfirmModalProps {
isOpen: boolean;
onConfirm: () => void;
onCancel: () => void;
}
export function NavigationConfirmModal({ isOpen, onConfirm, onCancel }: NavigationConfirmModalProps) {
if (!isOpen) return null;
return (
e.stopPropagation()}>
Leave Page?
Your uploaded image will be deleted if you leave this page. Are you sure you want to continue?
Leave Page
Stay
);
}
interface FallbackNotificationModalProps {
isOpen: boolean;
fallbackInfo: {
originalModel: string;
fallbackModel: string;
reason: string;
} | null;
onClose: () => void;
}
export function FallbackNotificationModal({ isOpen, fallbackInfo, onClose }: FallbackNotificationModalProps) {
if (!isOpen || !fallbackInfo) return null;
// Parse the reason to make it more user-friendly
const parseReason = (reason: string): string => {
if (reason.includes("quota") || reason.includes("credits")) {
return "API quota exceeded - you've used up your monthly free credits";
} else if (reason.includes("rate") || reason.includes("429")) {
return "Rate limit exceeded - too many requests";
} else if (reason.includes("loading") || reason.includes("503")) {
return "Model is currently loading or unavailable";
} else if (reason.includes("network") || reason.includes("timeout")) {
return "Network connection issue";
} else if (reason.includes("MODEL_UNAVAILABLE")) {
return "Model service is temporarily unavailable";
} else {
return reason;
}
};
const userFriendlyReason = parseReason(fallbackInfo.reason);
return (
e.stopPropagation()}>
⚠️ Model Changed
{fallbackInfo.originalModel} is currently unavailable.
We've automatically switched to {fallbackInfo.fallbackModel} to complete your request.
Reason:
{userFriendlyReason}
Got it
);
}
interface PreprocessingNotificationModalProps {
isOpen: boolean;
preprocessingInfo: {
original_filename: string;
processed_filename: string;
original_mime_type: string;
processed_mime_type: string;
was_preprocessed: boolean;
error?: string;
} | null;
onClose: () => void;
}
export function PreprocessingNotificationModal({ isOpen, preprocessingInfo, onClose }: PreprocessingNotificationModalProps) {
if (!isOpen || !preprocessingInfo) return null;
return (
e.stopPropagation()}>
File Converted
Your file {preprocessingInfo.original_filename} has been converted from
{preprocessingInfo.original_mime_type} to
{preprocessingInfo.processed_mime_type} for optimal processing.
This conversion ensures your file is in the best format for our AI models to analyze.
Got it
);
}
interface PreprocessingModalProps {
isOpen: boolean;
isPreprocessing: boolean;
preprocessingProgress: string;
onConfirm: () => void;
onCancel: () => void;
}
export function PreprocessingModal({
isOpen,
isPreprocessing,
preprocessingProgress,
onConfirm,
onCancel
}: PreprocessingModalProps) {
if (!isOpen) return null;
return (
e.stopPropagation()}>
File Conversion Required
The file you selected will be converted to PNG format.
This ensures optimal compatibility and processing by our AI models.
{!isPreprocessing && (
Convert File
Cancel
)}
{isPreprocessing && (
)}
);
}
interface UnsupportedFormatModalProps {
isOpen: boolean;
unsupportedFile: File | null;
onClose: () => void;
}
export function UnsupportedFormatModal({ isOpen, unsupportedFile, onClose }: UnsupportedFormatModalProps) {
if (!isOpen || !unsupportedFile) return null;
return (
e.stopPropagation()}>
Unsupported File Format
The file {unsupportedFile.name} is not supported for upload.
Supported formats:
• Images: JPEG, PNG, TIFF, HEIC, WebP, GIF
• Documents: PDF (will be converted to image)
Recommendation: Convert your file to JPEG or PNG format for best compatibility.
Got it
);
}
interface FileSizeWarningModalProps {
isOpen: boolean;
oversizedFile: File | null;
onClose: () => void;
onCancel: () => void;
}
export function FileSizeWarningModal({ isOpen, oversizedFile, onClose, onCancel }: FileSizeWarningModalProps) {
if (!isOpen || !oversizedFile) return null;
return (
e.stopPropagation()}>
File Size Warning
The file {oversizedFile.name} is large ({(oversizedFile.size / (1024 * 1024)).toFixed(1)}MB).
Warning: This file size might exceed the limits of the AI models we use.
You can still proceed, but consider using a smaller file if you encounter issues.
Continue
Cancel
);
}