@questwork/q-inventory 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/.storybook/main.js +23 -0
  2. package/.storybook/preview.js +17 -0
  3. package/README.md +16 -0
  4. package/app/qInventory/App.vue +164 -0
  5. package/app/qInventory/index.html +12 -0
  6. package/app/qInventory/main.ts +4 -0
  7. package/app/qInventory/styles.scss +59 -0
  8. package/dist/components/InventoryAssetDetail.vue.d.ts +8 -0
  9. package/dist/components/InventoryAssetDetail.vue.d.ts.map +1 -0
  10. package/dist/components/InventoryLocationAdmin.vue.d.ts +10 -0
  11. package/dist/components/InventoryLocationAdmin.vue.d.ts.map +1 -0
  12. package/dist/components/InventoryLocationDetail.vue.d.ts +8 -0
  13. package/dist/components/InventoryLocationDetail.vue.d.ts.map +1 -0
  14. package/dist/components/InventoryOverview.vue.d.ts +15 -0
  15. package/dist/components/InventoryOverview.vue.d.ts.map +1 -0
  16. package/dist/components/InventoryScanner.vue.d.ts +21 -0
  17. package/dist/components/InventoryScanner.vue.d.ts.map +1 -0
  18. package/dist/components/QInventory.vue.d.ts +24 -0
  19. package/dist/components/QInventory.vue.d.ts.map +1 -0
  20. package/dist/index.d.ts +16 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/mixins/CSSMixin.d.ts +7 -0
  23. package/dist/mixins/CSSMixin.d.ts.map +1 -0
  24. package/dist/models/index.d.ts +62 -0
  25. package/dist/models/index.d.ts.map +1 -0
  26. package/dist/models/inventoryAssetRepoAxios.d.ts +18 -0
  27. package/dist/models/inventoryAssetRepoAxios.d.ts.map +1 -0
  28. package/dist/models/inventoryAuthRepoAxios.d.ts +26 -0
  29. package/dist/models/inventoryAuthRepoAxios.d.ts.map +1 -0
  30. package/dist/models/inventoryAxiosBase.d.ts +41 -0
  31. package/dist/models/inventoryAxiosBase.d.ts.map +1 -0
  32. package/dist/models/inventoryLocationRepoAxios.d.ts +13 -0
  33. package/dist/models/inventoryLocationRepoAxios.d.ts.map +1 -0
  34. package/dist/models/inventoryMovementRepoAxios.d.ts +13 -0
  35. package/dist/models/inventoryMovementRepoAxios.d.ts.map +1 -0
  36. package/dist/q-inventory.esm.js +961 -0
  37. package/dist/q-inventory.esm.js.map +1 -0
  38. package/dist/q-inventory.min.cjs +2 -0
  39. package/dist/q-inventory.min.cjs.map +1 -0
  40. package/dist/q-inventory.min.css +1 -0
  41. package/dist/q-inventory.min.js +2 -0
  42. package/dist/q-inventory.min.js.map +1 -0
  43. package/dist-app/qInventory/assets/q-inventory-app.css +1 -0
  44. package/dist-app/qInventory/assets/q-inventory-app.js +18 -0
  45. package/dist-app/qInventory/index.html +13 -0
  46. package/package.json +58 -0
  47. package/src/components/InventoryAssetDetail.vue +55 -0
  48. package/src/components/InventoryLocationAdmin.vue +56 -0
  49. package/src/components/InventoryLocationDetail.vue +51 -0
  50. package/src/components/InventoryOverview.vue +81 -0
  51. package/src/components/InventoryScanner.vue +315 -0
  52. package/src/components/QInventory.vue +117 -0
  53. package/src/index.ts +36 -0
  54. package/src/mixins/CSSMixin.ts +14 -0
  55. package/src/models/index.ts +114 -0
  56. package/src/models/inventoryAssetRepoAxios.ts +38 -0
  57. package/src/models/inventoryAuthRepoAxios.ts +48 -0
  58. package/src/models/inventoryAxiosBase.ts +149 -0
  59. package/src/models/inventoryLocationRepoAxios.ts +25 -0
  60. package/src/models/inventoryMovementRepoAxios.ts +24 -0
  61. package/src/styles/index.scss +148 -0
  62. package/stories/stories.scss +9 -0
  63. package/stories/stories.ts +362 -0
  64. package/tsconfig.json +29 -0
  65. package/vite.app.config.js +37 -0
  66. package/vite.config.js +68 -0
  67. package/vitest.config.js +11 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"q-inventory.esm.js","sources":["../src/components/InventoryScanner.vue","../src/components/InventoryOverview.vue","../src/components/InventoryAssetDetail.vue","../src/components/InventoryLocationDetail.vue","../src/components/InventoryLocationAdmin.vue","../src/components/QInventory.vue","../src/models/inventoryAxiosBase.ts","../src/models/inventoryAssetRepoAxios.ts","../src/models/inventoryLocationRepoAxios.ts","../src/models/inventoryMovementRepoAxios.ts","../src/models/inventoryAuthRepoAxios.ts","../src/models/index.ts","../src/index.ts"],"sourcesContent":["<template>\n <div class=\"inventory-scanner\">\n <div class=\"inventory-scanner__mode\">\n <button\n class=\"inventory-scanner__mode-button\"\n :class=\"{ 'inventory-scanner__mode-button--active': mode === INVENTORY_MOVEMENT_TYPE.PICKUP }\"\n type=\"button\"\n @click=\"setMode(INVENTORY_MOVEMENT_TYPE.PICKUP)\"\n >\n Pickup\n </button>\n <button\n class=\"inventory-scanner__mode-button\"\n :class=\"{ 'inventory-scanner__mode-button--active': mode === INVENTORY_MOVEMENT_TYPE.DROPOFF }\"\n type=\"button\"\n @click=\"setMode(INVENTORY_MOVEMENT_TYPE.DROPOFF)\"\n >\n Drop-off\n </button>\n </div>\n <div class=\"inventory-scanner__state\">\n <div>Mode: {{ mode }}</div>\n <div>{{ locationLabel }}: {{ activeLocationCode || '-' }}</div>\n <div>Holder: {{ holderLocationCode || '-' }}</div>\n </div>\n <div class=\"inventory-scanner__manual\">\n <input\n v-model=\"manualQr\"\n class=\"inventory-scanner__input\"\n placeholder=\"Scan or enter QR text\"\n @keyup.enter=\"submitManualQr\"\n />\n <button type=\"button\" @click=\"submitManualQr\">Submit</button>\n </div>\n <div class=\"inventory-scanner__basket-header\">\n <div>\n <strong>My Basket</strong>\n <span>{{ basketItems.length }} on hand</span>\n </div>\n <button\n type=\"button\"\n :disabled=\"scanLog.length === 0\"\n @click=\"clearScanLog\"\n >\n Clear log\n </button>\n </div>\n <div class=\"inventory-scanner__basket\">\n <div\n v-if=\"basketItems.length === 0\"\n class=\"inventory-scanner__empty\"\n >\n No items on hand\n </div>\n <div\n v-for=\"item in basketItems\"\n :key=\"item.assetTag\"\n class=\"inventory-scanner__basket-item\"\n >\n <strong>{{ item.assetTag }}</strong>\n <small>{{ item.name || item.category || item.currentLocationCode }}</small>\n </div>\n </div>\n <div class=\"inventory-scanner__log\">\n <div\n v-for=\"item in scanLog\"\n :key=\"item.key\"\n class=\"inventory-scanner__log-item\"\n :class=\"{\n 'inventory-scanner__log-item--failed': item.status === 'FAILED',\n 'inventory-scanner__log-item--warning': item.status === 'WARNING',\n }\"\n >\n <div>\n <strong>{{ item.title }}</strong>\n <span>{{ item.status }}</span>\n </div>\n <small>{{ item.message }}</small>\n </div>\n </div>\n <div\n v-if=\"scanLog.length === 0\"\n class=\"inventory-scanner__log-empty\"\n >\n Scan log will appear here\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport {\n INVENTORY_LOCATION_KIND,\n INVENTORY_MOVEMENT_TYPE,\n getVirtualUserLocationCode,\n isLocationQr,\n parseInventoryQr,\n} from '@questwork/q-inventory-model'\nimport type { InventoryAssetApiClient, InventoryMovePayload, InventoryMoveResult, InventoryMoveWarning } from '../models/index.js'\n\ndefineOptions({\n name: 'inventory-scanner',\n})\n\ntype ScannerMode = typeof INVENTORY_MOVEMENT_TYPE.PICKUP | typeof INVENTORY_MOVEMENT_TYPE.DROPOFF\ntype ScanLogStatus = 'OK' | 'WARNING' | 'FAILED' | 'INFO'\n\ninterface BasketItem {\n assetTag: string\n category?: string\n currentLocationCode?: string\n name?: string\n}\n\ninterface ScanLogItem {\n key: string\n message: string\n status: ScanLogStatus\n title: string\n}\n\nconst props = defineProps<{\n assetApiClient?: InventoryAssetApiClient\n assets?: unknown[]\n currentUserCode?: string\n}>()\n\nconst emit = defineEmits<{\n moved: [payload: InventoryMovePayload]\n scan: [payload: { raw: string, parsed: unknown }]\n}>()\n\nconst activeLocationCode = ref('')\nconst basketItems = ref<BasketItem[]>([])\nconst manualQr = ref('')\nconst mode = ref<ScannerMode>(INVENTORY_MOVEMENT_TYPE.PICKUP)\nconst scanLog = ref<ScanLogItem[]>([])\n\nconst holderLocationCode = computed(() => getVirtualUserLocationCode(props.currentUserCode || 'currentUser'))\nconst locationLabel = computed(() => mode.value === INVENTORY_MOVEMENT_TYPE.PICKUP ? 'Source' : 'Destination')\n\nwatch(\n () => [props.assets, holderLocationCode.value],\n syncBasketFromAssets,\n { deep: true, immediate: true },\n)\n\nfunction setMode(nextMode: ScannerMode) {\n mode.value = nextMode\n activeLocationCode.value = ''\n addLog({\n message: `Mode changed to ${nextMode}`,\n status: 'INFO',\n title: 'Mode',\n })\n}\n\nasync function submitManualQr() {\n const value = manualQr.value.trim()\n if (!value) return\n manualQr.value = ''\n await handleQr(value)\n}\n\nasync function handleQr(value: string) {\n const parsed = parseInventoryQr(value)\n emit('scan', { raw: value, parsed })\n\n if (isLocationQr(value)) {\n activeLocationCode.value = parsed.code\n addLog({\n message: `${locationLabel.value} set to ${parsed.code}`,\n status: 'INFO',\n title: 'Location',\n })\n return\n }\n\n if (!activeLocationCode.value) {\n addLog({\n message: `Scan ${locationLabel.value.toLowerCase()} location first`,\n status: 'FAILED',\n title: parsed.code,\n })\n return\n }\n\n const payload = getMovePayload(parsed.code)\n try {\n if (props.assetApiClient?.move) {\n const result = await props.assetApiClient.move(payload)\n const warnings = getMoveWarnings(result)\n emit('moved', payload)\n applyBasketMove(payload)\n if (warnings.length) {\n addLog({\n message: formatWarnings(warnings),\n status: 'WARNING',\n title: parsed.code,\n })\n return\n }\n } else {\n emit('moved', payload)\n applyBasketMove(payload)\n }\n addLog({\n message: `${payload.fromLocationCode || '-'} -> ${payload.toLocationCode}`,\n status: 'OK',\n title: parsed.code,\n })\n } catch (err) {\n addLog({\n message: getErrorMessage(err),\n status: 'FAILED',\n title: parsed.code,\n })\n }\n}\n\nfunction getMovePayload(assetTag: string): InventoryMovePayload {\n if (mode.value === INVENTORY_MOVEMENT_TYPE.PICKUP) {\n return {\n assetTag,\n fromLocationCode: activeLocationCode.value,\n fromLocationKind: INVENTORY_LOCATION_KIND.REGISTERED,\n movementType: INVENTORY_MOVEMENT_TYPE.PICKUP,\n toLocationCode: holderLocationCode.value,\n toLocationKind: INVENTORY_LOCATION_KIND.VIRTUAL,\n }\n }\n return {\n assetTag,\n fromLocationCode: holderLocationCode.value,\n fromLocationKind: INVENTORY_LOCATION_KIND.VIRTUAL,\n movementType: INVENTORY_MOVEMENT_TYPE.DROPOFF,\n toLocationCode: activeLocationCode.value,\n toLocationKind: INVENTORY_LOCATION_KIND.REGISTERED,\n }\n}\n\nfunction applyBasketMove(payload: InventoryMovePayload) {\n if (payload.toLocationCode === holderLocationCode.value) {\n upsertBasketItem({\n assetTag: payload.assetTag,\n currentLocationCode: holderLocationCode.value,\n })\n return\n }\n basketItems.value = basketItems.value.filter((item) => item.assetTag !== payload.assetTag)\n}\n\nfunction upsertBasketItem(item: BasketItem) {\n const index = basketItems.value.findIndex((basketItem) => basketItem.assetTag === item.assetTag)\n if (index >= 0) {\n basketItems.value[index] = {\n ...basketItems.value[index],\n ...item,\n }\n return\n }\n basketItems.value.unshift(item)\n}\n\nfunction syncBasketFromAssets() {\n basketItems.value = (props.assets || [])\n .map(toBasketItem)\n .filter((item): item is BasketItem => !!item && item.currentLocationCode === holderLocationCode.value)\n}\n\nfunction toBasketItem(asset: unknown): BasketItem | null {\n const item = asset as Record<string, unknown>\n const assetTag = getString(item.assetTag)\n if (!assetTag) {\n return null\n }\n return {\n assetTag,\n category: getString(item.category),\n currentLocationCode: getString(item.currentLocationCode),\n name: getString(item.name),\n }\n}\n\nfunction addLog({ message, status, title }: Omit<ScanLogItem, 'key'>) {\n scanLog.value.unshift({\n key: `${Date.now()}-${Math.random()}`,\n message,\n status,\n title,\n })\n scanLog.value = scanLog.value.slice(0, 30)\n}\n\nfunction getString(value: unknown) {\n return typeof value === 'string' ? value : ''\n}\n\nfunction getErrorMessage(err: unknown) {\n return err instanceof Error ? err.message : String(err)\n}\n\nfunction getMoveWarnings(result: unknown) {\n const response = result as { data?: InventoryMoveResult[] }\n return response?.data?.[0]?.warnings || []\n}\n\nfunction formatWarnings(warnings: InventoryMoveWarning[]) {\n return warnings.map((warning) => `${warning.code}: ${warning.message}`).join('; ')\n}\n\nfunction clearScanLog() {\n scanLog.value = []\n}\n</script>\n","<template>\n <div class=\"inventory-overview\">\n <div class=\"inventory-overview__header\">\n <div>Assets</div>\n <button type=\"button\" @click=\"reload\">Reload</button>\n </div>\n <div class=\"inventory-overview__rows\">\n <button\n v-for=\"asset in displayAssets\"\n :key=\"getAssetKey(asset)\"\n class=\"inventory-overview__row\"\n type=\"button\"\n @click=\"$emit('selectAsset', asset)\"\n >\n <span>{{ getAssetText(asset, 'assetTag') }}</span>\n <span>{{ getAssetText(asset, 'name') }}</span>\n <span\n class=\"inventory-overview__location\"\n @click.stop=\"$emit('selectLocation', getAssetText(asset, 'currentLocationCode'))\"\n >\n {{ getDisplayLocation(asset) }}\n </span>\n </button>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport {\n getVirtualUserCode,\n isVirtualInventoryLocation,\n isVirtualUserLocationCode,\n} from '@questwork/q-inventory-model'\nimport type { InventoryAssetApiClient } from '../models/index.js'\n\ndefineOptions({\n name: 'inventory-overview',\n})\n\nconst props = defineProps<{\n assetApiClient?: InventoryAssetApiClient\n assets?: unknown[]\n locations?: unknown[]\n}>()\n\ndefineEmits<{\n selectAsset: [payload: unknown]\n selectLocation: [payload: unknown]\n}>()\n\nconst loadedAssets = ref<unknown[]>([])\nconst displayAssets = computed(() => loadedAssets.value.length > 0 ? loadedAssets.value : (props.assets || []))\n\nasync function reload() {\n if (props.assetApiClient?.findAll) {\n loadedAssets.value = await props.assetApiClient.findAll()\n }\n}\n\nfunction getAssetKey(asset: unknown) {\n return getAssetText(asset, 'id') || getAssetText(asset, 'assetTag') || JSON.stringify(asset)\n}\n\nfunction getAssetText(asset: unknown, key: string) {\n return String((asset as Record<string, unknown>)?.[key] || '')\n}\n\nfunction getDisplayLocation(asset: unknown) {\n const locationCode = getAssetText(asset, 'currentLocationCode')\n const locationKind = getAssetText(asset, 'currentLocationKind')\n if (!locationCode) return 'Never scanned'\n if (isVirtualInventoryLocation({ locationCode, locationKind }) || isVirtualUserLocationCode(locationCode)) {\n return `In transit - ${getVirtualUserCode(locationCode)}`\n }\n const location = (props.locations || []).find((item) => {\n return (item as Record<string, unknown>).locationCode === locationCode\n }) as Record<string, unknown> | undefined\n return String(location?.name || locationCode)\n}\n</script>\n","<template>\n <div class=\"inventory-asset-detail\">\n <div v-if=\"asset\" class=\"inventory-asset-detail__body\">\n <h3>{{ getValue('assetTag') }}</h3>\n <div>{{ getValue('name') }}</div>\n <div>{{ getValue('currentLocationCode') }}</div>\n <button type=\"button\" @click=\"loadHistory\">Load History</button>\n <div\n v-for=\"item in history\"\n :key=\"getHistoryKey(item)\"\n class=\"inventory-asset-detail__history\"\n >\n {{ getHistoryText(item) }}\n </div>\n </div>\n <div v-else class=\"inventory-asset-detail__empty\">No asset selected</div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport type { InventoryMovementApiClient } from '../models/index.js'\n\ndefineOptions({\n name: 'inventory-asset-detail',\n})\n\nconst props = defineProps<{\n movementApiClient?: InventoryMovementApiClient\n asset?: unknown\n}>()\n\nconst history = ref<unknown[]>([])\n\nasync function loadHistory() {\n const assetTag = getValue('assetTag')\n if (assetTag && props.movementApiClient?.findAll) {\n history.value = await props.movementApiClient.findAll({ assetTag })\n }\n}\n\nfunction getValue(key: string) {\n return String((props.asset as Record<string, unknown>)?.[key] || '')\n}\n\nfunction getHistoryKey(item: unknown) {\n const data = item as Record<string, unknown>\n return String(data.id || data.inventoryMovementCode || data.movedAt || JSON.stringify(item))\n}\n\nfunction getHistoryText(item: unknown) {\n const data = item as Record<string, unknown>\n return `${data.fromLocationCode || '-'} -> ${data.toLocationCode || '-'}`\n}\n</script>\n","<template>\n <div class=\"inventory-location-detail\">\n <div class=\"inventory-location-detail__header\">\n <div>{{ locationCode || 'No location selected' }}</div>\n <button type=\"button\" :disabled=\"!locationCode\" @click=\"loadAssets\">Load Assets</button>\n </div>\n <div\n v-for=\"asset in assets\"\n :key=\"getAssetKey(asset)\"\n class=\"inventory-location-detail__asset\"\n >\n {{ getAssetText(asset) }}\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport type { InventoryAssetApiClient } from '../models/index.js'\n\ndefineOptions({\n name: 'inventory-location-detail',\n})\n\nconst props = defineProps<{\n assetApiClient?: InventoryAssetApiClient\n location?: unknown\n}>()\n\nconst assets = ref<unknown[]>([])\nconst locationCode = computed(() => {\n if (typeof props.location === 'string') return props.location\n return String((props.location as Record<string, unknown>)?.locationCode || '')\n})\n\nasync function loadAssets() {\n if (locationCode.value && props.assetApiClient?.findAll) {\n assets.value = await props.assetApiClient.findAll({ currentLocationCode: locationCode.value })\n }\n}\n\nfunction getAssetKey(asset: unknown) {\n const data = asset as Record<string, unknown>\n return String(data.id || data.assetTag || JSON.stringify(asset))\n}\n\nfunction getAssetText(asset: unknown) {\n const data = asset as Record<string, unknown>\n return `${data.assetTag || ''} ${data.name || ''}`.trim()\n}\n</script>\n","<template>\n <div class=\"inventory-location-admin\">\n <form class=\"inventory-location-admin__form\" @submit.prevent=\"submit\">\n <input v-model=\"form.locationCode\" placeholder=\"Location code\" />\n <input v-model=\"form.name\" placeholder=\"Name\" />\n <input v-model=\"form.locationType\" placeholder=\"Type\" />\n <button type=\"submit\">Save</button>\n </form>\n <div\n v-for=\"location in locations\"\n :key=\"getLocationKey(location)\"\n class=\"inventory-location-admin__row\"\n >\n {{ getLocationText(location) }}\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { reactive } from 'vue'\n\ndefineOptions({\n name: 'inventory-location-admin',\n})\n\ndefineProps<{\n locations?: unknown[]\n}>()\n\nconst emit = defineEmits<{\n saveLocation: [payload: Record<string, string>]\n}>()\n\nconst form = reactive({\n locationCode: '',\n locationType: '',\n name: '',\n})\n\nfunction submit() {\n emit('saveLocation', { ...form })\n form.locationCode = ''\n form.locationType = ''\n form.name = ''\n}\n\nfunction getLocationKey(location: unknown) {\n const data = location as Record<string, unknown>\n return String(data.id || data.locationCode || JSON.stringify(location))\n}\n\nfunction getLocationText(location: unknown) {\n const data = location as Record<string, unknown>\n return `${data.locationCode || ''} ${data.name || ''}`.trim()\n}\n</script>\n","<template>\n <div class=\"q-inventory\">\n <div class=\"q-inventory__toolbar\">\n <button\n v-for=\"item in tabs\"\n :key=\"item.key\"\n class=\"q-inventory__tab\"\n :class=\"{ 'q-inventory__tab--active': activeTab === item.key }\"\n type=\"button\"\n @click=\"activeTab = item.key\"\n >\n {{ item.label }}\n </button>\n </div>\n <inventory-scanner\n v-show=\"activeTab === 'scanner'\"\n :asset-api-client=\"assetApiClient\"\n :assets=\"assets\"\n :current-user-code=\"currentUserCode\"\n @moved=\"onMoved\"\n @scan=\"onScan\"\n />\n <inventory-overview\n v-if=\"activeTab === 'overview'\"\n :asset-api-client=\"assetApiClient\"\n :assets=\"assets\"\n :locations=\"locations\"\n @select-asset=\"onSelectAsset\"\n @select-location=\"onSelectLocation\"\n />\n <inventory-asset-detail\n v-if=\"activeTab === 'asset'\"\n :movement-api-client=\"movementApiClient\"\n :asset=\"selectedAsset\"\n />\n <inventory-location-detail\n v-if=\"activeTab === 'location'\"\n :asset-api-client=\"assetApiClient\"\n :location=\"selectedLocation\"\n />\n <inventory-location-admin\n v-if=\"activeTab === 'locations'\"\n :locations=\"locations\"\n @save-location=\"onSaveLocation\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport InventoryScanner from './InventoryScanner.vue'\nimport InventoryOverview from './InventoryOverview.vue'\nimport InventoryAssetDetail from './InventoryAssetDetail.vue'\nimport InventoryLocationDetail from './InventoryLocationDetail.vue'\nimport InventoryLocationAdmin from './InventoryLocationAdmin.vue'\nimport type {\n InventoryAssetApiClient,\n InventoryLocationApiClient,\n InventoryMovementApiClient,\n} from '../models/index.js'\n\ndefineOptions({\n name: 'q-inventory',\n})\n\nconst props = defineProps<{\n assetApiClient?: InventoryAssetApiClient\n locationApiClient?: InventoryLocationApiClient\n movementApiClient?: InventoryMovementApiClient\n assets?: unknown[]\n currentUserCode?: string\n locations?: unknown[]\n}>()\n\nconst emit = defineEmits<{\n moved: [payload: unknown]\n saveLocation: [payload: unknown]\n scan: [payload: unknown]\n selectAsset: [payload: unknown]\n selectLocation: [payload: unknown]\n}>()\n\nconst activeTab = ref('scanner')\nconst selectedAsset = ref<unknown>(null)\nconst selectedLocation = ref<unknown>(null)\nconst tabs = computed(() => [\n { key: 'scanner', label: 'Scan' },\n { key: 'overview', label: 'Overview' },\n { key: 'asset', label: 'Asset' },\n { key: 'location', label: 'Location' },\n { key: 'locations', label: 'Locations' },\n])\n\nfunction onMoved(payload: unknown) {\n emit('moved', payload)\n}\n\nfunction onScan(payload: unknown) {\n emit('scan', payload)\n}\n\nfunction onSaveLocation(payload: unknown) {\n emit('saveLocation', payload)\n}\n\nfunction onSelectAsset(payload: unknown) {\n selectedAsset.value = payload\n activeTab.value = 'asset'\n emit('selectAsset', payload)\n}\n\nfunction onSelectLocation(payload: unknown) {\n selectedLocation.value = payload\n activeTab.value = 'location'\n emit('selectLocation', payload)\n}\n</script>\n","export interface InventoryAxiosLike {\n get: (url: string, config?: { headers?: Record<string, string>, params?: Record<string, unknown> }) => Promise<{ data: unknown }>\n post: (url: string, body?: Record<string, unknown>, config?: { headers?: Record<string, string> }) => Promise<{ data: unknown }>\n}\n\nexport interface InventoryRepoAxiosOptions {\n axios?: InventoryAxiosLike\n authenticatorTokenProvider?: () => Promise<string> | string\n baseURL?: string\n movedBy?: string\n qRepo?: string\n tenantCode?: string\n userTokenProvider?: () => Promise<string> | string\n}\n\nexport abstract class InventoryRepoAxiosBase {\n axios?: InventoryAxiosLike\n authenticatorTokenProvider?: () => Promise<string> | string\n baseURL: string\n movedBy: string\n qRepo?: string\n tenantCode: string\n userTokenProvider?: () => Promise<string> | string\n\n constructor(options: InventoryRepoAxiosOptions = {}) {\n this.axios = options.axios\n this.authenticatorTokenProvider = options.authenticatorTokenProvider\n this.baseURL = (options.baseURL || '').replace(/\\/$/, '')\n this.movedBy = options.movedBy || 'currentUser'\n this.qRepo = options.qRepo\n this.tenantCode = options.tenantCode || 'tenantCode'\n this.userTokenProvider = options.userTokenProvider\n }\n\n protected async get(path: string, query: Record<string, unknown> = {}) {\n const headers = await this.getAuthHeaders()\n if (this.axios) {\n const response = await this.axios.get(this.getUrl(path), { headers, params: query })\n return unwrapQSystemData(response.data)\n }\n const url = new URL(this.getUrl(path), getUrlBase())\n Object.entries(query).forEach(([key, value]) => {\n if (typeof value !== 'undefined' && value !== null && value !== '') {\n url.searchParams.set(key, String(value))\n }\n })\n const response = await fetch(this.getFetchUrl(url), { headers })\n return unwrapQSystemData(await response.json(), response)\n }\n\n protected async post(path: string, body: Record<string, unknown> = {}) {\n const headers = {\n 'Content-Type': 'application/json',\n ...await this.getAuthHeaders(),\n }\n if (this.axios) {\n const response = await this.axios.post(this.getUrl(path), body, { headers })\n return unwrapQSystemResponse(response.data)\n }\n const response = await fetch(this.getUrl(path), {\n body: JSON.stringify(body),\n headers,\n method: 'POST',\n })\n return unwrapQSystemResponse(await response.json(), response)\n }\n\n protected getUrl(path: string) {\n return `${this.baseURL}/api/v1${path}`\n }\n\n protected getFetchUrl(url: URL) {\n return this.baseURL ? url.toString() : `${url.pathname}${url.search}`\n }\n\n protected withDefaults(obj: Record<string, unknown> = {}) {\n return removeEmptyValues({\n ...obj,\n qRepo: obj.qRepo || this.qRepo,\n tenantCode: obj.tenantCode || this.tenantCode,\n })\n }\n\n private async getAuthHeaders() {\n const headers: Record<string, string> = {}\n const authenticatorToken = await resolveTokenProvider(this.authenticatorTokenProvider)\n const userToken = await resolveTokenProvider(this.userTokenProvider)\n if (authenticatorToken) {\n headers['X-Q-Authenticator'] = authenticatorToken\n }\n if (userToken) {\n headers['X-Q-Inventory-User-Token'] = userToken\n }\n return headers\n }\n}\n\nasync function resolveTokenProvider(provider?: () => Promise<string> | string) {\n if (!provider) {\n return ''\n }\n return provider()\n}\n\nfunction unwrapQSystemResponse(json: unknown, response?: Response) {\n const data = json as Record<string, unknown>\n const err = data?.err as Record<string, unknown> | undefined\n const errors = data?.errors as Record<string, unknown> | undefined\n if ((response && !response.ok) || err?.hasError || errors) {\n throw new Error(getResponseErrorMessage({ data, err, errors, response }))\n }\n return data\n}\n\nfunction unwrapQSystemData(json: unknown, response?: Response): unknown[] {\n const data = unwrapQSystemResponse(json, response)\n return Array.isArray(data?.data) ? data.data : []\n}\n\nfunction getUrlBase() {\n if (typeof window !== 'undefined') {\n return window.location.origin\n }\n return 'http://localhost'\n}\n\nfunction getResponseErrorMessage({ data, err, errors, response }: {\n data: Record<string, unknown>\n err?: Record<string, unknown>\n errors?: Record<string, unknown>\n response?: Response\n}) {\n const code = String(response?.status || err?.statusCode || err?.code || errors?.name || data?.code || 'REQUEST_ERROR')\n const message = formatErrorMessage(err?.message || errors?.message || data?.message || 'QInventory request failed')\n return `${code}: ${message}`\n}\n\nfunction formatErrorMessage(value: unknown) {\n if (Array.isArray(value)) {\n return value.join('; ')\n }\n return String(value)\n}\n\nfunction removeEmptyValues(obj: Record<string, unknown>) {\n return Object.fromEntries(\n Object.entries(obj).filter(([, value]) => typeof value !== 'undefined' && value !== null && value !== ''),\n )\n}\n","import { InventoryRepoAxiosBase, type InventoryRepoAxiosOptions } from './inventoryAxiosBase.js'\nimport type { InventoryMovePayload } from './index.js'\n\nexport interface InventoryAssetFindAllQuery extends Record<string, unknown> {\n assetTag?: string\n assetTags?: string[]\n category?: string\n currentLocationCode?: string\n currentLocationKind?: string\n currentLocationType?: string\n}\n\nexport class InventoryAssetRepoAxios extends InventoryRepoAxiosBase {\n constructor(options: InventoryRepoAxiosOptions = {}) {\n super(options)\n }\n\n async findAll(query: InventoryAssetFindAllQuery = {}) {\n return this.get('/qInventoryAsset', this.withDefaults(query))\n }\n\n async findOne(assetTag: string) {\n return this.get(`/qInventoryAsset/${encodeURIComponent(assetTag)}`, this.withDefaults())\n }\n\n async saveOne(doc: Record<string, unknown>) {\n return this.post('/qInventoryAsset', this.withDefaults(doc))\n }\n\n async move(payload: InventoryMovePayload) {\n const assetTag = String(payload.assetTag || '')\n const movedBy = payload.movedBy || this.movedBy\n return this.post(`/qInventoryAsset/${encodeURIComponent(assetTag)}/move`, this.withDefaults({\n ...payload,\n movedBy,\n }))\n }\n}\n","import { InventoryRepoAxiosBase, type InventoryRepoAxiosOptions } from './inventoryAxiosBase.js'\n\nexport interface InventoryLocationFindAllQuery extends Record<string, unknown> {\n locationCode?: string\n locationType?: string\n parentLocationCode?: string\n}\n\nexport class InventoryLocationRepoAxios extends InventoryRepoAxiosBase {\n constructor(options: InventoryRepoAxiosOptions = {}) {\n super(options)\n }\n\n async findAll(query: InventoryLocationFindAllQuery = {}) {\n return this.get('/qInventoryLocation', this.withDefaults(query))\n }\n\n async findOne(locationCode: string) {\n return this.get(`/qInventoryLocation/${encodeURIComponent(locationCode)}`, this.withDefaults())\n }\n\n async saveOne(doc: Record<string, unknown>) {\n return this.post('/qInventoryLocation', this.withDefaults(doc))\n }\n}\n","import { InventoryRepoAxiosBase, type InventoryRepoAxiosOptions } from './inventoryAxiosBase.js'\n\nexport interface InventoryMovementFindAllQuery extends Record<string, unknown> {\n assetTag?: string\n fromLocationCode?: string\n toLocationCode?: string\n movedBy?: string\n movementType?: string\n}\n\nexport class InventoryMovementRepoAxios extends InventoryRepoAxiosBase {\n constructor(options: InventoryRepoAxiosOptions = {}) {\n super(options)\n }\n\n async findAll(query: InventoryMovementFindAllQuery = {}) {\n const assetTag = String(query.assetTag || '')\n if (!assetTag) {\n throw new Error('assetTag is required for movement findAll')\n }\n const { assetTag: _omit, ...rest } = query\n return this.get(`/qInventoryAsset/${encodeURIComponent(assetTag)}/movements`, this.withDefaults(rest))\n }\n}\n","import { InventoryRepoAxiosBase, type InventoryRepoAxiosOptions } from './inventoryAxiosBase.js'\n\nexport interface InventoryTokenResult {\n token: string\n tokenExpiry: number\n}\n\nexport interface InventoryLoginLinkResult {\n email: string\n loginUrl: string\n sent: boolean\n}\n\nexport interface InventoryUserTokenResult {\n email: string\n tenantCode: string\n userCode: string\n userToken: string\n}\n\nexport class InventoryAuthRepoAxios extends InventoryRepoAxiosBase {\n constructor(options: InventoryRepoAxiosOptions = {}) {\n super(options)\n }\n\n async getBrowserToken() {\n const result = await this.post('/qInventory/token', {\n clientAppId: 'qInventoryBrowser',\n clientAppName: 'qInventoryBrowser',\n }) as { data?: InventoryTokenResult[] }\n return result.data?.[0]\n }\n\n async requestLoginLink({ email, tenantCode = this.tenantCode }: { email: string, tenantCode?: string }) {\n const result = await this.post('/qInventory/login-link', {\n email,\n tenantCode,\n }) as { data?: InventoryLoginLinkResult[] }\n return result.data?.[0]\n }\n\n async verifyLoginToken(loginToken: string) {\n const result = await this.post('/qInventory/login-token/verify', {\n loginToken,\n }) as { data?: InventoryUserTokenResult[] }\n return result.data?.[0]\n }\n}\n","import { InventoryAssetRepoAxios } from './inventoryAssetRepoAxios.js'\nimport { InventoryLocationRepoAxios } from './inventoryLocationRepoAxios.js'\nimport { InventoryMovementRepoAxios } from './inventoryMovementRepoAxios.js'\nimport type { InventoryRepoAxiosOptions } from './inventoryAxiosBase.js'\n\nexport interface InventoryAssetApiClient {\n findAll?: (query?: Record<string, unknown>) => Promise<unknown[]>\n findOne?: (id: string) => Promise<unknown[]>\n saveOne?: (doc: Record<string, unknown>) => Promise<unknown>\n move?: (payload: InventoryMovePayload) => Promise<unknown>\n}\n\nexport interface InventoryLocationApiClient {\n findAll?: (query?: Record<string, unknown>) => Promise<unknown[]>\n findOne?: (id: string) => Promise<unknown[]>\n saveOne?: (doc: Record<string, unknown>) => Promise<unknown>\n}\n\nexport interface InventoryMovementApiClient {\n findAll?: (query?: Record<string, unknown>) => Promise<unknown[]>\n}\n\n// Backward-compatible union type for consumers that still expect one object\nexport type InventoryApiClient = InventoryAssetApiClient & InventoryLocationApiClient & InventoryMovementApiClient\n\nexport interface InventoryMovePayload {\n assetTag: string\n fromLocationCode?: string\n fromLocationKind?: string\n movedBy?: string\n toLocationCode: string\n toLocationKind?: string\n movementType?: string\n}\n\nexport interface InventoryMoveWarning {\n actualLocationCode?: string\n assetTag?: string\n code: string\n message: string\n requestedFromLocationCode?: string\n requestedFromLocationKind?: string\n}\n\nexport interface InventoryMoveResult {\n warnings?: InventoryMoveWarning[]\n}\n\nexport interface InventoryDisplayLocation {\n code: string\n label: string\n type?: string\n}\n\nexport * from './inventoryAxiosBase.js'\nexport * from './inventoryAssetRepoAxios.js'\nexport * from './inventoryAuthRepoAxios.js'\nexport * from './inventoryLocationRepoAxios.js'\nexport * from './inventoryMovementRepoAxios.js'\n\n// Backward-compat wrapper so existing callers don't break immediately.\n// Internally it delegates to the focused repos above.\nexport class InventoryRepoAxios implements InventoryApiClient {\n private assetRepo: InventoryAssetRepoAxios\n private locationRepo: InventoryLocationRepoAxios\n private movementRepo: InventoryMovementRepoAxios\n\n constructor(options: InventoryRepoAxiosOptions = {}) {\n this.assetRepo = new InventoryAssetRepoAxios(options)\n this.locationRepo = new InventoryLocationRepoAxios(options)\n this.movementRepo = new InventoryMovementRepoAxios(options)\n }\n\n async findAll(query?: Record<string, unknown>) {\n return this.assetRepo.findAll(query)\n }\n\n async findOne(id: string) {\n return this.assetRepo.findOne(id)\n }\n\n async saveOne(doc: Record<string, unknown>) {\n return this.assetRepo.saveOne(doc)\n }\n\n async move(payload: InventoryMovePayload) {\n return this.assetRepo.move(payload)\n }\n\n // Legacy alias for asset findAll\n async findAssets(query?: Record<string, unknown>) {\n return this.assetRepo.findAll(query)\n }\n\n // Legacy alias for location findAll\n async findLocations(query?: Record<string, unknown>) {\n return this.locationRepo.findAll(query)\n }\n\n // Legacy alias — location assets are just assets filtered by currentLocationCode\n async findLocationAssets(locationCode: string) {\n return this.assetRepo.findAll({ currentLocationCode: locationCode })\n }\n\n // Legacy alias for movement history\n async findAssetHistory(assetTag: string) {\n return this.movementRepo.findAll({ assetTag })\n }\n\n // Legacy alias for move\n async moveAsset(payload: InventoryMovePayload) {\n return this.assetRepo.move(payload)\n }\n}\n","import type { App } from 'vue'\nimport QInventory from './components/QInventory.vue'\nimport InventoryScanner from './components/InventoryScanner.vue'\nimport InventoryOverview from './components/InventoryOverview.vue'\nimport InventoryAssetDetail from './components/InventoryAssetDetail.vue'\nimport InventoryLocationDetail from './components/InventoryLocationDetail.vue'\nimport InventoryLocationAdmin from './components/InventoryLocationAdmin.vue'\nimport './styles/index.scss'\n\nexport * from '@questwork/q-inventory-model'\nexport * from './models/index.js'\n\nfunction install(app: App) {\n app.component('q-inventory', QInventory)\n app.component('inventory-scanner', InventoryScanner)\n app.component('inventory-overview', InventoryOverview)\n app.component('inventory-asset-detail', InventoryAssetDetail)\n app.component('inventory-location-detail', InventoryLocationDetail)\n app.component('inventory-location-admin', InventoryLocationAdmin)\n}\n\nQInventory.install = install\n\nexport {\n install,\n InventoryAssetDetail,\n InventoryLocationAdmin,\n InventoryLocationDetail,\n InventoryOverview,\n InventoryScanner,\n QInventory,\n}\n\nexport default {\n install,\n}\n"],"names":["props","__props","emit","__emit","activeLocationCode","ref","basketItems","manualQr","mode","INVENTORY_MOVEMENT_TYPE","scanLog","holderLocationCode","computed","getVirtualUserLocationCode","locationLabel","watch","syncBasketFromAssets","setMode","nextMode","addLog","submitManualQr","value","handleQr","parsed","parseInventoryQr","isLocationQr","payload","getMovePayload","result","warnings","getMoveWarnings","applyBasketMove","formatWarnings","err","getErrorMessage","assetTag","INVENTORY_LOCATION_KIND","upsertBasketItem","item","index","basketItem","toBasketItem","asset","getString","message","status","title","warning","clearScanLog","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_7","_hoisted_9","_openBlock","_createElementBlock","_createElementVNode","_normalizeClass","$setup","_cache","$event","_toDisplayString","_withDirectives","_withKeys","_hoisted_6","_hoisted_8","_createCommentVNode","_Fragment","_renderList","_hoisted_10","loadedAssets","displayAssets","reload","getAssetKey","getAssetText","key","getDisplayLocation","locationCode","locationKind","isVirtualInventoryLocation","isVirtualUserLocationCode","getVirtualUserCode","location","_ctx","_withModifiers","history","loadHistory","getValue","getHistoryKey","data","getHistoryText","$props","assets","loadAssets","form","reactive","submit","getLocationKey","getLocationText","_vModelText","activeTab","selectedAsset","selectedLocation","tabs","onMoved","onScan","onSaveLocation","onSelectAsset","onSelectLocation","_createVNode","_createBlock","InventoryRepoAxiosBase","options","path","query","headers","response","unwrapQSystemData","url","getUrlBase","body","unwrapQSystemResponse","obj","removeEmptyValues","authenticatorToken","resolveTokenProvider","userToken","provider","json","errors","getResponseErrorMessage","code","formatErrorMessage","InventoryAssetRepoAxios","doc","movedBy","InventoryLocationRepoAxios","InventoryMovementRepoAxios","_omit","rest","InventoryAuthRepoAxios","email","tenantCode","loginToken","InventoryRepoAxios","id","install","app","QInventory","InventoryScanner","InventoryOverview","InventoryAssetDetail","InventoryLocationDetail","InventoryLocationAdmin"],"mappings":";;;;;;;;;;;;;;AAyHA,UAAMA,IAAQC,GAMRC,IAAOC,GAKPC,IAAqBC,EAAI,EAAE,GAC3BC,IAAcD,EAAkB,EAAE,GAClCE,IAAWF,EAAI,EAAE,GACjBG,IAAOH,EAAiBI,EAAwB,MAAM,GACtDC,IAAUL,EAAmB,EAAE,GAE/BM,IAAqBC,EAAS,MAAMC,GAA2Bb,EAAM,mBAAmB,aAAa,CAAC,GACtGc,IAAgBF,EAAS,MAAMJ,EAAK,UAAUC,EAAwB,SAAS,WAAW,aAAa;AAE7G,IAAAM;AAAA,MACE,MAAM,CAACf,EAAM,QAAQW,EAAmB,KAAK;AAAA,MAC7CK;AAAA,MACA,EAAE,MAAM,IAAM,WAAW,GAAA;AAAA,IAAK;AAGhC,aAASC,EAAQC,GAAuB;AACtC,MAAAV,EAAK,QAAQU,GACbd,EAAmB,QAAQ,IAC3Be,EAAO;AAAA,QACL,SAAS,mBAAmBD,CAAQ;AAAA,QACpC,QAAQ;AAAA,QACR,OAAO;AAAA,MAAA,CACR;AAAA,IACH;AAEA,mBAAeE,IAAiB;AAC9B,YAAMC,IAAQd,EAAS,MAAM,KAAA;AAC7B,MAAKc,MACLd,EAAS,QAAQ,IACjB,MAAMe,EAASD,CAAK;AAAA,IACtB;AAEA,mBAAeC,EAASD,GAAe;AACrC,YAAME,IAASC,GAAiBH,CAAK;AAGrC,UAFAnB,EAAK,QAAQ,EAAE,KAAKmB,GAAO,QAAAE,GAAQ,GAE/BE,GAAaJ,CAAK,GAAG;AACvB,QAAAjB,EAAmB,QAAQmB,EAAO,MAClCJ,EAAO;AAAA,UACL,SAAS,GAAGL,EAAc,KAAK,WAAWS,EAAO,IAAI;AAAA,UACrD,QAAQ;AAAA,UACR,OAAO;AAAA,QAAA,CACR;AACD;AAAA,MACF;AAEA,UAAI,CAACnB,EAAmB,OAAO;AAC7B,QAAAe,EAAO;AAAA,UACL,SAAS,QAAQL,EAAc,MAAM,aAAa;AAAA,UAClD,QAAQ;AAAA,UACR,OAAOS,EAAO;AAAA,QAAA,CACf;AACD;AAAA,MACF;AAEA,YAAMG,IAAUC,EAAeJ,EAAO,IAAI;AAC1C,UAAI;AACF,YAAIvB,EAAM,gBAAgB,MAAM;AAC9B,gBAAM4B,IAAS,MAAM5B,EAAM,eAAe,KAAK0B,CAAO,GAChDG,IAAWC,EAAgBF,CAAM;AAGvC,cAFA1B,EAAK,SAASwB,CAAO,GACrBK,EAAgBL,CAAO,GACnBG,EAAS,QAAQ;AACnB,YAAAV,EAAO;AAAA,cACL,SAASa,EAAeH,CAAQ;AAAA,cAChC,QAAQ;AAAA,cACR,OAAON,EAAO;AAAA,YAAA,CACf;AACD;AAAA,UACF;AAAA,QACF;AACE,UAAArB,EAAK,SAASwB,CAAO,GACrBK,EAAgBL,CAAO;AAEzB,QAAAP,EAAO;AAAA,UACL,SAAS,GAAGO,EAAQ,oBAAoB,GAAG,OAAOA,EAAQ,cAAc;AAAA,UACxE,QAAQ;AAAA,UACR,OAAOH,EAAO;AAAA,QAAA,CACf;AAAA,MACH,SAASU,GAAK;AACZ,QAAAd,EAAO;AAAA,UACL,SAASe,EAAgBD,CAAG;AAAA,UAC5B,QAAQ;AAAA,UACR,OAAOV,EAAO;AAAA,QAAA,CACf;AAAA,MACH;AAAA,IACF;AAEA,aAASI,EAAeQ,GAAwC;AAC9D,aAAI3B,EAAK,UAAUC,EAAwB,SAClC;AAAA,QACL,UAAA0B;AAAA,QACA,kBAAkB/B,EAAmB;AAAA,QACrC,kBAAkBgC,EAAwB;AAAA,QAC1C,cAAc3B,EAAwB;AAAA,QACtC,gBAAgBE,EAAmB;AAAA,QACnC,gBAAgByB,EAAwB;AAAA,MAAA,IAGrC;AAAA,QACL,UAAAD;AAAA,QACA,kBAAkBxB,EAAmB;AAAA,QACrC,kBAAkByB,EAAwB;AAAA,QAC1C,cAAc3B,EAAwB;AAAA,QACtC,gBAAgBL,EAAmB;AAAA,QACnC,gBAAgBgC,EAAwB;AAAA,MAAA;AAAA,IAE5C;AAEA,aAASL,EAAgBL,GAA+B;AACtD,UAAIA,EAAQ,mBAAmBf,EAAmB,OAAO;AACvD,QAAA0B,EAAiB;AAAA,UACf,UAAUX,EAAQ;AAAA,UAClB,qBAAqBf,EAAmB;AAAA,QAAA,CACzC;AACD;AAAA,MACF;AACA,MAAAL,EAAY,QAAQA,EAAY,MAAM,OAAO,CAACgC,MAASA,EAAK,aAAaZ,EAAQ,QAAQ;AAAA,IAC3F;AAEA,aAASW,EAAiBC,GAAkB;AAC1C,YAAMC,IAAQjC,EAAY,MAAM,UAAU,CAACkC,MAAeA,EAAW,aAAaF,EAAK,QAAQ;AAC/F,UAAIC,KAAS,GAAG;AACd,QAAAjC,EAAY,MAAMiC,CAAK,IAAI;AAAA,UACzB,GAAGjC,EAAY,MAAMiC,CAAK;AAAA,UAC1B,GAAGD;AAAA,QAAA;AAEL;AAAA,MACF;AACA,MAAAhC,EAAY,MAAM,QAAQgC,CAAI;AAAA,IAChC;AAEA,aAAStB,IAAuB;AAC9B,MAAAV,EAAY,SAASN,EAAM,UAAU,CAAA,GAClC,IAAIyC,CAAY,EAChB,OAAO,CAACH,MAA6B,CAAC,CAACA,KAAQA,EAAK,wBAAwB3B,EAAmB,KAAK;AAAA,IACzG;AAEA,aAAS8B,EAAaC,GAAmC;AACvD,YAAMJ,IAAOI,GACPP,IAAWQ,EAAUL,EAAK,QAAQ;AACxC,aAAKH,IAGE;AAAA,QACL,UAAAA;AAAA,QACA,UAAUQ,EAAUL,EAAK,QAAQ;AAAA,QACjC,qBAAqBK,EAAUL,EAAK,mBAAmB;AAAA,QACvD,MAAMK,EAAUL,EAAK,IAAI;AAAA,MAAA,IANlB;AAAA,IAQX;AAEA,aAASnB,EAAO,EAAE,SAAAyB,GAAS,QAAAC,GAAQ,OAAAC,KAAmC;AACpE,MAAApC,EAAQ,MAAM,QAAQ;AAAA,QACpB,KAAK,GAAG,KAAK,IAAA,CAAK,IAAI,KAAK,QAAQ;AAAA,QACnC,SAAAkC;AAAA,QACA,QAAAC;AAAA,QACA,OAAAC;AAAA,MAAA,CACD,GACDpC,EAAQ,QAAQA,EAAQ,MAAM,MAAM,GAAG,EAAE;AAAA,IAC3C;AAEA,aAASiC,EAAUtB,GAAgB;AACjC,aAAO,OAAOA,KAAU,WAAWA,IAAQ;AAAA,IAC7C;AAEA,aAASa,EAAgBD,GAAc;AACrC,aAAOA,aAAe,QAAQA,EAAI,UAAU,OAAOA,CAAG;AAAA,IACxD;AAEA,aAASH,EAAgBF,GAAiB;AAExC,aADiBA,GACA,OAAO,CAAC,GAAG,YAAY,CAAA;AAAA,IAC1C;AAEA,aAASI,EAAeH,GAAkC;AACxD,aAAOA,EAAS,IAAI,CAACkB,MAAY,GAAGA,EAAQ,IAAI,KAAKA,EAAQ,OAAO,EAAE,EAAE,KAAK,IAAI;AAAA,IACnF;AAEA,aAASC,KAAe;AACtB,MAAAtC,EAAQ,QAAQ,CAAA;AAAA,IAClB;;;;;;;;;;;GAxTOuC,KAAA,EAAA,OAAM,oBAAA,GACJC,KAAA,EAAA,OAAM,0BAAA,GAkBNC,KAAA,EAAA,OAAM,2BAAA,GAKNC,KAAA,EAAA,OAAM,4BAAA,GASNC,KAAA,EAAA,OAAM,mCAAA,sBAaNC,KAAA,EAAA,OAAM,4BAAA;;EAGP,OAAM;GAaLC,KAAA,EAAA,OAAM,yBAAA;;EAmBT,OAAM;;;AAjFV,SAAAC,EAAA,GAAAC,EAqFM,OArFNR,IAqFM;AAAA,IApFJS,EAiBM,OAjBNR,IAiBM;AAAA,MAhBJQ;AAAAA,QAOS;AAAA,QAAA;AAAA,UANP,OAAKC,EAAA,CAAC,kCAAgC,EAAA,0CACcC,EAAA,SAASA,0BAAwB,OAAA,CAAM,CAAA;AAAA,UAC3F,MAAK;AAAA,UACJ,SAAKC,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAAC,MAAEF,EAAA,QAAQA,EAAA,wBAAwB,MAAM;AAAA,QAAA;AAAA,QAC/C;AAAA,QAED;AAAA;AAAA,MAAA;AAAA,MACAF;AAAAA,QAOS;AAAA,QAAA;AAAA,UANP,OAAKC,EAAA,CAAC,kCAAgC,EAAA,0CACcC,EAAA,SAASA,0BAAwB,QAAA,CAAO,CAAA;AAAA,UAC5F,MAAK;AAAA,UACJ,SAAKC,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAAC,MAAEF,EAAA,QAAQA,EAAA,wBAAwB,OAAO;AAAA,QAAA;AAAA,QAChD;AAAA,QAED;AAAA;AAAA,MAAA;AAAA,IAAA,CAAA;AAAA,IAEFF,EAIM,OAJNP,IAIM;AAAA,MAHJO;AAAAA,QAA2B;AAAA,QAAA;AAAA,QAAtB,WAAMK,EAAGH,EAAA,IAAI;AAAA,QAAA;AAAA;AAAA,MAAA;AAAA,MAClBF;AAAAA,QAA+D;AAAA,QAAA;AAAA,QAAAK,EAAvDH,EAAA,aAAa,IAAG,OAAEG,EAAGH,EAAA,sBAAkB,GAAA;AAAA,QAAA;AAAA;AAAA,MAAA;AAAA,MAC/CF;AAAAA,QAAkD;AAAA,QAAA;AAAA,QAA7C,aAAQK,EAAGH,EAAA,sBAAkB,GAAA;AAAA,QAAA;AAAA;AAAA,MAAA;AAAA,IAAA,CAAA;AAAA,IAEpCF,EAQM,OARNN,IAQM;AAAA,MAAAY,EAPJN;AAAAA,QAKE;AAAA,QAAA;AAAA,UAAA,uBAAAG,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAAC,MAJSF,EAAA,WAAQE;AAAA,UACjB,OAAM;AAAA,UACN,aAAY;AAAA,UACX,SAAKG,GAAQL,EAAA,gBAAc,CAAA,OAAA,CAAA;AAAA,QAAA;AAAA;;;;YAHnBA,EAAA,QAAQ;AAAA,MAAA,CAAA;AAAA,MAKnBF,EAA6D,UAAA;AAAA,QAArD,MAAK;AAAA,QAAU,SAAOE,EAAA;AAAA,MAAA,GAAgB,QAAM;AAAA,IAAA,CAAA;AAAA,IAEtDF,EAYM,OAZNL,IAYM;AAAA,MAXJK,EAGM,OAAA,MAAA;AAAA,QAAAG,EAAA,CAAA,MAAAA,EAAA,CAAA,IAFJH;AAAAA,UAA0B;AAAA,UAAA;AAAA,UAAlB;AAAA,UAAS;AAAA;AAAA,QAAA;AAAA,QACjBA;AAAAA,UAA6C;AAAA,UAAA;AAAA,UAAAK,EAApCH,EAAA,YAAY,MAAM,IAAG;AAAA,UAAQ;AAAA;AAAA,QAAA;AAAA,MAAA,CAAA;AAAA,MAExCF,EAMS,UAAA;AAAA,QALP,MAAK;AAAA,QACJ,UAAUE,UAAQ,WAAM;AAAA,QACxB,SAAOA,EAAA;AAAA,MAAA,GACT,eAED,GAAAM,EAAA;AAAA,IAAA,CAAA;AAAA,IAEFR,EAeM,OAfNJ,IAeM;AAAA,MAbIM,cAAY,WAAM,KAAAJ,EAAA,GAD1BC,EAKM,OALNU,IAGC,oBAED,KAAAC,EAAA,QAAA,EAAA;AAAA,OACAZ,EAAA,EAAA,GAAAC;AAAAA,QAOMY;AAAAA,QAAA;AAAA,QAAAC,EANWV,EAAA,aAAW,CAAnBtB,YADTmB,EAOM,OAAA;AAAA,UALH,KAAKnB,EAAK;AAAA,UACX,OAAM;AAAA,QAAA,GAAA;AAAA,UAENoB;AAAAA,YAAoC;AAAA,YAAA;AAAA,YAAAK,EAAzBzB,EAAK,QAAQ;AAAA,YAAA;AAAA;AAAA,UAAA;AAAA,UACxBoB;AAAAA,YAA2E;AAAA,YAAA;AAAA,YAAAK,EAAjEzB,EAAK,QAAQA,EAAK,YAAYA,EAAK,mBAAmB;AAAA,YAAA;AAAA;AAAA,UAAA;AAAA,QAAA,CAAA;;;;;IAGpEoB,EAgBM,OAhBNH,IAgBM;AAAA,OAAAC,EAAA,EAAA,GAfJC;AAAAA,QAcMY;AAAAA,QAAA;AAAA,QAAAC,EAbWV,EAAA,SAAO,CAAftB,OADTkB,EAAA,GAAAC;AAAAA,UAcM;AAAA,UAAA;AAAA,YAZH,KAAKnB,EAAK;AAAA,YACX,OAAKqB,GAAC,+BAA6B;AAAA,cAAA,uCACwBrB,EAAK,WAAM;AAAA,cAAA,wCAAiEA,EAAK,WAAM;AAAA,YAAA,CAAA,CAAA;AAAA;;YAKlJoB,EAGM,OAAA,MAAA;AAAA,cAFJA;AAAAA,gBAAiC;AAAA,gBAAA;AAAA,gBAAAK,EAAtBzB,EAAK,KAAK;AAAA,gBAAA;AAAA;AAAA,cAAA;AAAA,cACrBoB;AAAAA,gBAA8B;AAAA,gBAAA;AAAA,gBAAAK,EAArBzB,EAAK,MAAM;AAAA,gBAAA;AAAA;AAAA,cAAA;AAAA,YAAA,CAAA;AAAA,YAEtBoB;AAAAA,cAAiC;AAAA,cAAA;AAAA,cAAAK,EAAvBzB,EAAK,OAAO;AAAA,cAAA;AAAA;AAAA,YAAA;AAAA,UAAA;AAAA;;;;;;;IAIlBsB,EAAA,QAAQ,WAAM,KAAAJ,EAAA,GADtBC,EAKM,OALNc,IAGC,6BAED,KAAAH,EAAA,QAAA,EAAA;AAAA;;;;;;;;;;;;;AC7CJ,UAAMpE,IAAQC,GAWRuE,IAAenE,EAAe,EAAE,GAChCoE,IAAgB7D,EAAS,MAAM4D,EAAa,MAAM,SAAS,IAAIA,EAAa,QAASxE,EAAM,UAAU,CAAA,CAAG;AAE9G,mBAAe0E,IAAS;AACtB,MAAI1E,EAAM,gBAAgB,YACxBwE,EAAa,QAAQ,MAAMxE,EAAM,eAAe,QAAA;AAAA,IAEpD;AAEA,aAAS2E,EAAYjC,GAAgB;AACnC,aAAOkC,EAAalC,GAAO,IAAI,KAAKkC,EAAalC,GAAO,UAAU,KAAK,KAAK,UAAUA,CAAK;AAAA,IAC7F;AAEA,aAASkC,EAAalC,GAAgBmC,GAAa;AACjD,aAAO,OAAQnC,IAAoCmC,CAAG,KAAK,EAAE;AAAA,IAC/D;AAEA,aAASC,EAAmBpC,GAAgB;AAC1C,YAAMqC,IAAeH,EAAalC,GAAO,qBAAqB,GACxDsC,IAAeJ,EAAalC,GAAO,qBAAqB;AAC9D,UAAI,CAACqC,EAAc,QAAO;AAC1B,UAAIE,GAA2B,EAAE,cAAAF,GAAc,cAAAC,EAAA,CAAc,KAAKE,GAA0BH,CAAY;AACtG,eAAO,gBAAgBI,GAAmBJ,CAAY,CAAC;AAEzD,YAAMK,KAAYpF,EAAM,aAAa,CAAA,GAAI,KAAK,CAACsC,MACrCA,EAAiC,iBAAiByC,CAC3D;AACD,aAAO,OAAOK,GAAU,QAAQL,CAAY;AAAA,IAC9C;;;;IA9EO9B,KAAA,EAAA,OAAM,qBAAA,GAKJC,KAAA,EAAA,OAAM,2BAAA;;AALb,SAAAM,EAAA,GAAAC,EAuBM,OAvBNR,IAuBM;AAAA,IAtBJS,EAGM,OAAA,EAHD,OAAM,6BAAA,GAA4B;AAAA,MAAAG,EAAA,CAAA,MAAAA,EAAA,CAAA,IACrCH;AAAAA,QAAiB;AAAA,QAAA;AAAA,QAAZ;AAAA,QAAM;AAAA;AAAA,MAAA;AAAA,MACXA,EAAqD,UAAA;AAAA,QAA7C,MAAK;AAAA,QAAU,SAAOE,EAAA;AAAA,MAAA,GAAQ,QAAM;AAAA,IAAA,CAAA;AAAA,IAE9CF,EAiBM,OAjBNR,IAiBM;AAAA,OAAAM,EAAA,EAAA,GAhBJC;AAAAA,QAeSY;AAAAA,QAAA;AAAA,QAAAC,EAdSV,EAAA,eAAa,CAAtBlB,YADTe,EAeS,UAAA;AAAA,UAbN,KAAKG,cAAYlB,CAAK;AAAA,UACvB,OAAM;AAAA,UACN,MAAK;AAAA,UACJ,SAAK,CAAAoB,MAAEuB,EAAA,MAAK,eAAgB3C,CAAK;AAAA,QAAA,GAAA;AAAA,UAElCgB;AAAAA,YAAkD;AAAA,YAAA;AAAA,YAAAK,EAAzCH,eAAalB,GAAK,UAAA,CAAA;AAAA,YAAA;AAAA;AAAA,UAAA;AAAA,UAC3BgB;AAAAA,YAA8C;AAAA,YAAA;AAAA,YAAAK,EAArCH,eAAalB,GAAK,MAAA,CAAA;AAAA,YAAA;AAAA;AAAA,UAAA;AAAA,UAC3BgB,EAKO,QAAA;AAAA,YAJL,OAAM;AAAA,YACL,SAAK4B,EAAA,CAAAxB,MAAOuB,EAAA,MAAK,kBAAmBzB,eAAalB,GAAK,qBAAA,CAAA,GAAA,CAAA,MAAA,CAAA;AAAA,UAAA,GAAAqB,EAEpDH,qBAAmBlB,CAAK,CAAA,GAAA,GAAAU,EAAA;AAAA,QAAA,GAAA,GAAAD,EAAA;;;;;;;;;;;;;;;;ACOrC,UAAMnD,IAAQC,GAKRsF,IAAUlF,EAAe,EAAE;AAEjC,mBAAemF,IAAc;AAC3B,YAAMrD,IAAWsD,EAAS,UAAU;AACpC,MAAItD,KAAYnC,EAAM,mBAAmB,YACvCuF,EAAQ,QAAQ,MAAMvF,EAAM,kBAAkB,QAAQ,EAAE,UAAAmC,GAAU;AAAA,IAEtE;AAEA,aAASsD,EAASZ,GAAa;AAC7B,aAAO,OAAQ7E,EAAM,QAAoC6E,CAAG,KAAK,EAAE;AAAA,IACrE;AAEA,aAASa,EAAcpD,GAAe;AACpC,YAAMqD,IAAOrD;AACb,aAAO,OAAOqD,EAAK,MAAMA,EAAK,yBAAyBA,EAAK,WAAW,KAAK,UAAUrD,CAAI,CAAC;AAAA,IAC7F;AAEA,aAASsD,EAAetD,GAAe;AACrC,YAAMqD,IAAOrD;AACb,aAAO,GAAGqD,EAAK,oBAAoB,GAAG,OAAOA,EAAK,kBAAkB,GAAG;AAAA,IACzE;;;;IApDO1C,KAAA,EAAA,OAAM,yBAAA;;EACS,OAAM;;;EAaZ,OAAM;;;AAdpB,SAAAO,EAAA,GAAAC,EAeM,OAfNR,IAeM;AAAA,IAdO4C,EAAA,SAAArC,EAAA,GAAXC,EAYM,OAZNP,IAYM;AAAA,MAXJQ;AAAAA,QAAmC;AAAA,QAAA;AAAA,QAAAK,EAA5BH,EAAA,SAAQ,UAAA,CAAA;AAAA,QAAA;AAAA;AAAA,MAAA;AAAA,MACfF;AAAAA,QAAiC;AAAA,QAAA;AAAA,QAAAK,EAAzBH,EAAA,SAAQ,MAAA,CAAA;AAAA,QAAA;AAAA;AAAA,MAAA;AAAA,MAChBF;AAAAA,QAAgD;AAAA,QAAA;AAAA,QAAAK,EAAxCH,EAAA,SAAQ,qBAAA,CAAA;AAAA,QAAA;AAAA;AAAA,MAAA;AAAA,MAChBF,EAAgE,UAAA;AAAA,QAAxD,MAAK;AAAA,QAAU,SAAOE,EAAA;AAAA,MAAA,GAAa,cAAY;AAAA,OAAAJ,EAAA,EAAA,GACvDC;AAAAA,QAMMY;AAAAA,QAAA;AAAA,QAAAC,EALWV,EAAA,SAAO,CAAftB,OADTkB,EAAA,GAAAC;AAAAA,UAMM;AAAA,UAAA;AAAA,YAJH,KAAKG,gBAActB,CAAI;AAAA,YACxB,OAAM;AAAA,UAAA;AAAA,UAEHyB,EAAAH,EAAA,eAAetB,CAAI,CAAA;AAAA,UAAA;AAAA;AAAA,QAAA,EAAA;AAAA;;;gBAG1BmB,EAAyE,OAAzEN,IAAkD,mBAAiB;AAAA,EAAA,CAAA;;;;;;;;;;;ACSvE,UAAMnD,IAAQC,GAKR6F,IAASzF,EAAe,EAAE,GAC1B0E,IAAenE,EAAS,MACxB,OAAOZ,EAAM,YAAa,WAAiBA,EAAM,WAC9C,OAAQA,EAAM,UAAsC,gBAAgB,EAAE,CAC9E;AAED,mBAAe+F,IAAa;AAC1B,MAAIhB,EAAa,SAAS/E,EAAM,gBAAgB,YAC9C8F,EAAO,QAAQ,MAAM9F,EAAM,eAAe,QAAQ,EAAE,qBAAqB+E,EAAa,OAAO;AAAA,IAEjG;AAEA,aAASJ,EAAYjC,GAAgB;AACnC,YAAMiD,IAAOjD;AACb,aAAO,OAAOiD,EAAK,MAAMA,EAAK,YAAY,KAAK,UAAUjD,CAAK,CAAC;AAAA,IACjE;AAEA,aAASkC,EAAalC,GAAgB;AACpC,YAAMiD,IAAOjD;AACb,aAAO,GAAGiD,EAAK,YAAY,EAAE,IAAIA,EAAK,QAAQ,EAAE,GAAG,KAAA;AAAA,IACrD;;;;IAhDO1C,KAAA,EAAA,OAAM,4BAAA,GACJC,KAAA,EAAA,OAAM,oCAAA;;AADb,SAAAM,EAAA,GAAAC,EAYM,OAZNR,IAYM;AAAA,IAXJS,EAGM,OAHNR,IAGM;AAAA,MAFJQ;AAAAA,QAAuD;AAAA,QAAA;AAAA,QAAAK,EAA/CH,EAAA,gBAAY,sBAAA;AAAA,QAAA;AAAA;AAAA,MAAA;AAAA,MACpBF,EAAwF,UAAA;AAAA,QAAhF,MAAK;AAAA,QAAU,UAAQ,CAAGE,EAAA;AAAA,QAAe,SAAOA,EAAA;AAAA,MAAA,GAAY,eAAW,GAAAT,EAAA;AAAA,IAAA,CAAA;AAAA,KAEjFK,EAAA,EAAA,GAAAC;AAAAA,MAMMY;AAAAA,MAAA;AAAA,MAAAC,EALYV,EAAA,QAAM,CAAflB,OADTc,EAAA,GAAAC;AAAAA,QAMM;AAAA,QAAA;AAAA,UAJH,KAAKG,cAAYlB,CAAK;AAAA,UACvB,OAAM;AAAA,QAAA;AAAA,QAEHqB,EAAAH,EAAA,aAAalB,CAAK,CAAA;AAAA,QAAA;AAAA;AAAA,MAAA,EAAA;AAAA;;;;;;;;;;;;;;ACkB3B,UAAMxC,IAAOC,GAIP6F,IAAOC,GAAS;AAAA,MACpB,cAAc;AAAA,MACd,cAAc;AAAA,MACd,MAAM;AAAA,IAAA,CACP;AAED,aAASC,IAAS;AAChB,MAAAhG,EAAK,gBAAgB,EAAE,GAAG8F,GAAM,GAChCA,EAAK,eAAe,IACpBA,EAAK,eAAe,IACpBA,EAAK,OAAO;AAAA,IACd;AAEA,aAASG,EAAef,GAAmB;AACzC,YAAMO,IAAOP;AACb,aAAO,OAAOO,EAAK,MAAMA,EAAK,gBAAgB,KAAK,UAAUP,CAAQ,CAAC;AAAA,IACxE;AAEA,aAASgB,EAAgBhB,GAAmB;AAC1C,YAAMO,IAAOP;AACb,aAAO,GAAGO,EAAK,gBAAgB,EAAE,IAAIA,EAAK,QAAQ,EAAE,GAAG,KAAA;AAAA,IACzD;;;;IArDO1C,KAAA,EAAA,OAAM,2BAAA;;AAAX,SAAAO,EAAA,GAAAC,EAcM,OAdNR,IAcM;AAAA,IAbJS;AAAAA,MAKO;AAAA,MAAA;AAAA,QALD,OAAM;AAAA,QAAkC,UAAM4B,EAAU1B,EAAA,QAAM,CAAA,SAAA,CAAA;AAAA,MAAA;AAAA;QAClEI,EAAAN;AAAAA,UAAiE;AAAA,UAAA;AAAA,YAAA,uBAAAG,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAAC,MAAjDF,OAAK,eAAYE;AAAA,YAAE,aAAY;AAAA,UAAA;AAAA;;;;UAA/B,CAAAuC,GAAAzC,EAAA,KAAK,YAAY;AAAA,QAAA,CAAA;AAAA,QACjCI,EAAAN;AAAAA,UAAgD;AAAA,UAAA;AAAA,YAAA,uBAAAG,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAAC,MAAhCF,OAAK,OAAIE;AAAA,YAAE,aAAY;AAAA,UAAA;AAAA;;;;UAAvB,CAAAuC,GAAAzC,EAAA,KAAK,IAAI;AAAA,QAAA,CAAA;AAAA,QACzBI,EAAAN;AAAAA,UAAwD;AAAA,UAAA;AAAA,YAAA,uBAAAG,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAAC,MAAxCF,OAAK,eAAYE;AAAA,YAAE,aAAY;AAAA,UAAA;AAAA;;;;UAA/B,CAAAuC,GAAAzC,EAAA,KAAK,YAAY;AAAA,QAAA,CAAA;AAAA,QACjCC,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAAH;AAAAA,UAAmC;AAAA,UAAA,EAA3B,MAAK,SAAA;AAAA,UAAS;AAAA,UAAI;AAAA;AAAA,QAAA;AAAA,MAAA;AAAA;;;KAE5BF,EAAA,EAAA,GAAAC;AAAAA,MAMMY;AAAAA,MAAA;AAAA,MAAAC,EALeuB,EAAA,WAAS,CAArBT,OADT5B,EAAA,GAAAC;AAAAA,QAMM;AAAA,QAAA;AAAA,UAJH,KAAKG,iBAAewB,CAAQ;AAAA,UAC7B,OAAM;AAAA,QAAA;AAAA,QAEHrB,EAAAH,EAAA,gBAAgBwB,CAAQ,CAAA;AAAA,QAAA;AAAA;AAAA,MAAA,EAAA;AAAA;;;;;;;;;;;;;;;;;;;ACoDjC,UAAMpF,IAAQC,GASRC,IAAOC,GAQPmG,IAAYjG,EAAI,SAAS,GACzBkG,IAAgBlG,EAAa,IAAI,GACjCmG,IAAmBnG,EAAa,IAAI,GACpCoG,IAAO7F,EAAS,MAAM;AAAA,MAC1B,EAAE,KAAK,WAAW,OAAO,OAAA;AAAA,MACzB,EAAE,KAAK,YAAY,OAAO,WAAA;AAAA,MAC1B,EAAE,KAAK,SAAS,OAAO,QAAA;AAAA,MACvB,EAAE,KAAK,YAAY,OAAO,WAAA;AAAA,MAC1B,EAAE,KAAK,aAAa,OAAO,YAAA;AAAA,IAAY,CACxC;AAED,aAAS8F,EAAQhF,GAAkB;AACjC,MAAAxB,EAAK,SAASwB,CAAO;AAAA,IACvB;AAEA,aAASiF,EAAOjF,GAAkB;AAChC,MAAAxB,EAAK,QAAQwB,CAAO;AAAA,IACtB;AAEA,aAASkF,EAAelF,GAAkB;AACxC,MAAAxB,EAAK,gBAAgBwB,CAAO;AAAA,IAC9B;AAEA,aAASmF,EAAcnF,GAAkB;AACvC,MAAA6E,EAAc,QAAQ7E,GACtB4E,EAAU,QAAQ,SAClBpG,EAAK,eAAewB,CAAO;AAAA,IAC7B;AAEA,aAASoF,EAAiBpF,GAAkB;AAC1C,MAAA8E,EAAiB,QAAQ9E,GACzB4E,EAAU,QAAQ,YAClBpG,EAAK,kBAAkBwB,CAAO;AAAA,IAChC;;;;IAlHOuB,KAAA,EAAA,OAAM,cAAA,GACJC,KAAA,EAAA,OAAM,uBAAA;;AADb,SAAAM,EAAA,GAAAC,EA4CM,OA5CNR,IA4CM;AAAA,IA3CJS,EAWM,OAXNR,IAWM;AAAA,OAAAM,EAAA,EAAA,GAVJC;AAAAA,QASSY;AAAAA,QAAA;AAAA,QAAAC,EARQV,EAAA,MAAI,CAAZtB,YADTmB,EASS,UAAA;AAAA,UAPN,KAAKnB,EAAK;AAAA,UACX,OAAKqB,EAAA,CAAC,oBAAkB,EAAA,4BACcC,EAAA,cAActB,EAAK,IAAA,CAAG,CAAA;AAAA,UAC5D,MAAK;AAAA,UACJ,SAAK,CAAAwB,MAAEF,EAAA,YAAYtB,EAAK;AAAA,QAAA,GAAAyB,EAEtBzB,EAAK,KAAK,GAAA,IAAAa,EAAA,EAAA;AAAA;;;;MAGjB4D,GAOEnD,EAAA,kBAAA;AAAA,MALC,oBAAkBiC,EAAA;AAAA,MAClB,QAAQA,EAAA;AAAA,MACR,qBAAmBA,EAAA;AAAA,MACnB,SAAOjC,EAAA;AAAA,MACP,QAAMA,EAAA;AAAA,IAAA,GAAA,MAAA,GAAA,CAAA,oBAAA,UAAA,mBAAA,CAAA,GAAA;AAAA,WALCA,EAAA,cAAS,SAAA;AAAA,IAAA,CAAA;AAAA,IAQXA,EAAA,cAAS,mBADjBoD,EAOEpD,EAAA,mBAAA;AAAA,MAAA,KAAA;AAAA,MALC,oBAAkBiC,EAAA;AAAA,MAClB,QAAQA,EAAA;AAAA,MACR,WAAWA,EAAA;AAAA,MACX,eAAcjC,EAAA;AAAA,MACd,kBAAiBA,EAAA;AAAA,IAAA,GAAA,MAAA,GAAA,CAAA,oBAAA,UAAA,WAAA,CAAA,KAAAQ,EAAA,QAAA,EAAA;AAAA,IAGZR,EAAA,cAAS,gBADjBoD,EAIEpD,EAAA,sBAAA;AAAA,MAAA,KAAA;AAAA,MAFC,uBAAqBiC,EAAA;AAAA,MACrB,OAAOjC,EAAA;AAAA,IAAA,GAAA,MAAA,GAAA,CAAA,uBAAA,OAAA,CAAA,KAAAQ,EAAA,QAAA,EAAA;AAAA,IAGFR,EAAA,cAAS,mBADjBoD,EAIEpD,EAAA,yBAAA;AAAA,MAAA,KAAA;AAAA,MAFC,oBAAkBiC,EAAA;AAAA,MAClB,UAAUjC,EAAA;AAAA,IAAA,GAAA,MAAA,GAAA,CAAA,oBAAA,UAAA,CAAA,KAAAQ,EAAA,QAAA,EAAA;AAAA,IAGLR,EAAA,cAAS,oBADjBoD,EAIEpD,EAAA,wBAAA;AAAA,MAAA,KAAA;AAAA,MAFC,WAAWiC,EAAA;AAAA,MACX,gBAAejC,EAAA;AAAA,IAAA,GAAA,MAAA,GAAA,CAAA,WAAA,CAAA,KAAAQ,EAAA,QAAA,EAAA;AAAA;;;AC5Bf,MAAe6C,EAAuB;AAAA,EAS3C,YAAYC,IAAqC,IAAI;AACnD,SAAK,QAAQA,EAAQ,OACrB,KAAK,6BAA6BA,EAAQ,4BAC1C,KAAK,WAAWA,EAAQ,WAAW,IAAI,QAAQ,OAAO,EAAE,GACxD,KAAK,UAAUA,EAAQ,WAAW,eAClC,KAAK,QAAQA,EAAQ,OACrB,KAAK,aAAaA,EAAQ,cAAc,cACxC,KAAK,oBAAoBA,EAAQ;AAAA,EACnC;AAAA,EAEA,MAAgB,IAAIC,GAAcC,IAAiC,IAAI;AACrE,UAAMC,IAAU,MAAM,KAAK,eAAA;AAC3B,QAAI,KAAK,OAAO;AACd,YAAMC,IAAW,MAAM,KAAK,MAAM,IAAI,KAAK,OAAOH,CAAI,GAAG,EAAE,SAAAE,GAAS,QAAQD,GAAO;AACnF,aAAOG,EAAkBD,EAAS,IAAI;AAAA,IACxC;AACA,UAAME,IAAM,IAAI,IAAI,KAAK,OAAOL,CAAI,GAAGM,IAAY;AACnD,WAAO,QAAQL,CAAK,EAAE,QAAQ,CAAC,CAACvC,GAAKxD,CAAK,MAAM;AAC9C,MAAI,OAAOA,IAAU,OAAeA,MAAU,QAAQA,MAAU,MAC9DmG,EAAI,aAAa,IAAI3C,GAAK,OAAOxD,CAAK,CAAC;AAAA,IAE3C,CAAC;AACD,UAAMiG,IAAW,MAAM,MAAM,KAAK,YAAYE,CAAG,GAAG,EAAE,SAAAH,GAAS;AAC/D,WAAOE,EAAkB,MAAMD,EAAS,KAAA,GAAQA,CAAQ;AAAA,EAC1D;AAAA,EAEA,MAAgB,KAAKH,GAAcO,IAAgC,IAAI;AACrE,UAAML,IAAU;AAAA,MACd,gBAAgB;AAAA,MAChB,GAAG,MAAM,KAAK,eAAA;AAAA,IAAe;AAE/B,QAAI,KAAK,OAAO;AACd,YAAMC,IAAW,MAAM,KAAK,MAAM,KAAK,KAAK,OAAOH,CAAI,GAAGO,GAAM,EAAE,SAAAL,EAAA,CAAS;AAC3E,aAAOM,EAAsBL,EAAS,IAAI;AAAA,IAC5C;AACA,UAAMA,IAAW,MAAM,MAAM,KAAK,OAAOH,CAAI,GAAG;AAAA,MAC9C,MAAM,KAAK,UAAUO,CAAI;AAAA,MACzB,SAAAL;AAAA,MACA,QAAQ;AAAA,IAAA,CACT;AACD,WAAOM,EAAsB,MAAML,EAAS,KAAA,GAAQA,CAAQ;AAAA,EAC9D;AAAA,EAEU,OAAOH,GAAc;AAC7B,WAAO,GAAG,KAAK,OAAO,UAAUA,CAAI;AAAA,EACtC;AAAA,EAEU,YAAYK,GAAU;AAC9B,WAAO,KAAK,UAAUA,EAAI,SAAA,IAAa,GAAGA,EAAI,QAAQ,GAAGA,EAAI,MAAM;AAAA,EACrE;AAAA,EAEU,aAAaI,IAA+B,IAAI;AACxD,WAAOC,GAAkB;AAAA,MACvB,GAAGD;AAAA,MACH,OAAOA,EAAI,SAAS,KAAK;AAAA,MACzB,YAAYA,EAAI,cAAc,KAAK;AAAA,IAAA,CACpC;AAAA,EACH;AAAA,EAEA,MAAc,iBAAiB;AAC7B,UAAMP,IAAkC,CAAA,GAClCS,IAAqB,MAAMC,EAAqB,KAAK,0BAA0B,GAC/EC,IAAY,MAAMD,EAAqB,KAAK,iBAAiB;AACnE,WAAID,MACFT,EAAQ,mBAAmB,IAAIS,IAE7BE,MACFX,EAAQ,0BAA0B,IAAIW,IAEjCX;AAAA,EACT;AACF;AAEA,eAAeU,EAAqBE,GAA2C;AAC7E,SAAKA,IAGEA,EAAA,IAFE;AAGX;AAEA,SAASN,EAAsBO,GAAeZ,GAAqB;AACjE,QAAM3B,IAAOuC,GACPjG,IAAM0D,GAAM,KACZwC,IAASxC,GAAM;AACrB,MAAK2B,KAAY,CAACA,EAAS,MAAOrF,GAAK,YAAYkG;AACjD,UAAM,IAAI,MAAMC,GAAwB,EAAE,MAAAzC,GAAM,KAAA1D,GAAK,QAAAkG,GAAQ,UAAAb,EAAA,CAAU,CAAC;AAE1E,SAAO3B;AACT;AAEA,SAAS4B,EAAkBW,GAAeZ,GAAgC;AACxE,QAAM3B,IAAOgC,EAAsBO,GAAMZ,CAAQ;AACjD,SAAO,MAAM,QAAQ3B,GAAM,IAAI,IAAIA,EAAK,OAAO,CAAA;AACjD;AAEA,SAAS8B,KAAa;AACpB,SAAI,OAAO,SAAW,MACb,OAAO,SAAS,SAElB;AACT;AAEA,SAASW,GAAwB,EAAE,MAAAzC,GAAM,KAAA1D,GAAK,QAAAkG,GAAQ,UAAAb,KAKnD;AACD,QAAMe,IAAO,OAAOf,GAAU,UAAUrF,GAAK,cAAcA,GAAK,QAAQkG,GAAQ,QAAQxC,GAAM,QAAQ,eAAe,GAC/G/C,IAAU0F,GAAmBrG,GAAK,WAAWkG,GAAQ,WAAWxC,GAAM,WAAW,2BAA2B;AAClH,SAAO,GAAG0C,CAAI,KAAKzF,CAAO;AAC5B;AAEA,SAAS0F,GAAmBjH,GAAgB;AAC1C,SAAI,MAAM,QAAQA,CAAK,IACdA,EAAM,KAAK,IAAI,IAEjB,OAAOA,CAAK;AACrB;AAEA,SAASwG,GAAkBD,GAA8B;AACvD,SAAO,OAAO;AAAA,IACZ,OAAO,QAAQA,CAAG,EAAE,OAAO,CAAC,CAAA,EAAGvG,CAAK,MAAM,OAAOA,IAAU,OAAeA,MAAU,QAAQA,MAAU,EAAE;AAAA,EAAA;AAE5G;ACxIO,MAAMkH,WAAgCtB,EAAuB;AAAA,EAClE,YAAYC,IAAqC,IAAI;AACnD,UAAMA,CAAO;AAAA,EACf;AAAA,EAEA,MAAM,QAAQE,IAAoC,IAAI;AACpD,WAAO,KAAK,IAAI,oBAAoB,KAAK,aAAaA,CAAK,CAAC;AAAA,EAC9D;AAAA,EAEA,MAAM,QAAQjF,GAAkB;AAC9B,WAAO,KAAK,IAAI,oBAAoB,mBAAmBA,CAAQ,CAAC,IAAI,KAAK,cAAc;AAAA,EACzF;AAAA,EAEA,MAAM,QAAQqG,GAA8B;AAC1C,WAAO,KAAK,KAAK,oBAAoB,KAAK,aAAaA,CAAG,CAAC;AAAA,EAC7D;AAAA,EAEA,MAAM,KAAK9G,GAA+B;AACxC,UAAMS,IAAW,OAAOT,EAAQ,YAAY,EAAE,GACxC+G,IAAU/G,EAAQ,WAAW,KAAK;AACxC,WAAO,KAAK,KAAK,oBAAoB,mBAAmBS,CAAQ,CAAC,SAAS,KAAK,aAAa;AAAA,MAC1F,GAAGT;AAAA,MACH,SAAA+G;AAAA,IAAA,CACD,CAAC;AAAA,EACJ;AACF;AC7BO,MAAMC,WAAmCzB,EAAuB;AAAA,EACrE,YAAYC,IAAqC,IAAI;AACnD,UAAMA,CAAO;AAAA,EACf;AAAA,EAEA,MAAM,QAAQE,IAAuC,IAAI;AACvD,WAAO,KAAK,IAAI,uBAAuB,KAAK,aAAaA,CAAK,CAAC;AAAA,EACjE;AAAA,EAEA,MAAM,QAAQrC,GAAsB;AAClC,WAAO,KAAK,IAAI,uBAAuB,mBAAmBA,CAAY,CAAC,IAAI,KAAK,cAAc;AAAA,EAChG;AAAA,EAEA,MAAM,QAAQyD,GAA8B;AAC1C,WAAO,KAAK,KAAK,uBAAuB,KAAK,aAAaA,CAAG,CAAC;AAAA,EAChE;AACF;ACdO,MAAMG,WAAmC1B,EAAuB;AAAA,EACrE,YAAYC,IAAqC,IAAI;AACnD,UAAMA,CAAO;AAAA,EACf;AAAA,EAEA,MAAM,QAAQE,IAAuC,IAAI;AACvD,UAAMjF,IAAW,OAAOiF,EAAM,YAAY,EAAE;AAC5C,QAAI,CAACjF;AACH,YAAM,IAAI,MAAM,2CAA2C;AAE7D,UAAM,EAAE,UAAUyG,GAAO,GAAGC,MAASzB;AACrC,WAAO,KAAK,IAAI,oBAAoB,mBAAmBjF,CAAQ,CAAC,cAAc,KAAK,aAAa0G,CAAI,CAAC;AAAA,EACvG;AACF;ACHO,MAAMC,WAA+B7B,EAAuB;AAAA,EACjE,YAAYC,IAAqC,IAAI;AACnD,UAAMA,CAAO;AAAA,EACf;AAAA,EAEA,MAAM,kBAAkB;AAKtB,YAJe,MAAM,KAAK,KAAK,qBAAqB;AAAA,MAClD,aAAa;AAAA,MACb,eAAe;AAAA,IAAA,CAChB,GACa,OAAO,CAAC;AAAA,EACxB;AAAA,EAEA,MAAM,iBAAiB,EAAE,OAAA6B,GAAO,YAAAC,IAAa,KAAK,cAAsD;AAKtG,YAJe,MAAM,KAAK,KAAK,0BAA0B;AAAA,MACvD,OAAAD;AAAA,MACA,YAAAC;AAAA,IAAA,CACD,GACa,OAAO,CAAC;AAAA,EACxB;AAAA,EAEA,MAAM,iBAAiBC,GAAoB;AAIzC,YAHe,MAAM,KAAK,KAAK,kCAAkC;AAAA,MAC/D,YAAAA;AAAA,IAAA,CACD,GACa,OAAO,CAAC;AAAA,EACxB;AACF;ACeO,MAAMC,GAAiD;AAAA,EAK5D,YAAYhC,IAAqC,IAAI;AACnD,SAAK,YAAY,IAAIqB,GAAwBrB,CAAO,GACpD,KAAK,eAAe,IAAIwB,GAA2BxB,CAAO,GAC1D,KAAK,eAAe,IAAIyB,GAA2BzB,CAAO;AAAA,EAC5D;AAAA,EAEA,MAAM,QAAQE,GAAiC;AAC7C,WAAO,KAAK,UAAU,QAAQA,CAAK;AAAA,EACrC;AAAA,EAEA,MAAM,QAAQ+B,GAAY;AACxB,WAAO,KAAK,UAAU,QAAQA,CAAE;AAAA,EAClC;AAAA,EAEA,MAAM,QAAQX,GAA8B;AAC1C,WAAO,KAAK,UAAU,QAAQA,CAAG;AAAA,EACnC;AAAA,EAEA,MAAM,KAAK9G,GAA+B;AACxC,WAAO,KAAK,UAAU,KAAKA,CAAO;AAAA,EACpC;AAAA;AAAA,EAGA,MAAM,WAAW0F,GAAiC;AAChD,WAAO,KAAK,UAAU,QAAQA,CAAK;AAAA,EACrC;AAAA;AAAA,EAGA,MAAM,cAAcA,GAAiC;AACnD,WAAO,KAAK,aAAa,QAAQA,CAAK;AAAA,EACxC;AAAA;AAAA,EAGA,MAAM,mBAAmBrC,GAAsB;AAC7C,WAAO,KAAK,UAAU,QAAQ,EAAE,qBAAqBA,GAAc;AAAA,EACrE;AAAA;AAAA,EAGA,MAAM,iBAAiB5C,GAAkB;AACvC,WAAO,KAAK,aAAa,QAAQ,EAAE,UAAAA,GAAU;AAAA,EAC/C;AAAA;AAAA,EAGA,MAAM,UAAUT,GAA+B;AAC7C,WAAO,KAAK,UAAU,KAAKA,CAAO;AAAA,EACpC;AACF;ACrGA,SAAS0H,GAAQC,GAAU;AACzB,EAAAA,EAAI,UAAU,eAAeC,EAAU,GACvCD,EAAI,UAAU,qBAAqBE,CAAgB,GACnDF,EAAI,UAAU,sBAAsBG,EAAiB,GACrDH,EAAI,UAAU,0BAA0BI,EAAoB,GAC5DJ,EAAI,UAAU,6BAA6BK,EAAuB,GAClEL,EAAI,UAAU,4BAA4BM,EAAsB;AAClE;AAEAL,GAAW,UAAUF;AAYrB,MAAA7G,KAAe;AAAA,EACb,SAAA6G;AACF;"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),m=require("@questwork/q-inventory-model"),G=e.defineComponent({name:"inventory-scanner",__name:"InventoryScanner",props:{assetApiClient:{type:Object,required:!1},assets:{type:Array,required:!1},currentUserCode:{type:String,required:!1}},emits:["moved","scan"],setup(r,{expose:t,emit:o}){t();const n=r,a=o,l=e.ref(""),s=e.ref([]),u=e.ref(""),y=e.ref(m.INVENTORY_MOVEMENT_TYPE.PICKUP),d=e.ref([]),c=e.computed(()=>m.getVirtualUserLocationCode(n.currentUserCode||"currentUser")),f=e.computed(()=>y.value===m.INVENTORY_MOVEMENT_TYPE.PICKUP?"Source":"Destination");e.watch(()=>[n.assets,c.value],q,{deep:!0,immediate:!0});function A(i){y.value=i,l.value="",h({message:`Mode changed to ${i}`,status:"INFO",title:"Mode"})}async function k(){const i=u.value.trim();i&&(u.value="",await g(i))}async function g(i){const v=m.parseInventoryQr(i);if(a("scan",{raw:i,parsed:v}),m.isLocationQr(i)){l.value=v.code,h({message:`${f.value} set to ${v.code}`,status:"INFO",title:"Location"});return}if(!l.value){h({message:`Scan ${f.value.toLowerCase()} location first`,status:"FAILED",title:v.code});return}const p=_(v.code);try{if(n.assetApiClient?.move){const T=await n.assetApiClient.move(p),Y=P(T);if(a("moved",p),I(p),Y.length){h({message:U(Y),status:"WARNING",title:v.code});return}}else a("moved",p),I(p);h({message:`${p.fromLocationCode||"-"} -> ${p.toLocationCode}`,status:"OK",title:v.code})}catch(T){h({message:x(T),status:"FAILED",title:v.code})}}function _(i){return y.value===m.INVENTORY_MOVEMENT_TYPE.PICKUP?{assetTag:i,fromLocationCode:l.value,fromLocationKind:m.INVENTORY_LOCATION_KIND.REGISTERED,movementType:m.INVENTORY_MOVEMENT_TYPE.PICKUP,toLocationCode:c.value,toLocationKind:m.INVENTORY_LOCATION_KIND.VIRTUAL}:{assetTag:i,fromLocationCode:c.value,fromLocationKind:m.INVENTORY_LOCATION_KIND.VIRTUAL,movementType:m.INVENTORY_MOVEMENT_TYPE.DROPOFF,toLocationCode:l.value,toLocationKind:m.INVENTORY_LOCATION_KIND.REGISTERED}}function I(i){if(i.toLocationCode===c.value){D({assetTag:i.assetTag,currentLocationCode:c.value});return}s.value=s.value.filter(v=>v.assetTag!==i.assetTag)}function D(i){const v=s.value.findIndex(p=>p.assetTag===i.assetTag);if(v>=0){s.value[v]={...s.value[v],...i};return}s.value.unshift(i)}function q(){s.value=(n.assets||[]).map(M).filter(i=>!!i&&i.currentLocationCode===c.value)}function M(i){const v=i,p=C(v.assetTag);return p?{assetTag:p,category:C(v.category),currentLocationCode:C(v.currentLocationCode),name:C(v.name)}:null}function h({message:i,status:v,title:p}){d.value.unshift({key:`${Date.now()}-${Math.random()}`,message:i,status:v,title:p}),d.value=d.value.slice(0,30)}function C(i){return typeof i=="string"?i:""}function x(i){return i instanceof Error?i.message:String(i)}function P(i){return i?.data?.[0]?.warnings||[]}function U(i){return i.map(v=>`${v.code}: ${v.message}`).join("; ")}function z(){d.value=[]}const K={props:n,emit:a,activeLocationCode:l,basketItems:s,manualQr:u,mode:y,scanLog:d,holderLocationCode:c,locationLabel:f,setMode:A,submitManualQr:k,handleQr:g,getMovePayload:_,applyBasketMove:I,upsertBasketItem:D,syncBasketFromAssets:q,toBasketItem:M,addLog:h,getString:C,getErrorMessage:x,getMoveWarnings:P,formatWarnings:U,clearScanLog:z,get INVENTORY_MOVEMENT_TYPE(){return m.INVENTORY_MOVEMENT_TYPE}};return Object.defineProperty(K,"__isScriptSetup",{enumerable:!1,value:!0}),K}}),E=(r,t)=>{const o=r.__vccOpts||r;for(const[n,a]of t)o[n]=a;return o},W={class:"inventory-scanner"},X={class:"inventory-scanner__mode"},Z={class:"inventory-scanner__state"},$={class:"inventory-scanner__manual"},ee={class:"inventory-scanner__basket-header"},te=["disabled"],ne={class:"inventory-scanner__basket"},oe={key:0,class:"inventory-scanner__empty"},se={class:"inventory-scanner__log"},re={key:0,class:"inventory-scanner__log-empty"};function ae(r,t,o,n,a,l){return e.openBlock(),e.createElementBlock("div",W,[e.createElementVNode("div",X,[e.createElementVNode("button",{class:e.normalizeClass(["inventory-scanner__mode-button",{"inventory-scanner__mode-button--active":n.mode===n.INVENTORY_MOVEMENT_TYPE.PICKUP}]),type:"button",onClick:t[0]||(t[0]=s=>n.setMode(n.INVENTORY_MOVEMENT_TYPE.PICKUP))}," Pickup ",2),e.createElementVNode("button",{class:e.normalizeClass(["inventory-scanner__mode-button",{"inventory-scanner__mode-button--active":n.mode===n.INVENTORY_MOVEMENT_TYPE.DROPOFF}]),type:"button",onClick:t[1]||(t[1]=s=>n.setMode(n.INVENTORY_MOVEMENT_TYPE.DROPOFF))}," Drop-off ",2)]),e.createElementVNode("div",Z,[e.createElementVNode("div",null,"Mode: "+e.toDisplayString(n.mode),1),e.createElementVNode("div",null,e.toDisplayString(n.locationLabel)+": "+e.toDisplayString(n.activeLocationCode||"-"),1),e.createElementVNode("div",null,"Holder: "+e.toDisplayString(n.holderLocationCode||"-"),1)]),e.createElementVNode("div",$,[e.withDirectives(e.createElementVNode("input",{"onUpdate:modelValue":t[2]||(t[2]=s=>n.manualQr=s),class:"inventory-scanner__input",placeholder:"Scan or enter QR text",onKeyup:e.withKeys(n.submitManualQr,["enter"])},null,544),[[e.vModelText,n.manualQr]]),e.createElementVNode("button",{type:"button",onClick:n.submitManualQr},"Submit")]),e.createElementVNode("div",ee,[e.createElementVNode("div",null,[t[3]||(t[3]=e.createElementVNode("strong",null,"My Basket",-1)),e.createElementVNode("span",null,e.toDisplayString(n.basketItems.length)+" on hand",1)]),e.createElementVNode("button",{type:"button",disabled:n.scanLog.length===0,onClick:n.clearScanLog}," Clear log ",8,te)]),e.createElementVNode("div",ne,[n.basketItems.length===0?(e.openBlock(),e.createElementBlock("div",oe," No items on hand ")):e.createCommentVNode("v-if",!0),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(n.basketItems,s=>(e.openBlock(),e.createElementBlock("div",{key:s.assetTag,class:"inventory-scanner__basket-item"},[e.createElementVNode("strong",null,e.toDisplayString(s.assetTag),1),e.createElementVNode("small",null,e.toDisplayString(s.name||s.category||s.currentLocationCode),1)]))),128))]),e.createElementVNode("div",se,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(n.scanLog,s=>(e.openBlock(),e.createElementBlock("div",{key:s.key,class:e.normalizeClass(["inventory-scanner__log-item",{"inventory-scanner__log-item--failed":s.status==="FAILED","inventory-scanner__log-item--warning":s.status==="WARNING"}])},[e.createElementVNode("div",null,[e.createElementVNode("strong",null,e.toDisplayString(s.title),1),e.createElementVNode("span",null,e.toDisplayString(s.status),1)]),e.createElementVNode("small",null,e.toDisplayString(s.message),1)],2))),128))]),n.scanLog.length===0?(e.openBlock(),e.createElementBlock("div",re," Scan log will appear here ")):e.createCommentVNode("v-if",!0)])}const b=E(G,[["render",ae],["__file","/Users/donlee/Developer/qw.q.inventory/src/components/InventoryScanner.vue"]]),ie=e.defineComponent({name:"inventory-overview",__name:"InventoryOverview",props:{assetApiClient:{type:Object,required:!1},assets:{type:Array,required:!1},locations:{type:Array,required:!1}},emits:["selectAsset","selectLocation"],setup(r,{expose:t}){t();const o=r,n=e.ref([]),a=e.computed(()=>n.value.length>0?n.value:o.assets||[]);async function l(){o.assetApiClient?.findAll&&(n.value=await o.assetApiClient.findAll())}function s(c){return u(c,"id")||u(c,"assetTag")||JSON.stringify(c)}function u(c,f){return String(c?.[f]||"")}function y(c){const f=u(c,"currentLocationCode"),A=u(c,"currentLocationKind");if(!f)return"Never scanned";if(m.isVirtualInventoryLocation({locationCode:f,locationKind:A})||m.isVirtualUserLocationCode(f))return`In transit - ${m.getVirtualUserCode(f)}`;const k=(o.locations||[]).find(g=>g.locationCode===f);return String(k?.name||f)}const d={props:o,loadedAssets:n,displayAssets:a,reload:l,getAssetKey:s,getAssetText:u,getDisplayLocation:y};return Object.defineProperty(d,"__isScriptSetup",{enumerable:!1,value:!0}),d}}),ce={class:"inventory-overview"},le={class:"inventory-overview__rows"},de=["onClick"],ue=["onClick"];function ve(r,t,o,n,a,l){return e.openBlock(),e.createElementBlock("div",ce,[e.createElementVNode("div",{class:"inventory-overview__header"},[t[0]||(t[0]=e.createElementVNode("div",null,"Assets",-1)),e.createElementVNode("button",{type:"button",onClick:n.reload},"Reload")]),e.createElementVNode("div",le,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(n.displayAssets,s=>(e.openBlock(),e.createElementBlock("button",{key:n.getAssetKey(s),class:"inventory-overview__row",type:"button",onClick:u=>r.$emit("selectAsset",s)},[e.createElementVNode("span",null,e.toDisplayString(n.getAssetText(s,"assetTag")),1),e.createElementVNode("span",null,e.toDisplayString(n.getAssetText(s,"name")),1),e.createElementVNode("span",{class:"inventory-overview__location",onClick:e.withModifiers(u=>r.$emit("selectLocation",n.getAssetText(s,"currentLocationCode")),["stop"])},e.toDisplayString(n.getDisplayLocation(s)),9,ue)],8,de))),128))])])}const S=E(ie,[["render",ve],["__file","/Users/donlee/Developer/qw.q.inventory/src/components/InventoryOverview.vue"]]),me=e.defineComponent({name:"inventory-asset-detail",__name:"InventoryAssetDetail",props:{movementApiClient:{type:Object,required:!1},asset:{type:null,required:!1}},setup(r,{expose:t}){t();const o=r,n=e.ref([]);async function a(){const d=l("assetTag");d&&o.movementApiClient?.findAll&&(n.value=await o.movementApiClient.findAll({assetTag:d}))}function l(d){return String(o.asset?.[d]||"")}function s(d){const c=d;return String(c.id||c.inventoryMovementCode||c.movedAt||JSON.stringify(d))}function u(d){const c=d;return`${c.fromLocationCode||"-"} -> ${c.toLocationCode||"-"}`}const y={props:o,history:n,loadHistory:a,getValue:l,getHistoryKey:s,getHistoryText:u};return Object.defineProperty(y,"__isScriptSetup",{enumerable:!1,value:!0}),y}}),ye={class:"inventory-asset-detail"},fe={key:0,class:"inventory-asset-detail__body"},_e={key:1,class:"inventory-asset-detail__empty"};function pe(r,t,o,n,a,l){return e.openBlock(),e.createElementBlock("div",ye,[o.asset?(e.openBlock(),e.createElementBlock("div",fe,[e.createElementVNode("h3",null,e.toDisplayString(n.getValue("assetTag")),1),e.createElementVNode("div",null,e.toDisplayString(n.getValue("name")),1),e.createElementVNode("div",null,e.toDisplayString(n.getValue("currentLocationCode")),1),e.createElementVNode("button",{type:"button",onClick:n.loadHistory},"Load History"),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(n.history,s=>(e.openBlock(),e.createElementBlock("div",{key:n.getHistoryKey(s),class:"inventory-asset-detail__history"},e.toDisplayString(n.getHistoryText(s)),1))),128))])):(e.openBlock(),e.createElementBlock("div",_e,"No asset selected"))])}const V=E(me,[["render",pe],["__file","/Users/donlee/Developer/qw.q.inventory/src/components/InventoryAssetDetail.vue"]]),ge=e.defineComponent({name:"inventory-location-detail",__name:"InventoryLocationDetail",props:{assetApiClient:{type:Object,required:!1},location:{type:null,required:!1}},setup(r,{expose:t}){t();const o=r,n=e.ref([]),a=e.computed(()=>typeof o.location=="string"?o.location:String(o.location?.locationCode||""));async function l(){a.value&&o.assetApiClient?.findAll&&(n.value=await o.assetApiClient.findAll({currentLocationCode:a.value}))}function s(d){const c=d;return String(c.id||c.assetTag||JSON.stringify(d))}function u(d){const c=d;return`${c.assetTag||""} ${c.name||""}`.trim()}const y={props:o,assets:n,locationCode:a,loadAssets:l,getAssetKey:s,getAssetText:u};return Object.defineProperty(y,"__isScriptSetup",{enumerable:!1,value:!0}),y}}),he={class:"inventory-location-detail"},Ee={class:"inventory-location-detail__header"},Ae=["disabled"];function ke(r,t,o,n,a,l){return e.openBlock(),e.createElementBlock("div",he,[e.createElementVNode("div",Ee,[e.createElementVNode("div",null,e.toDisplayString(n.locationCode||"No location selected"),1),e.createElementVNode("button",{type:"button",disabled:!n.locationCode,onClick:n.loadAssets},"Load Assets",8,Ae)]),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(n.assets,s=>(e.openBlock(),e.createElementBlock("div",{key:n.getAssetKey(s),class:"inventory-location-detail__asset"},e.toDisplayString(n.getAssetText(s)),1))),128))])}const O=E(ge,[["render",ke],["__file","/Users/donlee/Developer/qw.q.inventory/src/components/InventoryLocationDetail.vue"]]),Ce=e.defineComponent({name:"inventory-location-admin",__name:"InventoryLocationAdmin",props:{locations:{type:Array,required:!1}},emits:["saveLocation"],setup(r,{expose:t,emit:o}){t();const n=o,a=e.reactive({locationCode:"",locationType:"",name:""});function l(){n("saveLocation",{...a}),a.locationCode="",a.locationType="",a.name=""}function s(d){const c=d;return String(c.id||c.locationCode||JSON.stringify(d))}function u(d){const c=d;return`${c.locationCode||""} ${c.name||""}`.trim()}const y={emit:n,form:a,submit:l,getLocationKey:s,getLocationText:u};return Object.defineProperty(y,"__isScriptSetup",{enumerable:!1,value:!0}),y}}),Ne={class:"inventory-location-admin"};function Ie(r,t,o,n,a,l){return e.openBlock(),e.createElementBlock("div",Ne,[e.createElementVNode("form",{class:"inventory-location-admin__form",onSubmit:e.withModifiers(n.submit,["prevent"])},[e.withDirectives(e.createElementVNode("input",{"onUpdate:modelValue":t[0]||(t[0]=s=>n.form.locationCode=s),placeholder:"Location code"},null,512),[[e.vModelText,n.form.locationCode]]),e.withDirectives(e.createElementVNode("input",{"onUpdate:modelValue":t[1]||(t[1]=s=>n.form.name=s),placeholder:"Name"},null,512),[[e.vModelText,n.form.name]]),e.withDirectives(e.createElementVNode("input",{"onUpdate:modelValue":t[2]||(t[2]=s=>n.form.locationType=s),placeholder:"Type"},null,512),[[e.vModelText,n.form.locationType]]),t[3]||(t[3]=e.createElementVNode("button",{type:"submit"},"Save",-1))],32),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(o.locations,s=>(e.openBlock(),e.createElementBlock("div",{key:n.getLocationKey(s),class:"inventory-location-admin__row"},e.toDisplayString(n.getLocationText(s)),1))),128))])}const w=E(Ce,[["render",Ie],["__file","/Users/donlee/Developer/qw.q.inventory/src/components/InventoryLocationAdmin.vue"]]),Te=e.defineComponent({name:"q-inventory",__name:"QInventory",props:{assetApiClient:{type:Object,required:!1},locationApiClient:{type:Object,required:!1},movementApiClient:{type:Object,required:!1},assets:{type:Array,required:!1},currentUserCode:{type:String,required:!1},locations:{type:Array,required:!1}},emits:["moved","saveLocation","scan","selectAsset","selectLocation"],setup(r,{expose:t,emit:o}){t();const n=r,a=o,l=e.ref("scanner"),s=e.ref(null),u=e.ref(null),y=e.computed(()=>[{key:"scanner",label:"Scan"},{key:"overview",label:"Overview"},{key:"asset",label:"Asset"},{key:"location",label:"Location"},{key:"locations",label:"Locations"}]);function d(_){a("moved",_)}function c(_){a("scan",_)}function f(_){a("saveLocation",_)}function A(_){s.value=_,l.value="asset",a("selectAsset",_)}function k(_){u.value=_,l.value="location",a("selectLocation",_)}const g={props:n,emit:a,activeTab:l,selectedAsset:s,selectedLocation:u,tabs:y,onMoved:d,onScan:c,onSaveLocation:f,onSelectAsset:A,onSelectLocation:k,InventoryScanner:b,InventoryOverview:S,InventoryAssetDetail:V,InventoryLocationDetail:O,InventoryLocationAdmin:w};return Object.defineProperty(g,"__isScriptSetup",{enumerable:!1,value:!0}),g}}),Le={class:"q-inventory"},be={class:"q-inventory__toolbar"},Se=["onClick"];function Ve(r,t,o,n,a,l){return e.openBlock(),e.createElementBlock("div",Le,[e.createElementVNode("div",be,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(n.tabs,s=>(e.openBlock(),e.createElementBlock("button",{key:s.key,class:e.normalizeClass(["q-inventory__tab",{"q-inventory__tab--active":n.activeTab===s.key}]),type:"button",onClick:u=>n.activeTab=s.key},e.toDisplayString(s.label),11,Se))),128))]),e.withDirectives(e.createVNode(n.InventoryScanner,{"asset-api-client":o.assetApiClient,assets:o.assets,"current-user-code":o.currentUserCode,onMoved:n.onMoved,onScan:n.onScan},null,8,["asset-api-client","assets","current-user-code"]),[[e.vShow,n.activeTab==="scanner"]]),n.activeTab==="overview"?(e.openBlock(),e.createBlock(n.InventoryOverview,{key:0,"asset-api-client":o.assetApiClient,assets:o.assets,locations:o.locations,onSelectAsset:n.onSelectAsset,onSelectLocation:n.onSelectLocation},null,8,["asset-api-client","assets","locations"])):e.createCommentVNode("v-if",!0),n.activeTab==="asset"?(e.openBlock(),e.createBlock(n.InventoryAssetDetail,{key:1,"movement-api-client":o.movementApiClient,asset:n.selectedAsset},null,8,["movement-api-client","asset"])):e.createCommentVNode("v-if",!0),n.activeTab==="location"?(e.openBlock(),e.createBlock(n.InventoryLocationDetail,{key:2,"asset-api-client":o.assetApiClient,location:n.selectedLocation},null,8,["asset-api-client","location"])):e.createCommentVNode("v-if",!0),n.activeTab==="locations"?(e.openBlock(),e.createBlock(n.InventoryLocationAdmin,{key:3,locations:o.locations,onSaveLocation:n.onSaveLocation},null,8,["locations"])):e.createCommentVNode("v-if",!0)])}const B=E(Te,[["render",Ve],["__file","/Users/donlee/Developer/qw.q.inventory/src/components/QInventory.vue"]]);class N{constructor(t={}){this.axios=t.axios,this.authenticatorTokenProvider=t.authenticatorTokenProvider,this.baseURL=(t.baseURL||"").replace(/\/$/,""),this.movedBy=t.movedBy||"currentUser",this.qRepo=t.qRepo,this.tenantCode=t.tenantCode||"tenantCode",this.userTokenProvider=t.userTokenProvider}async get(t,o={}){const n=await this.getAuthHeaders();if(this.axios){const s=await this.axios.get(this.getUrl(t),{headers:n,params:o});return F(s.data)}const a=new URL(this.getUrl(t),Oe());Object.entries(o).forEach(([s,u])=>{typeof u<"u"&&u!==null&&u!==""&&a.searchParams.set(s,String(u))});const l=await fetch(this.getFetchUrl(a),{headers:n});return F(await l.json(),l)}async post(t,o={}){const n={"Content-Type":"application/json",...await this.getAuthHeaders()};if(this.axios){const l=await this.axios.post(this.getUrl(t),o,{headers:n});return L(l.data)}const a=await fetch(this.getUrl(t),{body:JSON.stringify(o),headers:n,method:"POST"});return L(await a.json(),a)}getUrl(t){return`${this.baseURL}/api/v1${t}`}getFetchUrl(t){return this.baseURL?t.toString():`${t.pathname}${t.search}`}withDefaults(t={}){return Re({...t,qRepo:t.qRepo||this.qRepo,tenantCode:t.tenantCode||this.tenantCode})}async getAuthHeaders(){const t={},o=await j(this.authenticatorTokenProvider),n=await j(this.userTokenProvider);return o&&(t["X-Q-Authenticator"]=o),n&&(t["X-Q-Inventory-User-Token"]=n),t}}async function j(r){return r?r():""}function L(r,t){const o=r,n=o?.err,a=o?.errors;if(t&&!t.ok||n?.hasError||a)throw new Error(we({data:o,err:n,errors:a,response:t}));return o}function F(r,t){const o=L(r,t);return Array.isArray(o?.data)?o.data:[]}function Oe(){return typeof window<"u"?window.location.origin:"http://localhost"}function we({data:r,err:t,errors:o,response:n}){const a=String(n?.status||t?.statusCode||t?.code||o?.name||r?.code||"REQUEST_ERROR"),l=Be(t?.message||o?.message||r?.message||"QInventory request failed");return`${a}: ${l}`}function Be(r){return Array.isArray(r)?r.join("; "):String(r)}function Re(r){return Object.fromEntries(Object.entries(r).filter(([,t])=>typeof t<"u"&&t!==null&&t!==""))}class Q extends N{constructor(t={}){super(t)}async findAll(t={}){return this.get("/qInventoryAsset",this.withDefaults(t))}async findOne(t){return this.get(`/qInventoryAsset/${encodeURIComponent(t)}`,this.withDefaults())}async saveOne(t){return this.post("/qInventoryAsset",this.withDefaults(t))}async move(t){const o=String(t.assetTag||""),n=t.movedBy||this.movedBy;return this.post(`/qInventoryAsset/${encodeURIComponent(o)}/move`,this.withDefaults({...t,movedBy:n}))}}class H extends N{constructor(t={}){super(t)}async findAll(t={}){return this.get("/qInventoryLocation",this.withDefaults(t))}async findOne(t){return this.get(`/qInventoryLocation/${encodeURIComponent(t)}`,this.withDefaults())}async saveOne(t){return this.post("/qInventoryLocation",this.withDefaults(t))}}class J extends N{constructor(t={}){super(t)}async findAll(t={}){const o=String(t.assetTag||"");if(!o)throw new Error("assetTag is required for movement findAll");const{assetTag:n,...a}=t;return this.get(`/qInventoryAsset/${encodeURIComponent(o)}/movements`,this.withDefaults(a))}}class De extends N{constructor(t={}){super(t)}async getBrowserToken(){return(await this.post("/qInventory/token",{clientAppId:"qInventoryBrowser",clientAppName:"qInventoryBrowser"})).data?.[0]}async requestLoginLink({email:t,tenantCode:o=this.tenantCode}){return(await this.post("/qInventory/login-link",{email:t,tenantCode:o})).data?.[0]}async verifyLoginToken(t){return(await this.post("/qInventory/login-token/verify",{loginToken:t})).data?.[0]}}class qe{constructor(t={}){this.assetRepo=new Q(t),this.locationRepo=new H(t),this.movementRepo=new J(t)}async findAll(t){return this.assetRepo.findAll(t)}async findOne(t){return this.assetRepo.findOne(t)}async saveOne(t){return this.assetRepo.saveOne(t)}async move(t){return this.assetRepo.move(t)}async findAssets(t){return this.assetRepo.findAll(t)}async findLocations(t){return this.locationRepo.findAll(t)}async findLocationAssets(t){return this.assetRepo.findAll({currentLocationCode:t})}async findAssetHistory(t){return this.movementRepo.findAll({assetTag:t})}async moveAsset(t){return this.assetRepo.move(t)}}function R(r){r.component("q-inventory",B),r.component("inventory-scanner",b),r.component("inventory-overview",S),r.component("inventory-asset-detail",V),r.component("inventory-location-detail",O),r.component("inventory-location-admin",w)}B.install=R;const Me={install:R};exports.InventoryAssetDetail=V;exports.InventoryAssetRepoAxios=Q;exports.InventoryAuthRepoAxios=De;exports.InventoryLocationAdmin=w;exports.InventoryLocationDetail=O;exports.InventoryLocationRepoAxios=H;exports.InventoryMovementRepoAxios=J;exports.InventoryOverview=S;exports.InventoryRepoAxios=qe;exports.InventoryRepoAxiosBase=N;exports.InventoryScanner=b;exports.QInventory=B;exports.default=Me;exports.install=R;Object.keys(m).forEach(r=>{r!=="default"&&!Object.prototype.hasOwnProperty.call(exports,r)&&Object.defineProperty(exports,r,{enumerable:!0,get:()=>m[r]})});
2
+ //# sourceMappingURL=q-inventory.min.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"q-inventory.min.cjs","sources":["../src/components/InventoryScanner.vue","../src/components/InventoryOverview.vue","../src/components/InventoryAssetDetail.vue","../src/components/InventoryLocationDetail.vue","../src/components/InventoryLocationAdmin.vue","../src/components/QInventory.vue","../src/models/inventoryAxiosBase.ts","../src/models/inventoryAssetRepoAxios.ts","../src/models/inventoryLocationRepoAxios.ts","../src/models/inventoryMovementRepoAxios.ts","../src/models/inventoryAuthRepoAxios.ts","../src/models/index.ts","../src/index.ts"],"sourcesContent":["<template>\n <div class=\"inventory-scanner\">\n <div class=\"inventory-scanner__mode\">\n <button\n class=\"inventory-scanner__mode-button\"\n :class=\"{ 'inventory-scanner__mode-button--active': mode === INVENTORY_MOVEMENT_TYPE.PICKUP }\"\n type=\"button\"\n @click=\"setMode(INVENTORY_MOVEMENT_TYPE.PICKUP)\"\n >\n Pickup\n </button>\n <button\n class=\"inventory-scanner__mode-button\"\n :class=\"{ 'inventory-scanner__mode-button--active': mode === INVENTORY_MOVEMENT_TYPE.DROPOFF }\"\n type=\"button\"\n @click=\"setMode(INVENTORY_MOVEMENT_TYPE.DROPOFF)\"\n >\n Drop-off\n </button>\n </div>\n <div class=\"inventory-scanner__state\">\n <div>Mode: {{ mode }}</div>\n <div>{{ locationLabel }}: {{ activeLocationCode || '-' }}</div>\n <div>Holder: {{ holderLocationCode || '-' }}</div>\n </div>\n <div class=\"inventory-scanner__manual\">\n <input\n v-model=\"manualQr\"\n class=\"inventory-scanner__input\"\n placeholder=\"Scan or enter QR text\"\n @keyup.enter=\"submitManualQr\"\n />\n <button type=\"button\" @click=\"submitManualQr\">Submit</button>\n </div>\n <div class=\"inventory-scanner__basket-header\">\n <div>\n <strong>My Basket</strong>\n <span>{{ basketItems.length }} on hand</span>\n </div>\n <button\n type=\"button\"\n :disabled=\"scanLog.length === 0\"\n @click=\"clearScanLog\"\n >\n Clear log\n </button>\n </div>\n <div class=\"inventory-scanner__basket\">\n <div\n v-if=\"basketItems.length === 0\"\n class=\"inventory-scanner__empty\"\n >\n No items on hand\n </div>\n <div\n v-for=\"item in basketItems\"\n :key=\"item.assetTag\"\n class=\"inventory-scanner__basket-item\"\n >\n <strong>{{ item.assetTag }}</strong>\n <small>{{ item.name || item.category || item.currentLocationCode }}</small>\n </div>\n </div>\n <div class=\"inventory-scanner__log\">\n <div\n v-for=\"item in scanLog\"\n :key=\"item.key\"\n class=\"inventory-scanner__log-item\"\n :class=\"{\n 'inventory-scanner__log-item--failed': item.status === 'FAILED',\n 'inventory-scanner__log-item--warning': item.status === 'WARNING',\n }\"\n >\n <div>\n <strong>{{ item.title }}</strong>\n <span>{{ item.status }}</span>\n </div>\n <small>{{ item.message }}</small>\n </div>\n </div>\n <div\n v-if=\"scanLog.length === 0\"\n class=\"inventory-scanner__log-empty\"\n >\n Scan log will appear here\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport {\n INVENTORY_LOCATION_KIND,\n INVENTORY_MOVEMENT_TYPE,\n getVirtualUserLocationCode,\n isLocationQr,\n parseInventoryQr,\n} from '@questwork/q-inventory-model'\nimport type { InventoryAssetApiClient, InventoryMovePayload, InventoryMoveResult, InventoryMoveWarning } from '../models/index.js'\n\ndefineOptions({\n name: 'inventory-scanner',\n})\n\ntype ScannerMode = typeof INVENTORY_MOVEMENT_TYPE.PICKUP | typeof INVENTORY_MOVEMENT_TYPE.DROPOFF\ntype ScanLogStatus = 'OK' | 'WARNING' | 'FAILED' | 'INFO'\n\ninterface BasketItem {\n assetTag: string\n category?: string\n currentLocationCode?: string\n name?: string\n}\n\ninterface ScanLogItem {\n key: string\n message: string\n status: ScanLogStatus\n title: string\n}\n\nconst props = defineProps<{\n assetApiClient?: InventoryAssetApiClient\n assets?: unknown[]\n currentUserCode?: string\n}>()\n\nconst emit = defineEmits<{\n moved: [payload: InventoryMovePayload]\n scan: [payload: { raw: string, parsed: unknown }]\n}>()\n\nconst activeLocationCode = ref('')\nconst basketItems = ref<BasketItem[]>([])\nconst manualQr = ref('')\nconst mode = ref<ScannerMode>(INVENTORY_MOVEMENT_TYPE.PICKUP)\nconst scanLog = ref<ScanLogItem[]>([])\n\nconst holderLocationCode = computed(() => getVirtualUserLocationCode(props.currentUserCode || 'currentUser'))\nconst locationLabel = computed(() => mode.value === INVENTORY_MOVEMENT_TYPE.PICKUP ? 'Source' : 'Destination')\n\nwatch(\n () => [props.assets, holderLocationCode.value],\n syncBasketFromAssets,\n { deep: true, immediate: true },\n)\n\nfunction setMode(nextMode: ScannerMode) {\n mode.value = nextMode\n activeLocationCode.value = ''\n addLog({\n message: `Mode changed to ${nextMode}`,\n status: 'INFO',\n title: 'Mode',\n })\n}\n\nasync function submitManualQr() {\n const value = manualQr.value.trim()\n if (!value) return\n manualQr.value = ''\n await handleQr(value)\n}\n\nasync function handleQr(value: string) {\n const parsed = parseInventoryQr(value)\n emit('scan', { raw: value, parsed })\n\n if (isLocationQr(value)) {\n activeLocationCode.value = parsed.code\n addLog({\n message: `${locationLabel.value} set to ${parsed.code}`,\n status: 'INFO',\n title: 'Location',\n })\n return\n }\n\n if (!activeLocationCode.value) {\n addLog({\n message: `Scan ${locationLabel.value.toLowerCase()} location first`,\n status: 'FAILED',\n title: parsed.code,\n })\n return\n }\n\n const payload = getMovePayload(parsed.code)\n try {\n if (props.assetApiClient?.move) {\n const result = await props.assetApiClient.move(payload)\n const warnings = getMoveWarnings(result)\n emit('moved', payload)\n applyBasketMove(payload)\n if (warnings.length) {\n addLog({\n message: formatWarnings(warnings),\n status: 'WARNING',\n title: parsed.code,\n })\n return\n }\n } else {\n emit('moved', payload)\n applyBasketMove(payload)\n }\n addLog({\n message: `${payload.fromLocationCode || '-'} -> ${payload.toLocationCode}`,\n status: 'OK',\n title: parsed.code,\n })\n } catch (err) {\n addLog({\n message: getErrorMessage(err),\n status: 'FAILED',\n title: parsed.code,\n })\n }\n}\n\nfunction getMovePayload(assetTag: string): InventoryMovePayload {\n if (mode.value === INVENTORY_MOVEMENT_TYPE.PICKUP) {\n return {\n assetTag,\n fromLocationCode: activeLocationCode.value,\n fromLocationKind: INVENTORY_LOCATION_KIND.REGISTERED,\n movementType: INVENTORY_MOVEMENT_TYPE.PICKUP,\n toLocationCode: holderLocationCode.value,\n toLocationKind: INVENTORY_LOCATION_KIND.VIRTUAL,\n }\n }\n return {\n assetTag,\n fromLocationCode: holderLocationCode.value,\n fromLocationKind: INVENTORY_LOCATION_KIND.VIRTUAL,\n movementType: INVENTORY_MOVEMENT_TYPE.DROPOFF,\n toLocationCode: activeLocationCode.value,\n toLocationKind: INVENTORY_LOCATION_KIND.REGISTERED,\n }\n}\n\nfunction applyBasketMove(payload: InventoryMovePayload) {\n if (payload.toLocationCode === holderLocationCode.value) {\n upsertBasketItem({\n assetTag: payload.assetTag,\n currentLocationCode: holderLocationCode.value,\n })\n return\n }\n basketItems.value = basketItems.value.filter((item) => item.assetTag !== payload.assetTag)\n}\n\nfunction upsertBasketItem(item: BasketItem) {\n const index = basketItems.value.findIndex((basketItem) => basketItem.assetTag === item.assetTag)\n if (index >= 0) {\n basketItems.value[index] = {\n ...basketItems.value[index],\n ...item,\n }\n return\n }\n basketItems.value.unshift(item)\n}\n\nfunction syncBasketFromAssets() {\n basketItems.value = (props.assets || [])\n .map(toBasketItem)\n .filter((item): item is BasketItem => !!item && item.currentLocationCode === holderLocationCode.value)\n}\n\nfunction toBasketItem(asset: unknown): BasketItem | null {\n const item = asset as Record<string, unknown>\n const assetTag = getString(item.assetTag)\n if (!assetTag) {\n return null\n }\n return {\n assetTag,\n category: getString(item.category),\n currentLocationCode: getString(item.currentLocationCode),\n name: getString(item.name),\n }\n}\n\nfunction addLog({ message, status, title }: Omit<ScanLogItem, 'key'>) {\n scanLog.value.unshift({\n key: `${Date.now()}-${Math.random()}`,\n message,\n status,\n title,\n })\n scanLog.value = scanLog.value.slice(0, 30)\n}\n\nfunction getString(value: unknown) {\n return typeof value === 'string' ? value : ''\n}\n\nfunction getErrorMessage(err: unknown) {\n return err instanceof Error ? err.message : String(err)\n}\n\nfunction getMoveWarnings(result: unknown) {\n const response = result as { data?: InventoryMoveResult[] }\n return response?.data?.[0]?.warnings || []\n}\n\nfunction formatWarnings(warnings: InventoryMoveWarning[]) {\n return warnings.map((warning) => `${warning.code}: ${warning.message}`).join('; ')\n}\n\nfunction clearScanLog() {\n scanLog.value = []\n}\n</script>\n","<template>\n <div class=\"inventory-overview\">\n <div class=\"inventory-overview__header\">\n <div>Assets</div>\n <button type=\"button\" @click=\"reload\">Reload</button>\n </div>\n <div class=\"inventory-overview__rows\">\n <button\n v-for=\"asset in displayAssets\"\n :key=\"getAssetKey(asset)\"\n class=\"inventory-overview__row\"\n type=\"button\"\n @click=\"$emit('selectAsset', asset)\"\n >\n <span>{{ getAssetText(asset, 'assetTag') }}</span>\n <span>{{ getAssetText(asset, 'name') }}</span>\n <span\n class=\"inventory-overview__location\"\n @click.stop=\"$emit('selectLocation', getAssetText(asset, 'currentLocationCode'))\"\n >\n {{ getDisplayLocation(asset) }}\n </span>\n </button>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport {\n getVirtualUserCode,\n isVirtualInventoryLocation,\n isVirtualUserLocationCode,\n} from '@questwork/q-inventory-model'\nimport type { InventoryAssetApiClient } from '../models/index.js'\n\ndefineOptions({\n name: 'inventory-overview',\n})\n\nconst props = defineProps<{\n assetApiClient?: InventoryAssetApiClient\n assets?: unknown[]\n locations?: unknown[]\n}>()\n\ndefineEmits<{\n selectAsset: [payload: unknown]\n selectLocation: [payload: unknown]\n}>()\n\nconst loadedAssets = ref<unknown[]>([])\nconst displayAssets = computed(() => loadedAssets.value.length > 0 ? loadedAssets.value : (props.assets || []))\n\nasync function reload() {\n if (props.assetApiClient?.findAll) {\n loadedAssets.value = await props.assetApiClient.findAll()\n }\n}\n\nfunction getAssetKey(asset: unknown) {\n return getAssetText(asset, 'id') || getAssetText(asset, 'assetTag') || JSON.stringify(asset)\n}\n\nfunction getAssetText(asset: unknown, key: string) {\n return String((asset as Record<string, unknown>)?.[key] || '')\n}\n\nfunction getDisplayLocation(asset: unknown) {\n const locationCode = getAssetText(asset, 'currentLocationCode')\n const locationKind = getAssetText(asset, 'currentLocationKind')\n if (!locationCode) return 'Never scanned'\n if (isVirtualInventoryLocation({ locationCode, locationKind }) || isVirtualUserLocationCode(locationCode)) {\n return `In transit - ${getVirtualUserCode(locationCode)}`\n }\n const location = (props.locations || []).find((item) => {\n return (item as Record<string, unknown>).locationCode === locationCode\n }) as Record<string, unknown> | undefined\n return String(location?.name || locationCode)\n}\n</script>\n","<template>\n <div class=\"inventory-asset-detail\">\n <div v-if=\"asset\" class=\"inventory-asset-detail__body\">\n <h3>{{ getValue('assetTag') }}</h3>\n <div>{{ getValue('name') }}</div>\n <div>{{ getValue('currentLocationCode') }}</div>\n <button type=\"button\" @click=\"loadHistory\">Load History</button>\n <div\n v-for=\"item in history\"\n :key=\"getHistoryKey(item)\"\n class=\"inventory-asset-detail__history\"\n >\n {{ getHistoryText(item) }}\n </div>\n </div>\n <div v-else class=\"inventory-asset-detail__empty\">No asset selected</div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport type { InventoryMovementApiClient } from '../models/index.js'\n\ndefineOptions({\n name: 'inventory-asset-detail',\n})\n\nconst props = defineProps<{\n movementApiClient?: InventoryMovementApiClient\n asset?: unknown\n}>()\n\nconst history = ref<unknown[]>([])\n\nasync function loadHistory() {\n const assetTag = getValue('assetTag')\n if (assetTag && props.movementApiClient?.findAll) {\n history.value = await props.movementApiClient.findAll({ assetTag })\n }\n}\n\nfunction getValue(key: string) {\n return String((props.asset as Record<string, unknown>)?.[key] || '')\n}\n\nfunction getHistoryKey(item: unknown) {\n const data = item as Record<string, unknown>\n return String(data.id || data.inventoryMovementCode || data.movedAt || JSON.stringify(item))\n}\n\nfunction getHistoryText(item: unknown) {\n const data = item as Record<string, unknown>\n return `${data.fromLocationCode || '-'} -> ${data.toLocationCode || '-'}`\n}\n</script>\n","<template>\n <div class=\"inventory-location-detail\">\n <div class=\"inventory-location-detail__header\">\n <div>{{ locationCode || 'No location selected' }}</div>\n <button type=\"button\" :disabled=\"!locationCode\" @click=\"loadAssets\">Load Assets</button>\n </div>\n <div\n v-for=\"asset in assets\"\n :key=\"getAssetKey(asset)\"\n class=\"inventory-location-detail__asset\"\n >\n {{ getAssetText(asset) }}\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport type { InventoryAssetApiClient } from '../models/index.js'\n\ndefineOptions({\n name: 'inventory-location-detail',\n})\n\nconst props = defineProps<{\n assetApiClient?: InventoryAssetApiClient\n location?: unknown\n}>()\n\nconst assets = ref<unknown[]>([])\nconst locationCode = computed(() => {\n if (typeof props.location === 'string') return props.location\n return String((props.location as Record<string, unknown>)?.locationCode || '')\n})\n\nasync function loadAssets() {\n if (locationCode.value && props.assetApiClient?.findAll) {\n assets.value = await props.assetApiClient.findAll({ currentLocationCode: locationCode.value })\n }\n}\n\nfunction getAssetKey(asset: unknown) {\n const data = asset as Record<string, unknown>\n return String(data.id || data.assetTag || JSON.stringify(asset))\n}\n\nfunction getAssetText(asset: unknown) {\n const data = asset as Record<string, unknown>\n return `${data.assetTag || ''} ${data.name || ''}`.trim()\n}\n</script>\n","<template>\n <div class=\"inventory-location-admin\">\n <form class=\"inventory-location-admin__form\" @submit.prevent=\"submit\">\n <input v-model=\"form.locationCode\" placeholder=\"Location code\" />\n <input v-model=\"form.name\" placeholder=\"Name\" />\n <input v-model=\"form.locationType\" placeholder=\"Type\" />\n <button type=\"submit\">Save</button>\n </form>\n <div\n v-for=\"location in locations\"\n :key=\"getLocationKey(location)\"\n class=\"inventory-location-admin__row\"\n >\n {{ getLocationText(location) }}\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { reactive } from 'vue'\n\ndefineOptions({\n name: 'inventory-location-admin',\n})\n\ndefineProps<{\n locations?: unknown[]\n}>()\n\nconst emit = defineEmits<{\n saveLocation: [payload: Record<string, string>]\n}>()\n\nconst form = reactive({\n locationCode: '',\n locationType: '',\n name: '',\n})\n\nfunction submit() {\n emit('saveLocation', { ...form })\n form.locationCode = ''\n form.locationType = ''\n form.name = ''\n}\n\nfunction getLocationKey(location: unknown) {\n const data = location as Record<string, unknown>\n return String(data.id || data.locationCode || JSON.stringify(location))\n}\n\nfunction getLocationText(location: unknown) {\n const data = location as Record<string, unknown>\n return `${data.locationCode || ''} ${data.name || ''}`.trim()\n}\n</script>\n","<template>\n <div class=\"q-inventory\">\n <div class=\"q-inventory__toolbar\">\n <button\n v-for=\"item in tabs\"\n :key=\"item.key\"\n class=\"q-inventory__tab\"\n :class=\"{ 'q-inventory__tab--active': activeTab === item.key }\"\n type=\"button\"\n @click=\"activeTab = item.key\"\n >\n {{ item.label }}\n </button>\n </div>\n <inventory-scanner\n v-show=\"activeTab === 'scanner'\"\n :asset-api-client=\"assetApiClient\"\n :assets=\"assets\"\n :current-user-code=\"currentUserCode\"\n @moved=\"onMoved\"\n @scan=\"onScan\"\n />\n <inventory-overview\n v-if=\"activeTab === 'overview'\"\n :asset-api-client=\"assetApiClient\"\n :assets=\"assets\"\n :locations=\"locations\"\n @select-asset=\"onSelectAsset\"\n @select-location=\"onSelectLocation\"\n />\n <inventory-asset-detail\n v-if=\"activeTab === 'asset'\"\n :movement-api-client=\"movementApiClient\"\n :asset=\"selectedAsset\"\n />\n <inventory-location-detail\n v-if=\"activeTab === 'location'\"\n :asset-api-client=\"assetApiClient\"\n :location=\"selectedLocation\"\n />\n <inventory-location-admin\n v-if=\"activeTab === 'locations'\"\n :locations=\"locations\"\n @save-location=\"onSaveLocation\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport InventoryScanner from './InventoryScanner.vue'\nimport InventoryOverview from './InventoryOverview.vue'\nimport InventoryAssetDetail from './InventoryAssetDetail.vue'\nimport InventoryLocationDetail from './InventoryLocationDetail.vue'\nimport InventoryLocationAdmin from './InventoryLocationAdmin.vue'\nimport type {\n InventoryAssetApiClient,\n InventoryLocationApiClient,\n InventoryMovementApiClient,\n} from '../models/index.js'\n\ndefineOptions({\n name: 'q-inventory',\n})\n\nconst props = defineProps<{\n assetApiClient?: InventoryAssetApiClient\n locationApiClient?: InventoryLocationApiClient\n movementApiClient?: InventoryMovementApiClient\n assets?: unknown[]\n currentUserCode?: string\n locations?: unknown[]\n}>()\n\nconst emit = defineEmits<{\n moved: [payload: unknown]\n saveLocation: [payload: unknown]\n scan: [payload: unknown]\n selectAsset: [payload: unknown]\n selectLocation: [payload: unknown]\n}>()\n\nconst activeTab = ref('scanner')\nconst selectedAsset = ref<unknown>(null)\nconst selectedLocation = ref<unknown>(null)\nconst tabs = computed(() => [\n { key: 'scanner', label: 'Scan' },\n { key: 'overview', label: 'Overview' },\n { key: 'asset', label: 'Asset' },\n { key: 'location', label: 'Location' },\n { key: 'locations', label: 'Locations' },\n])\n\nfunction onMoved(payload: unknown) {\n emit('moved', payload)\n}\n\nfunction onScan(payload: unknown) {\n emit('scan', payload)\n}\n\nfunction onSaveLocation(payload: unknown) {\n emit('saveLocation', payload)\n}\n\nfunction onSelectAsset(payload: unknown) {\n selectedAsset.value = payload\n activeTab.value = 'asset'\n emit('selectAsset', payload)\n}\n\nfunction onSelectLocation(payload: unknown) {\n selectedLocation.value = payload\n activeTab.value = 'location'\n emit('selectLocation', payload)\n}\n</script>\n","export interface InventoryAxiosLike {\n get: (url: string, config?: { headers?: Record<string, string>, params?: Record<string, unknown> }) => Promise<{ data: unknown }>\n post: (url: string, body?: Record<string, unknown>, config?: { headers?: Record<string, string> }) => Promise<{ data: unknown }>\n}\n\nexport interface InventoryRepoAxiosOptions {\n axios?: InventoryAxiosLike\n authenticatorTokenProvider?: () => Promise<string> | string\n baseURL?: string\n movedBy?: string\n qRepo?: string\n tenantCode?: string\n userTokenProvider?: () => Promise<string> | string\n}\n\nexport abstract class InventoryRepoAxiosBase {\n axios?: InventoryAxiosLike\n authenticatorTokenProvider?: () => Promise<string> | string\n baseURL: string\n movedBy: string\n qRepo?: string\n tenantCode: string\n userTokenProvider?: () => Promise<string> | string\n\n constructor(options: InventoryRepoAxiosOptions = {}) {\n this.axios = options.axios\n this.authenticatorTokenProvider = options.authenticatorTokenProvider\n this.baseURL = (options.baseURL || '').replace(/\\/$/, '')\n this.movedBy = options.movedBy || 'currentUser'\n this.qRepo = options.qRepo\n this.tenantCode = options.tenantCode || 'tenantCode'\n this.userTokenProvider = options.userTokenProvider\n }\n\n protected async get(path: string, query: Record<string, unknown> = {}) {\n const headers = await this.getAuthHeaders()\n if (this.axios) {\n const response = await this.axios.get(this.getUrl(path), { headers, params: query })\n return unwrapQSystemData(response.data)\n }\n const url = new URL(this.getUrl(path), getUrlBase())\n Object.entries(query).forEach(([key, value]) => {\n if (typeof value !== 'undefined' && value !== null && value !== '') {\n url.searchParams.set(key, String(value))\n }\n })\n const response = await fetch(this.getFetchUrl(url), { headers })\n return unwrapQSystemData(await response.json(), response)\n }\n\n protected async post(path: string, body: Record<string, unknown> = {}) {\n const headers = {\n 'Content-Type': 'application/json',\n ...await this.getAuthHeaders(),\n }\n if (this.axios) {\n const response = await this.axios.post(this.getUrl(path), body, { headers })\n return unwrapQSystemResponse(response.data)\n }\n const response = await fetch(this.getUrl(path), {\n body: JSON.stringify(body),\n headers,\n method: 'POST',\n })\n return unwrapQSystemResponse(await response.json(), response)\n }\n\n protected getUrl(path: string) {\n return `${this.baseURL}/api/v1${path}`\n }\n\n protected getFetchUrl(url: URL) {\n return this.baseURL ? url.toString() : `${url.pathname}${url.search}`\n }\n\n protected withDefaults(obj: Record<string, unknown> = {}) {\n return removeEmptyValues({\n ...obj,\n qRepo: obj.qRepo || this.qRepo,\n tenantCode: obj.tenantCode || this.tenantCode,\n })\n }\n\n private async getAuthHeaders() {\n const headers: Record<string, string> = {}\n const authenticatorToken = await resolveTokenProvider(this.authenticatorTokenProvider)\n const userToken = await resolveTokenProvider(this.userTokenProvider)\n if (authenticatorToken) {\n headers['X-Q-Authenticator'] = authenticatorToken\n }\n if (userToken) {\n headers['X-Q-Inventory-User-Token'] = userToken\n }\n return headers\n }\n}\n\nasync function resolveTokenProvider(provider?: () => Promise<string> | string) {\n if (!provider) {\n return ''\n }\n return provider()\n}\n\nfunction unwrapQSystemResponse(json: unknown, response?: Response) {\n const data = json as Record<string, unknown>\n const err = data?.err as Record<string, unknown> | undefined\n const errors = data?.errors as Record<string, unknown> | undefined\n if ((response && !response.ok) || err?.hasError || errors) {\n throw new Error(getResponseErrorMessage({ data, err, errors, response }))\n }\n return data\n}\n\nfunction unwrapQSystemData(json: unknown, response?: Response): unknown[] {\n const data = unwrapQSystemResponse(json, response)\n return Array.isArray(data?.data) ? data.data : []\n}\n\nfunction getUrlBase() {\n if (typeof window !== 'undefined') {\n return window.location.origin\n }\n return 'http://localhost'\n}\n\nfunction getResponseErrorMessage({ data, err, errors, response }: {\n data: Record<string, unknown>\n err?: Record<string, unknown>\n errors?: Record<string, unknown>\n response?: Response\n}) {\n const code = String(response?.status || err?.statusCode || err?.code || errors?.name || data?.code || 'REQUEST_ERROR')\n const message = formatErrorMessage(err?.message || errors?.message || data?.message || 'QInventory request failed')\n return `${code}: ${message}`\n}\n\nfunction formatErrorMessage(value: unknown) {\n if (Array.isArray(value)) {\n return value.join('; ')\n }\n return String(value)\n}\n\nfunction removeEmptyValues(obj: Record<string, unknown>) {\n return Object.fromEntries(\n Object.entries(obj).filter(([, value]) => typeof value !== 'undefined' && value !== null && value !== ''),\n )\n}\n","import { InventoryRepoAxiosBase, type InventoryRepoAxiosOptions } from './inventoryAxiosBase.js'\nimport type { InventoryMovePayload } from './index.js'\n\nexport interface InventoryAssetFindAllQuery extends Record<string, unknown> {\n assetTag?: string\n assetTags?: string[]\n category?: string\n currentLocationCode?: string\n currentLocationKind?: string\n currentLocationType?: string\n}\n\nexport class InventoryAssetRepoAxios extends InventoryRepoAxiosBase {\n constructor(options: InventoryRepoAxiosOptions = {}) {\n super(options)\n }\n\n async findAll(query: InventoryAssetFindAllQuery = {}) {\n return this.get('/qInventoryAsset', this.withDefaults(query))\n }\n\n async findOne(assetTag: string) {\n return this.get(`/qInventoryAsset/${encodeURIComponent(assetTag)}`, this.withDefaults())\n }\n\n async saveOne(doc: Record<string, unknown>) {\n return this.post('/qInventoryAsset', this.withDefaults(doc))\n }\n\n async move(payload: InventoryMovePayload) {\n const assetTag = String(payload.assetTag || '')\n const movedBy = payload.movedBy || this.movedBy\n return this.post(`/qInventoryAsset/${encodeURIComponent(assetTag)}/move`, this.withDefaults({\n ...payload,\n movedBy,\n }))\n }\n}\n","import { InventoryRepoAxiosBase, type InventoryRepoAxiosOptions } from './inventoryAxiosBase.js'\n\nexport interface InventoryLocationFindAllQuery extends Record<string, unknown> {\n locationCode?: string\n locationType?: string\n parentLocationCode?: string\n}\n\nexport class InventoryLocationRepoAxios extends InventoryRepoAxiosBase {\n constructor(options: InventoryRepoAxiosOptions = {}) {\n super(options)\n }\n\n async findAll(query: InventoryLocationFindAllQuery = {}) {\n return this.get('/qInventoryLocation', this.withDefaults(query))\n }\n\n async findOne(locationCode: string) {\n return this.get(`/qInventoryLocation/${encodeURIComponent(locationCode)}`, this.withDefaults())\n }\n\n async saveOne(doc: Record<string, unknown>) {\n return this.post('/qInventoryLocation', this.withDefaults(doc))\n }\n}\n","import { InventoryRepoAxiosBase, type InventoryRepoAxiosOptions } from './inventoryAxiosBase.js'\n\nexport interface InventoryMovementFindAllQuery extends Record<string, unknown> {\n assetTag?: string\n fromLocationCode?: string\n toLocationCode?: string\n movedBy?: string\n movementType?: string\n}\n\nexport class InventoryMovementRepoAxios extends InventoryRepoAxiosBase {\n constructor(options: InventoryRepoAxiosOptions = {}) {\n super(options)\n }\n\n async findAll(query: InventoryMovementFindAllQuery = {}) {\n const assetTag = String(query.assetTag || '')\n if (!assetTag) {\n throw new Error('assetTag is required for movement findAll')\n }\n const { assetTag: _omit, ...rest } = query\n return this.get(`/qInventoryAsset/${encodeURIComponent(assetTag)}/movements`, this.withDefaults(rest))\n }\n}\n","import { InventoryRepoAxiosBase, type InventoryRepoAxiosOptions } from './inventoryAxiosBase.js'\n\nexport interface InventoryTokenResult {\n token: string\n tokenExpiry: number\n}\n\nexport interface InventoryLoginLinkResult {\n email: string\n loginUrl: string\n sent: boolean\n}\n\nexport interface InventoryUserTokenResult {\n email: string\n tenantCode: string\n userCode: string\n userToken: string\n}\n\nexport class InventoryAuthRepoAxios extends InventoryRepoAxiosBase {\n constructor(options: InventoryRepoAxiosOptions = {}) {\n super(options)\n }\n\n async getBrowserToken() {\n const result = await this.post('/qInventory/token', {\n clientAppId: 'qInventoryBrowser',\n clientAppName: 'qInventoryBrowser',\n }) as { data?: InventoryTokenResult[] }\n return result.data?.[0]\n }\n\n async requestLoginLink({ email, tenantCode = this.tenantCode }: { email: string, tenantCode?: string }) {\n const result = await this.post('/qInventory/login-link', {\n email,\n tenantCode,\n }) as { data?: InventoryLoginLinkResult[] }\n return result.data?.[0]\n }\n\n async verifyLoginToken(loginToken: string) {\n const result = await this.post('/qInventory/login-token/verify', {\n loginToken,\n }) as { data?: InventoryUserTokenResult[] }\n return result.data?.[0]\n }\n}\n","import { InventoryAssetRepoAxios } from './inventoryAssetRepoAxios.js'\nimport { InventoryLocationRepoAxios } from './inventoryLocationRepoAxios.js'\nimport { InventoryMovementRepoAxios } from './inventoryMovementRepoAxios.js'\nimport type { InventoryRepoAxiosOptions } from './inventoryAxiosBase.js'\n\nexport interface InventoryAssetApiClient {\n findAll?: (query?: Record<string, unknown>) => Promise<unknown[]>\n findOne?: (id: string) => Promise<unknown[]>\n saveOne?: (doc: Record<string, unknown>) => Promise<unknown>\n move?: (payload: InventoryMovePayload) => Promise<unknown>\n}\n\nexport interface InventoryLocationApiClient {\n findAll?: (query?: Record<string, unknown>) => Promise<unknown[]>\n findOne?: (id: string) => Promise<unknown[]>\n saveOne?: (doc: Record<string, unknown>) => Promise<unknown>\n}\n\nexport interface InventoryMovementApiClient {\n findAll?: (query?: Record<string, unknown>) => Promise<unknown[]>\n}\n\n// Backward-compatible union type for consumers that still expect one object\nexport type InventoryApiClient = InventoryAssetApiClient & InventoryLocationApiClient & InventoryMovementApiClient\n\nexport interface InventoryMovePayload {\n assetTag: string\n fromLocationCode?: string\n fromLocationKind?: string\n movedBy?: string\n toLocationCode: string\n toLocationKind?: string\n movementType?: string\n}\n\nexport interface InventoryMoveWarning {\n actualLocationCode?: string\n assetTag?: string\n code: string\n message: string\n requestedFromLocationCode?: string\n requestedFromLocationKind?: string\n}\n\nexport interface InventoryMoveResult {\n warnings?: InventoryMoveWarning[]\n}\n\nexport interface InventoryDisplayLocation {\n code: string\n label: string\n type?: string\n}\n\nexport * from './inventoryAxiosBase.js'\nexport * from './inventoryAssetRepoAxios.js'\nexport * from './inventoryAuthRepoAxios.js'\nexport * from './inventoryLocationRepoAxios.js'\nexport * from './inventoryMovementRepoAxios.js'\n\n// Backward-compat wrapper so existing callers don't break immediately.\n// Internally it delegates to the focused repos above.\nexport class InventoryRepoAxios implements InventoryApiClient {\n private assetRepo: InventoryAssetRepoAxios\n private locationRepo: InventoryLocationRepoAxios\n private movementRepo: InventoryMovementRepoAxios\n\n constructor(options: InventoryRepoAxiosOptions = {}) {\n this.assetRepo = new InventoryAssetRepoAxios(options)\n this.locationRepo = new InventoryLocationRepoAxios(options)\n this.movementRepo = new InventoryMovementRepoAxios(options)\n }\n\n async findAll(query?: Record<string, unknown>) {\n return this.assetRepo.findAll(query)\n }\n\n async findOne(id: string) {\n return this.assetRepo.findOne(id)\n }\n\n async saveOne(doc: Record<string, unknown>) {\n return this.assetRepo.saveOne(doc)\n }\n\n async move(payload: InventoryMovePayload) {\n return this.assetRepo.move(payload)\n }\n\n // Legacy alias for asset findAll\n async findAssets(query?: Record<string, unknown>) {\n return this.assetRepo.findAll(query)\n }\n\n // Legacy alias for location findAll\n async findLocations(query?: Record<string, unknown>) {\n return this.locationRepo.findAll(query)\n }\n\n // Legacy alias — location assets are just assets filtered by currentLocationCode\n async findLocationAssets(locationCode: string) {\n return this.assetRepo.findAll({ currentLocationCode: locationCode })\n }\n\n // Legacy alias for movement history\n async findAssetHistory(assetTag: string) {\n return this.movementRepo.findAll({ assetTag })\n }\n\n // Legacy alias for move\n async moveAsset(payload: InventoryMovePayload) {\n return this.assetRepo.move(payload)\n }\n}\n","import type { App } from 'vue'\nimport QInventory from './components/QInventory.vue'\nimport InventoryScanner from './components/InventoryScanner.vue'\nimport InventoryOverview from './components/InventoryOverview.vue'\nimport InventoryAssetDetail from './components/InventoryAssetDetail.vue'\nimport InventoryLocationDetail from './components/InventoryLocationDetail.vue'\nimport InventoryLocationAdmin from './components/InventoryLocationAdmin.vue'\nimport './styles/index.scss'\n\nexport * from '@questwork/q-inventory-model'\nexport * from './models/index.js'\n\nfunction install(app: App) {\n app.component('q-inventory', QInventory)\n app.component('inventory-scanner', InventoryScanner)\n app.component('inventory-overview', InventoryOverview)\n app.component('inventory-asset-detail', InventoryAssetDetail)\n app.component('inventory-location-detail', InventoryLocationDetail)\n app.component('inventory-location-admin', InventoryLocationAdmin)\n}\n\nQInventory.install = install\n\nexport {\n install,\n InventoryAssetDetail,\n InventoryLocationAdmin,\n InventoryLocationDetail,\n InventoryOverview,\n InventoryScanner,\n QInventory,\n}\n\nexport default {\n install,\n}\n"],"names":["props","__props","emit","__emit","activeLocationCode","ref","basketItems","manualQr","mode","INVENTORY_MOVEMENT_TYPE","scanLog","holderLocationCode","computed","getVirtualUserLocationCode","locationLabel","watch","syncBasketFromAssets","setMode","nextMode","addLog","submitManualQr","value","handleQr","parsed","parseInventoryQr","isLocationQr","payload","getMovePayload","result","warnings","getMoveWarnings","applyBasketMove","formatWarnings","err","getErrorMessage","assetTag","INVENTORY_LOCATION_KIND","upsertBasketItem","item","index","basketItem","toBasketItem","asset","getString","message","status","title","warning","clearScanLog","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_7","_hoisted_9","_openBlock","_createElementBlock","_createElementVNode","_normalizeClass","$setup","_cache","$event","_toDisplayString","_withDirectives","_withKeys","_hoisted_6","_hoisted_8","_createCommentVNode","_Fragment","_renderList","_hoisted_10","loadedAssets","displayAssets","reload","getAssetKey","getAssetText","key","getDisplayLocation","locationCode","locationKind","isVirtualInventoryLocation","isVirtualUserLocationCode","getVirtualUserCode","location","_ctx","_withModifiers","history","loadHistory","getValue","getHistoryKey","data","getHistoryText","$props","assets","loadAssets","form","reactive","submit","getLocationKey","getLocationText","_vModelText","activeTab","selectedAsset","selectedLocation","tabs","onMoved","onScan","onSaveLocation","onSelectAsset","onSelectLocation","_createVNode","_createBlock","InventoryRepoAxiosBase","options","path","query","headers","response","unwrapQSystemData","url","getUrlBase","body","unwrapQSystemResponse","obj","removeEmptyValues","authenticatorToken","resolveTokenProvider","userToken","provider","json","errors","getResponseErrorMessage","code","formatErrorMessage","InventoryAssetRepoAxios","doc","movedBy","InventoryLocationRepoAxios","InventoryMovementRepoAxios","_omit","rest","InventoryAuthRepoAxios","email","tenantCode","loginToken","InventoryRepoAxios","id","install","app","QInventory","InventoryScanner","InventoryOverview","InventoryAssetDetail","InventoryLocationDetail","InventoryLocationAdmin"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ .q-inventory,.inventory-scanner,.inventory-overview,.inventory-asset-detail,.inventory-location-detail,.inventory-location-admin{box-sizing:border-box;color:#202124;font-family:Arial,sans-serif}.q-inventory{min-height:100%;background:#f6f7f9}.q-inventory__toolbar,.inventory-scanner__mode,.inventory-scanner__manual,.inventory-overview__header,.inventory-location-detail__header,.inventory-location-admin__form{display:flex;gap:8px;padding:12px}.q-inventory__tab,.inventory-scanner__mode-button,button{min-height:36px;border:1px solid #ccd1d8;border-radius:4px;background:#fff;color:#202124;cursor:pointer;padding:0 12px}.q-inventory__tab--active,.inventory-scanner__mode-button--active{border-color:#1769aa;background:#1769aa;color:#fff}.inventory-scanner__state,.inventory-scanner__basket-header,.inventory-scanner__basket,.inventory-scanner__log,.inventory-scanner__log-empty,.inventory-overview__rows,.inventory-asset-detail__body,.inventory-asset-detail__empty,.inventory-location-detail__asset,.inventory-location-admin__row{padding:12px}.inventory-scanner__basket-header{align-items:center;display:flex;justify-content:space-between;gap:8px;border-top:1px solid #e0e3e7;border-bottom:1px solid #e0e3e7;background:#fff;font-size:13px}.inventory-scanner__basket-header div{display:grid;gap:2px}.inventory-scanner__basket-header span,.inventory-scanner__empty,.inventory-scanner__log-empty{color:#5f6368}.inventory-scanner__basket,.inventory-scanner__log{display:grid;gap:8px}.inventory-scanner__basket-item,.inventory-scanner__log-item{display:grid;gap:4px;border:1px solid #d7dde5;border-radius:4px;background:#fff;padding:10px}.inventory-scanner__basket-item{border-left:4px solid #1769aa}.inventory-scanner__log-item{border-left:4px solid #188038}.inventory-scanner__log-item--failed{border-left-color:#d93025}.inventory-scanner__log-item--warning{border-left-color:#f9ab00}.inventory-scanner__log-item div{align-items:center;display:flex;justify-content:space-between;gap:8px}.inventory-scanner__basket-item small,.inventory-scanner__log-item span,.inventory-scanner__log-item small{color:#5f6368}.inventory-scanner__input,.inventory-location-admin__form input{min-height:36px;min-width:0;border:1px solid #ccd1d8;border-radius:4px;flex:1;padding:0 8px}.inventory-overview__row{align-items:center;display:grid;grid-template-columns:minmax(90px,1fr) minmax(120px,2fr) minmax(120px,2fr);width:100%;margin-bottom:6px;text-align:left}.inventory-overview__location{color:#1769aa}
@@ -0,0 +1,2 @@
1
+ (function(f,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue"),require("@questwork/q-inventory-model")):typeof define=="function"&&define.amd?define(["exports","vue","@questwork/q-inventory-model"],e):(f=typeof globalThis<"u"?globalThis:f||self,e(f.QInventory={},f.Vue,f.qInventoryModel))})(this,function(f,e,_){"use strict";const G=e.defineComponent({name:"inventory-scanner",__name:"InventoryScanner",props:{assetApiClient:{type:Object,required:!1},assets:{type:Array,required:!1},currentUserCode:{type:String,required:!1}},emits:["moved","scan"],setup(r,{expose:t,emit:o}){t();const n=r,a=o,l=e.ref(""),s=e.ref([]),m=e.ref(""),p=e.ref(_.INVENTORY_MOVEMENT_TYPE.PICKUP),d=e.ref([]),c=e.computed(()=>_.getVirtualUserLocationCode(n.currentUserCode||"currentUser")),u=e.computed(()=>p.value===_.INVENTORY_MOVEMENT_TYPE.PICKUP?"Source":"Destination");e.watch(()=>[n.assets,c.value],Y,{deep:!0,immediate:!0});function C(i){p.value=i,l.value="",E({message:`Mode changed to ${i}`,status:"INFO",title:"Mode"})}async function N(){const i=m.value.trim();i&&(m.value="",await v(i))}async function v(i){const y=_.parseInventoryQr(i);if(a("scan",{raw:i,parsed:y}),_.isLocationQr(i)){l.value=y.code,E({message:`${u.value} set to ${y.code}`,status:"INFO",title:"Location"});return}if(!l.value){E({message:`Scan ${u.value.toLowerCase()} location first`,status:"FAILED",title:y.code});return}const h=g(y.code);try{if(n.assetApiClient?.move){const D=await n.assetApiClient.move(h),z=Q(D);if(a("moved",h),R(h),z.length){E({message:H(z),status:"WARNING",title:y.code});return}}else a("moved",h),R(h);E({message:`${h.fromLocationCode||"-"} -> ${h.toLocationCode}`,status:"OK",title:y.code})}catch(D){E({message:F(D),status:"FAILED",title:y.code})}}function g(i){return p.value===_.INVENTORY_MOVEMENT_TYPE.PICKUP?{assetTag:i,fromLocationCode:l.value,fromLocationKind:_.INVENTORY_LOCATION_KIND.REGISTERED,movementType:_.INVENTORY_MOVEMENT_TYPE.PICKUP,toLocationCode:c.value,toLocationKind:_.INVENTORY_LOCATION_KIND.VIRTUAL}:{assetTag:i,fromLocationCode:c.value,fromLocationKind:_.INVENTORY_LOCATION_KIND.VIRTUAL,movementType:_.INVENTORY_MOVEMENT_TYPE.DROPOFF,toLocationCode:l.value,toLocationKind:_.INVENTORY_LOCATION_KIND.REGISTERED}}function R(i){if(i.toLocationCode===c.value){K({assetTag:i.assetTag,currentLocationCode:c.value});return}s.value=s.value.filter(y=>y.assetTag!==i.assetTag)}function K(i){const y=s.value.findIndex(h=>h.assetTag===i.assetTag);if(y>=0){s.value[y]={...s.value[y],...i};return}s.value.unshift(i)}function Y(){s.value=(n.assets||[]).map(j).filter(i=>!!i&&i.currentLocationCode===c.value)}function j(i){const y=i,h=T(y.assetTag);return h?{assetTag:h,category:T(y.category),currentLocationCode:T(y.currentLocationCode),name:T(y.name)}:null}function E({message:i,status:y,title:h}){d.value.unshift({key:`${Date.now()}-${Math.random()}`,message:i,status:y,title:h}),d.value=d.value.slice(0,30)}function T(i){return typeof i=="string"?i:""}function F(i){return i instanceof Error?i.message:String(i)}function Q(i){return i?.data?.[0]?.warnings||[]}function H(i){return i.map(y=>`${y.code}: ${y.message}`).join("; ")}function qe(){d.value=[]}const J={props:n,emit:a,activeLocationCode:l,basketItems:s,manualQr:m,mode:p,scanLog:d,holderLocationCode:c,locationLabel:u,setMode:C,submitManualQr:N,handleQr:v,getMovePayload:g,applyBasketMove:R,upsertBasketItem:K,syncBasketFromAssets:Y,toBasketItem:j,addLog:E,getString:T,getErrorMessage:F,getMoveWarnings:Q,formatWarnings:H,clearScanLog:qe,get INVENTORY_MOVEMENT_TYPE(){return _.INVENTORY_MOVEMENT_TYPE}};return Object.defineProperty(J,"__isScriptSetup",{enumerable:!1,value:!0}),J}}),A=(r,t)=>{const o=r.__vccOpts||r;for(const[n,a]of t)o[n]=a;return o},W={class:"inventory-scanner"},X={class:"inventory-scanner__mode"},Z={class:"inventory-scanner__state"},$={class:"inventory-scanner__manual"},ee={class:"inventory-scanner__basket-header"},te=["disabled"],ne={class:"inventory-scanner__basket"},oe={key:0,class:"inventory-scanner__empty"},se={class:"inventory-scanner__log"},re={key:0,class:"inventory-scanner__log-empty"};function ae(r,t,o,n,a,l){return e.openBlock(),e.createElementBlock("div",W,[e.createElementVNode("div",X,[e.createElementVNode("button",{class:e.normalizeClass(["inventory-scanner__mode-button",{"inventory-scanner__mode-button--active":n.mode===n.INVENTORY_MOVEMENT_TYPE.PICKUP}]),type:"button",onClick:t[0]||(t[0]=s=>n.setMode(n.INVENTORY_MOVEMENT_TYPE.PICKUP))}," Pickup ",2),e.createElementVNode("button",{class:e.normalizeClass(["inventory-scanner__mode-button",{"inventory-scanner__mode-button--active":n.mode===n.INVENTORY_MOVEMENT_TYPE.DROPOFF}]),type:"button",onClick:t[1]||(t[1]=s=>n.setMode(n.INVENTORY_MOVEMENT_TYPE.DROPOFF))}," Drop-off ",2)]),e.createElementVNode("div",Z,[e.createElementVNode("div",null,"Mode: "+e.toDisplayString(n.mode),1),e.createElementVNode("div",null,e.toDisplayString(n.locationLabel)+": "+e.toDisplayString(n.activeLocationCode||"-"),1),e.createElementVNode("div",null,"Holder: "+e.toDisplayString(n.holderLocationCode||"-"),1)]),e.createElementVNode("div",$,[e.withDirectives(e.createElementVNode("input",{"onUpdate:modelValue":t[2]||(t[2]=s=>n.manualQr=s),class:"inventory-scanner__input",placeholder:"Scan or enter QR text",onKeyup:e.withKeys(n.submitManualQr,["enter"])},null,544),[[e.vModelText,n.manualQr]]),e.createElementVNode("button",{type:"button",onClick:n.submitManualQr},"Submit")]),e.createElementVNode("div",ee,[e.createElementVNode("div",null,[t[3]||(t[3]=e.createElementVNode("strong",null,"My Basket",-1)),e.createElementVNode("span",null,e.toDisplayString(n.basketItems.length)+" on hand",1)]),e.createElementVNode("button",{type:"button",disabled:n.scanLog.length===0,onClick:n.clearScanLog}," Clear log ",8,te)]),e.createElementVNode("div",ne,[n.basketItems.length===0?(e.openBlock(),e.createElementBlock("div",oe," No items on hand ")):e.createCommentVNode("v-if",!0),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(n.basketItems,s=>(e.openBlock(),e.createElementBlock("div",{key:s.assetTag,class:"inventory-scanner__basket-item"},[e.createElementVNode("strong",null,e.toDisplayString(s.assetTag),1),e.createElementVNode("small",null,e.toDisplayString(s.name||s.category||s.currentLocationCode),1)]))),128))]),e.createElementVNode("div",se,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(n.scanLog,s=>(e.openBlock(),e.createElementBlock("div",{key:s.key,class:e.normalizeClass(["inventory-scanner__log-item",{"inventory-scanner__log-item--failed":s.status==="FAILED","inventory-scanner__log-item--warning":s.status==="WARNING"}])},[e.createElementVNode("div",null,[e.createElementVNode("strong",null,e.toDisplayString(s.title),1),e.createElementVNode("span",null,e.toDisplayString(s.status),1)]),e.createElementVNode("small",null,e.toDisplayString(s.message),1)],2))),128))]),n.scanLog.length===0?(e.openBlock(),e.createElementBlock("div",re," Scan log will appear here ")):e.createCommentVNode("v-if",!0)])}const L=A(G,[["render",ae],["__file","/Users/donlee/Developer/qw.q.inventory/src/components/InventoryScanner.vue"]]),ie=e.defineComponent({name:"inventory-overview",__name:"InventoryOverview",props:{assetApiClient:{type:Object,required:!1},assets:{type:Array,required:!1},locations:{type:Array,required:!1}},emits:["selectAsset","selectLocation"],setup(r,{expose:t}){t();const o=r,n=e.ref([]),a=e.computed(()=>n.value.length>0?n.value:o.assets||[]);async function l(){o.assetApiClient?.findAll&&(n.value=await o.assetApiClient.findAll())}function s(c){return m(c,"id")||m(c,"assetTag")||JSON.stringify(c)}function m(c,u){return String(c?.[u]||"")}function p(c){const u=m(c,"currentLocationCode"),C=m(c,"currentLocationKind");if(!u)return"Never scanned";if(_.isVirtualInventoryLocation({locationCode:u,locationKind:C})||_.isVirtualUserLocationCode(u))return`In transit - ${_.getVirtualUserCode(u)}`;const N=(o.locations||[]).find(v=>v.locationCode===u);return String(N?.name||u)}const d={props:o,loadedAssets:n,displayAssets:a,reload:l,getAssetKey:s,getAssetText:m,getDisplayLocation:p};return Object.defineProperty(d,"__isScriptSetup",{enumerable:!1,value:!0}),d}}),ce={class:"inventory-overview"},le={class:"inventory-overview__rows"},de=["onClick"],me=["onClick"];function ye(r,t,o,n,a,l){return e.openBlock(),e.createElementBlock("div",ce,[e.createElementVNode("div",{class:"inventory-overview__header"},[t[0]||(t[0]=e.createElementVNode("div",null,"Assets",-1)),e.createElementVNode("button",{type:"button",onClick:n.reload},"Reload")]),e.createElementVNode("div",le,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(n.displayAssets,s=>(e.openBlock(),e.createElementBlock("button",{key:n.getAssetKey(s),class:"inventory-overview__row",type:"button",onClick:m=>r.$emit("selectAsset",s)},[e.createElementVNode("span",null,e.toDisplayString(n.getAssetText(s,"assetTag")),1),e.createElementVNode("span",null,e.toDisplayString(n.getAssetText(s,"name")),1),e.createElementVNode("span",{class:"inventory-overview__location",onClick:e.withModifiers(m=>r.$emit("selectLocation",n.getAssetText(s,"currentLocationCode")),["stop"])},e.toDisplayString(n.getDisplayLocation(s)),9,me)],8,de))),128))])])}const I=A(ie,[["render",ye],["__file","/Users/donlee/Developer/qw.q.inventory/src/components/InventoryOverview.vue"]]),fe=e.defineComponent({name:"inventory-asset-detail",__name:"InventoryAssetDetail",props:{movementApiClient:{type:Object,required:!1},asset:{type:null,required:!1}},setup(r,{expose:t}){t();const o=r,n=e.ref([]);async function a(){const d=l("assetTag");d&&o.movementApiClient?.findAll&&(n.value=await o.movementApiClient.findAll({assetTag:d}))}function l(d){return String(o.asset?.[d]||"")}function s(d){const c=d;return String(c.id||c.inventoryMovementCode||c.movedAt||JSON.stringify(d))}function m(d){const c=d;return`${c.fromLocationCode||"-"} -> ${c.toLocationCode||"-"}`}const p={props:o,history:n,loadHistory:a,getValue:l,getHistoryKey:s,getHistoryText:m};return Object.defineProperty(p,"__isScriptSetup",{enumerable:!1,value:!0}),p}}),_e={class:"inventory-asset-detail"},pe={key:0,class:"inventory-asset-detail__body"},ue={key:1,class:"inventory-asset-detail__empty"};function ge(r,t,o,n,a,l){return e.openBlock(),e.createElementBlock("div",_e,[o.asset?(e.openBlock(),e.createElementBlock("div",pe,[e.createElementVNode("h3",null,e.toDisplayString(n.getValue("assetTag")),1),e.createElementVNode("div",null,e.toDisplayString(n.getValue("name")),1),e.createElementVNode("div",null,e.toDisplayString(n.getValue("currentLocationCode")),1),e.createElementVNode("button",{type:"button",onClick:n.loadHistory},"Load History"),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(n.history,s=>(e.openBlock(),e.createElementBlock("div",{key:n.getHistoryKey(s),class:"inventory-asset-detail__history"},e.toDisplayString(n.getHistoryText(s)),1))),128))])):(e.openBlock(),e.createElementBlock("div",ue,"No asset selected"))])}const b=A(fe,[["render",ge],["__file","/Users/donlee/Developer/qw.q.inventory/src/components/InventoryAssetDetail.vue"]]),he=e.defineComponent({name:"inventory-location-detail",__name:"InventoryLocationDetail",props:{assetApiClient:{type:Object,required:!1},location:{type:null,required:!1}},setup(r,{expose:t}){t();const o=r,n=e.ref([]),a=e.computed(()=>typeof o.location=="string"?o.location:String(o.location?.locationCode||""));async function l(){a.value&&o.assetApiClient?.findAll&&(n.value=await o.assetApiClient.findAll({currentLocationCode:a.value}))}function s(d){const c=d;return String(c.id||c.assetTag||JSON.stringify(d))}function m(d){const c=d;return`${c.assetTag||""} ${c.name||""}`.trim()}const p={props:o,assets:n,locationCode:a,loadAssets:l,getAssetKey:s,getAssetText:m};return Object.defineProperty(p,"__isScriptSetup",{enumerable:!1,value:!0}),p}}),ve={class:"inventory-location-detail"},Ee={class:"inventory-location-detail__header"},Ae=["disabled"];function ke(r,t,o,n,a,l){return e.openBlock(),e.createElementBlock("div",ve,[e.createElementVNode("div",Ee,[e.createElementVNode("div",null,e.toDisplayString(n.locationCode||"No location selected"),1),e.createElementVNode("button",{type:"button",disabled:!n.locationCode,onClick:n.loadAssets},"Load Assets",8,Ae)]),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(n.assets,s=>(e.openBlock(),e.createElementBlock("div",{key:n.getAssetKey(s),class:"inventory-location-detail__asset"},e.toDisplayString(n.getAssetText(s)),1))),128))])}const V=A(he,[["render",ke],["__file","/Users/donlee/Developer/qw.q.inventory/src/components/InventoryLocationDetail.vue"]]),Ce=e.defineComponent({name:"inventory-location-admin",__name:"InventoryLocationAdmin",props:{locations:{type:Array,required:!1}},emits:["saveLocation"],setup(r,{expose:t,emit:o}){t();const n=o,a=e.reactive({locationCode:"",locationType:"",name:""});function l(){n("saveLocation",{...a}),a.locationCode="",a.locationType="",a.name=""}function s(d){const c=d;return String(c.id||c.locationCode||JSON.stringify(d))}function m(d){const c=d;return`${c.locationCode||""} ${c.name||""}`.trim()}const p={emit:n,form:a,submit:l,getLocationKey:s,getLocationText:m};return Object.defineProperty(p,"__isScriptSetup",{enumerable:!1,value:!0}),p}}),Ne={class:"inventory-location-admin"};function Te(r,t,o,n,a,l){return e.openBlock(),e.createElementBlock("div",Ne,[e.createElementVNode("form",{class:"inventory-location-admin__form",onSubmit:e.withModifiers(n.submit,["prevent"])},[e.withDirectives(e.createElementVNode("input",{"onUpdate:modelValue":t[0]||(t[0]=s=>n.form.locationCode=s),placeholder:"Location code"},null,512),[[e.vModelText,n.form.locationCode]]),e.withDirectives(e.createElementVNode("input",{"onUpdate:modelValue":t[1]||(t[1]=s=>n.form.name=s),placeholder:"Name"},null,512),[[e.vModelText,n.form.name]]),e.withDirectives(e.createElementVNode("input",{"onUpdate:modelValue":t[2]||(t[2]=s=>n.form.locationType=s),placeholder:"Type"},null,512),[[e.vModelText,n.form.locationType]]),t[3]||(t[3]=e.createElementVNode("button",{type:"submit"},"Save",-1))],32),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(o.locations,s=>(e.openBlock(),e.createElementBlock("div",{key:n.getLocationKey(s),class:"inventory-location-admin__row"},e.toDisplayString(n.getLocationText(s)),1))),128))])}const S=A(Ce,[["render",Te],["__file","/Users/donlee/Developer/qw.q.inventory/src/components/InventoryLocationAdmin.vue"]]),Le=e.defineComponent({name:"q-inventory",__name:"QInventory",props:{assetApiClient:{type:Object,required:!1},locationApiClient:{type:Object,required:!1},movementApiClient:{type:Object,required:!1},assets:{type:Array,required:!1},currentUserCode:{type:String,required:!1},locations:{type:Array,required:!1}},emits:["moved","saveLocation","scan","selectAsset","selectLocation"],setup(r,{expose:t,emit:o}){t();const n=r,a=o,l=e.ref("scanner"),s=e.ref(null),m=e.ref(null),p=e.computed(()=>[{key:"scanner",label:"Scan"},{key:"overview",label:"Overview"},{key:"asset",label:"Asset"},{key:"location",label:"Location"},{key:"locations",label:"Locations"}]);function d(g){a("moved",g)}function c(g){a("scan",g)}function u(g){a("saveLocation",g)}function C(g){s.value=g,l.value="asset",a("selectAsset",g)}function N(g){m.value=g,l.value="location",a("selectLocation",g)}const v={props:n,emit:a,activeTab:l,selectedAsset:s,selectedLocation:m,tabs:p,onMoved:d,onScan:c,onSaveLocation:u,onSelectAsset:C,onSelectLocation:N,InventoryScanner:L,InventoryOverview:I,InventoryAssetDetail:b,InventoryLocationDetail:V,InventoryLocationAdmin:S};return Object.defineProperty(v,"__isScriptSetup",{enumerable:!1,value:!0}),v}}),Ie={class:"q-inventory"},be={class:"q-inventory__toolbar"},Ve=["onClick"];function Se(r,t,o,n,a,l){return e.openBlock(),e.createElementBlock("div",Ie,[e.createElementVNode("div",be,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(n.tabs,s=>(e.openBlock(),e.createElementBlock("button",{key:s.key,class:e.normalizeClass(["q-inventory__tab",{"q-inventory__tab--active":n.activeTab===s.key}]),type:"button",onClick:m=>n.activeTab=s.key},e.toDisplayString(s.label),11,Ve))),128))]),e.withDirectives(e.createVNode(n.InventoryScanner,{"asset-api-client":o.assetApiClient,assets:o.assets,"current-user-code":o.currentUserCode,onMoved:n.onMoved,onScan:n.onScan},null,8,["asset-api-client","assets","current-user-code"]),[[e.vShow,n.activeTab==="scanner"]]),n.activeTab==="overview"?(e.openBlock(),e.createBlock(n.InventoryOverview,{key:0,"asset-api-client":o.assetApiClient,assets:o.assets,locations:o.locations,onSelectAsset:n.onSelectAsset,onSelectLocation:n.onSelectLocation},null,8,["asset-api-client","assets","locations"])):e.createCommentVNode("v-if",!0),n.activeTab==="asset"?(e.openBlock(),e.createBlock(n.InventoryAssetDetail,{key:1,"movement-api-client":o.movementApiClient,asset:n.selectedAsset},null,8,["movement-api-client","asset"])):e.createCommentVNode("v-if",!0),n.activeTab==="location"?(e.openBlock(),e.createBlock(n.InventoryLocationDetail,{key:2,"asset-api-client":o.assetApiClient,location:n.selectedLocation},null,8,["asset-api-client","location"])):e.createCommentVNode("v-if",!0),n.activeTab==="locations"?(e.openBlock(),e.createBlock(n.InventoryLocationAdmin,{key:3,locations:o.locations,onSaveLocation:n.onSaveLocation},null,8,["locations"])):e.createCommentVNode("v-if",!0)])}const w=A(Le,[["render",Se],["__file","/Users/donlee/Developer/qw.q.inventory/src/components/QInventory.vue"]]);class k{constructor(t={}){this.axios=t.axios,this.authenticatorTokenProvider=t.authenticatorTokenProvider,this.baseURL=(t.baseURL||"").replace(/\/$/,""),this.movedBy=t.movedBy||"currentUser",this.qRepo=t.qRepo,this.tenantCode=t.tenantCode||"tenantCode",this.userTokenProvider=t.userTokenProvider}async get(t,o={}){const n=await this.getAuthHeaders();if(this.axios){const s=await this.axios.get(this.getUrl(t),{headers:n,params:o});return U(s.data)}const a=new URL(this.getUrl(t),we());Object.entries(o).forEach(([s,m])=>{typeof m<"u"&&m!==null&&m!==""&&a.searchParams.set(s,String(m))});const l=await fetch(this.getFetchUrl(a),{headers:n});return U(await l.json(),l)}async post(t,o={}){const n={"Content-Type":"application/json",...await this.getAuthHeaders()};if(this.axios){const l=await this.axios.post(this.getUrl(t),o,{headers:n});return O(l.data)}const a=await fetch(this.getUrl(t),{body:JSON.stringify(o),headers:n,method:"POST"});return O(await a.json(),a)}getUrl(t){return`${this.baseURL}/api/v1${t}`}getFetchUrl(t){return this.baseURL?t.toString():`${t.pathname}${t.search}`}withDefaults(t={}){return Re({...t,qRepo:t.qRepo||this.qRepo,tenantCode:t.tenantCode||this.tenantCode})}async getAuthHeaders(){const t={},o=await P(this.authenticatorTokenProvider),n=await P(this.userTokenProvider);return o&&(t["X-Q-Authenticator"]=o),n&&(t["X-Q-Inventory-User-Token"]=n),t}}async function P(r){return r?r():""}function O(r,t){const o=r,n=o?.err,a=o?.errors;if(t&&!t.ok||n?.hasError||a)throw new Error(Oe({data:o,err:n,errors:a,response:t}));return o}function U(r,t){const o=O(r,t);return Array.isArray(o?.data)?o.data:[]}function we(){return typeof window<"u"?window.location.origin:"http://localhost"}function Oe({data:r,err:t,errors:o,response:n}){const a=String(n?.status||t?.statusCode||t?.code||o?.name||r?.code||"REQUEST_ERROR"),l=Be(t?.message||o?.message||r?.message||"QInventory request failed");return`${a}: ${l}`}function Be(r){return Array.isArray(r)?r.join("; "):String(r)}function Re(r){return Object.fromEntries(Object.entries(r).filter(([,t])=>typeof t<"u"&&t!==null&&t!==""))}class q extends k{constructor(t={}){super(t)}async findAll(t={}){return this.get("/qInventoryAsset",this.withDefaults(t))}async findOne(t){return this.get(`/qInventoryAsset/${encodeURIComponent(t)}`,this.withDefaults())}async saveOne(t){return this.post("/qInventoryAsset",this.withDefaults(t))}async move(t){const o=String(t.assetTag||""),n=t.movedBy||this.movedBy;return this.post(`/qInventoryAsset/${encodeURIComponent(o)}/move`,this.withDefaults({...t,movedBy:n}))}}class x extends k{constructor(t={}){super(t)}async findAll(t={}){return this.get("/qInventoryLocation",this.withDefaults(t))}async findOne(t){return this.get(`/qInventoryLocation/${encodeURIComponent(t)}`,this.withDefaults())}async saveOne(t){return this.post("/qInventoryLocation",this.withDefaults(t))}}class M extends k{constructor(t={}){super(t)}async findAll(t={}){const o=String(t.assetTag||"");if(!o)throw new Error("assetTag is required for movement findAll");const{assetTag:n,...a}=t;return this.get(`/qInventoryAsset/${encodeURIComponent(o)}/movements`,this.withDefaults(a))}}class De extends k{constructor(t={}){super(t)}async getBrowserToken(){return(await this.post("/qInventory/token",{clientAppId:"qInventoryBrowser",clientAppName:"qInventoryBrowser"})).data?.[0]}async requestLoginLink({email:t,tenantCode:o=this.tenantCode}){return(await this.post("/qInventory/login-link",{email:t,tenantCode:o})).data?.[0]}async verifyLoginToken(t){return(await this.post("/qInventory/login-token/verify",{loginToken:t})).data?.[0]}}class Pe{constructor(t={}){this.assetRepo=new q(t),this.locationRepo=new x(t),this.movementRepo=new M(t)}async findAll(t){return this.assetRepo.findAll(t)}async findOne(t){return this.assetRepo.findOne(t)}async saveOne(t){return this.assetRepo.saveOne(t)}async move(t){return this.assetRepo.move(t)}async findAssets(t){return this.assetRepo.findAll(t)}async findLocations(t){return this.locationRepo.findAll(t)}async findLocationAssets(t){return this.assetRepo.findAll({currentLocationCode:t})}async findAssetHistory(t){return this.movementRepo.findAll({assetTag:t})}async moveAsset(t){return this.assetRepo.move(t)}}function B(r){r.component("q-inventory",w),r.component("inventory-scanner",L),r.component("inventory-overview",I),r.component("inventory-asset-detail",b),r.component("inventory-location-detail",V),r.component("inventory-location-admin",S)}w.install=B;const Ue={install:B};f.InventoryAssetDetail=b,f.InventoryAssetRepoAxios=q,f.InventoryAuthRepoAxios=De,f.InventoryLocationAdmin=S,f.InventoryLocationDetail=V,f.InventoryLocationRepoAxios=x,f.InventoryMovementRepoAxios=M,f.InventoryOverview=I,f.InventoryRepoAxios=Pe,f.InventoryRepoAxiosBase=k,f.InventoryScanner=L,f.QInventory=w,f.default=Ue,f.install=B,Object.keys(_).forEach(r=>{r!=="default"&&!Object.prototype.hasOwnProperty.call(f,r)&&Object.defineProperty(f,r,{enumerable:!0,get:()=>_[r]})}),Object.defineProperties(f,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
2
+ //# sourceMappingURL=q-inventory.min.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"q-inventory.min.js","sources":["../src/components/InventoryScanner.vue","../src/components/InventoryOverview.vue","../src/components/InventoryAssetDetail.vue","../src/components/InventoryLocationDetail.vue","../src/components/InventoryLocationAdmin.vue","../src/components/QInventory.vue","../src/models/inventoryAxiosBase.ts","../src/models/inventoryAssetRepoAxios.ts","../src/models/inventoryLocationRepoAxios.ts","../src/models/inventoryMovementRepoAxios.ts","../src/models/inventoryAuthRepoAxios.ts","../src/models/index.ts","../src/index.ts"],"sourcesContent":["<template>\n <div class=\"inventory-scanner\">\n <div class=\"inventory-scanner__mode\">\n <button\n class=\"inventory-scanner__mode-button\"\n :class=\"{ 'inventory-scanner__mode-button--active': mode === INVENTORY_MOVEMENT_TYPE.PICKUP }\"\n type=\"button\"\n @click=\"setMode(INVENTORY_MOVEMENT_TYPE.PICKUP)\"\n >\n Pickup\n </button>\n <button\n class=\"inventory-scanner__mode-button\"\n :class=\"{ 'inventory-scanner__mode-button--active': mode === INVENTORY_MOVEMENT_TYPE.DROPOFF }\"\n type=\"button\"\n @click=\"setMode(INVENTORY_MOVEMENT_TYPE.DROPOFF)\"\n >\n Drop-off\n </button>\n </div>\n <div class=\"inventory-scanner__state\">\n <div>Mode: {{ mode }}</div>\n <div>{{ locationLabel }}: {{ activeLocationCode || '-' }}</div>\n <div>Holder: {{ holderLocationCode || '-' }}</div>\n </div>\n <div class=\"inventory-scanner__manual\">\n <input\n v-model=\"manualQr\"\n class=\"inventory-scanner__input\"\n placeholder=\"Scan or enter QR text\"\n @keyup.enter=\"submitManualQr\"\n />\n <button type=\"button\" @click=\"submitManualQr\">Submit</button>\n </div>\n <div class=\"inventory-scanner__basket-header\">\n <div>\n <strong>My Basket</strong>\n <span>{{ basketItems.length }} on hand</span>\n </div>\n <button\n type=\"button\"\n :disabled=\"scanLog.length === 0\"\n @click=\"clearScanLog\"\n >\n Clear log\n </button>\n </div>\n <div class=\"inventory-scanner__basket\">\n <div\n v-if=\"basketItems.length === 0\"\n class=\"inventory-scanner__empty\"\n >\n No items on hand\n </div>\n <div\n v-for=\"item in basketItems\"\n :key=\"item.assetTag\"\n class=\"inventory-scanner__basket-item\"\n >\n <strong>{{ item.assetTag }}</strong>\n <small>{{ item.name || item.category || item.currentLocationCode }}</small>\n </div>\n </div>\n <div class=\"inventory-scanner__log\">\n <div\n v-for=\"item in scanLog\"\n :key=\"item.key\"\n class=\"inventory-scanner__log-item\"\n :class=\"{\n 'inventory-scanner__log-item--failed': item.status === 'FAILED',\n 'inventory-scanner__log-item--warning': item.status === 'WARNING',\n }\"\n >\n <div>\n <strong>{{ item.title }}</strong>\n <span>{{ item.status }}</span>\n </div>\n <small>{{ item.message }}</small>\n </div>\n </div>\n <div\n v-if=\"scanLog.length === 0\"\n class=\"inventory-scanner__log-empty\"\n >\n Scan log will appear here\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport {\n INVENTORY_LOCATION_KIND,\n INVENTORY_MOVEMENT_TYPE,\n getVirtualUserLocationCode,\n isLocationQr,\n parseInventoryQr,\n} from '@questwork/q-inventory-model'\nimport type { InventoryAssetApiClient, InventoryMovePayload, InventoryMoveResult, InventoryMoveWarning } from '../models/index.js'\n\ndefineOptions({\n name: 'inventory-scanner',\n})\n\ntype ScannerMode = typeof INVENTORY_MOVEMENT_TYPE.PICKUP | typeof INVENTORY_MOVEMENT_TYPE.DROPOFF\ntype ScanLogStatus = 'OK' | 'WARNING' | 'FAILED' | 'INFO'\n\ninterface BasketItem {\n assetTag: string\n category?: string\n currentLocationCode?: string\n name?: string\n}\n\ninterface ScanLogItem {\n key: string\n message: string\n status: ScanLogStatus\n title: string\n}\n\nconst props = defineProps<{\n assetApiClient?: InventoryAssetApiClient\n assets?: unknown[]\n currentUserCode?: string\n}>()\n\nconst emit = defineEmits<{\n moved: [payload: InventoryMovePayload]\n scan: [payload: { raw: string, parsed: unknown }]\n}>()\n\nconst activeLocationCode = ref('')\nconst basketItems = ref<BasketItem[]>([])\nconst manualQr = ref('')\nconst mode = ref<ScannerMode>(INVENTORY_MOVEMENT_TYPE.PICKUP)\nconst scanLog = ref<ScanLogItem[]>([])\n\nconst holderLocationCode = computed(() => getVirtualUserLocationCode(props.currentUserCode || 'currentUser'))\nconst locationLabel = computed(() => mode.value === INVENTORY_MOVEMENT_TYPE.PICKUP ? 'Source' : 'Destination')\n\nwatch(\n () => [props.assets, holderLocationCode.value],\n syncBasketFromAssets,\n { deep: true, immediate: true },\n)\n\nfunction setMode(nextMode: ScannerMode) {\n mode.value = nextMode\n activeLocationCode.value = ''\n addLog({\n message: `Mode changed to ${nextMode}`,\n status: 'INFO',\n title: 'Mode',\n })\n}\n\nasync function submitManualQr() {\n const value = manualQr.value.trim()\n if (!value) return\n manualQr.value = ''\n await handleQr(value)\n}\n\nasync function handleQr(value: string) {\n const parsed = parseInventoryQr(value)\n emit('scan', { raw: value, parsed })\n\n if (isLocationQr(value)) {\n activeLocationCode.value = parsed.code\n addLog({\n message: `${locationLabel.value} set to ${parsed.code}`,\n status: 'INFO',\n title: 'Location',\n })\n return\n }\n\n if (!activeLocationCode.value) {\n addLog({\n message: `Scan ${locationLabel.value.toLowerCase()} location first`,\n status: 'FAILED',\n title: parsed.code,\n })\n return\n }\n\n const payload = getMovePayload(parsed.code)\n try {\n if (props.assetApiClient?.move) {\n const result = await props.assetApiClient.move(payload)\n const warnings = getMoveWarnings(result)\n emit('moved', payload)\n applyBasketMove(payload)\n if (warnings.length) {\n addLog({\n message: formatWarnings(warnings),\n status: 'WARNING',\n title: parsed.code,\n })\n return\n }\n } else {\n emit('moved', payload)\n applyBasketMove(payload)\n }\n addLog({\n message: `${payload.fromLocationCode || '-'} -> ${payload.toLocationCode}`,\n status: 'OK',\n title: parsed.code,\n })\n } catch (err) {\n addLog({\n message: getErrorMessage(err),\n status: 'FAILED',\n title: parsed.code,\n })\n }\n}\n\nfunction getMovePayload(assetTag: string): InventoryMovePayload {\n if (mode.value === INVENTORY_MOVEMENT_TYPE.PICKUP) {\n return {\n assetTag,\n fromLocationCode: activeLocationCode.value,\n fromLocationKind: INVENTORY_LOCATION_KIND.REGISTERED,\n movementType: INVENTORY_MOVEMENT_TYPE.PICKUP,\n toLocationCode: holderLocationCode.value,\n toLocationKind: INVENTORY_LOCATION_KIND.VIRTUAL,\n }\n }\n return {\n assetTag,\n fromLocationCode: holderLocationCode.value,\n fromLocationKind: INVENTORY_LOCATION_KIND.VIRTUAL,\n movementType: INVENTORY_MOVEMENT_TYPE.DROPOFF,\n toLocationCode: activeLocationCode.value,\n toLocationKind: INVENTORY_LOCATION_KIND.REGISTERED,\n }\n}\n\nfunction applyBasketMove(payload: InventoryMovePayload) {\n if (payload.toLocationCode === holderLocationCode.value) {\n upsertBasketItem({\n assetTag: payload.assetTag,\n currentLocationCode: holderLocationCode.value,\n })\n return\n }\n basketItems.value = basketItems.value.filter((item) => item.assetTag !== payload.assetTag)\n}\n\nfunction upsertBasketItem(item: BasketItem) {\n const index = basketItems.value.findIndex((basketItem) => basketItem.assetTag === item.assetTag)\n if (index >= 0) {\n basketItems.value[index] = {\n ...basketItems.value[index],\n ...item,\n }\n return\n }\n basketItems.value.unshift(item)\n}\n\nfunction syncBasketFromAssets() {\n basketItems.value = (props.assets || [])\n .map(toBasketItem)\n .filter((item): item is BasketItem => !!item && item.currentLocationCode === holderLocationCode.value)\n}\n\nfunction toBasketItem(asset: unknown): BasketItem | null {\n const item = asset as Record<string, unknown>\n const assetTag = getString(item.assetTag)\n if (!assetTag) {\n return null\n }\n return {\n assetTag,\n category: getString(item.category),\n currentLocationCode: getString(item.currentLocationCode),\n name: getString(item.name),\n }\n}\n\nfunction addLog({ message, status, title }: Omit<ScanLogItem, 'key'>) {\n scanLog.value.unshift({\n key: `${Date.now()}-${Math.random()}`,\n message,\n status,\n title,\n })\n scanLog.value = scanLog.value.slice(0, 30)\n}\n\nfunction getString(value: unknown) {\n return typeof value === 'string' ? value : ''\n}\n\nfunction getErrorMessage(err: unknown) {\n return err instanceof Error ? err.message : String(err)\n}\n\nfunction getMoveWarnings(result: unknown) {\n const response = result as { data?: InventoryMoveResult[] }\n return response?.data?.[0]?.warnings || []\n}\n\nfunction formatWarnings(warnings: InventoryMoveWarning[]) {\n return warnings.map((warning) => `${warning.code}: ${warning.message}`).join('; ')\n}\n\nfunction clearScanLog() {\n scanLog.value = []\n}\n</script>\n","<template>\n <div class=\"inventory-overview\">\n <div class=\"inventory-overview__header\">\n <div>Assets</div>\n <button type=\"button\" @click=\"reload\">Reload</button>\n </div>\n <div class=\"inventory-overview__rows\">\n <button\n v-for=\"asset in displayAssets\"\n :key=\"getAssetKey(asset)\"\n class=\"inventory-overview__row\"\n type=\"button\"\n @click=\"$emit('selectAsset', asset)\"\n >\n <span>{{ getAssetText(asset, 'assetTag') }}</span>\n <span>{{ getAssetText(asset, 'name') }}</span>\n <span\n class=\"inventory-overview__location\"\n @click.stop=\"$emit('selectLocation', getAssetText(asset, 'currentLocationCode'))\"\n >\n {{ getDisplayLocation(asset) }}\n </span>\n </button>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport {\n getVirtualUserCode,\n isVirtualInventoryLocation,\n isVirtualUserLocationCode,\n} from '@questwork/q-inventory-model'\nimport type { InventoryAssetApiClient } from '../models/index.js'\n\ndefineOptions({\n name: 'inventory-overview',\n})\n\nconst props = defineProps<{\n assetApiClient?: InventoryAssetApiClient\n assets?: unknown[]\n locations?: unknown[]\n}>()\n\ndefineEmits<{\n selectAsset: [payload: unknown]\n selectLocation: [payload: unknown]\n}>()\n\nconst loadedAssets = ref<unknown[]>([])\nconst displayAssets = computed(() => loadedAssets.value.length > 0 ? loadedAssets.value : (props.assets || []))\n\nasync function reload() {\n if (props.assetApiClient?.findAll) {\n loadedAssets.value = await props.assetApiClient.findAll()\n }\n}\n\nfunction getAssetKey(asset: unknown) {\n return getAssetText(asset, 'id') || getAssetText(asset, 'assetTag') || JSON.stringify(asset)\n}\n\nfunction getAssetText(asset: unknown, key: string) {\n return String((asset as Record<string, unknown>)?.[key] || '')\n}\n\nfunction getDisplayLocation(asset: unknown) {\n const locationCode = getAssetText(asset, 'currentLocationCode')\n const locationKind = getAssetText(asset, 'currentLocationKind')\n if (!locationCode) return 'Never scanned'\n if (isVirtualInventoryLocation({ locationCode, locationKind }) || isVirtualUserLocationCode(locationCode)) {\n return `In transit - ${getVirtualUserCode(locationCode)}`\n }\n const location = (props.locations || []).find((item) => {\n return (item as Record<string, unknown>).locationCode === locationCode\n }) as Record<string, unknown> | undefined\n return String(location?.name || locationCode)\n}\n</script>\n","<template>\n <div class=\"inventory-asset-detail\">\n <div v-if=\"asset\" class=\"inventory-asset-detail__body\">\n <h3>{{ getValue('assetTag') }}</h3>\n <div>{{ getValue('name') }}</div>\n <div>{{ getValue('currentLocationCode') }}</div>\n <button type=\"button\" @click=\"loadHistory\">Load History</button>\n <div\n v-for=\"item in history\"\n :key=\"getHistoryKey(item)\"\n class=\"inventory-asset-detail__history\"\n >\n {{ getHistoryText(item) }}\n </div>\n </div>\n <div v-else class=\"inventory-asset-detail__empty\">No asset selected</div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport type { InventoryMovementApiClient } from '../models/index.js'\n\ndefineOptions({\n name: 'inventory-asset-detail',\n})\n\nconst props = defineProps<{\n movementApiClient?: InventoryMovementApiClient\n asset?: unknown\n}>()\n\nconst history = ref<unknown[]>([])\n\nasync function loadHistory() {\n const assetTag = getValue('assetTag')\n if (assetTag && props.movementApiClient?.findAll) {\n history.value = await props.movementApiClient.findAll({ assetTag })\n }\n}\n\nfunction getValue(key: string) {\n return String((props.asset as Record<string, unknown>)?.[key] || '')\n}\n\nfunction getHistoryKey(item: unknown) {\n const data = item as Record<string, unknown>\n return String(data.id || data.inventoryMovementCode || data.movedAt || JSON.stringify(item))\n}\n\nfunction getHistoryText(item: unknown) {\n const data = item as Record<string, unknown>\n return `${data.fromLocationCode || '-'} -> ${data.toLocationCode || '-'}`\n}\n</script>\n","<template>\n <div class=\"inventory-location-detail\">\n <div class=\"inventory-location-detail__header\">\n <div>{{ locationCode || 'No location selected' }}</div>\n <button type=\"button\" :disabled=\"!locationCode\" @click=\"loadAssets\">Load Assets</button>\n </div>\n <div\n v-for=\"asset in assets\"\n :key=\"getAssetKey(asset)\"\n class=\"inventory-location-detail__asset\"\n >\n {{ getAssetText(asset) }}\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport type { InventoryAssetApiClient } from '../models/index.js'\n\ndefineOptions({\n name: 'inventory-location-detail',\n})\n\nconst props = defineProps<{\n assetApiClient?: InventoryAssetApiClient\n location?: unknown\n}>()\n\nconst assets = ref<unknown[]>([])\nconst locationCode = computed(() => {\n if (typeof props.location === 'string') return props.location\n return String((props.location as Record<string, unknown>)?.locationCode || '')\n})\n\nasync function loadAssets() {\n if (locationCode.value && props.assetApiClient?.findAll) {\n assets.value = await props.assetApiClient.findAll({ currentLocationCode: locationCode.value })\n }\n}\n\nfunction getAssetKey(asset: unknown) {\n const data = asset as Record<string, unknown>\n return String(data.id || data.assetTag || JSON.stringify(asset))\n}\n\nfunction getAssetText(asset: unknown) {\n const data = asset as Record<string, unknown>\n return `${data.assetTag || ''} ${data.name || ''}`.trim()\n}\n</script>\n","<template>\n <div class=\"inventory-location-admin\">\n <form class=\"inventory-location-admin__form\" @submit.prevent=\"submit\">\n <input v-model=\"form.locationCode\" placeholder=\"Location code\" />\n <input v-model=\"form.name\" placeholder=\"Name\" />\n <input v-model=\"form.locationType\" placeholder=\"Type\" />\n <button type=\"submit\">Save</button>\n </form>\n <div\n v-for=\"location in locations\"\n :key=\"getLocationKey(location)\"\n class=\"inventory-location-admin__row\"\n >\n {{ getLocationText(location) }}\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { reactive } from 'vue'\n\ndefineOptions({\n name: 'inventory-location-admin',\n})\n\ndefineProps<{\n locations?: unknown[]\n}>()\n\nconst emit = defineEmits<{\n saveLocation: [payload: Record<string, string>]\n}>()\n\nconst form = reactive({\n locationCode: '',\n locationType: '',\n name: '',\n})\n\nfunction submit() {\n emit('saveLocation', { ...form })\n form.locationCode = ''\n form.locationType = ''\n form.name = ''\n}\n\nfunction getLocationKey(location: unknown) {\n const data = location as Record<string, unknown>\n return String(data.id || data.locationCode || JSON.stringify(location))\n}\n\nfunction getLocationText(location: unknown) {\n const data = location as Record<string, unknown>\n return `${data.locationCode || ''} ${data.name || ''}`.trim()\n}\n</script>\n","<template>\n <div class=\"q-inventory\">\n <div class=\"q-inventory__toolbar\">\n <button\n v-for=\"item in tabs\"\n :key=\"item.key\"\n class=\"q-inventory__tab\"\n :class=\"{ 'q-inventory__tab--active': activeTab === item.key }\"\n type=\"button\"\n @click=\"activeTab = item.key\"\n >\n {{ item.label }}\n </button>\n </div>\n <inventory-scanner\n v-show=\"activeTab === 'scanner'\"\n :asset-api-client=\"assetApiClient\"\n :assets=\"assets\"\n :current-user-code=\"currentUserCode\"\n @moved=\"onMoved\"\n @scan=\"onScan\"\n />\n <inventory-overview\n v-if=\"activeTab === 'overview'\"\n :asset-api-client=\"assetApiClient\"\n :assets=\"assets\"\n :locations=\"locations\"\n @select-asset=\"onSelectAsset\"\n @select-location=\"onSelectLocation\"\n />\n <inventory-asset-detail\n v-if=\"activeTab === 'asset'\"\n :movement-api-client=\"movementApiClient\"\n :asset=\"selectedAsset\"\n />\n <inventory-location-detail\n v-if=\"activeTab === 'location'\"\n :asset-api-client=\"assetApiClient\"\n :location=\"selectedLocation\"\n />\n <inventory-location-admin\n v-if=\"activeTab === 'locations'\"\n :locations=\"locations\"\n @save-location=\"onSaveLocation\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport InventoryScanner from './InventoryScanner.vue'\nimport InventoryOverview from './InventoryOverview.vue'\nimport InventoryAssetDetail from './InventoryAssetDetail.vue'\nimport InventoryLocationDetail from './InventoryLocationDetail.vue'\nimport InventoryLocationAdmin from './InventoryLocationAdmin.vue'\nimport type {\n InventoryAssetApiClient,\n InventoryLocationApiClient,\n InventoryMovementApiClient,\n} from '../models/index.js'\n\ndefineOptions({\n name: 'q-inventory',\n})\n\nconst props = defineProps<{\n assetApiClient?: InventoryAssetApiClient\n locationApiClient?: InventoryLocationApiClient\n movementApiClient?: InventoryMovementApiClient\n assets?: unknown[]\n currentUserCode?: string\n locations?: unknown[]\n}>()\n\nconst emit = defineEmits<{\n moved: [payload: unknown]\n saveLocation: [payload: unknown]\n scan: [payload: unknown]\n selectAsset: [payload: unknown]\n selectLocation: [payload: unknown]\n}>()\n\nconst activeTab = ref('scanner')\nconst selectedAsset = ref<unknown>(null)\nconst selectedLocation = ref<unknown>(null)\nconst tabs = computed(() => [\n { key: 'scanner', label: 'Scan' },\n { key: 'overview', label: 'Overview' },\n { key: 'asset', label: 'Asset' },\n { key: 'location', label: 'Location' },\n { key: 'locations', label: 'Locations' },\n])\n\nfunction onMoved(payload: unknown) {\n emit('moved', payload)\n}\n\nfunction onScan(payload: unknown) {\n emit('scan', payload)\n}\n\nfunction onSaveLocation(payload: unknown) {\n emit('saveLocation', payload)\n}\n\nfunction onSelectAsset(payload: unknown) {\n selectedAsset.value = payload\n activeTab.value = 'asset'\n emit('selectAsset', payload)\n}\n\nfunction onSelectLocation(payload: unknown) {\n selectedLocation.value = payload\n activeTab.value = 'location'\n emit('selectLocation', payload)\n}\n</script>\n","export interface InventoryAxiosLike {\n get: (url: string, config?: { headers?: Record<string, string>, params?: Record<string, unknown> }) => Promise<{ data: unknown }>\n post: (url: string, body?: Record<string, unknown>, config?: { headers?: Record<string, string> }) => Promise<{ data: unknown }>\n}\n\nexport interface InventoryRepoAxiosOptions {\n axios?: InventoryAxiosLike\n authenticatorTokenProvider?: () => Promise<string> | string\n baseURL?: string\n movedBy?: string\n qRepo?: string\n tenantCode?: string\n userTokenProvider?: () => Promise<string> | string\n}\n\nexport abstract class InventoryRepoAxiosBase {\n axios?: InventoryAxiosLike\n authenticatorTokenProvider?: () => Promise<string> | string\n baseURL: string\n movedBy: string\n qRepo?: string\n tenantCode: string\n userTokenProvider?: () => Promise<string> | string\n\n constructor(options: InventoryRepoAxiosOptions = {}) {\n this.axios = options.axios\n this.authenticatorTokenProvider = options.authenticatorTokenProvider\n this.baseURL = (options.baseURL || '').replace(/\\/$/, '')\n this.movedBy = options.movedBy || 'currentUser'\n this.qRepo = options.qRepo\n this.tenantCode = options.tenantCode || 'tenantCode'\n this.userTokenProvider = options.userTokenProvider\n }\n\n protected async get(path: string, query: Record<string, unknown> = {}) {\n const headers = await this.getAuthHeaders()\n if (this.axios) {\n const response = await this.axios.get(this.getUrl(path), { headers, params: query })\n return unwrapQSystemData(response.data)\n }\n const url = new URL(this.getUrl(path), getUrlBase())\n Object.entries(query).forEach(([key, value]) => {\n if (typeof value !== 'undefined' && value !== null && value !== '') {\n url.searchParams.set(key, String(value))\n }\n })\n const response = await fetch(this.getFetchUrl(url), { headers })\n return unwrapQSystemData(await response.json(), response)\n }\n\n protected async post(path: string, body: Record<string, unknown> = {}) {\n const headers = {\n 'Content-Type': 'application/json',\n ...await this.getAuthHeaders(),\n }\n if (this.axios) {\n const response = await this.axios.post(this.getUrl(path), body, { headers })\n return unwrapQSystemResponse(response.data)\n }\n const response = await fetch(this.getUrl(path), {\n body: JSON.stringify(body),\n headers,\n method: 'POST',\n })\n return unwrapQSystemResponse(await response.json(), response)\n }\n\n protected getUrl(path: string) {\n return `${this.baseURL}/api/v1${path}`\n }\n\n protected getFetchUrl(url: URL) {\n return this.baseURL ? url.toString() : `${url.pathname}${url.search}`\n }\n\n protected withDefaults(obj: Record<string, unknown> = {}) {\n return removeEmptyValues({\n ...obj,\n qRepo: obj.qRepo || this.qRepo,\n tenantCode: obj.tenantCode || this.tenantCode,\n })\n }\n\n private async getAuthHeaders() {\n const headers: Record<string, string> = {}\n const authenticatorToken = await resolveTokenProvider(this.authenticatorTokenProvider)\n const userToken = await resolveTokenProvider(this.userTokenProvider)\n if (authenticatorToken) {\n headers['X-Q-Authenticator'] = authenticatorToken\n }\n if (userToken) {\n headers['X-Q-Inventory-User-Token'] = userToken\n }\n return headers\n }\n}\n\nasync function resolveTokenProvider(provider?: () => Promise<string> | string) {\n if (!provider) {\n return ''\n }\n return provider()\n}\n\nfunction unwrapQSystemResponse(json: unknown, response?: Response) {\n const data = json as Record<string, unknown>\n const err = data?.err as Record<string, unknown> | undefined\n const errors = data?.errors as Record<string, unknown> | undefined\n if ((response && !response.ok) || err?.hasError || errors) {\n throw new Error(getResponseErrorMessage({ data, err, errors, response }))\n }\n return data\n}\n\nfunction unwrapQSystemData(json: unknown, response?: Response): unknown[] {\n const data = unwrapQSystemResponse(json, response)\n return Array.isArray(data?.data) ? data.data : []\n}\n\nfunction getUrlBase() {\n if (typeof window !== 'undefined') {\n return window.location.origin\n }\n return 'http://localhost'\n}\n\nfunction getResponseErrorMessage({ data, err, errors, response }: {\n data: Record<string, unknown>\n err?: Record<string, unknown>\n errors?: Record<string, unknown>\n response?: Response\n}) {\n const code = String(response?.status || err?.statusCode || err?.code || errors?.name || data?.code || 'REQUEST_ERROR')\n const message = formatErrorMessage(err?.message || errors?.message || data?.message || 'QInventory request failed')\n return `${code}: ${message}`\n}\n\nfunction formatErrorMessage(value: unknown) {\n if (Array.isArray(value)) {\n return value.join('; ')\n }\n return String(value)\n}\n\nfunction removeEmptyValues(obj: Record<string, unknown>) {\n return Object.fromEntries(\n Object.entries(obj).filter(([, value]) => typeof value !== 'undefined' && value !== null && value !== ''),\n )\n}\n","import { InventoryRepoAxiosBase, type InventoryRepoAxiosOptions } from './inventoryAxiosBase.js'\nimport type { InventoryMovePayload } from './index.js'\n\nexport interface InventoryAssetFindAllQuery extends Record<string, unknown> {\n assetTag?: string\n assetTags?: string[]\n category?: string\n currentLocationCode?: string\n currentLocationKind?: string\n currentLocationType?: string\n}\n\nexport class InventoryAssetRepoAxios extends InventoryRepoAxiosBase {\n constructor(options: InventoryRepoAxiosOptions = {}) {\n super(options)\n }\n\n async findAll(query: InventoryAssetFindAllQuery = {}) {\n return this.get('/qInventoryAsset', this.withDefaults(query))\n }\n\n async findOne(assetTag: string) {\n return this.get(`/qInventoryAsset/${encodeURIComponent(assetTag)}`, this.withDefaults())\n }\n\n async saveOne(doc: Record<string, unknown>) {\n return this.post('/qInventoryAsset', this.withDefaults(doc))\n }\n\n async move(payload: InventoryMovePayload) {\n const assetTag = String(payload.assetTag || '')\n const movedBy = payload.movedBy || this.movedBy\n return this.post(`/qInventoryAsset/${encodeURIComponent(assetTag)}/move`, this.withDefaults({\n ...payload,\n movedBy,\n }))\n }\n}\n","import { InventoryRepoAxiosBase, type InventoryRepoAxiosOptions } from './inventoryAxiosBase.js'\n\nexport interface InventoryLocationFindAllQuery extends Record<string, unknown> {\n locationCode?: string\n locationType?: string\n parentLocationCode?: string\n}\n\nexport class InventoryLocationRepoAxios extends InventoryRepoAxiosBase {\n constructor(options: InventoryRepoAxiosOptions = {}) {\n super(options)\n }\n\n async findAll(query: InventoryLocationFindAllQuery = {}) {\n return this.get('/qInventoryLocation', this.withDefaults(query))\n }\n\n async findOne(locationCode: string) {\n return this.get(`/qInventoryLocation/${encodeURIComponent(locationCode)}`, this.withDefaults())\n }\n\n async saveOne(doc: Record<string, unknown>) {\n return this.post('/qInventoryLocation', this.withDefaults(doc))\n }\n}\n","import { InventoryRepoAxiosBase, type InventoryRepoAxiosOptions } from './inventoryAxiosBase.js'\n\nexport interface InventoryMovementFindAllQuery extends Record<string, unknown> {\n assetTag?: string\n fromLocationCode?: string\n toLocationCode?: string\n movedBy?: string\n movementType?: string\n}\n\nexport class InventoryMovementRepoAxios extends InventoryRepoAxiosBase {\n constructor(options: InventoryRepoAxiosOptions = {}) {\n super(options)\n }\n\n async findAll(query: InventoryMovementFindAllQuery = {}) {\n const assetTag = String(query.assetTag || '')\n if (!assetTag) {\n throw new Error('assetTag is required for movement findAll')\n }\n const { assetTag: _omit, ...rest } = query\n return this.get(`/qInventoryAsset/${encodeURIComponent(assetTag)}/movements`, this.withDefaults(rest))\n }\n}\n","import { InventoryRepoAxiosBase, type InventoryRepoAxiosOptions } from './inventoryAxiosBase.js'\n\nexport interface InventoryTokenResult {\n token: string\n tokenExpiry: number\n}\n\nexport interface InventoryLoginLinkResult {\n email: string\n loginUrl: string\n sent: boolean\n}\n\nexport interface InventoryUserTokenResult {\n email: string\n tenantCode: string\n userCode: string\n userToken: string\n}\n\nexport class InventoryAuthRepoAxios extends InventoryRepoAxiosBase {\n constructor(options: InventoryRepoAxiosOptions = {}) {\n super(options)\n }\n\n async getBrowserToken() {\n const result = await this.post('/qInventory/token', {\n clientAppId: 'qInventoryBrowser',\n clientAppName: 'qInventoryBrowser',\n }) as { data?: InventoryTokenResult[] }\n return result.data?.[0]\n }\n\n async requestLoginLink({ email, tenantCode = this.tenantCode }: { email: string, tenantCode?: string }) {\n const result = await this.post('/qInventory/login-link', {\n email,\n tenantCode,\n }) as { data?: InventoryLoginLinkResult[] }\n return result.data?.[0]\n }\n\n async verifyLoginToken(loginToken: string) {\n const result = await this.post('/qInventory/login-token/verify', {\n loginToken,\n }) as { data?: InventoryUserTokenResult[] }\n return result.data?.[0]\n }\n}\n","import { InventoryAssetRepoAxios } from './inventoryAssetRepoAxios.js'\nimport { InventoryLocationRepoAxios } from './inventoryLocationRepoAxios.js'\nimport { InventoryMovementRepoAxios } from './inventoryMovementRepoAxios.js'\nimport type { InventoryRepoAxiosOptions } from './inventoryAxiosBase.js'\n\nexport interface InventoryAssetApiClient {\n findAll?: (query?: Record<string, unknown>) => Promise<unknown[]>\n findOne?: (id: string) => Promise<unknown[]>\n saveOne?: (doc: Record<string, unknown>) => Promise<unknown>\n move?: (payload: InventoryMovePayload) => Promise<unknown>\n}\n\nexport interface InventoryLocationApiClient {\n findAll?: (query?: Record<string, unknown>) => Promise<unknown[]>\n findOne?: (id: string) => Promise<unknown[]>\n saveOne?: (doc: Record<string, unknown>) => Promise<unknown>\n}\n\nexport interface InventoryMovementApiClient {\n findAll?: (query?: Record<string, unknown>) => Promise<unknown[]>\n}\n\n// Backward-compatible union type for consumers that still expect one object\nexport type InventoryApiClient = InventoryAssetApiClient & InventoryLocationApiClient & InventoryMovementApiClient\n\nexport interface InventoryMovePayload {\n assetTag: string\n fromLocationCode?: string\n fromLocationKind?: string\n movedBy?: string\n toLocationCode: string\n toLocationKind?: string\n movementType?: string\n}\n\nexport interface InventoryMoveWarning {\n actualLocationCode?: string\n assetTag?: string\n code: string\n message: string\n requestedFromLocationCode?: string\n requestedFromLocationKind?: string\n}\n\nexport interface InventoryMoveResult {\n warnings?: InventoryMoveWarning[]\n}\n\nexport interface InventoryDisplayLocation {\n code: string\n label: string\n type?: string\n}\n\nexport * from './inventoryAxiosBase.js'\nexport * from './inventoryAssetRepoAxios.js'\nexport * from './inventoryAuthRepoAxios.js'\nexport * from './inventoryLocationRepoAxios.js'\nexport * from './inventoryMovementRepoAxios.js'\n\n// Backward-compat wrapper so existing callers don't break immediately.\n// Internally it delegates to the focused repos above.\nexport class InventoryRepoAxios implements InventoryApiClient {\n private assetRepo: InventoryAssetRepoAxios\n private locationRepo: InventoryLocationRepoAxios\n private movementRepo: InventoryMovementRepoAxios\n\n constructor(options: InventoryRepoAxiosOptions = {}) {\n this.assetRepo = new InventoryAssetRepoAxios(options)\n this.locationRepo = new InventoryLocationRepoAxios(options)\n this.movementRepo = new InventoryMovementRepoAxios(options)\n }\n\n async findAll(query?: Record<string, unknown>) {\n return this.assetRepo.findAll(query)\n }\n\n async findOne(id: string) {\n return this.assetRepo.findOne(id)\n }\n\n async saveOne(doc: Record<string, unknown>) {\n return this.assetRepo.saveOne(doc)\n }\n\n async move(payload: InventoryMovePayload) {\n return this.assetRepo.move(payload)\n }\n\n // Legacy alias for asset findAll\n async findAssets(query?: Record<string, unknown>) {\n return this.assetRepo.findAll(query)\n }\n\n // Legacy alias for location findAll\n async findLocations(query?: Record<string, unknown>) {\n return this.locationRepo.findAll(query)\n }\n\n // Legacy alias — location assets are just assets filtered by currentLocationCode\n async findLocationAssets(locationCode: string) {\n return this.assetRepo.findAll({ currentLocationCode: locationCode })\n }\n\n // Legacy alias for movement history\n async findAssetHistory(assetTag: string) {\n return this.movementRepo.findAll({ assetTag })\n }\n\n // Legacy alias for move\n async moveAsset(payload: InventoryMovePayload) {\n return this.assetRepo.move(payload)\n }\n}\n","import type { App } from 'vue'\nimport QInventory from './components/QInventory.vue'\nimport InventoryScanner from './components/InventoryScanner.vue'\nimport InventoryOverview from './components/InventoryOverview.vue'\nimport InventoryAssetDetail from './components/InventoryAssetDetail.vue'\nimport InventoryLocationDetail from './components/InventoryLocationDetail.vue'\nimport InventoryLocationAdmin from './components/InventoryLocationAdmin.vue'\nimport './styles/index.scss'\n\nexport * from '@questwork/q-inventory-model'\nexport * from './models/index.js'\n\nfunction install(app: App) {\n app.component('q-inventory', QInventory)\n app.component('inventory-scanner', InventoryScanner)\n app.component('inventory-overview', InventoryOverview)\n app.component('inventory-asset-detail', InventoryAssetDetail)\n app.component('inventory-location-detail', InventoryLocationDetail)\n app.component('inventory-location-admin', InventoryLocationAdmin)\n}\n\nQInventory.install = install\n\nexport {\n install,\n InventoryAssetDetail,\n InventoryLocationAdmin,\n InventoryLocationDetail,\n InventoryOverview,\n InventoryScanner,\n QInventory,\n}\n\nexport default {\n install,\n}\n"],"names":["props","__props","emit","__emit","activeLocationCode","ref","basketItems","manualQr","mode","INVENTORY_MOVEMENT_TYPE","scanLog","holderLocationCode","computed","getVirtualUserLocationCode","locationLabel","watch","syncBasketFromAssets","setMode","nextMode","addLog","submitManualQr","value","handleQr","parsed","parseInventoryQr","isLocationQr","payload","getMovePayload","result","warnings","getMoveWarnings","applyBasketMove","formatWarnings","err","getErrorMessage","assetTag","INVENTORY_LOCATION_KIND","upsertBasketItem","item","index","basketItem","toBasketItem","asset","getString","message","status","title","warning","clearScanLog","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_7","_hoisted_9","_openBlock","_createElementBlock","_createElementVNode","_normalizeClass","$setup","_cache","$event","_toDisplayString","_withDirectives","_withKeys","_hoisted_6","_hoisted_8","_createCommentVNode","_Fragment","_renderList","_hoisted_10","loadedAssets","displayAssets","reload","getAssetKey","getAssetText","key","getDisplayLocation","locationCode","locationKind","isVirtualInventoryLocation","isVirtualUserLocationCode","getVirtualUserCode","location","_ctx","_withModifiers","history","loadHistory","getValue","getHistoryKey","data","getHistoryText","$props","assets","loadAssets","form","reactive","submit","getLocationKey","getLocationText","_vModelText","activeTab","selectedAsset","selectedLocation","tabs","onMoved","onScan","onSaveLocation","onSelectAsset","onSelectLocation","_createVNode","_createBlock","InventoryRepoAxiosBase","options","path","query","headers","response","unwrapQSystemData","url","getUrlBase","body","unwrapQSystemResponse","obj","removeEmptyValues","authenticatorToken","resolveTokenProvider","userToken","provider","json","errors","getResponseErrorMessage","code","formatErrorMessage","InventoryAssetRepoAxios","doc","movedBy","InventoryLocationRepoAxios","InventoryMovementRepoAxios","_omit","rest","InventoryAuthRepoAxios","email","tenantCode","loginToken","InventoryRepoAxios","id","install","app","QInventory","InventoryScanner","InventoryOverview","InventoryAssetDetail","InventoryLocationDetail","InventoryLocationAdmin"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ .q-inventory,.inventory-scanner,.inventory-overview,.inventory-asset-detail,.inventory-location-detail,.inventory-location-admin{box-sizing:border-box;color:#202124;font-family:Arial,sans-serif}.q-inventory{min-height:100%;background:#f6f7f9}.q-inventory__toolbar,.inventory-scanner__mode,.inventory-scanner__manual,.inventory-overview__header,.inventory-location-detail__header,.inventory-location-admin__form{display:flex;gap:8px;padding:12px}.q-inventory__tab,.inventory-scanner__mode-button,button{min-height:36px;border:1px solid #ccd1d8;border-radius:4px;background:#fff;color:#202124;cursor:pointer;padding:0 12px}.q-inventory__tab--active,.inventory-scanner__mode-button--active{border-color:#1769aa;background:#1769aa;color:#fff}.inventory-scanner__state,.inventory-scanner__basket-header,.inventory-scanner__basket,.inventory-scanner__log,.inventory-scanner__log-empty,.inventory-overview__rows,.inventory-asset-detail__body,.inventory-asset-detail__empty,.inventory-location-detail__asset,.inventory-location-admin__row{padding:12px}.inventory-scanner__basket-header{align-items:center;display:flex;justify-content:space-between;gap:8px;border-top:1px solid #e0e3e7;border-bottom:1px solid #e0e3e7;background:#fff;font-size:13px}.inventory-scanner__basket-header div{display:grid;gap:2px}.inventory-scanner__basket-header span,.inventory-scanner__empty,.inventory-scanner__log-empty{color:#5f6368}.inventory-scanner__basket,.inventory-scanner__log{display:grid;gap:8px}.inventory-scanner__basket-item,.inventory-scanner__log-item{display:grid;gap:4px;border:1px solid #d7dde5;border-radius:4px;background:#fff;padding:10px}.inventory-scanner__basket-item{border-left:4px solid #1769aa}.inventory-scanner__log-item{border-left:4px solid #188038}.inventory-scanner__log-item--failed{border-left-color:#d93025}.inventory-scanner__log-item--warning{border-left-color:#f9ab00}.inventory-scanner__log-item div{align-items:center;display:flex;justify-content:space-between;gap:8px}.inventory-scanner__basket-item small,.inventory-scanner__log-item span,.inventory-scanner__log-item small{color:#5f6368}.inventory-scanner__input,.inventory-location-admin__form input{min-height:36px;min-width:0;border:1px solid #ccd1d8;border-radius:4px;flex:1;padding:0 8px}.inventory-overview__row{align-items:center;display:grid;grid-template-columns:minmax(90px,1fr) minmax(120px,2fr) minmax(120px,2fr);width:100%;margin-bottom:6px;text-align:left}.inventory-overview__location{color:#1769aa}html,body,#app{min-height:100%;margin:0}body{background:#eef1f5}.q-inventory-app{min-height:100vh;background:#f6f7f9}.q-inventory-app__header{align-items:center;display:flex;justify-content:space-between;gap:12px;padding:14px 16px;background:#202124;color:#fff}.q-inventory-app__header h1{margin:0;font-size:18px;font-weight:700}.q-inventory-app__header p{margin:4px 0 0;color:#c8ccd2;font-size:12px}.q-inventory-app__header button{flex:0 0 auto}.q-inventory-app__error{margin:12px;border:1px solid #d93025;border-radius:4px;background:#fce8e6;color:#a50e0e;padding:10px 12px}.q-inventory-app__notice{margin:12px;border:1px solid #188038;border-radius:4px;background:#e6f4ea;color:#0d652d;padding:10px 12px}