import React from 'react' import { usePage } from '@inertiajs/react' import StudioLayout from '../../Layouts/StudioLayout' import StudioToolbar from '../../Components/Studio/StudioToolbar' import StudioGridCard from '../../Components/Studio/StudioGridCard' import StudioTable from '../../Components/Studio/StudioTable' import BulkActionsBar from '../../Components/Studio/BulkActionsBar' import BulkTagModal from '../../Components/Studio/BulkTagModal' import BulkCategoryModal from '../../Components/Studio/BulkCategoryModal' import ConfirmDangerModal from '../../Components/Studio/ConfirmDangerModal' function getCsrfToken() { return document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '' } export default function StudioDrafts() { const { props } = usePage() const { categories } = props const [viewMode, setViewMode] = React.useState(() => localStorage.getItem('studio_view_mode') || 'grid') const [artworks, setArtworks] = React.useState([]) const [meta, setMeta] = React.useState({ current_page: 1, last_page: 1, per_page: 24, total: 0 }) const [loading, setLoading] = React.useState(true) const [search, setSearch] = React.useState('') const [sort, setSort] = React.useState('created_at:desc') const [selectedIds, setSelectedIds] = React.useState([]) const [deleteModal, setDeleteModal] = React.useState({ open: false, ids: [] }) const [tagModal, setTagModal] = React.useState({ open: false, mode: 'add' }) const [categoryModal, setCategoryModal] = React.useState({ open: false }) const searchTimer = React.useRef(null) const perPage = viewMode === 'list' ? 50 : 24 function getCsrfToken() { return document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '' } const fetchArtworks = React.useCallback(async (page = 1) => { setLoading(true) try { const params = new URLSearchParams() params.set('page', page) params.set('per_page', perPage) params.set('sort', sort) params.set('status', 'draft') if (search) params.set('q', search) const res = await fetch(`/api/studio/artworks?${params.toString()}`, { headers: { 'Accept': 'application/json', 'X-CSRF-TOKEN': getCsrfToken() }, credentials: 'same-origin', }) const data = await res.json() setArtworks(data.data || []) setMeta(data.meta || meta) } catch (err) { console.error('Failed to fetch:', err) } finally { setLoading(false) } }, [search, sort, perPage]) React.useEffect(() => { clearTimeout(searchTimer.current) searchTimer.current = setTimeout(() => fetchArtworks(1), 300) return () => clearTimeout(searchTimer.current) }, [fetchArtworks]) const handleViewModeChange = (mode) => { setViewMode(mode) localStorage.setItem('studio_view_mode', mode) } const toggleSelect = (id) => setSelectedIds((p) => p.includes(id) ? p.filter((i) => i !== id) : [...p, id]) const selectAll = () => { const ids = artworks.map((a) => a.id) setSelectedIds(ids.every((id) => selectedIds.includes(id)) ? [] : ids) } const handleAction = async (action, artwork) => { if (action === 'edit') { window.location.href = `/studio/artworks/${artwork.id}/edit`; return } if (action === 'delete') { setDeleteModal({ open: true, ids: [artwork.id] }); return } try { await fetch(`/api/studio/artworks/${artwork.id}/toggle`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', 'X-CSRF-TOKEN': getCsrfToken() }, credentials: 'same-origin', body: JSON.stringify({ action }), }) fetchArtworks(meta.current_page) } catch (err) { console.error(err) } } const executeBulk = async (action) => { if (action === 'delete') { setDeleteModal({ open: true, ids: [...selectedIds] }); return } if (action === 'add_tags') { setTagModal({ open: true, mode: 'add' }); return } if (action === 'remove_tags') { setTagModal({ open: true, mode: 'remove' }); return } if (action === 'change_category') { setCategoryModal({ open: true }); return } try { await fetch('/api/studio/artworks/bulk', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', 'X-CSRF-TOKEN': getCsrfToken() }, credentials: 'same-origin', body: JSON.stringify({ action, artwork_ids: selectedIds, params: {} }), }) setSelectedIds([]) fetchArtworks(meta.current_page) } catch (err) { console.error(err) } } const confirmBulkTags = async (tagIds) => { const action = tagModal.mode === 'add' ? 'add_tags' : 'remove_tags' setTagModal({ open: false, mode: 'add' }) try { await fetch('/api/studio/artworks/bulk', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', 'X-CSRF-TOKEN': getCsrfToken() }, credentials: 'same-origin', body: JSON.stringify({ action, artwork_ids: selectedIds, params: { tag_ids: tagIds } }), }) setSelectedIds([]) fetchArtworks(meta.current_page) } catch (err) { console.error(err) } } const confirmBulkCategory = async (categoryId) => { setCategoryModal({ open: false }) try { await fetch('/api/studio/artworks/bulk', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', 'X-CSRF-TOKEN': getCsrfToken() }, credentials: 'same-origin', body: JSON.stringify({ action: 'change_category', artwork_ids: selectedIds, params: { category_id: categoryId } }), }) setSelectedIds([]) fetchArtworks(meta.current_page) } catch (err) { console.error(err) } } const confirmDelete = async () => { try { await fetch('/api/studio/artworks/bulk', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', 'X-CSRF-TOKEN': getCsrfToken() }, credentials: 'same-origin', body: JSON.stringify({ action: 'delete', artwork_ids: deleteModal.ids, confirm: 'DELETE' }), }) setDeleteModal({ open: false, ids: [] }) setSelectedIds((p) => p.filter((id) => !deleteModal.ids.includes(id))) fetchArtworks(meta.current_page) } catch (err) { console.error(err) } } return ( {}} selectedCount={selectedIds.length} /> {loading && (
)} {!loading && viewMode === 'grid' && (
{artworks.map((art) => ( ))}
)} {!loading && viewMode === 'list' && ( )} {!loading && artworks.length === 0 && (

No draft artworks

)} {meta.last_page > 1 && (
{Array.from({ length: meta.last_page }, (_, i) => i + 1) .filter((p) => p === 1 || p === meta.last_page || Math.abs(p - meta.current_page) <= 2) .map((page, idx, arr) => ( {idx > 0 && arr[idx - 1] !== page - 1 && } ))}
)} setSelectedIds([])} /> setDeleteModal({ open: false, ids: [] })} onConfirm={confirmDelete} title="Permanently delete?" message={`Delete ${deleteModal.ids.length} artwork(s) permanently?`} /> setTagModal({ open: false, mode: 'add' })} onConfirm={confirmBulkTags} /> setCategoryModal({ open: false })} onConfirm={confirmBulkCategory} /> ) }