Better results page, CSS organization, responsive design.

* Moved colors to $VERLAINE configuration variable.
* Colors in the options table result.
* Organized CSS in several files.
+ Responsive design!
This commit is contained in:
Madeorsk 2018-08-13 21:25:14 +02:00
parent f738330baf
commit b763b1d9e6
10 changed files with 303 additions and 237 deletions

View File

@ -2,4 +2,13 @@
$VERLAINE = [
"app_url" => "",
"chart_colors" => [
"#FF4B44", // Red.
"#FFD149", // Yellow.
"#56B3FF", // Dark blue.
"#FF9535", // Orange.
"#7DFF59", // Green.
"#FFAFEC", // Pink.
"#82FFE8", // Light blue.
],
];

View File

@ -92,6 +92,7 @@ Flight::route("POST /polls/@id:[a-fA-F0-9]+/vote", function ($id) {
});
Flight::route("GET /polls/@id:[a-fA-F0-9]+/results", function ($id) {
global $VERLAINE;
$poll = Poll::load_poll($id);
if ($poll)
{
@ -99,8 +100,8 @@ Flight::route("GET /polls/@id:[a-fA-F0-9]+/results", function ($id) {
Flight::json(format_poll($poll)); //TODO Add a svg for results?
else
{
Flight::render("svg/results", ["poll" => $poll], "results_chart");
Flight::render("results", ["poll" => $poll], "body_content");
Flight::render("svg/results", ["poll" => $poll, "colors" => $VERLAINE["chart_colors"]], "results_chart");
Flight::render("results", ["poll" => $poll, "chart_colors" => $VERLAINE["chart_colors"]], "body_content");
Flight::render("layout");
}
}

102
static/css/common.css Normal file
View File

@ -0,0 +1,102 @@
html, body
{
margin: 0;
padding: 0;
}
body
{
background: #242424;
color: #ECECEC;
font-family: "Nunito", sans-serif;
}
::-moz-focus-inner
{ border: none; }
body h1
{
display: block;
margin: 1em auto;
font-size: 4em;
font-weight: 300;
text-align: center;
}
main
{
margin: 0 5%;
}
main p
{
font-size: 1.5em;
text-align: center;
}
main p strong
{
font-family: "PT Serif", serif;
font-size: 1.2em;
font-weight: normal;
}
main input,
main button,
main a.button
{
transition: background 0.1s ease-in;
display: block;
margin: auto;
padding: 1em;
width: 25rem;
box-sizing: border-box;
background: #141414;
color: #ECECEC;
border: none;
outline: none;
font-size: 1.3em;
text-align: center;
text-decoration: none;
}
main input[type="submit"],
main button,
main a.button
{ cursor: pointer; }
main input[type="submit"],
a.button.margin
{ margin-top: 1em; }
main input:focus,
main input[type="submit"]:hover,
main button:hover,
main a.button:hover
{ background: #1D1D1D; }
footer
{
display: block;
margin: 5em;
color: #8E8E8E;
font-size: 0.9em;
font-weight: 700;
text-align: center;
}
@media screen and (max-width: 640px)
{
body h1
{ font-size: 3em; }
main input,
main button,
main a.button
{
width: 100%;
font-size: 1.2em;
}
}

47
static/css/home.css Normal file
View File

@ -0,0 +1,47 @@
main input[name="title"],
main input[name="title"]:focus
{
background: transparent;
font-family: "PT Serif", serif;
font-size: 1.5em;
}
@keyframes scalex
{
0%
{ transform: scaleX(0); }
100%
{ transform: scaleX(1); }
}
main #choices .choice
{
animation: scalex 0.2s linear;
display: flex;
flex-direction: row;
margin: auto;
width: 25rem;
}
main #choices .choice > *
{ margin: 0; }
main #choices .choice input
{ font-family: "PT Serif", serif; }
main #choices .choice .delete
{
background: #FF2E31;
width: 4em;
}
@media screen and (max-width: 640px)
{
main #choices .choice
{ width: 100%; }
main #choices .choice input
{ flex: 1; min-width: 0; }
main #choices .choice .delete
{ flex: 0 0; min-width: 3em; }
main input[name="title"],
main input[name="title"]:focus
{ font-size: 1.3em; }
}

View File

@ -1,223 +1,7 @@
@import url("/static/fonts/Nunito/Nunito.css");
@import url("/static/fonts/PTSerif/PTSerif.css");
html, body
{
margin: 0;
padding: 0;
}
body
{
background: #242424;
color: #ECECEC;
font-family: "Nunito", sans-serif;
}
::-moz-focus-inner
{ border: none; }
body h1
{
display: block;
margin: 1em auto;
font-size: 4em;
font-weight: 300;
text-align: center;
}
main
{
margin: 0 5%;
}
main p
{
font-size: 1.5em;
text-align: center;
}
main p strong
{
font-family: "PT Serif", serif;
font-size: 1.2em;
font-weight: normal;
}
main input,
main button,
main a.button
{
transition: background 0.1s ease-in;
display: block;
margin: auto;
padding: 1em;
width: 25rem;
box-sizing: border-box;
background: #141414;
color: #ECECEC;
border: none;
outline: none;
font-size: 1.3em;
text-align: center;
text-decoration: none;
}
main input[type="submit"],
main button,
main a.button
{ cursor: pointer; }
main input[type="submit"],
a.button.margin
{ margin-top: 1em; }
main input:focus,
main input[type="submit"]:hover,
main button:hover,
main a.button:hover
{ background: #1D1D1D; }
main input[name="title"],
main input[name="title"]:focus
{
background: transparent;
font-family: "PT Serif", serif;
font-size: 1.5em;
}
@keyframes scalex
{
0%
{ transform: scaleX(0); }
100%
{ transform: scaleX(1); }
}
main #choices .choice
{
animation: scalex 0.2s linear;
display: flex;
flex-direction: row;
margin: auto;
width: 25rem;
}
main #choices .choice > *
{ margin: 0; }
main #choices .choice input
{ font-family: "PT Serif", serif; }
main #choices .choice .delete
{
background: #FF2E31;
width: 4em;
}
/*
* IFNEZIUN
*/
h1.poll
{
margin: 1.5em 5%;
font-family: "PT Serif", serif;
font-size: 2.5rem;
}
.option
{
display: flex;
align-items: center;
margin: auto;
width: 25rem;
box-sizing: border-box;
background: #141414;
}
.option > input
{
position: absolute;
float: left;
width: 0;
opacity: 0;
cursor: pointer;
}
.option > .check
{
flex: none;
display: flex;
align-items: center;
justify-content: center;
margin-left: 1em;
padding: 0;
width: 1.25em;
height: 1.25em;
background: #202020;
}
.option > .check::before
{
content: "";
transition: transform 0.1s linear, border-radius 0.4s ease-out;
display: block;
background: #0088E5;
width: 0.75em;
height: 0.75em;
border-radius: 50%;
transform: scale(0);
}
.option input:checked ~ .check::before
{ border-radius: 0; transform: scale(1); }
.option > label
{
flex: 1;
display: block;
padding: 1em;
font-family: "PT Serif", serif;
font-size: 1.2em;
cursor: pointer;
}
/*
* JHFNDSJH
*/
main.results
{
display: flex;
flex-direction: row;
justify-content: center;
}
main.results > *
{ flex: 1; }
main.results .chart
{ flex: 2; max-height: 70vh; }
main.results .chart > svg
{ display: block; margin: auto; height: 100%; }
main.results .options table
{
margin: 0;
padding: 0 3em;
box-sizing: border-box;
width: 100%;
height: 100%;
font-size: 1.5em;
}
main.results .options table td
{ text-align: right; }
main.results .options .number
{
font-family: "PT Serif", serif;
font-size: 2em;
}
footer
{
display: block;
margin: 5em;
color: #8E8E8E;
font-size: 0.9em;
font-weight: 700;
text-align: center;
}
@import "common.css";
@import "home.css";
@import "poll.css";
@import "results.css";

67
static/css/poll.css Normal file
View File

@ -0,0 +1,67 @@
h1.poll
{
margin: 1.5em 5%;
font-family: "PT Serif", serif;
font-size: 2.5rem;
}
.option
{
display: flex;
align-items: center;
margin: auto;
width: 25rem;
box-sizing: border-box;
background: #141414;
}
.option > input
{
position: absolute;
float: left;
width: 0;
opacity: 0;
cursor: pointer;
}
.option > .check
{
flex: none;
display: flex;
align-items: center;
justify-content: center;
margin-left: 1em;
padding: 0;
width: 1.25em;
height: 1.25em;
background: #202020;
}
.option > .check::before
{
content: "";
transition: transform 0.1s linear, border-radius 0.4s ease-out;
display: block;
background: #0088E5;
width: 0.75em;
height: 0.75em;
border-radius: 50%;
transform: scale(0);
}
.option input:checked ~ .check::before
{ border-radius: 0; transform: scale(1); }
.option > label
{
flex: 1;
display: block;
padding: 1em;
font-family: "PT Serif", serif;
font-size: 1.2em;
cursor: pointer;
}
@media screen and (max-width: 640px)
{
h1.poll
{ font-size: 2em; }
.option
{ width: 100%; }
}

59
static/css/results.css Normal file
View File

@ -0,0 +1,59 @@
main.results
{
display: flex;
flex-direction: row;
justify-content: center;
}
main.results > *
{ flex: 1; }
main.results .chart
{ flex: 2; max-height: 70vh; }
main.results .chart > svg
{ display: block; margin: auto; height: 100%; }
main.results .options table
{
margin: 0;
padding: 0 3em;
box-sizing: border-box;
width: 100%;
height: 100%;
font-size: 1.5em;
}
main.results .options table td
{
padding: 0 1em;
text-align: right;
}
main.results .options .number
{
font-family: "PT Serif", serif;
font-size: 2em;
}
@media screen and (max-width: 640px)
{
main.results
{
flex-direction: column;
align-items: center;
margin: auto;
width: 95%;
}
main.results .options table
{
padding: 0;
width: 100%;
font-size: 1.2em;
}
main.results .options table td
{ padding: 0 0.5em; }
main.results .chart
{
margin-top: 2em;
width: 80%;
}
}

View File

@ -2,7 +2,8 @@
<html>
<head>
<meta charset="UTF-8" />
<title>Poll Verlaine</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Poll Verlaine</title>
<link rel="stylesheet" type="text/css" href="/static/css/main.css" />
</head>
<body>

View File

@ -1,4 +1,5 @@
<?php
$chart_colors_number = count($chart_colors);
$total_votes = 0;
foreach ($poll->options as $option)
$total_votes += $option->votes;
@ -7,10 +8,10 @@ foreach ($poll->options as $option)
<main class="results">
<div class="options">
<table>
<?php foreach ($poll->options as $option): ?>
<?php foreach ($poll->options as $index => $option): ?>
<tr>
<td class="number"><?= $option->votes ?></td>
<td><?= $option->label ?></td>
<td style="color: <?= $chart_colors[$index%$chart_colors_number] ?>"><?= $option->label ?></td>
<td><?= round($option->votes / $total_votes, 3)*100 ?>%</td>
</tr>
<?php endforeach; ?>

View File

@ -1,16 +1,7 @@
<?php
define("CIRCLE_R", 50);
$COLORS = [
"#FF4B44", // Red.
"#FFD149", // Yellow.
"#56B3FF", // Dark blue.
"#FF9535", // Orange.
"#7DFF59", // Green.
"#FFAFEC", // Pink.
"#82FFE8", // Light blue.
];
$colors_number = count($colors);
$total_votes = 0;
foreach ($poll->options as $option)
@ -33,7 +24,11 @@ function percentage_pos_y($r, $percentage)
<circle cx="0" cy="0" r="<?= CIRCLE_R ?>" fill="black" fill-opacity="0.2"></circle>
<?php
$used_percentage = 0;
foreach ($poll->options as $index => $option): ?>
<path d="M<?= percentage_pos_x(CIRCLE_R, $used_percentage) ?> <?= percentage_pos_y(CIRCLE_R, $used_percentage) ?> A<?= CIRCLE_R." ".CIRCLE_R ?> 0 <?= ($options_percentages[$index] > 0.5 ? 1 : 0) ?> 1 <?= percentage_pos_x(CIRCLE_R, $used_percentage + $options_percentages[$index]) ?> <?= percentage_pos_y(CIRCLE_R, $used_percentage + $options_percentages[$index]) ?> L0 0" fill="<?= $COLORS[$index%7] ?>"></path>
foreach ($poll->options as $index => $option):
if($options_percentages[$index] == 1): ?>
<circle cx="0" cy="0" r="<?= CIRCLE_R ?>" fill="<?= $colors[$index%$colors_number] ?>"></circle>
<?php elseif($options_percentages[$index] != 0): ?>
<path d="M<?= percentage_pos_x(CIRCLE_R, $used_percentage) ?> <?= percentage_pos_y(CIRCLE_R, $used_percentage) ?> A<?= CIRCLE_R." ".CIRCLE_R ?> 0 <?= ($options_percentages[$index] > 0.5 ? 1 : 0) ?> 1 <?= percentage_pos_x(CIRCLE_R, $used_percentage + $options_percentages[$index]) ?> <?= percentage_pos_y(CIRCLE_R, $used_percentage + $options_percentages[$index]) ?> L0 0" fill="<?= $colors[$index%$colors_number] ?>"></path>
<?php endif; ?>
<?php $used_percentage += $options_percentages[$index]; endforeach; ?>
</svg>