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
Showing only changes of commit 8417713aa1 - Show all commits
+45 -13
View File
@@ -3,6 +3,7 @@ use crate::components::ActionButton;
use leptos::prelude::*; use leptos::prelude::*;
use std::collections::HashMap; use std::collections::HashMap;
use leptos::logging::log; use leptos::logging::log;
use leptos_icons::Icon;
use uuid::Uuid; use uuid::Uuid;
// region Helper Functions // region Helper Functions
@@ -12,6 +13,13 @@ fn get_uuid_from_map(map: &HashMap<String, ValueType>) -> Option<String> {
map.get("uuid")?.as_string().unwrap_or(None) map.get("uuid")?.as_string().unwrap_or(None)
} }
fn get_uuid(vt: ValueType) -> Option<String> {
vt.as_map().ok().flatten().unwrap_or_default()
.get("uuid")?
.as_string()
.ok().flatten()
}
/// Updates an Entry within the given `Vec`. /// Updates an Entry within the given `Vec`.
fn update_entry_list(list: &mut Vec<ValueType>, data: &HashMap<String, ValueType>) { fn update_entry_list(list: &mut Vec<ValueType>, data: &HashMap<String, ValueType>) {
if let Some(uuid) = get_uuid_from_map(&data) { if let Some(uuid) = get_uuid_from_map(&data) {
@@ -115,7 +123,7 @@ pub fn MultiEntry(
<span>{description}</span> <span>{description}</span>
</Show> </Show>
</div> </div>
<div class="flex flex-col gap-2 p-2"> <div class="flex flex-col gap-6 p-2">
// Render the entries // Render the entries
<Show <Show
when=move || !data_list.get().is_empty() when=move || !data_list.get().is_empty()
@@ -126,16 +134,22 @@ pub fn MultiEntry(
<For <For
each=move || data_list.get() each=move || data_list.get()
// Entries MUST be given a unique ID. // Entries MUST be given a unique ID.
key=|entry| get_uuid_from_map(&entry.as_map().unwrap().unwrap()) key=|entry| get_uuid(entry.clone())
children=move |mut entry_map| { children=move |mut entry_map| {
let map_signal = RwSignal::new( let map_signal = RwSignal::new(
entry_map.as_map().ok().flatten().unwrap_or_default(), entry_map.as_map().ok().flatten().unwrap_or_default(),
); );
let unique_id = Memo::new(move |_| { let unique_id = Memo::new(move |_| {
get_uuid_from_map(&map_signal.get()).unwrap_or_default() get_uuid_from_map(&map_signal.get()).unwrap_or_default()
}); });
let on_delete = move || {
let mut list = data_list.get_untracked();
let uuid = unique_id.get_untracked();
list.retain(|map| {
get_uuid(map.clone()).unwrap_or_default() != uuid
});
update_parent_list(list);
};
Effect::new(move |_| { Effect::new(move |_| {
let child_map = map_signal.get(); let child_map = map_signal.get();
let mut list = data_list.get_untracked(); let mut list = data_list.get_untracked();
@@ -143,7 +157,14 @@ pub fn MultiEntry(
update_parent_list(list); update_parent_list(list);
}); });
view! { <Entry data_map=map_signal schema=schema id=unique_id /> } view! {
<Entry
data_map=map_signal
schema=schema
id=unique_id
on_delete=on_delete
/>
}
} }
/> />
</Show> </Show>
@@ -191,18 +212,29 @@ fn Entry(
#[prop(into)] schema: Signal<Vec<InputType>>, #[prop(into)] schema: Signal<Vec<InputType>>,
/// The unique ID for this entry. /// The unique ID for this entry.
#[prop(into)] id: Signal<String>, #[prop(into)] id: Signal<String>,
/// The function to run when the delete button is clicked.
#[prop(into)] on_delete: Callback<()>,
) -> impl IntoView { ) -> impl IntoView {
view! { view! {
<div class="flex flex-col flex-1 p-2 rounded-sm transition-shadow shadow-sm hover:shadow-lg/30"> <div class="relative rounded-sm transition-shadow shadow-sm hover:shadow-lg/30">
{move || schema // Delete button
<div
class="absolute rounded-full w-8 h-8 -top-4 -right-4 flex items-center justify-center bg-gray-100 text-gray-700 hover:text-red-600 transition-all"
on:click=move |_| on_delete.run(())
>
<Icon icon=icondata::FaTrashCanRegular />
</div>
// Input section
<div class="flex flex-col flex-1 p-2">
{move || {
schema
.get() .get()
.iter() .iter()
.map(|input_type| .map(|input_type| input_type.clone().into_view(data_map.clone(), id.get()))
input_type .collect_view()
.clone() }}
.into_view(data_map.clone(), id.get()) </div>
)
.collect_view()}
</div> </div>
} }
} }