You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
120 lines
3.5 KiB
120 lines
3.5 KiB
<script> |
|
import { onMount } from 'svelte'; |
|
import { api } from '../../urls.svelte'; |
|
import { error, yikes } from '../../warn.svelte'; |
|
import { t } from '../../translations.svelte'; |
|
|
|
import Locations from './Locations.svelte'; |
|
import ItemList from './ItemList.svelte'; |
|
import ItemProps from './ItemProps.svelte'; |
|
import Notes from '../notes/RelatedNotes.svelte'; |
|
import Tags from '../tags/TagList.svelte'; |
|
|
|
let loc_data = $derived.by(loadLocation); |
|
let item = $state(null); |
|
let location = $state(null); |
|
let draggedItem = $state(null) |
|
|
|
$effect(() => { |
|
// This effect runs whenever `location` changes |
|
if (location !== null) item = null; |
|
}); |
|
let properties = $state(null); |
|
let top_level = $state(null); |
|
|
|
async function move_dragged_to(new_loc){ |
|
const data = { item : draggedItem, target: new_loc }; |
|
const url = api('stock/move_item'); |
|
const res = await fetch(url,{ |
|
credentials : 'include', |
|
method : 'PATCH', |
|
body : JSON.stringify(data) |
|
}); |
|
if (res.ok){ |
|
yikes(); |
|
} else error(res); |
|
} |
|
|
|
async function loadLocation(){ |
|
if (!location) return null; |
|
const url = api(`stock/location/${location.id}`) |
|
const res = await fetch(url,{credentials:'include'}); |
|
if (res.ok){ |
|
yikes(); |
|
return res.json(); |
|
} else { |
|
error(res); |
|
return null; |
|
} |
|
} |
|
|
|
async function loadProperties(){ |
|
const url = api('stock/properties') |
|
const res = await fetch(url,{credentials:'include'}); |
|
if (res.ok){ |
|
var json = await res.json(); |
|
var dict = {} |
|
for (var entry of json.sort((a,b) => b.id - a.id)) dict[entry.name+'.'+entry.unit] = entry; |
|
properties = null; |
|
properties = Object.values(dict).sort((a,b) => a.name.localeCompare(b.name)); |
|
yikes(); |
|
} else error(res); |
|
} |
|
|
|
async function loadUserLocations(){ |
|
const url = api('stock/locations/of_user') |
|
const res = await fetch(url,{credentials:'include'}); |
|
if (res.ok){ |
|
top_level = await res.json(); |
|
yikes(); |
|
} else error(res); |
|
} |
|
|
|
function load(){ |
|
loadUserLocations(); |
|
loadProperties(); |
|
} |
|
|
|
onMount(load); |
|
</script> |
|
|
|
<style> |
|
|
|
</style> |
|
|
|
<h2>{t('Stock')}</h2> |
|
<div class="grid3"> |
|
<div class="locations"> |
|
{#if top_level} |
|
{#each top_level as realm,idx} |
|
<h3>{realm.name}</h3> |
|
{#if realm.locations} |
|
<Locations locations={realm.locations} bind:selected={location} {move_dragged_to} /> |
|
{/if} |
|
{/each} |
|
{/if} |
|
</div> |
|
{#await loc_data} |
|
<span>loading…</span> |
|
{:then data} |
|
<div class="items"> |
|
{#if location} |
|
<h3>{location.name}</h3> |
|
{/if} |
|
<ItemList items={data?.items.sort((a,b) => a.code.localeCompare(b.code))} bind:selected={item} drag_start={item => draggedItem = item} /> |
|
</div> |
|
<div class="properties"> |
|
<ItemProps {item} {properties} /> |
|
</div> |
|
{#if item} |
|
<div class="tags"> |
|
<span>{t('tags')}</span> |
|
<Tags module="stock" id={item.id} user_list={data.users} /> |
|
</div> |
|
<div class="notes"> |
|
<span>{t('notes')}</span> |
|
<Notes module="stock" entity_id={item.id} /> |
|
</div> |
|
{/if} |
|
{/await} |
|
</div> |