reinhardt_admin/pages/components/
layout.rs1use reinhardt_pages::component::{IntoPage, Page, PageElement};
10
11#[derive(Debug, Clone)]
13pub struct ModelInfo {
14 pub name: String,
16 pub url: String,
18}
19
20pub fn header(site_name: &str, user_name: Option<&str>) -> Page {
32 let user_display = user_name.unwrap_or("Guest");
33
34 PageElement::new("nav")
35 .attr("class", "navbar navbar-dark bg-dark")
36 .child(
37 PageElement::new("div")
38 .attr("class", "container-fluid")
39 .child(
40 PageElement::new("a")
41 .attr("class", "navbar-brand")
42 .attr("href", "/admin/")
43 .child(site_name.to_string()),
44 )
45 .child(
46 PageElement::new("span")
47 .attr("class", "navbar-text")
48 .child(format!("User: {}", user_display)),
49 ),
50 )
51 .into_page()
52}
53
54pub fn sidebar(models: &[ModelInfo], current_path: Option<&str>) -> Page {
71 use reinhardt_pages::component::Component;
72 use reinhardt_pages::router::Link;
73
74 let nav_items: Vec<Page> = models
75 .iter()
76 .map(|model| {
77 let is_active = current_path.is_some_and(|path| path.starts_with(&model.url));
78 let item_class = if is_active {
79 "nav-link active"
80 } else {
81 "nav-link"
82 };
83
84 PageElement::new("li")
85 .attr("class", "nav-item")
86 .child(
87 Link::new(model.url.clone(), model.name.clone())
88 .class(item_class)
89 .render(),
90 )
91 .into_page()
92 })
93 .collect();
94
95 PageElement::new("div")
96 .attr("class", "sidebar bg-light border-end")
97 .attr(
98 "style",
99 "width: 250px; height: 100vh; position: fixed; top: 56px; left: 0; overflow-y: auto;",
100 )
101 .child(
102 PageElement::new("ul")
103 .attr("class", "nav flex-column")
104 .children(nav_items),
105 )
106 .into_page()
107}
108
109pub fn footer(version: &str) -> Page {
121 PageElement::new("footer")
122 .attr("class", "footer bg-light text-center py-3 border-top")
123 .attr("style", "margin-left: 250px;")
124 .child(
125 PageElement::new("div")
126 .attr("class", "container-fluid")
127 .child(format!("Reinhardt Admin Panel v{}", version)),
128 )
129 .into_page()
130}
131
132pub fn main_layout(
151 site_name: &str,
152 models: &[ModelInfo],
153 user_name: Option<&str>,
154 version: &str,
155 router: std::sync::Arc<reinhardt_pages::router::Router>,
156) -> Page {
157 use reinhardt_pages::component::Component;
158 use reinhardt_pages::router::RouterOutlet;
159
160 PageElement::new("div")
161 .attr("class", "admin-layout")
162 .child(header(site_name, user_name))
163 .child(sidebar(models, None))
164 .child(
165 PageElement::new("main")
166 .attr("class", "main-content")
167 .attr(
168 "style",
169 "margin-left: 250px; margin-top: 56px; padding: 20px; min-height: calc(100vh - 120px);",
170 )
171 .child(
172 RouterOutlet::new(router)
173 .id("admin-outlet")
174 .class("router-content")
175 .render(),
176 ),
177 )
178 .child(footer(version))
179 .into_page()
180}