PR with too many features #58

Merged
BobdaFett merged 56 commits from feat/admin-page into main 2026-02-10 14:31:49 +00:00
2 changed files with 46 additions and 7 deletions
Showing only changes of commit 12a980f327 - Show all commits

No files matched your search

+34 -5
View File
@@ -5,7 +5,7 @@ use crate::components::utils;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct NavListInfo { pub struct NavListInfo {
pub text: String, pub text: Vec<String>,
pub id: String, pub id: String,
pub slug: String, pub slug: String,
} }
@@ -14,11 +14,25 @@ pub struct NavListInfo {
fn NavListItem( fn NavListItem(
#[prop(into)] name: Signal<String>, #[prop(into)] name: Signal<String>,
#[prop(into)] value: Signal<String>, #[prop(into)] value: Signal<String>,
#[prop(into)] text: Signal<String>, #[prop(into)] text: Signal<Vec<String>>,
#[prop(into)] slug: Signal<String>, #[prop(into)] slug: Signal<String>,
#[prop(into)] selected: Signal<bool>, #[prop(into)] selected: Signal<bool>,
#[prop(into)] on_change: Callback<()>, #[prop(into)] on_change: Callback<()>,
) -> impl IntoView { ) -> impl IntoView {
let linked_info = Signal::derive(move ||
text.get()
.get(0)
.cloned()
.unwrap_or_default()
);
let other_info = Signal::derive(move ||
text.get()
.iter()
.cloned()
.skip(1)
.collect::<Vec<String>>()
);
view! { view! {
<div <div
class="flex flex-row gap-2 p-1 rounded-lg" class="flex flex-row gap-2 p-1 rounded-lg"
@@ -30,9 +44,16 @@ fn NavListItem(
on_change=move || on_change.run(()) on_change=move || on_change.run(())
selected=selected selected=selected
/> />
<A href=move || slug.get() {..} class="flex items-center underline hover:text-blue-400"> <A href=move || slug.get() {..} class="flex flex-1 items-center underline hover:text-blue-400">
{text} {linked_info}
</A> </A>
<For
each=move || other_info.get()
key=|info| info.clone()
let(info)
>
<p class="flex flex-1 items-center">{info}</p>
</For>
</div> </div>
} }
} }
@@ -80,6 +101,7 @@ fn NavListCheckbox(
pub fn SelectableNavList( pub fn SelectableNavList(
#[prop(into)] selected: RwSignal<Vec<String>>, #[prop(into)] selected: RwSignal<Vec<String>>,
#[prop(into)] items: Signal<Vec<NavListInfo>>, #[prop(into)] items: Signal<Vec<NavListInfo>>,
#[prop(into)] headers: Signal<Vec<String>>,
#[prop(into)] name: Signal<String>, #[prop(into)] name: Signal<String>,
) -> impl IntoView { ) -> impl IntoView {
let all_selected = RwSignal::new(false); let all_selected = RwSignal::new(false);
@@ -106,13 +128,20 @@ pub fn SelectableNavList(
// Header block - contains evenly spaced headers and the "select all" checkbox. // Header block - contains evenly spaced headers and the "select all" checkbox.
// Include a checkbox here that's got the same style as the items. This maintains spacing. // Include a checkbox here that's got the same style as the items. This maintains spacing.
// All headers *must* be evenly spaced, otherwise the list starts getting confusing. // All headers *must* be evenly spaced, otherwise the list starts getting confusing.
<div class="flex flex-row bg-red-800 rounded-lg p-1"> <div class="flex flex-row bg-red-800 rounded-lg p-1 gap-2">
<NavListCheckbox <NavListCheckbox
selected=all_selected selected=all_selected
name=name name=name
value="select-all" value="select-all"
on_change=all_selected_change on_change=all_selected_change
/> />
<For
each=move || headers.get()
key=|header| header.clone()
let(header_text)
>
<div class="flex flex-1 text-white font-bold items-center">{header_text}</div>
</For>
</div> </div>
// Items block - contains constructed items. These are selectable. // Items block - contains constructed items. These are selectable.
<For <For
+12 -2
View File
@@ -6,17 +6,26 @@ pub fn AdminProviderPage() -> impl IntoView {
let selected_items = RwSignal::new(Vec::new()); let selected_items = RwSignal::new(Vec::new());
let provider_list = RwSignal::new(vec![ let provider_list = RwSignal::new(vec![
NavListInfo { NavListInfo {
text: "Testing 1".to_string(), text: vec!["Testing 1".to_string(), 3.to_string(), 500.to_string()],
id: "1".to_string(), id: "1".to_string(),
slug: "1".to_string(), slug: "1".to_string(),
}, },
NavListInfo { NavListInfo {
text: "Testing 2".to_string(), text: vec!["Testing 2".to_string(), 2.to_string(), 1000.to_string()],
id: "2".to_string(), id: "2".to_string(),
slug: "2".to_string(), slug: "2".to_string(),
} }
]); ]);
let headers = vec![
"Scholarship Name",
"Number of Awards",
"Amount of Awards"
]
.iter()
.map(|s| s.to_string())
.collect::<Vec<String>>();
view! { view! {
<div class="flex flex-1 flex-col gap-4 items-stretch mt-4"> <div class="flex flex-1 flex-col gap-4 items-stretch mt-4">
<div class="font-bold text-3xl self-center">"Provider View"</div> <div class="font-bold text-3xl self-center">"Provider View"</div>
@@ -24,6 +33,7 @@ pub fn AdminProviderPage() -> impl IntoView {
selected=selected_items selected=selected_items
name="providers-nav-list" name="providers-nav-list"
items=provider_list items=provider_list
headers=headers
/> />
</div> </div>
} }