Added vote button en/disabling, remaining vote count

This commit is contained in:
aymm 2021-03-28 13:15:54 +02:00
parent 22096f43eb
commit 21f7623859
Signed by: phlaym
GPG Key ID: A06651BAB6777237
3 changed files with 92 additions and 11 deletions

View File

@ -1,10 +1,39 @@
window.addEventListener('DOMContentLoaded', (event) => { window.addEventListener('DOMContentLoaded', () => {
displayLocalTimestamps(); displayLocalTimestamps();
for (const el of document.querySelectorAll('.option input[type=checkbox]')) {
el.onclick = updateVotesRemaining;
}
}); });
function displayLocalTimestamps() { function displayLocalTimestamps() {
for (const el of document.getElementsByTagName('time')) { for (const el of document.getElementsByTagName('time')) {
let dateObj = new Date(el.getAttribute('datetime')); const dateObj = new Date(el.getAttribute('datetime'));
el.innerText = dateObj.toLocaleString(); const relDate = compareDateToToday(dateObj);
el.innerText = relDate === 0
? `Today, ${dateObj.toLocaleTimeString()}`
: dateObj.toLocaleDateString();
} }
}
function compareDateToToday(date) {
const today = new Date();
if (today.getDate() === date.getDate()
&& today.getMonth() === date.getMonth()
&& date.getFullYear() === today.getFullYear()) {
return 0;
}
today.setHours(0, 0, 0, 0);
return today > date ? -1 : 1;
}
function updateVotesRemaining() {
const numChecked = document.querySelectorAll('.option input[type=checkbox]:checked').length;
const votesRemainingElement = document.querySelector('.votes-remaining');
const total = votesRemainingElement.dataset.maxVotes;
const remaining = Math.max(0, total - numChecked);
const plural = remaining === 1 ? '' : 's';
votesRemainingElement.innerText = `${remaining} Vote${plural} remaining`;
const voteButton = document.querySelector('button[name=submit_vote]');
const canVoteInitial = voteButton.dataset.canVote === 'true';
voteButton.disabled = !canVoteInitial || (total - numChecked) < 0 || numChecked === 0;
} }

View File

@ -3,7 +3,8 @@
--main-bg-color: rgb(48, 48, 48); --main-bg-color: rgb(48, 48, 48);
--secondary-bg-color: rgba(10, 10, 10, 0.7); --secondary-bg-color: rgba(10, 10, 10, 0.7);
--main-fg-color: white; --main-fg-color: white;
--main-accent-color: rgb(253, 122, 0) --main-accent-color: rgb(253, 122, 0);
--disabled-color: gray;
} }
@supports (color: color(display-p3 1 1 1)) { @supports (color: color(display-p3 1 1 1)) {
:root { :root {
@ -28,6 +29,29 @@ body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Cantarell, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Cantarell, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
} }
button {
background-color: var(--main-accent-color);
outline: 1px solid var(--main-fg-color);
color: var(--main-fg-color);
cursor: pointer;
border: none;
transition: all 0.2s;
}
button:hover:not(:disabled) {
box-shadow: 4px 6px 3px 0 var(--secondary-bg-color);
transform: translate(-2px, -2px);
}
button:disabled {
background-color: var(--disabled-color);
cursor: not-allowed;
}
.hidden {
display: none;
}
/* Header */ /* Header */
header { header {
display: flex; display: flex;
@ -93,3 +117,7 @@ datewrapper time {
grid-template-columns: auto 1fr; grid-template-columns: auto 1fr;
grid-column-gap: 8px; grid-column-gap: 8px;
} }
.votes-remaining {
font-size: small;
}

View File

@ -42,6 +42,15 @@ $disabled = $poll->canVote() ? '' : 'disabled';
$user_name = $poll->user->name ?? ''; $user_name = $poll->user->name ?? '';
$created_at = $poll->created_at; $created_at = $poll->created_at;
$closed_at = $poll->closed_at; $closed_at = $poll->closed_at;
$user_votes = $poll->getMyVotes();
$votes_remaining = $poll->max_options - count($user_votes);
$votes_remaining_plural = $votes_remaining === 1 ? '' : 's';
$votes_remaining_text = "$votes_remaining Vote$votes_remaining_plural remaining";
$votes_remaining_hidden = $poll->canVote() ? '' : ' hidden';
$data_can_vote = $poll->canVote() ? 'true' : 'false';
$disabled_button = ($poll->canVote() && count($user_votes) > 0) ? '' : 'disabled';
?> ?>
<div class="poll"> <div class="poll">
@ -64,9 +73,16 @@ $closed_at = $poll->closed_at;
</time> </time>
</div> </div>
</div> </div>
<span class="prompt"><em><?= $poll->prompt ?></em></span> <span class="prompt">
<em><?= $poll->prompt ?></em><br>
<span
class="votes-remaining <?= $votes_remaining_hidden ?>"
data-max-votes="<?= $poll->max_options ?>"><?= $votes_remaining_text ?>
</span>
</span>
</div> </div>
<div class="options"> <div class="options">
<form>
<?php <?php
$row = 1; $row = 1;
$user_args = [ $user_args = [
@ -76,16 +92,24 @@ $closed_at = $poll->closed_at;
foreach ($poll->options as $option) { foreach ($poll->options as $option) {
$checked = $option->is_your_response ? 'checked' : ''; ?> $checked = $option->is_your_response ? 'checked' : ''; ?>
<div class="option" style="grid-row: <?= $row ?>;"> <div class="option" style="grid-row: <?= $row ?>;">
<input type="checkbox" <?= $checked.' '.$disabled ?>/> <input type="checkbox" <?= $checked.' '.$disabled ?>/>
<span class="option-text"><?= $option->text . ' (' . $option->respondents . ')'?></span> <span class="option-text"><?= $option->text . ' (' . $option->respondents . ')'?></span>
</div> </div>
<div class="option-responses" style="grid-row: <?= $row++ ?>;grid-column: 2;"> <div class="option-responses" style="grid-row: <?= $row++ ?>;grid-column: 2;">
<?php foreach ($option->respondent_ids as $res_id) { <?php foreach ($option->respondent_ids as $res_id) {
$u = $api->getUser($res_id, $user_args); ?> $u = $api->getUser($res_id, $user_args); ?>
<img src="<?= $u->getAvatarUrl(20) ?>" class="avatar" title="@<?= $u->username ?>"> <img src="<?= $u->getAvatarUrl(20) ?>" class="avatar" title="@<?= $u->username ?>">
<?php } ?> <?php } ?>
</div> </div>
<?php } ?> <?php } ?>
<button
type="submit"
name="submit_vote"
value="submit" <?= $disabled_button?>
data-can-vote="<?= $data_can_vote ?>">
Vote
</button>
</form>
</div> </div>
</div> </div>