loom3 / index.html
droplyvictor89's picture
Upload 6 files
1b1667b verified
<!DOCTYPE html>
<html lang="ro">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<meta name="theme-color" content="#0a0a0a">
<meta name="apple-mobile-web-app-capable" content="yes">
<title>Loom</title>
<link rel="icon" type="image/svg+xml" href="logo.svg">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Playfair+Display:ital,wght@0,600;1,400&display=swap" rel="stylesheet">
<script type="module">
import{initializeApp}from'https://www.gstatic.com/firebasejs/10.12.0/firebase-app.js';
import{getAuth,createUserWithEmailAndPassword,signInWithEmailAndPassword,onAuthStateChanged,signOut,updateProfile}from'https://www.gstatic.com/firebasejs/10.12.0/firebase-auth.js';
import{getFirestore,collection,doc,setDoc,getDoc,getDocs,addDoc,updateDoc,deleteDoc,onSnapshot,query,where,orderBy,serverTimestamp,arrayUnion,arrayRemove,increment}from'https://www.gstatic.com/firebasejs/10.12.0/firebase-firestore.js';
import{getStorage,ref,uploadString,getDownloadURL}from'https://www.gstatic.com/firebasejs/10.12.0/firebase-storage.js';
const cfg={apiKey:"AIzaSyAy35d5sY7E0yfhkfD-OrENzOA-3OZi4g0",authDomain:"loom-742c0.firebaseapp.com",projectId:"loom-742c0",storageBucket:"loom-742c0.firebasestorage.app",messagingSenderId:"335224128378",appId:"1:335224128378:web:fd99ab19fd72dfc8b50cc3"};
const app=initializeApp(cfg);
window.FB={
auth:getAuth(app),db:getFirestore(app),storage:getStorage(app),
createUserWithEmailAndPassword,signInWithEmailAndPassword,onAuthStateChanged,signOut,updateProfile,
collection,doc,setDoc,getDoc,getDocs,addDoc,updateDoc,deleteDoc,onSnapshot,query,where,orderBy,serverTimestamp,arrayUnion,arrayRemove,increment
};
window.dispatchEvent(new Event('firebase-ready'));
</script>
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- ═══ AUTH ═══ -->
<div id="auth-screen" class="hidden">
<div class="auth-card">
<div class="auth-logo">
<img src="logo.svg" class="auth-logo-img" alt="">
<span class="logo-text font-serif">Loom</span>
</div>
<p class="auth-tagline">Conectează-te cu lumea ta</p>
<div class="auth-tabs">
<button class="auth-tab active" onclick="switchAuthTab('login')">Autentificare</button>
<button class="auth-tab" onclick="switchAuthTab('register')">Înregistrare</button>
</div>
<div id="login-form" class="auth-form">
<div class="input-group">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
<input type="text" id="li-user" placeholder="Utilizator sau email" autocomplete="username">
</div>
<div class="input-group">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
<input type="password" id="li-pass" placeholder="Parolă" autocomplete="current-password" onkeydown="if(event.key==='Enter')handleLogin()">
</div>
<button class="btn-primary" onclick="handleLogin()">
<span id="li-text">Autentificare</span>
<span id="li-spin" class="btn-spinner hidden"></span>
</button>
</div>
<div id="register-form" class="auth-form hidden">
<div class="input-group">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
<input type="text" id="re-name" placeholder="Nume complet">
</div>
<div class="input-group">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
<input type="text" id="re-user" placeholder="Nume de utilizator">
</div>
<div class="input-group">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>
<input type="email" id="re-email" placeholder="Email">
</div>
<div class="input-group">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
<input type="password" id="re-pass" placeholder="Parolă (min. 6 caractere)" onkeydown="if(event.key==='Enter')handleRegister()">
</div>
<button class="btn-primary" onclick="handleRegister()">
<span id="re-text">Creează cont</span>
<span id="re-spin" class="btn-spinner hidden"></span>
</button>
</div>
<p class="auth-error hidden" id="auth-error"></p>
</div>
</div>
<!-- ═══ APP ═══ -->
<div id="app" class="hidden">
<!-- MAIN CONTENT -->
<main class="main-content">
<!-- FEED -->
<div id="pg-feed" class="page active">
<div class="page-header">
<h1 class="page-title font-serif">Feed</h1>
<div class="header-actions">
<button class="icon-btn" onclick="openNewPost()" title="Post nou">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
</button>
</div>
</div>
<div class="stories-section">
<div class="stories-scroll" id="stories-scroll">
<div class="story-item" id="my-story-add" onclick="openAddStory()">
<div class="story-ring add-ring">
<div class="avatar sm" id="my-story-av"></div>
<div class="add-story-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
</div>
</div>
<span class="story-label">Story tău</span>
</div>
</div>
</div>
<div id="feed-posts">
<div class="skeleton-post"></div>
<div class="skeleton-post"></div>
</div>
</div>
<!-- CHAT -->
<div id="pg-chat" class="page">
<div class="chat-layout" id="chat-layout">
<div class="chat-sidebar">
<div class="chat-sidebar-header">
<h2 class="font-serif">Mesaje</h2>
<button class="icon-btn" onclick="openNewChat()">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
</button>
</div>
<div class="chat-search-area">
<div class="search-bar">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
<input type="text" id="chat-search-input" placeholder="Caută..." oninput="filterChats()">
</div>
</div>
<div class="chat-tabs-row">
<button class="chat-tab active" onclick="switchChatTab('all',this)">Toate</button>
<button class="chat-tab" onclick="switchChatTab('secret',this)">Secret</button>
<button class="chat-tab" onclick="switchChatTab('hidden',this)">Ascuns</button>
</div>
<div class="chat-list-scroll" id="chat-list"></div>
</div>
<div class="chat-main" id="chat-main">
<div class="chat-empty-state">
<div class="chat-empty-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
</div>
<p>Selectează o conversație</p>
<span>sau începe una nouă →</span>
</div>
</div>
</div>
</div>
<!-- NOTIFICĂRI -->
<div id="pg-notifications" class="page">
<div class="page-header">
<h1 class="page-title font-serif">Notificări</h1>
<button class="icon-btn" onclick="clearAllNotifications()" title="Șterge tot">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg>
</button>
</div>
<div class="notif-list" id="notif-list"></div>
</div>
<!-- EXPLORARE -->
<div id="pg-explore" class="page">
<div class="page-header">
<h1 class="page-title font-serif">Explorare</h1>
</div>
<div class="explore-search-wrap">
<div class="search-bar large">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
<input type="text" id="explore-input" placeholder="Caută utilizatori..." oninput="searchUsers()">
</div>
</div>
<div id="explore-results"></div>
<div class="explore-section">
<p class="section-label">Toți utilizatorii</p>
<div id="explore-suggested"></div>
</div>
</div>
<!-- PROFIL -->
<div id="pg-profile" class="page">
<div id="profile-content"></div>
</div>
</main>
<!-- NAVBAR JOS -->
<nav class="bottom-nav">
<div class="nav-item active" data-page="feed" onclick="navigateTo('feed')">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>
<span>Feed</span>
</div>
<div class="nav-item" data-page="chat" onclick="navigateTo('chat')">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
<span>Mesaje</span>
<div class="nav-badge hidden" id="msg-badge">0</div>
</div>
<div class="nav-item" data-page="notifications" onclick="navigateTo('notifications')">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg>
<span>Notificări</span>
<div class="nav-badge hidden" id="notif-badge">0</div>
</div>
<div class="nav-item" data-page="explore" onclick="navigateTo('explore')">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
<span>Explorare</span>
</div>
<div class="nav-item" data-page="profile" onclick="navigateTo('profile')">
<div class="nav-av-wrap">
<div class="avatar xs" id="sb-avatar"></div>
</div>
<span>Profil</span>
</div>
</nav>
</div><!-- /app -->
<!-- ═══ MODALS ═══ -->
<!-- POST NOU -->
<div class="modal-overlay hidden" id="new-post-modal" onclick="if(event.target===this)closeModal('new-post-modal')">
<div class="modal">
<div class="modal-header">
<h2 class="font-serif">Post Nou</h2>
<button class="modal-close" onclick="closeModal('new-post-modal')"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button>
</div>
<div class="modal-body">
<div class="composer-row">
<div class="avatar sm" id="composer-av"></div>
<textarea id="post-text-input" class="post-textarea" placeholder="Ce gândești?" rows="3"></textarea>
</div>
<div id="post-img-preview" class="hidden"></div>
<div class="composer-toolbar">
<label class="toolbar-btn">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>
Foto
<input type="file" accept="image/*" id="post-img-input" onchange="previewPostImg()" hidden>
</label>
</div>
<button class="btn-primary" onclick="submitPost()">Publică ✦</button>
</div>
</div>
</div>
<!-- ADAUGĂ STORY -->
<div class="modal-overlay hidden" id="add-story-modal" onclick="if(event.target===this)closeModal('add-story-modal')">
<div class="modal">
<div class="modal-header">
<h2 class="font-serif">Adaugă Story</h2>
<button class="modal-close" onclick="closeModal('add-story-modal')"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button>
</div>
<div class="modal-body">
<label class="upload-area" id="story-upload-label">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>
<span>Apasă pentru a selecta o poză</span>
<input type="file" accept="image/*" id="story-img-input" onchange="previewStory()" hidden>
</label>
<div id="story-preview" class="hidden story-preview-wrap"><img id="story-preview-img" alt=""></div>
<input type="text" id="story-text-input" class="auth-input" placeholder="Adaugă text (opțional)">
<button class="btn-primary" onclick="submitStory()">Distribuie Story</button>
</div>
</div>
</div>
<!-- VIZUALIZATOR STORY -->
<div class="story-viewer hidden" id="story-viewer">
<div class="story-bg" id="sv-bg"></div>
<div class="story-progress-bar"><div class="story-progress" id="sv-prog"></div></div>
<div class="story-top-bar">
<div class="story-user-info">
<div class="avatar sm" id="sv-avatar"></div>
<div><p class="sv-name" id="sv-name"></p><p class="sv-time" id="sv-time"></p></div>
</div>
<button class="sv-close" onclick="closeStoryViewer()"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button>
</div>
<img class="story-img" id="sv-img" alt="">
<p class="story-caption" id="sv-caption"></p>
<div class="story-nav-l" onclick="prevStory()"></div>
<div class="story-nav-r" onclick="nextStory()"></div>
<div class="story-viewers hidden" id="sv-viewers">
<p class="sv-viewers-label">Vizualizatori</p>
<div id="sv-viewers-list"></div>
</div>
</div>
<!-- COMENTARII -->
<div class="modal-overlay hidden" id="comments-modal" onclick="if(event.target===this)closeModal('comments-modal')">
<div class="modal tall-modal">
<div class="modal-header">
<h2 class="font-serif">Comentarii</h2>
<button class="modal-close" onclick="closeModal('comments-modal')"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button>
</div>
<div class="comments-list" id="comments-list"></div>
<div class="comment-compose">
<div class="avatar xs" id="comment-avatar"></div>
<input type="text" id="comment-input" class="comment-field" placeholder="Adaugă un comentariu..." onkeydown="if(event.key==='Enter')submitComment()">
<button class="send-icon-btn" onclick="submitComment()"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg></button>
</div>
</div>
</div>
<!-- SETĂRI -->
<div class="modal-overlay hidden" id="settings-modal" onclick="if(event.target===this)closeModal('settings-modal')">
<div class="modal">
<div class="modal-header">
<h2 class="font-serif">Setări</h2>
<button class="modal-close" onclick="closeModal('settings-modal')"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button>
</div>
<div class="modal-body">
<div class="settings-avatar-wrap">
<label style="cursor:pointer;position:relative">
<div class="avatar lg" id="settings-avatar"></div>
<div class="change-avatar-overlay"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/><circle cx="12" cy="13" r="4"/></svg></div>
<input type="file" accept="image/*" id="avatar-upload" onchange="changeAvatar()" hidden>
</label>
<p class="settings-avatar-hint">Apasă pentru a schimba poza</p>
</div>
<input type="text" id="settings-name" class="auth-input" placeholder="Nume complet">
<input type="text" id="settings-bio" class="auth-input" placeholder="Bio (opțional)">
<div class="toggle-row">
<div><p class="toggle-label">Cont privat</p><p class="toggle-sub">Doar urmăritorii aprobați îți văd postările</p></div>
<div class="toggle" id="private-toggle" onclick="this.classList.toggle('on')"><div class="toggle-knob"></div></div>
</div>
<button class="btn-primary" onclick="saveSettings()">Salvează</button>
<button class="btn-ghost" onclick="handleLogout()"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg>Deconectare</button>
</div>
</div>
</div>
<!-- CHAT NOU -->
<div class="modal-overlay hidden" id="new-chat-modal" onclick="if(event.target===this)closeModal('new-chat-modal')">
<div class="modal">
<div class="modal-header">
<h2 class="font-serif">Mesaj Nou</h2>
<button class="modal-close" onclick="closeModal('new-chat-modal')"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button>
</div>
<div class="modal-body">
<div class="search-bar"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg><input type="text" id="new-chat-search" placeholder="Caută utilizatori..." oninput="searchNewChat()"></div>
<div id="new-chat-results"></div>
<div class="toggle-row">
<div><p class="toggle-label">Chat Secret</p><p class="toggle-sub">Apare criptat, ascuns din listă</p></div>
<div class="toggle" id="secret-toggle" onclick="this.classList.toggle('on')"><div class="toggle-knob"></div></div>
</div>
</div>
</div>
</div>
<!-- VERIFICARE -->
<div class="modal-overlay hidden" id="verify-modal" onclick="if(event.target===this)closeModal('verify-modal')">
<div class="modal">
<div class="modal-header">
<h2 class="font-serif">Verifică Contul</h2>
<button class="modal-close" onclick="closeModal('verify-modal')"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button>
</div>
<div class="modal-body">
<div id="verify-step-1">
<p class="modal-desc">Trimite detaliile tale pentru a solicita verificarea de la creator.</p>
<input type="email" id="verify-email" class="auth-input" placeholder="Adresă de email">
<input type="tel" id="verify-phone" class="auth-input" placeholder="Număr de telefon">
<input type="text" id="verify-realname" class="auth-input" placeholder="Nume real">
<button class="btn-primary" onclick="submitVerifyRequest()">Solicită Verificarea</button>
</div>
<div id="verify-step-2" class="hidden">
<p class="modal-desc">Introdu codul de 6 cifre trimis de creator.</p>
<div class="code-grid">
<input type="text" maxlength="1" class="code-box" oninput="codeNext(this,0)" onkeydown="codeBack(event,this,0)">
<input type="text" maxlength="1" class="code-box" oninput="codeNext(this,1)" onkeydown="codeBack(event,this,1)">
<input type="text" maxlength="1" class="code-box" oninput="codeNext(this,2)" onkeydown="codeBack(event,this,2)">
<input type="text" maxlength="1" class="code-box" oninput="codeNext(this,3)" onkeydown="codeBack(event,this,3)">
<input type="text" maxlength="1" class="code-box" oninput="codeNext(this,4)" onkeydown="codeBack(event,this,4)">
<input type="text" maxlength="1" class="code-box" oninput="codeNext(this,5)" onkeydown="codeBack(event,this,5)">
</div>
<button class="btn-primary" onclick="submitVerifyCode()">Confirmă Codul</button>
</div>
</div>
</div>
</div>
<!-- PIN -->
<div class="modal-overlay hidden" id="pin-modal" onclick="if(event.target===this)closeModal('pin-modal')">
<div class="modal small-modal">
<div class="modal-header">
<h2 class="font-serif">Protejat 🔒</h2>
<button class="modal-close" onclick="closeModal('pin-modal')"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button>
</div>
<div class="modal-body">
<p class="modal-desc">Introdu PIN-ul pentru a debloca acest chat</p>
<input type="password" id="pin-input" class="auth-input" placeholder="PIN" maxlength="6" onkeydown="if(event.key==='Enter')submitPin()">
<button class="btn-primary" onclick="submitPin()">Deblochează</button>
</div>
</div>
</div>
<!-- STREAK -->
<div class="streak-overlay hidden" id="streak-modal">
<div class="streak-card">
<div class="streak-emoji">🔥</div>
<h2 class="streak-title font-serif" id="streak-title"></h2>
<p class="streak-desc" id="streak-desc"></p>
<button class="btn-primary" onclick="closeStreakModal()">Super! 🎉</button>
</div>
</div>
<!-- TOAST -->
<div class="toast hidden" id="toast-el"></div>
<script src="app.js"></script>
</body>
</html>