update
This commit is contained in:
@@ -28,7 +28,7 @@ features = ["full"]
|
|||||||
|
|
||||||
[dependencies.serde]
|
[dependencies.serde]
|
||||||
version = "1.0"
|
version = "1.0"
|
||||||
features = ["derive"]
|
features = ["derive", "rc"]
|
||||||
|
|
||||||
[dependencies.uuid]
|
[dependencies.uuid]
|
||||||
version = "0.8"
|
version = "0.8"
|
||||||
|
|||||||
236
api/src/db.rs
236
api/src/db.rs
@@ -1,3 +1,6 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use rusqlite;
|
use rusqlite;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@@ -12,6 +15,8 @@ use super::PreparationStep;
|
|||||||
use super::Trip;
|
use super::Trip;
|
||||||
use super::TripParameters;
|
use super::TripParameters;
|
||||||
use super::TripState;
|
use super::TripState;
|
||||||
|
use super::TripItem;
|
||||||
|
use super::TripItemStatus;
|
||||||
|
|
||||||
pub fn load() -> rusqlite::Result<()> {
|
pub fn load() -> rusqlite::Result<()> {
|
||||||
let example_lists = vec![
|
let example_lists = vec![
|
||||||
@@ -726,6 +731,20 @@ pub fn load() -> rusqlite::Result<()> {
|
|||||||
[],
|
[],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
conn.execute(
|
||||||
|
"CREATE TABLE trip_items (
|
||||||
|
trip_id TEXT NOT NULL,
|
||||||
|
packagelistitem_id TEXT NOT NULL,
|
||||||
|
status INTEGER NOT NULL,
|
||||||
|
|
||||||
|
FOREIGN KEY(trip_id) REFERENCES trips(id)
|
||||||
|
FOREIGN KEY(packagelistitem_id) REFERENCES packagelistitems(id)
|
||||||
|
|
||||||
|
PRIMARY KEY(trip_id, packagelistitem_id)
|
||||||
|
)",
|
||||||
|
[],
|
||||||
|
)?;
|
||||||
|
|
||||||
for list in example_lists {
|
for list in example_lists {
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"INSERT INTO
|
"INSERT INTO
|
||||||
@@ -1040,3 +1059,220 @@ pub fn get_trips() -> rusqlite::Result<Vec<Trip>> {
|
|||||||
|
|
||||||
Ok(trips)
|
Ok(trips)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_trip(trip_id: Uuid) -> rusqlite::Result<Option<Trip>> {
|
||||||
|
let conn = rusqlite::Connection::open("./sqlite.db")?;
|
||||||
|
|
||||||
|
let mut statement = conn.prepare(
|
||||||
|
"SELECT
|
||||||
|
trips.id AS trip_id,
|
||||||
|
trips.name AS trip_name,
|
||||||
|
trips.date AS trip_date,
|
||||||
|
trips.days AS trip_days,
|
||||||
|
trips.state AS trip_state
|
||||||
|
FROM trips
|
||||||
|
WHERE
|
||||||
|
trip_id = ?1
|
||||||
|
",
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let trip_query_result = statement.query_map(rusqlite::params![trip_id], |row| {
|
||||||
|
Ok(Trip{
|
||||||
|
id: row.get_unwrap(0),
|
||||||
|
name: row.get_unwrap(1),
|
||||||
|
date: row.get_unwrap(2),
|
||||||
|
parameters: TripParameters{
|
||||||
|
days: row.get_unwrap(3),
|
||||||
|
},
|
||||||
|
package_lists: vec![],
|
||||||
|
state: row.get_unwrap(4),
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let mut trip_query_result: Vec<Trip> = trip_query_result.flatten().collect();
|
||||||
|
|
||||||
|
if trip_query_result.is_empty() {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut trip: Trip = trip_query_result.remove(0);
|
||||||
|
|
||||||
|
let mut statement = conn.prepare(
|
||||||
|
"SELECT
|
||||||
|
trip_packagelist.packagelist_id as package_list_id,
|
||||||
|
packagelists.name as package_list_name
|
||||||
|
FROM trip_packagelist
|
||||||
|
INNER JOIN packagelists
|
||||||
|
ON packagelists.id == trip_packagelist.packagelist_id
|
||||||
|
WHERE
|
||||||
|
trip_packagelist.trip_id = ?1
|
||||||
|
|
||||||
|
",
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let lists: Vec<(Uuid, String)> = statement
|
||||||
|
.query_map(rusqlite::params![trip_id], |row| {
|
||||||
|
Ok((row.get_unwrap(0), row.get_unwrap(1)))
|
||||||
|
})?
|
||||||
|
.flatten()
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
trip.set_package_lists(lists);
|
||||||
|
|
||||||
|
Ok(Some(trip))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_trip_items(trip_id: Uuid) -> rusqlite::Result<Option<Vec<TripItem>>> {
|
||||||
|
// there has to be better way to get the rested option result
|
||||||
|
let trip: Option<Trip> = get_trip(trip_id)?;
|
||||||
|
println!("Getting trip items");
|
||||||
|
if let None = trip {
|
||||||
|
return Ok(None)
|
||||||
|
}
|
||||||
|
let trip = trip.unwrap();
|
||||||
|
|
||||||
|
let conn = rusqlite::Connection::open("./sqlite.db")?;
|
||||||
|
|
||||||
|
let mut statement = conn.prepare(
|
||||||
|
"SELECT
|
||||||
|
trip_items.packagelistitem_id,
|
||||||
|
status AS status,
|
||||||
|
pli.id AS packageitem_id,
|
||||||
|
pli.name AS packageitem_name,
|
||||||
|
pli.count AS packageitem_count,
|
||||||
|
FROM trip_items
|
||||||
|
INNER JOIN packagelistitems as pli
|
||||||
|
ON trip_items.packagelistitem_id = pli.id
|
||||||
|
WHERE
|
||||||
|
trip_items.trip_id = ?1
|
||||||
|
",
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let mut result : Vec<TripItem> = Vec::new();
|
||||||
|
|
||||||
|
let trip_items : Vec<TripItem> = statement.query_map(rusqlite::params![trip_id], |row| {
|
||||||
|
let package_item = PackageItem::new(
|
||||||
|
row.get_unwrap(2),
|
||||||
|
row.get_unwrap(3),
|
||||||
|
ItemSize::None,
|
||||||
|
row.get_unwrap(4),
|
||||||
|
ItemUsage::Singleton,
|
||||||
|
Preparation::None,
|
||||||
|
);
|
||||||
|
|
||||||
|
let package_list_id = row.get_unwrap(5);
|
||||||
|
|
||||||
|
let package_list = Rc::new(PackageList::new(
|
||||||
|
package_list_id,
|
||||||
|
row.get_unwrap(6),
|
||||||
|
));
|
||||||
|
|
||||||
|
Ok(TripItem{
|
||||||
|
status: row.get_unwrap(1),
|
||||||
|
package_item,
|
||||||
|
package_list: Rc::clone(package_lists.get(&package_list_id).unwrap()),
|
||||||
|
})
|
||||||
|
})?.flatten().collect();
|
||||||
|
|
||||||
|
println!("Found {} trip items in database", trip_items.len());
|
||||||
|
// get all package list items, so we know what we SHOULD have
|
||||||
|
let mut package_list_items = vec![];
|
||||||
|
for package_list in &trip.package_lists {
|
||||||
|
package_list_items.append(&mut get_list_items(package_list.id)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("There should be {} items according to the package lists", package_list_items.len());
|
||||||
|
|
||||||
|
let package_list_item_ids: Vec<Uuid> = package_list_items.iter().map(|item| item.id).collect();
|
||||||
|
|
||||||
|
// three possibilities:
|
||||||
|
//
|
||||||
|
// * The trip item is there => use it
|
||||||
|
// * The trip item is not there => create it with defaults
|
||||||
|
// * There is a trip item that should no be there (e.g. because the package
|
||||||
|
// list was changed and a package item was removed)
|
||||||
|
//
|
||||||
|
// We can either just not use it (letting it rot in the database). It will
|
||||||
|
// never be removed automatically. But if we later add it again, something
|
||||||
|
// will break (e.g. if someone re-attaches the package list to the trip).
|
||||||
|
|
||||||
|
// first run: get all trip items that have the trip id set. We need to
|
||||||
|
// check this list against the items. If there are any returned that are
|
||||||
|
// NOT part of the package list items, we remove them
|
||||||
|
for package_item in package_list_items {
|
||||||
|
|
||||||
|
|
||||||
|
for trip_item in &trip_items {
|
||||||
|
let item_id = trip_item.package_item.id;
|
||||||
|
if !package_list_item_ids.contains(&item_id) {
|
||||||
|
// there is a trip item that does no longer have a corresponding
|
||||||
|
// package list item (because a package list was detached).
|
||||||
|
// Remove it
|
||||||
|
println!("Would remove package item with id {} (\"{}\")",
|
||||||
|
package_item.id, package_item.name);
|
||||||
|
// conn.execute(
|
||||||
|
// "DELETE
|
||||||
|
// FROM trip_items
|
||||||
|
// WHERE
|
||||||
|
// trip_items.trip_id = ?1
|
||||||
|
// AND
|
||||||
|
// trip_items.packagelistitem_id = ?2
|
||||||
|
// ",
|
||||||
|
// rusqlite::params![trip_id, package_item.id]
|
||||||
|
// )?;
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !trip_items.iter().map(|i| i.package_item.id).collect::<Vec<Uuid>>().contains(&package_item.id) {
|
||||||
|
println!("Found new trip item!");
|
||||||
|
|
||||||
|
println!("Looking into hashmap with {:?}", package_item.id);
|
||||||
|
let list = Rc::clone(package_lists.get(&package_item.id).unwrap());
|
||||||
|
let new_trip_item = TripItem {
|
||||||
|
status: TripItemStatus::Pending,
|
||||||
|
package_item,
|
||||||
|
package_list: list,
|
||||||
|
};
|
||||||
|
|
||||||
|
conn.execute(
|
||||||
|
"INSERT INTO
|
||||||
|
trip_items (
|
||||||
|
trip_id,
|
||||||
|
packagelistitem_id,
|
||||||
|
status
|
||||||
|
) VALUES (
|
||||||
|
?1,
|
||||||
|
?2,
|
||||||
|
?3
|
||||||
|
)
|
||||||
|
",
|
||||||
|
rusqlite::params![
|
||||||
|
trip_id,
|
||||||
|
new_trip_item.package_item.id,
|
||||||
|
new_trip_item.status
|
||||||
|
]
|
||||||
|
)?;
|
||||||
|
|
||||||
|
|
||||||
|
result.push(new_trip_item);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we've come so far, the trip is actually in the database, so let's
|
||||||
|
// just use it
|
||||||
|
println!("Using trip item from database");
|
||||||
|
let list = Rc::clone(package_lists.get(&package_item.id).unwrap());
|
||||||
|
result.push(TripItem {
|
||||||
|
status: TripItemStatus::Pending,
|
||||||
|
package_item,
|
||||||
|
package_list: list,
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Ok(Some(result))
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ pub mod trip;
|
|||||||
pub use trip::Trip;
|
pub use trip::Trip;
|
||||||
pub use trip::TripParameters;
|
pub use trip::TripParameters;
|
||||||
pub use trip::TripState;
|
pub use trip::TripState;
|
||||||
|
pub use trip::TripItem;
|
||||||
|
pub use trip::TripItemStatus;
|
||||||
|
|
||||||
pub fn get_list(id: Uuid) -> Option<packagelist::PackageList> {
|
pub fn get_list(id: Uuid) -> Option<packagelist::PackageList> {
|
||||||
self::db::get_list(id).unwrap()
|
self::db::get_list(id).unwrap()
|
||||||
@@ -51,3 +53,11 @@ pub fn new_item(list_id: Uuid, item_name: String, item_count: i32) -> packagelis
|
|||||||
pub fn get_trips() -> Vec<Trip> {
|
pub fn get_trips() -> Vec<Trip> {
|
||||||
self::db::get_trips().unwrap()
|
self::db::get_trips().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_trip(trip_id: Uuid) -> Option<Trip> {
|
||||||
|
self::db::get_trip(trip_id).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_trip_items(trip_id: Uuid) -> Option<Vec<TripItem>> {
|
||||||
|
self::db::get_trip_items(trip_id).unwrap()
|
||||||
|
}
|
||||||
|
|||||||
@@ -131,6 +131,40 @@ pub fn new() -> warp::filters::BoxedFilter<(impl warp::Reply,)> {
|
|||||||
.map(|| warp::reply::json(&super::get_trips()))
|
.map(|| warp::reply::json(&super::get_trips()))
|
||||||
.with(&cors);
|
.with(&cors);
|
||||||
|
|
||||||
|
let trip = warp::path!("v1" / "trips" / String)
|
||||||
|
.and(warp::path::end())
|
||||||
|
.and(warp::get())
|
||||||
|
.and(accept_json)
|
||||||
|
.and_then(|trip_id: String| async move {
|
||||||
|
match Uuid::parse_str(&trip_id) {
|
||||||
|
Ok(trip_id) => {
|
||||||
|
match &super::get_trip(trip_id) {
|
||||||
|
Some(trip) => Ok(warp::reply::json(trip)),
|
||||||
|
None => Err(warp::reject::not_found()),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(_) => Err(warp::reject::custom(InvalidUuid)),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.with(&cors);
|
||||||
|
|
||||||
|
let trip_items = warp::path!("v1" / "trips" / String / "items")
|
||||||
|
.and(warp::path::end())
|
||||||
|
.and(warp::get())
|
||||||
|
.and(accept_json)
|
||||||
|
.and_then(|trip_id: String| async move {
|
||||||
|
match Uuid::parse_str(&trip_id) {
|
||||||
|
Ok(trip_id) => {
|
||||||
|
match &super::get_trip_items(trip_id) {
|
||||||
|
Some(trip) => Ok(warp::reply::json(trip)),
|
||||||
|
None => Err(warp::reject::not_found()),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(_) => Err(warp::reject::custom(InvalidUuid)),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.with(&cors);
|
||||||
|
|
||||||
root.or(v1)
|
root.or(v1)
|
||||||
.or(lists)
|
.or(lists)
|
||||||
.or(list)
|
.or(list)
|
||||||
@@ -138,6 +172,8 @@ pub fn new() -> warp::filters::BoxedFilter<(impl warp::Reply,)> {
|
|||||||
.or(list_items)
|
.or(list_items)
|
||||||
.or(preparation)
|
.or(preparation)
|
||||||
.or(trips)
|
.or(trips)
|
||||||
|
.or(trip)
|
||||||
|
.or(trip_items)
|
||||||
.recover(handle_rejection)
|
.recover(handle_rejection)
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::PackageItem;
|
||||||
|
use crate::PackageList;
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub enum TripItemStatus {
|
pub enum TripItemStatus {
|
||||||
@@ -9,6 +14,36 @@ pub enum TripItemStatus {
|
|||||||
Packed,
|
Packed,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl rusqlite::types::FromSql for TripItemStatus {
|
||||||
|
fn column_result(value: rusqlite::types::ValueRef) -> rusqlite::types::FromSqlResult<Self> {
|
||||||
|
match value.as_i64()? {
|
||||||
|
1 => Ok(TripItemStatus::Pending),
|
||||||
|
2 => Ok(TripItemStatus::Ready),
|
||||||
|
3 => Ok(TripItemStatus::Packed),
|
||||||
|
v => Err(rusqlite::types::FromSqlError::OutOfRange(v)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl rusqlite::types::ToSql for TripItemStatus {
|
||||||
|
fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput> {
|
||||||
|
let v = rusqlite::types::Value::Integer(match self {
|
||||||
|
TripItemStatus::Pending => 1,
|
||||||
|
TripItemStatus::Ready => 2,
|
||||||
|
TripItemStatus::Packed => 3,
|
||||||
|
});
|
||||||
|
rusqlite::Result::Ok(rusqlite::types::ToSqlOutput::Owned(v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct TripItem {
|
||||||
|
pub status: TripItemStatus,
|
||||||
|
pub package_item: PackageItem,
|
||||||
|
pub package_list: Rc<PackageList>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct TripParameters {
|
pub struct TripParameters {
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
import PackageList from "./routes/PackageList.svelte";
|
import PackageList from "./routes/PackageList.svelte";
|
||||||
import Preparation from "./routes/Preparation.svelte";
|
import Preparation from "./routes/Preparation.svelte";
|
||||||
import Trips from "./routes/Trips.svelte";
|
import Trips from "./routes/Trips.svelte";
|
||||||
|
import Trip from "./routes/Trip.svelte";
|
||||||
|
import NotFound from "./routes/NotFound.svelte";
|
||||||
|
|
||||||
function normalize(path) {
|
function normalize(path) {
|
||||||
return path.replace(/\/+$/, '') + "/";
|
return path.replace(/\/+$/, '') + "/";
|
||||||
@@ -32,6 +34,10 @@
|
|||||||
} else if (urlParts[0] == "trips" && urlParts.length == 1) {
|
} else if (urlParts[0] == "trips" && urlParts.length == 1) {
|
||||||
console.log("=> Trips");
|
console.log("=> Trips");
|
||||||
currentRoute = Trips;
|
currentRoute = Trips;
|
||||||
|
} else if (urlParts[0] == "trips" && urlParts.length == 2) {
|
||||||
|
console.log("=> Trip");
|
||||||
|
currentRoute = Trip;
|
||||||
|
data = {id: urlParts[1]};
|
||||||
} else if (urlParts[0] == "lists" && urlParts.length == 2) {
|
} else if (urlParts[0] == "lists" && urlParts.length == 2) {
|
||||||
console.log("=> PackageList");
|
console.log("=> PackageList");
|
||||||
currentRoute = PackageList;
|
currentRoute = PackageList;
|
||||||
@@ -45,6 +51,7 @@
|
|||||||
data = {list_id: urlParts[1], item_id: urlParts[3]};
|
data = {list_id: urlParts[1], item_id: urlParts[3]};
|
||||||
} else {
|
} else {
|
||||||
console.log("No matching route found");
|
console.log("No matching route found");
|
||||||
|
currentRoute = NotFound;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
10
ui/src/routes/NotFound.svelte
Normal file
10
ui/src/routes/NotFound.svelte
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export let redirect;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<div>
|
||||||
|
404 -- Not Found
|
||||||
|
</div>
|
||||||
|
<button on:click={() => redirect("/")}>Back to home</button>
|
||||||
|
</main>
|
||||||
78
ui/src/routes/Trip.svelte
Normal file
78
ui/src/routes/Trip.svelte
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export let redirect;
|
||||||
|
export let data;
|
||||||
|
|
||||||
|
export const url = "/trips/"
|
||||||
|
|
||||||
|
async function getTrip() {
|
||||||
|
let response = await fetch(`http://localhost:9000/v1/trips/${data.id}`, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Accept": "application/json"
|
||||||
|
},
|
||||||
|
cache: "no-store",
|
||||||
|
});
|
||||||
|
let trip = await response.json();
|
||||||
|
return trip;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getTripItems() {
|
||||||
|
let response = await fetch(`http://localhost:9000/v1/trips/${data.id}/items`, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Accept": "application/json"
|
||||||
|
},
|
||||||
|
cache: "no-store",
|
||||||
|
});
|
||||||
|
let items = await response.json();
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<div class="container mx-auto mt-12">
|
||||||
|
{#await getTrip()}
|
||||||
|
<p>Loading</p>
|
||||||
|
{:then trip}
|
||||||
|
<h2 class="text-3xl mt-12 mb-20 font-semibold text-center mb-5 mt-3">{trip.name}</h2>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>Date</td>
|
||||||
|
<td>{trip.date}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Duration</td>
|
||||||
|
<td>{trip.parameters.days} Days</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Status</td>
|
||||||
|
<td>{trip.state}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table class="table-auto w-full">
|
||||||
|
<thead>
|
||||||
|
<tr class="font-semibold tracking-wider text-left bg-gray-100 uppercase border-b border-gray-400">
|
||||||
|
<th class="p-3">Name</th>
|
||||||
|
<th class="p-3">Status</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{#await getTripItems()}
|
||||||
|
<p>Loading</p>
|
||||||
|
{:then items}
|
||||||
|
{#each items as item}
|
||||||
|
<tr class="border">
|
||||||
|
<td class="p-3">{item.packageItem.name}</td>
|
||||||
|
<td class="p-3">{item.status}</td>
|
||||||
|
</tr>
|
||||||
|
{/each}
|
||||||
|
{:catch error}
|
||||||
|
{error}
|
||||||
|
{/await}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{/await}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
{:then trips}
|
{:then trips}
|
||||||
{#each trips as trip}
|
{#each trips as trip}
|
||||||
<tr class="border" on:click={e => redirect(url + trip.id)}>
|
<tr class="border" on:click={e => redirect(url + trip.id)}>
|
||||||
<td class="p-3">{trip.name}</td>
|
<td class="p-3" on:click={() => redirect(`/trips/${trip.id}`)}>{trip.name}</td>
|
||||||
<td class="p-3">{trip.date}</td>
|
<td class="p-3">{trip.date}</td>
|
||||||
<td class="p-3">{trip.parameters.days}</td>
|
<td class="p-3">{trip.parameters.days}</td>
|
||||||
{#if trip.state == "active"}
|
{#if trip.state == "active"}
|
||||||
|
|||||||
Reference in New Issue
Block a user