logicaffeine_web/ui/pages/
workspace.rs1use dioxus::prelude::*;
19#[cfg(all(feature = "split", target_arch = "wasm32"))]
20use dioxus::wasm_split;
21use crate::ui::state::AppState;
22use crate::ui::components::chat::ChatDisplay;
23use crate::ui::components::input::InputArea;
24use crate::ui::components::main_nav::{MainNav, ActivePage};
25use crate::ui::seo::PageHead;
26
27const WORKSPACE_STYLE: &str = r#"
28.workspace {
29 height: 100vh;
30 display: flex;
31 flex-direction: column;
32}
33
34.workspace-header {
35 background: rgba(0, 0, 0, 0.3);
36 backdrop-filter: blur(10px);
37 padding: 16px 24px;
38 border-bottom: 1px solid rgba(255, 255, 255, 0.1);
39 display: flex;
40 justify-content: space-between;
41 align-items: center;
42}
43
44.workspace-header .breadcrumb {
45 display: flex;
46 align-items: center;
47 gap: 8px;
48}
49
50.workspace-header .breadcrumb a {
51 color: #888;
52 text-decoration: none;
53 font-size: 14px;
54}
55
56.workspace-header .breadcrumb a:hover {
57 color: #00d4ff;
58}
59
60.workspace-header .breadcrumb span {
61 color: #666;
62}
63
64.workspace-header h1 {
65 font-size: 20px;
66 font-weight: 600;
67 background: linear-gradient(90deg, #00d4ff, #7b2cbf);
68 -webkit-background-clip: text;
69 -webkit-text-fill-color: transparent;
70}
71
72.workspace-content {
73 flex: 1;
74 display: flex;
75 overflow: hidden;
76}
77
78.sidebar {
79 width: 260px;
80 background: rgba(0, 0, 0, 0.2);
81 border-right: 1px solid rgba(255, 255, 255, 0.1);
82 padding: 20px;
83 overflow-y: auto;
84}
85
86.sidebar h3 {
87 color: #888;
88 font-size: 12px;
89 text-transform: uppercase;
90 letter-spacing: 1px;
91 margin-bottom: 16px;
92}
93
94.lesson-tree {
95 list-style: none;
96}
97
98.lesson-tree li {
99 padding: 10px 12px;
100 margin-bottom: 4px;
101 border-radius: 8px;
102 color: #aaa;
103 font-size: 14px;
104 cursor: pointer;
105 transition: all 0.2s ease;
106}
107
108.lesson-tree li:hover {
109 background: rgba(255, 255, 255, 0.05);
110 color: #fff;
111}
112
113.lesson-tree li.active {
114 background: rgba(102, 126, 234, 0.2);
115 color: #667eea;
116}
117
118.lesson-tree li.locked {
119 opacity: 0.4;
120 cursor: not-allowed;
121}
122
123.main-area {
124 flex: 1;
125 display: flex;
126 flex-direction: column;
127 overflow: hidden;
128}
129
130.inspector {
131 width: 300px;
132 background: rgba(0, 0, 0, 0.2);
133 border-left: 1px solid rgba(255, 255, 255, 0.1);
134 padding: 20px;
135 overflow-y: auto;
136}
137
138.inspector h3 {
139 color: #888;
140 font-size: 12px;
141 text-transform: uppercase;
142 letter-spacing: 1px;
143 margin-bottom: 16px;
144}
145
146.inspector-placeholder {
147 color: #666;
148 font-size: 14px;
149 font-style: italic;
150 text-align: center;
151 padding: 40px 20px;
152}
153
154@media (max-width: 900px) {
155 .sidebar, .inspector {
156 display: none;
157 }
158}
159"#;
160
161#[component(lazy)]
162pub fn Workspace(subject: String) -> Element {
163 let mut state = use_context_provider(|| Signal::new(AppState::new()));
164
165 let title = match subject.as_str() {
166 "logic" => "First-Order Logic",
167 "english" => "English",
168 "coding" => "Coding",
169 "math" => "Mathematics",
170 _ => "Workspace",
171 };
172 let page_title = format!("{} Workspace - LOGICAFFEINE", title);
173 let page_path = format!("/workspace/{}", subject);
174
175 rsx! {
176 PageHead {
177 title: page_title,
178 description: "Interactive workspace for practicing formal logic and reasoning.",
179 canonical_path: page_path,
180 }
181 style { "{WORKSPACE_STYLE}" }
182
183 MainNav { active: ActivePage::Studio, subtitle: Some(title) }
184
185 div { class: "workspace",
186 div { class: "workspace-content",
187 div { class: "sidebar",
188 h3 { "The Path" }
189 ul { class: "lesson-tree",
190 li { class: "active", "1. Basic Propositions" }
191 li { "2. Connectives" }
192 li { "3. Quantifiers" }
193 li { "4. Predicates" }
194 li { class: "locked", "5. Modal Logic" }
195 li { class: "locked", "6. Temporal Logic" }
196 }
197
198 h3 { style: "margin-top: 32px;", "History" }
199 p { style: "color: #666; font-size: 13px;", "Your recent sessions will appear here." }
200 }
201
202 div { class: "main-area",
203 ChatDisplay { messages: state.read().get_history() }
204 InputArea { on_send: move |text| state.write().add_user_message(text) }
205 }
206
207 div { class: "inspector",
208 h3 { "AST Inspector" }
209 div { class: "inspector-placeholder",
210 "Parse a sentence to see its abstract syntax tree visualization here."
211 }
212 }
213 }
214 }
215 }
216}