MaCH repo
This commit is contained in:
1
07_roundest_pokemon_htmx/README.md
Normal file
1
07_roundest_pokemon_htmx/README.md
Normal file
@@ -0,0 +1 @@
|
||||
compare to https://github.com/t3dotgg/1app5stacks
|
||||
7
07_roundest_pokemon_htmx/create_pokemons_table.sql
Normal file
7
07_roundest_pokemon_htmx/create_pokemons_table.sql
Normal file
@@ -0,0 +1,7 @@
|
||||
CREATE TABLE IF NOT EXISTS pokemons (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
sprite TEXT NOT NULL,
|
||||
wins INTEGER NOT NULL DEFAULT 0,
|
||||
loses INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
4
07_roundest_pokemon_htmx/get_challengers.sql
Normal file
4
07_roundest_pokemon_htmx/get_challengers.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
select id, name, sprite
|
||||
from pokemons
|
||||
order by random()
|
||||
limit 2;
|
||||
5
07_roundest_pokemon_htmx/get_results.sql
Normal file
5
07_roundest_pokemon_htmx/get_results.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
select id, name, sprite, wins, loses,
|
||||
cast(wins as real) / nullif(loses, 0) as ratio_of_wins_to_loses,
|
||||
row_number() over (order by (cast(wins as real) / nullif(loses, 0)) desc) as rank
|
||||
from pokemons
|
||||
order by ratio_of_wins_to_loses desc;
|
||||
53
07_roundest_pokemon_htmx/home.mustache.html
Normal file
53
07_roundest_pokemon_htmx/home.mustache.html
Normal file
@@ -0,0 +1,53 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Roundest (MaCH Version)</title>
|
||||
{{> htmx }}
|
||||
{{> tailwind }}
|
||||
</head>
|
||||
<body hx-boost='true'>
|
||||
<div class='bg-gray-950 text-white flex flex-col justify-between font-geist min-h-screen border-t-2 border-red-300'>
|
||||
<nav class='flex flex-row justify-between items-center py-4 px-8'>
|
||||
<div class='flex items-baseline'>
|
||||
<a href='{{url:home}}' class='font-bold text-3xl'>
|
||||
Round<span class='text-red-300'>est</span>
|
||||
</a>
|
||||
<p class='text-gray-400 font-extralight pl-2 text-2xl'>
|
||||
(MaCH Version)
|
||||
</p>
|
||||
</div>
|
||||
<div class='flex flex-row items-center gap-8'>
|
||||
<a href='{{url:results}}' class='hover:underline text-lg'>Results</a>
|
||||
</div>
|
||||
</nav>
|
||||
<main>
|
||||
{{$body}}
|
||||
<div class='container mx-auto px-4'>
|
||||
<h1 class='text-3xl font-bold text-center mb-8'>Vote for which is roundest</h1>
|
||||
<div class='flex justify-center gap-16 items-center min-h-[80vh]'>
|
||||
{{#challengers}}
|
||||
<form action='{{url:home}}' method='post'>
|
||||
<div class='flex flex-col items-center gap-4'>
|
||||
<img src='{{sprite}}' alt='{{name}}' class='w-64 h-64 sprite'>
|
||||
<div class='text-center'>
|
||||
<span class='text-gray-500 text-lg'>#{{id}}</span>
|
||||
<h2 class='text-2xl font-bold capitalize'>{{name}}</h2>
|
||||
<input type='hidden' name='winner' value='{{id}}'>
|
||||
<input type='hidden' name='loser' value='{{opponent_id}}'>
|
||||
<button class='mt-4 px-8 py-3 bg-blue-500 text-white rounded-lg text-lg font-semibold hover:bg-blue-600 transition-colors'>
|
||||
Vote
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{{/challengers}}
|
||||
</div>
|
||||
</div>
|
||||
{{/body}}
|
||||
</main>
|
||||
<footer class='font-light text-center py-3 text-gray-500'>
|
||||
<a href='https://code.nightshadecoder.dev/nightshade/mach_examples' target='_blank'>GitHub</a>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
46
07_roundest_pokemon_htmx/main.c
Normal file
46
07_roundest_pokemon_htmx/main.c
Normal file
@@ -0,0 +1,46 @@
|
||||
#include <mach.h>
|
||||
#include <htmx.h>
|
||||
#include <sqlite.h>
|
||||
#include <tailwind.h>
|
||||
|
||||
void mach(){
|
||||
resource("home", "/",
|
||||
.get = {
|
||||
sqlite_query({"pokemon_db", "get_challengers", "challengers"}),
|
||||
exec(^(){
|
||||
auto const t = get("challengers");
|
||||
auto const p0 = table_get(t, 0);
|
||||
auto const p1 = table_get(t, 1);
|
||||
record_set(p0, "opponent_id", record_get(p1, "id"));
|
||||
record_set(p1, "opponent_id", record_get(p0, "id"));
|
||||
}),
|
||||
mustache("home")
|
||||
},
|
||||
|
||||
.post = {
|
||||
input(
|
||||
{"winner", m_positive},
|
||||
{"loser", m_positive}
|
||||
),
|
||||
sqlite_query({"pokemin_db", "vote"}),
|
||||
reroute("home")
|
||||
}
|
||||
);
|
||||
|
||||
resource("result", "/results",
|
||||
.get = {
|
||||
sqlite_query({"pokemon_db", "get_results", "results"}),
|
||||
mustache("results")
|
||||
}
|
||||
);
|
||||
|
||||
sqlite_database(
|
||||
.name = "pokemon_db",
|
||||
.connect = "file::memory:?cache=shared",
|
||||
.migrations = {"create_pokemons_table.sql"}
|
||||
);
|
||||
|
||||
htmx();
|
||||
sqlite();
|
||||
tailwind();
|
||||
}
|
||||
28
07_roundest_pokemon_htmx/results.mustache.html
Normal file
28
07_roundest_pokemon_htmx/results.mustache.html
Normal file
@@ -0,0 +1,28 @@
|
||||
{{< home}}
|
||||
{{$body}}
|
||||
<div class='container mx-auto px-4 py-8 text-white'>
|
||||
<div class='grid gap-4'>
|
||||
{{#results}}
|
||||
<div class='flex items-center gap-6 p-6 bg-gray-800/40 rounded-lg shadow hover:shadow-md transition-shadow'>
|
||||
<div class='text-2xl font-bold text-gray-400 w-8'>
|
||||
{{rank}}
|
||||
</div>
|
||||
<img src='{{sprite}}' alt='{{name}}' loading='lazy' class='w-20 h-20'>
|
||||
<div class='flex-grow'>
|
||||
<div class='text-gray-400 text-sm'>#{{id}}</div>
|
||||
<h2 class='text-xl font-semibold capitalize'>{{name}}</h2>
|
||||
</div>
|
||||
<div class='text-right'>
|
||||
<div class='text-2xl font-bold text-blue-400'>
|
||||
{{ratio_of_wins_to_loses}}
|
||||
</div>
|
||||
<div class='text-sm text-gray-400'>
|
||||
{{wins}}W - {{loses}}L
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/results}}
|
||||
</div>
|
||||
</div>
|
||||
{{/body}}
|
||||
{{/home}}
|
||||
8
07_roundest_pokemon_htmx/vote.sql
Normal file
8
07_roundest_pokemon_htmx/vote.sql
Normal file
@@ -0,0 +1,8 @@
|
||||
begin transaction;
|
||||
update pokemons
|
||||
set wins = wins + 1
|
||||
where id = {{winner}};
|
||||
update pokemons
|
||||
set loses = loses + 1
|
||||
where id = {{loser}};
|
||||
commit;
|
||||
Reference in New Issue
Block a user