ai-clone-me / index.html
rahul7star's picture
Update index.html
8844b2d verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI Clone - Create Your Digital Twin</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>
.gradient-bg {
background: linear-gradient(135deg, #f9f9f9 0%, #f0f4ff 50%, #f5f7fa 100%);
}
.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);
}
.progress-bar {
transition: width 0.5s ease;
}
.avatar-preview {
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
}
.plan-card {
transition: all 0.3s ease;
}
.plan-card:hover {
transform: translateY(-5px);
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
.selected-plan {
border-color: #667eea;
background-color: rgba(102, 126, 234, 0.05);
}
.toast {
animation: slideIn 0.5s, fadeOut 0.5s 2.5s;
}
@keyframes slideIn {
from { transform: translateX(100%); }
to { transform: translateX(0); }
}
@keyframes fadeOut {
from { opacity: 1; }
to { opacity: 0; }
}
</style>
</head>
<body class="min-h-screen bg-gray-50">
<!-- Navigation Bar -->
<nav class="bg-gray-900 shadow-sm sticky top-0 z-10 border-b border-purple-500">
<div class="container mx-auto px-4 py-3 flex justify-between items-center">
<div class="flex items-center">
<video class="w-48 h-12 rounded-md object-cover mr-2" src="https://huggingface.co/rahul7star/ohamlab/resolve/main/ohamlab.mp4" autoplay muted loop playsinline></video>
<span class="text-xl font-bold text-purple-200">OhamLab</span>
</div>
<div class="hidden md:flex space-x-8">
<a href="#home" class="nav-link text-purple-200 hover:text-white font-medium">Home</a>
<a href="#features" class="nav-link text-purple-200 hover:text-white font-medium">Features</a>
<a href="#create" class="nav-link text-purple-200 hover:text-white font-medium">Create</a>
<a href="#pricing" class="nav-link text-purple-200 hover:text-white font-medium">Pricing</a>
<button id="demo-toggle" class="text-purple-200 hover:text-white font-medium">Demo</button>
</div>
<button id="mobile-menu-button" class="md:hidden text-gray-600">
<i class="fas fa-bars text-xl"></i>
</button>
</div>
</nav>
<div class="container mx-auto px-4 py-8">
<!-- Header -->
<header class="flex justify-between items-center mb-12">
<div class="flex items-center">
<video class="w-24 h-12 rounded-md object-cover mr-3" src="https://huggingface.co/rahul7star/ohamlab/resolve/main/ohamlab.mp4" autoplay muted loop playsinline></video>
<h1 class="text-2xl font-bold text-gray-800">OhamLab</h1>
</div>
<div id="auth-section">
<button id="sign-in-btn" class="bg-white text-gray-700 px-6 py-2 rounded-full shadow-md hover:bg-gray-100 transition flex items-center">
<i class="fab fa-google text-red-500 mr-2"></i>
Sign In with Google
</button>
<button id="guest-btn" class="ml-2 bg-gray-200 text-gray-700 px-6 py-2 rounded-full shadow-md hover:bg-gray-300 transition">
Continue as Guest
</button>
<button id="logout-guest-btn" class="hidden ml-2 bg-red-100 text-red-700 px-6 py-2 rounded-full shadow-md hover:bg-red-200 transition">
Logout Guest
</button>
<div id="user-profile" class="hidden flex items-center space-x-4">
<img id="user-avatar" class="w-10 h-10 rounded-full" src="" alt="User Avatar">
<span id="user-name" class="font-medium text-gray-700"></span>
<button id="sign-out-btn" class="text-gray-500 hover:text-gray-700">
<i class="fas fa-sign-out-alt"></i>
</button>
</div>
</div>
</header>
<!-- Main Content -->
<main class="max-w-4xl mx-auto">
<!-- Home Section -->
<section id="home" class="text-center py-16">
<h1 class="text-4xl font-bold text-gray-800 mb-4">OhamLab - Create Your Digital Twin</h1>
<p class="text-xl text-gray-600 mb-8">Generate AI-powered avatars that look just like you</p>
<div class="flex space-x-4 justify-center">
<button id="get-started-btn" class="bg-gradient-to-r from-purple-500 to-pink-600 text-white px-8 py-3 rounded-full font-medium shadow-lg hover:opacity-90 transition">
Get Started
</button>
<button id="demo-btn" class="bg-white text-indigo-600 border-2 border-indigo-600 px-8 py-3 rounded-full font-medium shadow-lg hover:bg-indigo-50 transition">
See Demo
</button>
</div>
</section>
<!-- Features Section -->
<section id="features" class="mb-16">
<h2 class="text-2xl font-bold text-gray-800 mb-8 text-center">Key Features</h2>
<div class="grid md:grid-cols-3 gap-8">
<div class="bg-white p-6 rounded-xl shadow-md border border-indigo-100">
<div class="text-indigo-500 text-3xl mb-4">
<i class="fas fa-user-circle"></i>
</div>
<h3 class="text-lg font-semibold mb-2">Realistic Avatars</h3>
<p class="text-gray-600">Generate high-quality avatars that capture your unique features.</p>
</div>
<div class="bg-white p-6 rounded-xl shadow-md">
<div class="text-purple-500 text-3xl mb-4">
<i class="fas fa-video"></i>
</div>
<h3 class="text-lg font-semibold mb-2">Animated Videos</h3>
<p class="text-gray-600">Bring your avatar to life with custom animated videos.</p>
</div>
<div class="bg-white p-6 rounded-xl shadow-md">
<div class="text-pink-500 text-3xl mb-4">
<i class="fas fa-magic"></i>
</div>
<h3 class="text-lg font-semibold mb-2">AI Magic</h3>
<p class="text-gray-600">Use AI to transform your photos into stunning digital art.</p>
</div>
</div>
</section>
<!-- Social Promo Box -->
<section id="social-promo" class="mb-16 bg-gradient-to-r from-purple-50 to-indigo-50 py-12 rounded-2xl hidden">
<div class="max-w-6xl mx-auto px-4">
<h2 class="text-3xl font-bold text-gray-800 mb-6 text-center">See Our AI in Action</h2>
<p class="text-lg text-gray-600 mb-8 text-center">Explore our latest creations on social media</p>
<!-- Full-width video -->
<div class="w-full aspect-video bg-black rounded-xl overflow-hidden mb-6">
<iframe
class="w-full h-full"
src="about:blank"
data-src="https://www.youtube.com/embed/videoseries?list=PL8HXQOLwB6k0N8m2Ql2paDAY_n_KdXSSM"
allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
title="YouTube Playlist Player">
</iframe>
</div>
<!-- Small social buttons centered below -->
<div class="flex justify-center gap-4">
<a href="https://www.instagram.com/ohamlab/reels" target="_blank"
class="flex items-center gap-2 text-xs bg-gradient-to-r from-pink-500 to-purple-500 text-white px-3 py-1.5 rounded-full shadow hover:opacity-90 transition">
<i class="fab fa-instagram text-base"></i>
<span>Instagram</span>
</a>
<a href="https://www.youtube.com/@Rahul7starAI/shorts" target="_blank"
class="flex items-center gap-2 text-xs bg-gradient-to-r from-red-600 to-red-500 text-white px-3 py-1.5 rounded-full shadow hover:opacity-90 transition">
<i class="fab fa-youtube text-base"></i>
<span>YouTube</span>
</a>
</div>
</div>
</section>
<!-- Upload Section -->
<section id="create" class="mb-12 bg-white rounded-xl shadow-lg p-6 hidden border border-gray-200">
<h2 class="text-xl font-semibold text-gray-800 mb-6">Create Your AI Clone</h2>
<div class="grid md:grid-cols-2 gap-6">
<!-- Image Upload -->
<div class="upload-area rounded-lg p-8 text-center cursor-pointer" id="image-upload">
<i class="fas fa-images text-indigo-500 text-4xl mb-4"></i>
<h3 class="text-lg font-medium text-gray-700 mb-2">Upload Images</h3>
<p class="text-gray-500 mb-4">Upload at least 5 images of yourself from different angles</p>
<input type="file" id="image-input" class="hidden" accept="image/*" multiple>
<button class="bg-indigo-100 text-indigo-600 px-4 py-2 rounded-full text-sm font-medium">
Select Files
</button>
</div>
<!-- ZIP Upload -->
<div class="upload-area rounded-lg p-8 text-center cursor-pointer" id="zip-upload">
<i class="fas fa-file-archive text-purple-500 text-4xl mb-4"></i>
<h3 class="text-lg font-medium text-gray-700 mb-2">Upload ZIP File</h3>
<p class="text-gray-500 mb-4">Compress your images into a single .zip file</p>
<input type="file" id="zip-input" class="hidden" accept=".zip">
<button class="bg-purple-100 text-purple-600 px-4 py-2 rounded-full text-sm font-medium">
Select ZIP File
</button>
</div>
</div>
<!-- Image Preview Carousel -->
<div id="image-preview-container" class="hidden mt-8">
<div class="flex justify-between items-center mb-4">
<h3 class="text-md font-medium text-gray-700">
<span id="image-count">0</span> images selected
</h3>
<button id="clear-images" class="text-red-500 text-sm font-medium">Clear all</button>
</div>
<div id="image-carousel" class="flex space-x-4 overflow-x-auto pb-4">
<!-- Images will be added here dynamically -->
</div>
</div>
<!-- Train Model Button -->
<div id="train-model-section" class="hidden mt-8 text-center">
<button id="train-model-btn" class="bg-gradient-to-r from-indigo-500 to-purple-600 text-white px-8 py-3 rounded-full font-medium shadow-lg hover:opacity-90 transition">
Train Your AI Model
</button>
</div>
<!-- Training Progress -->
<div id="training-progress" class="hidden mt-8">
<div class="flex justify-between mb-2">
<span class="text-sm font-medium text-gray-700">Training in progress...</span>
<span id="progress-percent" class="text-sm font-medium text-gray-700">0%</span>
</div>
<div class="w-full bg-gray-200 rounded-full h-2.5">
<div id="progress-bar" class="bg-gradient-to-r from-indigo-500 to-purple-600 h-2.5 rounded-full progress-bar" style="width: 0%"></div>
</div>
</div>
</section>
<!-- AI Clone Results -->
<section id="results-section" class="hidden mb-12 bg-white rounded-xl shadow-lg p-6">
<h2 class="text-xl font-semibold text-gray-800 mb-6">Your AI Clone Results</h2>
<div class="flex flex-col items-center">
<div class="avatar-preview w-64 h-64 rounded-full bg-gray-100 mb-6 overflow-hidden flex items-center justify-center">
<img id="generated-avatar" src="" alt="Generated Avatar" class="hidden w-full h-full object-cover">
<i class="fas fa-user text-gray-400 text-6xl" id="avatar-placeholder"></i>
</div>
<button id="recreate-btn" class="bg-indigo-600 text-white px-6 py-2 rounded-full font-medium hover:bg-indigo-700 transition">
<i class="fas fa-sync-alt mr-2"></i> Recreate
</button>
<div class="mt-6 flex space-x-4">
<button class="share-btn bg-blue-500 text-white px-4 py-2 rounded-full text-sm font-medium hover:bg-blue-600 transition">
<i class="fab fa-twitter mr-2"></i> Share to Twitter
</button>
<button class="share-btn bg-pink-500 text-white px-4 py-2 rounded-full text-sm font-medium hover:bg-pink-600 transition">
<i class="fab fa-instagram mr-2"></i> Share to Instagram
</button>
<button class="share-btn bg-gray-700 text-white px-4 py-2 rounded-full text-sm font-medium hover:bg-gray-800 transition">
<i class="fas fa-link mr-2"></i> Copy Link
</button>
</div>
</div>
</section>
<!-- Bring Avatar to Life -->
<section id="animate-section" class="hidden mb-12 bg-white rounded-xl shadow-lg p-6">
<h2 class="text-xl font-semibold text-gray-800 mb-6">Bring Your Avatar to Life</h2>
<div class="mb-6">
<label for="prompt-input" class="block text-sm font-medium text-gray-700 mb-2">Enter a prompt for your avatar</label>
<textarea id="prompt-input" rows="3" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-indigo-500 focus:border-indigo-500" placeholder="E.g., 'A professional headshot with a blue background'"></textarea>
</div>
<button id="generate-video-btn" class="bg-gradient-to-r from-purple-500 to-pink-600 text-white px-8 py-3 rounded-full font-medium shadow-lg hover:opacity-90 transition">
<i class="fas fa-film mr-2"></i> Generate Video
</button>
<!-- Video Loading -->
<div id="video-loading" class="hidden mt-8 text-center">
<div class="inline-block animate-spin rounded-full h-10 w-10 border-t-2 border-b-2 border-purple-500 mb-4"></div>
<p class="text-gray-700">Generating your animated avatar... This may take a few moments.</p>
</div>
<!-- Video Preview -->
<div id="video-preview" class="hidden mt-8">
<div class="bg-gray-100 rounded-xl overflow-hidden w-full aspect-video flex items-center justify-center">
<i class="fas fa-play-circle text-purple-500 text-6xl opacity-70" id="video-play-icon"></i>
</div>
<div class="mt-4 flex justify-center space-x-4">
<button class="share-btn bg-blue-500 text-white px-4 py-2 rounded-full text-sm font-medium hover:bg-blue-600 transition">
<i class="fab fa-twitter mr-2"></i> Share
</button>
<button class="share-btn bg-pink-500 text-white px-4 py-2 rounded-full text-sm font-medium hover:bg-pink-600 transition">
<i class="fab fa-instagram mr-2"></i> Share
</button>
<button class="share-btn bg-gray-700 text-white px-4 py-2 rounded-full text-sm font-medium hover:bg-gray-800 transition">
<i class="fas fa-download mr-2"></i> Download
</button>
</div>
</div>
</section>
<!-- Pricing Plans -->
<section id="pricing" class="mb-12 bg-white rounded-xl shadow-lg p-6 border border-gray-200">
<h2 class="text-xl font-semibold text-gray-800 mb-6">Choose Your Plan</h2>
<div class="grid md:grid-cols-3 gap-6">
<!-- Free Plan -->
<div class="plan-card border-2 border-gray-200 rounded-xl p-6 cursor-pointer" data-plan="free">
<div class="flex justify-between items-start mb-4">
<div>
<h3 class="text-lg font-bold text-gray-800">Free</h3>
<p class="text-gray-600 text-sm">Basic features</p>
</div>
<div class="text-right">
<span class="text-2xl font-bold text-gray-800">$0</span>
<span class="text-gray-500 text-sm">/request</span>
</div>
</div>
<ul class="space-y-2 mb-6">
<li class="flex items-center text-gray-700">
<i class="fas fa-check-circle text-green-500 mr-2"></i>
<span>1 AI Generation</span>
</li>
<li class="flex items-center text-gray-700">
<i class="fas fa-check-circle text-green-500 mr-2"></i>
<span>Standard Quality</span>
</li>
<li class="flex items-center text-gray-500">
<i class="fas fa-times-circle text-gray-300 mr-2"></i>
<span>No Video Generation</span>
</li>
<li class="flex items-center text-gray-500">
<i class="fas fa-times-circle text-gray-300 mr-2"></i>
<span>No Priority Support</span>
</li>
</ul>
<button class="w-full border-2 border-gray-300 text-gray-700 py-2 rounded-lg font-medium hover:bg-gray-50 transition">
Current Plan
</button>
</div>
<!-- Pro Plan -->
<div class="plan-card border-2 border-indigo-300 rounded-xl p-6 cursor-pointer bg-indigo-50" data-plan="pro">
<div class="flex justify-between items-start mb-4">
<div>
<h3 class="text-lg font-bold text-gray-800">Pro</h3>
<p class="text-gray-600 text-sm">For creators</p>
</div>
<div class="text-right">
<span id="pro-price-label" class="text-2xl font-bold text-gray-800">$20</span>
<span id="pro-price-currency" class="text-gray-500 text-sm">/request</span>
</div>
</div>
<ul class="space-y-2 mb-6">
<li class="flex items-center text-gray-700">
<i class="fas fa-check-circle text-green-500 mr-2"></i>
<span>Pay-per-request</span>
</li>
<li class="flex items-center text-gray-700">
<i class="fas fa-check-circle text-green-500 mr-2"></i>
<span>High Quality</span>
</li>
<li class="flex items-center text-gray-700">
<i class="fas fa-check-circle text-green-500 mr-2"></i>
<span>5 Video Generations</span>
</li>
<li class="flex items-center text-gray-500">
<i class="fas fa-times-circle text-gray-300 mr-2"></i>
<span>Standard Support</span>
</li>
</ul>
<button id="upgrade-pro-btn" class="w-full bg-indigo-600 text-white py-2 rounded-lg font-medium hover:bg-indigo-700 transition">
Upgrade to Pro
</button>
</div>
<!-- Studio Plan -->
<div class="plan-card border-2 border-gray-200 rounded-xl p-6 cursor-pointer" data-plan="studio">
<div class="flex justify-between items-start mb-4">
<div>
<h3 class="text-lg font-bold text-gray-800">Studio</h3>
<p class="text-gray-600 text-sm">For professionals</p>
</div>
<div class="text-right">
<span class="text-2xl font-bold text-gray-800">$50</span>
<span class="text-gray-500 text-sm">/request</span>
</div>
</div>
<ul class="space-y-2 mb-6">
<li class="flex items-center text-gray-700">
<i class="fas fa-check-circle text-green-500 mr-2"></i>
<span>Pay-per-request</span>
</li>
<li class="flex items-center text-gray-700">
<i class="fas fa-check-circle text-green-500 mr-2"></i>
<span>Ultra Quality</span>
</li>
<li class="flex items-center text-gray-700">
<i class="fas fa-check-circle text-green-500 mr-2"></i>
<span>Unlimited Videos</span>
</li>
<li class="flex items-center text-gray-700">
<i class="fas fa-check-circle text-green-500 mr-2"></i>
<span>Priority Support</span>
</li>
</ul>
<button class="w-full border-2 border-gray-300 text-gray-700 py-2 rounded-lg font-medium hover:bg-gray-50 transition">
Choose Studio
</button>
</div>
</div>
<!-- Plan Confirmation -->
<div id="plan-confirmation" class="hidden mt-6 p-4 bg-green-50 border border-green-200 rounded-lg text-center">
<div class="flex justify-center items-center text-green-600">
<i class="fas fa-check-circle text-2xl mr-2"></i>
<span class="font-medium">Your plan has been updated successfully!</span>
</div>
</div>
</section>
</main>
<!-- Footer -->
<footer class="mt-12 bg-gray-50 py-8 border-t border-gray-200">
<div class="container mx-auto px-4 text-center text-gray-500">
<p>© 2025 OhamLab. All rights reserved.</p>
<div class="flex justify-center space-x-4 mt-4">
<a href="https://www.instagram.com/ohamlab/" target="_blank" class="text-gray-600 hover:text-pink-500">
<i class="fab fa-instagram text-2xl"></i>
</a>
<a href="https://www.youtube.com/" target="_blank" class="text-gray-600 hover:text-red-500">
<i class="fab fa-youtube text-2xl"></i>
</a>
</div>
</div>
<!-- Page view counter -->
<div class="fixed bottom-4 right-4 bg-gray-800 text-white px-3 py-1 rounded-full text-sm flex items-center shadow-lg">
<i class="fas fa-eye mr-2"></i>
<span id="page-counter">0</span> views
</div>
</footer>
<!-- Toast Notification -->
<div id="toast" class="fixed bottom-4 right-4 hidden">
<div class="bg-gray-800 text-white px-6 py-3 rounded-lg shadow-lg flex items-center">
<i class="fas fa-check-circle text-green-400 mr-2"></i>
<span id="toast-message">Link copied to clipboard!</span>
</div>
</div>
</div>
<!-- Demo Video Modal -->
<div id="demo-modal" class="fixed inset-0 z-50 hidden flex items-center justify-center bg-black bg-opacity-75">
<div class="relative w-full max-w-4xl mx-4">
<div class="bg-white rounded-lg overflow-hidden shadow-xl">
<div class="flex justify-between items-center px-6 py-4 border-b">
<h3 class="text-xl font-semibold text-gray-800">OhamLab Demo</h3>
<button id="close-modal" class="text-gray-500 hover:text-gray-700">
<i class="fas fa-times text-2xl"></i>
</button>
</div>
<div class="p-4">
<div class="aspect-w-16 aspect-h-9">
<iframe id="demo-video" class="w-full h-96" src="https://www.youtube.com/embed/LRkj_ObV0T0?enablejsapi=1" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
</div>
</div>
</div>
</div>
<script src="https://accounts.google.com/gsi/client" async defer></script>
<script src="https://checkout.razorpay.com/v1/checkout.js"></script>
<script>
// Auto-set currency & price label on load
(function setLocalePrice() {
const isIndia = (Intl.DateTimeFormat().resolvedOptions().timeZone || '').startsWith('Asia/Kolkata');
document.getElementById('pro-price-label').textContent = isIndia ? '₹1650' : '$20';
document.getElementById('pro-price-currency').textContent = '/month';
})();
// Central configuration – all secrets injected by Hugging-Face Space
const CONFIG = {
stripePubKey: "__HF_STRIPE_PUBLISHABLE_KEY__", // injected at build time
googleClientId: "__HF_OAUTH_CLIENT_ID__", // injected at build time
endpoints: {
uploadImages: "https://rahul7star-ohamlab-ai-toolkit.hf.space/upload",
uploadZip: "https://rahul7star-ohamlab-ai-toolkit.hf.space/upload-zip",
trainModel: "__HF_TRAIN_MODEL__" || "https://rahul7star-ohamlab-ai-toolkit.hf.space/train",
generateVideo: "https://rahul7star-ohamlab-ai-toolkit.hf.space/generate-video",
updatePlan: "https://rahul7star-ohamlab-ai-toolkit.hf.space/update-plan",
createCheckoutSession: "__HF_CREATE_CHECKOUT__" || "https://rahul7star-ohamlab-ai-toolkit.hf.space/create-checkout-session",
oauthLogin: "__HF_OAUTH_LOGIN__" || "https://rahul7star-ohamlab-ai-toolkit.hf.space/auth/google"
}
};
// Demo Video Modal
const demoBtn = document.getElementById('demo-btn');
const demoModal = document.getElementById('demo-modal');
const closeModal = document.getElementById('close-modal');
const demoVideo = document.getElementById('demo-video');
demoBtn.addEventListener('click', () => {
demoModal.classList.remove('hidden');
document.body.style.overflow = 'hidden';
});
closeModal.addEventListener('click', () => {
demoModal.classList.add('hidden');
document.body.style.overflow = 'auto';
// Reset video when closing modal
demoVideo.src = demoVideo.src;
});
// Close modal when clicking outside
demoModal.addEventListener('click', (e) => {
if (e.target === demoModal) {
demoModal.classList.add('hidden');
document.body.style.overflow = 'auto';
demoVideo.src = demoVideo.src;
}
});
// Mock user data
const mockUser = {
name: "John Doe",
avatar: "https://randomuser.me/api/portraits/men/1.jpg"
};
// DOM Elements
const signOutBtn = document.getElementById('sign-out-btn');
// Mock generated avatars
const mockAvatars = [
"https://randomuser.me/api/portraits/men/2.jpg",
"https://randomuser.me/api/portraits/men/3.jpg",
"https://randomuser.me/api/portraits/men/4.jpg",
"https://randomuser.me/api/portraits/men/5.jpg"
];
// DOM Elements
const signInBtn = document.getElementById('sign-in-btn');
const userProfile = document.getElementById('user-profile');
const userName = document.getElementById('user-name');
const userAvatar = document.getElementById('user-avatar');
const imageUpload = document.getElementById('image-upload');
const zipUpload = document.getElementById('zip-upload');
const imageInput = document.getElementById('image-input');
const zipInput = document.getElementById('zip-input');
const imagePreviewContainer = document.getElementById('image-preview-container');
const imageCarousel = document.getElementById('image-carousel');
const imageCount = document.getElementById('image-count');
const clearImagesBtn = document.getElementById('clear-images');
const trainModelSection = document.getElementById('train-model-section');
const trainModelBtn = document.getElementById('train-model-btn');
const trainingProgress = document.getElementById('training-progress');
const progressBar = document.getElementById('progress-bar');
const progressPercent = document.getElementById('progress-percent');
const resultsSection = document.getElementById('results-section');
const generatedAvatar = document.getElementById('generated-avatar');
const avatarPlaceholder = document.getElementById('avatar-placeholder');
const recreateBtn = document.getElementById('recreate-btn');
const animateSection = document.getElementById('animate-section');
const promptInput = document.getElementById('prompt-input');
const generateVideoBtn = document.getElementById('generate-video-btn');
const videoLoading = document.getElementById('video-loading');
const videoPreview = document.getElementById('video-preview');
const pricingSection = document.getElementById('pricing-section');
const planCards = document.querySelectorAll('.plan-card');
const planConfirmation = document.getElementById('plan-confirmation');
const toast = document.getElementById('toast');
const toastMessage = document.getElementById('toast-message');
// State
let selectedImages = [];
let currentAvatarIndex = 0;
let selectedPlan = 'free';
// Event Listeners
signInBtn.addEventListener('click', () => googleSignIn());
signOutBtn.addEventListener('click', handleSignOut);
document.getElementById('guest-btn').addEventListener('click', () => {
signInBtn.classList.add('hidden');
document.getElementById('guest-btn').classList.add('hidden');
document.getElementById('logout-guest-btn').classList.remove('hidden');
userProfile.classList.add('hidden');
document.getElementById('create').classList.remove('hidden');
});
document.getElementById('logout-guest-btn').addEventListener('click', () => {
document.getElementById('logout-guest-btn').classList.add('hidden');
signInBtn.classList.remove('hidden');
document.getElementById('guest-btn').classList.remove('hidden');
document.getElementById('create').classList.add('hidden');
clearImages();
window.scrollTo({ top: 0, behavior: 'smooth' });
});
document.getElementById('upgrade-pro-btn').addEventListener('click', startProCheckout);
imageUpload.addEventListener('click', () => imageInput.click());
zipUpload.addEventListener('click', () => zipInput.click());
imageInput.addEventListener('change', handleImageUpload);
zipInput.addEventListener('change', handleZipUpload);
clearImagesBtn.addEventListener('click', clearImages);
trainModelBtn.addEventListener('click', trainModel);
recreateBtn.addEventListener('click', recreateAvatar);
generateVideoBtn.addEventListener('click', generateVideo);
planCards.forEach(card => card.addEventListener('click', () => selectPlan(card.dataset.plan)));
document.querySelectorAll('.share-btn').forEach(btn => btn.addEventListener('click', showToast));
// Functions
function initiateRazorpay() {
const options = {
key: "rzp_test_1234567890", // replace with live key for prod
amount: 1900, // Rs 19 in paise
currency: "INR",
name: "OhamLab Pro",
description: "Upgrade to Pro plan",
handler: async function (response) {
// response.razorpay_payment_id is the successful payment id
const res = await fetch(CONFIG.endpoints.updatePlan, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ plan: "pro", payment_id: response.razorpay_payment_id })
});
if (res.ok) {
showToast("Payment successful! You are now on Pro.");
selectPlan("pro");
} else {
showToast("Payment recorded but plan update failed.");
}
},
prefill: { email: "user@example.com" },
theme: { color: "#667eea" }
};
const razorpay = new Razorpay(options);
razorpay.open();
}
// Google OAuth
function googleSignIn() {
google.accounts.id.initialize({
client_id: CONFIG.googleClientId,
callback: handleCredentialResponse
});
google.accounts.id.prompt();
}
// After user picks a Google account
async function handleCredentialResponse(response) {
try {
const res = await fetch(CONFIG.endpoints.oauthLogin, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ credential: response.credential })
});
const data = await res.json();
if (res.ok && data.user) {
signInBtn.classList.add('hidden');
userProfile.classList.remove('hidden');
userName.textContent = data.user.name;
userAvatar.src = data.user.picture;
document.getElementById('create').classList.remove('hidden');
} else {
showToast("Login failed");
}
} catch (err) {
console.error(err);
showToast("Login error");
}
}
// Stripe Checkout for Pro plan
async function startProCheckout() {
initiateRazorpay();
}
function handleSignOut() {
signInBtn.classList.remove('hidden');
userProfile.classList.add('hidden');
// Hide upload section and clear any uploaded images
document.getElementById('create').classList.add('hidden');
clearImages();
// Scroll back to top
window.scrollTo({
top: 0,
behavior: 'smooth'
});
}
async function handleImageUpload(e) {
const files = Array.from(e.target.files);
if (files.length < 5) {
alert('Please upload at least 5 images');
return;
}
selectedImages = files.slice(0, 5); // Limit to 5 images
updateImagePreview();
// Show loading spinner
const uploadSpinner = document.createElement('div');
uploadSpinner.className = 'inline-block animate-spin rounded-full h-6 w-6 border-t-2 border-b-2 border-indigo-500';
imageUpload.innerHTML = '';
imageUpload.appendChild(uploadSpinner);
try {
const formData = new FormData();
selectedImages.forEach(file => formData.append('files', file));
const res = await fetch(CONFIG.endpoints.uploadImages, {
method: "POST",
body: formData,
});
if (!res.ok) throw new Error('Upload failed');
const data = await res.json();
// Restore upload area with success message
imageUpload.innerHTML = `
<i class="fas fa-check-circle text-green-500 text-4xl mb-4"></i>
<h3 class="text-lg font-medium text-gray-700 mb-2">Upload Complete</h3>
<p class="text-gray-500 mb-4">${selectedImages.length} images uploaded successfully</p>
`;
// Show the train model button
trainModelSection.classList.remove('hidden');
showToast('Images uploaded successfully!');
} catch (err) {
console.error('Upload error:', err);
// Restore original upload area
imageUpload.innerHTML = `
<i class="fas fa-images text-indigo-500 text-4xl mb-4"></i>
<h3 class="text-lg font-medium text-gray-700 mb-2">Upload Images</h3>
<p class="text-gray-500 mb-4">Upload at least 5 images of yourself from different angles</p>
<button class="bg-indigo-100 text-indigo-600 px-4 py-2 rounded-full text-sm font-medium">
Select Files
</button>
`;
showToast('Upload failed. Please try again.');
}
}
async function handleZipUpload(e) {
if (e.target.files.length > 0) {
// Show loading spinner
const uploadSpinner = document.createElement('div');
uploadSpinner.className = 'inline-block animate-spin rounded-full h-6 w-6 border-t-2 border-b-2 border-purple-500';
zipUpload.innerHTML = '';
zipUpload.appendChild(uploadSpinner);
try {
const formData = new FormData();
formData.append('zip', e.target.files[0]);
const res = await fetch("https://rahul7star-ohamlab-ai-toolkit.hf.space/upload-zip", {
method: "POST",
body: formData,
});
if (!res.ok) throw new Error('ZIP upload failed');
// Restore upload area with success message
zipUpload.innerHTML = `
<i class="fas fa-check-circle text-green-500 text-4xl mb-4"></i>
<h3 class="text-lg font-medium text-gray-700 mb-2">Upload Complete</h3>
<p class="text-gray-500 mb-4">ZIP file uploaded successfully</p>
`;
// Show the train model button
trainModelSection.classList.remove('hidden');
showToast("ZIP file uploaded successfully!");
} catch (err) {
console.error('ZIP upload error:', err);
// Restore original upload area
zipUpload.innerHTML = `
<i class="fas fa-file-archive text-purple-500 text-4xl mb-4"></i>
<h3 class="text-lg font-medium text-gray-700 mb-2">Upload ZIP File</h3>
<p class="text-gray-500 mb-4">Compress your images into a single .zip file</p>
<button class="bg-purple-100 text-purple-600 px-4 py-2 rounded-full text-sm font-medium">
Select ZIP File
</button>
`;
showToast('ZIP upload failed. Please try again.');
}
}
}
function updateImagePreview() {
imageCarousel.innerHTML = '';
imageCount.textContent = selectedImages.length;
selectedImages.forEach((file, index) => {
const reader = new FileReader();
reader.onload = (e) => {
const imgContainer = document.createElement('div');
imgContainer.className = 'flex-shrink-0 relative';
const img = document.createElement('img');
img.src = e.target.result;
img.className = 'w-24 h-24 rounded-lg object-cover';
img.alt = `Preview ${index + 1}`;
imgContainer.appendChild(img);
imageCarousel.appendChild(imgContainer);
};
reader.readAsDataURL(file);
});
imagePreviewContainer.classList.remove('hidden');
}
function clearImages() {
selectedImages = [];
imageInput.value = '';
imagePreviewContainer.classList.add('hidden');
trainModelSection.classList.add('hidden');
}
async function trainModel() {
// Show training progress
trainingProgress.classList.remove('hidden');
trainModelSection.classList.add('hidden');
try {
const data = "test"
console.log('Training started:', data);
let progress = 0;
const targetDuration = 30 * 60 * 1000; // 30 minutes in milliseconds
const intervalDuration = 2000; // Update every 2 seconds
const totalTicks = targetDuration / intervalDuration;
const incrementPerTick = 100 / totalTicks;
const interval = setInterval(() => {
progress += incrementPerTick;
if (progress >= 100) progress = 100;
progressBar.style.width = `${progress}%`;
progressPercent.textContent = `${Math.floor(progress)}%`;
if (progress === 100) {
clearInterval(interval);
setTimeout(() => {
trainingProgress.classList.add('hidden');
showResults();
}, 500);
}
}, intervalDuration);
} catch (err) {
console.error('Training error:', err);
showToast('Training failed. Please try again.');
trainingProgress.classList.add('hidden');
trainModelSection.classList.remove('hidden');
}
}
function showResults() {
resultsSection.classList.remove('hidden');
animateSection.classList.remove('hidden');
currentAvatarIndex = 0;
displayGeneratedAvatar();
}
function displayGeneratedAvatar() {
avatarPlaceholder.classList.add('hidden');
generatedAvatar.classList.remove('hidden');
generatedAvatar.src = mockAvatars[currentAvatarIndex];
}
function recreateAvatar() {
avatarPlaceholder.classList.remove('hidden');
generatedAvatar.classList.add('hidden');
// Simulate loading
setTimeout(() => {
currentAvatarIndex = (currentAvatarIndex + 1) % mockAvatars.length;
displayGeneratedAvatar();
showToast("New avatar generated!");
}, 800);
}
async function generateVideo() {
if (!promptInput.value.trim()) {
showToast("Please enter a prompt first");
return;
}
videoLoading.classList.remove('hidden');
videoPreview.classList.add('hidden');
// Mock API call
try {
const res = await fetch(CONFIG.endpoints.generateVideo, {
method: "POST",
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
prompt: promptInput.value.trim()
})
});
if (!res.ok) throw new Error('Video generation failed');
const data = await res.json();
console.log('Video generated:', data);
videoLoading.classList.add('hidden');
videoPreview.classList.remove('hidden');
showToast("Video generated successfully!");
} catch (err) {
console.error('Video generation error:', err);
showToast('Video generation failed. Please try again.');
videoLoading.classList.add('hidden');
}
}
async function selectPlan(plan) {
selectedPlan = plan;
// Mock API call
try {
const res = await fetch(CONFIG.endpoints.updatePlan, {
method: "POST",
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
plan: plan
})
});
if (!res.ok) throw new Error('Plan update failed');
const data = await res.json();
console.log('Plan updated:', data);
// Update UI
planCards.forEach(card => {
if (card.dataset.plan === plan) {
card.classList.add('selected-plan');
card.querySelector('button').classList.add('bg-indigo-600', 'text-white');
card.querySelector('button').classList.remove('border-gray-300', 'text-gray-700');
} else {
card.classList.remove('selected-plan');
card.querySelector('button').classList.remove('bg-indigo-600', 'text-white');
card.querySelector('button').classList.add('border-gray-300', 'text-gray-700');
}
});
// Show confirmation
planConfirmation.classList.remove('hidden');
setTimeout(() => {
planConfirmation.classList.add('hidden');
}, 3000);
} catch (err) {
console.error('Plan update error:', err);
showToast('Plan update failed. Please try again.');
}
}
function showToast(message) {
toastMessage.textContent = message;
toast.classList.remove('hidden');
setTimeout(() => {
toast.classList.add('hidden');
}, 3000);
}
// Navigation functionality
document.querySelectorAll('.nav-link').forEach(link => {
link.addEventListener('click', (e) => {
e.preventDefault();
const targetId = link.getAttribute('href').substring(1);
const targetElement = document.getElementById(targetId);
if (targetElement) {
window.scrollTo({
top: targetElement.offsetTop - 80,
behavior: 'smooth'
});
}
});
});
// Get Started button
document.getElementById('get-started-btn').addEventListener('click', () => {
document.getElementById('sign-in-btn').click();
});
// Mobile menu toggle (placeholder - would need additional HTML/CSS)
document.getElementById('mobile-menu-button').addEventListener('click', () => {
showToast("Mobile menu would open here");
});
// Page view counter
const pageCounter = document.getElementById('page-counter');
let views = localStorage.getItem('pageViews') || 0;
views++;
localStorage.setItem('pageViews', views);
pageCounter.textContent = views;
// Scroll navigation
const scrollNav = document.getElementById('scroll-nav');
const scrollUpBtn = document.getElementById('scroll-up-btn');
const scrollDownBtn = document.getElementById('scroll-down-btn');
const sections = ['home', 'features', 'create', 'pricing'];
let currentIndex = 0;
// Demo toggle functionality
document.getElementById('demo-toggle').addEventListener('click', () => {
const promoSection = document.getElementById('social-promo');
const iframe = promoSection.querySelector('iframe');
promoSection.classList.toggle('hidden');
if (!promoSection.classList.contains('hidden')) {
// Load video when showing
iframe.src = iframe.dataset.src + '&autoplay=1';
// Scroll to the promo section
promoSection.scrollIntoView({ behavior: 'smooth' });
} else {
// Unload video when hiding
iframe.src = 'about:blank';
}
});
</script></body>
</html>