2025-12-09 08:17:44 -06:00

174 lines
6.7 KiB
JavaScript

import { useState, useEffect } from 'react';
import './MediaGallery.css';
function MediaGallery({ kaNumber, token, onInsertMedia, isOpen, onToggle }) {
const [media, setMedia] = useState([]);
const [loading, setLoading] = useState(true);
const [uploading, setUploading] = useState(false);
const [error, setError] = useState('');
useEffect(() => {
fetchMedia();
}, [kaNumber, isOpen]);
const fetchMedia = async () => {
try {
const response = await fetch(`http://localhost:9000/api/articles/${kaNumber}/media`, {
headers: {
'Authorization': `Bearer ${token}`
}
});
if (response.ok) {
const data = await response.json();
setMedia(data);
} else {
setError('Failed to fetch media');
}
} catch(err) {
console.error('Error fetching media:', err);
setError('Failed to load media');
} finally {
setLoading(false);
}
};
const handleFileUpload = async (e) => {
const file = e.target.files[0];
if (!file) return;
setUploading(true);
setError('');
const formData = new FormData();
formData.append('file', file);
try {
const response = await fetch(`/api/articles/${kaNumber}/media`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`
},
body: formData
});
if (response.ok) {
const newMedia = await response.json();
setMedia([...media, newMedia]);
} else {
const data = await response.json();
setError(data.error || 'Upload failed');
}
} catch(err) {
console.error('Failed to upload file:', err);
setError('Failed to upload file');
} finally {
setUploading(false);
e.target.value = '';
}
}
const handleDelete = async (filename) => {
if (!confirm('Are you sure you want to delete this file?')) return;
try {
const response = await fetch(`/api/articles/${kaNumber}/media/${filename}`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${token}`
}
});
if (response.ok) {
setMedia(media.filter(m => m.filename !== filename));
} else {
alert('Failed to delete file');
}
} catch(err) {
console.error('Error deleting file:', err);
alert('Failed to delete file');
}
};
return (
<>
<button className={`drawer-toggle ${isOpen ? 'open' : ''}`} onClick={onToggle}>
<span className='toggle-icon'>{isOpen ? '▼' : '▲'}</span>
<span className='toggle-text'>Media Gallery</span>
{media.length > 0 && <span className='media-count'>{media.length}</span>}
</button>
<div className={`media-drawer ${isOpen ? 'open' : ''}`}>
<div className='drawer-handle' onClick={onToggle}>
<div className='handle-bar'></div>
</div>
<div className='drawer-content'>
<div className='gallery-header'>
<h3>Media Gallery - {kaNumber}</h3>
<label className='btn btn-success'>
<input
type='file'
onChange={handleFileUpload}
accept='image/*, video/*'
disabled={uploading}
style={{display: 'none'}}
/>
{uploading ? 'Uploading...' : '+ Upload Media'}
</label>
</div>
{error && <div className='error-message'>{error}</div>}
{loading ? (
<div className='loading-container'>
<div className='loading-spinner'></div>
<div className='loading-text'>Loading media...</div>
</div>
) : media.length === 0 ? (
<div className='empty-state'>
<div className='empty-state-icon'>📷</div>
<h3 className='empty-state-title'>No Media Yet</h3>
<p className='empty-state-description'>
Click "Upload Media" to add images or videos to this article.
</p>
</div>
) : (
<div className='media-grid'>
{media.map(item => (
<div key={item.filename} className='media-item'>
{item.type === 'image' ? (
<img
src={`${item.url}`}
alt={item.filename}
onClick={() => onInsertMedia(item)}
/>
) : (
<div className='video-thumbnail' onClick={() => onInsertMedia(item)}>
<span className='video-icon'>🎥</span>
<span className='video-label'>Video</span>
</div>
)}
<div className='btn-group gap-sm'>
<button
className='btn btn-primary btn-sm'
onClick={() => onInsertMedia(item)}
>Insert</button>
<button
className='btn btn-danger btn-sm'
onClick={() => handleDelete(item.filename)}
>Delete</button>
</div>
<div className='media-filename'>{item.filename}</div>
</div>
))}
</div>
)}
</div>
</div>
</>
);
}
export default MediaGallery;