diff --git a/app/src/admin/MediaLibrary.jsx b/app/src/admin/MediaLibrary.jsx new file mode 100644 index 0000000..1077fe2 --- /dev/null +++ b/app/src/admin/MediaLibrary.jsx @@ -0,0 +1,89 @@ +import { useState, useEffect, useCallback } from 'react'; +import { useToast, ConfirmModal, inputStyle } from '../../teknav-ui.jsx'; +import { adminApi } from '../lib/admin-api.js'; +import { PanelState, actionBtn } from './Shared.jsx'; + +function MediaLibrary({ role }) { + const toast = useToast(); + const [items, setItems] = useState([]); + const [query, setQuery] = useState(''); + const [mimeType, setMimeType] = useState(''); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(false); + const [confirm, setConfirm] = useState(null); + + const refresh = useCallback(() => { + setLoading(true); + setError(false); + return adminApi.listMedia({ q: query, mimeType, limit: 60 }) + .then(res => setItems(res.items ?? [])) + .catch(() => { setItems([]); setError(true); }) + .finally(() => setLoading(false)); + }, [query, mimeType]); + + useEffect(() => { refresh(); }, [refresh]); + + const copyUrl = async (url) => { + try { + await navigator.clipboard.writeText(url); + toast('آدرس رسانه کپی شد'); + } catch { + toast('کپی آدرس رسانه ناموفق بود', 'error'); + } + }; + + const deleteMedia = async (id) => { + try { + await adminApi.deleteMedia(id); + toast('رسانه حذف شد'); + refresh(); + } catch (e) { + toast(e.body?.error === 'media_in_use' ? 'این رسانه در محتوا یا پروفایل استفاده شده است' : 'حذف رسانه ناموفق بود', 'error'); + } finally { + setConfirm(null); + } + }; + + return ( +
+ {confirm && deleteMedia(confirm)} onCancel={() => setConfirm(null)} />} +
+ setQuery(e.target.value)} placeholder="جستجوی نام فایل..." style={{ ...inputStyle, maxWidth: 260 }} dir="rtl" /> + +
+ + {!loading && !error && items.length > 0 && ( +
+ {items.map(item => ( +
+
+ {item.mimeType?.startsWith('image/') + ? {item.filename} + : {item.mimeType}} +
+
+
{item.filename}
+
+ {item.sizeBytes ? `${Math.round(item.sizeBytes / 1024).toLocaleString('fa-IR')} KB` : 'اندازه نامشخص'} + {item.width && item.height ? ` · ${item.width}×${item.height}` : ''} +
+
+ + {role === 'admin' && } +
+
+
+ ))} +
+ )} +
+ ); +} + +export { MediaLibrary };