Added galery

This commit is contained in:
2026-01-26 10:37:06 +01:00
parent d9b4c73baa
commit 33243fbe4a
31 changed files with 2508 additions and 229 deletions

View File

@@ -0,0 +1,51 @@
<div class="gallery-container">
<div class="gallery-header">
<a href="<?php echo Config::get('URL'); ?>gallery/view/<?php echo $this->image->id; ?>" class="gallery-back">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="19" y1="12" x2="5" y2="12"></line>
<polyline points="12 19 5 12 12 5"></polyline>
</svg>
Back to Image
</a>
</div>
<div class="gallery-form-container">
<h1>Edit Image</h1>
<div class="gallery-edit-preview">
<img src="<?php echo Config::get('URL'); ?>gallery/image/<?php echo $this->image->id; ?>/thumb"
alt="<?php echo htmlspecialchars($this->image->title); ?>">
</div>
<form method="post" action="<?php echo Config::get('URL'); ?>gallery/edit/<?php echo $this->image->id; ?>" class="gallery-form">
<div class="gallery-form-group">
<label class="gallery-form-label" for="title">Title</label>
<input type="text" name="title" id="title" class="gallery-form-input"
value="<?php echo htmlspecialchars($this->image->title); ?>" required>
</div>
<div class="gallery-form-group">
<label class="gallery-form-label" for="description">Description</label>
<textarea name="description" id="description" class="gallery-form-textarea" rows="4"><?php echo htmlspecialchars($this->image->description); ?></textarea>
</div>
<div class="gallery-form-group">
<label class="gallery-form-checkbox">
<input type="checkbox" name="is_public" value="1" <?php echo $this->image->is_public ? 'checked' : ''; ?>>
<span>Make this image public</span>
</label>
<small class="gallery-form-hint">Public images are visible to everyone in the gallery</small>
</div>
<div class="gallery-form-actions">
<button type="submit" name="submit_edit" class="gallery-btn gallery-btn-primary">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="20 6 9 17 4 12"></polyline>
</svg>
Save Changes
</button>
<a href="<?php echo Config::get('URL'); ?>gallery/view/<?php echo $this->image->id; ?>" class="gallery-btn gallery-btn-secondary">Cancel</a>
</div>
</form>
</div>
</div>

View File

@@ -0,0 +1,59 @@
<div class="gallery-container">
<div class="gallery-header">
<h1>Gallery</h1>
<div class="gallery-actions">
<?php if (Session::userIsLoggedIn()): ?>
<a href="<?php echo Config::get('URL'); ?>gallery/my" class="gallery-btn gallery-btn-secondary">My Images</a>
<a href="<?php echo Config::get('URL'); ?>gallery/upload" class="gallery-btn gallery-btn-primary">Upload Image</a>
<?php endif; ?>
</div>
</div>
<?php if (empty($this->images)): ?>
<div class="gallery-empty">
<div class="gallery-empty-icon">
<svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
<circle cx="8.5" cy="8.5" r="1.5"></circle>
<polyline points="21 15 16 10 5 21"></polyline>
</svg>
</div>
<h3>No images yet</h3>
<p>Be the first to share an image!</p>
<?php if (Session::userIsLoggedIn()): ?>
<a href="<?php echo Config::get('URL'); ?>gallery/upload" class="gallery-btn gallery-btn-primary" style="margin-top: 16px;">Upload Image</a>
<?php endif; ?>
</div>
<?php else: ?>
<div class="gallery-grid">
<?php foreach ($this->images as $image): ?>
<a href="<?php echo Config::get('URL'); ?>gallery/view/<?php echo $image->id; ?>" class="gallery-item">
<img src="<?php echo Config::get('URL'); ?>gallery/image/<?php echo $image->id; ?>/thumb"
alt="<?php echo htmlspecialchars($image->title); ?>"
loading="lazy">
<div class="gallery-item-overlay">
<span class="gallery-item-title"><?php echo htmlspecialchars($image->title); ?></span>
<span class="gallery-item-author">by <?php echo htmlspecialchars($image->user_name); ?></span>
</div>
</a>
<?php endforeach; ?>
</div>
<?php
$total_pages = ceil($this->total_images / $this->per_page);
if ($total_pages > 1):
?>
<div class="gallery-pagination">
<?php if ($this->current_page > 1): ?>
<a href="<?php echo Config::get('URL'); ?>gallery/index/<?php echo $this->current_page - 1; ?>" class="gallery-btn gallery-btn-secondary">Previous</a>
<?php endif; ?>
<span class="gallery-pagination-info">Page <?php echo $this->current_page; ?> of <?php echo $total_pages; ?></span>
<?php if ($this->current_page < $total_pages): ?>
<a href="<?php echo Config::get('URL'); ?>gallery/index/<?php echo $this->current_page + 1; ?>" class="gallery-btn gallery-btn-secondary">Next</a>
<?php endif; ?>
</div>
<?php endif; ?>
<?php endif; ?>
</div>

View File

@@ -0,0 +1,76 @@
<div class="gallery-container">
<div class="gallery-header">
<h1>My Images</h1>
<div class="gallery-actions">
<a href="<?php echo Config::get('URL'); ?>gallery/index" class="gallery-btn gallery-btn-secondary">Public Gallery</a>
<a href="<?php echo Config::get('URL'); ?>gallery/upload" class="gallery-btn gallery-btn-primary">Upload Image</a>
</div>
</div>
<?php if (empty($this->images)): ?>
<div class="gallery-empty">
<div class="gallery-empty-icon">
<svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
<circle cx="8.5" cy="8.5" r="1.5"></circle>
<polyline points="21 15 16 10 5 21"></polyline>
</svg>
</div>
<h3>No images uploaded</h3>
<p>Upload your first image to get started.</p>
<a href="<?php echo Config::get('URL'); ?>gallery/upload" class="gallery-btn gallery-btn-primary" style="margin-top: 16px;">Upload Image</a>
</div>
<?php else: ?>
<div class="gallery-grid">
<?php foreach ($this->images as $image): ?>
<div class="gallery-item gallery-item-owned">
<a href="<?php echo Config::get('URL'); ?>gallery/view/<?php echo $image->id; ?>">
<img src="<?php echo Config::get('URL'); ?>gallery/image/<?php echo $image->id; ?>/thumb"
alt="<?php echo htmlspecialchars($image->title); ?>"
loading="lazy">
</a>
<div class="gallery-item-overlay">
<span class="gallery-item-title"><?php echo htmlspecialchars($image->title); ?></span>
<span class="gallery-item-visibility <?php echo $image->is_public ? 'public' : 'private'; ?>">
<?php echo $image->is_public ? 'Public' : 'Private'; ?>
</span>
</div>
<div class="gallery-item-actions">
<a href="<?php echo Config::get('URL'); ?>gallery/edit/<?php echo $image->id; ?>" class="gallery-btn-icon" title="Edit">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path>
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path>
</svg>
</a>
<a href="<?php echo Config::get('URL'); ?>gallery/delete/<?php echo $image->id; ?>"
class="gallery-btn-icon gallery-btn-danger"
title="Delete"
onclick="return confirm('Delete this image?');">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="3 6 5 6 21 6"></polyline>
<path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
</svg>
</a>
</div>
</div>
<?php endforeach; ?>
</div>
<?php
$total_pages = ceil($this->total_images / $this->per_page);
if ($total_pages > 1):
?>
<div class="gallery-pagination">
<?php if ($this->current_page > 1): ?>
<a href="<?php echo Config::get('URL'); ?>gallery/my/<?php echo $this->current_page - 1; ?>" class="gallery-btn gallery-btn-secondary">Previous</a>
<?php endif; ?>
<span class="gallery-pagination-info">Page <?php echo $this->current_page; ?> of <?php echo $total_pages; ?></span>
<?php if ($this->current_page < $total_pages): ?>
<a href="<?php echo Config::get('URL'); ?>gallery/my/<?php echo $this->current_page + 1; ?>" class="gallery-btn gallery-btn-secondary">Next</a>
<?php endif; ?>
</div>
<?php endif; ?>
<?php endif; ?>
</div>

View File

@@ -0,0 +1,168 @@
<div class="gallery-success-overlay">
<div class="gallery-success-card">
<div class="gallery-success-icon">
<svg class="checkmark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52">
<circle class="checkmark-circle" cx="26" cy="26" r="25" fill="none"/>
<path class="checkmark-check" fill="none" d="M14.1 27.2l7.1 7.2 16.7-16.8"/>
</svg>
</div>
<h2>Upload Successful!</h2>
<p>Your image has been uploaded successfully.</p>
<div class="gallery-success-preview">
<img src="<?php echo Config::get('URL'); ?>gallery/image/<?php echo $this->image->id; ?>/thumb"
alt="<?php echo htmlspecialchars($this->image->title); ?>">
</div>
<p class="gallery-success-title"><?php echo htmlspecialchars($this->image->title); ?></p>
<p class="gallery-success-redirect">Redirecting to your image<span class="dots"></span></p>
</div>
</div>
<style>
.gallery-success-overlay {
position: fixed;
inset: 0;
background: rgba(255, 255, 255, 0.98);
display: flex;
align-items: center;
justify-content: center;
z-index: 9999;
animation: fadeIn 0.3s ease;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.gallery-success-card {
text-align: center;
padding: 40px;
max-width: 400px;
animation: slideUp 0.4s ease 0.1s both;
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.gallery-success-icon {
margin-bottom: 24px;
}
.checkmark {
width: 80px;
height: 80px;
border-radius: 50%;
display: block;
stroke-width: 2;
stroke: #4CAF50;
stroke-miterlimit: 10;
margin: 0 auto;
box-shadow: inset 0px 0px 0px #4CAF50;
animation: fill 0.4s ease-in-out 0.4s forwards, scale 0.3s ease-in-out 0.9s both;
}
.checkmark-circle {
stroke-dasharray: 166;
stroke-dashoffset: 166;
stroke-width: 2;
stroke-miterlimit: 10;
stroke: #4CAF50;
fill: none;
animation: stroke 0.6s cubic-bezier(0.65, 0, 0.45, 1) forwards;
}
.checkmark-check {
transform-origin: 50% 50%;
stroke-dasharray: 48;
stroke-dashoffset: 48;
animation: stroke 0.3s cubic-bezier(0.65, 0, 0.45, 1) 0.8s forwards;
}
@keyframes stroke {
100% { stroke-dashoffset: 0; }
}
@keyframes scale {
0%, 100% { transform: none; }
50% { transform: scale3d(1.1, 1.1, 1); }
}
@keyframes fill {
100% { box-shadow: inset 0px 0px 0px 40px rgba(76, 175, 80, 0.1); }
}
.gallery-success-card h2 {
margin: 0 0 8px;
font-size: 28px;
font-weight: 600;
color: #333;
}
.gallery-success-card p {
margin: 0;
color: #666;
font-size: 16px;
}
.gallery-success-preview {
margin: 24px 0 16px;
animation: previewFade 0.5s ease 0.6s both;
}
@keyframes previewFade {
from { opacity: 0; transform: scale(0.9); }
to { opacity: 1; transform: scale(1); }
}
.gallery-success-preview img {
max-width: 200px;
max-height: 200px;
border-radius: 12px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
object-fit: cover;
}
.gallery-success-title {
font-weight: 500;
color: #333;
margin-bottom: 24px !important;
}
.gallery-success-redirect {
font-size: 14px !important;
color: #999 !important;
animation: pulse 1.5s ease infinite;
}
@keyframes pulse {
0%, 100% { opacity: 0.6; }
50% { opacity: 1; }
}
.dots::after {
content: '';
animation: dots 1.5s steps(4, end) infinite;
}
@keyframes dots {
0% { content: ''; }
25% { content: '.'; }
50% { content: '..'; }
75% { content: '...'; }
100% { content: ''; }
}
</style>
<script>
setTimeout(function() {
window.location.href = '<?php echo Config::get('URL'); ?>gallery/view/<?php echo $this->image->id; ?>';
}, 2500);
</script>

View File

@@ -0,0 +1,437 @@
<div class="gallery-container">
<div class="gallery-header">
<a href="<?php echo Config::get('URL'); ?>gallery/my" class="gallery-back">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="19" y1="12" x2="5" y2="12"></line>
<polyline points="12 19 5 12 12 5"></polyline>
</svg>
Back to My Images
</a>
</div>
<div class="gallery-form-container">
<h1>Upload Image</h1>
<?php $this->renderFeedbackMessages(); ?>
<form id="upload-form" method="post" action="<?php echo Config::get('URL'); ?>gallery/upload" enctype="multipart/form-data" class="gallery-form">
<div class="gallery-form-group">
<label class="gallery-form-label">Image File</label>
<div class="gallery-upload-zone" id="upload-zone">
<input type="file" name="image" id="image-input" accept="image/jpeg,image/png,image/gif,image/webp" required>
<div class="gallery-upload-placeholder">
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
<polyline points="17 8 12 3 7 8"></polyline>
<line x1="12" y1="3" x2="12" y2="15"></line>
</svg>
<span>Click or drag image here</span>
<small>JPG, PNG, GIF, WebP - Max 10MB</small>
</div>
<div class="gallery-upload-preview" id="upload-preview" style="display: none;">
<img id="preview-image" src="" alt="Preview">
<button type="button" class="gallery-upload-remove" id="remove-preview">&times;</button>
</div>
</div>
</div>
<div class="gallery-form-group">
<label class="gallery-form-label" for="title">Title</label>
<input type="text" name="title" id="title" class="gallery-form-input" placeholder="Give your image a title">
</div>
<div class="gallery-form-group">
<label class="gallery-form-label" for="description">Description</label>
<textarea name="description" id="description" class="gallery-form-textarea" rows="4" placeholder="Add a description (optional)"></textarea>
</div>
<div class="gallery-form-group">
<label class="gallery-form-checkbox">
<input type="checkbox" name="is_public" value="1" checked>
<span>Make this image public</span>
</label>
<small class="gallery-form-hint">Public images are visible to everyone in the gallery</small>
</div>
<div class="gallery-form-actions">
<button type="submit" name="submit_upload" class="gallery-btn gallery-btn-primary">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
<polyline points="17 8 12 3 7 8"></polyline>
<line x1="12" y1="3" x2="12" y2="15"></line>
</svg>
Upload Image
</button>
<a href="<?php echo Config::get('URL'); ?>gallery/my" class="gallery-btn gallery-btn-secondary">Cancel</a>
</div>
</form>
</div>
</div>
<!-- Upload Progress Overlay -->
<div id="upload-overlay" class="upload-overlay" style="display: none;">
<div class="upload-modal">
<!-- Progress State -->
<div id="upload-progress-state" class="upload-state">
<div class="upload-icon uploading">
<svg class="upload-spinner" viewBox="0 0 50 50">
<circle cx="25" cy="25" r="20" fill="none" stroke-width="4"></circle>
</svg>
</div>
<h2>Uploading...</h2>
<div class="upload-progress-bar">
<div class="upload-progress-fill" id="progress-fill"></div>
</div>
<p class="upload-progress-text"><span id="progress-percent">0</span>%</p>
</div>
<!-- Success State -->
<div id="upload-success-state" class="upload-state" style="display: none;">
<div class="upload-icon success">
<svg class="checkmark" viewBox="0 0 52 52">
<circle class="checkmark-circle" cx="26" cy="26" r="25" fill="none"/>
<path class="checkmark-check" fill="none" d="M14.1 27.2l7.1 7.2 16.7-16.8"/>
</svg>
</div>
<h2>Upload Complete!</h2>
<p>Your image has been uploaded successfully.</p>
<p class="upload-redirect">Redirecting<span class="dots"></span></p>
</div>
<!-- Error State -->
<div id="upload-error-state" class="upload-state" style="display: none;">
<div class="upload-icon error">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="10"></circle>
<line x1="15" y1="9" x2="9" y2="15"></line>
<line x1="9" y1="9" x2="15" y2="15"></line>
</svg>
</div>
<h2>Upload Failed</h2>
<p id="error-message">Something went wrong. Please try again.</p>
<button type="button" class="gallery-btn gallery-btn-primary" onclick="hideOverlay()">Try Again</button>
</div>
</div>
</div>
<style>
.upload-overlay {
position: fixed;
inset: 0;
background: rgba(255, 255, 255, 0.95);
display: flex;
align-items: center;
justify-content: center;
z-index: 9999;
animation: fadeIn 0.3s ease;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.upload-modal {
text-align: center;
padding: 40px;
max-width: 400px;
}
.upload-state {
animation: slideUp 0.4s ease;
}
@keyframes slideUp {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.upload-icon {
width: 80px;
height: 80px;
margin: 0 auto 24px;
}
.upload-icon svg {
width: 100%;
height: 100%;
}
.upload-icon.uploading svg {
stroke: #333;
}
.upload-icon.success svg {
stroke: #4CAF50;
}
.upload-icon.error svg {
stroke: #dc3545;
}
.upload-spinner {
animation: rotate 1.5s linear infinite;
}
.upload-spinner circle {
stroke: #333;
stroke-linecap: round;
stroke-dasharray: 90, 150;
stroke-dashoffset: 0;
animation: dash 1.5s ease-in-out infinite;
}
@keyframes rotate {
100% { transform: rotate(360deg); }
}
@keyframes dash {
0% { stroke-dasharray: 1, 150; stroke-dashoffset: 0; }
50% { stroke-dasharray: 90, 150; stroke-dashoffset: -35; }
100% { stroke-dasharray: 90, 150; stroke-dashoffset: -124; }
}
.upload-modal h2 {
margin: 0 0 16px;
font-size: 24px;
font-weight: 600;
color: #333;
}
.upload-modal p {
margin: 0;
color: #666;
font-size: 14px;
}
.upload-progress-bar {
width: 100%;
height: 8px;
background: #e0e0e0;
border-radius: 4px;
overflow: hidden;
margin: 20px 0 12px;
}
.upload-progress-fill {
height: 100%;
background: linear-gradient(90deg, #333, #555);
border-radius: 4px;
width: 0%;
transition: width 0.3s ease;
}
.upload-progress-text {
font-family: monospace;
font-size: 16px !important;
font-weight: 600;
color: #333 !important;
}
/* Checkmark Animation */
.checkmark {
width: 80px;
height: 80px;
border-radius: 50%;
display: block;
stroke-width: 2;
stroke: #4CAF50;
stroke-miterlimit: 10;
box-shadow: inset 0px 0px 0px #4CAF50;
animation: fill 0.4s ease-in-out 0.4s forwards, scale 0.3s ease-in-out 0.9s both;
}
.checkmark-circle {
stroke-dasharray: 166;
stroke-dashoffset: 166;
stroke-width: 2;
stroke-miterlimit: 10;
stroke: #4CAF50;
fill: none;
animation: stroke 0.6s cubic-bezier(0.65, 0, 0.45, 1) forwards;
}
.checkmark-check {
transform-origin: 50% 50%;
stroke-dasharray: 48;
stroke-dashoffset: 48;
animation: stroke 0.3s cubic-bezier(0.65, 0, 0.45, 1) 0.8s forwards;
}
@keyframes stroke {
100% { stroke-dashoffset: 0; }
}
@keyframes scale {
0%, 100% { transform: none; }
50% { transform: scale3d(1.1, 1.1, 1); }
}
@keyframes fill {
100% { box-shadow: inset 0px 0px 0px 40px rgba(76, 175, 80, 0.1); }
}
.upload-redirect {
margin-top: 20px !important;
font-size: 13px !important;
color: #999 !important;
animation: pulse 1.5s ease infinite;
}
@keyframes pulse {
0%, 100% { opacity: 0.6; }
50% { opacity: 1; }
}
.dots::after {
content: '';
animation: dots 1.5s steps(4, end) infinite;
}
@keyframes dots {
0% { content: ''; }
25% { content: '.'; }
50% { content: '..'; }
75% { content: '...'; }
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function() {
const form = document.getElementById('upload-form');
const uploadZone = document.getElementById('upload-zone');
const imageInput = document.getElementById('image-input');
const uploadPreview = document.getElementById('upload-preview');
const previewImage = document.getElementById('preview-image');
const removePreview = document.getElementById('remove-preview');
const placeholder = uploadZone.querySelector('.gallery-upload-placeholder');
const overlay = document.getElementById('upload-overlay');
const progressState = document.getElementById('upload-progress-state');
const successState = document.getElementById('upload-success-state');
const errorState = document.getElementById('upload-error-state');
const progressFill = document.getElementById('progress-fill');
const progressPercent = document.getElementById('progress-percent');
const errorMessage = document.getElementById('error-message');
// Image preview
imageInput.addEventListener('change', function(e) {
if (this.files && this.files[0]) {
const reader = new FileReader();
reader.onload = function(e) {
previewImage.src = e.target.result;
placeholder.style.display = 'none';
uploadPreview.style.display = 'block';
};
reader.readAsDataURL(this.files[0]);
}
});
removePreview.addEventListener('click', function() {
imageInput.value = '';
previewImage.src = '';
placeholder.style.display = 'flex';
uploadPreview.style.display = 'none';
});
// Drag and drop
uploadZone.addEventListener('dragover', function(e) {
e.preventDefault();
this.classList.add('dragover');
});
uploadZone.addEventListener('dragleave', function(e) {
e.preventDefault();
this.classList.remove('dragover');
});
uploadZone.addEventListener('drop', function(e) {
e.preventDefault();
this.classList.remove('dragover');
if (e.dataTransfer.files && e.dataTransfer.files[0]) {
imageInput.files = e.dataTransfer.files;
imageInput.dispatchEvent(new Event('change'));
}
});
// Form submission with AJAX
form.addEventListener('submit', function(e) {
e.preventDefault();
if (!imageInput.files || !imageInput.files[0]) {
alert('Please select an image to upload');
return;
}
const formData = new FormData(form);
formData.append('submit_upload', '1');
// Show overlay with progress state
showOverlay('progress');
const xhr = new XMLHttpRequest();
// Progress tracking
xhr.upload.addEventListener('progress', function(e) {
if (e.lengthComputable) {
const percent = Math.round((e.loaded / e.total) * 100);
progressFill.style.width = percent + '%';
progressPercent.textContent = percent;
}
});
xhr.addEventListener('load', function() {
if (xhr.status === 200) {
try {
const response = JSON.parse(xhr.responseText);
if (response.success) {
showOverlay('success');
// Redirect after animation
setTimeout(function() {
window.location.href = '<?php echo Config::get('URL'); ?>gallery/view/' + response.image_id;
}, 2000);
} else {
showOverlay('error', response.message || 'Upload failed');
}
} catch (e) {
showOverlay('error', 'Invalid server response');
}
} else {
showOverlay('error', 'Server error: ' + xhr.status);
}
});
xhr.addEventListener('error', function() {
showOverlay('error', 'Network error. Please check your connection.');
});
xhr.open('POST', form.action);
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.send(formData);
});
function showOverlay(state, message) {
overlay.style.display = 'flex';
progressState.style.display = 'none';
successState.style.display = 'none';
errorState.style.display = 'none';
if (state === 'progress') {
progressState.style.display = 'block';
progressFill.style.width = '0%';
progressPercent.textContent = '0';
} else if (state === 'success') {
successState.style.display = 'block';
} else if (state === 'error') {
errorState.style.display = 'block';
if (message) {
errorMessage.textContent = message;
}
}
}
window.hideOverlay = function() {
overlay.style.display = 'none';
};
});
</script>

View File

@@ -0,0 +1,80 @@
<div class="gallery-container">
<div class="gallery-header">
<a href="<?php echo Config::get('URL'); ?>gallery/index" class="gallery-back">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="19" y1="12" x2="5" y2="12"></line>
<polyline points="12 19 5 12 12 5"></polyline>
</svg>
Back to Gallery
</a>
</div>
<div class="gallery-view">
<div class="gallery-view-image">
<img src="<?php echo Config::get('URL'); ?>gallery/image/<?php echo $this->image->id; ?>/full"
alt="<?php echo htmlspecialchars($this->image->title); ?>">
</div>
<div class="gallery-view-info">
<h1><?php echo htmlspecialchars($this->image->title); ?></h1>
<div class="gallery-view-meta">
<div class="gallery-view-author">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
<circle cx="12" cy="7" r="4"></circle>
</svg>
<a href="<?php echo Config::get('URL'); ?>profile/showProfile/<?php echo $this->image->user_name; ?>">
<?php echo htmlspecialchars($this->image->user_name); ?>
</a>
</div>
<div class="gallery-view-date">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect>
<line x1="16" y1="2" x2="16" y2="6"></line>
<line x1="8" y1="2" x2="8" y2="6"></line>
<line x1="3" y1="10" x2="21" y2="10"></line>
</svg>
<?php echo date('M j, Y', strtotime($this->image->created_at)); ?>
</div>
<div class="gallery-view-size">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
<polyline points="7 10 12 15 17 10"></polyline>
<line x1="12" y1="15" x2="12" y2="3"></line>
</svg>
<?php echo GalleryModel::formatFileSize($this->image->file_size); ?>
</div>
</div>
<?php if ($this->image->description): ?>
<div class="gallery-view-description">
<?php echo nl2br(htmlspecialchars($this->image->description)); ?>
</div>
<?php endif; ?>
<?php if ($this->image->user_id == Session::get('user_id')): ?>
<div class="gallery-view-actions">
<a href="<?php echo Config::get('URL'); ?>gallery/edit/<?php echo $this->image->id; ?>" class="gallery-btn gallery-btn-secondary">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path>
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path>
</svg>
Edit
</a>
<a href="<?php echo Config::get('URL'); ?>gallery/delete/<?php echo $this->image->id; ?>"
class="gallery-btn gallery-btn-danger"
onclick="return confirm('Delete this image permanently?');">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="3 6 5 6 21 6"></polyline>
<path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
</svg>
Delete
</a>
</div>
<?php endif; ?>
</div>
</div>
</div>