frontend_nyla/src/components/FormGenerator/ActionButtons/ViewActionButton/ViewActionButton.tsx
2025-10-12 14:36:39 +02:00

97 lines
3.1 KiB
TypeScript

import React, { useState } from 'react';
import { IoIosEye } from 'react-icons/io';
import { useLanguage } from '../../../../contexts/LanguageContext';
import { FilePreview } from '../../../FilePreview/FilePreview';
import styles from '../ActionButton.module.css';
export interface ViewActionButtonProps<T = any> {
row: T;
onView: (row: T) => Promise<void> | void;
disabled?: boolean | { disabled: boolean; message?: string };
loading?: boolean;
className?: string;
title?: string;
isViewing?: boolean;
hookData?: any; // Contains all hook data including operations
// Field mappings
idField?: string; // Field name for the unique identifier
nameField?: string; // Field name for display name
typeField?: string; // Field name for type/mime type
loadingStateName?: string; // Name of the loading state in hookData
}
export function ViewActionButton<T = any>({
row,
onView,
disabled = false,
loading = false,
className = '',
title,
isViewing = false,
hookData,
idField = 'id',
nameField = 'name',
typeField = 'type',
loadingStateName = 'previewingFiles'
}: ViewActionButtonProps<T>) {
const { t } = useLanguage();
const [internalLoading, setInternalLoading] = useState(false);
const [isPopupOpen, setIsPopupOpen] = useState(false);
// Extract disabled state and tooltip message
const isDisabled = typeof disabled === 'boolean' ? disabled : disabled?.disabled || false;
const disabledMessage = typeof disabled === 'object' ? disabled?.message : undefined;
const handleClick = async (e: React.MouseEvent) => {
e.stopPropagation();
if (!isDisabled && !loading && !isViewing && !internalLoading) {
setInternalLoading(true);
try {
// Call the onView callback if provided
if (onView) {
await onView(row);
}
// Open the file preview
setIsPopupOpen(true);
} finally {
setInternalLoading(false);
}
}
};
const buttonTitle = title || t('files.action.preview', 'Preview');
// Use hookData viewing state if available, otherwise use passed isViewing
const loadingState = hookData?.[loadingStateName];
const actualIsViewing = loadingState?.has((row as any)[idField]) || isViewing;
const isLoading = loading || actualIsViewing || internalLoading;
// Determine the final button title (tooltip)
const finalTitle = isDisabled && disabledMessage ? disabledMessage : buttonTitle;
return (
<>
<button
onClick={handleClick}
className={`${styles.actionButton} ${styles.view} ${isLoading ? styles.loading : ''} ${isDisabled ? styles.disabled : ''} ${className}`}
title={finalTitle}
disabled={isDisabled || isLoading}
>
<span className={styles.actionIcon}>
{isLoading ? '⏳' : <IoIosEye />}
</span>
</button>
{/* File Preview Component */}
<FilePreview
isOpen={isPopupOpen}
onClose={() => setIsPopupOpen(false)}
fileId={(row as any)[idField]}
fileName={(row as any)[nameField] || 'Unknown Item'}
mimeType={(row as any)[typeField]}
/>
</>
);
}
export default ViewActionButton;