1use axum_extra::routing::TypedPath;
2use http::StatusCode;
3
4use crate::{Children, Element, IntoNode, MaybeRedirect, Node, NodeId};
5
6pub struct LiveView {
7 pub id: String,
8 pub href: String,
9}
10
11impl LiveView {
12 pub fn new<I, T>(id: I, href: T) -> Self
13 where
14 I: ToString,
15 T: TypedPath,
16 {
17 Self {
18 id: id.to_string(),
19 href: href.to_string(),
20 }
21 }
22
23 pub fn view(self, inner: Node) -> Node {
24 Node::Element(
25 Element {
26 attributes: crate::Attributes::default()
27 .set(Some(("id", self.id.to_string())))
28 .set(Some(("href", self.href.to_string()))),
29 children: Children::default().set(inner),
30 name: "live-view",
31 },
32 NodeId::new(),
33 )
34 }
35}
36
37impl From<LiveView> for ComponentType {
38 fn from(item: LiveView) -> Self {
39 ComponentType::LiveView(item)
40 }
41}
42
43pub enum ComponentType {
44 LiveView(LiveView),
45 Component,
46}
47
48impl ComponentType {
49 pub fn view(self, inner: Node) -> Node {
50 match self {
51 ComponentType::LiveView(live_view) => live_view.view(inner),
52 ComponentType::Component => inner,
53 }
54 }
55}
56
57pub trait ComponentError {
58 fn message(&self) -> String {
59 "".to_string()
60 }
61}
62
63pub trait Component {
64 fn status_code(&self) -> StatusCode {
65 StatusCode::OK
66 }
67
68 fn ty(&self) -> ComponentType {
69 ComponentType::Component
70 }
71
72 fn view(self) -> Node;
73}
74
75impl<C> IntoNode for C
76where
77 C: Component,
78{
79 fn into_node(self) -> Node {
80 self.ty().view(self.view())
81 }
82}
83
84impl<C> From<C> for Node
85where
86 C: Component,
87{
88 fn from(item: C) -> Self {
89 item.ty().view(item.view())
90 }
91}
92
93impl<C> Component for Vec<C>
94where
95 C: Component + Clone,
96{
97 fn view(self) -> Node {
98 Node::Fragment(
99 Children {
100 children: self.iter().map(|c| c.clone().into_node()).collect(),
101 },
102 NodeId::new(),
103 )
104 }
105}
106
107impl<C> Component for Option<C>
108where
109 C: Component,
110{
111 fn view(self) -> Node {
112 match self {
113 Some(component) => component.into_node(),
114 None => Node::None,
115 }
116 }
117}
118
119impl<S, E> Component for Result<S, E>
120where
121 S: Component,
122 E: Component,
123{
124 fn view(self) -> Node {
125 match self {
126 Ok(s) => s.into_node(),
127 Err(e) => e.into_node(),
128 }
129 }
130}
131
132impl<C> Component for MaybeRedirect<C>
133where
134 C: Component,
135{
136 fn view(self) -> Node {
137 match self {
138 MaybeRedirect::Redirect(status_code, location) => {
139 Node::Redirect(status_code.clone(), location.clone())
140 }
141 MaybeRedirect::Else(component) => component.into_node(),
142 }
143 }
144}