Merge branch 'main' into feat/provider_portal
# Conflicts: # src/pages/mod.rs
No files matched your search
|
After Width: | Height: | Size: 314 KiB |
|
After Width: | Height: | Size: 506 KiB |
|
After Width: | Height: | Size: 548 KiB |
|
After Width: | Height: | Size: 83 KiB |
|
After Width: | Height: | Size: 113 KiB |
|
After Width: | Height: | Size: 110 KiB |
|
After Width: | Height: | Size: 131 KiB |
|
After Width: | Height: | Size: 184 KiB |
|
After Width: | Height: | Size: 250 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 118 KiB |
|
After Width: | Height: | Size: 167 KiB |
|
After Width: | Height: | Size: 163 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 121 KiB |
|
After Width: | Height: | Size: 119 KiB |
|
After Width: | Height: | Size: 145 KiB |
|
After Width: | Height: | Size: 104 KiB |
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 77 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 167 KiB |
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7 20C7 17.2386 9.23858 15 12 15C14.7614 15 17 17.2386 17 20M7.2 20H16.8C17.9201 20 18.4802 20 18.908 19.782C19.2843 19.5903 19.5903 19.2843 19.782 18.908C20 18.4802 20 17.9201 20 16.8V7.2C20 6.0799 20 5.51984 19.782 5.09202C19.5903 4.71569 19.2843 4.40973 18.908 4.21799C18.4802 4 17.9201 4 16.8 4H7.2C6.0799 4 5.51984 4 5.09202 4.21799C4.71569 4.40973 4.40973 4.71569 4.21799 5.09202C4 5.51984 4 6.07989 4 7.2V16.8C4 17.9201 4 18.4802 4.21799 18.908C4.40973 19.2843 4.71569 19.5903 5.09202 19.782C5.51984 20 6.07989 20 7.2 20ZM14 10C14 11.1046 13.1046 12 12 12C10.8954 12 10 11.1046 10 10C10 8.89543 10.8954 8 12 8C13.1046 8 14 8.89543 14 10Z" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 968 B |
@@ -7,7 +7,7 @@ use leptos_router::{
|
||||
};
|
||||
use url::Url;
|
||||
|
||||
use crate::pages::{AboutPage, HomePage, UnauthenticatedPage};
|
||||
use crate::pages::{AboutPage, HomePage, TestPage, UnauthenticatedPage};
|
||||
|
||||
pub fn shell(options: LeptosOptions) -> impl IntoView {
|
||||
view! {
|
||||
@@ -67,6 +67,7 @@ pub fn App() -> impl IntoView {
|
||||
<Routes fallback=|| "Page not found.".into_view()>
|
||||
<Route path=StaticSegment("") view=HomePage/>
|
||||
<Route path=StaticSegment("about") view=AboutPage/>
|
||||
<Route path=StaticSegment("test_page") view=TestPage/>
|
||||
</Routes>
|
||||
</main>
|
||||
</Router>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::common::ValueType;
|
||||
use crate::components::utils::create_unique_id;
|
||||
use leptos::prelude::*;
|
||||
use std::collections::HashMap;
|
||||
|
||||
@@ -7,10 +8,13 @@ pub fn Checkbox(
|
||||
#[prop()] checked: Signal<bool>,
|
||||
#[prop(into)] on_change: Callback<(), ()>,
|
||||
#[prop(into)] value: String,
|
||||
#[prop(into)] name: String,
|
||||
#[prop(default = RwSignal::new(false))] disabled: RwSignal<bool>,
|
||||
) -> impl IntoView {
|
||||
let id = create_unique_id(&name, &value);
|
||||
|
||||
view! {
|
||||
<label for=value class="flex items-center">
|
||||
<label for=id class="flex items-center">
|
||||
<input
|
||||
// Using the "peer" class links this input with the div "peer" at the same level.
|
||||
// By using the "peer-checked" selector this div can toggle states based on this
|
||||
@@ -19,7 +23,8 @@ pub fn Checkbox(
|
||||
relative peer shrink-0
|
||||
hidden"
|
||||
type="checkbox"
|
||||
id=value.clone()
|
||||
id=id.clone()
|
||||
name=name.clone()
|
||||
on:change=move |_| on_change.run(())
|
||||
prop:checked=checked
|
||||
disabled=disabled
|
||||
@@ -109,6 +114,7 @@ pub fn CheckboxList(
|
||||
on_change=on_change
|
||||
// The actual selected values are tracked by this element, not by the checkboxes themselves.
|
||||
value=item.clone()
|
||||
name=data_member.clone()
|
||||
disabled=disabled
|
||||
/>
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
use std::collections::HashMap;
|
||||
use leptos::prelude::*;
|
||||
use crate::common::ValueType;
|
||||
use crate::components::utils::create_unique_id;
|
||||
use leptos::prelude::*;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// # Chip Component
|
||||
///
|
||||
///
|
||||
/// This component defines a single chip for use in the `ChipsList` component. It functions almost
|
||||
/// identically to the `Checkbox` component. It should only be created from within its parent
|
||||
/// `CheckboxList` component.
|
||||
///
|
||||
///
|
||||
/// Example usage:
|
||||
/// ```
|
||||
/// view! {
|
||||
@@ -31,11 +32,8 @@ pub fn Chip(
|
||||
) -> impl IntoView {
|
||||
// Generate a unique id - ensure that the value doesn't contain spaces.
|
||||
// Without this id, checkbox/radio inputs can interfere with each other.
|
||||
let value_no_spaces = value.clone().chars()
|
||||
.filter(|c| !c.is_whitespace())
|
||||
.collect::<String>();
|
||||
let id = format!("{}-{}", name.clone(), value_no_spaces);
|
||||
|
||||
let id = create_unique_id(&name, &value);
|
||||
|
||||
view! {
|
||||
<label for=id>
|
||||
<input
|
||||
@@ -62,10 +60,10 @@ pub fn Chip(
|
||||
}
|
||||
|
||||
/// # Chips List Component
|
||||
///
|
||||
///
|
||||
/// This defines a list of `Chip` components. The list of values is created based on the data from the
|
||||
/// `data_map` prop, which is found using the given `data_member`.
|
||||
///
|
||||
///
|
||||
/// Any values selected from the list are stored within the `data_map` immediately as part of a callback
|
||||
/// passed to the `on_change` prop for each individual `Chip` component.
|
||||
#[component]
|
||||
@@ -97,7 +95,7 @@ pub fn ChipsList(
|
||||
.contains(&ValueType::String(Some(item_name.clone())))
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
let on_change = {
|
||||
let item_name = value.clone();
|
||||
let data_member = data_member.clone();
|
||||
@@ -129,7 +127,7 @@ pub fn ChipsList(
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
view! {
|
||||
<Chip
|
||||
checked=checked_signal
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
use leptos::prelude::*;
|
||||
use leptos_router::hooks::use_navigate;
|
||||
|
||||
/// # Dashboard Button Component
|
||||
///
|
||||
/// This component displays a large panel-like button that redirects a user to a specified page.
|
||||
/// It's best used on a user dashboard, where multiple instances of the button are present.
|
||||
/// It has a title, a description, and icon
|
||||
///
|
||||
/// Example usage:
|
||||
/// ```
|
||||
/// <div class="p-6 space-y-4 max-w-1/3">
|
||||
/// <DashboardButton
|
||||
/// title="Home Page"
|
||||
/// description="Navigate to Home Page"
|
||||
/// icon="square-user.svg"
|
||||
/// path="/"
|
||||
/// />
|
||||
/// </div>
|
||||
/// ```
|
||||
#[component]
|
||||
pub fn DashboardButton(
|
||||
/// The main label displayed on the button.
|
||||
#[prop(into)]
|
||||
title: String,
|
||||
/// A brief explanatory text that describes the destination page.
|
||||
#[prop(into)]
|
||||
description: String,
|
||||
/// The file path or URL of the icon displayed at the top of the button.
|
||||
#[prop(into)]
|
||||
icon: String,
|
||||
/// The route that the user is navigated to when clicking the button.
|
||||
#[prop(into)]
|
||||
path: String,
|
||||
) -> impl IntoView {
|
||||
let navigate = use_navigate();
|
||||
|
||||
let on_click = move |_| navigate(&path, Default::default());
|
||||
|
||||
view! {
|
||||
<button
|
||||
type="button"
|
||||
class="dashboard-button flex items-start gap-3 rounded-lg border-grey-300 p-6
|
||||
hover:bg-gray-100 transition cursor-pointer w-full text-left
|
||||
shadow-[inset_0_0_6px_rgba(0,0,0,0.12)]"
|
||||
on:click=on_click>
|
||||
|
||||
<div class="flex flex-col">
|
||||
<img src={icon.clone()} class="h-8 w-8" alt="icon"/>
|
||||
<h3 class="font-semibold text-base">
|
||||
{title.clone()}
|
||||
</h3>
|
||||
|
||||
<p class="text-sm text-gray-600 pt-6">
|
||||
{description.clone()}
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</button>
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
mod action_button;
|
||||
mod checkbox;
|
||||
mod chips;
|
||||
mod dashboard_button;
|
||||
mod loading;
|
||||
mod multi_entry;
|
||||
mod panel;
|
||||
@@ -7,9 +9,9 @@ mod radio;
|
||||
mod row;
|
||||
mod select;
|
||||
mod text_field;
|
||||
mod chips;
|
||||
mod utils;
|
||||
|
||||
pub use self::{
|
||||
action_button::*, checkbox::*, loading::*, multi_entry::*, panel::*, radio::*, row::*,
|
||||
select::*, text_field::*, chips::*
|
||||
action_button::*, checkbox::*, chips::*, dashboard_button::*, loading::*, multi_entry::*,
|
||||
panel::*, radio::*, row::*, select::*, text_field::*,
|
||||
};
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::common::ValueType;
|
||||
use crate::components::utils::create_unique_id;
|
||||
use leptos::prelude::*;
|
||||
use std::collections::HashMap;
|
||||
|
||||
@@ -7,10 +8,13 @@ pub fn Radio(
|
||||
#[prop()] checked: Signal<bool>,
|
||||
#[prop(into)] on_change: Callback<(), ()>,
|
||||
#[prop(into)] value: String,
|
||||
#[prop(into)] name: String,
|
||||
#[prop(default = RwSignal::new(false))] disabled: RwSignal<bool>,
|
||||
) -> impl IntoView {
|
||||
let id = create_unique_id(&name, &value);
|
||||
|
||||
view! {
|
||||
<label for=value class="flex items-center">
|
||||
<label for=id class="flex items-center">
|
||||
<input
|
||||
// Using the "peer" class links this input with the div "peer" at the same level.
|
||||
// By using the "peer-checked" selector this div can toggle states based on this
|
||||
@@ -18,8 +22,9 @@ pub fn Radio(
|
||||
class="
|
||||
relative peer shrink-0
|
||||
hidden"
|
||||
type="checkbox"
|
||||
id=value.clone()
|
||||
type="radio"
|
||||
id=id.clone()
|
||||
name=name.clone()
|
||||
on:change=move |_| on_change.run(())
|
||||
prop:checked=checked
|
||||
disabled=disabled
|
||||
@@ -96,6 +101,7 @@ pub fn RadioList(
|
||||
on_change=on_change
|
||||
// The actual selected values are tracked by this element, not by the checkboxes themselves.
|
||||
value=item.clone()
|
||||
name=data_member.clone()
|
||||
disabled=disabled
|
||||
/>
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
/// Creates a unique ID for use in components like the [`CheckboxList`],
|
||||
/// [`RadioList`], and [`ChipsList`].
|
||||
pub fn create_unique_id(name: &String, value: &String) -> String {
|
||||
let value_no_spaces = value
|
||||
.clone()
|
||||
.chars()
|
||||
.filter(|c| !c.is_whitespace())
|
||||
.collect::<String>();
|
||||
format!("{}-{}", name.clone(), value_no_spaces)
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
mod about_page;
|
||||
mod home_page;
|
||||
mod provider_portal;
|
||||
mod test_page;
|
||||
mod unauthenticated_page;
|
||||
|
||||
pub use self::{about_page::*, home_page::*, provider_portal::*, unauthenticated_page::*};
|
||||
pub use self::{
|
||||
about_page::*, home_page::*, provider_portal::*, test_page::*, unauthenticated_page::*,
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
use crate::components::DashboardButton;
|
||||
use leptos::prelude::*;
|
||||
|
||||
#[component]
|
||||
pub fn TestPage() -> impl IntoView {
|
||||
view! {
|
||||
<div class="p-6 space-y-4 max-w-1/3">
|
||||
<DashboardButton
|
||||
title="Home Page"
|
||||
description="Navigate to Home Page"
|
||||
icon="Book.png"
|
||||
path="/"
|
||||
/>
|
||||
<DashboardButton
|
||||
title="Home Page"
|
||||
description="Navigate to Home Page"
|
||||
icon="Calendar.png"
|
||||
path="/"
|
||||
/>
|
||||
<DashboardButton
|
||||
title="Home Page"
|
||||
description="Navigate to Home Page"
|
||||
icon="Edit.png"
|
||||
path="/"
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
}
|
||||