541 lines
20 KiB
JavaScript
541 lines
20 KiB
JavaScript
let currentYear;
|
||
|
||
//Adding new element in the array creates new tab
|
||
const years = ['pre-2009', '2009', '2010', '2011', '2012', '2013', '2014', '2015',
|
||
'2016','2017','2018','2019','2020','2021','2022','2023', '2024', 're-watch', 'manga'];
|
||
|
||
function loadYearTabs() {
|
||
const yearTabs = document.getElementById('year-tabs');
|
||
|
||
// Populate the tabs
|
||
years.forEach(year => {
|
||
const li = document.createElement('li');
|
||
li.textContent = year;
|
||
li.classList.add('tab');
|
||
li.dataset.year = year; // Set data-year attribute for each tab
|
||
|
||
// Add a click event listener to each tab
|
||
li.addEventListener('click', () => {
|
||
loadYearContent(year);
|
||
});
|
||
|
||
yearTabs.appendChild(li);
|
||
// Now check if all entries are completed for this year
|
||
fetch(`php/check_completed_year.php?year=${encodeURIComponent(year)}`)
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
if (data.all_completed) {
|
||
// Strike through the tab if all are completed
|
||
li.style.textDecoration = 'line-through';
|
||
}
|
||
})
|
||
.catch(error => console.error('Error checking completed status:', error));
|
||
});
|
||
|
||
// Load the last active tab or default to 'pre-2009'
|
||
const activeYear = localStorage.getItem('activeYear') || 'pre-2009';
|
||
loadYearContent(activeYear);
|
||
}
|
||
|
||
function loadYearContent(year) {
|
||
currentYear = year;
|
||
// Save the current year in localStorage for persistence
|
||
localStorage.setItem('activeYear', year);
|
||
|
||
// Highlight the active tab
|
||
const tabs = document.querySelectorAll('#year-tabs .tab');
|
||
tabs.forEach(tab => {
|
||
// Add or remove the active class based on the tab's data-year
|
||
if (tab.dataset.year === year) {
|
||
tab.classList.add('active');
|
||
} else {
|
||
tab.classList.remove('active');
|
||
}
|
||
});
|
||
|
||
// Fetch and display content for the selected year
|
||
fetch(`php/fetch_data.php?year=${encodeURIComponent(year)}`)
|
||
.then(response => response.text())
|
||
.then(html => {
|
||
document.getElementById('content').innerHTML = html;
|
||
setupFormSubmission();
|
||
setupEditButtons();
|
||
setupDeleteButtons();
|
||
setupSuggestButton();
|
||
setupSetCompleteButtons();
|
||
setupSetCurrentlyWatchingButtons();
|
||
})
|
||
.catch(error => console.error('Error loading content:', error));
|
||
}
|
||
|
||
function setupFormSubmission() {
|
||
const form = document.getElementById('add-form');
|
||
|
||
function handleFormSubmit(event) {
|
||
event.preventDefault();
|
||
const formData = new FormData(form);
|
||
fetch('php/add_record.php', {
|
||
method: 'POST',
|
||
body: formData
|
||
})
|
||
.then(response => {
|
||
if (!response.ok) {
|
||
// Если сервер вернул ошибку (например, 403)
|
||
return response.json().then(errorData => {
|
||
if (response.status === 403) {
|
||
alert(errorData.message || 'Access denied: You are not authorized to perform this action.');
|
||
}
|
||
throw new Error(errorData.message || 'An error occurred.');
|
||
});
|
||
}
|
||
return response.text();
|
||
})
|
||
.then(() => {
|
||
// Если запись добавлена успешно
|
||
loadYearContent(currentYear);
|
||
})
|
||
.catch(error => {
|
||
console.error('Error:', error);
|
||
});
|
||
}
|
||
|
||
form.addEventListener('submit', handleFormSubmit);
|
||
|
||
form.addEventListener('keydown', event => {
|
||
if (event.ctrlKey && event.key === 'Enter') {
|
||
event.preventDefault();
|
||
handleFormSubmit(event);
|
||
}
|
||
});
|
||
}
|
||
|
||
|
||
function setupEditButtons() {
|
||
const editButtons = document.querySelectorAll('.edit-button');
|
||
editButtons.forEach(button => {
|
||
button.addEventListener('click', () => {
|
||
const recordId = button.dataset.id;
|
||
openEditModal(recordId);
|
||
});
|
||
});
|
||
}
|
||
|
||
function setupDeleteButtons() {
|
||
const deleteButtons = document.querySelectorAll('.delete-button');
|
||
deleteButtons.forEach(button => {
|
||
button.addEventListener('click', () => {
|
||
const recordId = button.dataset.id;
|
||
if (confirm('Are you sure you want to delete this record?')) {
|
||
fetch(`php/delete_record.php?id=${recordId}`, {
|
||
method: 'DELETE' // Используем метод DELETE для удаления
|
||
})
|
||
.then(response => {
|
||
if (!response.ok) {
|
||
// Если сервер вернул ошибку (например, 403)
|
||
return response.json().then(errorData => {
|
||
if (response.status === 403) {
|
||
alert(errorData.message || 'Access denied: You are not authorized to delete this record.');
|
||
}
|
||
throw new Error(errorData.message || 'An error occurred while deleting the record.');
|
||
});
|
||
}
|
||
return response.text();
|
||
})
|
||
.then(() => {
|
||
// Если удаление прошло успешно
|
||
loadYearContent(currentYear);
|
||
})
|
||
.catch(error => {
|
||
console.error('Error:', error);
|
||
});
|
||
}
|
||
});
|
||
});
|
||
}
|
||
|
||
|
||
function openEditModal(id) {
|
||
// Fetch record data
|
||
fetch(`php/fetch_record.php?id=${id}`)
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
const modal = document.getElementById('edit-modal');
|
||
const form = document.getElementById('edit-form');
|
||
form.innerHTML = generateEditForm(data);
|
||
modal.style.display = 'block';
|
||
setupEditFormSubmission();
|
||
});
|
||
}
|
||
|
||
function setupModal() {
|
||
const modal = document.getElementById('edit-modal');
|
||
const closeModal = document.getElementById('close-modal');
|
||
closeModal.addEventListener('click', () => modal.style.display = 'none');
|
||
|
||
window.addEventListener('keydown', event => {
|
||
if (event.key === 'Escape') {
|
||
modal.style.display = 'none';
|
||
}
|
||
});
|
||
|
||
// Close modal when clicking outside the modal content
|
||
modal.addEventListener('click', event => {
|
||
if (event.target === modal) {
|
||
modal.style.display = 'none';
|
||
}
|
||
});
|
||
}
|
||
|
||
function mapLabelToYear(label) {
|
||
if (label === 'pre-2009') return -1;
|
||
if (label === 're-watch') return -2;
|
||
return parseInt(label, 10);
|
||
}
|
||
|
||
function setupEditFormSubmission() {
|
||
const form = document.getElementById('edit-form');
|
||
|
||
function handleEditFormSubmit(event) {
|
||
event.preventDefault();
|
||
|
||
const yearLabelSelect = form.querySelector('#year_label');
|
||
const numericYearInput = form.querySelector('#year_numeric');
|
||
const selectedLabel = yearLabelSelect.value;
|
||
|
||
// Use the mapLabelToYear function
|
||
numericYearInput.value = mapLabelToYear(selectedLabel);
|
||
|
||
const formData = new FormData(form);
|
||
fetch('php/edit_record.php', {
|
||
method: 'POST',
|
||
body: formData
|
||
})
|
||
.then(response => {
|
||
if (!response.ok) {
|
||
return response.json().then(errorData => {
|
||
if (response.status === 403) {
|
||
alert(errorData.message || 'Access denied: You are not authorized to edit this record.');
|
||
}
|
||
throw new Error(errorData.message || 'An error occurred while editing the record.');
|
||
});
|
||
}
|
||
return response.text();
|
||
})
|
||
.then(() => {
|
||
const modal = document.getElementById('edit-modal');
|
||
modal.style.display = 'none';
|
||
loadYearContent(currentYear);
|
||
})
|
||
.catch(error => {
|
||
console.error('Error:', error);
|
||
});
|
||
}
|
||
|
||
|
||
form.addEventListener('submit', handleEditFormSubmit);
|
||
|
||
form.addEventListener('keydown', event => {
|
||
if (event.ctrlKey && event.key === 'Enter') {
|
||
event.preventDefault();
|
||
handleEditFormSubmit(event);
|
||
}
|
||
});
|
||
}
|
||
|
||
function generateEditForm(data) {
|
||
|
||
function mapYearToLabel(yearValue) {
|
||
if (yearValue == -1) return 'pre-2009';
|
||
if (yearValue == -2) return 're-watch';
|
||
if (yearValue == -3) return 'manga';
|
||
return yearValue.toString();
|
||
}
|
||
|
||
const selectedYearLabel = mapYearToLabel(data.year);
|
||
|
||
return `
|
||
<h3>Edit Record</h3>
|
||
<input type="hidden" name="id" value="${data.id}">
|
||
<input type="hidden" name="year" id="year_numeric" value="${data.year}">
|
||
|
||
<div class="form-group">
|
||
<label for="name">Name:</label>
|
||
<input type="text" name="name" id="name" class="form-control" value="${data.name || ''}" required>
|
||
</div>
|
||
|
||
<!-- Wrap season, year, and type fields in a single container -->
|
||
<div class="form-row">
|
||
<div class="form-group">
|
||
<label for="season">Season:</label>
|
||
<select name="season" id="season" class="form-control">
|
||
${['winter', 'spring', 'summer', 'fall', 'omake'].map(season => `
|
||
<option value="${season}" ${data.season === season ? 'selected' : ''}>
|
||
${season.charAt(0).toUpperCase() + season.slice(1)}
|
||
</option>
|
||
`).join('')}
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="year_label">Year:</label>
|
||
<select name="year_label" id="year_label" class="form-control">
|
||
${years.map(y => `
|
||
<option value="${y}" ${y === selectedYearLabel ? 'selected' : ''}>${y}</option>
|
||
`).join('')}
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="type">Type:</label>
|
||
<select name="type" id="type" class="form-control">
|
||
${['tv', 'special', 'short', 'ova', 'movie', 'other'].map(type => `
|
||
<option value="${type}" ${data.type === type ? 'selected' : ''}>${type}</option>
|
||
`).join('')}
|
||
</select>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="comment">Comment:</label>
|
||
<input type="text" name="comment" id="comment" class="form-control" value="${data.comment || ''}">
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="date_completed">Date Completed:</label>
|
||
<input type="date" name="date_completed" id="date_completed" class="form-control" value="${data.date_completed || ''}">
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="url">URL:</label>
|
||
<input type="url" name="url" id="url" class="form-control" value="${data.url || ''}">
|
||
</div>
|
||
<div class="form-group form-check">
|
||
<input type="checkbox" name="is_completed" id="is_completed" class="form-check-input" ${parseInt(data.is_completed) ? 'checked' : ''}>
|
||
<label for="is_completed" class="form-check-label">Is Completed</label>
|
||
</div>
|
||
<div class="form-group form-check">
|
||
<input type="checkbox" name="currently_watching" id="currently_watching" class="form-check-input" ${parseInt(data.currently_watching) ? 'checked' : ''}>
|
||
<label for="currently_watching" class="form-check-label">Currently Watching</label>
|
||
</div>
|
||
<button type="submit" class="btn btn-primary">Save Changes</button>
|
||
`;
|
||
}
|
||
|
||
|
||
function setupSuggestButton() {
|
||
const suggestButton = document.getElementById('suggest-button');
|
||
if (suggestButton) {
|
||
suggestButton.addEventListener('click', () => {
|
||
makeSuggestion();
|
||
});
|
||
}
|
||
}
|
||
|
||
|
||
function makeSuggestion() {
|
||
// Clear any previous suggestions
|
||
const previousSuggestion = document.getElementById('suggestion-display');
|
||
if (previousSuggestion) {
|
||
previousSuggestion.remove();
|
||
}
|
||
|
||
// Get all table rows that are not completed
|
||
const rows = Array.from(document.querySelectorAll('table tbody tr')).filter(row => {
|
||
return !row.classList.contains('completed');
|
||
});
|
||
|
||
// Exclude header rows and ensure there are at least two entries
|
||
if (rows.length < 1) {
|
||
alert('Not enough uncompleted entries to make a suggestion.');
|
||
return;
|
||
}
|
||
|
||
// Randomly select two different rows
|
||
const indices = [];
|
||
while (indices.length < 1) {
|
||
const index = Math.floor(Math.random() * rows.length);
|
||
if (!indices.includes(index)) {
|
||
indices.push(index);
|
||
}
|
||
}
|
||
|
||
const selectedRows = [rows[indices[0]]];
|
||
|
||
// Get the names of the selected records
|
||
const names = selectedRows.map(row => row.getAttribute('data-name'));
|
||
|
||
// Display the names at the top of the content
|
||
const content = document.getElementById('content');
|
||
const suggestionDisplayDiv = document.createElement('div');
|
||
suggestionDisplayDiv.id = 'suggestion-display';
|
||
suggestionDisplayDiv.innerHTML = `<p>${names.join('<br> ')}</p>`;
|
||
content.insertBefore(suggestionDisplayDiv, content.querySelector('button')); // Insert before the add form
|
||
}
|
||
|
||
function setupStickyTabs() {
|
||
const tabsContainer = document.querySelector('.tabs-container');
|
||
|
||
const observer = new IntersectionObserver(
|
||
([e]) => e.target.classList.toggle('is-sticky', e.intersectionRatio < 1),
|
||
{ threshold: [1] }
|
||
);
|
||
|
||
observer.observe(tabsContainer);
|
||
}
|
||
|
||
function setupSetCompleteButtons() {
|
||
const setCompleteButtons = document.querySelectorAll('.set-complete-button');
|
||
setCompleteButtons.forEach(button => {
|
||
button.addEventListener('click', () => {
|
||
const recordId = button.dataset.id;
|
||
const formData = new FormData();
|
||
formData.append('id', recordId);
|
||
fetch('php/set_complete.php', {
|
||
method: 'POST',
|
||
body: formData
|
||
})
|
||
.then(response => {
|
||
if (!response.ok) {
|
||
return response.json().then(errorData => {
|
||
if (response.status === 403) {
|
||
alert(errorData.message || 'Access denied: You are not authorized to perform this action.');
|
||
}
|
||
throw new Error(errorData.message || 'An error occurred while setting the record as complete.');
|
||
});
|
||
}
|
||
return response.json();
|
||
})
|
||
.then(() => {
|
||
// Reload the table to reflect the changes
|
||
loadYearContent(currentYear);
|
||
})
|
||
.catch(error => {
|
||
console.error('Error:', error);
|
||
});
|
||
});
|
||
});
|
||
}
|
||
|
||
function setupSetCurrentlyWatchingButtons() {
|
||
const setCurrentlyWatchingButtons = document.querySelectorAll('.set-currently-watching-button');
|
||
setCurrentlyWatchingButtons.forEach(button => {
|
||
button.addEventListener('click', () => {
|
||
const recordId = button.dataset.id;
|
||
const formData = new FormData();
|
||
formData.append('id', recordId);
|
||
fetch('php/set_currently_watching.php', {
|
||
method: 'POST',
|
||
body: formData
|
||
})
|
||
.then(response => {
|
||
if (!response.ok) {
|
||
return response.json().then(errorData => {
|
||
if (response.status === 403) {
|
||
alert(errorData.message || 'Access denied: You are not authorized to perform this action.');
|
||
}
|
||
throw new Error(errorData.message || 'An error occurred while setting the record as currently watching.');
|
||
});
|
||
}
|
||
return response.json();
|
||
})
|
||
.then(() => {
|
||
// Reload the table to reflect the changes
|
||
loadYearContent(currentYear);
|
||
})
|
||
.catch(error => {
|
||
console.error('Error:', error);
|
||
});
|
||
});
|
||
});
|
||
}
|
||
|
||
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
console.log('DOM fully loaded and parsed');
|
||
loadYearTabs();
|
||
setupModal();
|
||
var imageCache = {};
|
||
var currentHoverTarget = null;
|
||
|
||
function showImageTooltip(event, imageUrl) {
|
||
var tooltip = document.getElementById('image-tooltip');
|
||
if (!tooltip) {
|
||
tooltip = document.createElement('div');
|
||
tooltip.id = 'image-tooltip';
|
||
tooltip.style.position = 'absolute';
|
||
tooltip.style.border = '1px solid #ccc';
|
||
tooltip.style.background = '#fff';
|
||
tooltip.style.padding = '5px';
|
||
tooltip.style.zIndex = 1000;
|
||
tooltip.style.maxWidth = '200px';
|
||
tooltip.style.maxHeight = '300px';
|
||
tooltip.style.overflow = 'hidden';
|
||
tooltip.style.display = 'none';
|
||
document.body.appendChild(tooltip);
|
||
}
|
||
|
||
tooltip.innerHTML = '<img src="' + imageUrl + '" style="max-width: 100%; max-height: 100%;">';
|
||
tooltip.style.left = (event.pageX + 15) + 'px';
|
||
tooltip.style.top = (event.pageY + 15) + 'px';
|
||
tooltip.style.display = 'block';
|
||
}
|
||
|
||
function hideImageTooltip() {
|
||
var tooltip = document.getElementById('image-tooltip');
|
||
if (tooltip) {
|
||
tooltip.style.display = 'none';
|
||
}
|
||
}
|
||
|
||
// Добавляем обработчики событий на родительский элемент
|
||
var contentDiv = document.getElementById('content');
|
||
|
||
contentDiv.addEventListener('mouseover', function (event) {
|
||
var target = event.target;
|
||
|
||
// Проверяем, является ли целевой элемент ссылкой с атрибутом data-url
|
||
if (target.tagName.toLowerCase() === 'a' && target.hasAttribute('data-url')) {
|
||
var url = target.getAttribute('data-url');
|
||
currentHoverTarget = target; // Set the current hover target
|
||
|
||
if (imageCache[url]) {
|
||
showImageTooltip(event, imageCache[url]);
|
||
} else {
|
||
var xhr = new XMLHttpRequest();
|
||
xhr.open('GET', './php/get_image.php?url=' + encodeURIComponent(url), true);
|
||
xhr.onreadystatechange = function () {
|
||
if (xhr.readyState === 4 && xhr.status === 200) {
|
||
var response = JSON.parse(xhr.responseText);
|
||
if (response.image_url) {
|
||
imageCache[url] = response.image_url;
|
||
if (currentHoverTarget === target) {
|
||
showImageTooltip(event, response.image_url);
|
||
}
|
||
} else if (response.error) {
|
||
console.error(response.error);
|
||
}
|
||
}
|
||
};
|
||
xhr.send();
|
||
}
|
||
}
|
||
});
|
||
|
||
contentDiv.addEventListener('mouseout', function (event) {
|
||
var target = event.target;
|
||
|
||
if (target.tagName.toLowerCase() === 'a' && target.hasAttribute('data-url')) {
|
||
hideImageTooltip();
|
||
if (currentHoverTarget === target) {
|
||
currentHoverTarget = null; // Clear the current hover target
|
||
}
|
||
}
|
||
});
|
||
|
||
contentDiv.addEventListener('mousemove', function (event) {
|
||
var tooltip = document.getElementById('image-tooltip');
|
||
if (tooltip && tooltip.style.display === 'block') {
|
||
tooltip.style.left = (event.pageX + 15) + 'px';
|
||
tooltip.style.top = (event.pageY + 15) + 'px';
|
||
}
|
||
});
|
||
});
|