diff options
| author | ilotterytea <iltsu@alright.party> | 2025-10-14 15:36:31 +0500 |
|---|---|---|
| committer | ilotterytea <iltsu@alright.party> | 2025-10-14 15:36:31 +0500 |
| commit | 33fd114a314212b8759b525fb9e08d4ff4ca8869 (patch) | |
| tree | 7abbb155a7515148f355b30978e3a0fa77913fd1 | |
| parent | d6196a61348dbd0040e332147ef4a34ade64b309 (diff) | |
feat: web frontend
| -rw-r--r-- | web/config.php | 12 | ||||
| -rw-r--r-- | web/index.php | 103 | ||||
| -rw-r--r-- | web/partials.php | 23 | ||||
| -rwxr-xr-x | web/static/img/icons/word.png | bin | 0 -> 567 bytes | |||
| -rw-r--r-- | web/static/style.css | 99 |
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>> <a href="/?c=<?= $c ?>">#<?= $c ?></a></p> + <?php endif; ?> + <?php if (isset($u)): ?> + <p>> <a href="/?u=<?= $u ?>"><?= $u ?></a></p> + <?php endif; ?> + <?php if (isset($u, $c)): ?> + <p> > <a href="/?c=<?= $c ?>&u=<?= $u ?>"><?= $u ?> in #<?= $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 Binary files differnew file mode 100755 index 0000000..b7960db --- /dev/null +++ b/web/static/img/icons/word.png 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 |
