Labareda1945/ai-dev-tools-hub-explorer
0
1 2// Authentication functions3function signInWithGoogle() {4 // Simulate Google OAuth flow5 showNotification('Connecting to Google...', 'info');6 7 setTimeout(() => {8 // Mock successful Google sign in9 const mockGoogleUser = {10 email: 'user@gmail.com',11 displayName: 'Google User',12 photoURL: 'https://picsum.photos/seed/google-user/100/100.jpg',13 provider: 'google',14 credits: 500,15 plan: 'Free Plan',16 createdAt: new Date().toISOString()17 };18 19 localStorage.setItem('user', JSON.stringify(mockGoogleUser));20 showNotification('Successfully signed in with Google!', 'success');21 22 // Redirect to home page23 setTimeout(() => {24 window.location.href = 'index.html';25 }, 1500);26 }, 2000);27}28 29function handleLogin(event) {30 if (event) event.preventDefault();31 32 const email = document.getElementById('email')?.value;33 const password = document.getElementById('password')?.value;34 35 if (!email || !password) {36 showNotification('Please fill in all fields', 'error');37 return;38 }39 40 // Simulate login process41 showNotification('Signing in...', 'info');42 43 setTimeout(() => {44 // Mock successful login45 const mockUser = {46 email: email,47 displayName: email.split('@')[0],48 credits: 1000,49 plan: 'Pro Plan',50 createdAt: new Date().toISOString()51 };52 53 localStorage.setItem('user', JSON.stringify(mockUser));54 showNotification('Login successful! Welcome back.', 'success');55 56 // Redirect to home page57 setTimeout(() => {58 window.location.href = 'index.html';59 }, 1500);60 }, 1500);61}62 63function handleRegister(event) {64 if (event) event.preventDefault();65 66 const firstName = document.getElementById('firstName')?.value;67 const lastName = document.getElementById('lastName')?.value;68 const email = document.getElementById('email')?.value;69 const password = document.getElementById('password')?.value;70 const confirmPassword = document.getElementById('confirmPassword')?.value;71 72 if (!firstName || !lastName || !email || !password || !confirmPassword) {73 showNotification('Please fill in all fields', 'error');74 return;75 }76 77 if (password !== confirmPassword) {78 showNotification('Passwords do not match', 'error');79 return;80 }81 82 if (password.length < 8) {83 showNotification('Password must be at least 8 characters long', 'error');84 return;85 }86 87 // Simulate registration process88 showNotification('Creating your account...', 'info');89 90 setTimeout(() => {91 // Mock successful registration92 const mockUser = {93 email: email,94 displayName: `${firstName} ${lastName}`,95 credits: 500, // Welcome bonus96 plan: 'Free Plan',97 createdAt: new Date().toISOString()98 };99 100 localStorage.setItem('user', JSON.stringify(mockUser));101 showNotification('Account created successfully! Welcome to AI Muse Forge!', 'success');102 103 // Redirect to home page104 setTimeout(() => {105 window.location.href = 'index.html';106 }, 1500);107 }, 2000);108}109 110function handleLogout() {111 showNotification('Signing out...', 'info');112 113 setTimeout(() => {114 localStorage.removeItem('user');115 showNotification('You have been signed out successfully', 'success');116 117 // Redirect to login page118 setTimeout(() => {119 window.location.href = 'login.html';120 }, 1000);121 }, 1000);122}123 124function togglePassword() {125 const passwordInput = document.getElementById('password');126 const passwordToggleIcon = document.getElementById('password-toggle-icon');127 128 if (passwordInput && passwordToggleIcon) {129 if (passwordInput.type === 'password') {130 passwordInput.type = 'text';131 passwordToggleIcon.setAttribute('data-feather', 'eye-off');132 } else {133 passwordInput.type = 'password';134 passwordToggleIcon.setAttribute('data-feather', 'eye');135 }136 feather.replace();137 }138}139 140function toggleConfirmPassword() {141 const confirmPasswordInput = document.getElementById('confirmPassword');142 const confirmPasswordToggleIcon = document.getElementById('confirm-password-toggle-icon');143 144 if (confirmPasswordInput && confirmPasswordToggleIcon) {145 if (confirmPasswordInput.type === 'password') {146 confirmPasswordInput.type = 'text';147 confirmPasswordToggleIcon.setAttribute('data-feather', 'eye-off');148 } else {149 confirmPasswordInput.type = 'password';150 confirmPasswordToggleIcon.setAttribute('data-feather', 'eye');151 }152 feather.replace();153 }154}155 156// Check authentication status on page load157function checkAuthStatus() {158 const user = JSON.parse(localStorage.getItem('user') || 'null');159 const currentPath = window.location.pathname;160 161 // Redirect authenticated users away from auth pages162 if (user && (currentPath.includes('login.html') || currentPath.includes('register.html'))) {163 window.location.href = 'index.html';164 return false;165 }166 167 // Redirect unauthenticated users to login if needed (for protected pages)168 if (!user && currentPath.includes('dashboard.html')) {169 window.location.href = 'login.html';170 return false;171 }172 173 return true;174}175 176// Main application script177document.addEventListener('DOMContentLoaded', function() {178 // Check authentication status first179 if (!checkAuthStatus()) {180 return;181 }182// Initialize Feather Icons183 feather.replace();184 185 // Mock API data for demonstration186 const mockModels = [187 {188 id: 1,189 name: "Cyberpunk Samurai",190 type: "LORA",191 triggerWords: ["cyber_samurai", "neon_warrior"],192 image: "http://static.photos/technology/640x360/1",193 description: "Futuristic warrior with neon enhancements"194 },195 {196 id: 2,197 name: "Fantasy Elven Queen",198 type: "LORA",199 triggerWords: ["elven_queen", "fantasy_royalty"],200 image: "http://static.photos/fantasy/640x360/2",201 description: "Ethereal elven royalty with magical aura"202 },203 {204 id: 3,205 name: "Steampunk Inventor",206 type: "LORA",207 triggerWords: ["steampunk_inventor", "gear_master"],208 image: "http://static.photos/vintage/640x360/3",209 description: "Victorian-era inventor with mechanical enhancements"210 },211 {212 id: 4,213 name: "Astral Traveler",214 type: "CHECKPOINT",215 triggerWords: ["astral", "cosmic_wanderer"],216 image: "http://static.photos/abstract/640x360/4",217 description: "Cosmic being traversing dimensional planes"218 }219 ];220 221 const mockQueue = [222 { id: 7892, status: 'PROCESSING', progress: 75 },223 { id: 7891, status: 'PENDING', progress: 0 },224 { id: 7890, status: 'QUEUED', progress: 0 }225 ];226 227 // Load models gallery228 function loadModelsGallery() {229 const gallery = document.getElementById('models-gallery');230 if (!gallery) return;231 232 gallery.innerHTML = mockModels.map(model => `233 <div class="model-card bg-gray-800/50 backdrop-blur-sm rounded-xl overflow-hidden border border-gray-700 hover-lift">234 <div class="relative h-48 overflow-hidden">235 <img src="${model.image}" alt="${model.name}" class="w-full h-full object-cover transition-transform duration-500 hover:scale-110">236 <div class="absolute top-3 right-3">237 <span class="status-badge ${model.type === 'LORA' ? 'bg-secondary-900/80' : 'bg-primary-900/80'} text-xs px-2 py-1 rounded">238 ${model.type}239 </span>240 </div>241 </div>242 <div class="p-4">243 <h3 class="font-bold text-lg mb-2">${model.name}</h3>244 <p class="text-gray-400 text-sm mb-3">${model.description}</p>245 <div class="flex flex-wrap gap-1 mb-4">246 ${model.triggerWords.map(word => `247 <span class="px-2 py-1 bg-gray-900/70 text-xs rounded">${word}</span>248 `).join('')}249 </div>250 <button class="w-full px-4 py-2 bg-gray-700 hover:bg-gray-600 rounded-lg text-sm transition-colors flex items-center justify-center gap-2" onclick="selectModel(${model.id})">251 <i data-feather="plus" class="w-4 h-4"></i>252 Select Model253 </button>254 </div>255 </div>256 `).join('');257 258 // Re-initialize feather icons for new content259 setTimeout(() => feather.replace(), 100);260 }261 262 // Update queue display263 function updateQueueDisplay() {264 const queueList = document.getElementById('queue-list');265 if (!queueList) return;266 267 queueList.innerHTML = mockQueue.map(job => `268 <div class="flex items-center justify-between p-3 bg-gray-900/50 rounded-lg hover:bg-gray-800/70 transition-colors">269 <div class="flex items-center gap-3">270 <div class="w-2 h-2 rounded-full ${getStatusColor(job.status)} ${job.status === 'PROCESSING' ? 'animate-pulse' : ''}"></div>271 <div>272 <div class="font-medium">Job #${job.id}</div>273 <div class="text-xs text-gray-400">${getStatusText(job.status)}</div>274 </div>275 </div>276 <div class="flex items-center gap-3">277 ${job.status === 'PROCESSING' ? `278 <div class="w-24 h-2 bg-gray-700 rounded-full overflow-hidden">279 <div class="h-full bg-primary-500 rounded-full" style="width: ${job.progress}%"></div>280 </div>281 ` : ''}282 <span class="text-sm ${getStatusTextColor(job.status)}">${job.status}</span>283 </div>284 </div>285 `).join('');286 }287 288 // Helper functions for status display289 function getStatusColor(status) {290 switch(status) {291 case 'PROCESSING': return 'bg-green-500';292 case 'PENDING': return 'bg-yellow-500';293 case 'QUEUED': return 'bg-blue-500';294 case 'SUCCESS': return 'bg-green-500';295 case 'FAILED': return 'bg-red-500';296 default: return 'bg-gray-500';297 }298 }299 300 function getStatusText(status) {301 switch(status) {302 case 'PROCESSING': return 'Processing on GPU #3';303 case 'PENDING': return 'Awaiting GPU allocation';304 case 'QUEUED': return 'In queue position #2';305 case 'SUCCESS': return 'Completed successfully';306 case 'FAILED': return 'Generation failed';307 default: return status;308 }309 }310 311 function getStatusTextColor(status) {312 switch(status) {313 case 'PROCESSING': return 'text-green-400';314 case 'PENDING': return 'text-yellow-400';315 case 'QUEUED': return 'text-blue-400';316 case 'SUCCESS': return 'text-green-400';317 case 'FAILED': return 'text-red-400';318 default: return 'text-gray-400';319 }320 }321 322 // Update stats with random numbers for demo323 function updateStats() {324 const stats = {325 gpuCount: Math.floor(Math.random() * 5) + 10, // 10-15326 imagesCount: Math.floor(Math.random() * 1000) + 8000, // 8000-9000327 modelsCount: Math.floor(Math.random() * 50) + 150, // 150-200328 queueTime: Math.floor(Math.random() * 30) + 30 // 30-60 seconds329 };330 331 document.getElementById('gpu-count').textContent = stats.gpuCount;332 document.getElementById('images-count').textContent = stats.imagesCount.toLocaleString();333 document.getElementById('models-count').textContent = stats.modelsCount;334 document.getElementById('queue-time').textContent = `${stats.queueTime}s`;335 336 // Animate number counting337 animateCounter('gpu-count', stats.gpuCount);338 animateCounter('images-count', stats.imagesCount);339 animateCounter('models-count', stats.modelsCount);340 }341 342 function animateCounter(elementId, target) {343 const element = document.getElementById(elementId);344 if (!element) return;345 346 const current = parseInt(element.textContent.replace(/,/g, '')) || 0;347 const increment = (target - current) / 30; // 30 frames348 let currentValue = current;349 350 const timer = setInterval(() => {351 currentValue += increment;352 if ((increment > 0 && currentValue >= target) || (increment < 0 && currentValue <= target)) {353 currentValue = target;354 clearInterval(timer);355 }356 element.textContent = Math.round(currentValue).toLocaleString();357 }, 50);358 }359 360 // Simulate queue updates361 function simulateQueueUpdates() {362 setInterval(() => {363 mockQueue.forEach(job => {364 if (job.status === 'PROCESSING' && job.progress < 100) {365 job.progress += Math.random() * 10;366 if (job.progress >= 100) {367 job.progress = 100;368 job.status = 'SUCCESS';369 }370 } else if (job.status === 'QUEUED') {371 job.status = 'PENDING';372 } else if (job.status === 'PENDING') {373 job.status = 'PROCESSING';374 job.progress = 0;375 }376 });377 updateQueueDisplay();378 }, 3000);379 }380 381 // Initialize everything382 loadModelsGallery();383 updateQueueDisplay();384 updateStats();385 simulateQueueUpdates();386 387 // Add smooth scrolling for anchor links388 document.querySelectorAll('a[href^="#"]').forEach(anchor => {389 anchor.addEventListener('click', function (e) {390 e.preventDefault();391 const target = document.querySelector(this.getAttribute('href'));392 if (target) {393 target.scrollIntoView({394 behavior: 'smooth',395 block: 'start'396 });397 }398 });399 });400 401 // Add floating animation to hero section402 const heroTitle = document.querySelector('h1');403 if (heroTitle) {404 heroTitle.style.animation = 'float 6s ease-in-out infinite';405 }406});407 408// Global function for model selection409window.selectModel = function(modelId) {410 const model = mockModels.find(m => m.id === modelId);411 if (model) {412 // Show notification413 showNotification(`Selected model: ${model.name}`, 'success');414 415 // Update control panel trigger words416 const promptInput = document.querySelector('textarea[placeholder*="prompt"]');417 if (promptInput) {418 const triggerWord = model.triggerWords[0];419 if (!promptInput.value.includes(triggerWord)) {420 promptInput.value = `${promptInput.value} ${triggerWord}`.trim();421 }422 }423 }424};425 426// Notification system427function showNotification(message, type = 'info') {428 const notification = document.createElement('div');429 notification.className = `fixed top-4 right-4 z-50 px-6 py-3 rounded-lg shadow-lg transform translate-x-full transition-transform duration-300 ${430 type === 'success' ? 'bg-green-900/90 border border-green-700' : 431 type === 'error' ? 'bg-red-900/90 border border-red-700' : 432 'bg-primary-900/90 border border-primary-700'433 }`;434 notification.innerHTML = `435 <div class="flex items-center gap-3">436 <i data-feather="${type === 'success' ? 'check-circle' : type === 'error' ? 'alert-circle' : 'info'}" 437 class="w-5 h-5 ${type === 'success' ? 'text-green-400' : type === 'error' ? 'text-red-400' : 'text-primary-400'}"></i>438 <span>${message}</span>439 </div>440 `;441 442 document.body.appendChild(notification);443 feather.replace();444 445 // Animate in446 setTimeout(() => {447 notification.style.transform = 'translateX(0)';448 }, 10);449 450 // Remove after 3 seconds451 setTimeout(() => {452 notification.style.transform = 'translateX(100%)';453 setTimeout(() => {454 if (notification.parentNode) {455 notification.parentNode.removeChild(notification);456 }457 }, 300);458 }, 3000);459}460 461// Export functions for use in components462window.showNotification = showNotification;