2024-12-06 14:45:14 +03:00
|
|
|
use crate::models::item::Item;
|
2024-12-18 21:49:26 +03:00
|
|
|
use gloo_net::http::Request;
|
2024-12-20 02:56:42 +03:00
|
|
|
use leptos::logging::log;
|
|
|
|
use leptos::*;
|
|
|
|
use serde::Deserialize;
|
|
|
|
use std::collections::HashMap;
|
2024-12-18 21:49:26 +03:00
|
|
|
use wasm_bindgen_futures::spawn_local;
|
|
|
|
|
|
|
|
#[derive(Deserialize, Clone, Debug)]
|
|
|
|
struct WikidataResponse {
|
2024-12-20 02:56:42 +03:00
|
|
|
entities: HashMap<String, WikidataEntity>,
|
2024-12-18 21:49:26 +03:00
|
|
|
}
|
2024-12-20 02:56:42 +03:00
|
|
|
|
2024-12-18 21:49:26 +03:00
|
|
|
#[derive(Deserialize, Clone, Debug)]
|
|
|
|
struct WikidataEntity {
|
2024-12-20 02:56:42 +03:00
|
|
|
labels: Option<HashMap<String, WikidataLabel>>,
|
|
|
|
descriptions: Option<HashMap<String, WikidataLabel>>,
|
2024-12-18 21:49:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Deserialize, Clone, Debug)]
|
|
|
|
struct WikidataLabel {
|
|
|
|
value: String,
|
|
|
|
}
|
2024-12-06 14:45:14 +03:00
|
|
|
|
|
|
|
#[component]
|
2024-12-20 02:56:42 +03:00
|
|
|
pub fn ItemsList(items: ReadSignal<Vec<Item>>, set_items: WriteSignal<Vec<Item>>, on_add_item: impl Fn() + 'static, ) -> impl IntoView {
|
2024-12-18 21:49:26 +03:00
|
|
|
let (wikidata_data, set_wikidata_data) = create_signal(Vec::<Option<WikidataEntity>>::new());
|
|
|
|
|
2024-12-20 02:56:42 +03:00
|
|
|
// Fetch data from Wikidata for a given item name
|
|
|
|
let fetch_wikidata = move |item_name: String| {
|
|
|
|
spawn_local(async move {
|
|
|
|
let url = format!("https://www.wikidata.org/w/api.php?action=wbsearchentities&search={}&language=en&limit=1&format=json", item_name);
|
|
|
|
match Request::get(&url).send().await {
|
|
|
|
Ok(response) => match response.json::<WikidataResponse>().await {
|
|
|
|
Ok(parsed_data) => {
|
|
|
|
if let Some(entity) = parsed_data.entities.values().next() {
|
|
|
|
set_wikidata_data.update(|current_data| {
|
|
|
|
current_data.push(Some(entity.clone()));
|
|
|
|
});
|
|
|
|
}
|
2024-12-18 21:49:26 +03:00
|
|
|
}
|
2024-12-20 02:56:42 +03:00
|
|
|
Err(_) => log!("Failed to parse response from Wikidata"),
|
|
|
|
},
|
|
|
|
Err(_) => log!("Failed to make request to Wikidata"),
|
2024-12-18 21:49:26 +03:00
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
2024-12-20 02:56:42 +03:00
|
|
|
|
|
|
|
// Handle updating grid cells
|
|
|
|
let update_item = move |index: usize, column: &str, value: String| {
|
|
|
|
set_items.update(|items| {
|
|
|
|
if let Some(item) = items.get_mut(index) {
|
|
|
|
match column {
|
|
|
|
"name" => item.name = value,
|
|
|
|
"description" => item.description = value,
|
|
|
|
"tags" => item.tags.push((value.clone(), value)), // For simplicity, adding the same value as key and value.
|
|
|
|
"review" => item.reviews.push(crate::models::item::ReviewWithRating {
|
|
|
|
content: value.clone(),
|
|
|
|
rating: 5, // Assuming a default rating of 5
|
|
|
|
}),
|
|
|
|
"rating" => {
|
|
|
|
if let Ok(rating) = value.parse::<u8>() {
|
|
|
|
item.reviews.last_mut().map(|r| r.rating = rating);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => (),
|
|
|
|
}
|
2024-12-18 16:00:40 +03:00
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2024-12-20 02:56:42 +03:00
|
|
|
// Trigger add item event
|
|
|
|
let add_item = move |_| {
|
|
|
|
on_add_item(); // Call the passed closure from App to add a new item
|
|
|
|
};
|
|
|
|
|
2024-12-06 14:45:14 +03:00
|
|
|
view! {
|
|
|
|
<div>
|
2024-12-20 02:56:42 +03:00
|
|
|
<h1>{ "CompareWare" }</h1>
|
2024-12-17 16:14:49 +03:00
|
|
|
|
2024-12-20 02:56:42 +03:00
|
|
|
<button on:click=add_item>{ "Add New Item" }</button>
|
2024-12-18 21:49:26 +03:00
|
|
|
|
2024-12-17 16:14:49 +03:00
|
|
|
<table>
|
|
|
|
<thead>
|
|
|
|
<tr>
|
2024-12-20 02:56:42 +03:00
|
|
|
<th>{ "Name" }</th>
|
2024-12-17 16:14:49 +03:00
|
|
|
<th>{ "Description" }</th>
|
|
|
|
<th>{ "Tags" }</th>
|
2024-12-20 02:56:42 +03:00
|
|
|
<th>{ "Review" }</th>
|
|
|
|
<th>{ "Rating" }</th>
|
2024-12-17 16:14:49 +03:00
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
{move || {
|
2024-12-20 02:56:42 +03:00
|
|
|
items.get().iter().enumerate().map(|(index, item)| {
|
2024-12-17 16:14:49 +03:00
|
|
|
view! {
|
2024-12-20 02:56:42 +03:00
|
|
|
<tr>
|
2024-12-17 16:14:49 +03:00
|
|
|
<td>
|
2024-12-20 02:56:42 +03:00
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
value={item.name.clone()}
|
|
|
|
on:input=move |e| {
|
|
|
|
update_item(index, "name", event_target_value(&e));
|
|
|
|
fetch_wikidata(event_target_value(&e)); // Fetch Wikidata when name is entered
|
|
|
|
}
|
|
|
|
/>
|
2024-12-17 16:14:49 +03:00
|
|
|
</td>
|
|
|
|
<td>
|
2024-12-20 02:56:42 +03:00
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
value={item.description.clone()}
|
|
|
|
on:input=move |e| update_item(index, "description", event_target_value(&e))
|
|
|
|
/>
|
2024-12-17 16:14:49 +03:00
|
|
|
</td>
|
2024-12-18 21:49:26 +03:00
|
|
|
<td>
|
2024-12-20 02:56:42 +03:00
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
placeholder="Add tags"
|
|
|
|
on:input=move |e| update_item(index, "tags", event_target_value(&e))
|
|
|
|
/>
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
<textarea
|
|
|
|
value={item.reviews.iter().map(|review| format!("{}: {}", review.rating, review.content)).collect::<Vec<_>>().join("\n")}
|
|
|
|
on:input=move |e| update_item(index, "review", event_target_value(&e))
|
|
|
|
/>
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
<input
|
|
|
|
type="number"
|
|
|
|
value={item.reviews.last().map(|r| r.rating).unwrap_or(5)}
|
|
|
|
min="1" max="5"
|
|
|
|
on:input=move |e| update_item(index, "rating", event_target_value(&e))
|
|
|
|
/>
|
2024-12-18 21:49:26 +03:00
|
|
|
</td>
|
2024-12-17 16:14:49 +03:00
|
|
|
</tr>
|
|
|
|
}
|
|
|
|
}).collect::<Vec<_>>()
|
|
|
|
}}
|
|
|
|
</tbody>
|
|
|
|
</table>
|
2024-12-06 14:45:14 +03:00
|
|
|
</div>
|
|
|
|
}
|
2024-12-18 16:00:40 +03:00
|
|
|
}
|