1use dioxus::prelude::*;
4#[allow(unused_imports)]
5use dioxus_router::prelude::*;
6
7use crate::ui::{
8 layout::Layout,
9 pages::{Dashboard, Login, NotFound, Profile},
10 router::Route,
11 state::AppStateProvider,
12};
13
14#[component]
16pub fn App() -> Element {
17 rsx! {
18 AppStateProvider {
19 Router::<Route> {}
20 }
21 }
22}
23
24#[component]
26fn RootLayout() -> Element {
27 rsx! {
28 AppStateProvider {
29 div {
30 class: "min-h-screen bg-gray-50",
31 Outlet::<Route> {}
32 }
33 }
34 }
35}
36
37#[component]
39fn AuthGuard(children: Element) -> Element {
40 let app_state = use_context::<crate::ui::state::AppStateContext>();
41
42 let is_authenticated = app_state.current_user.is_some();
44
45 if is_authenticated {
46 rsx! { {children} }
47 } else {
48 rsx! {
49 div {
50 class: "min-h-screen flex items-center justify-center bg-gray-50",
51 Login {}
52 }
53 }
54 }
55}
56
57#[component]
59fn ProtectedRoute(children: Element) -> Element {
60 rsx! {
61 AuthGuard {
62 Layout {
63 {children}
64 }
65 }
66 }
67}
68
69#[derive(Clone, Routable, Debug, PartialEq)]
71pub enum AppRoute {
72 #[route("/")]
73 #[redirect("/dashboard", || AppRoute::DashboardPage {})]
74 HomePage {},
75
76 #[route("/login")]
77 LoginPage {},
78
79 #[route("/dashboard")]
80 DashboardPage {},
81
82 #[route("/profile")]
83 ProfilePage {},
84
85 #[route("/:..route")]
87 NotFoundPage { route: Vec<String> },
88}
89
90#[component]
92fn HomePage() -> Element {
93 rsx! {
94 ProtectedRoute {
95 Dashboard {}
96 }
97 }
98}
99
100#[component]
101fn LoginPage() -> Element {
102 rsx! {
103 div {
104 class: "min-h-screen flex items-center justify-center bg-gray-50",
105 Login {}
106 }
107 }
108}
109
110#[component]
111fn DashboardPage() -> Element {
112 rsx! {
113 ProtectedRoute {
114 Dashboard {}
115 }
116 }
117}
118
119#[component]
120fn ProfilePage() -> Element {
121 rsx! {
122 ProtectedRoute {
123 Profile {}
124 }
125 }
126}
127
128#[component]
129fn NotFoundPage(route: Vec<String>) -> Element {
130 rsx! {
131 div {
132 class: "min-h-screen flex items-center justify-center bg-gray-50",
133 NotFound {
134 path: route.join("/")
135 }
136 }
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use super::*;
143 use dioxus::prelude::*;
144
145 #[test]
146 fn app_component_renders() {
147 let mut vdom = VirtualDom::new(App);
149 let _ = vdom.rebuild_in_place();
150 }
151}