Skip to content

Commit

Permalink
Merge pull request #5 from OpenRedSoftware/refactorIntoMultipleFiles
Browse files Browse the repository at this point in the history
Refactor things into multiple files
  • Loading branch information
dginovker authored Feb 26, 2024
2 parents 21b5816 + 43cc9e5 commit 9ab7170
Show file tree
Hide file tree
Showing 6 changed files with 236 additions and 247 deletions.
15 changes: 15 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import displayResultsPage from './resultsPage.js';
import displayVotePage from './votePage.js';
import displayCreatePollPage from './createPollPage.js';

window.onload = function () {
const path = window.location.pathname.split('/').filter(Boolean);

if (path.length === 1) {
displayResultsPage(path[0]);
} else if (path.length === 2 && path[1] === 'vote') {
displayVotePage(path[0]);
} else {
displayCreatePollPage();
}
};
72 changes: 72 additions & 0 deletions createPollPage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { ref, runTransaction } from 'https://www.gstatic.com/firebasejs/9.6.1/firebase-database.js';
import { db } from './database.js';

export default function displayCreatePollPage() {
const html = `
<h1>Create a New Poll</h1>
<form id="createPollForm">
<input type="text" id="pollQuestion" placeholder="Enter poll question" required>
<div id="pollOptions">
<input type="text" class="poll-option" placeholder="Option 1" required>
<input type="text" class="poll-option" placeholder="Option 2" required>
</div>
<button type="button" id="addOptionButton">Add Option</button>
<button type="submit" id="createPollButton">Create Poll</button>
</form>
`;

document.getElementById('content').innerHTML = html;

// Set up event listeners
document.getElementById('addOptionButton').addEventListener('click', addOption);
document.getElementById('createPollForm').addEventListener('submit', createPoll);
}


function addOption() {
const pollOptionsDiv = document.getElementById('pollOptions');
const newOptionIndex = pollOptionsDiv.getElementsByClassName('poll-option').length + 1;
const newOptionInput = document.createElement('input');
newOptionInput.type = 'text';
newOptionInput.className = 'poll-option';
newOptionInput.placeholder = `Option ${newOptionIndex}`;
pollOptionsDiv.appendChild(newOptionInput);
}

function getNewPollId() {
const pollIdRef = ref(db, 'nextPollId');
return runTransaction(pollIdRef, (currentId) => {
return (currentId || 0) + 1;
}).then((transaction) => {
return transaction.snapshot.val();
}).catch((error) => {
console.error('Transaction failed: ', error);
});
}

function createPoll(event) {
event.preventDefault();
const createButton = document.getElementById('createPollButton');
createButton.disabled = true; // Disable the button during the async operation
const pollQuestion = document.getElementById('pollQuestion').value;
const optionElements = document.getElementsByClassName('poll-option');
const options = Array.from(optionElements).map(option => option.value.trim()).filter(Boolean);

getNewPollId().then((pollId) => {
const newPoll = {
id: pollId,
question: pollQuestion,
options: options,
votes: options.reduce((acc, option) => ({ ...acc, [option]: 0 }), {})
};
const pollRef = ref(db, 'polls/' + pollId);
return set(pollRef, newPoll).then(() => pollId); // Return pollId for the next .then()
}).then((pollId) => {
window.location.href = `/${pollId}/vote`;
}).catch((error) => {
console.error('Error creating poll: ', error);
}).finally(() => {
createButton.disabled = false; // Re-enable the button after the operation
});
}

8 changes: 8 additions & 0 deletions database.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { initializeApp } from 'https://www.gstatic.com/firebasejs/9.6.1/firebase-app.js';
import { getDatabase } from 'https://www.gstatic.com/firebasejs/9.6.1/firebase-database.js';
import { firebaseConfig } from '/firebaseConfig.js';

const app = initializeApp(firebaseConfig);
const db = getDatabase(app);

export { db };
251 changes: 4 additions & 247 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,262 +1,19 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Strawpoll.lol - Simple Strawpoll.me clone</title>
<meta name="description"
content="Create a poll in seconds - No signup. No ads. No complexity. Free and open source." />
<meta name="description" content="Create a poll in seconds - No signup. No ads. No complexity. Free and open source." />
<link rel="stylesheet" href="/index.css">

<script type="module">
// Firebase App (the core Firebase SDK) is always required and must be listed first
import { initializeApp } from 'https://www.gstatic.com/firebasejs/9.6.1/firebase-app.js';
import {
getDatabase,
ref,
onValue,
push,
set,
runTransaction,
get,
child
} from 'https://www.gstatic.com/firebasejs/9.6.1/firebase-database.js';

import { firebaseConfig } from '/firebaseConfig.js';

const app = initializeApp(firebaseConfig);
const db = getDatabase(app);

window.onload = function () {
const path = window.location.pathname.split('/').filter(Boolean);

if (path.length === 1) {
displayResultsPage(path[0]);
} else if (path.length === 2 && path[1] === 'vote') {
displayVotePage(path[0]);
} else {
displayCreatePollPage();
}
};

function displayVotePage(pollId) {
if (!pollId) {
document.getElementById('content').innerHTML = 'Poll ID is required.';
return;
}

// Retrieve the poll data from Firebase
const pollRef = ref(db, 'polls/' + pollId);
get(pollRef).then((snapshot) => {
if (snapshot.exists()) {
const pollData = snapshot.val();

document.title = pollData.question + " - Vote now on Strawpoll.lol";

// Create the HTML for the voting options
let html = `<h1>${pollData.question}</h1>`;
pollData.options.forEach((option, index) => {
html += `
<label class="vote-option" for="option${index}">
<input type="radio" id="option${index}" name="vote" value="${option}">
${option}
</label>
`;
});
html += `<button id="submitVoteButton" style="margin-right: 0.5rem;">Vote</button>`;
html += `<button id="goResultsButton">Results</button>`;
// Display the HTML in the 'content' div
document.getElementById('content').innerHTML = html;

// Add the event listener to the button
document.getElementById('submitVoteButton').addEventListener('click', () => submitVote(pollId));
document.getElementById('goResultsButton').addEventListener('click', () => window.location.href = `/${pollId}`);
} else {
document.getElementById('content').innerHTML = 'Poll not found.';
}
}).catch((error) => {
console.error(error);
});
}


function displayResultsPage(pollId) {
const contentDiv = document.getElementById('content');
contentDiv.innerHTML = ''; // Clear previous content

const pollRef = ref(db, 'polls/' + pollId);
onValue(pollRef, (snapshot) => {
if (snapshot.exists()) {
const data = snapshot.val();
document.title = data.question + " - See results on Strawpoll.lol";

// Calculate total votes
const totalVotes = Object.values(data.votes).reduce((total, num) => total + num, 0);

// Check if totalVotes is greater than zero
if (totalVotes > 0) {
// Create results header
const header = document.createElement('h1');
header.textContent = data.question;
contentDiv.appendChild(header);

// Create a list to display poll results
const list = document.createElement('ul');
for (const [option, votes] of Object.entries(data.votes)) {
const item = document.createElement('li');
item.style.cssText = `
display: flex;
align-items: center; /* Vertically centers the flex items */
position: relative;
min-height: 36px;
background: #fff7e6;
margin-bottom: 10px;
border-radius: 5px;
overflow: hidden;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
`;
const percentage = votes * 100 / totalVotes;
const bar = document.createElement('div');
bar.style.cssText = `
width: ${percentage}%;
background-color: #f0f0f0;
position: absolute;
top: 0;
left: 0;
height: 100%;
z-index: 1;
border-radius: 5px 0 0 5px; /* Rounded corners on the left side */
`; // Adjusted color and added border-radius

const text = document.createElement('span');
text.textContent = `${option}: ${votes} votes (${percentage.toFixed(2)}%)`;
text.style.cssText = `
z-index: 2;
margin-left: 10px; /* Replaces the 'left' property */
color: #000;
font-weight: normal;
white-space: nowrap;
`;
item.appendChild(bar);
item.appendChild(text); // Ensure text is added after the bar so it appears on top
list.appendChild(item);
}

contentDiv.appendChild(list);
contentDiv.innerHTML += `<button id="goVotePageButton" onclick="window.location.href='/${pollId}/vote'">Vote</button>`;
} else {
// Display a message if there are no votes
contentDiv.innerHTML = 'No votes have been cast yet.';
}
} else {
contentDiv.innerHTML = 'Poll not found.';
}
}, {
onlyOnce: true
});
}



function displayCreatePollPage() {
const html = `
<h1>Create a New Poll</h1>
<form id="createPollForm">
<input type="text" id="pollQuestion" placeholder="Enter poll question" required>
<div id="pollOptions">
<input type="text" class="poll-option" placeholder="Option 1" required>
<input type="text" class="poll-option" placeholder="Option 2" required>
</div>
<button type="button" id="addOptionButton">Add Option</button>
<button type="submit" id="createPollButton">Create Poll</button>
</form>
`;

document.getElementById('content').innerHTML = html;

// Set up event listeners
document.getElementById('addOptionButton').addEventListener('click', addOption);
document.getElementById('createPollForm').addEventListener('submit', createPoll);
}


function addOption() {
const pollOptionsDiv = document.getElementById('pollOptions');
const newOptionIndex = pollOptionsDiv.getElementsByClassName('poll-option').length + 1;
const newOptionInput = document.createElement('input');
newOptionInput.type = 'text';
newOptionInput.className = 'poll-option';
newOptionInput.placeholder = `Option ${newOptionIndex}`;
pollOptionsDiv.appendChild(newOptionInput);
}

function getNewPollId() {
const pollIdRef = ref(db, 'nextPollId');
return runTransaction(pollIdRef, (currentId) => {
return (currentId || 0) + 1;
}).then((transaction) => {
return transaction.snapshot.val();
}).catch((error) => {
console.error('Transaction failed: ', error);
});
}

function createPoll(event) {
event.preventDefault();
const createButton = document.getElementById('createPollButton');
createButton.disabled = true; // Disable the button during the async operation
const pollQuestion = document.getElementById('pollQuestion').value;
const optionElements = document.getElementsByClassName('poll-option');
const options = Array.from(optionElements).map(option => option.value.trim()).filter(Boolean);

getNewPollId().then((pollId) => {
const newPoll = {
id: pollId,
question: pollQuestion,
options: options,
votes: options.reduce((acc, option) => ({ ...acc, [option]: 0 }), {})
};
const pollRef = ref(db, 'polls/' + pollId);
return set(pollRef, newPoll).then(() => pollId); // Return pollId for the next .then()
}).then((pollId) => {
window.location.href = `/${pollId}/vote`;
}).catch((error) => {
console.error('Error creating poll: ', error);
}).finally(() => {
createButton.disabled = false; // Re-enable the button after the operation
});
}


function submitVote(pollId) {
const voteButton = document.getElementById('submitVoteButton');
voteButton.disabled = true; // Disable the button during the async operation
const selectedOption = document.querySelector('input[name="vote"]:checked').value;
const voteRef = ref(db, 'polls/' + pollId + '/votes/' + selectedOption);
runTransaction(voteRef, (currentVotes) => {
return (currentVotes || 0) + 1;
}).then(() => {
window.location.href = `/${pollId}`;
}).catch((error) => {
console.error('Error submitting vote: ', error);
}).finally(() => {
voteButton.disabled = false; // Re-enable the button after the operation
});
}

</script>
</head>

<body>
<div id="content"></div>

<footer>
<a href="/">Create a Poll</a> |
<a href="https://github.com/OpenRedSoftware/strawpoll.lol" target="_blank">Source Code</a>
</footer>

<!-- Import the app.js module -->
<script type="module" src="/app.js"></script>
</body>


</html>
</html>
Loading

0 comments on commit 9ab7170

Please sign in to comment.