promptforge / script.js
fukdufydsu's picture
Build a modern, minimalistic website that acts as a directory for AI-generated image prompt components and their corresponding output images.
c00d809 verified
// Demo data for proof of concept
const demoData = [
{
prompt: "A futuristic cityscape at night with neon lights reflecting on wet streets, cyberpunk aesthetic, cinematic lighting, 8k resolution",
image: "http://static.photos/cityscape/640x360/1",
tags: ["cyberpunk", "futuristic", "night", "urban"]
},
{
prompt: "Minimalist interior design with clean lines, natural light, Scandinavian style, wooden furniture, plants, soft textures",
image: "http://static.photos/interior/640x360/2",
tags: ["minimalist", "scandinavian", "interior", "natural"]
},
{
prompt: "Abstract geometric patterns with vibrant colors, digital art, fractal designs, high detail, symmetrical composition",
image: "http://static.photos/abstract/640x360/3",
tags: ["abstract", "geometric", "digital", "vibrant"]
},
{
prompt: "Steampunk airship flying over Victorian-era city, brass and copper details, mechanical wings, cloudy sky, detailed machinery",
image: "http://static.photos/technology/640x360/4",
tags: ["steampunk", "victorian", "airship", "mechanical"]
},
{
prompt: "Underwater coral reef with bioluminescent creatures, deep sea colors, mysterious atmosphere, high detail, 4k resolution",
image: "http://static.photos/nature/640x360/5",
tags: ["underwater", "bioluminescent", "nature", "mysterious"]
},
{
prompt: "Space station orbiting a gas giant planet, futuristic architecture, stars in background, cinematic composition, NASA aesthetic",
image: "http://static.photos/space/640x360/6",
tags: ["space", "futuristic", "cinematic", "science"]
},
{
prompt: "Vintage film noir scene with detective in trench coat, rainy street, neon signs, dramatic shadows, black and white with selective color",
image: "http://static.photos/cityscape/640x360/7",
tags: ["noir", "vintage", "detective", "dramatic"]
},
{
prompt: "Fantasy forest with glowing mushrooms, magical creatures, ethereal lighting, detailed environment, concept art style",
image: "http://static.photos/nature/640x360/8",
tags: ["fantasy", "magical", "forest", "ethereal"]
},
{
prompt: "Industrial robot arm assembling circuit boards, factory setting, metallic textures, sparks, high-tech machinery, detailed mechanics",
image: "http://static.photos/technology/640x360/9",
tags: ["industrial", "robotic", "technology", "mechanical"]
}
];
let allTags = [];
let currentFilter = '';
let filteredData = [...demoData];
// Initialize the page
document.addEventListener('DOMContentLoaded', () => {
// Extract all unique tags
demoData.forEach(item => {
item.tags.forEach(tag => {
if (!allTags.includes(tag)) {
allTags.push(tag);
}
});
});
renderTagFilters();
renderPromptCards();
// Set up dark mode toggle
const toggleButton = document.getElementById('toggleDarkMode');
toggleButton.addEventListener('click', () => {
document.documentElement.classList.toggle('dark');
localStorage.setItem('darkMode', document.documentElement.classList.contains('dark'));
feather.replace();
});
// Check for saved dark mode preference
if (localStorage.getItem('darkMode') === 'true') {
document.documentElement.classList.add('dark');
}
// Add grid overlay
const gridOverlay = document.createElement('div');
gridOverlay.className = 'grid-overlay';
document.body.appendChild(gridOverlay);
});
// Render tag filter chips
function renderTagFilters() {
const container = document.getElementById('tagFilters');
container.innerHTML = '<button class="tag px-3 py-1 bg-gray-200 dark:bg-gray-700 rounded-full text-sm hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors" data-tag="">All</button>';
allTags.forEach(tag => {
const tagButton = document.createElement('button');
tagButton.className = 'tag px-3 py-1 bg-gray-200 dark:bg-gray-700 rounded-full text-sm hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors';
tagButton.textContent = tag;
tagButton.dataset.tag = tag;
tagButton.addEventListener('click', () => {
document.querySelectorAll('.tag').forEach(btn => btn.classList.remove('bg-blue-500', 'dark:bg-blue-600', 'text-white'));
tagButton.classList.add('bg-blue-500', 'dark:bg-blue-600', 'text-white');
currentFilter = tag;
filterPrompts();
});
container.appendChild(tagButton);
});
}
// Render prompt cards
function renderPromptCards() {
const container = document.getElementById('promptGrid');
container.innerHTML = '';
filteredData.forEach(item => {
const card = document.createElement('div');
card.className = 'prompt-card bg-white dark:bg-gray-800 rounded-xl overflow-hidden shadow-md hover:shadow-xl transition-shadow duration-300';
card.innerHTML = `
<div class="relative">
<img src="${item.image}" alt="AI-generated image" class="w-full h-48 object-cover">
<div class="prompt-overlay absolute inset-0 flex items-center justify-center opacity-0 hover:opacity-100 p-4">
<p class="text-white text-center text-sm">${item.prompt}</p>
</div>
<div class="absolute top-2 right-2">
<button class="copy-btn bg-white dark:bg-gray-700 p-2 rounded-full shadow-md" data-prompt="${item.prompt.replace(/"/g, '&quot;')}">
<i data-feather="copy" class="w-4 h-4"></i>
</button>
</div>
</div>
<div class="p-4">
<div class="flex flex-wrap gap-2 mb-3">
${item.tags.map(tag => `<span class="px-2 py-1 bg-gray-100 dark:bg-gray-700 text-xs rounded">${tag}</span>`).join('')}
</div>
<button class="copy-btn w-full py-2 bg-gray-100 dark:bg-gray-700 rounded-lg text-sm flex items-center justify-center gap-2 hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors" data-prompt="${item.prompt.replace(/"/g, '&quot;')}">
<i data-feather="copy" class="w-4 h-4"></i>
Copy Prompt
</button>
</div>
`;
container.appendChild(card);
});
// Initialize feather icons
feather.replace();
// Add event listeners to copy buttons
document.querySelectorAll('.copy-btn').forEach(button => {
button.addEventListener('click', (e) => {
const prompt = e.currentTarget.dataset.prompt;
navigator.clipboard.writeText(prompt).then(() => {
// Show feedback
const originalHTML = e.currentTarget.innerHTML;
e.currentTarget.innerHTML = '<i data-feather="check" class="w-4 h-4"></i> Copied!';
feather.replace();
setTimeout(() => {
e.currentTarget.innerHTML = originalHTML;
feather.replace();
}, 2000);
});
});
});
}
// Filter prompts based on current filter
function filterPrompts() {
if (currentFilter === '') {
filteredData = [...demoData];
} else {
filteredData = demoData.filter(item =>
item.tags.includes(currentFilter)
);
}
renderPromptCards();
}
// Search functionality (to be implemented with real search bar)
function searchPrompts(query) {
if (!query) {
filteredData = currentFilter ? demoData.filter(item => item.tags.includes(currentFilter)) : [...demoData];
} else {
const lowerQuery = query.toLowerCase();
filteredData = demoData.filter(item =>
item.prompt.toLowerCase().includes(lowerQuery) ||
item.tags.some(tag => tag.toLowerCase().includes(lowerQuery))
);
// If we have a tag filter, apply it as well
if (currentFilter) {
filteredData = filteredData.filter(item => item.tags.includes(currentFilter));
}
}
renderPromptCards();
}