fix: Photo gallery methods definition error

PROBLEM:
- Photo gallery button caused 'this.showPhotoGallery is not a function' error
- Methods were defined inside class but after closing brace
- JavaScript couldn't find the methods in correct scope

SOLUTION:
- Moved all photo gallery methods to proper prototype definitions
- Fixed method scope and accessibility issues
- Changed from class methods to TaskChallengeGame.prototype methods
- Consistent with existing codebase pattern (like showAnnoyanceManagement)

FIXED METHODS:
 showPhotoGallery - main entry point
 setupPhotoGalleryEventListeners - UI event binding
 loadPhotoGallery - data loading and display
 updatePhotoStats - statistics display
 renderPhotoGrid - photo grid rendering with filters/sorting
 createPhotoItem - individual photo item HTML generation
 formatSessionName - session type display formatting
 filterPhotos - photo filtering logic
 showPhotoDetail - photo detail modal
 closePhotoDetail - modal close functionality
 downloadCurrentPhoto - individual photo download
 deleteCurrentPhoto - photo deletion with confirmation
 downloadAllPhotos - batch download functionality
 clearAllPhotos - bulk deletion with confirmation
 showPhotoSettings - settings modal display
 closePhotoSettings - settings modal close
 savePhotoSettings - settings persistence

Photo gallery should now work correctly without JavaScript errors!
This commit is contained in:
dilgenfritz 2025-10-28 07:52:22 -05:00
parent 96c846cf8b
commit 5861c07bab
1 changed files with 257 additions and 257 deletions

View File

@ -6131,265 +6131,265 @@ class MusicManager {
// Set current selection
trackSelector.value = this.currentTrackIndex;
}
// Photo Gallery Management Methods
showPhotoGallery() {
this.showScreen('photo-gallery-screen');
this.setupPhotoGalleryEventListeners();
this.loadPhotoGallery();
}
setupPhotoGalleryEventListeners() {
// Back button
const backBtn = document.getElementById('back-to-start-from-photos-btn');
if (backBtn) {
backBtn.onclick = () => this.showScreen('start-screen');
}
// Action buttons
const downloadAllBtn = document.getElementById('download-all-photos-btn');
if (downloadAllBtn) {
downloadAllBtn.onclick = () => this.downloadAllPhotos();
}
const clearAllBtn = document.getElementById('clear-all-photos-btn');
if (clearAllBtn) {
clearAllBtn.onclick = () => this.clearAllPhotos();
}
const settingsBtn = document.getElementById('photo-storage-settings-btn');
if (settingsBtn) {
settingsBtn.onclick = () => this.showPhotoSettings();
}
// Filter controls
const sessionFilter = document.getElementById('photo-session-filter');
if (sessionFilter) {
sessionFilter.onchange = () => this.filterPhotos();
}
const sortOrder = document.getElementById('photo-sort-order');
if (sortOrder) {
sortOrder.onchange = () => this.filterPhotos();
}
// Modal close buttons
const closeDetailBtn = document.getElementById('close-photo-detail');
if (closeDetailBtn) {
closeDetailBtn.onclick = () => this.closePhotoDetail();
}
const closeSettingsBtn = document.getElementById('close-photo-settings');
if (closeSettingsBtn) {
closeSettingsBtn.onclick = () => this.closePhotoSettings();
}
// Photo detail modal actions
const downloadBtn = document.getElementById('download-photo-btn');
if (downloadBtn) {
downloadBtn.onclick = () => this.downloadCurrentPhoto();
}
const deleteBtn = document.getElementById('delete-photo-btn');
if (deleteBtn) {
deleteBtn.onclick = () => this.deleteCurrentPhoto();
}
// Settings modal actions
const saveSettingsBtn = document.getElementById('save-photo-settings-btn');
if (saveSettingsBtn) {
saveSettingsBtn.onclick = () => this.savePhotoSettings();
}
}
loadPhotoGallery() {
const stats = this.webcamManager.getPhotoStats();
this.updatePhotoStats(stats);
const photos = this.webcamManager.getSavedPhotos();
const grid = document.getElementById('photo-grid');
const noPhotosMsg = document.getElementById('no-photos-message');
if (photos.length === 0) {
grid.style.display = 'none';
noPhotosMsg.style.display = 'block';
return;
}
grid.style.display = 'grid';
noPhotosMsg.style.display = 'none';
this.renderPhotoGrid(photos);
}
updatePhotoStats(stats) {
const countDisplay = document.getElementById('photo-count-display');
const sizeDisplay = document.getElementById('storage-size-display');
if (countDisplay) {
countDisplay.textContent = `${stats.count} photos`;
}
if (sizeDisplay) {
const sizeInKB = (stats.totalSize / 1024).toFixed(1);
sizeDisplay.textContent = `${sizeInKB} KB used`;
}
}
renderPhotoGrid(photos) {
const grid = document.getElementById('photo-grid');
const sessionFilter = document.getElementById('photo-session-filter').value;
const sortOrder = document.getElementById('photo-sort-order').value;
// Filter photos
let filteredPhotos = photos;
if (sessionFilter !== 'all') {
filteredPhotos = photos.filter(photo => photo.sessionType === sessionFilter);
}
// Sort photos
switch (sortOrder) {
case 'newest':
filteredPhotos.sort((a, b) => b.timestamp - a.timestamp);
break;
case 'oldest':
filteredPhotos.sort((a, b) => a.timestamp - b.timestamp);
break;
case 'session':
filteredPhotos.sort((a, b) => a.sessionType.localeCompare(b.sessionType));
break;
}
// Render photo items
grid.innerHTML = filteredPhotos.map(photo => this.createPhotoItem(photo)).join('');
// Add click listeners
grid.querySelectorAll('.photo-item').forEach(item => {
const photoId = item.dataset.photoId;
item.onclick = () => this.showPhotoDetail(photoId);
});
}
createPhotoItem(photo) {
const date = new Date(photo.timestamp).toLocaleDateString();
const sessionName = this.formatSessionName(photo.sessionType);
return `
<div class="photo-item" data-photo-id="${photo.id}">
<img src="${photo.dataURL}" alt="Captured photo" loading="lazy">
<div class="photo-item-info">
<div class="photo-item-date">${date}</div>
<div class="photo-item-session">${sessionName}</div>
</div>
</div>
`;
}
formatSessionName(sessionType) {
const sessionNames = {
'dress-up-photo': 'Dress-up',
'photography-studio': 'Studio',
'custom': 'Custom'
};
return sessionNames[sessionType] || sessionType;
}
filterPhotos() {
const photos = this.webcamManager.getSavedPhotos();
this.renderPhotoGrid(photos);
}
showPhotoDetail(photoId) {
const photos = this.webcamManager.getSavedPhotos();
const photo = photos.find(p => p.id === photoId);
if (!photo) return;
this.currentDetailPhoto = photo;
// Populate modal
document.getElementById('photo-detail-image').src = photo.dataURL;
document.getElementById('photo-detail-date').textContent = new Date(photo.timestamp).toLocaleString();
document.getElementById('photo-detail-session').textContent = this.formatSessionName(photo.sessionType);
document.getElementById('photo-detail-task').textContent = photo.taskId || 'Unknown';
document.getElementById('photo-detail-size').textContent = `${Math.round(photo.size / 1024)} KB`;
// Show modal
document.getElementById('photo-detail-modal').style.display = 'flex';
}
closePhotoDetail() {
document.getElementById('photo-detail-modal').style.display = 'none';
this.currentDetailPhoto = null;
}
downloadCurrentPhoto() {
if (this.currentDetailPhoto) {
this.webcamManager.downloadPhoto(this.currentDetailPhoto);
}
}
deleteCurrentPhoto() {
if (!this.currentDetailPhoto) return;
if (confirm('Are you sure you want to delete this photo? This cannot be undone.')) {
const success = this.webcamManager.deletePhoto(this.currentDetailPhoto.id);
if (success) {
this.closePhotoDetail();
this.loadPhotoGallery(); // Refresh the gallery
this.webcamManager.showNotification('Photo deleted', 'success');
} else {
this.webcamManager.showNotification('Failed to delete photo', 'error');
}
}
}
downloadAllPhotos() {
this.webcamManager.downloadAllPhotos();
}
clearAllPhotos() {
if (confirm('Are you sure you want to delete ALL photos? This cannot be undone.')) {
const success = this.webcamManager.clearAllPhotos();
if (success) {
this.loadPhotoGallery(); // Refresh the gallery
this.webcamManager.showNotification('All photos cleared', 'success');
} else {
this.webcamManager.showNotification('Failed to clear photos', 'error');
}
}
}
showPhotoSettings() {
const stats = this.webcamManager.getPhotoStats();
// Update consent radio buttons
const consentValue = stats.storageConsent;
document.getElementById('consent-enable').checked = consentValue === 'true';
document.getElementById('consent-disable').checked = consentValue === 'false';
// Update stats
document.getElementById('settings-photo-count').textContent = stats.count;
document.getElementById('settings-storage-size').textContent = `${(stats.totalSize / 1024).toFixed(1)} KB`;
document.getElementById('settings-oldest-photo').textContent =
stats.oldestPhoto ? new Date(stats.oldestPhoto).toLocaleDateString() : 'None';
// Show modal
document.getElementById('photo-settings-modal').style.display = 'flex';
}
closePhotoSettings() {
document.getElementById('photo-settings-modal').style.display = 'none';
}
savePhotoSettings() {
const consentValue = document.querySelector('input[name="photo-consent"]:checked').value;
localStorage.setItem('photoStorageConsent', consentValue);
this.closePhotoSettings();
this.webcamManager.showNotification('Photo settings saved', 'success');
}
}
// Photo Gallery Management Methods
TaskChallengeGame.prototype.showPhotoGallery = function() {
this.showScreen('photo-gallery-screen');
this.setupPhotoGalleryEventListeners();
this.loadPhotoGallery();
};
TaskChallengeGame.prototype.setupPhotoGalleryEventListeners = function() {
// Back button
const backBtn = document.getElementById('back-to-start-from-photos-btn');
if (backBtn) {
backBtn.onclick = () => this.showScreen('start-screen');
}
// Action buttons
const downloadAllBtn = document.getElementById('download-all-photos-btn');
if (downloadAllBtn) {
downloadAllBtn.onclick = () => this.downloadAllPhotos();
}
const clearAllBtn = document.getElementById('clear-all-photos-btn');
if (clearAllBtn) {
clearAllBtn.onclick = () => this.clearAllPhotos();
}
const settingsBtn = document.getElementById('photo-storage-settings-btn');
if (settingsBtn) {
settingsBtn.onclick = () => this.showPhotoSettings();
}
// Filter controls
const sessionFilter = document.getElementById('photo-session-filter');
if (sessionFilter) {
sessionFilter.onchange = () => this.filterPhotos();
}
const sortOrder = document.getElementById('photo-sort-order');
if (sortOrder) {
sortOrder.onchange = () => this.filterPhotos();
}
// Modal close buttons
const closeDetailBtn = document.getElementById('close-photo-detail');
if (closeDetailBtn) {
closeDetailBtn.onclick = () => this.closePhotoDetail();
}
const closeSettingsBtn = document.getElementById('close-photo-settings');
if (closeSettingsBtn) {
closeSettingsBtn.onclick = () => this.closePhotoSettings();
}
// Photo detail modal actions
const downloadBtn = document.getElementById('download-photo-btn');
if (downloadBtn) {
downloadBtn.onclick = () => this.downloadCurrentPhoto();
}
const deleteBtn = document.getElementById('delete-photo-btn');
if (deleteBtn) {
deleteBtn.onclick = () => this.deleteCurrentPhoto();
}
// Settings modal actions
const saveSettingsBtn = document.getElementById('save-photo-settings-btn');
if (saveSettingsBtn) {
saveSettingsBtn.onclick = () => this.savePhotoSettings();
}
};
TaskChallengeGame.prototype.loadPhotoGallery = function() {
const stats = this.webcamManager.getPhotoStats();
this.updatePhotoStats(stats);
const photos = this.webcamManager.getSavedPhotos();
const grid = document.getElementById('photo-grid');
const noPhotosMsg = document.getElementById('no-photos-message');
if (photos.length === 0) {
grid.style.display = 'none';
noPhotosMsg.style.display = 'block';
return;
}
grid.style.display = 'grid';
noPhotosMsg.style.display = 'none';
this.renderPhotoGrid(photos);
};
TaskChallengeGame.prototype.updatePhotoStats = function(stats) {
const countDisplay = document.getElementById('photo-count-display');
const sizeDisplay = document.getElementById('storage-size-display');
if (countDisplay) {
countDisplay.textContent = `${stats.count} photos`;
}
if (sizeDisplay) {
const sizeInKB = (stats.totalSize / 1024).toFixed(1);
sizeDisplay.textContent = `${sizeInKB} KB used`;
}
};
TaskChallengeGame.prototype.renderPhotoGrid = function(photos) {
const grid = document.getElementById('photo-grid');
const sessionFilter = document.getElementById('photo-session-filter').value;
const sortOrder = document.getElementById('photo-sort-order').value;
// Filter photos
let filteredPhotos = photos;
if (sessionFilter !== 'all') {
filteredPhotos = photos.filter(photo => photo.sessionType === sessionFilter);
}
// Sort photos
switch (sortOrder) {
case 'newest':
filteredPhotos.sort((a, b) => b.timestamp - a.timestamp);
break;
case 'oldest':
filteredPhotos.sort((a, b) => a.timestamp - b.timestamp);
break;
case 'session':
filteredPhotos.sort((a, b) => a.sessionType.localeCompare(b.sessionType));
break;
}
// Render photo items
grid.innerHTML = filteredPhotos.map(photo => this.createPhotoItem(photo)).join('');
// Add click listeners
grid.querySelectorAll('.photo-item').forEach(item => {
const photoId = item.dataset.photoId;
item.onclick = () => this.showPhotoDetail(photoId);
});
};
TaskChallengeGame.prototype.createPhotoItem = function(photo) {
const date = new Date(photo.timestamp).toLocaleDateString();
const sessionName = this.formatSessionName(photo.sessionType);
return `
<div class="photo-item" data-photo-id="${photo.id}">
<img src="${photo.dataURL}" alt="Captured photo" loading="lazy">
<div class="photo-item-info">
<div class="photo-item-date">${date}</div>
<div class="photo-item-session">${sessionName}</div>
</div>
</div>
`;
};
TaskChallengeGame.prototype.formatSessionName = function(sessionType) {
const sessionNames = {
'dress-up-photo': 'Dress-up',
'photography-studio': 'Studio',
'custom': 'Custom'
};
return sessionNames[sessionType] || sessionType;
};
TaskChallengeGame.prototype.filterPhotos = function() {
const photos = this.webcamManager.getSavedPhotos();
this.renderPhotoGrid(photos);
};
TaskChallengeGame.prototype.showPhotoDetail = function(photoId) {
const photos = this.webcamManager.getSavedPhotos();
const photo = photos.find(p => p.id === photoId);
if (!photo) return;
this.currentDetailPhoto = photo;
// Populate modal
document.getElementById('photo-detail-image').src = photo.dataURL;
document.getElementById('photo-detail-date').textContent = new Date(photo.timestamp).toLocaleString();
document.getElementById('photo-detail-session').textContent = this.formatSessionName(photo.sessionType);
document.getElementById('photo-detail-task').textContent = photo.taskId || 'Unknown';
document.getElementById('photo-detail-size').textContent = `${Math.round(photo.size / 1024)} KB`;
// Show modal
document.getElementById('photo-detail-modal').style.display = 'flex';
};
TaskChallengeGame.prototype.closePhotoDetail = function() {
document.getElementById('photo-detail-modal').style.display = 'none';
this.currentDetailPhoto = null;
};
TaskChallengeGame.prototype.downloadCurrentPhoto = function() {
if (this.currentDetailPhoto) {
this.webcamManager.downloadPhoto(this.currentDetailPhoto);
}
};
TaskChallengeGame.prototype.deleteCurrentPhoto = function() {
if (!this.currentDetailPhoto) return;
if (confirm('Are you sure you want to delete this photo? This cannot be undone.')) {
const success = this.webcamManager.deletePhoto(this.currentDetailPhoto.id);
if (success) {
this.closePhotoDetail();
this.loadPhotoGallery(); // Refresh the gallery
this.webcamManager.showNotification('Photo deleted', 'success');
} else {
this.webcamManager.showNotification('Failed to delete photo', 'error');
}
}
};
TaskChallengeGame.prototype.downloadAllPhotos = function() {
this.webcamManager.downloadAllPhotos();
};
TaskChallengeGame.prototype.clearAllPhotos = function() {
if (confirm('Are you sure you want to delete ALL photos? This cannot be undone.')) {
const success = this.webcamManager.clearAllPhotos();
if (success) {
this.loadPhotoGallery(); // Refresh the gallery
this.webcamManager.showNotification('All photos cleared', 'success');
} else {
this.webcamManager.showNotification('Failed to clear photos', 'error');
}
}
};
TaskChallengeGame.prototype.showPhotoSettings = function() {
const stats = this.webcamManager.getPhotoStats();
// Update consent radio buttons
const consentValue = stats.storageConsent;
document.getElementById('consent-enable').checked = consentValue === 'true';
document.getElementById('consent-disable').checked = consentValue === 'false';
// Update stats
document.getElementById('settings-photo-count').textContent = stats.count;
document.getElementById('settings-storage-size').textContent = `${(stats.totalSize / 1024).toFixed(1)} KB`;
document.getElementById('settings-oldest-photo').textContent =
stats.oldestPhoto ? new Date(stats.oldestPhoto).toLocaleDateString() : 'None';
// Show modal
document.getElementById('photo-settings-modal').style.display = 'flex';
};
TaskChallengeGame.prototype.closePhotoSettings = function() {
document.getElementById('photo-settings-modal').style.display = 'none';
};
TaskChallengeGame.prototype.savePhotoSettings = function() {
const consentValue = document.querySelector('input[name="photo-consent"]:checked').value;
localStorage.setItem('photoStorageConsent', consentValue);
this.closePhotoSettings();
this.webcamManager.showNotification('Photo settings saved', 'success');
};
// Annoyance Management Methods - Phase 2: Advanced Message Management
TaskChallengeGame.prototype.showAnnoyanceManagement = function() {
this.showScreen('annoyance-management-screen');