mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-30 08:00:21 +00:00
c866ae602b
* Add `#[component]` attribute + system for creating component attributes + other stuff * Delete inlineprops.rs * Update inline_props.rs * Cargo fmt * Fix clippy warnings and paths in props/mods.rs * Include where clause in `#[inline_props]` output * Allow Clippy type complexity in `LinkProps` * Allow the type complexity lint for the entire link.rs file * Remove snake_case -> PascalCase converter, but rather enforce PascalCase Also: - Put the second function inside the main one instead of besides it. - Simplify * Simplify type check lints so they don't return false positives They will not always work, but they won't return any false positives, like for aliases. This is likely going to be replaced by a more polished Clippy-backed linting system. * Fix #583 * Cargo fmt * Add docs for `deserialize()` and remove useless comment * Add `#[component]` to prelude * Merge branch 'master' of https://github.com/tigerros/dioxus * #[inline_props] is no more. Except in the docs folder, but that's going to be removed * Remove docs folder * Remove docs from workspace * Resolve `DeserializerOutput` conversation
198 lines
5.2 KiB
Rust
198 lines
5.2 KiB
Rust
//! Tiny CRM: A port of the Yew CRM example to Dioxus.
|
|
use dioxus::prelude::*;
|
|
use dioxus_router::prelude::*;
|
|
|
|
fn main() {
|
|
dioxus_desktop::launch(App);
|
|
}
|
|
|
|
#[derive(Routable, Clone)]
|
|
#[rustfmt::skip]
|
|
enum Route {
|
|
#[route("/")]
|
|
ClientList {},
|
|
#[route("/new")]
|
|
ClientAdd {},
|
|
#[route("/settings")]
|
|
Settings {},
|
|
}
|
|
|
|
#[derive(Clone, Debug, Default)]
|
|
pub struct Client {
|
|
pub first_name: String,
|
|
pub last_name: String,
|
|
pub description: String,
|
|
}
|
|
|
|
type ClientContext = Vec<Client>;
|
|
|
|
#[component]
|
|
fn App(cx: Scope) -> Element {
|
|
use_shared_state_provider::<ClientContext>(cx, Default::default);
|
|
|
|
render! {
|
|
link {
|
|
rel: "stylesheet",
|
|
href: "https://unpkg.com/purecss@2.0.6/build/pure-min.css",
|
|
integrity: "sha384-Uu6IeWbM+gzNVXJcM9XV3SohHtmWE+3VGi496jvgX1jyvDTXfdK+rfZc8C1Aehk5",
|
|
crossorigin: "anonymous",
|
|
}
|
|
|
|
style { "
|
|
.red {{
|
|
background-color: rgb(202, 60, 60) !important;
|
|
}}
|
|
" }
|
|
|
|
h1 { "Dioxus CRM Example" }
|
|
|
|
Router::<Route> {}
|
|
}
|
|
}
|
|
|
|
#[component]
|
|
fn ClientList(cx: Scope) -> Element {
|
|
let clients = use_shared_state::<ClientContext>(cx).unwrap();
|
|
|
|
cx.render(rsx! {
|
|
h2 { "List of Clients" }
|
|
|
|
Link {
|
|
to: Route::ClientAdd {},
|
|
class: "pure-button pure-button-primary",
|
|
"Add Client"
|
|
}
|
|
Link {
|
|
to: Route::Settings {},
|
|
class: "pure-button",
|
|
"Settings"
|
|
}
|
|
|
|
clients.read().iter().map(|client| rsx! {
|
|
div {
|
|
class: "client",
|
|
style: "margin-bottom: 50px",
|
|
|
|
p { "Name: {client.first_name} {client.last_name}" }
|
|
p { "Description: {client.description}" }
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
#[component]
|
|
fn ClientAdd(cx: Scope) -> Element {
|
|
let clients = use_shared_state::<ClientContext>(cx).unwrap();
|
|
let first_name = use_state(cx, String::new);
|
|
let last_name = use_state(cx, String::new);
|
|
let description = use_state(cx, String::new);
|
|
|
|
let navigator = use_navigator(cx);
|
|
|
|
cx.render(rsx! {
|
|
h2 { "Add new Client" }
|
|
|
|
form {
|
|
class: "pure-form pure-form-aligned",
|
|
onsubmit: move |_| {
|
|
let mut clients = clients.write();
|
|
|
|
clients.push(Client {
|
|
first_name: first_name.to_string(),
|
|
last_name: last_name.to_string(),
|
|
description: description.to_string(),
|
|
});
|
|
|
|
navigator.push(Route::ClientList {});
|
|
},
|
|
|
|
fieldset {
|
|
div {
|
|
class: "pure-control-group",
|
|
label {
|
|
"for": "first_name",
|
|
"First Name"
|
|
}
|
|
input {
|
|
id: "first_name",
|
|
"type": "text",
|
|
placeholder: "First Name…",
|
|
required: "",
|
|
value: "{first_name}",
|
|
oninput: move |e| first_name.set(e.value.clone())
|
|
}
|
|
}
|
|
|
|
div {
|
|
class: "pure-control-group",
|
|
label {
|
|
"for": "last_name",
|
|
"Last Name"
|
|
}
|
|
input {
|
|
id: "last_name",
|
|
"type": "text",
|
|
placeholder: "Last Name…",
|
|
required: "",
|
|
value: "{last_name}",
|
|
oninput: move |e| last_name.set(e.value.clone())
|
|
}
|
|
}
|
|
|
|
div {
|
|
class: "pure-control-group",
|
|
label {
|
|
"for": "description",
|
|
"Description"
|
|
}
|
|
textarea {
|
|
id: "description",
|
|
placeholder: "Description…",
|
|
value: "{description}",
|
|
oninput: move |e| description.set(e.value.clone())
|
|
}
|
|
}
|
|
|
|
div {
|
|
class: "pure-controls",
|
|
button {
|
|
"type": "submit",
|
|
class: "pure-button pure-button-primary",
|
|
"Save"
|
|
}
|
|
Link {
|
|
to: Route::ClientList {},
|
|
class: "pure-button pure-button-primary red",
|
|
"Cancel"
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
})
|
|
}
|
|
|
|
#[component]
|
|
fn Settings(cx: Scope) -> Element {
|
|
let clients = use_shared_state::<ClientContext>(cx).unwrap();
|
|
|
|
cx.render(rsx! {
|
|
h2 { "Settings" }
|
|
|
|
button {
|
|
class: "pure-button pure-button-primary red",
|
|
onclick: move |_| {
|
|
let mut clients = clients.write();
|
|
clients.clear();
|
|
},
|
|
"Remove all Clients"
|
|
}
|
|
|
|
Link {
|
|
to: Route::ClientList {},
|
|
class: "pure-button",
|
|
"Go back"
|
|
}
|
|
})
|
|
}
|