/
Valeriannna
/
SchoolActive
Обзор
Документация
Войти
/
Valeriannna
/
SchoolActive
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
script.js
196 строк
7 KB
Valeriannna
upload files
15 сен 2025, 10:54
15 сен 2025, 10:54
bbebaeb
Код
Авторство
О чём код?
// Modern JS module. Uses Firestore and Auth. import { initializeApp } from "https://www.gstatic.com/firebasejs/10.12.2/firebase-app.js"; import { getAuth, GoogleAuthProvider, signInWithPopup, signOut, onAuthStateChanged } from "https://www.gstatic.com/firebasejs/10.12.2/firebase-auth.js"; import { getFirestore, collection, addDoc, query, where, orderBy, onSnapshot, getDocs } from "https://www.gstatic.com/firebasejs/10.12.2/firebase-firestore.js"; import { getStorage, ref as sref, uploadBytes, getDownloadURL } from "https://www.gstatic.com/firebasejs/10.12.2/firebase-storage.js"; // ----- FIREBASE CONFIG (вставлен ваш конфиг) const firebaseConfig = { apiKey: "AIzaSyBwvbImLNO95_sYS2utr6BtXfW04_MNmQc", authDomain: "schoolactive-8abce.firebaseapp.com", projectId: "schoolactive-8abce", storageBucket: "schoolactive-8abce.firebasestorage.app", messagingSenderId: "112505692044", appId: "1:112505692044:web:d6adfb858c8ec55dcc80a9", measurementId: "G-XB36R8J523" }; // init const app = initializeApp(firebaseConfig); const auth = getAuth(app); const db = getFirestore(app); const storage = getStorage(app); // ui const signinBtn = document.getElementById('signin'); const signoutBtn = document.getElementById('signout'); const userInfo = document.getElementById('user-info'); const userNameSpan = document.getElementById('user-name'); const userPhoto = document.getElementById('user-photo'); const messageInput = document.getElementById('message-input'); const sendBtn = document.getElementById('send'); const messagesDiv = document.getElementById('messages'); const leaderboardDiv = document.getElementById('leaderboard'); const teamNameInput = document.getElementById('team-name'); const createTeamBtn = document.getElementById('create-team'); const teamsList = document.getElementById('teams-list'); const currentTeamSpan = document.getElementById('current-team'); const photoInput = document.getElementById('photo-input'); let currentUser = null; let currentTeamId = null; // AUTH signinBtn.addEventListener('click', async ()=>{ const provider = new GoogleAuthProvider(); try { await signInWithPopup(auth, provider); } catch(e){ alert('Ошибка входа: ' + e.message); } }); signoutBtn.addEventListener('click', async ()=>{ await signOut(auth); }); onAuthStateChanged(auth, user=>{ currentUser = user; if(user){ signinBtn.classList.add('hidden'); userInfo.classList.remove('hidden'); userNameSpan.textContent = user.displayName; userPhoto.src = user.photoURL || ''; } else { signinBtn.classList.remove('hidden'); userInfo.classList.add('hidden'); userNameSpan.textContent = ''; userPhoto.src = ''; } }); // TEAMS createTeamBtn.addEventListener('click', async ()=>{ if(!currentUser) return alert('Войдите'); const name = teamNameInput.value.trim(); if(!name) return; try{ await addDoc(collection(db,'teams'), {name, owner: currentUser.uid, createdAt: Date.now()}); teamNameInput.value = ''; }catch(e){console.error(e); alert('Ошибка создания')}; }); const teamsQ = query(collection(db,'teams'), orderBy('createdAt','desc')); onSnapshot(teamsQ, snapshot=>{ teamsList.innerHTML = ''; snapshot.forEach(docu=>{ const t = docu.data(); const id = docu.id; const el = document.createElement('div'); el.className = 'team-item'; el.innerHTML = `<div><strong>${t.name}</strong><div class="muted small">создано ${new Date(t.createdAt).toLocaleString()}</div></div> <div><button class="btn small" data-id="${id}">Открыть</button></div>`; teamsList.appendChild(el); el.querySelector('button').addEventListener('click', ()=> { openTeam(id, t.name); }); }); }); // OPEN TEAM function openTeam(id,name){ currentTeamId = id; currentTeamSpan.textContent = name; // load team messages const msgsQ = query(collection(db,'messages'), where('team','==',id), orderBy('createdAt')); if(window._unsubscribeMessages) window._unsubscribeMessages(); window._unsubscribeMessages = onSnapshot(msgsQ, snapshot=>{ messagesDiv.innerHTML = ''; snapshot.forEach(docu=>{ const m = docu.data(); const div = document.createElement('div'); div.className = 'msg' + (m.uid === (currentUser && currentUser.uid) ? ' me' : ''); let html = `<div><strong>${m.name}</strong> <span class="muted small">· ${new Date(m.createdAt).toLocaleTimeString()}</span></div>`; html += `<div>${escapeHtml(m.text || '')}</div>`; if(m.photoURL) html += `<div><img src="${m.photoURL}" style="max-width:220px;border-radius:8px;margin-top:8px"></div>`; div.innerHTML = html; messagesDiv.appendChild(div); }); messagesDiv.scrollTop = messagesDiv.scrollHeight; }); } // SEND MESSAGE sendBtn.addEventListener('click', async ()=>{ if(!currentUser) return alert('Войдите'); if(!currentTeamId) return alert('Выберите команду'); const text = messageInput.value.trim(); if(!text && !photoInput.files.length) return; let photoURL = null; if(photoInput.files.length){ const file = photoInput.files[0]; const ref = sref(storage, `photos/${Date.now()}_${file.name}`); await uploadBytes(ref, file); photoURL = await getDownloadURL(ref); photoInput.value = ''; } await addDoc(collection(db,'messages'), { uid: currentUser.uid, name: currentUser.displayName, team: currentTeamId, text, photoURL: photoURL || null, createdAt: Date.now() }); messageInput.value = ''; }); // POINTS window.addPoints = async (amount)=>{ if(!currentUser) return alert('Войдите'); await addDoc(collection(db,'points'), { uid: currentUser.uid, name: currentUser.displayName, points: amount, team: currentTeamId || null, createdAt: Date.now() }); }; // LEADERBOARD const pointsQ = query(collection(db,'points'), orderBy('createdAt')); onSnapshot(pointsQ, snapshot=>{ const map = {}; snapshot.forEach(d=>{ const p = d.data(); map[p.name] = (map[p.name] || 0) + (p.points || 0); }); leaderboardDiv.innerHTML = ''; Object.entries(map).sort((a,b)=>b[1]-a[1]).forEach(([name,pts])=>{ const el = document.createElement('div'); el.innerHTML = `<span>${name}</span><strong>${pts} ⸱</strong>`; leaderboardDiv.appendChild(el); }); }); // UTILS function escapeHtml(str){ return str.replace(/[&<>"']/g, s=>({ '&':'&','<':'<','>':'>','"':'"',"'":''' }[s])); } // QUICK: preload open first team if exists (async function(){ try{ const docs = await getDocs(query(collection(db,'teams'), orderBy('createdAt','desc'))); if(!docs.empty){ const first = docs.docs[0]; openTeam(first.id, first.data().name); } }catch(e){ console.log('no teams yet') } })(); // photo input handling (optional quick upload) photoInput.addEventListener('change', ()=> { // small visual cue could be added });