174 lines
6.1 KiB
JavaScript
174 lines
6.1 KiB
JavaScript
/**
|
|
* Folders Management Composable
|
|
* Handles folder operations for recordings
|
|
*/
|
|
|
|
const { computed, ref } = Vue;
|
|
|
|
export function useFolders({
|
|
recordings,
|
|
availableFolders,
|
|
selectedRecording,
|
|
showToast,
|
|
setGlobalError
|
|
}) {
|
|
// Computed / Helpers
|
|
const getRecordingFolder = (recording) => {
|
|
if (!recording || !recording.folder_id) return null;
|
|
// Try to get from recording.folder first, then lookup
|
|
if (recording.folder) return recording.folder;
|
|
return availableFolders.value?.find(f => f.id === recording.folder_id) || null;
|
|
};
|
|
|
|
const getFolderById = (folderId) => {
|
|
if (!folderId || !availableFolders.value) return null;
|
|
// Use == for loose equality to handle string/number type mismatch (e.g., from localStorage)
|
|
return availableFolders.value.find(f => f.id == folderId) || null;
|
|
};
|
|
|
|
const getFolderColor = (folderId) => {
|
|
const folder = getFolderById(folderId);
|
|
return folder?.color || '#10B981';
|
|
};
|
|
|
|
const getFolderName = (folderId) => {
|
|
const folder = getFolderById(folderId);
|
|
return folder?.name || 'Folder';
|
|
};
|
|
|
|
const getAvailableFoldersForRecording = () => {
|
|
if (!availableFolders.value) return [];
|
|
return availableFolders.value;
|
|
};
|
|
|
|
// Methods
|
|
const assignFolderToRecording = async (recordingId, folderId) => {
|
|
try {
|
|
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
|
|
|
|
const response = await fetch(`/api/recordings/${recordingId}/folder`, {
|
|
method: 'PUT',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRFToken': csrfToken
|
|
},
|
|
body: JSON.stringify({ folder_id: folderId || null })
|
|
});
|
|
|
|
if (!response.ok) {
|
|
const errorData = await response.json();
|
|
throw new Error(errorData.error || 'Failed to update folder');
|
|
}
|
|
|
|
const updatedRecording = await response.json();
|
|
|
|
// Update local recording data
|
|
const recordingInList = recordings.value.find(r => r.id === recordingId);
|
|
if (recordingInList) {
|
|
recordingInList.folder_id = updatedRecording.folder_id;
|
|
recordingInList.folder = updatedRecording.folder;
|
|
}
|
|
|
|
// Update selectedRecording if it matches
|
|
if (selectedRecording.value && selectedRecording.value.id === recordingId) {
|
|
selectedRecording.value.folder_id = updatedRecording.folder_id;
|
|
selectedRecording.value.folder = updatedRecording.folder;
|
|
}
|
|
|
|
// Update folder recording counts
|
|
if (availableFolders.value) {
|
|
availableFolders.value.forEach(f => {
|
|
const count = recordings.value.filter(r => r.folder_id === f.id).length;
|
|
f.recording_count = count;
|
|
});
|
|
}
|
|
|
|
if (folderId) {
|
|
const folder = availableFolders.value?.find(f => f.id === folderId);
|
|
showToast(`Moved to folder "${folder?.name || 'Unknown'}"`, 'fa-folder', 2000, 'success');
|
|
} else {
|
|
showToast('Removed from folder', 'fa-folder-minus', 2000, 'success');
|
|
}
|
|
|
|
return updatedRecording;
|
|
|
|
} catch (error) {
|
|
console.error('Error updating folder:', error);
|
|
setGlobalError(`Failed to update folder: ${error.message}`);
|
|
return null;
|
|
}
|
|
};
|
|
|
|
const removeRecordingFromFolder = async (recordingId) => {
|
|
return assignFolderToRecording(recordingId, null);
|
|
};
|
|
|
|
const bulkAssignFolder = async (recordingIds, folderId) => {
|
|
try {
|
|
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
|
|
|
|
const response = await fetch('/api/recordings/bulk/folder', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRFToken': csrfToken
|
|
},
|
|
body: JSON.stringify({
|
|
recording_ids: recordingIds,
|
|
folder_id: folderId || null
|
|
})
|
|
});
|
|
|
|
if (!response.ok) {
|
|
const errorData = await response.json();
|
|
throw new Error(errorData.error || 'Failed to update folders');
|
|
}
|
|
|
|
const result = await response.json();
|
|
|
|
// Update local recording data
|
|
recordingIds.forEach(id => {
|
|
const recording = recordings.value.find(r => r.id === id);
|
|
if (recording) {
|
|
recording.folder_id = folderId || null;
|
|
recording.folder = folderId ? availableFolders.value?.find(f => f.id === folderId) : null;
|
|
}
|
|
});
|
|
|
|
// Update folder recording counts
|
|
if (availableFolders.value) {
|
|
availableFolders.value.forEach(f => {
|
|
const count = recordings.value.filter(r => r.folder_id === f.id).length;
|
|
f.recording_count = count;
|
|
});
|
|
}
|
|
|
|
if (folderId) {
|
|
const folder = availableFolders.value?.find(f => f.id === folderId);
|
|
showToast(`${result.updated_count} recording(s) moved to "${folder?.name || 'Unknown'}"`, 'fa-folder', 2000, 'success');
|
|
} else {
|
|
showToast(`${result.updated_count} recording(s) removed from folder`, 'fa-folder-minus', 2000, 'success');
|
|
}
|
|
|
|
return result;
|
|
|
|
} catch (error) {
|
|
console.error('Error bulk updating folders:', error);
|
|
setGlobalError(`Failed to update folders: ${error.message}`);
|
|
return null;
|
|
}
|
|
};
|
|
|
|
return {
|
|
// Methods
|
|
getRecordingFolder,
|
|
getFolderById,
|
|
getFolderColor,
|
|
getFolderName,
|
|
getAvailableFoldersForRecording,
|
|
assignFolderToRecording,
|
|
removeRecordingFromFolder,
|
|
bulkAssignFolder
|
|
};
|
|
}
|