diff --git a/package-lock.json b/package-lock.json
index cca8a7f..c105687 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5,8 +5,7 @@
"packages": {
"": {
"dependencies": {
- "@tailwindcss/cli": "^4.1.5",
- "sass": "^1.92.0"
+ "@tailwindcss/cli": "^4.1.5"
},
"devDependencies": {
"tailwindcss": "^4.1.13"
@@ -589,21 +588,6 @@
"node": ">=8"
}
},
- "node_modules/chokidar": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
- "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
- "license": "MIT",
- "dependencies": {
- "readdirp": "^4.0.1"
- },
- "engines": {
- "node": ">= 14.16.0"
- },
- "funding": {
- "url": "https://paulmillr.com/funding/"
- }
- },
"node_modules/detect-libc": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
@@ -647,12 +631,6 @@
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"license": "ISC"
},
- "node_modules/immutable": {
- "version": "5.1.3",
- "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.3.tgz",
- "integrity": "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg==",
- "license": "MIT"
- },
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -975,48 +953,6 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/readdirp": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
- "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
- "license": "MIT",
- "engines": {
- "node": ">= 14.18.0"
- },
- "funding": {
- "type": "individual",
- "url": "https://paulmillr.com/funding/"
- }
- },
- "node_modules/sass": {
- "version": "1.92.0",
- "resolved": "https://registry.npmjs.org/sass/-/sass-1.92.0.tgz",
- "integrity": "sha512-KDNI0BxgIRDAfJgzNm5wuy+4yOCIZyrUbjSpiU/JItfih+KGXAVefKL53MTml054MmBA3DDKIBMSI/7XLxZJ3A==",
- "license": "MIT",
- "dependencies": {
- "chokidar": "^4.0.0",
- "immutable": "^5.0.2",
- "source-map-js": ">=0.6.2 <2.0.0"
- },
- "bin": {
- "sass": "sass.js"
- },
- "engines": {
- "node": ">=14.0.0"
- },
- "optionalDependencies": {
- "@parcel/watcher": "^2.4.1"
- }
- },
- "node_modules/source-map-js": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
- "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/tailwindcss": {
"version": "4.1.13",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.13.tgz",
diff --git a/src/app.rs b/src/app.rs
index d8b7104..e854ce4 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -7,7 +7,7 @@ use leptos_router::{
};
use url::Url;
-use crate::pages::{AboutPage, HomePage, ProviderEntry, UnauthenticatedPage};
+use crate::pages::{AboutPage, HomePage, UnauthenticatedPage};
pub fn shell(options: LeptosOptions) -> impl IntoView {
view! {
@@ -67,7 +67,6 @@ pub fn App() -> impl IntoView {
-
diff --git a/src/common/expandable_info.rs b/src/common/expandable_info.rs
index ebb0f8f..8f6c2b4 100644
--- a/src/common/expandable_info.rs
+++ b/src/common/expandable_info.rs
@@ -1,16 +1,16 @@
-use std::collections::HashMap;
-use serde::{Deserialize, Serialize};
+use crate::common::ValueType;
use macros::Reactive;
-use crate::components::ValueType;
+use serde::{Deserialize, Serialize};
+use std::collections::HashMap;
/// This struct allows for completely open-ended data storage.
-///
+///
/// The `HashMap` allows the application to store an arbitrary number of values which are accessible
/// using a `String` as a key, allowing for simple shifting of stored values. All information is
/// stored using the `ValueType` enum, which provides some simple methods to verify the type of the
/// stored value. It *must* have a main key member name so that a database will know how to store
/// the data.
-///
+///
/// In the future, this should also be optimized to store properly within a DynamoDB table. As of
/// now, the table will simply create a single massive `Map` field that contains all the stored
/// information in the `HashMap`. We'd prefer to be able to get single values if possible,
diff --git a/src/common/form_schema.rs b/src/common/form_schema.rs
index 5ebd963..84e2816 100644
--- a/src/common/form_schema.rs
+++ b/src/common/form_schema.rs
@@ -1,18 +1,121 @@
-use serde::{Serialize, Deserialize};
+use crate::common::ValueType;
+use crate::components::{CheckboxList, OutlinedTextField, RadioList, Row, Select};
+use leptos::either::EitherOf5;
+use leptos::prelude::RwSignal;
+use leptos::{IntoView, view};
+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. The entered value will be returned as a
- /// single `String` value.
- Text,
- /// Represents a number input. Requires a `String` key. The entered value will be returned as a
- /// single `i32` value.
- Number,
- /// Represents a radio input. Requires a `String` key and a series of options. The selected
- /// value will be returned as a single `String` value.
- Radio(Vec),
- /// Represents a checkbox input. Requires a `String` key and a series of options. The selected
- /// value will be returned as a `Vec`.
- Checkbox(Vec)
+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),
+ /// 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),
+ /// 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),
+ /// 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`.
+ Checkbox(String, String, Vec),
+ /// 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),
+}
+
+impl InputType {
+ pub fn into_view(self, data_map: RwSignal>) -> impl IntoView {
+ view! {
+ {match self {
+ InputType::Text(member, label, placeholder) =>
+ EitherOf5::A(view! {
+
+
+
+ }),
+ InputType::Number(member, label, placeholder) =>
+ EitherOf5::B(view! {
+
+ }),
+ InputType::Checkbox(member, label, options) =>
+ EitherOf5::C(view! {
+
+ }),
+ InputType::Radio(member, label, options) =>
+ EitherOf5::D(view! {
+
+ }),
+ InputType::Select(member, label, options) =>
+ EitherOf5::E(view! {
+
+ })
+ }}
+ }
+ }
+
+ pub fn into_view_rows(self, data_map: RwSignal>) -> impl IntoView {
+ view! {
+
+ {self.into_view(data_map)}
+
+ }
+ }
+}
+
+/// 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, [$($option:expr),* $(,)?]) => {
+ $crate::common::InputType::$variant(
+ $key.to_string(),
+ $label.to_string(),
+ vec![$($option.to_string()), *]
+ )
+ };
+
+ ($variant:ident, $key:expr, $label:expr, $placeholder:expr) => {
+ $crate::common::InputType::$variant(
+ $key.to_string(),
+ $label.to_string(),
+ $placeholder.to_string()
+ )
+ };
}
diff --git a/src/common/mod.rs b/src/common/mod.rs
index 7e04a46..fd320cb 100644
--- a/src/common/mod.rs
+++ b/src/common/mod.rs
@@ -1,7 +1,6 @@
-mod student_info;
-mod user;
-mod form_schema;
mod expandable_info;
+mod form_schema;
+mod user;
pub mod value_type;
-pub use self::{expandable_info::*, form_schema::*, student_info::*, user::*};
+pub use self::{expandable_info::*, form_schema::*, user::*, value_type::*};
diff --git a/src/common/student_info.rs b/src/common/student_info.rs
deleted file mode 100644
index 6f7b792..0000000
--- a/src/common/student_info.rs
+++ /dev/null
@@ -1,50 +0,0 @@
-use crate::components::{MultiEntryData, ValueType};
-use macros::Reactive;
-use serde::{Deserialize, Serialize};
-use std::default::Default;
-use chrono::{DateTime, Utc};
-use reactive_stores::Store;
-
-/// Represents information about a student.
-#[derive(Serialize, Deserialize, Debug, Clone, Default, Store, Reactive)]
-pub struct StudentInfo {
- /// The email address of the student. This was used in the previous version of the database,
- /// and should now be deprecated.
- ///
- /// This is the primary key of the table, and should not have a default value.
- pub Email: String,
- /// The student's first name.
- #[serde(default)]
- pub first_name: ValueType, // String
- /// The student's last name.
- #[serde(default)]
- pub last_name: ValueType, // String
- /// The student's highest math score on the SAT.
- #[serde(default = "default_number")]
- pub math_sat: ValueType, // Number
- /// The student's desired contact email.
- #[serde(default)]
- pub contact_email: ValueType, // String
- /// The student's address.
- #[serde(default)]
- pub address: ValueType, // String
- /// The student's town of residence.
- #[serde(default)]
- pub town: ValueType, // String
- /// The student's entered phone number.
- #[serde(default)]
- pub phone_number: ValueType, // May be stored as a straight number in the future, but String
- /// The student's birthdate.
- #[serde(default)]
- pub birth_date: DateTime,
- /// The student's gender.
- #[serde(default)]
- pub gender: ValueType, // String
- /// The student's athletic information.
- #[serde(default)]
- pub athletic_info: Vec,
-}
-
-fn default_number() -> ValueType {
- ValueType::Number(None)
-}
\ No newline at end of file
diff --git a/src/common/value_type.rs b/src/common/value_type.rs
index 4572e1b..982df27 100644
--- a/src/common/value_type.rs
+++ b/src/common/value_type.rs
@@ -1,9 +1,14 @@
-use serde::{Serialize, Deserialize};
+use serde::{Deserialize, Serialize};
+use std::collections::HashMap;
use std::fmt::Display;
/// Defines a set of possible input types. They allow for the type and value of every data member
/// to be stored within a single `HashMap` or `Vec`. This means that even though all the data is
/// created as a single type, the values are still able to be type safe.
+///
+/// A note: other structs cannot be stored in this enum, however it was designed to work with
+/// a `HashMap` of more `ValueType` enums. There are numerous ways to convert a struct into a
+/// `HashMap`, specifically storing all the struct's fields as `String` keys in the map.
#[derive(PartialEq, Clone, Serialize, Deserialize, Debug)]
pub enum ValueType {
/// Indicates a `String` value.
@@ -12,12 +17,18 @@ pub enum ValueType {
Number(Option),
/// Indicates a `Vec`, where `T` can be any other `ValueType`.
List(Option>),
+ /// Indicates a `HashMap`.
+ Map(Option>),
}
impl ValueType {
- /// Returns true if this is a `String`.
+ /// Returns true if this is a `String`, otherwise false.
pub fn is_string(&self) -> bool {
- if let ValueType::String(_) = self { true } else { false }
+ if let ValueType::String(_) = self {
+ true
+ } else {
+ false
+ }
}
/// Attempts to get this value as a `String` type. This is different from the `to_string` method.
@@ -29,9 +40,13 @@ impl ValueType {
}
}
- /// Returns true if this is a `Number`.
+ /// Returns true if this is a `Number`, otherwise false.
pub fn is_number(&self) -> bool {
- if let ValueType::Number(_) = self { true } else { false }
+ if let ValueType::Number(_) = self {
+ true
+ } else {
+ false
+ }
}
/// Attempts to get this value as an `i32`.
@@ -43,9 +58,13 @@ impl ValueType {
}
}
- /// Returns true if this is a `List`.
+ /// Returns true if this is a `List`, otherwise false.
pub fn is_list(&self) -> bool {
- if let ValueType::List(_) = self { true } else { false }
+ if let ValueType::List(_) = self {
+ true
+ } else {
+ false
+ }
}
/// Attempts to get this value as a `Vec`. Each of the values inside the list must
@@ -57,6 +76,24 @@ impl ValueType {
Err(self.clone())
}
}
+
+ /// Returns true if this is a `Map`, otherwise false.
+ pub fn is_map(&self) -> bool {
+ if let ValueType::Map(_) = self {
+ true
+ } else {
+ false
+ }
+ }
+
+ /// Attempts to get this value as a `HashMap`.
+ pub fn as_map(&self) -> Result