summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorilotterytea <iltsu@alright.party>2025-10-14 15:36:31 +0500
committerilotterytea <iltsu@alright.party>2025-10-14 15:36:31 +0500
commit33fd114a314212b8759b525fb9e08d4ff4ca8869 (patch)
tree7abbb155a7515148f355b30978e3a0fa77913fd1
parentd6196a61348dbd0040e332147ef4a34ade64b309 (diff)
feat: web frontend
-rw-r--r--web/config.php12
-rw-r--r--web/index.php103
-rw-r--r--web/partials.php23
-rwxr-xr-xweb/static/img/icons/word.pngbin0 -> 567 bytes
-rw-r--r--web/static/style.css99
5 files changed, 237 insertions, 0 deletions
diff --git a/web/config.php b/web/config.php
new file mode 100644
index 0000000..bee8597
--- /dev/null
+++ b/web/config.php
@@ -0,0 +1,12 @@
+<?php
+$file_path = $_SERVER['FILEPATH_CONFIG'] ?? ($_SERVER['DOCUMENT_ROOT'] . '/../config.ini');
+
+$c = parse_ini_file($file_path, true) ?: [];
+
+// INSTANCE
+define('INSTANCE_NAME', $c['instance']['name'] ?: $_SERVER['HTTP_HOST']);
+
+// DATABASE
+define('DB_URL', "{$c['database']['driver']}:dbname={$c['database']['name']};host={$c['database']['host']}");
+define('DB_USER', $c['database']['user']);
+define('DB_PASS', $c['database']['pass']);
diff --git a/web/index.php b/web/index.php
new file mode 100644
index 0000000..88c9711
--- /dev/null
+++ b/web/index.php
@@ -0,0 +1,103 @@
+<?php
+include_once $_SERVER['DOCUMENT_ROOT'] . '/config.php';
+include_once $_SERVER['DOCUMENT_ROOT'] . '/partials.php';
+
+$db = new PDO(DB_URL, DB_USER, DB_PASS);
+
+$channel = $_GET['c'] ?? null;
+$user = $_GET['u'] ?? null;
+
+if (isset($channel, $user)) {
+ $stmt = $db->prepare('SELECT w.name, SUM(cw.usage_count) AS usage_count
+ FROM channel_words cw
+ INNER JOIN words w ON w.id = cw.word_id
+ INNER JOIN channels c ON c.alias_name = ?
+ INNER JOIN users u ON u.alias_name = ?
+ WHERE cw.channel_id = c.id AND cw.user_id = u.id
+ GROUP BY cw.word_id
+ ORDER BY usage_count DESC
+ LIMIT 100
+ ');
+ $stmt->execute([$channel, $user]);
+} else if (isset($channel)) {
+ $stmt = $db->prepare('SELECT w.name, SUM(cw.usage_count) AS usage_count
+ FROM channel_words cw
+ INNER JOIN words w ON w.id = cw.word_id
+ INNER JOIN channels c ON c.alias_name = ?
+ WHERE cw.channel_id = c.id
+ GROUP BY cw.word_id
+ ORDER BY usage_count DESC
+ LIMIT 100
+ ');
+ $stmt->execute([$channel]);
+} else if (isset($user)) {
+ $stmt = $db->prepare('SELECT w.name, SUM(cw.usage_count) AS usage_count
+ FROM channel_words cw
+ INNER JOIN words w ON w.id = cw.word_id
+ INNER JOIN users u ON u.alias_name = ?
+ WHERE cw.user_id = u.id
+ GROUP BY cw.word_id
+ ORDER BY usage_count DESC
+ LIMIT 100
+ ');
+ $stmt->execute([$user]);
+} else {
+ $stmt = $db->prepare('SELECT w.name, SUM(cw.usage_count) AS usage_count
+ FROM channel_words cw
+ INNER JOIN words w ON w.id = cw.word_id
+ GROUP BY cw.word_id
+ ORDER BY usage_count DESC
+ LIMIT 100
+ ');
+ $stmt->execute();
+}
+
+$words = $stmt->fetchAll(PDO::FETCH_ASSOC);
+?>
+<!DOCTYPE html>
+<html>
+
+<head>
+ <title><?= INSTANCE_NAME ?></title>
+ <link rel="stylesheet" href="/static/style.css">
+ <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
+</head>
+
+<body>
+ <?php html_header(); ?>
+ <main class="row gap-8">
+ <form action="/" method="get">
+ <div class="box">
+ <div class="tab">Search</div>
+ <div class="content">
+ <input type="text" name="c" placeholder="Enter Twitch channel..." value="<?= $channel ?>">
+ <input type="text" name="u" placeholder="Enter Twitch user..." value="<?= $user ?>">
+ <button type="submit">Search</button>
+ </div>
+ </div>
+ </form>
+ <section class="column gap-8 grow">
+ <div class="scoreboard-showcase">
+ <div class="box">
+ <p class="tab">
+ <img src="/static/img/icons/word.png" alt=""> Words
+ </p>
+ <div class="content scoreboard">
+ <?php if (empty($words)): ?>
+ <p><i>No words.</i></p>
+ <?php endif; ?>
+ <?php foreach ($words as $i => $word): ?>
+ <div class="scoreboard-item">
+ <p class="scoreboard-place"><?= $i + 1 ?>.</p>
+ <p class="scoreboard-name"><?= $word['name'] ?></p>
+ <p class="scoreboard-counter"><?= $word['usage_count'] ?></p>
+ </div>
+ <?php endforeach; ?>
+ </div>
+ </div>
+ </div>
+ </section>
+ </main>
+</body>
+
+</html> \ No newline at end of file
diff --git a/web/partials.php b/web/partials.php
new file mode 100644
index 0000000..adbbd01
--- /dev/null
+++ b/web/partials.php
@@ -0,0 +1,23 @@
+<?php
+include_once $_SERVER['DOCUMENT_ROOT'] . '/config.php';
+
+function html_header()
+{
+ $u = $_GET['u'] ?: null;
+ $c = $_GET['c'] ?: null;
+
+ echo '' ?>
+ <header>
+ <a href="/"><img src="/static/img/brand/small.webp" alt=""> <?= INSTANCE_NAME ?></a>
+ <?php if (isset($c)): ?>
+ <p>&gt; <a href="/?c=<?= $c ?>">&#35;<?= $c ?></a></p>
+ <?php endif; ?>
+ <?php if (isset($u)): ?>
+ <p>&gt; <a href="/?u=<?= $u ?>"><?= $u ?></a></p>
+ <?php endif; ?>
+ <?php if (isset($u, $c)): ?>
+ <p> &gt; <a href="/?c=<?= $c ?>&u=<?= $u ?>"><?= $u ?> in &#35;<?= $c ?></a></p>
+ <?php endif; ?>
+ </header>
+ <?php ;
+} \ No newline at end of file
diff --git a/web/static/img/icons/word.png b/web/static/img/icons/word.png
new file mode 100755
index 0000000..b7960db
--- /dev/null
+++ b/web/static/img/icons/word.png
Binary files differ
diff --git a/web/static/style.css b/web/static/style.css
new file mode 100644
index 0000000..c1af9b7
--- /dev/null
+++ b/web/static/style.css
@@ -0,0 +1,99 @@
+:root {
+ --header-background: #dddddd;
+ --header-border: #c4c4c4;
+
+ --box-tab-background: #e0ecd7;
+ --box-tab-color: #373829;
+ --box-border: #a4b393;
+}
+
+* {
+ margin: 0;
+ padding: 0;
+}
+
+body {
+ width: 100%;
+ min-height: 100vh;
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+header {
+ background: var(--header-background);
+ border-bottom: var(--header-border) solid 2px;
+ color: var(--header-border);
+ font-family: monospace;
+
+ display: flex;
+ flex-direction: row;
+ gap: 8px;
+}
+
+header,
+main {
+ padding: 4px;
+}
+
+.box {
+ border: 2px solid var(--box-border);
+}
+
+.box>.tab {
+ background: var(--box-tab-background);
+ color: var(--box-tab-color);
+ padding: 2px;
+ border-bottom: 2px solid var(--box-border);
+ display: flex;
+ align-items: center;
+}
+
+.box>.content {
+ padding: 4px;
+}
+
+.box>.content.scoreboard {
+ padding: 0 4px;
+}
+
+.scoreboard-showcase {
+ display: grid;
+ grid-template-columns: auto auto auto;
+ gap: 4px;
+ flex-grow: 1;
+}
+
+.scoreboard {
+ max-height: 256px;
+ overflow-y: scroll;
+}
+
+.scoreboard-item {
+ display: flex;
+ flex-direction: row;
+}
+
+.scoreboard-name {
+ flex-grow: 1;
+}
+
+.scoreboard-place {
+ width: 38px;
+}
+
+.row {
+ display: flex;
+ flex-direction: row;
+}
+
+.column {
+ display: flex;
+ flex-direction: column;
+}
+
+.grow {
+ flex-grow: 1;
+}
+
+.gap-8 {
+ gap: 8px;
+} \ No newline at end of file