Files
scholarships-rs/src/common/form_schema.rs
T

128 lines
5.3 KiB
Rust

use crate::common::ValueType;
use crate::components::{CheckboxList, OutlinedTextField, RadioList, Row, Select, TextFieldType};
use leptos::prelude::*;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
/// Defines a series of options that allow a user to define a form.
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum InputType {
/// Represents a text input. Requires a `String` key, `String` label, and `String` placeholder.
/// The entered value will be returned as a single `String` value.
Text(String, String, String, bool),
/// Represents a number input. Requires a `String` key, `String` label, and a `String` placeholder.
/// The entered value will be returned as a `String`, and will be parseable into any number type
/// (i.e. an `i32`, `i64`, etc)
Number(String, String, String, bool),
/// Represents a radio input. Requires a `String` key, `String` label, and a series of `String`
/// options. The selected value will be returned as a `String`.
Radio(String, String, Vec<String>, bool),
/// Represents a checkbox input. Requires a `String` key, `String` label, and a series of `String`
/// options. The selected values will be returned as a `Vec<String>`.
Checkbox(String, String, Vec<String>, bool),
/// Represents a dropdown input. Requires a `String` key, `String` label, and a series
/// of `String` options. The selected value will be returned as a `String`.
Select(String, String, Vec<String>, bool),
}
impl InputType {
/// Converts an `InputType` into an `impl IntoView`. A name must be specified in the case that
/// the component is a checkbox/radio list, which requires a unique name to function properly.
/// Many times, the name will be the same as the data member.
pub fn into_view(
self,
data_map: RwSignal<HashMap<String, ValueType>>,
name: String,
) -> impl IntoView {
view! {
{match self {
InputType::Text(member, label, placeholder, required) =>
view! {
<Row>
<OutlinedTextField
label = label.clone()
placeholder = placeholder.clone()
data_member = member.clone()
data_map = data_map
required = required
/>
</Row>
}.into_any(),
InputType::Number(member, label, placeholder, required) =>
view! {
<OutlinedTextField
label = label.clone()
placeholder = placeholder.clone()
data_member = member.clone()
data_map = data_map
input_type = TextFieldType::Number
required = required
/>
}.into_any(),
InputType::Checkbox(member, label, options, required) =>
view! {
<CheckboxList
label = label.clone()
name = name.clone()
items = options.clone()
data_member = member.clone()
data_map = data_map
required = required
/>
}.into_any(),
InputType::Radio(member, label, options, required) =>
view! {
<RadioList
label = label.clone()
data_member = member.clone()
data_map = data_map
items = options.clone()
required = required
/>
}.into_any(),
InputType::Select(member, label, options, required) =>
view! {
<Select
label = label.clone()
value_list = options.clone()
data_member = member.clone()
data_map = data_map
required = required
/>
}.into_any()
}}
}
}
}
/// Shorthand macro for creating `InputType` enums.
///
/// Example usage:
/// ```
/// // To create an InputType::Text
/// let text_input = input!(Text, "member", "label", "placeholder");
///
/// // To create an InputType::Select
/// let select_input = input!(Select, "member", "label", ["option1", "option2"]);
/// ```
#[macro_export]
macro_rules! input {
($variant:ident, $key:expr, $label:expr, $required:expr, [$($option:expr),* $(,)?]) => {
$crate::common::InputType::$variant(
$key.to_string(),
$label.to_string(),
vec![$($option.to_string()), *],
$required
)
};
($variant:ident, $key:expr, $label:expr, $required:expr, $placeholder:expr) => {
$crate::common::InputType::$variant(
$key.to_string(),
$label.to_string(),
$placeholder.to_string(),
$required
)
};
}