import { defineStore } from 'pinia' import { ref } from 'vue' import { useApi } from '../composables/useApi.js' export const useCleanupStore = defineStore('cleanup', () => { const api = useApi() // Defaults sourced from ImportSettings on mount. Cards pre-fill from // these so the common case ("apply current import filters // retroactively") is one click; operator can override per-audit. const defaults = ref({ min_width: 0, min_height: 0, transparency_threshold: 0.9, single_color_threshold: 0.95, single_color_tolerance: 30, }) const recentRuns = ref([]) async function loadDefaults() { const s = await api.get('/api/settings/import') defaults.value = { min_width: s.min_width ?? 0, min_height: s.min_height ?? 0, transparency_threshold: s.transparency_threshold ?? 0.9, single_color_threshold: s.single_color_threshold ?? 0.95, single_color_tolerance: s.single_color_tolerance ?? 30, } } async function previewMinDim(min_width, min_height) { return await api.post('/api/cleanup/min-dimension/preview', { body: { min_width, min_height }, }) } async function deleteMinDim(min_width, min_height, confirm) { return await api.post('/api/cleanup/min-dimension/delete', { body: { min_width, min_height, confirm }, }) } async function startAudit(rule, params) { return await api.post('/api/cleanup/audit', { body: { rule, params } }) } async function getAudit(id) { return await api.get(`/api/cleanup/audit/${id}`) } async function loadHistory(limit = 20) { const body = await api.get(`/api/cleanup/audit?limit=${limit}`) recentRuns.value = body.runs return body.runs } // The most recent audit run for a given rule, or null. Cards call this on // mount to reconnect to a scan that's still running (or to show the last // completed result) after the user navigates away and back. async function latestAuditForRule(rule) { const body = await api.get('/api/cleanup/audit', { params: { rule, limit: 1 } }) return (body.runs && body.runs[0]) || null } async function applyAudit(id, confirm) { return await api.post(`/api/cleanup/audit/${id}/apply`, { body: { confirm } }) } async function cancelAudit(id) { return await api.post(`/api/cleanup/audit/${id}/cancel`) } // --- placement reconciler (milestone #421) -------------------------------- // // Runs are server-side rows, so the DATABASE is the durable state here — // no localStorage resurfacing (useMaintenanceTask) is needed. Reload the // page, open it on another machine, and the run and its status are simply // there. That also means a plan survives being walked away from for a day. const placementRuns = ref([]) const layout = ref(null) // The survey: which rows sit outside their artist's directory. check_disk // additionally stats every destination (collisions, missing sources) and // costs one stat per misplaced row over NFS, so it is opt-in. async function loadLayout(checkDisk = false) { layout.value = await api.get('/api/cleanup/layout', { params: checkDisk ? { check_disk: 1 } : {}, }) return layout.value } // id -> name, so a run row can say "Conto" instead of "#47". The runs // endpoint carries artist_id alone: the name belongs to the artist, and // denormalising it into every run would go stale the moment one is renamed. async function loadArtistNames() { const rows = await api.get('/api/artists/names') return Object.fromEntries((rows || []).map(a => [a.id, a.name])) } async function loadPlacementRuns(limit = 25) { const body = await api.get('/api/cleanup/placement/runs', { params: { limit } }) placementRuns.value = body.runs || [] return placementRuns.value } // Detail carries `moves` — the plan the operator reads before agreeing. async function getPlacementRun(id) { return await api.get(`/api/cleanup/placement/runs/${id}`) } async function planPlacement(artistId = null) { return await api.post('/api/cleanup/placement/plan', { body: artistId === null ? {} : { artist_id: artistId }, }) } async function applyPlacement(id) { return await api.post(`/api/cleanup/placement/runs/${id}/apply`) } async function revertPlacement(id) { return await api.post(`/api/cleanup/placement/runs/${id}/revert`) } return { defaults, recentRuns, loadDefaults, previewMinDim, deleteMinDim, startAudit, getAudit, loadHistory, latestAuditForRule, applyAudit, cancelAudit, placementRuns, layout, loadLayout, loadArtistNames, loadPlacementRuns, getPlacementRun, planPlacement, applyPlacement, revertPlacement, } })