88 lines
2.6 KiB
Rust
88 lines
2.6 KiB
Rust
mod components;
|
|
use std::time::Duration;
|
|
|
|
use axum::{extract::State, response::IntoResponse};
|
|
use axum_controller::*;
|
|
use datastar::{
|
|
axum::ReadSignals,
|
|
prelude::{FragmentMergeMode, MergeFragments},
|
|
Sse,
|
|
};
|
|
use hypertext::{maud, GlobalAttributes, Renderable};
|
|
use serde::Deserialize;
|
|
|
|
use crate::{ui::components::*, AppState};
|
|
|
|
pub mod html_elements {
|
|
use hypertext::elements;
|
|
pub use hypertext::html_elements::*;
|
|
|
|
elements! {
|
|
bla {
|
|
blub
|
|
}
|
|
my_element {
|
|
my_attribute
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Deserialize, Debug)]
|
|
struct Signals {
|
|
msginput: String,
|
|
}
|
|
|
|
pub struct UiController {}
|
|
|
|
#[controller(
|
|
state = AppState
|
|
)]
|
|
impl UiController {
|
|
#[route(GET "/msg")]
|
|
#[tracing::instrument]
|
|
async fn message(
|
|
State(_): State<AppState>,
|
|
ReadSignals(signals): ReadSignals<Signals>,
|
|
) -> impl IntoResponse {
|
|
tokio::time::sleep(Duration::from_millis(250)).await;
|
|
|
|
Sse(async_stream::stream! {
|
|
yield MergeFragments::new(maud! { div #user-1 class="mb-2 animated animated-bounce" { strong { "You:" } (signals.msginput) } }.render())
|
|
.selector("#chat")
|
|
.merge_mode(FragmentMergeMode::Append)
|
|
.into();
|
|
|
|
tokio::time::sleep(Duration::from_millis(250)).await;
|
|
|
|
yield MergeFragments::new(maud! { div #llm-1 class="mb-2 animated animated-bounce" { strong { "LLM:" } "This is a mock response."} }.render())
|
|
.selector("#chat")
|
|
.merge_mode(FragmentMergeMode::Append)
|
|
.into();
|
|
})
|
|
}
|
|
|
|
#[route(GET "/")]
|
|
#[tracing::instrument]
|
|
async fn index(State(_): State<AppState>) -> impl IntoResponse {
|
|
main_page(maud! {
|
|
div .container .p-4 .mx-auto {
|
|
h1 .m-4 .text-2xl .font-bold {
|
|
"LLM Chat App"
|
|
}
|
|
div .p-6 .bg-white .rounded-lg .shadow-md {
|
|
div #chat .m-4 {
|
|
// Chat messages will appear here
|
|
}
|
|
form id="chat-form" {
|
|
textarea #user-input .p-2 .m-2 .w-full .rounded-lg .border data-bind-msginput placeholder="Type your message..." {}
|
|
button #send-btn class="btn" type="button" data-on-click="@get('/msg')" {
|
|
"Send"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
)
|
|
.render()
|
|
}
|
|
}
|