mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 19:01:08 +02:00
refactor(mana): rename inventar → inventory across the codebase
The workbench-registry app id 'inventar' did not match its @mana/shared-branding MANA_APPS counterpart 'inventory', so the tier- gating join in apps/web/src/lib/app-registry/registry.ts silently failed for the inventory module — it fell into the "no MANA_APPS entry, default visible" fallback and was effectively un-gated. The codebase had also voted overwhelmingly for 'inventar' (53 files) vs 'inventory' (3 files in shared-branding), so the long-standing mismatch was just bookkeeping debt waiting to bite. Pre-release, no live data, so the cleanest fix is to align everything on the English 'inventory': - Workbench-registry id, module.config.ts appId, module folder, route folder and i18n locale folder all renamed via git mv - Standalone apps/inventar/ workspace package renamed - All imports, store identifiers (InventarEvents → InventoryEvents, INVENTAR_GUEST_SEED, inventarModuleConfig), i18n keys and href/goto paths follow the rename - The German display label "Inventar" is preserved everywhere it is a user-visible string (page titles, i18n values, toast labels) - Dexie table prefixes (invCollections, invItems, …) are unchanged - Drive-by fix: ListView.svelte was querying non-existent inventarCollections/inventarItems tables — corrected to the actual invCollections/invItems names from module.config - The "inventar ↔ inventory id mismatch" workaround comment in registry.ts is removed since the mismatch no longer exists module-registry.ts also picks up the user's parallel newsModuleConfig addition because both edits land in the same import block — keeping them split would have left the build in an inconsistent state. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
51f408755c
commit
45790ffbb8
65 changed files with 173 additions and 147 deletions
|
|
@ -1,14 +0,0 @@
|
||||||
{
|
|
||||||
"name": "inventar",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"private": true,
|
|
||||||
"description": "Inventar - Configurable Inventory Management",
|
|
||||||
"scripts": {
|
|
||||||
"dev": "pnpm --filter @inventar/web dev",
|
|
||||||
"dev:web": "pnpm --filter @inventar/web dev"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"typescript": "^5.9.3"
|
|
||||||
},
|
|
||||||
"packageManager": "pnpm@9.15.0"
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Inventar
|
# Inventory
|
||||||
|
|
||||||
Configurable inventory management app - track anything with custom schemas.
|
Configurable inventory management app - track anything with custom schemas.
|
||||||
|
|
||||||
|
|
@ -6,7 +6,7 @@ Configurable inventory management app - track anything with custom schemas.
|
||||||
|
|
||||||
## Project Overview
|
## Project Overview
|
||||||
|
|
||||||
Inventar is a schema-less inventory management system built with SvelteKit. Users can create collections with custom field definitions, organize items by location and category, and view them in list/grid/table views.
|
Inventory is a schema-less inventory management system built with SvelteKit. Users can create collections with custom field definitions, organize items by location and category, and view them in list/grid/table views.
|
||||||
|
|
||||||
### Tech Stack
|
### Tech Stack
|
||||||
|
|
||||||
|
|
@ -31,13 +31,13 @@ Inventar is a schema-less inventory management system built with SvelteKit. User
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# From monorepo root
|
# From monorepo root
|
||||||
pnpm dev:inventar:web # Start web app on port 5190
|
pnpm dev:inventory:web # Start web app on port 5190
|
||||||
```
|
```
|
||||||
|
|
||||||
## Project Structure
|
## Project Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
apps/inventar/
|
apps/inventory/
|
||||||
├── apps/
|
├── apps/
|
||||||
│ └── web/ # SvelteKit web client
|
│ └── web/ # SvelteKit web client
|
||||||
│ ├── src/
|
│ ├── src/
|
||||||
14
apps/inventory/package.json
Normal file
14
apps/inventory/package.json
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"name": "inventory",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"description": "Inventory - Configurable Inventory Management",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "pnpm --filter @inventory/web dev",
|
||||||
|
"dev:web": "pnpm --filter @inventory/web dev"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^5.9.3"
|
||||||
|
},
|
||||||
|
"packageManager": "pnpm@9.15.0"
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "@inventar/shared",
|
"name": "@inventory/shared",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|
@ -34,7 +34,7 @@ const sections: Section[] = [
|
||||||
{ name: 'ManaCalendar', icon: 'ph:calendar-bold', tagline: 'Kalender', url: 'https://calendar.mana.how' },
|
{ name: 'ManaCalendar', icon: 'ph:calendar-bold', tagline: 'Kalender', url: 'https://calendar.mana.how' },
|
||||||
{ name: 'Kontakte', icon: 'ph:address-book-bold', tagline: 'Kontakte', url: 'https://contacts.mana.how' },
|
{ name: 'Kontakte', icon: 'ph:address-book-bold', tagline: 'Kontakte', url: 'https://contacts.mana.how' },
|
||||||
{ name: 'ManaStorage', icon: 'ph:cloud-bold', tagline: 'Cloud-Speicher', url: 'https://storage.mana.how' },
|
{ name: 'ManaStorage', icon: 'ph:cloud-bold', tagline: 'Cloud-Speicher', url: 'https://storage.mana.how' },
|
||||||
{ name: 'Inventar', icon: 'ph:package-bold', tagline: 'Inventar', url: 'https://inventar.mana.how' },
|
{ name: 'Inventar', icon: 'ph:package-bold', tagline: 'Inventar', url: 'https://inventory.mana.how' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ const APP_SUBDOMAINS = new Set([
|
||||||
'picture',
|
'picture',
|
||||||
'calc',
|
'calc',
|
||||||
'citycorners',
|
'citycorners',
|
||||||
'inventar',
|
'inventory',
|
||||||
'times',
|
'times',
|
||||||
'uload',
|
'uload',
|
||||||
'memoro',
|
'memoro',
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ import {
|
||||||
Calculator,
|
Calculator,
|
||||||
Lightning,
|
Lightning,
|
||||||
Sparkle,
|
Sparkle,
|
||||||
|
Newspaper,
|
||||||
} from '@mana/shared-icons';
|
} from '@mana/shared-icons';
|
||||||
|
|
||||||
// ── Apps with entity capabilities ───────────────────────────
|
// ── Apps with entity capabilities ───────────────────────────
|
||||||
|
|
@ -565,13 +566,13 @@ registerApp({
|
||||||
});
|
});
|
||||||
|
|
||||||
registerApp({
|
registerApp({
|
||||||
id: 'inventar',
|
id: 'inventory',
|
||||||
name: 'Inventar',
|
name: 'Inventar',
|
||||||
color: '#78716C',
|
color: '#78716C',
|
||||||
icon: Package,
|
icon: Package,
|
||||||
views: {
|
views: {
|
||||||
list: { load: () => import('$lib/modules/inventar/ListView.svelte') },
|
list: { load: () => import('$lib/modules/inventory/ListView.svelte') },
|
||||||
detail: { load: () => import('$lib/modules/inventar/views/DetailView.svelte') },
|
detail: { load: () => import('$lib/modules/inventory/views/DetailView.svelte') },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -669,3 +670,24 @@ registerApp({
|
||||||
list: { load: () => import('$lib/modules/playground/ListView.svelte') },
|
list: { load: () => import('$lib/modules/playground/ListView.svelte') },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
registerApp({
|
||||||
|
id: 'news',
|
||||||
|
name: 'News',
|
||||||
|
color: '#10B981',
|
||||||
|
icon: Newspaper,
|
||||||
|
views: {
|
||||||
|
list: { load: () => import('$lib/modules/news/ListView.svelte') },
|
||||||
|
},
|
||||||
|
contextMenuActions: [
|
||||||
|
{
|
||||||
|
id: 'open-feed',
|
||||||
|
label: 'Feed öffnen',
|
||||||
|
icon: Plus,
|
||||||
|
action: () =>
|
||||||
|
window.dispatchEvent(
|
||||||
|
new CustomEvent('mana:quick-action', { detail: { app: 'news', action: 'open' } })
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -91,10 +91,9 @@ export function getAllApps(): AppDescriptor[] {
|
||||||
*
|
*
|
||||||
* Returns null when there is no matching MANA_APPS entry. Internal-only
|
* Returns null when there is no matching MANA_APPS entry. Internal-only
|
||||||
* tools that exist in the workbench but not in MANA_APPS (`automations`,
|
* tools that exist in the workbench but not in MANA_APPS (`automations`,
|
||||||
* `playground`, the `inventar` ↔ `inventory` id mismatch) fall into this
|
* `playground`) fall into this case — `getAccessibleApps` then treats
|
||||||
* case — `getAccessibleApps` then treats them as visible by default
|
* them as visible by default rather than hiding them for everyone, since
|
||||||
* rather than hiding them for everyone, since the alternative is a
|
* the alternative is a silent regression for founders/devs.
|
||||||
* silent regression for founders/devs.
|
|
||||||
*/
|
*/
|
||||||
function getAppRequiredTier(appId: string): AccessTier | null {
|
function getAppRequiredTier(appId: string): AccessTier | null {
|
||||||
const branding = MANA_APPS.find((a) => a.id === appId);
|
const branding = MANA_APPS.find((a) => a.id === appId);
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,7 @@ describe('module-registry — pre-refactor snapshot', () => {
|
||||||
music: ['songs', 'mukkePlaylists', 'playlistSongs', 'mukkeProjects', 'markers', 'songTags'],
|
music: ['songs', 'mukkePlaylists', 'playlistSongs', 'mukkeProjects', 'markers', 'songTags'],
|
||||||
storage: ['files', 'storageFolders', 'fileTags'],
|
storage: ['files', 'storageFolders', 'fileTags'],
|
||||||
presi: ['presiDecks', 'slides', 'presiDeckTags'],
|
presi: ['presiDecks', 'slides', 'presiDeckTags'],
|
||||||
inventar: ['invCollections', 'invItems', 'invLocations', 'invCategories', 'invItemTags'],
|
inventory: ['invCollections', 'invItems', 'invLocations', 'invCategories', 'invItemTags'],
|
||||||
photos: ['albums', 'albumItems', 'photoFavorites', 'photoMediaTags'],
|
photos: ['albums', 'albumItems', 'photoFavorites', 'photoMediaTags'],
|
||||||
skilltree: ['skills', 'activities', 'achievements', 'skillTags'],
|
skilltree: ['skills', 'activities', 'achievements', 'skillTags'],
|
||||||
citycorners: ['cities', 'ccLocations', 'ccFavorites', 'ccLocationTags'],
|
citycorners: ['cities', 'ccLocations', 'ccFavorites', 'ccLocationTags'],
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ import { zitareModuleConfig } from '$lib/modules/zitare/module.config';
|
||||||
import { musicModuleConfig } from '$lib/modules/music/module.config';
|
import { musicModuleConfig } from '$lib/modules/music/module.config';
|
||||||
import { storageModuleConfig } from '$lib/modules/storage/module.config';
|
import { storageModuleConfig } from '$lib/modules/storage/module.config';
|
||||||
import { presiModuleConfig } from '$lib/modules/presi/module.config';
|
import { presiModuleConfig } from '$lib/modules/presi/module.config';
|
||||||
import { inventarModuleConfig } from '$lib/modules/inventar/module.config';
|
import { inventoryModuleConfig } from '$lib/modules/inventory/module.config';
|
||||||
import { photosModuleConfig } from '$lib/modules/photos/module.config';
|
import { photosModuleConfig } from '$lib/modules/photos/module.config';
|
||||||
import { skilltreeModuleConfig } from '$lib/modules/skilltree/module.config';
|
import { skilltreeModuleConfig } from '$lib/modules/skilltree/module.config';
|
||||||
import { citycornersModuleConfig } from '$lib/modules/citycorners/module.config';
|
import { citycornersModuleConfig } from '$lib/modules/citycorners/module.config';
|
||||||
|
|
@ -84,6 +84,7 @@ import { financeModuleConfig } from '$lib/modules/finance/module.config';
|
||||||
import { placesModuleConfig } from '$lib/modules/places/module.config';
|
import { placesModuleConfig } from '$lib/modules/places/module.config';
|
||||||
import { playgroundModuleConfig } from '$lib/modules/playground/module.config';
|
import { playgroundModuleConfig } from '$lib/modules/playground/module.config';
|
||||||
import { whoModuleConfig } from '$lib/modules/who/module.config';
|
import { whoModuleConfig } from '$lib/modules/who/module.config';
|
||||||
|
import { newsModuleConfig } from '$lib/modules/news/module.config';
|
||||||
|
|
||||||
export const MODULE_CONFIGS: readonly ModuleConfig[] = [
|
export const MODULE_CONFIGS: readonly ModuleConfig[] = [
|
||||||
manaCoreConfig,
|
manaCoreConfig,
|
||||||
|
|
@ -100,7 +101,7 @@ export const MODULE_CONFIGS: readonly ModuleConfig[] = [
|
||||||
musicModuleConfig,
|
musicModuleConfig,
|
||||||
storageModuleConfig,
|
storageModuleConfig,
|
||||||
presiModuleConfig,
|
presiModuleConfig,
|
||||||
inventarModuleConfig,
|
inventoryModuleConfig,
|
||||||
photosModuleConfig,
|
photosModuleConfig,
|
||||||
skilltreeModuleConfig,
|
skilltreeModuleConfig,
|
||||||
citycornersModuleConfig,
|
citycornersModuleConfig,
|
||||||
|
|
@ -123,6 +124,7 @@ export const MODULE_CONFIGS: readonly ModuleConfig[] = [
|
||||||
placesModuleConfig,
|
placesModuleConfig,
|
||||||
playgroundModuleConfig,
|
playgroundModuleConfig,
|
||||||
whoModuleConfig,
|
whoModuleConfig,
|
||||||
|
newsModuleConfig,
|
||||||
];
|
];
|
||||||
|
|
||||||
// ─── Derived Maps ──────────────────────────────────────────
|
// ─── Derived Maps ──────────────────────────────────────────
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ function registerLocale(lang: SupportedLocale) {
|
||||||
presi,
|
presi,
|
||||||
uload,
|
uload,
|
||||||
times,
|
times,
|
||||||
inventar,
|
inventory,
|
||||||
photos,
|
photos,
|
||||||
nutriphi,
|
nutriphi,
|
||||||
planta,
|
planta,
|
||||||
|
|
@ -49,6 +49,7 @@ function registerLocale(lang: SupportedLocale) {
|
||||||
guides,
|
guides,
|
||||||
help,
|
help,
|
||||||
cycles,
|
cycles,
|
||||||
|
news,
|
||||||
] = await Promise.all([
|
] = await Promise.all([
|
||||||
import(`./locales/apps/${lang}.json`),
|
import(`./locales/apps/${lang}.json`),
|
||||||
import(`./locales/common/${lang}.json`),
|
import(`./locales/common/${lang}.json`),
|
||||||
|
|
@ -72,7 +73,7 @@ function registerLocale(lang: SupportedLocale) {
|
||||||
import(`./locales/presi/${lang}.json`),
|
import(`./locales/presi/${lang}.json`),
|
||||||
import(`./locales/uload/${lang}.json`),
|
import(`./locales/uload/${lang}.json`),
|
||||||
import(`./locales/times/${lang}.json`),
|
import(`./locales/times/${lang}.json`),
|
||||||
import(`./locales/inventar/${lang}.json`),
|
import(`./locales/inventory/${lang}.json`),
|
||||||
import(`./locales/photos/${lang}.json`),
|
import(`./locales/photos/${lang}.json`),
|
||||||
import(`./locales/nutriphi/${lang}.json`),
|
import(`./locales/nutriphi/${lang}.json`),
|
||||||
import(`./locales/planta/${lang}.json`),
|
import(`./locales/planta/${lang}.json`),
|
||||||
|
|
@ -83,6 +84,7 @@ function registerLocale(lang: SupportedLocale) {
|
||||||
import(`./locales/guides/${lang}.json`),
|
import(`./locales/guides/${lang}.json`),
|
||||||
import(`./locales/help/${lang}.json`),
|
import(`./locales/help/${lang}.json`),
|
||||||
import(`./locales/cycles/${lang}.json`),
|
import(`./locales/cycles/${lang}.json`),
|
||||||
|
import(`./locales/news/${lang}.json`),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -108,7 +110,7 @@ function registerLocale(lang: SupportedLocale) {
|
||||||
presi: presi.default,
|
presi: presi.default,
|
||||||
uload: uload.default,
|
uload: uload.default,
|
||||||
times: times.default,
|
times: times.default,
|
||||||
inventar: inventar.default,
|
inventory: inventory.default,
|
||||||
photos: photos.default,
|
photos: photos.default,
|
||||||
nutriphi: nutriphi.default,
|
nutriphi: nutriphi.default,
|
||||||
planta: planta.default,
|
planta: planta.default,
|
||||||
|
|
@ -119,6 +121,7 @@ function registerLocale(lang: SupportedLocale) {
|
||||||
guides: guides.default,
|
guides: guides.default,
|
||||||
help: help.default,
|
help: help.default,
|
||||||
cycles: cycles.default,
|
cycles: cycles.default,
|
||||||
|
news: news.default,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
"nutriphi": "NutriPhi",
|
"nutriphi": "NutriPhi",
|
||||||
"planta": "Planta",
|
"planta": "Planta",
|
||||||
"presi": "Presi",
|
"presi": "Presi",
|
||||||
"inventar": "Inventar",
|
"inventory": "Inventar",
|
||||||
"memoro": "Memoro",
|
"memoro": "Memoro",
|
||||||
"questions": "Recherche",
|
"questions": "Recherche",
|
||||||
"skilltree": "Skills",
|
"skilltree": "Skills",
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
"nutriphi": "NutriPhi",
|
"nutriphi": "NutriPhi",
|
||||||
"planta": "Planta",
|
"planta": "Planta",
|
||||||
"presi": "Presi",
|
"presi": "Presi",
|
||||||
"inventar": "Inventory",
|
"inventory": "Inventory",
|
||||||
"memoro": "Memoro",
|
"memoro": "Memoro",
|
||||||
"questions": "Research",
|
"questions": "Research",
|
||||||
"skilltree": "Skills",
|
"skilltree": "Skills",
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
"nutriphi": "NutriPhi",
|
"nutriphi": "NutriPhi",
|
||||||
"planta": "Planta",
|
"planta": "Planta",
|
||||||
"presi": "Presi",
|
"presi": "Presi",
|
||||||
"inventar": "Inventario",
|
"inventory": "Inventario",
|
||||||
"memoro": "Memoro",
|
"memoro": "Memoro",
|
||||||
"questions": "Investigación",
|
"questions": "Investigación",
|
||||||
"skilltree": "Skills",
|
"skilltree": "Skills",
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
"nutriphi": "NutriPhi",
|
"nutriphi": "NutriPhi",
|
||||||
"planta": "Planta",
|
"planta": "Planta",
|
||||||
"presi": "Presi",
|
"presi": "Presi",
|
||||||
"inventar": "Inventaire",
|
"inventory": "Inventaire",
|
||||||
"memoro": "Memoro",
|
"memoro": "Memoro",
|
||||||
"questions": "Recherche",
|
"questions": "Recherche",
|
||||||
"skilltree": "Skills",
|
"skilltree": "Skills",
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
"nutriphi": "NutriPhi",
|
"nutriphi": "NutriPhi",
|
||||||
"planta": "Planta",
|
"planta": "Planta",
|
||||||
"presi": "Presi",
|
"presi": "Presi",
|
||||||
"inventar": "Inventario",
|
"inventory": "Inventario",
|
||||||
"memoro": "Memoro",
|
"memoro": "Memoro",
|
||||||
"questions": "Ricerca",
|
"questions": "Ricerca",
|
||||||
"skilltree": "Skills",
|
"skilltree": "Skills",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<!--
|
<!--
|
||||||
Inventar — Workbench ListView
|
Inventory — Workbench ListView
|
||||||
Collections and items overview.
|
Collections and items overview.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
|
@ -12,12 +12,12 @@
|
||||||
let { navigate }: ViewProps = $props();
|
let { navigate }: ViewProps = $props();
|
||||||
|
|
||||||
const collectionsQuery = useLiveQueryWithDefault(async () => {
|
const collectionsQuery = useLiveQueryWithDefault(async () => {
|
||||||
const all = await db.table<LocalCollection>('inventarCollections').orderBy('order').toArray();
|
const all = await db.table<LocalCollection>('invCollections').orderBy('order').toArray();
|
||||||
return all.filter((c) => !c.deletedAt);
|
return all.filter((c) => !c.deletedAt);
|
||||||
}, [] as LocalCollection[]);
|
}, [] as LocalCollection[]);
|
||||||
|
|
||||||
const itemsQuery = useLiveQueryWithDefault(async () => {
|
const itemsQuery = useLiveQueryWithDefault(async () => {
|
||||||
const all = await db.table<LocalItem>('inventarItems').toArray();
|
const all = await db.table<LocalItem>('invItems').toArray();
|
||||||
return all.filter((i) => !i.deletedAt);
|
return all.filter((i) => !i.deletedAt);
|
||||||
}, [] as LocalItem[]);
|
}, [] as LocalItem[]);
|
||||||
|
|
||||||
|
|
@ -20,7 +20,7 @@ const DEMO_COLLECTION_ID = 'demo-electronics';
|
||||||
const DEMO_LOCATION_ID = 'demo-home';
|
const DEMO_LOCATION_ID = 'demo-home';
|
||||||
const DEMO_CATEGORY_ID = 'demo-tech';
|
const DEMO_CATEGORY_ID = 'demo-tech';
|
||||||
|
|
||||||
export const INVENTAR_GUEST_SEED = {
|
export const INVENTORY_GUEST_SEED = {
|
||||||
invCollections: [
|
invCollections: [
|
||||||
{
|
{
|
||||||
id: DEMO_COLLECTION_ID,
|
id: DEMO_COLLECTION_ID,
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* Inventar constants — templates and status definitions.
|
* Inventar constants — templates and status definitions.
|
||||||
*
|
*
|
||||||
* Inlined from @inventar/shared since the unified app does not depend on it.
|
* Inlined from @inventory/shared since the unified app does not depend on it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { ItemStatus } from './queries';
|
import type { ItemStatus } from './queries';
|
||||||
|
|
@ -49,6 +49,6 @@ export {
|
||||||
invItemTable,
|
invItemTable,
|
||||||
invLocationTable,
|
invLocationTable,
|
||||||
invCategoryTable,
|
invCategoryTable,
|
||||||
INVENTAR_GUEST_SEED,
|
INVENTORY_GUEST_SEED,
|
||||||
} from './collections';
|
} from './collections';
|
||||||
export type { LocalCollection, LocalItem, LocalLocation, LocalCategory } from './types';
|
export type { LocalCollection, LocalItem, LocalLocation, LocalCategory } from './types';
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import type { ModuleConfig } from '$lib/data/module-registry';
|
import type { ModuleConfig } from '$lib/data/module-registry';
|
||||||
|
|
||||||
export const inventarModuleConfig: ModuleConfig = {
|
export const inventoryModuleConfig: ModuleConfig = {
|
||||||
appId: 'inventar',
|
appId: 'inventory',
|
||||||
tables: [
|
tables: [
|
||||||
{ name: 'invCollections', syncName: 'collections' },
|
{ name: 'invCollections', syncName: 'collections' },
|
||||||
{ name: 'invItems', syncName: 'items' },
|
{ name: 'invItems', syncName: 'items' },
|
||||||
|
|
@ -9,7 +9,7 @@ import { db } from '$lib/data/database';
|
||||||
import { decryptRecords } from '$lib/data/crypto';
|
import { decryptRecords } from '$lib/data/crypto';
|
||||||
import type { LocalCollection, LocalItem, LocalLocation, LocalCategory } from './types';
|
import type { LocalCollection, LocalItem, LocalLocation, LocalCategory } from './types';
|
||||||
|
|
||||||
// ─── Shared Types (inline to avoid @inventar/shared dependency) ───
|
// ─── Shared Types (inline to avoid @inventory/shared dependency) ───
|
||||||
|
|
||||||
export interface Collection {
|
export interface Collection {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
import { invCategoryTable } from '../collections';
|
import { invCategoryTable } from '../collections';
|
||||||
import { toCategory } from '../queries';
|
import { toCategory } from '../queries';
|
||||||
import type { LocalCategory } from '../types';
|
import type { LocalCategory } from '../types';
|
||||||
import { InventarEvents } from '@mana/shared-utils/analytics';
|
import { InventoryEvents } from '@mana/shared-utils/analytics';
|
||||||
|
|
||||||
export const categoriesStore = {
|
export const categoriesStore = {
|
||||||
async create(data: { name: string; icon?: string; color?: string; parentId?: string }) {
|
async create(data: { name: string; icon?: string; color?: string; parentId?: string }) {
|
||||||
|
|
@ -25,7 +25,7 @@ export const categoriesStore = {
|
||||||
order: siblings.length,
|
order: siblings.length,
|
||||||
};
|
};
|
||||||
await invCategoryTable.add(newLocal);
|
await invCategoryTable.add(newLocal);
|
||||||
InventarEvents.categoryCreated();
|
InventoryEvents.categoryCreated();
|
||||||
return toCategory(newLocal);
|
return toCategory(newLocal);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -49,6 +49,6 @@ export const categoriesStore = {
|
||||||
for (const deleteId of idsToDelete) {
|
for (const deleteId of idsToDelete) {
|
||||||
await invCategoryTable.update(deleteId, { deletedAt: now, updatedAt: now });
|
await invCategoryTable.update(deleteId, { deletedAt: now, updatedAt: now });
|
||||||
}
|
}
|
||||||
InventarEvents.categoryDeleted();
|
InventoryEvents.categoryDeleted();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
import { invCollectionTable } from '../collections';
|
import { invCollectionTable } from '../collections';
|
||||||
import { toCollection } from '../queries';
|
import { toCollection } from '../queries';
|
||||||
import type { LocalCollection } from '../types';
|
import type { LocalCollection } from '../types';
|
||||||
import { InventarEvents } from '@mana/shared-utils/analytics';
|
import { InventoryEvents } from '@mana/shared-utils/analytics';
|
||||||
|
|
||||||
export const collectionsStore = {
|
export const collectionsStore = {
|
||||||
async create(data: {
|
async create(data: {
|
||||||
|
|
@ -33,7 +33,7 @@ export const collectionsStore = {
|
||||||
itemCount: 0,
|
itemCount: 0,
|
||||||
};
|
};
|
||||||
await invCollectionTable.add(newLocal);
|
await invCollectionTable.add(newLocal);
|
||||||
InventarEvents.collectionCreated();
|
InventoryEvents.collectionCreated();
|
||||||
return toCollection(newLocal);
|
return toCollection(newLocal);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -52,7 +52,7 @@ export const collectionsStore = {
|
||||||
deletedAt: new Date().toISOString(),
|
deletedAt: new Date().toISOString(),
|
||||||
updatedAt: new Date().toISOString(),
|
updatedAt: new Date().toISOString(),
|
||||||
});
|
});
|
||||||
InventarEvents.collectionDeleted();
|
InventoryEvents.collectionDeleted();
|
||||||
},
|
},
|
||||||
|
|
||||||
async reorder(orderedIds: string[]) {
|
async reorder(orderedIds: string[]) {
|
||||||
|
|
@ -9,7 +9,7 @@ import { invItemTable } from '../collections';
|
||||||
import { toItem } from '../queries';
|
import { toItem } from '../queries';
|
||||||
import type { LocalItem } from '../types';
|
import type { LocalItem } from '../types';
|
||||||
import type { ItemStatus } from '../queries';
|
import type { ItemStatus } from '../queries';
|
||||||
import { InventarEvents } from '@mana/shared-utils/analytics';
|
import { InventoryEvents } from '@mana/shared-utils/analytics';
|
||||||
import { encryptRecord } from '$lib/data/crypto';
|
import { encryptRecord } from '$lib/data/crypto';
|
||||||
|
|
||||||
export const itemsStore = {
|
export const itemsStore = {
|
||||||
|
|
@ -49,7 +49,7 @@ export const itemsStore = {
|
||||||
const plaintextSnapshot = toItem(newLocal);
|
const plaintextSnapshot = toItem(newLocal);
|
||||||
await encryptRecord('invItems', newLocal);
|
await encryptRecord('invItems', newLocal);
|
||||||
await invItemTable.add(newLocal);
|
await invItemTable.add(newLocal);
|
||||||
InventarEvents.itemCreated();
|
InventoryEvents.itemCreated();
|
||||||
return plaintextSnapshot;
|
return plaintextSnapshot;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -76,7 +76,7 @@ export const itemsStore = {
|
||||||
};
|
};
|
||||||
await encryptRecord('invItems', diff);
|
await encryptRecord('invItems', diff);
|
||||||
await invItemTable.update(id, diff);
|
await invItemTable.update(id, diff);
|
||||||
InventarEvents.itemUpdated();
|
InventoryEvents.itemUpdated();
|
||||||
},
|
},
|
||||||
|
|
||||||
async delete(id: string) {
|
async delete(id: string) {
|
||||||
|
|
@ -84,7 +84,7 @@ export const itemsStore = {
|
||||||
deletedAt: new Date().toISOString(),
|
deletedAt: new Date().toISOString(),
|
||||||
updatedAt: new Date().toISOString(),
|
updatedAt: new Date().toISOString(),
|
||||||
});
|
});
|
||||||
InventarEvents.itemDeleted();
|
InventoryEvents.itemDeleted();
|
||||||
},
|
},
|
||||||
|
|
||||||
async deleteByCollection(collectionId: string) {
|
async deleteByCollection(collectionId: string) {
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
import { invLocationTable } from '../collections';
|
import { invLocationTable } from '../collections';
|
||||||
import { toLocation } from '../queries';
|
import { toLocation } from '../queries';
|
||||||
import type { LocalLocation } from '../types';
|
import type { LocalLocation } from '../types';
|
||||||
import { InventarEvents } from '@mana/shared-utils/analytics';
|
import { InventoryEvents } from '@mana/shared-utils/analytics';
|
||||||
|
|
||||||
function buildPath(locations: LocalLocation[], parentId?: string): string {
|
function buildPath(locations: LocalLocation[], parentId?: string): string {
|
||||||
if (!parentId) return '';
|
if (!parentId) return '';
|
||||||
|
|
@ -42,7 +42,7 @@ export const locationsStore = {
|
||||||
order: siblings.length,
|
order: siblings.length,
|
||||||
};
|
};
|
||||||
await invLocationTable.add(newLocal);
|
await invLocationTable.add(newLocal);
|
||||||
InventarEvents.locationCreated();
|
InventoryEvents.locationCreated();
|
||||||
return toLocation(newLocal);
|
return toLocation(newLocal);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -66,6 +66,6 @@ export const locationsStore = {
|
||||||
for (const deleteId of idsToDelete) {
|
for (const deleteId of idsToDelete) {
|
||||||
await invLocationTable.update(deleteId, { deletedAt: now, updatedAt: now });
|
await invLocationTable.update(deleteId, { deletedAt: now, updatedAt: now });
|
||||||
}
|
}
|
||||||
InventarEvents.locationDeleted();
|
InventoryEvents.locationDeleted();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* Uinventar Tags — Uses shared global tags + module-specific junction table.
|
* Inventory Tags — Uses shared global tags + module-specific junction table.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { db } from '$lib/data/database';
|
import { db } from '$lib/data/database';
|
||||||
|
|
@ -6,7 +6,7 @@ import { createViewStore } from '@mana/shared-stores';
|
||||||
import type { ViewMode, FilterCriteria } from '../queries';
|
import type { ViewMode, FilterCriteria } from '../queries';
|
||||||
|
|
||||||
export const viewStore = createViewStore<ViewMode, FilterCriteria>({
|
export const viewStore = createViewStore<ViewMode, FilterCriteria>({
|
||||||
storagePrefix: 'inventar',
|
storagePrefix: 'inventory',
|
||||||
defaultViewMode: 'list',
|
defaultViewMode: 'list',
|
||||||
defaultSort: { field: 'name', direction: 'asc' },
|
defaultSort: { field: 'name', direction: 'asc' },
|
||||||
hasActiveFilters: (f) =>
|
hasActiveFilters: (f) =>
|
||||||
|
|
@ -17,7 +17,7 @@ const SPLIT_APP_ID_LIST = [
|
||||||
'music',
|
'music',
|
||||||
'storage',
|
'storage',
|
||||||
'presi',
|
'presi',
|
||||||
'inventar',
|
'inventory',
|
||||||
'photos',
|
'photos',
|
||||||
'skilltree',
|
'skilltree',
|
||||||
'citycorners',
|
'citycorners',
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@
|
||||||
useAllItems,
|
useAllItems,
|
||||||
useAllLocations,
|
useAllLocations,
|
||||||
useAllCategories,
|
useAllCategories,
|
||||||
} from '$lib/modules/inventar/queries';
|
} from '$lib/modules/inventory/queries';
|
||||||
import { viewStore } from '$lib/modules/inventar/stores/view.svelte';
|
import { viewStore } from '$lib/modules/inventory/stores/view.svelte';
|
||||||
|
|
||||||
let { children }: { children: Snippet } = $props();
|
let { children }: { children: Snippet } = $props();
|
||||||
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { getContext } from 'svelte';
|
import { getContext } from 'svelte';
|
||||||
import { collectionsStore } from '$lib/modules/inventar/stores/collections.svelte';
|
import { collectionsStore } from '$lib/modules/inventory/stores/collections.svelte';
|
||||||
import { itemsStore } from '$lib/modules/inventar/stores/items.svelte';
|
import { itemsStore } from '$lib/modules/inventory/stores/items.svelte';
|
||||||
import {
|
import {
|
||||||
getSortedCollections,
|
getSortedCollections,
|
||||||
getItemCountByCollection,
|
getItemCountByCollection,
|
||||||
getTotalItemCount,
|
getTotalItemCount,
|
||||||
} from '$lib/modules/inventar/queries';
|
} from '$lib/modules/inventory/queries';
|
||||||
import type { Collection, Item } from '$lib/modules/inventar/queries';
|
import type { Collection, Item } from '$lib/modules/inventory/queries';
|
||||||
import { Plus, Trash } from '@mana/shared-icons';
|
import { Plus, Trash } from '@mana/shared-icons';
|
||||||
|
|
||||||
const collectionsCtx: { readonly value: Collection[] } = getContext('collections');
|
const collectionsCtx: { readonly value: Collection[] } = getContext('collections');
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleCollectionClick(collection: Collection) {
|
function handleCollectionClick(collection: Collection) {
|
||||||
goto(`/inventar/collections/${collection.id}`);
|
goto(`/inventory/collections/${collection.id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleDelete(e: Event, id: string) {
|
function handleDelete(e: Event, id: string) {
|
||||||
|
|
@ -50,7 +50,7 @@
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<a
|
<a
|
||||||
href="/inventar/collections/new"
|
href="/inventory/collections/new"
|
||||||
class="flex items-center gap-2 rounded-lg bg-[hsl(var(--primary))] px-4 py-2 text-sm font-medium text-[hsl(var(--primary-foreground))] transition-colors hover:opacity-90"
|
class="flex items-center gap-2 rounded-lg bg-[hsl(var(--primary))] px-4 py-2 text-sm font-medium text-[hsl(var(--primary-foreground))] transition-colors hover:opacity-90"
|
||||||
>
|
>
|
||||||
<Plus size={20} />
|
<Plus size={20} />
|
||||||
|
|
@ -69,7 +69,7 @@
|
||||||
Erstelle deine erste Sammlung, um loszulegen.
|
Erstelle deine erste Sammlung, um loszulegen.
|
||||||
</p>
|
</p>
|
||||||
<a
|
<a
|
||||||
href="/inventar/collections/new"
|
href="/inventory/collections/new"
|
||||||
class="rounded-lg bg-[hsl(var(--primary))] px-6 py-2.5 text-sm font-medium text-[hsl(var(--primary-foreground))]"
|
class="rounded-lg bg-[hsl(var(--primary))] px-6 py-2.5 text-sm font-medium text-[hsl(var(--primary-foreground))]"
|
||||||
>
|
>
|
||||||
Neue Sammlung
|
Neue Sammlung
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
import { _ } from 'svelte-i18n';
|
import { _ } from 'svelte-i18n';
|
||||||
import { Plus } from '@mana/shared-icons';
|
import { Plus } from '@mana/shared-icons';
|
||||||
import { getContext } from 'svelte';
|
import { getContext } from 'svelte';
|
||||||
import { categoriesStore } from '$lib/modules/inventar/stores/categories.svelte';
|
import { categoriesStore } from '$lib/modules/inventory/stores/categories.svelte';
|
||||||
import type { Category } from '$lib/modules/inventar/queries';
|
import type { Category } from '$lib/modules/inventory/queries';
|
||||||
|
|
||||||
const categoriesCtx: { readonly value: Category[] } = getContext('categories');
|
const categoriesCtx: { readonly value: Category[] } = getContext('categories');
|
||||||
|
|
||||||
|
|
@ -3,18 +3,18 @@
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { CaretLeft, PencilSimple, Plus, Trash } from '@mana/shared-icons';
|
import { CaretLeft, PencilSimple, Plus, Trash } from '@mana/shared-icons';
|
||||||
import { getContext } from 'svelte';
|
import { getContext } from 'svelte';
|
||||||
import { itemsStore } from '$lib/modules/inventar/stores/items.svelte';
|
import { itemsStore } from '$lib/modules/inventory/stores/items.svelte';
|
||||||
import { viewStore } from '$lib/modules/inventar/stores/view.svelte';
|
import { viewStore } from '$lib/modules/inventory/stores/view.svelte';
|
||||||
import {
|
import {
|
||||||
getCollectionById,
|
getCollectionById,
|
||||||
getItemsByCollection,
|
getItemsByCollection,
|
||||||
getSortedItems,
|
getSortedItems,
|
||||||
} from '$lib/modules/inventar/queries';
|
} from '$lib/modules/inventory/queries';
|
||||||
import type { Collection, Item, ItemStatus } from '$lib/modules/inventar/queries';
|
import type { Collection, Item, ItemStatus } from '$lib/modules/inventory/queries';
|
||||||
import FieldRenderer from '$lib/modules/inventar/components/fields/FieldRenderer.svelte';
|
import FieldRenderer from '$lib/modules/inventory/components/fields/FieldRenderer.svelte';
|
||||||
import FieldEditor from '$lib/modules/inventar/components/fields/FieldEditor.svelte';
|
import FieldEditor from '$lib/modules/inventory/components/fields/FieldEditor.svelte';
|
||||||
import StatusBadge from '$lib/modules/inventar/components/StatusBadge.svelte';
|
import StatusBadge from '$lib/modules/inventory/components/StatusBadge.svelte';
|
||||||
import ViewModeToggle from '$lib/modules/inventar/components/ViewModeToggle.svelte';
|
import ViewModeToggle from '$lib/modules/inventory/components/ViewModeToggle.svelte';
|
||||||
|
|
||||||
const collectionsCtx: { readonly value: Collection[] } = getContext('collections');
|
const collectionsCtx: { readonly value: Collection[] } = getContext('collections');
|
||||||
const itemsCtx: { readonly value: Item[] } = getContext('items');
|
const itemsCtx: { readonly value: Item[] } = getContext('items');
|
||||||
|
|
@ -59,7 +59,7 @@
|
||||||
{#if !collection}
|
{#if !collection}
|
||||||
<div class="text-center py-16">
|
<div class="text-center py-16">
|
||||||
<p class="text-[hsl(var(--muted-foreground))]">Sammlung nicht gefunden</p>
|
<p class="text-[hsl(var(--muted-foreground))]">Sammlung nicht gefunden</p>
|
||||||
<a href="/inventar" class="mt-4 text-[hsl(var(--primary))]">Zuruck</a>
|
<a href="/inventory" class="mt-4 text-[hsl(var(--primary))]">Zuruck</a>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="space-y-6">
|
<div class="space-y-6">
|
||||||
|
|
@ -67,7 +67,7 @@
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<div class="flex items-center gap-3">
|
<div class="flex items-center gap-3">
|
||||||
<a
|
<a
|
||||||
href="/inventar"
|
href="/inventory"
|
||||||
class="text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))]"
|
class="text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))]"
|
||||||
>
|
>
|
||||||
<CaretLeft size={20} />
|
<CaretLeft size={20} />
|
||||||
|
|
@ -83,7 +83,7 @@
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<ViewModeToggle current={viewStore.viewMode} onchange={(m) => viewStore.setViewMode(m)} />
|
<ViewModeToggle current={viewStore.viewMode} onchange={(m) => viewStore.setViewMode(m)} />
|
||||||
<a
|
<a
|
||||||
href="/inventar/collections/{collection.id}/edit"
|
href="/inventory/collections/{collection.id}/edit"
|
||||||
class="rounded-lg border border-[hsl(var(--border))] p-2 text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))]"
|
class="rounded-lg border border-[hsl(var(--border))] p-2 text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))]"
|
||||||
>
|
>
|
||||||
<PencilSimple size={16} />
|
<PencilSimple size={16} />
|
||||||
|
|
@ -166,8 +166,8 @@
|
||||||
<div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
<div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
||||||
{#each sortedItems as item (item.id)}
|
{#each sortedItems as item (item.id)}
|
||||||
<div
|
<div
|
||||||
onclick={() => goto(`/inventar/items/${item.id}`)}
|
onclick={() => goto(`/inventory/items/${item.id}`)}
|
||||||
onkeydown={(e) => e.key === 'Enter' && goto(`/inventar/items/${item.id}`)}
|
onkeydown={(e) => e.key === 'Enter' && goto(`/inventory/items/${item.id}`)}
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
class="group cursor-pointer rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] p-4 text-left"
|
class="group cursor-pointer rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] p-4 text-left"
|
||||||
|
|
@ -221,7 +221,7 @@
|
||||||
{#each sortedItems as item (item.id)}
|
{#each sortedItems as item (item.id)}
|
||||||
<tr
|
<tr
|
||||||
class="cursor-pointer border-b border-[hsl(var(--border))] transition-colors hover:bg-[hsl(var(--accent)/0.05)]"
|
class="cursor-pointer border-b border-[hsl(var(--border))] transition-colors hover:bg-[hsl(var(--accent)/0.05)]"
|
||||||
onclick={() => goto(`/inventar/items/${item.id}`)}
|
onclick={() => goto(`/inventory/items/${item.id}`)}
|
||||||
>
|
>
|
||||||
<td class="px-4 py-2.5 font-medium text-[hsl(var(--foreground))]">{item.name}</td>
|
<td class="px-4 py-2.5 font-medium text-[hsl(var(--foreground))]">{item.name}</td>
|
||||||
<td class="px-4 py-2.5"><StatusBadge status={item.status} /></td>
|
<td class="px-4 py-2.5"><StatusBadge status={item.status} /></td>
|
||||||
|
|
@ -248,8 +248,8 @@
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
{#each sortedItems as item (item.id)}
|
{#each sortedItems as item (item.id)}
|
||||||
<div
|
<div
|
||||||
onclick={() => goto(`/inventar/items/${item.id}`)}
|
onclick={() => goto(`/inventory/items/${item.id}`)}
|
||||||
onkeydown={(e) => e.key === 'Enter' && goto(`/inventar/items/${item.id}`)}
|
onkeydown={(e) => e.key === 'Enter' && goto(`/inventory/items/${item.id}`)}
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
class="group flex w-full cursor-pointer items-center gap-4 rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-4 py-3 text-left transition-colors hover:border-[hsl(var(--primary)/0.3)]"
|
class="group flex w-full cursor-pointer items-center gap-4 rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-4 py-3 text-left transition-colors hover:border-[hsl(var(--primary)/0.3)]"
|
||||||
|
|
@ -3,11 +3,11 @@
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { CaretLeft } from '@mana/shared-icons';
|
import { CaretLeft } from '@mana/shared-icons';
|
||||||
import { getContext } from 'svelte';
|
import { getContext } from 'svelte';
|
||||||
import { collectionsStore } from '$lib/modules/inventar/stores/collections.svelte';
|
import { collectionsStore } from '$lib/modules/inventory/stores/collections.svelte';
|
||||||
import { getCollectionById } from '$lib/modules/inventar/queries';
|
import { getCollectionById } from '$lib/modules/inventory/queries';
|
||||||
import type { Collection } from '$lib/modules/inventar/queries';
|
import type { Collection } from '$lib/modules/inventory/queries';
|
||||||
import type { CollectionSchema } from '$lib/modules/inventar/constants';
|
import type { CollectionSchema } from '$lib/modules/inventory/constants';
|
||||||
import SchemaEditor from '$lib/modules/inventar/components/fields/SchemaEditor.svelte';
|
import SchemaEditor from '$lib/modules/inventory/components/fields/SchemaEditor.svelte';
|
||||||
|
|
||||||
const collectionsCtx: { readonly value: Collection[] } = getContext('collections');
|
const collectionsCtx: { readonly value: Collection[] } = getContext('collections');
|
||||||
|
|
||||||
|
|
@ -38,7 +38,7 @@
|
||||||
icon: icon || undefined,
|
icon: icon || undefined,
|
||||||
schema,
|
schema,
|
||||||
});
|
});
|
||||||
goto(`/inventar/collections/${collection.id}`);
|
goto(`/inventory/collections/${collection.id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const inputClass =
|
const inputClass =
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
<div class="mx-auto max-w-2xl space-y-6">
|
<div class="mx-auto max-w-2xl space-y-6">
|
||||||
<div class="flex items-center gap-3">
|
<div class="flex items-center gap-3">
|
||||||
<button
|
<button
|
||||||
onclick={() => goto(`/inventar/collections/${collection.id}`)}
|
onclick={() => goto(`/inventory/collections/${collection.id}`)}
|
||||||
class="text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))]"
|
class="text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))]"
|
||||||
>
|
>
|
||||||
<CaretLeft size={20} />
|
<CaretLeft size={20} />
|
||||||
|
|
@ -94,7 +94,7 @@
|
||||||
|
|
||||||
<div class="flex justify-end gap-3 pt-4">
|
<div class="flex justify-end gap-3 pt-4">
|
||||||
<button
|
<button
|
||||||
onclick={() => goto(`/inventar/collections/${collection.id}`)}
|
onclick={() => goto(`/inventory/collections/${collection.id}`)}
|
||||||
class="rounded-lg border border-[hsl(var(--border))] px-4 py-2 text-sm text-[hsl(var(--foreground))]"
|
class="rounded-lg border border-[hsl(var(--border))] px-4 py-2 text-sm text-[hsl(var(--foreground))]"
|
||||||
>
|
>
|
||||||
Abbrechen
|
Abbrechen
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { CaretLeft } from '@mana/shared-icons';
|
import { CaretLeft } from '@mana/shared-icons';
|
||||||
import { collectionsStore } from '$lib/modules/inventar/stores/collections.svelte';
|
import { collectionsStore } from '$lib/modules/inventory/stores/collections.svelte';
|
||||||
import {
|
import {
|
||||||
DEFAULT_TEMPLATES,
|
DEFAULT_TEMPLATES,
|
||||||
type Template,
|
type Template,
|
||||||
type CollectionSchema,
|
type CollectionSchema,
|
||||||
} from '$lib/modules/inventar/constants';
|
} from '$lib/modules/inventory/constants';
|
||||||
import SchemaEditor from '$lib/modules/inventar/components/fields/SchemaEditor.svelte';
|
import SchemaEditor from '$lib/modules/inventory/components/fields/SchemaEditor.svelte';
|
||||||
|
|
||||||
let step = $state<'template' | 'details'>('template');
|
let step = $state<'template' | 'details'>('template');
|
||||||
let selectedTemplate = $state<Template | null>(null);
|
let selectedTemplate = $state<Template | null>(null);
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
schema,
|
schema,
|
||||||
templateId: selectedTemplate?.id,
|
templateId: selectedTemplate?.id,
|
||||||
});
|
});
|
||||||
goto('/inventar');
|
goto('/inventory');
|
||||||
}
|
}
|
||||||
|
|
||||||
const inputClass =
|
const inputClass =
|
||||||
|
|
@ -50,7 +50,7 @@
|
||||||
<div class="flex items-center gap-3">
|
<div class="flex items-center gap-3">
|
||||||
<button
|
<button
|
||||||
onclick={() =>
|
onclick={() =>
|
||||||
step === 'details' && selectedTemplate ? (step = 'template') : goto('/inventar')}
|
step === 'details' && selectedTemplate ? (step = 'template') : goto('/inventory')}
|
||||||
class="text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))]"
|
class="text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))]"
|
||||||
>
|
>
|
||||||
<CaretLeft size={20} />
|
<CaretLeft size={20} />
|
||||||
|
|
@ -127,7 +127,7 @@
|
||||||
<!-- Actions -->
|
<!-- Actions -->
|
||||||
<div class="flex justify-end gap-3 pt-4">
|
<div class="flex justify-end gap-3 pt-4">
|
||||||
<button
|
<button
|
||||||
onclick={() => goto('/inventar')}
|
onclick={() => goto('/inventory')}
|
||||||
class="rounded-lg border border-[hsl(var(--border))] px-4 py-2 text-sm text-[hsl(var(--foreground))]"
|
class="rounded-lg border border-[hsl(var(--border))] px-4 py-2 text-sm text-[hsl(var(--foreground))]"
|
||||||
>
|
>
|
||||||
Abbrechen
|
Abbrechen
|
||||||
|
|
@ -4,24 +4,24 @@
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { CaretLeft } from '@mana/shared-icons';
|
import { CaretLeft } from '@mana/shared-icons';
|
||||||
import { getContext } from 'svelte';
|
import { getContext } from 'svelte';
|
||||||
import { itemsStore } from '$lib/modules/inventar/stores/items.svelte';
|
import { itemsStore } from '$lib/modules/inventory/stores/items.svelte';
|
||||||
import {
|
import {
|
||||||
getItemById,
|
getItemById,
|
||||||
getCollectionById,
|
getCollectionById,
|
||||||
getLocationById,
|
getLocationById,
|
||||||
getLocationFullPath,
|
getLocationFullPath,
|
||||||
getCategoryById,
|
getCategoryById,
|
||||||
} from '$lib/modules/inventar/queries';
|
} from '$lib/modules/inventory/queries';
|
||||||
import type {
|
import type {
|
||||||
Collection,
|
Collection,
|
||||||
Item,
|
Item,
|
||||||
Location,
|
Location,
|
||||||
Category,
|
Category,
|
||||||
ItemStatus,
|
ItemStatus,
|
||||||
} from '$lib/modules/inventar/queries';
|
} from '$lib/modules/inventory/queries';
|
||||||
import FieldRenderer from '$lib/modules/inventar/components/fields/FieldRenderer.svelte';
|
import FieldRenderer from '$lib/modules/inventory/components/fields/FieldRenderer.svelte';
|
||||||
import FieldEditor from '$lib/modules/inventar/components/fields/FieldEditor.svelte';
|
import FieldEditor from '$lib/modules/inventory/components/fields/FieldEditor.svelte';
|
||||||
import StatusBadge from '$lib/modules/inventar/components/StatusBadge.svelte';
|
import StatusBadge from '$lib/modules/inventory/components/StatusBadge.svelte';
|
||||||
|
|
||||||
const collectionsCtx: { readonly value: Collection[] } = getContext('collections');
|
const collectionsCtx: { readonly value: Collection[] } = getContext('collections');
|
||||||
const itemsCtx: { readonly value: Item[] } = getContext('items');
|
const itemsCtx: { readonly value: Item[] } = getContext('items');
|
||||||
|
|
@ -90,7 +90,7 @@
|
||||||
async function deleteItem() {
|
async function deleteItem() {
|
||||||
if (!item || !confirm('Item endgultig loschen?')) return;
|
if (!item || !confirm('Item endgultig loschen?')) return;
|
||||||
await itemsStore.delete(item.id);
|
await itemsStore.delete(item.id);
|
||||||
goto(collection ? `/inventar/collections/${collection.id}` : '/inventar');
|
goto(collection ? `/inventory/collections/${collection.id}` : '/inventory');
|
||||||
}
|
}
|
||||||
|
|
||||||
const inputClass =
|
const inputClass =
|
||||||
|
|
@ -104,7 +104,7 @@
|
||||||
{#if !item}
|
{#if !item}
|
||||||
<div class="text-center py-16">
|
<div class="text-center py-16">
|
||||||
<p class="text-[hsl(var(--muted-foreground))]">Item nicht gefunden</p>
|
<p class="text-[hsl(var(--muted-foreground))]">Item nicht gefunden</p>
|
||||||
<a href="/inventar" class="mt-4 text-[hsl(var(--primary))]">Zuruck</a>
|
<a href="/inventory" class="mt-4 text-[hsl(var(--primary))]">Zuruck</a>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="mx-auto max-w-2xl space-y-6">
|
<div class="mx-auto max-w-2xl space-y-6">
|
||||||
|
|
@ -112,7 +112,8 @@
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<div class="flex items-center gap-3">
|
<div class="flex items-center gap-3">
|
||||||
<button
|
<button
|
||||||
onclick={() => goto(collection ? `/inventar/collections/${collection.id}` : '/inventar')}
|
onclick={() =>
|
||||||
|
goto(collection ? `/inventory/collections/${collection.id}` : '/inventory')}
|
||||||
class="text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))]"
|
class="text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))]"
|
||||||
>
|
>
|
||||||
<CaretLeft size={20} />
|
<CaretLeft size={20} />
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { getContext } from 'svelte';
|
import { getContext } from 'svelte';
|
||||||
import { locationsStore } from '$lib/modules/inventar/stores/locations.svelte';
|
import { locationsStore } from '$lib/modules/inventory/stores/locations.svelte';
|
||||||
import { getLocationTree } from '$lib/modules/inventar/queries';
|
import { getLocationTree } from '$lib/modules/inventory/queries';
|
||||||
import type { Location } from '$lib/modules/inventar/queries';
|
import type { Location } from '$lib/modules/inventory/queries';
|
||||||
import { Plus } from '@mana/shared-icons';
|
import { Plus } from '@mana/shared-icons';
|
||||||
|
|
||||||
const locationsCtx: { readonly value: Location[] } = getContext('locations');
|
const locationsCtx: { readonly value: Location[] } = getContext('locations');
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { getContext } from 'svelte';
|
import { getContext } from 'svelte';
|
||||||
import { getFilteredItems, getCollectionById } from '$lib/modules/inventar/queries';
|
import { getFilteredItems, getCollectionById } from '$lib/modules/inventory/queries';
|
||||||
import type { Collection, Item } from '$lib/modules/inventar/queries';
|
import type { Collection, Item } from '$lib/modules/inventory/queries';
|
||||||
import StatusBadge from '$lib/modules/inventar/components/StatusBadge.svelte';
|
import StatusBadge from '$lib/modules/inventory/components/StatusBadge.svelte';
|
||||||
import { MagnifyingGlass } from '@mana/shared-icons';
|
import { MagnifyingGlass } from '@mana/shared-icons';
|
||||||
|
|
||||||
const collectionsCtx: { readonly value: Collection[] } = getContext('collections');
|
const collectionsCtx: { readonly value: Collection[] } = getContext('collections');
|
||||||
|
|
@ -41,7 +41,7 @@
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
{#each results as item (item.id)}
|
{#each results as item (item.id)}
|
||||||
<button
|
<button
|
||||||
onclick={() => goto(`/inventar/items/${item.id}`)}
|
onclick={() => goto(`/inventory/items/${item.id}`)}
|
||||||
class="flex w-full items-center gap-4 rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-4 py-3 text-left transition-colors hover:border-[hsl(var(--primary)/0.3)]"
|
class="flex w-full items-center gap-4 rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-4 py-3 text-left transition-colors hover:border-[hsl(var(--primary)/0.3)]"
|
||||||
>
|
>
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
|
|
@ -810,7 +810,7 @@ services:
|
||||||
# REMOVED standalone web containers — now served by unified mana-web container (mana.how):
|
# REMOVED standalone web containers — now served by unified mana-web container (mana.how):
|
||||||
# chat-web, todo-web, zitare-web, calendar-web, clock-web, contacts-web,
|
# chat-web, todo-web, zitare-web, calendar-web, clock-web, contacts-web,
|
||||||
# storage-web, presi-web, cards-web, nutriphi-web, skilltree-web, photos-web,
|
# storage-web, presi-web, cards-web, nutriphi-web, skilltree-web, photos-web,
|
||||||
# music-web, citycorners-web, picture-web, inventar-web, calc-web, times-web,
|
# music-web, citycorners-web, picture-web, inventory-web, calc-web, times-web,
|
||||||
# uload-web, memoro-web
|
# uload-web, memoro-web
|
||||||
|
|
||||||
# picture-backend: REMOVED — replaced by Hono server (apps/picture/apps/server)
|
# picture-backend: REMOVED — replaced by Hono server (apps/picture/apps/server)
|
||||||
|
|
|
||||||
|
|
@ -242,7 +242,7 @@ scrape_configs:
|
||||||
- https://mana.how/notes
|
- https://mana.how/notes
|
||||||
- https://mana.how/habits
|
- https://mana.how/habits
|
||||||
- https://mana.how/guides
|
- https://mana.how/guides
|
||||||
- https://mana.how/inventar
|
- https://mana.how/inventory
|
||||||
- https://mana.how/playground
|
- https://mana.how/playground
|
||||||
# Standalone games (separate containers)
|
# Standalone games (separate containers)
|
||||||
- https://whopxl.mana.how
|
- https://whopxl.mana.how
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,7 @@ Pure CRUD apps use mana-sync directly.
|
||||||
| 5022 | citycorners-web | *(local-first only)* |
|
| 5022 | citycorners-web | *(local-first only)* |
|
||||||
| 5023 | cards-web | 3036 cards-server |
|
| 5023 | cards-web | 3036 cards-server |
|
||||||
| 5024 | mukke-web | 3037 mukke-server |
|
| 5024 | mukke-web | 3037 mukke-server |
|
||||||
| 5025 | inventar-web | *(local-first only)* |
|
| 5025 | inventory-web | *(local-first only)* |
|
||||||
| 5026 | context-web | *(local-first only)* |
|
| 5026 | context-web | *(local-first only)* |
|
||||||
| 5027 | questions-web | *(local-first only)* |
|
| 5027 | questions-web | *(local-first only)* |
|
||||||
| 5028 | planta-web | 3039 planta-server |
|
| 5028 | planta-web | 3039 planta-server |
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ const apps = [
|
||||||
{ name: 'music', url: `${BASE}:5189` },
|
{ name: 'music', url: `${BASE}:5189` },
|
||||||
{ name: 'citycorners', url: `${BASE}:5190` },
|
{ name: 'citycorners', url: `${BASE}:5190` },
|
||||||
{ name: 'picture', url: `${BASE}:5174` },
|
{ name: 'picture', url: `${BASE}:5174` },
|
||||||
{ name: 'inventar', url: `${BASE}:5191` },
|
{ name: 'inventory', url: `${BASE}:5191` },
|
||||||
];
|
];
|
||||||
|
|
||||||
// When testing against production, use subdomains
|
// When testing against production, use subdomains
|
||||||
|
|
|
||||||
|
|
@ -108,8 +108,8 @@
|
||||||
"dev:photos:app": "pnpm dev:photos:web",
|
"dev:photos:app": "pnpm dev:photos:web",
|
||||||
"dev:photos:full": "concurrently -n auth,sync,web -c blue,magenta,cyan \"pnpm dev:auth\" \"pnpm dev:sync\" \"pnpm dev:photos:web\"",
|
"dev:photos:full": "concurrently -n auth,sync,web -c blue,magenta,cyan \"pnpm dev:auth\" \"pnpm dev:sync\" \"pnpm dev:photos:web\"",
|
||||||
"dev:tags-test": "concurrently -n auth,sync,api -c blue,magenta,yellow \"pnpm dev:auth\" \"pnpm dev:sync\" \"pnpm dev:api\"",
|
"dev:tags-test": "concurrently -n auth,sync,api -c blue,magenta,yellow \"pnpm dev:auth\" \"pnpm dev:sync\" \"pnpm dev:api\"",
|
||||||
"inventar:dev": "turbo run dev --filter=inventar...",
|
"inventory:dev": "turbo run dev --filter=inventory...",
|
||||||
"dev:inventar:web": "pnpm --filter @inventar/web dev",
|
"dev:inventory:web": "pnpm --filter @inventory/web dev",
|
||||||
"times:dev": "turbo run dev --filter=times...",
|
"times:dev": "turbo run dev --filter=times...",
|
||||||
"dev:times:web": "pnpm --filter @times/web dev",
|
"dev:times:web": "pnpm --filter @times/web dev",
|
||||||
"dev:times:full": "concurrently -n auth,sync,web -c blue,magenta,cyan \"pnpm dev:auth\" \"pnpm dev:sync\" \"pnpm dev:times:web\"",
|
"dev:times:full": "concurrently -n auth,sync,web -c blue,magenta,cyan \"pnpm dev:auth\" \"pnpm dev:sync\" \"pnpm dev:times:web\"",
|
||||||
|
|
@ -246,7 +246,7 @@
|
||||||
"dev:skilltree:local": "concurrently -n sync,web -c magenta,cyan \"pnpm dev:sync\" \"pnpm dev:skilltree:web\"",
|
"dev:skilltree:local": "concurrently -n sync,web -c magenta,cyan \"pnpm dev:sync\" \"pnpm dev:skilltree:web\"",
|
||||||
"dev:photos:local": "concurrently -n sync,web -c magenta,cyan \"pnpm dev:sync\" \"pnpm dev:photos:web\"",
|
"dev:photos:local": "concurrently -n sync,web -c magenta,cyan \"pnpm dev:sync\" \"pnpm dev:photos:web\"",
|
||||||
"dev:citycorners:local": "concurrently -n sync,web -c magenta,cyan \"pnpm dev:sync\" \"pnpm dev:citycorners:web\"",
|
"dev:citycorners:local": "concurrently -n sync,web -c magenta,cyan \"pnpm dev:sync\" \"pnpm dev:citycorners:web\"",
|
||||||
"dev:inventar:local": "concurrently -n sync,web -c magenta,cyan \"pnpm dev:sync\" \"pnpm dev:inventar:web\"",
|
"dev:inventory:local": "concurrently -n sync,web -c magenta,cyan \"pnpm dev:sync\" \"pnpm dev:inventory:web\"",
|
||||||
"dev:times:local": "concurrently -n sync,web -c magenta,cyan \"pnpm dev:sync\" \"pnpm dev:times:web\"",
|
"dev:times:local": "concurrently -n sync,web -c magenta,cyan \"pnpm dev:sync\" \"pnpm dev:times:web\"",
|
||||||
"dev:calc:local": "concurrently -n sync,web -c magenta,cyan \"pnpm dev:sync\" \"pnpm dev:calc:web\"",
|
"dev:calc:local": "concurrently -n sync,web -c magenta,cyan \"pnpm dev:sync\" \"pnpm dev:calc:web\"",
|
||||||
"dev:manavoxel:local": "concurrently -n sync,web -c magenta,cyan \"pnpm dev:sync\" \"pnpm dev:manavoxel:web\"",
|
"dev:manavoxel:local": "concurrently -n sync,web -c magenta,cyan \"pnpm dev:sync\" \"pnpm dev:manavoxel:web\"",
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@
|
||||||
music: ['Musik machen, einfach so', 'Quelloffen & unabhängig', 'Privat by Design'],
|
music: ['Musik machen, einfach so', 'Quelloffen & unabhängig', 'Privat by Design'],
|
||||||
storage: ['Deine Dateien, dein Tresor', 'Quelloffen & unabhängig', 'Privat by Design'],
|
storage: ['Deine Dateien, dein Tresor', 'Quelloffen & unabhängig', 'Privat by Design'],
|
||||||
times: ['Zeiterfassung ohne Overhead', 'Quelloffen & unabhängig', 'Privat by Design'],
|
times: ['Zeiterfassung ohne Overhead', 'Quelloffen & unabhängig', 'Privat by Design'],
|
||||||
inventar: ['Alles im Überblick behalten', 'Quelloffen & unabhängig', 'Privat by Design'],
|
inventory: ['Alles im Überblick behalten', 'Quelloffen & unabhängig', 'Privat by Design'],
|
||||||
uload: ['Links kürzen & verwalten', 'Quelloffen & unabhängig', 'Privat by Design'],
|
uload: ['Links kürzen & verwalten', 'Quelloffen & unabhängig', 'Privat by Design'],
|
||||||
news: ['Nachrichten, kuratiert für dich', 'Quelloffen & unabhängig', 'Privat by Design'],
|
news: ['Nachrichten, kuratiert für dich', 'Quelloffen & unabhängig', 'Privat by Design'],
|
||||||
arcade: ['Spiele direkt im Browser', 'Quelloffen & unabhängig', 'Privat by Design'],
|
arcade: ['Spiele direkt im Browser', 'Quelloffen & unabhängig', 'Privat by Design'],
|
||||||
|
|
@ -94,7 +94,7 @@
|
||||||
music: ['Make music, just like that', 'Open-source & independent', 'Private by design'],
|
music: ['Make music, just like that', 'Open-source & independent', 'Private by design'],
|
||||||
storage: ['Your files, your vault', 'Open-source & independent', 'Private by design'],
|
storage: ['Your files, your vault', 'Open-source & independent', 'Private by design'],
|
||||||
times: ['Time tracking without overhead', 'Open-source & independent', 'Private by design'],
|
times: ['Time tracking without overhead', 'Open-source & independent', 'Private by design'],
|
||||||
inventar: ['Keep track of everything', 'Open-source & independent', 'Private by design'],
|
inventory: ['Keep track of everything', 'Open-source & independent', 'Private by design'],
|
||||||
uload: ['Shorten & manage links', 'Open-source & independent', 'Private by design'],
|
uload: ['Shorten & manage links', 'Open-source & independent', 'Private by design'],
|
||||||
news: ['News, curated for you', 'Open-source & independent', 'Private by design'],
|
news: ['News, curated for you', 'Open-source & independent', 'Private by design'],
|
||||||
arcade: ['Games right in your browser', 'Open-source & independent', 'Private by design'],
|
arcade: ['Games right in your browser', 'Open-source & independent', 'Private by design'],
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* export const viewStore = createViewStore<MyViewMode, MyFilters>({
|
* export const viewStore = createViewStore<MyViewMode, MyFilters>({
|
||||||
* storagePrefix: 'inventar',
|
* storagePrefix: 'inventory',
|
||||||
* defaultViewMode: 'list',
|
* defaultViewMode: 'list',
|
||||||
* defaultSort: { field: 'name', direction: 'asc' },
|
* defaultSort: { field: 'name', direction: 'asc' },
|
||||||
* hasActiveFilters: (f) => !!(f.search || f.status?.length || f.tagIds?.length),
|
* hasActiveFilters: (f) => !!(f.search || f.status?.length || f.tagIds?.length),
|
||||||
|
|
@ -40,7 +40,7 @@ export interface SavedFilter<F> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ViewStoreConfig<V extends string, F extends object> {
|
export interface ViewStoreConfig<V extends string, F extends object> {
|
||||||
/** Prefix for localStorage keys (e.g. 'inventar' → 'inventar_view_mode') */
|
/** Prefix for localStorage keys (e.g. 'inventory' → 'inventory_view_mode') */
|
||||||
storagePrefix: string;
|
storagePrefix: string;
|
||||||
/** Default view mode */
|
/** Default view mode */
|
||||||
defaultViewMode: V;
|
defaultViewMode: V;
|
||||||
|
|
|
||||||
|
|
@ -167,7 +167,7 @@ const track = {
|
||||||
memoro: createModuleTracker('memoro'),
|
memoro: createModuleTracker('memoro'),
|
||||||
app: createModuleTracker('app'),
|
app: createModuleTracker('app'),
|
||||||
calc: createModuleTracker('calc'),
|
calc: createModuleTracker('calc'),
|
||||||
inventar: createModuleTracker('inventar'),
|
inventory: createModuleTracker('inventory'),
|
||||||
moodlit: createModuleTracker('moodlit'),
|
moodlit: createModuleTracker('moodlit'),
|
||||||
citycorners: createModuleTracker('citycorners'),
|
citycorners: createModuleTracker('citycorners'),
|
||||||
};
|
};
|
||||||
|
|
@ -570,18 +570,18 @@ export const CalcEvents = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inventar App Events
|
* Inventory App Events
|
||||||
*/
|
*/
|
||||||
export const InventarEvents = {
|
export const InventoryEvents = {
|
||||||
itemCreated: () => track.inventar('item_created'),
|
itemCreated: () => track.inventory('item_created'),
|
||||||
itemUpdated: () => track.inventar('item_updated'),
|
itemUpdated: () => track.inventory('item_updated'),
|
||||||
itemDeleted: () => track.inventar('item_deleted'),
|
itemDeleted: () => track.inventory('item_deleted'),
|
||||||
collectionCreated: () => track.inventar('collection_created'),
|
collectionCreated: () => track.inventory('collection_created'),
|
||||||
collectionDeleted: () => track.inventar('collection_deleted'),
|
collectionDeleted: () => track.inventory('collection_deleted'),
|
||||||
categoryCreated: () => track.inventar('category_created'),
|
categoryCreated: () => track.inventory('category_created'),
|
||||||
categoryDeleted: () => track.inventar('category_deleted'),
|
categoryDeleted: () => track.inventory('category_deleted'),
|
||||||
locationCreated: () => track.inventar('location_created'),
|
locationCreated: () => track.inventory('location_created'),
|
||||||
locationDeleted: () => track.inventar('location_deleted'),
|
locationDeleted: () => track.inventory('location_deleted'),
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,7 @@ export const MANA_APP_INDEX: Record<string, number> = {
|
||||||
photos: 12,
|
photos: 12,
|
||||||
skilltree: 13,
|
skilltree: 13,
|
||||||
citycorners: 14,
|
citycorners: 14,
|
||||||
inventar: 15,
|
inventory: 15,
|
||||||
times: 16,
|
times: 16,
|
||||||
nutriphi: 17,
|
nutriphi: 17,
|
||||||
planta: 18,
|
planta: 18,
|
||||||
|
|
|
||||||
|
|
@ -199,7 +199,6 @@ get_tier_badge() {
|
||||||
case "$appid" in
|
case "$appid" in
|
||||||
mana.how) appid="mana" ;;
|
mana.how) appid="mana" ;;
|
||||||
manadeck) appid="cards" ;;
|
manadeck) appid="cards" ;;
|
||||||
inventar) appid="inventory" ;;
|
|
||||||
esac
|
esac
|
||||||
|
|
||||||
echo "$TIER_APPS" | while IFS='|' read -r id name tier st; do
|
echo "$TIER_APPS" | while IFS='|' read -r id name tier st; do
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ const PROJECT_META: Record<string, { name: string; icon: string }> = {
|
||||||
picture: { name: 'ManaPicture', icon: '🎨' },
|
picture: { name: 'ManaPicture', icon: '🎨' },
|
||||||
zitare: { name: 'Zitare', icon: '✨' },
|
zitare: { name: 'Zitare', icon: '✨' },
|
||||||
presi: { name: 'Presi', icon: '📊' },
|
presi: { name: 'Presi', icon: '📊' },
|
||||||
inventar: { name: 'Inventar', icon: '📦' },
|
inventory: { name: 'Inventar', icon: '📦' },
|
||||||
nutriphi: { name: 'Nutriphi', icon: '🥗' },
|
nutriphi: { name: 'Nutriphi', icon: '🥗' },
|
||||||
planta: { name: 'Planta', icon: '🌱' },
|
planta: { name: 'Planta', icon: '🌱' },
|
||||||
storage: { name: 'Storage', icon: '☁️' },
|
storage: { name: 'Storage', icon: '☁️' },
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue