crm.rs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. //! Tiny CRM: A port of the Yew CRM example to Dioxus.
  2. #![allow(non_snake_case)]
  3. use std::sync::{Arc, Mutex};
  4. use dioxus::prelude::*;
  5. use dioxus_router::prelude::*;
  6. fn main() {
  7. dioxus_desktop::launch(App);
  8. }
  9. #[derive(Clone, Debug, Default)]
  10. pub struct Client {
  11. pub first_name: String,
  12. pub last_name: String,
  13. pub description: String,
  14. }
  15. type ClientContext = Arc<Mutex<Vec<Client>>>;
  16. fn App(cx: Scope) -> Element {
  17. use_router(cx, &|| RouterConfiguration::default(), &|| {
  18. Segment::content(comp(ClientList))
  19. .fixed(
  20. "new",
  21. Route::content(comp(ClientAdd)).name::<ClientAddName>(),
  22. )
  23. .fixed(
  24. "settings",
  25. Route::content(comp(Settings)).name::<SettingsName>(),
  26. )
  27. });
  28. use_context_provider::<ClientContext>(&cx, Default::default);
  29. render! {
  30. link {
  31. rel: "stylesheet",
  32. href: "https://unpkg.com/purecss@2.0.6/build/pure-min.css",
  33. integrity: "sha384-Uu6IeWbM+gzNVXJcM9XV3SohHtmWE+3VGi496jvgX1jyvDTXfdK+rfZc8C1Aehk5",
  34. crossorigin: "anonymous",
  35. }
  36. style { "
  37. .red {{
  38. background-color: rgb(202, 60, 60) !important;
  39. }}
  40. " }
  41. h1 { "Dioxus CRM Example" }
  42. Outlet { }
  43. }
  44. }
  45. fn ClientList(cx: Scope) -> Element {
  46. let clients = use_context::<ClientContext>(cx).unwrap();
  47. cx.render(rsx! {
  48. h2 { "List of Clients" }
  49. Link {
  50. target: named::<ClientAddName>(),
  51. class: "pure-button pure-button-primary",
  52. "Add Client"
  53. }
  54. Link {
  55. target: named::<SettingsName>(),
  56. class: "pure-button",
  57. "Settings"
  58. }
  59. clients.lock().unwrap().iter().map(|client| rsx! {
  60. div {
  61. class: "client",
  62. style: "margin-bottom: 50px",
  63. p { "Name: {client.first_name} {client.last_name}" }
  64. p { "Description: {client.description}" }
  65. }
  66. })
  67. })
  68. }
  69. struct ClientAddName;
  70. fn ClientAdd(cx: Scope) -> Element {
  71. let clients = use_context::<ClientContext>(cx).unwrap();
  72. let first_name = use_state(&cx, String::new);
  73. let last_name = use_state(&cx, String::new);
  74. let description = use_state(&cx, String::new);
  75. let navigator = use_navigate(&cx).unwrap();
  76. cx.render(rsx! {
  77. h2 { "Add new Client" }
  78. form {
  79. class: "pure-form pure-form-aligned",
  80. onsubmit: move |_| {
  81. let mut clients = clients.lock().unwrap();
  82. clients.push(Client {
  83. first_name: first_name.to_string(),
  84. last_name: last_name.to_string(),
  85. description: description.to_string(),
  86. });
  87. navigator.push(named::<RootIndex>());
  88. },
  89. fieldset {
  90. div {
  91. class: "pure-control-group",
  92. label {
  93. "for": "first_name",
  94. "First Name"
  95. }
  96. input {
  97. id: "first_name",
  98. "type": "text",
  99. placeholder: "First Name…",
  100. required: "",
  101. value: "{first_name}",
  102. oninput: move |e| first_name.set(e.value.clone())
  103. }
  104. }
  105. div {
  106. class: "pure-control-group",
  107. label {
  108. "for": "last_name",
  109. "Last Name"
  110. }
  111. input {
  112. id: "last_name",
  113. "type": "text",
  114. placeholder: "Last Name…",
  115. required: "",
  116. value: "{last_name}",
  117. oninput: move |e| last_name.set(e.value.clone())
  118. }
  119. }
  120. div {
  121. class: "pure-control-group",
  122. label {
  123. "for": "description",
  124. "Description"
  125. }
  126. textarea {
  127. id: "description",
  128. placeholder: "Description…",
  129. value: "{description}",
  130. oninput: move |e| description.set(e.value.clone())
  131. }
  132. }
  133. div {
  134. class: "pure-controls",
  135. button {
  136. "type": "submit",
  137. class: "pure-button pure-button-primary",
  138. "Save"
  139. }
  140. Link {
  141. target: named::<RootIndex>(),
  142. class: "pure-button pure-button-primary red",
  143. "Cancel"
  144. }
  145. }
  146. }
  147. }
  148. })
  149. }
  150. struct SettingsName;
  151. fn Settings(cx: Scope) -> Element {
  152. let clients = use_context::<ClientContext>(&cx).unwrap();
  153. cx.render(rsx! {
  154. h2 { "Settings" }
  155. button {
  156. class: "pure-button pure-button-primary red",
  157. onclick: move |_| {
  158. let mut clients = clients.lock().unwrap();
  159. clients.clear();
  160. },
  161. "Remove all Clients"
  162. }
  163. Link {
  164. target: named::<RootIndex>(),
  165. class: "pure-button",
  166. "Go back"
  167. }
  168. })
  169. }