Client-side poll creation
This commit is contained in:
parent
44d0940e23
commit
4572e730f9
@ -2,5 +2,9 @@
|
|||||||
|
|
||||||
require_once __DIR__ .'/bootstrap.php';
|
require_once __DIR__ .'/bootstrap.php';
|
||||||
|
|
||||||
|
// Support the old Dragonpolls links
|
||||||
|
if (isset($_GET['poll'])) {
|
||||||
|
redirect('view_poll.php?id='.$_GET['poll']);
|
||||||
|
}
|
||||||
echo get_page_header();
|
echo get_page_header();
|
||||||
echo get_page_footer();
|
echo get_page_footer();
|
||||||
|
38
new_poll.php
38
new_poll.php
@ -11,11 +11,43 @@ use APnutI\Entities\Poll;
|
|||||||
use APnutI\Entities\User;
|
use APnutI\Entities\User;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
echo get_page_header('New Poll', true, ['poll']);
|
echo get_page_header('New Poll', true, ['new_poll']);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
die('Something went wrong :( "'.$e->getMessage().'"');
|
die('Something went wrong :( "'.$e->getMessage().'"' . get_page_footer());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$api->isAuthenticated(false, true)) {
|
if (!$api->isAuthenticated(false, true)) {
|
||||||
die('You need to be logged in to create a new poll!');
|
die('You need to be logged in to create a new poll!' . get_page_footer());
|
||||||
}
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<form method="POST" class="create-poll">
|
||||||
|
<label for="prompt">Prompt</label>
|
||||||
|
<input type="text" name="prompt" placeholder="What would you like to poll about?" id="prompt" required/>
|
||||||
|
<label for="options">Options</label>
|
||||||
|
<div id="options">
|
||||||
|
<?php
|
||||||
|
for ($i = 0; $i < 10; $i++) { ?>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="option[]"
|
||||||
|
placeholder="This will be option #<?= $i+1 ?>" <?= $i < 2 ? 'required' : '' ?>/>
|
||||||
|
<?php } ?>
|
||||||
|
</div>
|
||||||
|
<label for="anonymous">Anonymous</label>
|
||||||
|
<input type="checkbox" name="anonymous" id="anonymous" />
|
||||||
|
<label for="public">Public</label>
|
||||||
|
<input type="checkbox" name="public" id="public" />
|
||||||
|
<label for="max_options">Max Options</label>
|
||||||
|
<input type="number" name="max_options" id="max_options" min="1" max="10" value="1" required/>
|
||||||
|
<label for="duration">Duration</label>
|
||||||
|
<div id="duration">
|
||||||
|
<input type="number" name="duration_days" value="1" min="0" required/><span>day(s)</span>
|
||||||
|
<input type="number" name="duration_hours" value="0" min="0" required/><span>hour(s)</span>
|
||||||
|
<input type="number" name="duration_minutes" value="0" min="0" required/><span>minute(s)</span><br>
|
||||||
|
<span id="openUntil"></span>
|
||||||
|
</div>
|
||||||
|
<span class="error"></span>
|
||||||
|
<button type="submit" name="submit" value="submit">Create poll</button>
|
||||||
|
</form>
|
||||||
|
</form>
|
52
scripts/new_poll.js
Normal file
52
scripts/new_poll.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
window.addEventListener('DOMContentLoaded', () => {
|
||||||
|
for (const el of document.querySelectorAll('.create-poll input')) {
|
||||||
|
el.onchange = validatePoll;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function validatePoll() {
|
||||||
|
let errors = [];
|
||||||
|
const form = document.querySelector('.create-poll');
|
||||||
|
if (!form.querySelector('input[name=prompt]').value) {
|
||||||
|
errors.push('Prompt cannot be empty');
|
||||||
|
}
|
||||||
|
const numOptionsProvided = Array.from(form.querySelectorAll('input[name="option[]"]'))
|
||||||
|
.map(x => !!x.value)
|
||||||
|
.filter(x => x)
|
||||||
|
.length;
|
||||||
|
if (numOptionsProvided <= 1) {
|
||||||
|
errors.push('At least two options must be provided');
|
||||||
|
}
|
||||||
|
|
||||||
|
const maxOptions = parseInt(form.querySelector('input[name=max_options]').value);
|
||||||
|
if (numOptionsProvided > 1 && (isNaN(maxOptions) || maxOptions <= 0 || maxOptions >= numOptionsProvided)) {
|
||||||
|
errors.push(`Max Options needs to be greater than 0 and smaller than ${numOptionsProvided}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const durationDays = parseInt(form.querySelector('input[name=duration_days]').value);
|
||||||
|
const durationHours = parseInt(form.querySelector('input[name=duration_hours]').value);
|
||||||
|
const durationMinutes = parseInt(form.querySelector('input[name=duration_minutes]').value);
|
||||||
|
const durationTotalMinutes = durationDays*60*24 + durationHours * 60 + durationMinutes;
|
||||||
|
// 20160 is the max duration accepted by pnut
|
||||||
|
if (isNaN(durationTotalMinutes) || durationTotalMinutes < 1 || durationTotalMinutes > 20160) {
|
||||||
|
errors.push('Duration must be more than 1 and less than 20160 minutes');
|
||||||
|
}
|
||||||
|
|
||||||
|
const closesAtLabel = document.getElementById('openUntil');
|
||||||
|
if (!isNaN(durationTotalMinutes)) {
|
||||||
|
// Add duration_total_minutes to the curent Date
|
||||||
|
const closes_at = new Date(new Date().getTime() + durationTotalMinutes*60000);
|
||||||
|
closesAtLabel.innerText = `Open until ${closes_at.toLocaleString()}`;
|
||||||
|
} else {
|
||||||
|
closesAtLabel.innerText = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const errorSpan = form.querySelector('.error');
|
||||||
|
if (errors.length) {
|
||||||
|
errorSpan.innerHTML = `<ul><li>${errors.join('</li><li>')}</li></ul>`;
|
||||||
|
} else {
|
||||||
|
errorSpan.innerText = '';
|
||||||
|
}
|
||||||
|
form.querySelector('button[name=submit]').disabled = !!errors.length;
|
||||||
|
|
||||||
|
}
|
@ -182,6 +182,70 @@ datewrapper time {
|
|||||||
font-size: x-large;
|
font-size: x-large;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Poll creation */
|
||||||
|
|
||||||
|
.create-poll {
|
||||||
|
display: grid;
|
||||||
|
max-width: 400px;
|
||||||
|
grid-auto-columns: auto 1fr;
|
||||||
|
grid-column-gap: 8px;
|
||||||
|
}
|
||||||
|
.create-poll input[type=text],
|
||||||
|
.create-poll input[type=number],
|
||||||
|
.create-poll input[type=checkbox] {
|
||||||
|
grid-column: 2;
|
||||||
|
}
|
||||||
|
.create-poll input[type=number] {
|
||||||
|
max-width: 3em;
|
||||||
|
background-color: var(--secondary-bg-color);
|
||||||
|
color: var(--main-accent-color);
|
||||||
|
}
|
||||||
|
.create-poll input[type=text] {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
background-color: var(--secondary-bg-color);
|
||||||
|
color: var(--main-accent-color);
|
||||||
|
}
|
||||||
|
.create-poll input[type=text]:focus {
|
||||||
|
outline: 1px solid var(--main-accent-color);
|
||||||
|
}
|
||||||
|
.create-poll label {
|
||||||
|
grid-column: 1;
|
||||||
|
}
|
||||||
|
.create-poll label[for=options] {
|
||||||
|
grid-row: 2;
|
||||||
|
}
|
||||||
|
.create-poll #options {
|
||||||
|
grid-row: 2;
|
||||||
|
}
|
||||||
|
.create-poll label[for=anonymous] {
|
||||||
|
grid-row: 3
|
||||||
|
}
|
||||||
|
.create-poll label[for=public] {
|
||||||
|
grid-row: 4
|
||||||
|
}
|
||||||
|
.create-poll label[for=max_options] {
|
||||||
|
grid-row: 5
|
||||||
|
}
|
||||||
|
.create-poll label[for=duration] {
|
||||||
|
grid-row: 6
|
||||||
|
}
|
||||||
|
#duration {
|
||||||
|
grid-row: 6;
|
||||||
|
}
|
||||||
|
.create-poll button[type=submit] {
|
||||||
|
grid-row: 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.create-poll .error {
|
||||||
|
grid-column: 1/3;
|
||||||
|
grid-row: 7;
|
||||||
|
background-color: rgba(255, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
.create-poll .error:not(:empty) {
|
||||||
|
margin: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Footer */
|
/* Footer */
|
||||||
footer {
|
footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
Loading…
Reference in New Issue
Block a user