mirror of
https://codeberg.org/vlw/vlw.se.git
synced 2025-09-13 21:13:40 +02:00
Compare commits
2 commits
6bbb6926da
...
b0ab6a4f5b
Author | SHA1 | Date | |
---|---|---|---|
b0ab6a4f5b | |||
7ee2ba631d |
13 changed files with 327 additions and 22 deletions
|
@ -5,4 +5,5 @@ pass = ""
|
||||||
|
|
||||||
[databases]
|
[databases]
|
||||||
vlw = ""
|
vlw = ""
|
||||||
|
playground = ""
|
||||||
battlestation = ""
|
battlestation = ""
|
40
api/endpoints/playground/coffee/DELETE.php
Normal file
40
api/endpoints/playground/coffee/DELETE.php
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Reflect\Path;
|
||||||
|
use Reflect\Response;
|
||||||
|
use ReflectRules\Type;
|
||||||
|
use ReflectRules\Rules;
|
||||||
|
use ReflectRules\Ruleset;
|
||||||
|
|
||||||
|
use const VLW\API\RESP_DELETE_OK;
|
||||||
|
use VLW\API\Databases\VLWdb\{
|
||||||
|
VLWdb,
|
||||||
|
Databases
|
||||||
|
};
|
||||||
|
use VLW\API\Databases\VLWdb\Models\Playground\Coffee\CoffeeModel;
|
||||||
|
|
||||||
|
require_once Path::root("src/databases/VLWdb.php");
|
||||||
|
require_once Path::root("src/databases/models/Playground/Coffee/Coffee.php");
|
||||||
|
|
||||||
|
class DELETE_PlaygroundCoffee extends VLWdb {
|
||||||
|
protected Ruleset $ruleset;
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
parent::__construct();
|
||||||
|
$this->ruleset = new Ruleset(strict: true);
|
||||||
|
|
||||||
|
$this->ruleset->GET([
|
||||||
|
(new Rules(CoffeeModel::ID->value))
|
||||||
|
->required()
|
||||||
|
->type(Type::NUMBER)
|
||||||
|
]);
|
||||||
|
|
||||||
|
parent::__construct(Databases::PLAYGROUND, $this->ruleset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function main(): Response {
|
||||||
|
return $this->db->for(WorkActionsModel::TABLE)->delete($_POST) === true
|
||||||
|
? new Response(RESP_DELETE_OK)
|
||||||
|
: new Response("D:", 500);
|
||||||
|
}
|
||||||
|
}
|
40
api/endpoints/playground/coffee/GET.php
Normal file
40
api/endpoints/playground/coffee/GET.php
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Reflect\Path;
|
||||||
|
use Reflect\Response;
|
||||||
|
use ReflectRules\Type;
|
||||||
|
use ReflectRules\Rules;
|
||||||
|
use ReflectRules\Ruleset;
|
||||||
|
|
||||||
|
use VLW\API\Databases\VLWdb\{
|
||||||
|
VLWdb,
|
||||||
|
Databases
|
||||||
|
};
|
||||||
|
use VLW\API\Databases\VLWdb\Models\Playground\Coffee\CoffeeModel;
|
||||||
|
|
||||||
|
require_once Path::root("src/databases/VLWdb.php");
|
||||||
|
require_once Path::root("src/databases/models/Playground/Coffee/Coffee.php");
|
||||||
|
|
||||||
|
class GET_PlaygroundCoffee extends VLWdb {
|
||||||
|
protected Ruleset $ruleset;
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
$this->ruleset = new Ruleset(strict: true);
|
||||||
|
|
||||||
|
parent::__construct(Databases::PLAYGROUND, $this->ruleset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function main(): Response {
|
||||||
|
$result = $this->db
|
||||||
|
->for(CoffeeModel::TABLE)
|
||||||
|
->order([CoffeeModel::ID->value => "DESC"])
|
||||||
|
->select([
|
||||||
|
CoffeeModel::ID->value
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $result->num_rows > 0
|
||||||
|
// Return entries as sequential array of integer timestamps
|
||||||
|
? new Response(array_map(fn(array $value): int => $value[0], $result->fetch_all(MYSQLI_NUM)))
|
||||||
|
: new Response([], 404);
|
||||||
|
}
|
||||||
|
}
|
38
api/endpoints/playground/coffee/POST.php
Normal file
38
api/endpoints/playground/coffee/POST.php
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Reflect\Path;
|
||||||
|
use Reflect\Response;
|
||||||
|
use ReflectRules\Type;
|
||||||
|
use ReflectRules\Rules;
|
||||||
|
use ReflectRules\Ruleset;
|
||||||
|
|
||||||
|
use VLW\API\Databases\VLWdb\{
|
||||||
|
VLWdb,
|
||||||
|
Databases
|
||||||
|
};
|
||||||
|
use VLW\API\Databases\VLWdb\Models\Playground\Coffee\CoffeeModel;
|
||||||
|
|
||||||
|
require_once Path::root("src/databases/VLWdb.php");
|
||||||
|
require_once Path::root("src/databases/models/Playground/Coffee/Coffee.php");
|
||||||
|
|
||||||
|
class POST_PlaygroundCoffee extends VLWdb {
|
||||||
|
protected Ruleset $ruleset;
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
$this->ruleset = new Ruleset(strict: true);
|
||||||
|
|
||||||
|
$this->ruleset->GET([
|
||||||
|
(new Rules(CoffeeModel::ID->value))
|
||||||
|
->type(Type::NUMBER)
|
||||||
|
->default(time())
|
||||||
|
]);
|
||||||
|
|
||||||
|
parent::__construct(Databases::PLAYGROUND, $this->ruleset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function main(): Response {
|
||||||
|
return $this->db->for(CoffeeModel::TABLE)->insert($_POST) === true
|
||||||
|
? new Response($_POST[CoffeeModel::ID->value], 201)
|
||||||
|
: new Response(":(", 500);
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,8 @@
|
||||||
case WORK_TAGS = "/work/tags";
|
case WORK_TAGS = "/work/tags";
|
||||||
case WORK_ACTIONS = "/work/actions";
|
case WORK_ACTIONS = "/work/actions";
|
||||||
|
|
||||||
|
case PLAYGROUND_COFFEE = "/playground/coffee";
|
||||||
|
|
||||||
case BATTLESTATION = "/battlestation";
|
case BATTLESTATION = "/battlestation";
|
||||||
case BATTLESTATION_MB = "/battlestation/mb";
|
case BATTLESTATION_MB = "/battlestation/mb";
|
||||||
case BATTLESTATION_CPU = "/battlestation/cpu";
|
case BATTLESTATION_CPU = "/battlestation/cpu";
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
enum Databases: string {
|
enum Databases: string {
|
||||||
case VLW = "vlw";
|
case VLW = "vlw";
|
||||||
|
case PLAYGROUND = "playground";
|
||||||
case BATTLESTATION = "battlestation";
|
case BATTLESTATION = "battlestation";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
9
api/src/databases/models/Playground/Coffee/Coffee.php
Normal file
9
api/src/databases/models/Playground/Coffee/Coffee.php
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace VLW\API\Databases\VLWdb\Models\Playground\Coffee;
|
||||||
|
|
||||||
|
enum CoffeeModel: string {
|
||||||
|
const TABLE = "coffee";
|
||||||
|
|
||||||
|
case ID = "id";
|
||||||
|
}
|
|
@ -20,6 +20,8 @@ header {
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
|
user-select: none;
|
||||||
|
pointer-events: none;
|
||||||
image-rendering: pixelated;
|
image-rendering: pixelated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,20 +30,20 @@ img {
|
||||||
/* ## Title */
|
/* ## Title */
|
||||||
|
|
||||||
section.title {
|
section.title {
|
||||||
gap: var(--padding);
|
|
||||||
display: grid;
|
display: grid;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-items: center;
|
justify-items: center;
|
||||||
grid-template-columns: repeat(10, 1fr);
|
min-height: 50vw;
|
||||||
min-height: 30vh;
|
grid-template-columns: repeat(5, 1fr);
|
||||||
|
padding-bottom: var(--padding);
|
||||||
}
|
}
|
||||||
|
|
||||||
section.title img {
|
section.title img {
|
||||||
--outline-width: 5px;
|
--outline-width: 5px;
|
||||||
--outline-color: black;
|
--outline-color: black;
|
||||||
|
|
||||||
width: 100%;
|
width: 10vw;
|
||||||
transform: translateY(-10px);
|
transform: translateY(-1vw);
|
||||||
animation: bouncy 1s infinite alternate ease-in-out;
|
animation: bouncy 1s infinite alternate ease-in-out;
|
||||||
filter:
|
filter:
|
||||||
drop-shadow(0 10px 0 blue)
|
drop-shadow(0 10px 0 blue)
|
||||||
|
@ -53,17 +55,47 @@ section.title img {
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes bouncy {
|
@keyframes bouncy {
|
||||||
25% { transform: translateY(10px); }
|
25% { transform: translateY(0); }
|
||||||
100% { transform: translateY(10px); }
|
100% { transform: translateY(0); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ### Super Secret Settings */
|
||||||
|
|
||||||
|
section.sss {
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: var(--padding);
|
||||||
|
margin: var(--padding) 0;
|
||||||
|
background-color: rgba(255, 255, 255, .1);
|
||||||
|
}
|
||||||
|
|
||||||
|
section.sss button {
|
||||||
|
margin-top: var(--padding);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ## Coffee */
|
/* ## Coffee */
|
||||||
|
|
||||||
section.coffee {
|
section.coffee {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
gap: var(--padding);
|
||||||
grid-template-columns: 100px 1fr;
|
grid-template-columns: 100px 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
section.coffee img {
|
section.coffee img {
|
||||||
height: 100%;
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* # Size queries */
|
||||||
|
|
||||||
|
@media (min-width: 700px) {
|
||||||
|
section.title {
|
||||||
|
gap: var(--padding);
|
||||||
|
margin: 50px 0;
|
||||||
|
min-height: unset;
|
||||||
|
grid-template-columns: repeat(10, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
section.title img {
|
||||||
|
width: 100%;
|
||||||
|
transform: translateY(-10px);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,9 +1,11 @@
|
||||||
/* # Sections */
|
/* # Sections */
|
||||||
|
|
||||||
super-secret-settings {
|
super-secret-settings {
|
||||||
|
--border-width: 5px;
|
||||||
|
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 5px;
|
top: var(--border-width);
|
||||||
left: 5px;
|
left: var(--border-width);
|
||||||
width: 400px;
|
width: 400px;
|
||||||
fill: white;
|
fill: white;
|
||||||
color: white;
|
color: white;
|
||||||
|
@ -11,8 +13,8 @@ super-secret-settings {
|
||||||
border: solid 1px white;
|
border: solid 1px white;
|
||||||
background-color: rgb(0, 102, 204);
|
background-color: rgb(0, 102, 204);
|
||||||
box-shadow:
|
box-shadow:
|
||||||
0 0 0 5px black,
|
0 0 0 var(--border-width) black,
|
||||||
0 0 40px 10px rgba(0, 0, 0, .4);
|
0 0 40px calc(var(--border-width) * 2) rgba(0, 0, 0, .4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ## Header */
|
/* ## Header */
|
||||||
|
@ -20,12 +22,15 @@ super-secret-settings {
|
||||||
super-secret-settings section.header {
|
super-secret-settings section.header {
|
||||||
display: grid;
|
display: grid;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border-bottom: solid 1px white;
|
|
||||||
grid-template-columns: 1fr repeat(2, var(--running-size));
|
grid-template-columns: 1fr repeat(2, var(--running-size));
|
||||||
height: var(--running-size);
|
height: var(--running-size);
|
||||||
cursor: grab;
|
cursor: grab;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
super-secret-settings:not(.collapsed) section.header {
|
||||||
|
border-bottom: solid 1px white;
|
||||||
|
}
|
||||||
|
|
||||||
super-secret-settings section.header:active {
|
super-secret-settings section.header:active {
|
||||||
cursor: grabbing;
|
cursor: grabbing;
|
||||||
}
|
}
|
||||||
|
@ -42,11 +47,30 @@ super-secret-settings section.header svg {
|
||||||
|
|
||||||
super-secret-settings section.header button {
|
super-secret-settings section.header button {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
border-left: solid 1px var(--border-color);
|
border-left: solid 1px white;
|
||||||
|
}
|
||||||
|
|
||||||
|
super-secret-settings.collapsed section.header button.collapse svg {
|
||||||
|
transform: rotate(-90deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ## Body */
|
/* ## Body */
|
||||||
|
|
||||||
super-secret-settings section.body {
|
super-secret-settings section.body {
|
||||||
padding: var(--padding);
|
padding: var(--padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
super-secret-settings.collapsed section.body {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* # Size queries */
|
||||||
|
|
||||||
|
@media not (hover: hover), (max-width: 900px) {
|
||||||
|
super-secret-settings {
|
||||||
|
top: unset;
|
||||||
|
bottom: 5px;
|
||||||
|
width: calc(100% - (var(--border-width) * 2));
|
||||||
|
transform: translate(0, 0) !important;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import { Elevent } from "/assets/js/modules/npm/Elevent.mjs";
|
import { Elevent } from "/assets/js/modules/npm/Elevent.mjs";
|
||||||
|
|
||||||
new Elevent("click", document.querySelector("section.sss button"), () => {
|
new Elevent("click", document.querySelector("section.sss button"), (event) => {
|
||||||
const SSS_TAG_NAME = "super-secret-settings";
|
const SSS_TAG_NAME = "super-secret-settings";
|
||||||
|
|
||||||
let sssElement = document.querySelector(SSS_TAG_NAME);
|
let sssElement = document.querySelector(SSS_TAG_NAME);
|
||||||
|
@ -11,6 +11,13 @@ new Elevent("click", document.querySelector("section.sss button"), () => {
|
||||||
document.body.appendChild(sssElement);
|
document.body.appendChild(sssElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const size = event.target.getBoundingClientRect();
|
||||||
|
|
||||||
|
// Set initial window position above button
|
||||||
|
const y = size.top;
|
||||||
|
const x = size.left + size.width;
|
||||||
|
sssElement.style.transform = `translate(${x}px, ${y}px)`
|
||||||
|
|
||||||
// Navigate SSS element to playground page
|
// Navigate SSS element to playground page
|
||||||
new vegvisir.Navigation("/playground/super-secret-settings").navigate(sssElement);
|
new vegvisir.Navigation("/playground/super-secret-settings").navigate(sssElement);
|
||||||
});
|
});
|
|
@ -8,6 +8,7 @@ const clampRight = (window.innerWidth - sssElement._size.width) - (borderWidth *
|
||||||
const clampBottom = (window.innerHeight - sssElement._size.height) - (borderWidth * 3);
|
const clampBottom = (window.innerHeight - sssElement._size.height) - (borderWidth * 3);
|
||||||
|
|
||||||
const moveWindow = new Elevent("mousemove", null, (event) => {
|
const moveWindow = new Elevent("mousemove", null, (event) => {
|
||||||
|
// Clamp window to viewport
|
||||||
const y = Math.max(borderWidth, Math.min(clampBottom, (event.clientY - 40)));
|
const y = Math.max(borderWidth, Math.min(clampBottom, (event.clientY - 40)));
|
||||||
const x = Math.max(borderWidth, Math.min(clampRight, event.clientX - (sssElement._size.width / 2)));
|
const x = Math.max(borderWidth, Math.min(clampRight, event.clientX - (sssElement._size.width / 2)));
|
||||||
|
|
||||||
|
@ -34,4 +35,5 @@ new Elevent("mousedown", sssElement.querySelector(".header"), (event) => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
new Elevent("click", sssElement.querySelector(".header button"), () => sssElement.remove());
|
new Elevent("click", sssElement.querySelector(".header button.close"), () => sssElement.remove());
|
||||||
|
new Elevent("click", sssElement.querySelector(".header button.collapse"), () => sssElement.classList.toggle("collapsed"));
|
|
@ -1,20 +1,129 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Reflect\Response;
|
||||||
|
|
||||||
|
use VLW\Client\API;
|
||||||
|
use VLW\API\Endpoints;
|
||||||
|
|
||||||
|
use VLW\API\Databases\VLWdb\Models\Work\WorkModel;
|
||||||
|
|
||||||
|
require_once VV::root("src/client/API.php");
|
||||||
|
require_once VV::root("api/src/Endpoints.php");
|
||||||
|
|
||||||
|
function to_plural(int $value): string {
|
||||||
|
return $value !== 1 ? "s" : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
$time = new class extends DateTimeImmutable {
|
||||||
|
public function __construct() {
|
||||||
|
parent::__construct("now", new DateTimeZone($_ENV["time"]["date_time_zone"]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hours(): int {
|
||||||
|
return (int) $this->format("G");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function minutes(): int {
|
||||||
|
return (int) $this->format("i");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function since_midnight_str(): string {
|
||||||
|
$hours = $this->hours();
|
||||||
|
$minutes = $this->minutes();
|
||||||
|
|
||||||
|
// Show minutes if we're not into the first hour yet
|
||||||
|
if ($hours < 1) {
|
||||||
|
return $minutes . " minute" . to_plural($minutes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Round up to the nearest hour
|
||||||
|
return ($minutes < 45 ? $hours : $hours + 1) . " hour" . to_plural($hours);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$coffee = new class extends API {
|
||||||
|
const THRESHOLDS = [
|
||||||
|
[-10, "a lot less than"],
|
||||||
|
[-5, "a bit less than"],
|
||||||
|
[0, "average"],
|
||||||
|
[5, "a bit more than"],
|
||||||
|
[10, "a lot more than"]
|
||||||
|
];
|
||||||
|
|
||||||
|
private readonly int $now;
|
||||||
|
private readonly Response $resp;
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
parent::__construct();
|
||||||
|
|
||||||
|
$this->now = time();
|
||||||
|
$this->resp = $this->call(Endpoints::PLAYGROUND_COFFEE->value)->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function get_until_timestamp(int $offset = 0): array {
|
||||||
|
return array_filter($this->resp->json(), fn(int $timestamp): int => $timestamp > $offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function get_average_month(): int {
|
||||||
|
$days = [0];
|
||||||
|
|
||||||
|
foreach ($this->get_until_timestamp(2592000) as $timestamp) {
|
||||||
|
// Append new value for next 24 hours
|
||||||
|
if ($timestamp % 86400 === 0) {
|
||||||
|
$days[] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$days[count($days) - 1]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count the average for each day
|
||||||
|
return array_sum($days) / count($days);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the number of cups within the last 24 hours
|
||||||
|
public function get_today(): int {
|
||||||
|
return $this->resp->ok ? count($this->get_until_timestamp(86400)) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_average_month_str(): string {
|
||||||
|
$diff = $this->get_today() - $this->get_average_month();
|
||||||
|
|
||||||
|
// Check diff of today against monthyl average thresholds
|
||||||
|
foreach (self::THRESHOLDS as $threshold) {
|
||||||
|
[$limit, $msg] = $threshold;
|
||||||
|
|
||||||
|
// Bail out if diff is less than threshold limit
|
||||||
|
if ($diff < $limit) {
|
||||||
|
return $msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return last entry if diff is more than last threshold limit
|
||||||
|
return self::THRESHOLDS[count(self::THRESHOLDS) - 1][1];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
?>
|
||||||
<style><?= VV::css("public/assets/css/pages/playground/index") ?></style>
|
<style><?= VV::css("public/assets/css/pages/playground/index") ?></style>
|
||||||
<section class="title">
|
<section class="title">
|
||||||
|
|
||||||
<?php // I was listening to https://www.youtube.com/watch?v=DsUb4Lq6DBE when I made the dancing letters ?>
|
<!-- I was listening to https://www.youtube.com/watch?v=DsUb4Lq6DBE when I made the dancing letters -->
|
||||||
<?php foreach (str_split("playground") as $idx => $char): ?>
|
<?php foreach (str_split("playground") as $idx => $char): ?>
|
||||||
<img src="data:image/gif;base64,<?= base64_encode(VV::embed("public/assets/media/playground/{$char}.gif")) ?>" style="animation-delay:<?= ($idx % rand(2, 4)) * 500 ?>ms">
|
<img src="data:image/gif;base64,<?= base64_encode(VV::embed("public/assets/media/playground/{$char}.gif")) ?>" style="animation-delay:<?= ($idx % rand(2, 4)) * 500 ?>ms">
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
<section class="sss">
|
<section class="sss">
|
||||||
<button class="inline">Super Secret Settings</button>
|
<h1>I'm so bored.</h1>
|
||||||
|
<p>Don't like the way my website looks? These oficially very Super Secret Settings<sup><a href="https://minecraft-archive.fandom.com/wiki/Super_Secret_Settings">™</a></sup> will give you something else to look at!</p>
|
||||||
|
<button class="inline">Try it</button>
|
||||||
</section>
|
</section>
|
||||||
<section class="coffee">
|
<section class="coffee">
|
||||||
<img src="data:image/gif;base64,<?= base64_encode(VV::embed("public/assets/media/playground/coffee.gif")) ?>">
|
<img src="data:image/gif;base64,<?= base64_encode(VV::embed("public/assets/media/playground/coffee.gif")) ?>">
|
||||||
<div>
|
<div>
|
||||||
<h1>How much coffee is enough coffee?</h1>
|
<h1>What else.. I've had <?= $coffee->get_today() ?> cup<?= to_plural($coffee->get_today()) ?> of coffee today!</h1>
|
||||||
<p>Woah, I 've had 4 cups of coffee today (counting from and to midnight). That's about the average amount for me (from the last 30 days)</p>
|
<p>That's <?= $coffee->get_average_month_str() ?> the daily average for me (last 30 days). Here I'm counting how many ~300ml cups of coffee I've had since midnight for my timezone <?= $_ENV["time"]["date_time_zone"] ?>, that was <?= $time->since_midnight_str() ?> ago.</p>
|
||||||
|
<p>How much coffee is enough coffee? <a href="<?= $_ENV["api"]["base_url"] . Endpoints::PLAYGROUND_COFFEE->value ?>">Click here to see my answer!!</a> (NOT CLICKBAIT). Each array value is a UNIX timestamp that represents a single cup of coffee.</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<script type="module"><?= VV::js("public/assets/js/pages/playground/index") ?></script>
|
<script type="module"><?= VV::js("public/assets/js/pages/playground/index") ?></script>
|
|
@ -1,8 +1,8 @@
|
||||||
<style><?= VV::css("public/assets/css/pages/playground/super-secret-settings") ?></style>
|
<style><?= VV::css("public/assets/css/pages/playground/super-secret-settings") ?></style>
|
||||||
<section class="header">
|
<section class="header">
|
||||||
<p>Super Secret Settings</p>
|
<p>Super Secret Settings</p>
|
||||||
<button><?= VV::embed("public/assets/media/icons/chevron.svg") ?></button>
|
<button class="collapse"><?= VV::embed("public/assets/media/icons/chevron.svg") ?></button>
|
||||||
<button><?= VV::embed("public/assets/media/icons/close.svg") ?></button>
|
<button class="close"><?= VV::embed("public/assets/media/icons/close.svg") ?></button>
|
||||||
</section>
|
</section>
|
||||||
<section class="body">
|
<section class="body">
|
||||||
<p>Do you have what it takes to click this button?</p>
|
<p>Do you have what it takes to click this button?</p>
|
||||||
|
|
Loading…
Add table
Reference in a new issue