Organized the differences between server and docker versions.
We are launching a docker version (server version) today so we want to just organize the repo so its easier to navigate.
This commit is contained in:
226
desktop/src/scripts/utils/list-modal-manager.js
Normal file
226
desktop/src/scripts/utils/list-modal-manager.js
Normal file
@@ -0,0 +1,226 @@
|
||||
const ListModalManager = {
|
||||
API_BASE: '/api',
|
||||
currentData: null,
|
||||
isInList: false,
|
||||
currentEntry: null,
|
||||
|
||||
STATUS_MAP: {
|
||||
CURRENT: 'CURRENT',
|
||||
COMPLETED: 'COMPLETED',
|
||||
PLANNING: 'PLANNING',
|
||||
PAUSED: 'PAUSED',
|
||||
DROPPED: 'DROPPED',
|
||||
REPEATING: 'REPEATING'
|
||||
},
|
||||
|
||||
getEntryType(data) {
|
||||
if (!data) return 'ANIME';
|
||||
if (data.entry_type) return data.entry_type.toUpperCase();
|
||||
return 'ANIME';
|
||||
},
|
||||
|
||||
async checkIfInList(entryId, source = 'anilist', entryType) {
|
||||
if (!AuthUtils.isAuthenticated()) return false;
|
||||
|
||||
const url = `${this.API_BASE}/list/entry/${entryId}?source=${source}&entry_type=${entryType}`;
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
headers: AuthUtils.getSimpleAuthHeaders()
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
this.isInList = data.found && !!data.entry;
|
||||
this.currentEntry = data.entry || null;
|
||||
} else {
|
||||
this.isInList = false;
|
||||
this.currentEntry = null;
|
||||
}
|
||||
|
||||
return this.isInList;
|
||||
} catch (error) {
|
||||
console.error('Error checking list entry:', error);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
updateButton(buttonSelector = '.hero-buttons .btn-blur') {
|
||||
const btn = document.querySelector(buttonSelector);
|
||||
if (!btn) return;
|
||||
|
||||
if (this.isInList) {
|
||||
btn.innerHTML = `
|
||||
<svg width="20" height="20" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/>
|
||||
</svg>
|
||||
In Your ${this.currentData?.format ? 'Library' : 'List'}
|
||||
`;
|
||||
btn.style.background = 'rgba(34, 197, 94, 0.2)';
|
||||
btn.style.color = '#22c55e';
|
||||
btn.style.borderColor = 'rgba(34, 197, 94, 0.3)';
|
||||
} else {
|
||||
btn.innerHTML = `+ Add to ${this.currentData?.format ? 'Library' : 'List'}`;
|
||||
btn.style.background = null;
|
||||
btn.style.color = null;
|
||||
btn.style.borderColor = null;
|
||||
}
|
||||
},
|
||||
|
||||
open(data, source = 'anilist') {
|
||||
if (!AuthUtils.isAuthenticated()) {
|
||||
NotificationUtils.error('Please log in to manage your list.');
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentData = data;
|
||||
const entryType = this.getEntryType(data);
|
||||
const totalUnits = data.episodes || data.chapters || data.volumes || 999;
|
||||
|
||||
const modalTitle = document.getElementById('modal-title');
|
||||
const deleteBtn = document.getElementById('modal-delete-btn');
|
||||
const progressLabel = document.querySelector('label[for="entry-progress"]') ||
|
||||
document.getElementById('progress-label');
|
||||
|
||||
if (this.isInList && this.currentEntry) {
|
||||
document.getElementById('entry-status').value = this.currentEntry.status || 'PLANNING';
|
||||
document.getElementById('entry-progress').value = this.currentEntry.progress || 0;
|
||||
document.getElementById('entry-score').value = this.currentEntry.score || '';
|
||||
document.getElementById('entry-start-date').value = this.currentEntry.start_date?.split('T')[0] || '';
|
||||
document.getElementById('entry-end-date').value = this.currentEntry.end_date?.split('T')[0] || '';
|
||||
document.getElementById('entry-repeat-count').value = this.currentEntry.repeat_count || 0;
|
||||
document.getElementById('entry-notes').value = this.currentEntry.notes || '';
|
||||
document.getElementById('entry-is-private').checked = this.currentEntry.is_private === true || this.currentEntry.is_private === 1;
|
||||
|
||||
modalTitle.textContent = `Edit ${entryType === 'ANIME' ? 'List' : 'Library'} Entry`;
|
||||
deleteBtn.style.display = 'block';
|
||||
} else {
|
||||
document.getElementById('entry-status').value = 'PLANNING';
|
||||
document.getElementById('entry-progress').value = 0;
|
||||
document.getElementById('entry-score').value = '';
|
||||
document.getElementById('entry-start-date').value = '';
|
||||
document.getElementById('entry-end-date').value = '';
|
||||
document.getElementById('entry-repeat-count').value = 0;
|
||||
document.getElementById('entry-notes').value = '';
|
||||
document.getElementById('entry-is-private').checked = false;
|
||||
|
||||
modalTitle.textContent = `Add to ${entryType === 'ANIME' ? 'List' : 'Library'}`;
|
||||
deleteBtn.style.display = 'none';
|
||||
}
|
||||
|
||||
const statusSelect = document.getElementById('entry-status');
|
||||
|
||||
[...statusSelect.options].forEach(opt => {
|
||||
if (opt.value === 'CURRENT') {
|
||||
opt.textContent = entryType === 'ANIME' ? 'Watching' : 'Reading';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (progressLabel) {
|
||||
if (entryType === 'ANIME') {
|
||||
progressLabel.textContent = 'Episodes Watched';
|
||||
} else if (entryType === 'MANGA') {
|
||||
progressLabel.textContent = 'Chapters Read';
|
||||
} else {
|
||||
progressLabel.textContent = 'Volumes/Parts Read';
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('entry-progress').max = totalUnits;
|
||||
document.getElementById('add-list-modal').classList.add('active');
|
||||
},
|
||||
|
||||
close() {
|
||||
document.getElementById('add-list-modal').classList.remove('active');
|
||||
},
|
||||
|
||||
async save(entryId, source = 'anilist') {
|
||||
const uiStatus = document.getElementById('entry-status').value;
|
||||
const status = this.STATUS_MAP[uiStatus] || uiStatus;
|
||||
const progress = parseInt(document.getElementById('entry-progress').value) || 0;
|
||||
const scoreValue = document.getElementById('entry-score').value;
|
||||
const score = scoreValue ? parseFloat(scoreValue) : null;
|
||||
const start_date = document.getElementById('entry-start-date').value || null;
|
||||
const end_date = document.getElementById('entry-end-date').value || null;
|
||||
const repeat_count = parseInt(document.getElementById('entry-repeat-count').value) || 0;
|
||||
const notes = document.getElementById('entry-notes').value || null;
|
||||
const is_private = document.getElementById('entry-is-private').checked;
|
||||
|
||||
const entryType = this.getEntryType(this.currentData);
|
||||
|
||||
try {
|
||||
const response = await fetch(`${this.API_BASE}/list/entry`, {
|
||||
method: 'POST',
|
||||
headers: AuthUtils.getAuthHeaders(),
|
||||
body: JSON.stringify({
|
||||
entry_id: entryId,
|
||||
source,
|
||||
entry_type: entryType,
|
||||
status,
|
||||
progress,
|
||||
score,
|
||||
start_date,
|
||||
end_date,
|
||||
repeat_count,
|
||||
notes,
|
||||
is_private
|
||||
})
|
||||
});
|
||||
|
||||
if (!response.ok) throw new Error('Failed to save entry');
|
||||
|
||||
const data = await response.json();
|
||||
this.isInList = true;
|
||||
this.currentEntry = data.entry;
|
||||
this.updateButton();
|
||||
this.close();
|
||||
NotificationUtils.success(this.isInList ? 'Updated successfully!' : 'Added to your list!');
|
||||
} catch (error) {
|
||||
console.error('Error saving to list:', error);
|
||||
NotificationUtils.error('Failed to save. Please try again.');
|
||||
}
|
||||
},
|
||||
|
||||
async delete(entryId, source = 'anilist') {
|
||||
if (!confirm(`Remove this ${this.getEntryType(this.currentData).toLowerCase()} from your list?`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const entryType = this.getEntryType(this.currentData);
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
`${this.API_BASE}/list/entry/${entryId}?source=${source}&entry_type=${entryType}`,
|
||||
{
|
||||
method: 'DELETE',
|
||||
headers: AuthUtils.getSimpleAuthHeaders()
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) throw new Error('Failed to delete entry');
|
||||
|
||||
this.isInList = false;
|
||||
this.currentEntry = null;
|
||||
this.updateButton();
|
||||
this.close();
|
||||
NotificationUtils.success('Removed from your list');
|
||||
} catch (error) {
|
||||
console.error('Error deleting from list:', error);
|
||||
NotificationUtils.error('Failed to remove. Please try again.');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const modal = document.getElementById('add-list-modal');
|
||||
if (modal) {
|
||||
modal.addEventListener('click', (e) => {
|
||||
if (e.target.id === 'add-list-modal') {
|
||||
ListModalManager.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
window.ListModalManager = ListModalManager;
|
||||
Reference in New Issue
Block a user