-
Notifications
You must be signed in to change notification settings - Fork 18
Expand file tree
/
Copy pathmain.rs
More file actions
104 lines (95 loc) · 2.93 KB
/
main.rs
File metadata and controls
104 lines (95 loc) · 2.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use ohkami::prelude::*;
use ohkami::serde::Deserialize;
use ohkami::format::{Query, Html};
use uibeam::{UI, Beam};
struct Layout {
title: String,
children: UI,
}
impl Beam for Layout {
fn render(self) -> UI {
UI! {
<html>
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" />
<title>{&*self.title}</title>
</head>
<body>
{self.children}
</body>
</html>
}
}
}
impl Layout {
fn fang_with_title(title: &str) -> impl FangAction {
#[derive(Clone)]
struct Fang {
title: String,
}
impl FangAction for Fang {
async fn back(&self, res: &mut Response) {
if res.headers.ContentType().is_some_and(|x| x.starts_with("text/html")) {
let content = res.drop_content().into_bytes().unwrap();
let content = std::str::from_utf8(&*content).unwrap();
res.set_html(uibeam::shoot(UI! {
<Layout title={self.title.clone()}>
unsafe {content}
</Layout>
}));
}
}
}
Fang {
title: title.to_string(),
}
}
}
struct Counter {
initial_count: i32,
}
impl Beam for Counter {
fn render(self) -> UI {
UI! {
<div>
<h1 class="text-2xl font-bold">
"count: "<span id="count">{self.initial_count}</span>
</h1>
<button
id="increment"
class="bg-blue-500 text-white px-4 py-2 rounded"
>"+"</button>
<button
id="decrement"
class="bg-red-500 text-white px-4 py-2 rounded"
>"-"</button>
<script>r#"
const count = document.getElementById('count');
document.getElementById('increment').addEventListener('click', () => {
count.innerText = parseInt(count.innerText) + 1;
});
document.getElementById('decrement').addEventListener('click', () => {
count.innerText = parseInt(count.innerText) - 1;
});
"#</script>
</div>
}
}
}
#[derive(Deserialize)]
struct CounterMeta {
init: Option<i32>,
}
async fn index(Query(q): Query<CounterMeta>) -> Html<std::borrow::Cow<'static, str>> {
let initial_count = q.init.unwrap_or(0);
Html(uibeam::shoot(UI! {
<Counter initial_count={initial_count} />
}))
}
#[tokio::main]
async fn main() {
Ohkami::new((
Layout::fang_with_title("Counter Example"),
"/".GET(index),
)).howl("localhost:5555").await
}