RT
Ryo Takeshi

App - Copy this React, Tailwind Component to your project

Thêm cho tôi giao diện đăng nhập sau khi đăng nhập sẽ hiện như code bên dưới <!DOCTYPE html><html lang="vi"> <head> <meta charset="UTF 8" /> <meta name="viewport" content="width=device width, initial scale=1.0"/> <title>Vote Ending</title> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <! Add Firebase SDK > <script src="https://www.gstatic.com/firebasejs/8.10.0/firebase app.js"></script> <script src="https://www.gstatic.com/firebasejs/8.10.0/firebase database.js"></script> <! Add Social Share Buttons > <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font awesome/6.0.0/css/all.min.css"> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Baloo+2:wght@400..800&display=swap" rel="stylesheet"> <style> body { font family: 'Baloo 2', sans serif; margin: 0; padding: 0; background color: #0d0d0d; color: #121212; transition: all 0.3s ease; } body.light mode { background color: #fdfdfd; color: #1a1a1a; } * { transition: background color 0.3s ease, color 0.3s ease; box sizing: border box; } #mode toggle { position: fixed; top: 16px; right: 16px; font size: 24px; cursor: pointer; z index: 999; transition: transform 0.2s ease; } #mode toggle:hover { transform: scale(1.2); } .container { max width: 600px; margin: 40px auto; padding: 24px; background: #FBFBFB; border radius: 20px; box shadow: 0 4px 20px rgba(0,0,0,0.1); } body.light mode .container { background: #fff; } h1, h2, h3, h4, h5 { text align: center; margin: 0.5em 0; } .note, .message, .footer note { border radius: 8px; padding: 12px; margin: 16px 0; font size: 14px; } .note { background color: #fff7f0; border left: 4px solid #ff6f61; color: #121212; } .message { background color: #fff7f0; border left: 4px solid #F9B57D; color: #121212; } .footer note { background color: #f5f5f5; text align: center; color: #121212; } .vote buttons { display: flex; justify content: space around; flex wrap: wrap; margin: 20px 0; } .vote btn { background: #f2f2f2; color: #000; padding: 12px 16px; border radius: 12px; font weight: bold; cursor: pointer; border: none; font size: 16px; margin: 8px; } .vote btn2 { background: #f2f2f2; color: #000; padding: 12px 16px; border radius: 12px; font weight: bold; cursor: pointer; border: none; font size: 16px; margin: 8px; } .vote btn:hover { transform: scale(1.05); color: #343434; background: #A4FF36; } .vote btn2:hover { transform: scale(1.05); color: #343434; background: #FC3A3D; } .result { text align: center; margin: 20px 0; display: none; } .lang select { text align: center; margin top: 8px; font size: 14px; } select { padding: 4px 8px; border radius: 8px; font size: 14px; } .chart box { margin top: 20px; } canvas { width: 100% !important; height: auto !important; } #votePopup { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.6); z index: 999; justify content: center; align items: center; animation: fadeIn 0.4s ease; } #votePopup .popup content { background: #ffffff; padding: 24px; border radius: 20px; width: "fit content"; max width: "fit content"; text align: center; box shadow: 0 4px 16px rgba(0,0,0,0.2); animation: popUp 0.4s ease; } @keyframes fadeIn { from { opacity: 0 } to { opacity: 1 } } @keyframes popUp { from { transform: scale(0.9); opacity: 0 } to { transform: scale(1); opacity: 1 } } @media (max width: 768px) { .container { margin: 16px; padding: 16px; } .vote buttons { flex direction: column; align items: center; } .vote btn { width: 100%; max width: 300px; } } .baloo1 { font weight: 700; text align: center; } .baloo2 { font weight: 700; text align: right; } /* Social Share Buttons */ .share buttons { display: flex; justify content: center; margin top: 20px; gap: 10px; } .share btn { width: 40px; height: 40px; border radius: 50%; display: flex; align items: center; justify content: center; color: white; font size: 18px; cursor: pointer; transition: transform 0.2s; } .share btn:hover { transform: scale(1.1); } .facebook { background color: #3b5998; } .twitter { background color: #1da1f2; } .linkedin { background color: #0077b5; } .whatsapp { background color: #25d366; } .telegram { background color: #0088cc; } </style> </head> <body> <div class="container" id="mainContainer"> <div id="mode toggle" title="Chuyển chế độ sáng/tối">🌙</div> <h2 class="baloo1">Chọn kết thúc cho câu chuyện</h2> <div class="note"> <strong>📜 Luật nhỏ xíu trước khi xem video nhé:</strong><br> Bạn chỉ được chọn một kết thúc một lần duy nhất<br> Hãy giữ kết quả ấy cho riêng bạn để người khác cũng có cảm giác trải nghiệm trọn vẹn như bạn<br> <strong>🚫 Đừng spoil nha:</strong><br> Để sự bí ẩn tiếp tục lan tỏa khắp nơi! Ở mỗi ending khác nhau của series </div> <div class="message"> <strong>💌 Lời nhắn nhẹ nhàng từ tụi mình:</strong><br> Vì muốn giữ trọn cảm giác bất ngờ, tụi mình đã giấu video ở một góc nhỏ trên YouTube Shorts cho nên mỗi lựa chọn ending đó là do bạn chọn nè <br> Mọi link ending tụi mình đều để ở phần bio nha!<br> Nếu bạn thấy series này hay ho hãy cho chúng mình: <ul> <li>▶️ 1 Subscribe, 1 Like, 1 Share ở YouTube</li> <li>👍 Like Facebook, 1 Folow&nbsp; &nbsp;</li> <li>🎶 1 Follow TikTok, 1 Tim</li> <li>🗨️ Comment góp hoặc thảo luận với mọi người có cùng ending như bạn ở dưới mỗi video nếu như các bạn thấy hay, không hay hoặc điều gì bọn mình làm chưa tốt để bọn mình mình sẽ cố gắng làm hay hơn tốt hơn, mỗi góp ý là động lực giúp bọn mình làm tốt hơn ở mỗi video sau </li> <li>‼️ Chúng mình hi vọng các bạn xem vui vẻ và góp ý comment và thảo luận với nhau vui vẻ không gây war và tiêu cực lẫn nhau</li> <li>✅ Hi vọng các bạn đã đọc kỹ những gì bọn mình đã ghi</li> </ul> <datagrid> <br> <strong> Mãi yêu bạn xin chào và hẹn gặp lại ở những series tiếp theo của bọn mình 🌟 <br> </strong> <h3 class="baloo2"><strong>FORM PIBEBI WITH LOVE &nbsp;🥰</strong></h3> </datagrid> </div> <div class="vote buttons" id="voteSection"> <button class="vote btn" onclick="castVote('good')">HAPPY ENDING</button> <button class="vote btn2" onclick="castVote('bad')">BAD ENDING</button> </div> <div class="result" id="resultMessage"></div> <div class="chart box"> <canvas id="voteChart"></canvas> </div> <! Social Share Buttons > <div class="share buttons"> <div class="share btn facebook" onclick="shareOnFacebook()"><i class="fab fa facebook f"></i></div> <div class="share btn twitter" onclick="shareOnTwitter()"><i class="fab fa twitter"></i></div> <div class="share btn linkedin" onclick="shareOnLinkedIn()"><i class="fab fa linkedin in"></i></div> <div class="share btn whatsapp" onclick="shareOnWhatsApp()"><i class="fab fa whatsapp"></i></div> <div class="share btn telegram" onclick="shareOnTelegram()"><i class="fab fa telegram plane"></i></div> </div> <div><p style="text align: center"><strong style="text align: left">Chia sẻ với bạn bè cùng biết nhé</strong></p> </div> <div class="lang select"> <label for="language"><strong style="color: #000000">🌐 Ngôn ngữ:</strong></label> <select id="language" onchange="handleLanguageChange()"> <option value="vi">Tiếng Việt 🇻🇳</option> <option value="en">Tiếng Anh 🇬🇧</option> </select> </div> <div class="footer note"><h4>© 2025 Pixgon Team Author: Dradoshi</h4></div> </div> <div id="votePopup"> <div class="popup content"> <h2>Cảm ơn bạn nhiều lắm! ❤️</h2> <p>Chúng mình đã nhận được lựa chọn của bạn rồi nè!</p> <p>Nhớ giữ bí mật để bạn khác cũng bất ngờ nha 🤫✨</p> <button onclick="closePopup()" style="margin top:16px; padding:10px 16px; border:none; border radius:10px; background:#121212; font weight:bold; cursor:pointer; color: #FFFFFF">Xem kết quả</button> </div> </div> <audio id="voteSound" src="https://cdn.pixabay.com/audio/2022/03/15/audio_6b92768d7f.mp3"></audio> <div style="text align: center; margin top: 20px;"> </div> <audio id="voteSFX" src="https://cdn.pixabay.com/audio/2022/03/15/audio_6b92768d7f.mp3"></audio> <script> // Firebase configuration const firebaseConfig = { apiKey: "AIzaSyB9_IDk8DUiy36Ad8qpKVX4rBCmVzEYfqM", authDomain: "vote ending.firebaseapp.com", databaseURL: "https://vote ending default rtdb.asia southeast1.firebasedatabase.app", projectId: "vote ending", storageBucket: "vote ending.firebasestorage.app", messagingSenderId: "1014258267077", appId: "1:1014258267077:web:3f029f4a65e02f008e91ac", measurementId: "G 4DMCBTC8JM" }; // Initialize Firebase firebase.initializeApp(firebaseConfig); const database = firebase.database(); // Initialize chart with empty data const ctx = document.getElementById('voteChart').getContext('2d'); const chart = new Chart(ctx, { type: 'pie', // Changed to pie chart for better visualization of proportions data: { labels: ['HAPPY ENDING', 'BAD ENDING'], datasets: [{ label: 'Tỉ lệ bình chọn', data: [0, 0], backgroundColor: ['#A4FF36', '#FC3A3D'], borderWidth: 1 }] }, options: { responsive: true, plugins: { legend: { position: 'bottom', labels: { font: { family: "'Baloo 2', sans serif", size: 14 } } }, tooltip: { callbacks: { label: function(context) { const total = context.dataset.data.reduce((a, b) => a + b, 0); const percentage = Math.round((context.raw / total) * 100); return `${context.label}: ${context.raw} votes (${percentage}%)`; } } } } } }); // Load votes from Firebase function loadVotes() { const votesRef = database.ref('votes'); votesRef.on('value', (snapshot) => { const data = snapshot.val() || { good: 0, bad: 0 }; chart.data.datasets[0].data = [data.good, data.bad]; chart.update(); }); } // Firebase listener for votes firebase.database().ref('votes').on('value', (snapshot) => { const data = snapshot.val(); if (data) { votes.good = data.good || 0; votes.bad = data.bad || 0; updateChart(); } }); // Initialize the app document.addEventListener('DOMContentLoaded', () => { loadVotes(); checkIfVoted(); }); // Check if user has already voted function checkIfVoted() { if (localStorage.getItem('voted')) { document.getElementById("voteSection").style.display = "none"; showResult(); } } // Cast vote function with Firebase integration function castVote(type) { if (localStorage.getItem('voted')) { alert("Bạn đã vote rồi, không thể thay đổi nữa nhé!"); return; } if (!confirm("Bạn chắc chắn chọn kết thúc này chứ? Bạn chỉ được vote một lần thôi nha!")) return; // Play sound effect document.getElementById("voteSFX").play(); // Update Firebase const voteRef = firebase.database().ref('votes'); voteRef.transaction((currentVotes) => { if (currentVotes) { currentVotes[type] = (currentVotes[type] || 0) + 1; } return currentVotes; }); // Save vote locally const ending = type === 'good' ? 'HAPPY ENDING' : 'BAD ENDING'; localStorage.setItem('votedEnding', ending); localStorage.setItem('voted', 'true'); // Change background based on vote if (type === 'good') { document.body.style.backgroundImage = "url('https://i.ibb.co/39Qj87wd/happy ending fix.png')"; } else { document.body.style.backgroundImage = "url('https://i.ibb.co/d0Ndnhfj/bad ending fix.png')"; } document.body.style.backgroundRepeat = "no repeat"; document.body.style.backgroundPosition = "center"; document.body.style.backgroundAttachment = "fixed"; // Show popup document.getElementById("mainContainer").style.filter = "blur(3px)"; document.getElementById("votePopup").style.display = "flex"; } function updateChart() { chart.data.datasets[0].data = [votes.good, votes.bad]; chart.update(); } function closePopup() { document.getElementById("votePopup").style.display = "none"; document.getElementById("mainContainer").style.filter = "none"; showResult(); } function showResult() { document.getElementById("voteSection").style.display = "none"; const ending = localStorage.getItem('votedEnding'); const videoLink = ending === 'HAPPY ENDING' ? 'https://www.google.com/' : 'https://www.google.com/'; const resultEl = document.getElementById('resultMessage'); resultEl.innerHTML = ` <p><strong>Cảm ơn bạn đã chọn ending hãy bấm vào nút bên dưới để xem video theo ending bạn chọn nhé </strong><br> <a href="${videoLink}" target="_blank" style="display:inline block; margin top:12px; padding:10px 16px; background:#cfe2ff; border radius:10px; text decoration:none; color:#000; font weight:bold;">Xem video kết thúc</a></p> `; resultEl.style.display = 'block'; } function handleLanguageChange() { const lang = document.getElementById("language").value; if (lang === "en") { alert("Sorry! English version is coming soon."); document.getElementById("language").value = "vi"; } } // Social Share Functions function shareOnFacebook() { const url = encodeURIComponent(window.location.href); window.open(`https://www.facebook.com/sharer/sharer.php?u=${url}`, '_blank'); } function shareOnTwitter() { const text = encodeURIComponent("Tôi vừa bình chọn cho kết thúc của câu chuyện này! Bạn cũng thử xem sao!"); const url = encodeURIComponent(window.location.href); window.open(`https://twitter.com/intent/tweet?text=${text}&url=${url}`, '_blank'); } function shareOnLinkedIn() { const url = encodeURIComponent(window.location.href); window.open(`https://www.linkedin.com/shareArticle?mini=true&url=${url}`, '_blank'); } function shareOnWhatsApp() { const text = encodeURIComponent("Tôi vừa bình chọn cho kết thúc của câu chuyện này! Bạn cũng thử xem sao: "); const url = encodeURIComponent(window.location.href); window.open(`https://wa.me/?text=${text}${url}`, '_blank'); } function shareOnTelegram() { const text = encodeURIComponent("Tôi vừa bình chọn cho kết thúc của câu chuyện này! Bạn cũng thử xem sao: "); const url = encodeURIComponent(window.location.href); window.open(`https://t.me/share/url?url=${url}&text=${text}`, '_blank'); } // Dark/Light mode toggle const modeToggle = document.getElementById('mode toggle'); const body = document.body; function setMode(mode) { if (mode === 'light') { body.classList.add('light mode'); modeToggle.textContent = '🌞'; } else { body.classList.remove('light mode'); modeToggle.textContent = '🌝 '; } localStorage.setItem('theme', mode); } modeToggle.addEventListener('click', () => { const currentMode = body.classList.contains('light mode') ? 'dark' : 'light'; setMode(currentMode); }); // Apply saved theme on load const savedMode = localStorage.getItem('theme'); if (savedMode) { setMode(savedMode); } else { setMode('dark'); } // Apply background if already voted const savedEnding = localStorage.getItem('votedEnding'); if (savedEnding === 'HAPPY ENDING') { document.body.style.backgroundImage = "url('https://i.ibb.co/39Qj87wd/happy ending fix.png')"; document.body.style.backgroundRepeat = "no repeat"; document.body.style.backgroundPosition = "center"; document.body.style.backgroundAttachment = "fixed"; } else if (savedEnding === 'Bad ENDING') { document.body.style.backgroundImage = "url('https://i.ibb.co/d0Ndnhfj/bad ending fix.png')"; document.body.style.backgroundRepeat = "no repeat"; document.body.style.backgroundPosition = "center"; document.body.style.backgroundAttachment = "fixed"; } console.log(localStorage.getItem('deviceId')); console.log(localStorage.getItem('hasVoted')); </script> </body> </html>

Prompt
Component Preview

About

App - a dynamic voting interface featuring light/dark mode toggle, social share buttons, and real-time chart updates, built with reac. Copy component code!

Share

Last updated 1 month ago