diff --git a/src/lib/components/SingleItemCard.svelte b/src/lib/components/SingleItemCard.svelte new file mode 100644 index 0000000..32935aa --- /dev/null +++ b/src/lib/components/SingleItemCard.svelte @@ -0,0 +1,35 @@ + + + diff --git a/src/lib/components/SingleItemCardWindow.svelte b/src/lib/components/SingleItemCardWindow.svelte new file mode 100644 index 0000000..aa95298 --- /dev/null +++ b/src/lib/components/SingleItemCardWindow.svelte @@ -0,0 +1,55 @@ + + + + + + + diff --git a/src/lib/styles/main.css b/src/lib/styles/main.css index cc21549..6caec57 100644 --- a/src/lib/styles/main.css +++ b/src/lib/styles/main.css @@ -46,6 +46,18 @@ border-radius: 10px; } +.last-edited-item-panel { + width: 50%; + max-width: 50%; +} + +@media (max-width: 768px) { + .last-edited-item-panel { + width: 100%; + max-width: 100%; + } +} + /* For components inset within other components*/ .internal-component { margin: 1rem 0; @@ -1134,4 +1146,65 @@ input[type="file"][accept*="image"] { ::backdrop { background: color-mix(in oklch, var(--color-surface-900) 70%, transparent); z-index: 9998; -} \ No newline at end of file +} + + +/* for SingleItemCard */ + +.single-item-card-flex { + display: flex; + align-items: center; + gap: 0.5rem; + } + + .single-item-card { + display: flex; + flex-direction: column; + gap: 0.75rem; + padding: 1rem; + border-radius: 0.5rem; + background: var(--glass-color, rgba(255, 255, 255, 0.1)); + text-decoration: none; + color: inherit; + transition: background-color 0.2s ease; + flex: 1; + } + + .single-item-card:hover { + background: var(--glass-hover-color, rgba(255, 255, 255, 0.15)); + } + + .single-item-card-subcard { + display: flex; + align-items: center; + gap: 1rem; + } + + .single-item-card-main-row { + justify-content: space-between; + gap: 1.5rem; + } + + .single-item-card-text-block { + display: flex; + flex-direction: column; + gap: 0.25rem; + text-align: left; + min-width: 0; + } + + .single-item-card-location { + margin-left: auto; + text-align: right; + white-space: nowrap; + } + + .single-important-text { + font-weight: 600; + font-size: 1.1rem; + } + + .single-sub-text { + font-size: 0.9rem; + opacity: 0.7; + } \ No newline at end of file diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 69f2393..df94283 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -4,6 +4,7 @@ import Dialog from "$lib/components/Dialog.svelte"; import EditItem from "$lib/components/EditItem.svelte"; import ItemContainer from "$lib/components/ItemContainer.svelte"; + import SingleItemCard from "$lib/components/SingleItemCard.svelte"; import ItemDetails from "$lib/components/ItemDetails.svelte"; import ItemTree from "$lib/components/ItemTree.svelte"; import Menu from "$lib/components/Menu.svelte"; @@ -22,6 +23,7 @@ import "$lib/styles/main.css"; import { Switch } from "@skeletonlabs/skeleton-svelte"; import { onDestroy, onMount } from "svelte"; + import SingleItemCardWindow from "$lib/components/SingleItemCardWindow.svelte"; let { searchQuery = "", @@ -34,6 +36,7 @@ }>(); let searchResults = $state([]); + let lastUpdatedItem = $state(null); let sortOption = $state("alphabetical"); let exactSearch = $state(false); let viewMode = $state("list"); @@ -104,6 +107,7 @@ const data = await response.json(); searchResults = data as IBasicItemPopulated[]; itemCount = searchResults.length; + getLastUpdatedItem(); if (showItemTree && itemTreeRef) { await itemTreeRef.reload(); } @@ -112,6 +116,29 @@ } } + async function getLastUpdatedItem(){ + try { + const response = await fetch( + `/api/items/search?` + + `name=${encodeURIComponent('')}&` + + `sort=${encodeURIComponent('recentlyChanged')}&` + + `exact=${'false'}`, + { + method: "GET", + headers: { "Content-Type": "application/json" }, + }, + ); + + if (!response.ok) throw new Error("Failed to fetch items"); + + const data = await response.json(); + const fullSearchResults = data as IBasicItemPopulated[]; + lastUpdatedItem = fullSearchResults[0] ?? null; + } catch (err) { + console.error("Home: Error loading last updated item:", err); + } + } + function toggleView() { if (viewMode === "list") { viewMode = "tree"; @@ -207,6 +234,7 @@ onMount(() => { document.title = "Home - AssetAtlas"; restoreToggleStates(); + void getLastUpdatedItem(); unsubscribe = topBarHeight.subscribe((value) => { currentTopBarHeight = value; }); @@ -278,9 +306,20 @@ + + {#if viewMode === "list"} {#if itemCount > 0} + {#if lastUpdatedItem} +
+ Last Edited Item: + + + + +
+ {/if} handleSearch(searchQuery)} @@ -319,6 +358,16 @@ {/if} {:else if showItemTree} + {#if lastUpdatedItem} + + + + + {/if}