flashes / index.html
Fate17's picture
Add 2 files
d46c2a0 verified
Raw
History Blame Contribute Delete
19.9 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Artistry Gallery | Your Personal Digital Art Space</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>
.gallery-item {
transition: all 0.3s ease;
transform: scale(1);
}
.gallery-item:hover {
transform: scale(1.03);
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
z-index: 10;
}
.modal-overlay {
background-color: rgba(0, 0, 0, 0.9);
}
.modal-content {
animation: fadeIn 0.3s ease-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: scale(0.9); }
to { opacity: 1; transform: scale(1); }
}
.upload-area {
border: 2px dashed #cbd5e0;
transition: all 0.3s ease;
}
.upload-area:hover {
border-color: #667eea;
background-color: rgba(102, 126, 234, 0.05);
}
.upload-area.dragover {
border-color: #667eea;
background-color: rgba(102, 126, 234, 0.1);
}
.category-btn.active {
background-color: #667eea;
color: white;
}
</style>
</head>
<body class="bg-gray-50 font-sans">
<!-- Navigation -->
<nav class="bg-white shadow-lg">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between h-16">
<div class="flex items-center">
<div class="flex-shrink-0 flex items-center">
<i class="fas fa-palette text-indigo-600 text-2xl mr-2"></i>
<span class="text-xl font-bold text-gray-900">Artistry Gallery</span>
</div>
</div>
<div class="flex items-center">
<button id="uploadBtn" class="bg-indigo-600 text-white px-4 py-2 rounded-md hover:bg-indigo-700 transition flex items-center">
<i class="fas fa-upload mr-2"></i> Upload Art
</button>
</div>
</div>
</div>
</nav>
<!-- Main Content -->
<main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<!-- Gallery Controls -->
<div class="flex flex-col sm:flex-row justify-between items-start sm:items-center mb-8">
<h1 class="text-3xl font-bold text-gray-900 mb-4 sm:mb-0">Your Personal Art Collection</h1>
<div class="flex space-x-2 overflow-x-auto pb-2 w-full sm:w-auto">
<button class="category-btn active px-4 py-2 rounded-full bg-indigo-600 text-white text-sm" data-category="all">All</button>
<button class="category-btn px-4 py-2 rounded-full bg-gray-200 text-gray-700 hover:bg-gray-300 text-sm" data-category="painting">Paintings</button>
<button class="category-btn px-4 py-2 rounded-full bg-gray-200 text-gray-700 hover:bg-gray-300 text-sm" data-category="photography">Photography</button>
<button class="category-btn px-4 py-2 rounded-full bg-gray-200 text-gray-700 hover:bg-gray-300 text-sm" data-category="digital">Digital Art</button>
<button class="category-btn px-4 py-2 rounded-full bg-gray-200 text-gray-700 hover:bg-gray-300 text-sm" data-category="sketch">Sketches</button>
</div>
</div>
<!-- Gallery Grid -->
<div id="galleryGrid" class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
<!-- Gallery items will be added here dynamically -->
<div class="text-center py-12 text-gray-500" id="emptyState">
<i class="fas fa-images text-4xl mb-4 text-gray-300"></i>
<p class="text-lg">Your gallery is empty</p>
<p class="text-sm mt-2">Upload your first artwork to get started</p>
</div>
</div>
</main>
<!-- Upload Modal -->
<div id="uploadModal" class="fixed inset-0 z-50 hidden">
<div class="modal-overlay absolute inset-0"></div>
<div class="flex items-center justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="modal-content inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start">
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left w-full">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg leading-6 font-medium text-gray-900">Upload Artwork</h3>
<button id="closeModal" class="text-gray-400 hover:text-gray-500">
<i class="fas fa-times"></i>
</button>
</div>
<div class="mt-2">
<div id="uploadArea" class="upload-area rounded-lg p-8 text-center cursor-pointer mb-4">
<i class="fas fa-cloud-upload-alt text-4xl text-indigo-500 mb-3"></i>
<p class="text-gray-600">Drag & drop your artwork here</p>
<p class="text-gray-400 text-sm mt-1">or click to browse files</p>
<input type="file" id="fileInput" class="hidden" accept="image/*" multiple>
</div>
<div class="mb-4">
<label for="artTitle" class="block text-sm font-medium text-gray-700 mb-1">Title</label>
<input type="text" id="artTitle" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500">
</div>
<div class="mb-4">
<label for="artCategory" class="block text-sm font-medium text-gray-700 mb-1">Category</label>
<select id="artCategory" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500">
<option value="painting">Painting</option>
<option value="photography">Photography</option>
<option value="digital">Digital Art</option>
<option value="sketch">Sketch</option>
<option value="other">Other</option>
</select>
</div>
<div class="mb-4">
<label for="artDescription" class="block text-sm font-medium text-gray-700 mb-1">Description (optional)</label>
<textarea id="artDescription" rows="3" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500"></textarea>
</div>
</div>
</div>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button id="submitUpload" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-indigo-600 text-base font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:ml-3 sm:w-auto sm:text-sm">
Upload Artwork
</button>
<button id="cancelUpload" class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
Cancel
</button>
</div>
</div>
</div>
</div>
<!-- Image Viewer Modal -->
<div id="imageViewer" class="fixed inset-0 z-50 hidden">
<div class="modal-overlay absolute inset-0"></div>
<div class="flex items-center justify-center min-h-screen">
<div class="relative max-w-4xl w-full mx-4">
<button id="closeViewer" class="absolute top-4 right-4 text-white text-3xl z-10 hover:text-gray-300">
<i class="fas fa-times"></i>
</button>
<button id="prevImage" class="absolute left-4 top-1/2 transform -translate-y-1/2 text-white text-3xl z-10 hover:text-gray-300">
<i class="fas fa-chevron-left"></i>
</button>
<button id="nextImage" class="absolute right-4 top-1/2 transform -translate-y-1/2 text-white text-3xl z-10 hover:text-gray-300">
<i class="fas fa-chevron-right"></i>
</button>
<div class="bg-white rounded-lg overflow-hidden">
<img id="viewerImage" src="" alt="" class="w-full max-h-screen-80 object-contain">
<div class="p-4 bg-white">
<h3 id="viewerTitle" class="text-xl font-bold text-gray-900"></h3>
<div class="flex items-center mt-1 mb-2">
<span id="viewerCategory" class="px-2 py-1 text-xs rounded-full bg-indigo-100 text-indigo-800"></span>
<span class="text-gray-500 text-sm ml-auto" id="viewerDate"></span>
</div>
<p id="viewerDescription" class="text-gray-700 mt-2"></p>
</div>
</div>
</div>
</div>
</div>
<script>
// Gallery data
let galleryData = JSON.parse(localStorage.getItem('artGallery')) || [];
let currentCategory = 'all';
let currentViewerIndex = 0;
// DOM Elements
const uploadBtn = document.getElementById('uploadBtn');
const uploadModal = document.getElementById('uploadModal');
const closeModal = document.getElementById('closeModal');
const cancelUpload = document.getElementById('cancelUpload');
const uploadArea = document.getElementById('uploadArea');
const fileInput = document.getElementById('fileInput');
const submitUpload = document.getElementById('submitUpload');
const galleryGrid = document.getElementById('galleryGrid');
const emptyState = document.getElementById('emptyState');
const categoryBtns = document.querySelectorAll('.category-btn');
const imageViewer = document.getElementById('imageViewer');
const closeViewer = document.getElementById('closeViewer');
const prevImage = document.getElementById('prevImage');
const nextImage = document.getElementById('nextImage');
const viewerImage = document.getElementById('viewerImage');
const viewerTitle = document.getElementById('viewerTitle');
const viewerCategory = document.getElementById('viewerCategory');
const viewerDescription = document.getElementById('viewerDescription');
const viewerDate = document.getElementById('viewerDate');
// Event Listeners
uploadBtn.addEventListener('click', () => uploadModal.classList.remove('hidden'));
closeModal.addEventListener('click', () => uploadModal.classList.add('hidden'));
cancelUpload.addEventListener('click', () => uploadModal.classList.add('hidden'));
closeViewer.addEventListener('click', () => imageViewer.classList.add('hidden'));
uploadArea.addEventListener('click', () => fileInput.click());
fileInput.addEventListener('change', (e) => {
if (e.target.files.length > 0) {
// You could show a preview here if needed
}
});
// Drag and drop functionality
uploadArea.addEventListener('dragover', (e) => {
e.preventDefault();
uploadArea.classList.add('dragover');
});
uploadArea.addEventListener('dragleave', () => {
uploadArea.classList.remove('dragover');
});
uploadArea.addEventListener('drop', (e) => {
e.preventDefault();
uploadArea.classList.remove('dragover');
fileInput.files = e.dataTransfer.files;
});
// Submit upload
submitUpload.addEventListener('click', () => {
const title = document.getElementById('artTitle').value.trim();
const category = document.getElementById('artCategory').value;
const description = document.getElementById('artDescription').value.trim();
if (!title) {
alert('Please enter a title for your artwork');
return;
}
if (fileInput.files.length === 0) {
alert('Please select an image file');
return;
}
const file = fileInput.files[0];
const reader = new FileReader();
reader.onload = function(e) {
const newArtwork = {
id: Date.now(),
title: title,
category: category,
description: description,
image: e.target.result,
date: new Date().toLocaleDateString()
};
galleryData.push(newArtwork);
saveGalleryData();
renderGallery();
uploadModal.classList.add('hidden');
// Reset form
document.getElementById('artTitle').value = '';
document.getElementById('artDescription').value = '';
fileInput.value = '';
};
reader.readAsDataURL(file);
});
// Category filtering
categoryBtns.forEach(btn => {
btn.addEventListener('click', () => {
categoryBtns.forEach(b => b.classList.remove('active'));
btn.classList.add('active');
currentCategory = btn.dataset.category;
renderGallery();
});
});
// Image viewer navigation
prevImage.addEventListener('click', () => {
if (currentViewerIndex > 0) {
currentViewerIndex--;
updateViewer();
}
});
nextImage.addEventListener('click', () => {
if (currentViewerIndex < getFilteredGallery().length - 1) {
currentViewerIndex++;
updateViewer();
}
});
// Functions
function saveGalleryData() {
localStorage.setItem('artGallery', JSON.stringify(galleryData));
}
function getFilteredGallery() {
if (currentCategory === 'all') return galleryData;
return galleryData.filter(item => item.category === currentCategory);
}
function renderGallery() {
const filteredGallery = getFilteredGallery();
if (filteredGallery.length === 0) {
emptyState.classList.remove('hidden');
galleryGrid.innerHTML = '';
galleryGrid.appendChild(emptyState);
return;
}
emptyState.classList.add('hidden');
galleryGrid.innerHTML = '';
filteredGallery.forEach((item, index) => {
const galleryItem = document.createElement('div');
galleryItem.className = 'gallery-item bg-white rounded-lg overflow-hidden shadow-md cursor-pointer';
galleryItem.dataset.index = index;
galleryItem.innerHTML = `
<div class="relative pb-3/4 h-48 overflow-hidden">
<img src="${item.image}" alt="${item.title}" class="absolute h-full w-full object-cover">
</div>
<div class="p-4">
<h3 class="font-medium text-gray-900 truncate">${item.title}</h3>
<div class="flex items-center mt-1">
<span class="px-2 py-1 text-xs rounded-full ${getCategoryClass(item.category)}">${formatCategory(item.category)}</span>
</div>
</div>
`;
galleryItem.addEventListener('click', () => {
currentViewerIndex = index;
updateViewer();
imageViewer.classList.remove('hidden');
});
galleryGrid.appendChild(galleryItem);
});
}
function updateViewer() {
const artwork = getFilteredGallery()[currentViewerIndex];
viewerImage.src = artwork.image;
viewerImage.alt = artwork.title;
viewerTitle.textContent = artwork.title;
viewerCategory.textContent = formatCategory(artwork.category);
viewerCategory.className = `px-2 py-1 text-xs rounded-full ${getCategoryClass(artwork.category)}`;
viewerDescription.textContent = artwork.description || 'No description provided';
viewerDate.textContent = artwork.date;
// Disable/enable navigation buttons
prevImage.style.display = currentViewerIndex === 0 ? 'none' : 'block';
nextImage.style.display = currentViewerIndex === getFilteredGallery().length - 1 ? 'none' : 'block';
}
function formatCategory(category) {
return category.charAt(0).toUpperCase() + category.slice(1);
}
function getCategoryClass(category) {
const classes = {
painting: 'bg-red-100 text-red-800',
photography: 'bg-blue-100 text-blue-800',
digital: 'bg-purple-100 text-purple-800',
sketch: 'bg-yellow-100 text-yellow-800',
other: 'bg-gray-100 text-gray-800'
};
return classes[category] || 'bg-gray-100 text-gray-800';
}
// Initialize
renderGallery();
</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=Fate17/flashes" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>