gallery-test / index.html
Gabszap's picture
Add 1 files
0b52e0f verified
Raw
History Blame Contribute Delete
21.8 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Gallery</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.fade-in {
animation: fadeIn 0.5s ease-in-out;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.grid-view {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 20px;
}
.list-view .gallery-item {
display: flex;
flex-direction: row;
width: 100%;
max-width: 100%;
}
.list-view .gallery-item img {
width: 150px;
height: 100px;
object-fit: cover;
}
.list-view .gallery-item .item-info {
padding-left: 15px;
text-align: left;
}
.gallery-item {
transition: all 0.3s ease;
}
.gallery-item:hover {
transform: scale(1.02);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
}
.login-container {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
}
.gallery-container {
background: linear-gradient(to right, #fdfbfb, #ebedee);
}
/* Modal styles */
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.8);
z-index: 1000;
justify-content: center;
align-items: center;
}
.modal-content {
max-width: 90%;
max-height: 90%;
}
.modal-content img {
max-width: 100%;
max-height: 80vh;
object-fit: contain;
}
.close-modal {
position: absolute;
top: 20px;
right: 30px;
color: white;
font-size: 30px;
cursor: pointer;
}
/* Dark mode styles */
.dark .login-container {
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
}
.dark .gallery-container {
background: linear-gradient(to right, #0f0c29, #302b63);
}
.dark .bg-white {
background-color: #1e293b !important;
}
.dark .text-gray-800 {
color: #e2e8f0 !important;
}
.dark .text-gray-700 {
color: #cbd5e1 !important;
}
.dark .text-gray-600 {
color: #94a3b8 !important;
}
.dark .border-gray-300 {
border-color: #475569 !important;
}
.dark .gallery-item {
background-color: #1e293b !important;
color: #e2e8f0 !important;
}
.dark .text-gray-500 {
color: #94a3b8 !important;
}
.dark .bg-red-50 {
background-color: #7f1d1d !important;
color: #fecaca !important;
}
.dark .hover\:bg-gray-50:hover {
background-color: #334155 !important;
}
.dark .shadow-sm {
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.5) !important;
}
.dark .bg-indigo-600 {
background-color: #4338ca !important;
}
.dark .hover\:bg-indigo-700:hover {
background-color: #3730a3 !important;
}
</style>
</head>
<body class="bg-gray-100">
<!-- Login Section (shown by default) -->
<div id="loginSection" class="min-h-screen flex items-center justify-center p-4 login-container">
<div class="bg-white p-8 rounded-lg shadow-xl w-full max-w-md fade-in">
<div class="text-center mb-8">
<i class="fas fa-camera-retro text-5xl text-indigo-500 mb-4"></i>
<h1 class="text-3xl font-bold text-gray-800">Welcome to My Gallery</h1>
<p class="text-gray-600 mt-2">Please login to view your photos</p>
</div>
<form id="loginForm" class="space-y-6">
<div>
<label for="username" class="block text-sm font-medium text-gray-700 mb-1">Username</label>
<input type="text" id="username" required
class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500">
</div>
<div>
<label for="password" class="block text-sm font-medium text-gray-700 mb-1">Password</label>
<input type="password" id="password" required
class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500">
</div>
<div class="flex items-center justify-between">
<div class="flex items-center">
<input id="remember-me" type="checkbox"
class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 rounded">
<label for="remember-me" class="ml-2 block text-sm text-gray-700">Remember me</label>
</div>
<a href="#" class="text-sm text-indigo-600 hover:text-indigo-500">Forgot password?</a>
</div>
<button type="submit"
class="w-full bg-indigo-600 text-white py-2 px-4 rounded-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 transition duration-150 ease-in-out">
Sign in
</button>
</form>
<div class="mt-6 text-center">
<p class="text-sm text-gray-600">
Don't have an account?
<a href="#" class="font-medium text-indigo-600 hover:text-indigo-500">Sign up</a>
</p>
</div>
</div>
</div>
<!-- Gallery Section (hidden by default) -->
<div id="gallerySection" class="hidden min-h-screen p-6 gallery-container">
<div class="max-w-7xl mx-auto">
<!-- Header -->
<div class="flex flex-col md:flex-row md:items-center md:justify-between mb-8">
<div class="mb-4 md:mb-0">
<h1 class="text-3xl font-bold text-gray-800">My Gallery</h1>
<p class="text-gray-600">Your personal photo collection</p>
</div>
<div class="flex items-center space-x-4">
<button id="themeToggle" class="flex items-center space-x-2 bg-white px-4 py-2 rounded-md shadow-sm hover:bg-gray-50">
<i class="fas fa-moon"></i>
<span>Dark Mode</span>
</button>
<div class="relative">
<button id="viewToggle" class="flex items-center space-x-2 bg-white px-4 py-2 rounded-md shadow-sm hover:bg-gray-50">
<i class="fas fa-th"></i>
<span>Grid View</span>
</button>
</div>
<button id="logoutBtn" class="flex items-center space-x-2 bg-red-50 text-red-600 px-4 py-2 rounded-md shadow-sm hover:bg-red-100">
<i class="fas fa-sign-out-alt"></i>
<span>Logout</span>
</button>
</div>
</div>
<!-- Gallery Content -->
<div id="galleryContent" class="grid-view fade-in">
<!-- Sample images will be loaded here -->
</div>
</div>
</div>
<!-- Modal for viewing images -->
<div id="imageModal" class="modal">
<span class="close-modal">&times;</span>
<div class="modal-content">
<img id="modalImage" src="" alt="">
<div class="text-center mt-4 text-white">
<button id="downloadFromModal" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded">
<i class="fas fa-download mr-2"></i>Download
</button>
</div>
</div>
</div>
<script>
// Sample image data with real Unsplash images
const sampleImages = [
{ id: 1, title: "Mountain View", url: "https://images.unsplash.com/photo-1464822759023-fed622ff2c3b?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&h=400&q=80", date: "2023-05-15" },
{ id: 2, title: "Ocean Sunset", url: "https://images.unsplash.com/photo-1505118380757-91f5f5632de0?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&h=400&q=80", date: "2023-06-22" },
{ id: 3, title: "City Lights", url: "https://images.unsplash.com/photo-1477959858617-67f85cf4f1df?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&h=400&q=80", date: "2023-07-10" },
{ id: 4, title: "Forest Path", url: "https://images.unsplash.com/photo-1448375240586-882707db888b?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&h=400&q=80", date: "2023-04-05" },
{ id: 5, title: "Desert Landscape", url: "https://images.unsplash.com/photo-1509316785289-025f5b8b4db1?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&h=400&q=80", date: "2023-03-18" },
{ id: 6, title: "Autumn Colors", url: "https://images.unsplash.com/photo-1504208434309-cb69f4fe52b0?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&h=400&q=80", date: "2023-10-12" },
{ id: 7, title: "Winter Wonderland", url: "https://images.unsplash.com/photo-1483728642387-6c3bdd6c93e5?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&h=400&q=80", date: "2023-01-30" },
{ id: 8, title: "Spring Flowers", url: "https://images.unsplash.com/photo-1490750967868-88aa4486c946?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&h=400&q=80", date: "2023-05-02" },
{ id: 9, title: "Wildlife", url: "https://images.unsplash.com/photo-1470114716159-e389f8712fda?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&h=400&q=80", date: "2023-08-19" },
{ id: 10, title: "Architecture", url: "https://images.unsplash.com/photo-1487958449943-2429e8be8625?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&h=400&q=80", date: "2023-09-25" },
{ id: 11, title: "Beach Day", url: "https://images.unsplash.com/photo-1507525428034-b723cf961d3e?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto:format&fit=crop&w=600&h=400&q=80", date: "2023-07-28" },
{ id: 12, title: "Waterfall", url: "https://images.unsplash.com/photo-1511497584788-876760111969?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto:format&fit=crop&w=600&h=400&q=80", date: "2023-06-14" }
];
// DOM elements
const loginForm = document.getElementById('loginForm');
const loginSection = document.getElementById('loginSection');
const gallerySection = document.getElementById('gallerySection');
const galleryContent = document.getElementById('galleryContent');
const viewToggle = document.getElementById('viewToggle');
const themeToggle = document.getElementById('themeToggle');
const logoutBtn = document.getElementById('logoutBtn');
const modal = document.getElementById('imageModal');
const modalImage = document.getElementById('modalImage');
const closeModal = document.querySelector('.close-modal');
const downloadFromModal = document.getElementById('downloadFromModal');
// Current view mode (true for grid, false for list)
let isGridView = true;
// Current theme mode (false for light, true for dark)
let isDarkMode = false;
// Current image being viewed/downloaded
let currentImageUrl = '';
let currentImageTitle = '';
// Function to download an image
function downloadImage(imageUrl, imageTitle) {
fetch(imageUrl)
.then(response => response.blob())
.then(blob => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = imageTitle || 'image';
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
})
.catch(() => {
// Fallback method if fetch fails (CORS issues)
const a = document.createElement('a');
a.href = imageUrl;
a.download = imageTitle || 'image';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
});
}
// Function to view an image in modal
function viewImage(imageUrl, imageTitle) {
currentImageUrl = imageUrl;
currentImageTitle = imageTitle;
modalImage.src = imageUrl;
modalImage.alt = imageTitle;
modal.style.display = 'flex';
}
// Load gallery images
function loadGalleryImages() {
galleryContent.innerHTML = '';
sampleImages.forEach(image => {
const item = document.createElement('div');
item.className = 'gallery-item bg-white rounded-lg overflow-hidden shadow-md';
if (isGridView) {
item.innerHTML = `
<img src="${image.url}" alt="${image.title}" class="w-full h-48 object-cover cursor-pointer" onclick="viewImage('${image.url}', '${image.title}')">
<div class="p-4">
<h3 class="font-semibold text-lg mb-1">${image.title}</h3>
<p class="text-gray-500 text-sm">${image.date}</p>
<div class="mt-2 flex space-x-2">
<button onclick="viewImage('${image.url}', '${image.title}')" class="text-blue-500 hover:text-blue-700">
<i class="fas fa-eye"></i> View
</button>
<button onclick="downloadImage('${image.url}', '${image.title}')" class="text-green-500 hover:text-green-700">
<i class="fas fa-download"></i> Download
</button>
</div>
</div>
`;
} else {
item.innerHTML = `
<img src="${image.url}" alt="${image.title}" class="rounded-l-lg cursor-pointer" onclick="viewImage('${image.url}', '${image.title}')">
<div class="item-info p-4 flex-grow">
<h3 class="font-semibold text-lg mb-1">${image.title}</h3>
<p class="text-gray-500 text-sm mb-2">${image.date}</p>
<div class="flex space-x-2">
<button onclick="viewImage('${image.url}', '${image.title}')" class="text-blue-500 hover:text-blue-700">
<i class="fas fa-eye"></i> View
</button>
<button onclick="downloadImage('${image.url}', '${image.title}')" class="text-green-500 hover:text-green-700">
<i class="fas fa-download"></i> Download
</button>
<button class="text-red-500 hover:text-red-700">
<i class="fas fa-trash"></i> Delete
</button>
</div>
</div>
`;
}
galleryContent.appendChild(item);
});
}
// Toggle view mode
function toggleViewMode() {
isGridView = !isGridView;
if (isGridView) {
galleryContent.classList.remove('list-view');
galleryContent.classList.add('grid-view');
viewToggle.innerHTML = '<i class="fas fa-th"></i><span>Grid View</span>';
} else {
galleryContent.classList.remove('grid-view');
galleryContent.classList.add('list-view');
viewToggle.innerHTML = '<i class="fas fa-list"></i><span>List View</span>';
}
loadGalleryImages();
}
// Toggle theme mode
function toggleThemeMode() {
isDarkMode = !isDarkMode;
if (isDarkMode) {
document.documentElement.classList.add('dark');
themeToggle.innerHTML = '<i class="fas fa-sun"></i><span>Light Mode</span>';
// Store preference in localStorage
localStorage.setItem('darkMode', 'enabled');
} else {
document.documentElement.classList.remove('dark');
themeToggle.innerHTML = '<i class="fas fa-moon"></i><span>Dark Mode</span>';
// Store preference in localStorage
localStorage.setItem('darkMode', 'disabled');
}
}
// Check for saved theme preference
function checkThemePreference() {
const savedMode = localStorage.getItem('darkMode');
if (savedMode === 'enabled') {
isDarkMode = true;
document.documentElement.classList.add('dark');
themeToggle.innerHTML = '<i class="fas fa-sun"></i><span>Light Mode</span>';
}
}
// Event listeners
loginForm.addEventListener('submit', function(e) {
e.preventDefault();
const username = document.getElementById('username').value;
const password = document.getElementById('password').value;
// Simple validation (in a real app, you would check against a database)
if (username && password) {
// Hide login, show gallery
loginSection.classList.add('hidden');
gallerySection.classList.remove('hidden');
// Load gallery images
loadGalleryImages();
} else {
alert('Please enter both username and password');
}
});
viewToggle.addEventListener('click', toggleViewMode);
themeToggle.addEventListener('click', toggleThemeMode);
logoutBtn.addEventListener('click', function() {
// Hide gallery, show login
gallerySection.classList.add('hidden');
loginSection.classList.remove('hidden');
// Reset form
loginForm.reset();
});
// Modal events
closeModal.addEventListener('click', function() {
modal.style.display = 'none';
});
downloadFromModal.addEventListener('click', function() {
downloadImage(currentImageUrl, currentImageTitle);
});
// Close modal when clicking outside the image
window.addEventListener('click', function(event) {
if (event.target === modal) {
modal.style.display = 'none';
}
});
// Initialize theme preference
checkThemePreference();
// Make functions available globally for inline event handlers
window.viewImage = viewImage;
window.downloadImage = downloadImage;
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Gabszap/gallery-test" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>