aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias Magnusson <mathias@magnusson.space>2025-09-23 00:07:35 +0200
committerMathias Magnusson <mathias@magnusson.space>2025-09-23 00:07:35 +0200
commitc70851504652267c95194a98756c6875271cdda7 (patch)
tree2c7cd22ad17567e907d36ccf76d7fcad6073a6e1
parenta2827963fbf6847166360be635c65dc85d20dd0d (diff)
downloadtraedgaardstomten-c70851504652267c95194a98756c6875271cdda7.tar.gz
Implement reviews
-rw-r--r--.gitignore1
-rw-r--r--README.md19
-rw-r--r--compose.yaml3
-rw-r--r--include/layout.php14
-rw-r--r--include/sqlite.php19
-rw-r--r--nginx.conf3
-rw-r--r--public/index.php12
-rw-r--r--public/kontakt.php10
-rw-r--r--public/omdömen.php32
-rw-r--r--public/omdömen/edit.php33
-rw-r--r--public/omdömen/index.php60
-rw-r--r--public/style.css6
12 files changed, 155 insertions, 57 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..82f0c3a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/data/
diff --git a/README.md b/README.md
index bcb3b44..ceed5e5 100644
--- a/README.md
+++ b/README.md
@@ -2,3 +2,22 @@ Optimize images:
```sh
magick $x.jpg -interlace Plane -quality 80 inter-$x.jpg
```
+
+Init database:
+```sh
+mkdir data
+sqlite3 data/data.db
+```
+
+```sql
+PRAGMA journal_mode=WAL;
+create table reviews (
+ name text not null,
+ content text not null
+) strict;
+```
+
+```sh
+chmod a+w data/
+chmod a+w data/data.db
+```
diff --git a/compose.yaml b/compose.yaml
index 6e78b8c..244a83c 100644
--- a/compose.yaml
+++ b/compose.yaml
@@ -7,6 +7,9 @@ services:
volumes:
- ./public:/var/www/trädgårdstomten/public:ro
- ./include:/var/www/trädgårdstomten/include:ro
+ - ./data:/data:rw
+ - type: tmpfs
+ target: /tmp
nginx:
image: docker.io/nginx:1.27-alpine
restart: unless-stopped
diff --git a/include/layout.php b/include/layout.php
index ba79595..7bc67d2 100644
--- a/include/layout.php
+++ b/include/layout.php
@@ -1,6 +1,6 @@
<?php
-include "defer.php";
+require "defer.php";
function layout(&$context): void {
?>
@@ -13,8 +13,20 @@ function layout(&$context): void {
<link rel="stylesheet" href="/style.css">
<script src="https://unpkg.com/hyperscript.org@0.9.14" crossorigin="anonymous"
integrity="sha384-NzchC8z9HmP/Ed8cheGl9XuSrFSkDNHPiDl+ujbHE0F0I7tWC4rUnwPXP+7IvVZv"></script>
+ <script src="https://unpkg.com/htmx.org@2.0.7" crossorigin="anonymous"
+ integrity="sha384-ZBXiYtYQ6hJ2Y0ZNoYuI+Nq5MqWBr+chMrS/RkXpNzQCApHEhOt2aY8EJgqwHLkJ"></script>
</head>
<body>
+<header>
+ <section>
+ <p>Trädgårdstomten ✂️</p>
+ </section>
+ <nav>
+ <a href="/">Tjänster</a>
+ <a href="/omdömen">Omdömen</a>
+ <a href="/kontakt">Kontakt</a>
+ </nav>
+</header>
<?php
defer($context, function () { echo "</body></html>"; });
}
diff --git a/include/sqlite.php b/include/sqlite.php
new file mode 100644
index 0000000..6759e36
--- /dev/null
+++ b/include/sqlite.php
@@ -0,0 +1,19 @@
+<?php
+
+$db = new SQLite3("/data/data.db");
+
+function query($q, ...$values) {
+ global $db;
+
+ $stmt = $db->prepare($q);
+ foreach ($values as $key => $value) {
+ $stmt->bindValue(is_int($key) ? $key + 1 : $key, $value);
+ }
+ return $stmt->execute();
+}
+
+function lastRowId() {
+ global $db;
+
+ return $db->lastInsertRowId();
+}
diff --git a/nginx.conf b/nginx.conf
index 7c34523..34be30d 100644
--- a/nginx.conf
+++ b/nginx.conf
@@ -5,9 +5,10 @@ server {
}
server {
- listen 8009;
+ listen 8009 default_server;
server_name xn--trdgrdstomten-cfbr.se;
root /var/www/trädgårdstomten/public;
+ rewrite ^/([^/]+/)*[^.]+[^/]$ $http_x_forwarded_proto://$host$request_uri/ permanent;
set_real_ip_from 127.0.0.1/8;
gzip on;
default_type "text/html";
diff --git a/public/index.php b/public/index.php
index 8e6f565..0dd4d48 100644
--- a/public/index.php
+++ b/public/index.php
@@ -1,16 +1,6 @@
<?php require "../include/layout.php"; layout($_); ?>
-<header>
- <section>
- <p>Trädgårdstomten ✂️</p>
- </section>
- <nav>
- <a href="/">Tjänster</a>
- <a href="/omdömen">Omdömen</a>
- <a href="/kontakt">Kontakt</a>
- </nav>
-</header>
<main>
- <article>
+ <article id="about-text">
<p style="grid-area: p1">
Jag heter Lucas Magnusson, är 26 år gammal och har flera års yrkeserfarenhet och
är även utbildad inom trädgård. Jag har alltid varit intresserad av allt som
diff --git a/public/kontakt.php b/public/kontakt.php
index a23e0c6..ed60c0d 100644
--- a/public/kontakt.php
+++ b/public/kontakt.php
@@ -1,14 +1,4 @@
<?php require "../include/layout.php"; layout($_); ?>
-<header>
- <section>
- <p>Trädgårdstomten ✂️</p>
- </section>
- <nav>
- <a href="/">Tjänster</a>
- <a href="/omdömen">Omdömen</a>
- <a href="/kontakt">Kontakt</a>
- </nav>
-</header>
<main>
<p>Kontakta mig gärna så hör jag av mig så fort jag kan!</p>
<br>
diff --git a/public/omdömen.php b/public/omdömen.php
deleted file mode 100644
index c4a912a..0000000
--- a/public/omdömen.php
+++ /dev/null
@@ -1,32 +0,0 @@
-<?php require "../include/layout.php"; layout($_); ?>
-<header>
- <section>
- <p>Trädgårdstomten ✂️</p>
- </section>
- <nav>
- <a href="/">Tjänster</a>
- <a href="/omdömen">Omdömen</a>
- <a href="/kontakt">Kontakt</a>
- </nav>
-</header>
-<main>
- <div class="height-transition-wrapper">
- <form>
- <label for="name">Namn:</label>
- <input type="text" name="name" id="name">
- <br>
- <label for="review">Omdöme:</label>
- <textarea name="review" id="review"></textarea>
- <br>
- <button>Skicka!</button>
- </form>
- </div>
- <button _="
- on click
- toggle .open on previous <div/>
- if (previous <div/>) match .open then
- set my.innerText to 'Stäng formulär'
- else
- set my.innerText to 'Lämna ett omdöme'
- ">Lämna ett omdöme</button>
-</main>
diff --git a/public/omdömen/edit.php b/public/omdömen/edit.php
new file mode 100644
index 0000000..00b2d3b
--- /dev/null
+++ b/public/omdömen/edit.php
@@ -0,0 +1,33 @@
+<?php
+require "../../include/sqlite.php";
+
+session_start();
+
+if (!isset($_SESSION["editable review"])) die("Kan ej redigera något omdöme.");
+
+$rowid = $_SESSION["editable review"];
+$res = query('select name, content from reviews where rowid = ?', $rowid);
+$review = (object) $res->fetchArray();
+
+if ($_SERVER["REQUEST_METHOD"] === "POST") {
+ $name = $_POST["name"];
+ $content = $_POST["content"];
+
+ query("update reviews set name = ?, content = ? where rowid = ?", $name, $content, $rowid);
+
+ header("HX-Redirect: /omd%c3%b6men/");
+ exit;
+}
+
+require "../../include/layout.php"; layout($_);
+?>
+
+<form hx-post="/omdömen/edit/">
+ <label for="name">Namn:</label>
+ <input type="text" name="name" id="name" value="<?= htmlspecialchars($review->name) ?>">
+ <br>
+ <label for="content" style="vertical-align: top">Omdöme:</label>
+ <textarea name="content" id="content" style="height: 10em; width: 20em"><?= htmlspecialchars($review->content) ?></textarea>
+ <br>
+ <button>Skicka!</button>
+</form>
diff --git a/public/omdömen/index.php b/public/omdömen/index.php
new file mode 100644
index 0000000..53a9123
--- /dev/null
+++ b/public/omdömen/index.php
@@ -0,0 +1,60 @@
+<?php
+require "../../include/sqlite.php";
+
+session_start();
+
+if ($_SERVER["REQUEST_METHOD"] === "POST") {
+ $name = $_POST["name"];
+ $content = $_POST["content"];
+
+ query("insert into reviews (name, content) values (?, ?)", $name, $content);
+
+ $_SESSION["editable review"] = lastRowId();
+
+ header("HX-Refresh: true");
+ exit;
+}
+
+$res = query('select rowid, name, content from reviews');
+$reviews = [];
+while ($row = $res->fetchArray()) {
+ $row["editable"] = isset($_SESSION["editable review"]) && $_SESSION["editable review"] === $row["rowid"];
+ $row = (object) $row;
+ $reviews[] = $row;
+}
+
+require "../../include/layout.php"; layout($_);
+?>
+<main>
+ <div class="height-transition-wrapper">
+ <form hx-post="/omdömen/">
+ <label for="name">Namn:</label>
+ <input type="text" name="name" id="name">
+ <br>
+ <br>
+ <label for="content" style="vertical-align: top">Omdöme:</label>
+ <textarea name="content" id="content" style="height: 10em; width: 20em"></textarea>
+ <br>
+ <button>Skicka!</button>
+ <p style="margin-bottom: 1em; font-size: 0.8em"><i>Du kommer kunna redigera ditt omdöme tills du stänger fliken</i></p>
+ </form>
+ </div>
+ <button _="
+ on click
+ toggle .open on previous <div/>
+ if (previous <div/>) match .open then
+ set my.innerText to 'Stäng formulär'
+ else
+ set my.innerText to 'Lämna ett omdöme'
+ ">Lämna ett omdöme</button>
+
+ <? foreach ($reviews as $review) { ?>
+ <article style="padding: 0.25em;">
+ <p><i style="color: #333"><?= htmlspecialchars($review->name) ?>:</i></p>
+ <p style="white-space: pre-line"><?= htmlspecialchars($review->content) ?></p>
+ <? if ($review->editable) { ?>
+ <a class="nf nf-fa-edit" href="/omdömen/edit/"></a>
+ <? } ?>
+ </article>
+ <? } ?>
+</main>
diff --git a/public/style.css b/public/style.css
index 6f145db..c157f7d 100644
--- a/public/style.css
+++ b/public/style.css
@@ -1,3 +1,5 @@
+@import "https://www.nerdfonts.com/assets/css/webfont.css";
+
* {
margin: 0;
box-sizing: border-box;
@@ -62,7 +64,7 @@ main {
margin-inline: auto;
}
-main article {
+#about-text {
padding-bottom: 4em;
display: grid;
gap: 2em;
@@ -71,7 +73,7 @@ main article {
}
@media (min-width: 500px) {
- main article {
+ #about-text {
grid-template-columns: auto auto;
grid-template-areas: "p1 img" "p2 p2" "p3 p3";
}