@cratis/scene.blueprint.inventory 0.0.0-stage → 4.53.1

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 (138) hide show
  1. package/README.md +66 -2
  2. package/blueprint.ts +16 -0
  3. package/blueprintCatalog.json +190 -0
  4. package/dist/cjs/blueprint.js +19 -0
  5. package/dist/cjs/blueprint.js.map +1 -0
  6. package/dist/cjs/index.js +72 -0
  7. package/dist/cjs/index.js.map +1 -0
  8. package/dist/cjs/inventoryApplication.js +49 -0
  9. package/dist/cjs/inventoryApplication.js.map +1 -0
  10. package/dist/cjs/inventoryParts.js +131 -0
  11. package/dist/cjs/inventoryParts.js.map +1 -0
  12. package/dist/cjs/inventoryQueries.js +72 -0
  13. package/dist/cjs/inventoryQueries.js.map +1 -0
  14. package/dist/cjs/inventoryScreenSet.js +69 -0
  15. package/dist/cjs/inventoryScreenSet.js.map +1 -0
  16. package/dist/cjs/manifest.js +65 -0
  17. package/dist/cjs/manifest.js.map +1 -0
  18. package/dist/cjs/navigation.js +143 -0
  19. package/dist/cjs/navigation.js.map +1 -0
  20. package/dist/cjs/package.json +3 -0
  21. package/dist/cjs/packageName.js +8 -0
  22. package/dist/cjs/packageName.js.map +1 -0
  23. package/dist/cjs/screens/index.js +22 -0
  24. package/dist/cjs/screens/index.js.map +1 -0
  25. package/dist/cjs/templateProvenance.js +24 -0
  26. package/dist/cjs/templateProvenance.js.map +1 -0
  27. package/dist/cjs/templates/dashboardTemplate.js +92 -0
  28. package/dist/cjs/templates/dashboardTemplate.js.map +1 -0
  29. package/dist/cjs/templates/formTemplates.js +94 -0
  30. package/dist/cjs/templates/formTemplates.js.map +1 -0
  31. package/dist/cjs/templates/index.js +34 -0
  32. package/dist/cjs/templates/index.js.map +1 -0
  33. package/dist/cjs/templates/listTemplates.js +212 -0
  34. package/dist/cjs/templates/listTemplates.js.map +1 -0
  35. package/dist/cjs/templates/locationsTemplate.js +63 -0
  36. package/dist/cjs/templates/locationsTemplate.js.map +1 -0
  37. package/dist/cjs/templates/recordTemplates.js +111 -0
  38. package/dist/cjs/templates/recordTemplates.js.map +1 -0
  39. package/dist/esm/blueprint.d.ts +3 -0
  40. package/dist/esm/blueprint.d.ts.map +1 -0
  41. package/dist/esm/blueprint.js +17 -0
  42. package/dist/esm/blueprint.js.map +1 -0
  43. package/dist/esm/index.d.ts +12 -0
  44. package/dist/esm/index.d.ts.map +1 -0
  45. package/dist/esm/index.js +18 -0
  46. package/dist/esm/index.js.map +1 -0
  47. package/dist/esm/inventoryApplication.d.ts +10 -0
  48. package/dist/esm/inventoryApplication.d.ts.map +1 -0
  49. package/dist/esm/inventoryApplication.js +44 -0
  50. package/dist/esm/inventoryApplication.js.map +1 -0
  51. package/dist/esm/inventoryParts.d.ts +15 -0
  52. package/dist/esm/inventoryParts.d.ts.map +1 -0
  53. package/dist/esm/inventoryParts.js +114 -0
  54. package/dist/esm/inventoryParts.js.map +1 -0
  55. package/dist/esm/inventoryQueries.d.ts +44 -0
  56. package/dist/esm/inventoryQueries.d.ts.map +1 -0
  57. package/dist/esm/inventoryQueries.js +64 -0
  58. package/dist/esm/inventoryQueries.js.map +1 -0
  59. package/dist/esm/inventoryScreenSet.d.ts +7 -0
  60. package/dist/esm/inventoryScreenSet.d.ts.map +1 -0
  61. package/dist/esm/inventoryScreenSet.js +67 -0
  62. package/dist/esm/inventoryScreenSet.js.map +1 -0
  63. package/dist/esm/manifest.d.ts +3 -0
  64. package/dist/esm/manifest.d.ts.map +1 -0
  65. package/dist/esm/manifest.js +63 -0
  66. package/dist/esm/manifest.js.map +1 -0
  67. package/dist/esm/navigation.d.ts +5 -0
  68. package/dist/esm/navigation.d.ts.map +1 -0
  69. package/dist/esm/navigation.js +139 -0
  70. package/dist/esm/navigation.js.map +1 -0
  71. package/dist/esm/package.json +3 -0
  72. package/dist/esm/packageName.d.ts +2 -0
  73. package/dist/esm/packageName.d.ts.map +1 -0
  74. package/dist/esm/packageName.js +6 -0
  75. package/dist/esm/packageName.js.map +1 -0
  76. package/dist/esm/screens/index.d.ts +3 -0
  77. package/dist/esm/screens/index.d.ts.map +1 -0
  78. package/dist/esm/screens/index.js +20 -0
  79. package/dist/esm/screens/index.js.map +1 -0
  80. package/dist/esm/templateProvenance.d.ts +3 -0
  81. package/dist/esm/templateProvenance.d.ts.map +1 -0
  82. package/dist/esm/templateProvenance.js +22 -0
  83. package/dist/esm/templateProvenance.js.map +1 -0
  84. package/dist/esm/templates/dashboardTemplate.d.ts +3 -0
  85. package/dist/esm/templates/dashboardTemplate.d.ts.map +1 -0
  86. package/dist/esm/templates/dashboardTemplate.js +90 -0
  87. package/dist/esm/templates/dashboardTemplate.js.map +1 -0
  88. package/dist/esm/templates/formTemplates.d.ts +5 -0
  89. package/dist/esm/templates/formTemplates.d.ts.map +1 -0
  90. package/dist/esm/templates/formTemplates.js +90 -0
  91. package/dist/esm/templates/formTemplates.js.map +1 -0
  92. package/dist/esm/templates/index.d.ts +8 -0
  93. package/dist/esm/templates/index.d.ts.map +1 -0
  94. package/dist/esm/templates/index.js +22 -0
  95. package/dist/esm/templates/index.js.map +1 -0
  96. package/dist/esm/templates/listTemplates.d.ts +6 -0
  97. package/dist/esm/templates/listTemplates.d.ts.map +1 -0
  98. package/dist/esm/templates/listTemplates.js +207 -0
  99. package/dist/esm/templates/listTemplates.js.map +1 -0
  100. package/dist/esm/templates/locationsTemplate.d.ts +3 -0
  101. package/dist/esm/templates/locationsTemplate.d.ts.map +1 -0
  102. package/dist/esm/templates/locationsTemplate.js +61 -0
  103. package/dist/esm/templates/locationsTemplate.js.map +1 -0
  104. package/dist/esm/templates/recordTemplates.d.ts +3 -0
  105. package/dist/esm/templates/recordTemplates.d.ts.map +1 -0
  106. package/dist/esm/templates/recordTemplates.js +109 -0
  107. package/dist/esm/templates/recordTemplates.js.map +1 -0
  108. package/dist/esm/tsconfig.tsbuildinfo +1 -0
  109. package/index.ts +14 -0
  110. package/inventoryApplication.ts +28 -0
  111. package/inventoryParts.ts +52 -0
  112. package/inventoryQueries.ts +64 -0
  113. package/inventoryScreenSet.ts +25 -0
  114. package/manifest.ts +41 -0
  115. package/navigation.ts +60 -0
  116. package/package.json +78 -4
  117. package/packageName.ts +5 -0
  118. package/sampleData/inventory-warehouse.json +1770 -0
  119. package/screens/index.ts +20 -0
  120. package/templateProvenance.ts +15 -0
  121. package/templates/dashboardTemplate.ts +45 -0
  122. package/templates/formTemplates.ts +60 -0
  123. package/templates/index.ts +25 -0
  124. package/templates/listTemplates.ts +109 -0
  125. package/templates/locationsTemplate.ts +36 -0
  126. package/templates/recordTemplates.ts +45 -0
  127. package/thumbnails/InventoryAdjustStock.svg +12 -0
  128. package/thumbnails/InventoryCheckInOut.svg +17 -0
  129. package/thumbnails/InventoryDashboard.svg +14 -0
  130. package/thumbnails/InventoryItemGallery.svg +29 -0
  131. package/thumbnails/InventoryItemList.svg +13 -0
  132. package/thumbnails/InventoryItemPage.svg +18 -0
  133. package/thumbnails/InventoryLocations.svg +20 -0
  134. package/thumbnails/InventoryMovementList.svg +13 -0
  135. package/thumbnails/InventoryQuickCreateItem.svg +12 -0
  136. package/thumbnails/InventoryQuickCreateSupplier.svg +12 -0
  137. package/thumbnails/InventorySupplierList.svg +13 -0
  138. package/thumbnails/inventory.svg +14 -0
@@ -0,0 +1,20 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import { Screen } from '@cratis/scene.model';
5
+ import { LayoutName } from '@cratis/scene.blueprint.default';
6
+ import { inventoryScreenDefinitions } from '../inventoryScreenSet';
7
+
8
+ /**
9
+ * The ready-to-use screens: real `Screen` instances, one for each entry of the manifest's `blueprint.screenSet`, each filling the screen template it names in
10
+ * the foundation's application shell. A new application that adopts the blueprint gets these, wired into its navigation (`inventoryNavigation`).
11
+ */
12
+ export const inventoryScreens: Screen[] = inventoryScreenDefinitions.map(definition => ({
13
+ name: definition.name,
14
+ layout: LayoutName.AppShell,
15
+ screenTemplate: definition.template,
16
+ slotContent: {},
17
+ forms: [],
18
+ contributions: [],
19
+ path: definition.name.split('.'),
20
+ }));
@@ -0,0 +1,15 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import { TemplateMetadata } from '@cratis/scene.model';
5
+
6
+ /** The compatibility, attribution and license metadata every template this blueprint ships carries. */
7
+ export const inventoryTemplateProvenance: Pick<TemplateMetadata, 'compatibility' | 'attribution' | 'license' | 'licenseUrl'> = {
8
+ compatibility: {
9
+ scene: '^4.13.0',
10
+ packages: [{ name: 'Cratis.Blueprint.Default', versionRange: '^1.0.0' }],
11
+ },
12
+ attribution: { author: 'Cratis', url: 'https://github.com/Cratis/Scene/tree/main/Source/JavaScript/blueprint.inventory' },
13
+ license: 'MIT',
14
+ licenseUrl: 'https://github.com/Cratis/Scene/blob/main/LICENSE',
15
+ };
@@ -0,0 +1,45 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import { ScreenTemplate, TemplateScope } from '@cratis/scene.model';
5
+ import { dashboardScreenTemplate } from '@cratis/scene.blueprint.default';
6
+ import { InventoryEntityKind, InventoryQuery, currencyOfData, fromQuery, inventoryQueriesOf, localeOfData } from '../inventoryQueries';
7
+ import { component, inventoryMetadata } from '../inventoryParts';
8
+
9
+ /**
10
+ * The inventory dashboard (the foundation Dashboard, Operational variant): what is running low and what the stock is worth as key figures, the items
11
+ * that move most as a chart, the movements of the last days beneath, and the items to reorder beside them. Every region is its own component with its own
12
+ * loading, empty and error states, so one failed query leaves the others.
13
+ */
14
+ export const inventoryDashboardTemplate: ScreenTemplate = {
15
+ name: 'InventoryDashboard',
16
+ fitsSlot: 'content',
17
+ slots: dashboardScreenTemplate.slots,
18
+ arrangement: dashboardScreenTemplate.arrangement,
19
+ content: {
20
+ header: [component('inventory-dashboard-header', 'pageHeader', { title: 'Inventory dashboard', subtitle: 'Stock levels and movements this week' })],
21
+ kpis: [
22
+ component('inventory-kpi-low', 'statCard', {
23
+ label: 'Low stock items', value: fromQuery(InventoryQuery.Kpis, '0.value'), change: fromQuery(InventoryQuery.Kpis, '0.change'), goodDirection: 'down', comparison: 'last week', ...localeOfData,
24
+ }),
25
+ component('inventory-kpi-value', 'statCard', {
26
+ label: 'Stock value', value: fromQuery(InventoryQuery.Kpis, '1.value'), change: fromQuery(InventoryQuery.Kpis, '1.change'), format: 'currency', fractionDigits: 0, comparison: 'last week', ...currencyOfData,
27
+ }),
28
+ component('inventory-kpi-movements', 'statCard', {
29
+ label: 'Movements this week', value: fromQuery(InventoryQuery.Kpis, '2.value'), change: fromQuery(InventoryQuery.Kpis, '2.change'), comparison: 'last week', ...localeOfData,
30
+ }),
31
+ ],
32
+ charts: [component('inventory-chart-movers', 'chartWrapper', {
33
+ title: 'Top movers', kind: 'bar', categories: fromQuery(InventoryQuery.TopMovers, '0.categories'), series: fromQuery(InventoryQuery.TopMovers, '0.series'), ...localeOfData,
34
+ })],
35
+ tables: [component('inventory-dashboard-movements', 'dataList', {
36
+ label: 'Recent movements', rows: fromQuery(InventoryQuery.RecentMovements), columns: fromQuery(inventoryQueriesOf(InventoryEntityKind.Movement).columns), titleField: 'item', pageSize: 5, ...localeOfData,
37
+ })],
38
+ aside: [component('inventory-dashboard-low', 'dataList', {
39
+ label: 'Reorder soon', rows: fromQuery(InventoryQuery.LowStock), columns: fromQuery(inventoryQueriesOf(InventoryEntityKind.Item).columns), titleField: 'name', toneField: 'tone', pageSize: 5, ...localeOfData,
40
+ })],
41
+ },
42
+ displayName: 'Inventory dashboard',
43
+ description: 'Low stock count, stock value, top movers, recent movements and the items to reorder.',
44
+ metadata: inventoryMetadata('InventoryDashboard', 'Dashboard', [TemplateScope.Module, TemplateScope.Feature]),
45
+ };
@@ -0,0 +1,60 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import { DialogTemplate, ScreenTemplate, TemplateScope } from '@cratis/scene.model';
5
+ import { formScreenTemplate, quickCreateDialogTemplate } from '@cratis/scene.blueprint.default';
6
+ import { InventoryQuery, currencyOfData, fromQuery, localeOfData } from '../inventoryQueries';
7
+ import { closesDialog, component, inventoryMetadata, withBehaviors } from '../inventoryParts';
8
+
9
+ /**
10
+ * Check in or out, made for a phone held in one hand beside a shelf: one column of large fields, the item first - scanned or searched for in the same field -
11
+ * then the direction, how many, who has it and when it is due back. The foundation `FormScreen` supplies the sections, validation, Save and the unsaved-changes
12
+ * guard; what is particular here is that nothing is arranged side by side.
13
+ */
14
+ export const inventoryCheckInOutTemplate: ScreenTemplate = {
15
+ name: 'InventoryCheckInOut',
16
+ fitsSlot: 'content',
17
+ slots: formScreenTemplate.slots,
18
+ arrangement: formScreenTemplate.arrangement,
19
+ content: {
20
+ header: [component('InventoryCheckInOut-header', 'pageHeader', { title: 'Check in or out', subtitle: 'Scan or search for the item first' })],
21
+ body: [component('InventoryCheckInOut-body', 'formScreenBody', {
22
+ mode: 'create', saveAndNew: true, strings: { formSave: 'Record movement' }, sections: fromQuery('CheckInOutSections'), errors: fromQuery(InventoryQuery.FormErrors, '0'), ...currencyOfData,
23
+ })],
24
+ actions: [],
25
+ },
26
+ displayName: 'Inventory check in and out',
27
+ description: 'A mobile-first form to scan or search for an item and check it in or out, with who has it and when it is due back.',
28
+ metadata: inventoryMetadata('InventoryCheckInOut', 'Form', [TemplateScope.Feature, TemplateScope.Subfeature]),
29
+ };
30
+
31
+ /** The screen templates that are forms. */
32
+ export const inventoryFormTemplates: ScreenTemplate[] = [inventoryCheckInOutTemplate];
33
+
34
+ /**
35
+ * One quick-create dialog: the foundation `QuickCreateDialog` - a short form opened from a page to make one record without leaving it - with the fields
36
+ * that thing needs to get started.
37
+ */
38
+ function quickCreateOf(name: string, title: string, subtitle: string, sections: string, noun: string, create: string): DialogTemplate {
39
+ return {
40
+ name,
41
+ slots: quickCreateDialogTemplate.slots,
42
+ content: {
43
+ header: [component(`${name}-frame`, 'dialogFrame', { title, subtitle })],
44
+ body: [withBehaviors(component(`${name}-form`, 'formScreenBody', {
45
+ mode: 'create', saveAndNew: false, strings: { formSave: create }, sections: fromQuery(sections), errors: fromQuery(InventoryQuery.FormErrors, '0'), ...localeOfData,
46
+ }), closesDialog())],
47
+ actions: [],
48
+ },
49
+ displayName: `Inventory quick create ${noun}`,
50
+ description: `A short form that ${noun === 'stock adjustment' ? 'adjusts the stock of one item' : `creates one ${noun}`} without leaving the page.`,
51
+ metadata: inventoryMetadata(name, 'Dialog', [TemplateScope.Slice]),
52
+ };
53
+ }
54
+
55
+ /** Adjust stock (an item, a quantity change and a reason), and the quick creation of an item and of a supplier. */
56
+ export const inventoryQuickCreateDialogs: DialogTemplate[] = [
57
+ quickCreateOf('InventoryAdjustStock', 'Adjust stock', 'Count what is on the shelf and say why it changed', 'AdjustStockSections', 'stock adjustment', 'Adjust'),
58
+ quickCreateOf('InventoryQuickCreateItem', 'New item', 'Only what is needed to get started', 'ItemQuickSections', 'item', 'Create'),
59
+ quickCreateOf('InventoryQuickCreateSupplier', 'New supplier', 'Only what is needed to get started', 'SupplierQuickSections', 'supplier', 'Create'),
60
+ ];
@@ -0,0 +1,25 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import { inventoryDashboardTemplate } from './dashboardTemplate';
5
+ import { inventoryFormTemplates } from './formTemplates';
6
+ import { inventoryItemGalleryTemplate, inventoryItemListTemplate, inventoryMovementListTemplate, inventorySupplierListTemplate } from './listTemplates';
7
+ import { inventoryLocationsTemplate } from './locationsTemplate';
8
+ import { inventoryItemPageTemplate } from './recordTemplates';
9
+
10
+ export * from './dashboardTemplate';
11
+ export * from './listTemplates';
12
+ export * from './recordTemplates';
13
+ export * from './locationsTemplate';
14
+ export * from './formTemplates';
15
+
16
+ /** Every screen template this blueprint provides, in the order the manifest lists them. */
17
+ export const inventoryScreenTemplates = [
18
+ inventoryDashboardTemplate,
19
+ inventoryItemListTemplate, inventoryItemGalleryTemplate, inventoryItemPageTemplate,
20
+ inventoryLocationsTemplate,
21
+ inventoryMovementListTemplate, ...inventoryFormTemplates,
22
+ inventorySupplierListTemplate,
23
+ ];
24
+
25
+ export { inventoryQuickCreateDialogs as inventoryDialogTemplates } from './formTemplates';
@@ -0,0 +1,109 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import { InteractionActionKind, InteractionTriggerKind, NotificationLevel, NotifyAction, ScreenTemplate, TemplateScope } from '@cratis/scene.model';
5
+ import { listScreenTemplate } from '@cratis/scene.blueprint.default';
6
+ import { InventoryEntityKind, fromQuery, inventoryQueriesOf, localeOfData } from '../inventoryQueries';
7
+ import { actionButton, component, goesTo, inventoryMetadata, opensDialog, opensRecordOnSelect, withBehaviors } from '../inventoryParts';
8
+
9
+ const listScopes = [TemplateScope.Module, TemplateScope.Feature];
10
+
11
+ /** The Export button: it tells the user the export has started, which is what the shell does for a long-running action it does not wait on. */
12
+ const exportAction = (id: string) => withBehaviors(actionButton(id, 'Export', 'secondary'), [{
13
+ bindings: [{
14
+ trigger: { kind: InteractionTriggerKind.Click },
15
+ actions: [{ kind: InteractionActionKind.Notify, level: NotificationLevel.Info, message: { text: 'The export has started.' } } as unknown as NotifyAction],
16
+ }],
17
+ }]);
18
+
19
+ interface ListOptions {
20
+ name: string;
21
+ entity: InventoryEntityKind;
22
+ displayName: string;
23
+ description: string;
24
+ title: string;
25
+ subtitle: string;
26
+ searchLabel: string;
27
+ urlKey: string;
28
+ /** The primary action of the header: a quick-create dialog to open, or a screen to go to. */
29
+ primary: { label: string; dialog?: string; screen?: string };
30
+ rowActions: string[];
31
+ bulkActions: string[];
32
+ titleField: string;
33
+ /** The screen a chosen row opens; the list then selects one row at a time. Absent, rows are selected many at a time for the bulk bar. */
34
+ recordScreen?: string;
35
+ /** Rows are not selectable at all: a record of what happened, which nobody edits. */
36
+ readOnly?: boolean;
37
+ /** Show the records as cards, each with the picture its `imageField` names. */
38
+ cards?: { imageField: string };
39
+ /** Tint a row by the tone in this field (always beside a status column that says the same in words). */
40
+ toneField?: string;
41
+ }
42
+
43
+ /**
44
+ * One Inventory list: the foundation `ListScreen` with its header, toolbar, filters, list and bulk bar filled for an entity. The slots, arrangement and
45
+ * every behavior - sort, search, paging and selection in the address, the table collapsing to cards on a phone - are the foundation's.
46
+ */
47
+ function listTemplateOf(options: ListOptions): ScreenTemplate {
48
+ const queries = inventoryQueriesOf(options.entity);
49
+ const id = options.name;
50
+ const listId = `${id}-records`;
51
+ const primary = withBehaviors(actionButton(`${id}-primary`, options.primary.label, 'primary'), options.primary.dialog ? opensDialog(options.primary.dialog) : goesTo(options.primary.screen!));
52
+ const list = component(listId, 'dataList', {
53
+ label: options.title, rows: fromQuery(queries.rows), columns: fromQuery(queries.columns), titleField: options.titleField, pageSize: options.cards ? 12 : 10, urlKey: options.urlKey, ...localeOfData,
54
+ rowActions: options.rowActions,
55
+ ...(options.readOnly ? {} : { selectionMode: options.recordScreen ? 'single' : 'multiple' }),
56
+ ...(options.cards ? { variant: 'cards', imageField: options.cards.imageField } : {}),
57
+ ...(options.toneField ? { toneField: options.toneField } : {}),
58
+ });
59
+
60
+ return {
61
+ name: options.name,
62
+ fitsSlot: 'content',
63
+ slots: listScreenTemplate.slots,
64
+ arrangement: listScreenTemplate.arrangement,
65
+ content: {
66
+ header: [component(`${id}-header`, 'pageHeader', { title: options.title, subtitle: options.subtitle }, { actions: [exportAction(`${id}-export`), primary] })],
67
+ toolbar: [
68
+ component(`${id}-search`, 'globalSearch', { placeholder: options.searchLabel, label: options.searchLabel, urlKey: `${options.urlKey}q` }),
69
+ component(`${id}-views`, 'savedViewsMenu', { views: fromQuery(queries.views), savePermission: 'enabled', managePermission: 'enabled' }),
70
+ component(`${id}-columns`, 'columnChooser', { columns: fromQuery(queries.columnChoices) }),
71
+ ],
72
+ filters: [component(`${id}-filter`, 'filterBuilder', { fields: fromQuery(queries.filterFields), ...localeOfData })],
73
+ list: [options.recordScreen ? withBehaviors(list, opensRecordOnSelect(listId, options.recordScreen)) : list],
74
+ bulkBar: options.recordScreen || options.readOnly ? [] : [component(`${id}-bulk`, 'bulkBar', { selection: fromQuery(queries.selection), actions: options.bulkActions })],
75
+ footer: [],
76
+ },
77
+ displayName: options.displayName,
78
+ description: options.description,
79
+ metadata: inventoryMetadata(options.name, 'List', listScopes),
80
+ };
81
+ }
82
+
83
+ /** The items: what is stored, how much of it and where. Items running low are tinted and say "Low stock" in their status. Choosing a row opens the item. */
84
+ export const inventoryItemListTemplate = listTemplateOf({
85
+ name: 'InventoryItemList', entity: InventoryEntityKind.Item, displayName: 'Inventory items', description: 'Items with sku, category, location, quantity and status, low stock highlighted, filtered by category, location and status.',
86
+ title: 'Items', subtitle: 'Everything in stock, low stock highlighted', searchLabel: 'Search items', urlKey: 'items', primary: { label: 'New item', dialog: 'InventoryQuickCreateItem' },
87
+ rowActions: ['Adjust stock', 'Check out', 'Archive'], bulkActions: [], titleField: 'name', recordScreen: 'inventory.items.record', toneField: 'tone',
88
+ });
89
+
90
+ /** The items as a gallery: the same records as cards, each with its picture, for finding a thing by how it looks. */
91
+ export const inventoryItemGalleryTemplate = listTemplateOf({
92
+ name: 'InventoryItemGallery', entity: InventoryEntityKind.Item, displayName: 'Inventory item gallery', description: 'Items as cards with a picture, sku, quantity and status, low stock highlighted.',
93
+ title: 'Item gallery', subtitle: 'Items by how they look', searchLabel: 'Search items', urlKey: 'gallery', primary: { label: 'New item', dialog: 'InventoryQuickCreateItem' },
94
+ rowActions: ['Adjust stock', 'Check out', 'Archive'], bulkActions: [], titleField: 'name', recordScreen: 'inventory.items.record', toneField: 'tone', cards: { imageField: 'photo' },
95
+ });
96
+
97
+ /** The movements: every time stock came in, went out, moved or was corrected, newest first. Nothing in it is edited. */
98
+ export const inventoryMovementListTemplate = listTemplateOf({
99
+ name: 'InventoryMovementList', entity: InventoryEntityKind.Movement, displayName: 'Inventory movements', description: 'Check ins, check outs, transfers and adjustments with the item, quantity, location and who did it.',
100
+ title: 'Movements', subtitle: 'What came in, went out and moved', searchLabel: 'Search movements', urlKey: 'movements', primary: { label: 'Check in or out', screen: 'inventory.movements.check' },
101
+ rowActions: ['View item'], bulkActions: [], titleField: 'item', readOnly: true,
102
+ });
103
+
104
+ /** The suppliers: who items are bought from, how to reach them and how many items they supply. */
105
+ export const inventorySupplierListTemplate = listTemplateOf({
106
+ name: 'InventorySupplierList', entity: InventoryEntityKind.Supplier, displayName: 'Inventory suppliers', description: 'Suppliers with their contact, the items they supply and their status.',
107
+ title: 'Suppliers', subtitle: 'Where the stock comes from', searchLabel: 'Search suppliers', urlKey: 'suppliers', primary: { label: 'New supplier', dialog: 'InventoryQuickCreateSupplier' },
108
+ rowActions: ['Edit', 'Deactivate'], bulkActions: ['Deactivate'], titleField: 'name',
109
+ });
@@ -0,0 +1,36 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import { ScreenTemplate, TemplateScope } from '@cratis/scene.model';
5
+ import { masterDetailScreenTemplate } from '@cratis/scene.blueprint.default';
6
+ import { InventoryQuery, fromQuery, localeOfData } from '../inventoryQueries';
7
+ import { actionButton, component, inventoryMetadata, opensDialog, withBehaviors } from '../inventoryParts';
8
+
9
+ /**
10
+ * The locations: the foundation `MasterDetail` with the tree of locations - warehouse, aisle, shelf - on the left and, on the right, what is stored in the one
11
+ * chosen, or in everything beneath it. The tree keeps the chosen location in the address under the parameter the contents list searches by, and a
12
+ * location's id is its path, so the contents are every row whose location starts with it - and a link or a refresh restores the choice. On a phone the two become a navigation stack. It fills the shell's `content` slot itself
13
+ * rather than the module workspace's, so a module without a workspace can use it.
14
+ */
15
+ export const inventoryLocationsTemplate: ScreenTemplate = {
16
+ name: 'InventoryLocations',
17
+ fitsSlot: 'content',
18
+ slots: masterDetailScreenTemplate.slots,
19
+ arrangement: masterDetailScreenTemplate.arrangement,
20
+ content: {
21
+ list: [component('inventory-locations-tree', 'orgTree', {
22
+ nodes: fromQuery(InventoryQuery.LocationNodes), expandedDepth: 2, urlKey: 'contentsq', strings: { orgTree: 'Locations', orgReports: '{count} locations beneath' }, ...localeOfData,
23
+ })],
24
+ details: [
25
+ component('inventory-locations-header', 'pageHeader', { title: 'Contents', subtitle: 'What is stored in the chosen location and beneath it' }, {
26
+ actions: [withBehaviors(actionButton('inventory-locations-adjust', 'Adjust stock', 'primary'), opensDialog('InventoryAdjustStock'))],
27
+ }),
28
+ component('inventory-locations-contents', 'dataList', {
29
+ label: 'Location contents', rows: fromQuery(InventoryQuery.LocationContents), columns: fromQuery(InventoryQuery.LocationContentColumns), titleField: 'name', pageSize: 10, toneField: 'tone', urlKey: 'contents', ...localeOfData,
30
+ }),
31
+ ],
32
+ },
33
+ displayName: 'Inventory locations',
34
+ description: 'The tree of locations beside what is stored in the chosen location.',
35
+ metadata: inventoryMetadata('InventoryLocations', 'Workspace', [TemplateScope.Module, TemplateScope.Feature]),
36
+ };
@@ -0,0 +1,45 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import { ScreenTemplate, TemplateScope } from '@cratis/scene.model';
5
+ import { recordPageTemplate } from '@cratis/scene.blueprint.default';
6
+ import { InventoryEntityKind, InventoryQuery, currencyOfData, fromQuery, inventoryQueriesOf, localeOfData } from '../inventoryQueries';
7
+ import { actionButton, component, goesTo, inventoryMetadata, opensDialog, withBehaviors } from '../inventoryParts';
8
+
9
+ const queries = inventoryQueriesOf(InventoryEntityKind.Item);
10
+
11
+ /**
12
+ * The item page: the foundation `RecordPage` with the item's name as its title, Adjust stock and Check out as its actions, its key facts under it, the record's
13
+ * fields with the supplier's details, the stock of the item in each location and its movement history as related lists, and the cycle counts to do beside it.
14
+ */
15
+ export const inventoryItemPageTemplate: ScreenTemplate = {
16
+ name: 'InventoryItemPage',
17
+ fitsSlot: 'content',
18
+ slots: recordPageTemplate.slots,
19
+ arrangement: recordPageTemplate.arrangement,
20
+ content: {
21
+ header: [component('InventoryItemPage-header', 'pageHeader', { title: fromQuery(queries.record, '0.name'), subtitle: 'Item' }, {
22
+ actions: [
23
+ withBehaviors(actionButton('InventoryItemPage-check', 'Check out', 'secondary'), goesTo('inventory.movements.check')),
24
+ withBehaviors(actionButton('InventoryItemPage-adjust', 'Adjust stock', 'primary'), opensDialog('InventoryAdjustStock')),
25
+ ],
26
+ })],
27
+ summary: [
28
+ component('InventoryItemPage-status', 'statusChip', { status: fromQuery(queries.summary, '0.status'), tone: fromQuery(queries.summary, '0.tone') }),
29
+ component('InventoryItemPage-onhand', 'statCard', { label: 'On hand', value: fromQuery(queries.summary, '0.onHand'), ...localeOfData }),
30
+ component('InventoryItemPage-reorder', 'statCard', { label: 'Reorder level', value: fromQuery(queries.summary, '0.reorderLevel'), ...localeOfData }),
31
+ component('InventoryItemPage-value', 'statCard', { label: 'Stock value', value: fromQuery(queries.summary, '0.stockValue'), format: 'currency', fractionDigits: 0, ...currencyOfData }),
32
+ ],
33
+ tabs: [component('InventoryItemPage-tabs', 'tabSet', { tabs: fromQuery(InventoryQuery.RecordTabs), urlKey: 'tab', label: 'Item sections' })],
34
+ main: [component('InventoryItemPage-form', 'formScreenBody', { mode: 'readOnly', sections: fromQuery(queries.sections), values: fromQuery(queries.record, '0'), ...localeOfData })],
35
+ related: [
36
+ component('InventoryItemPage-stock', 'dataList', { label: 'Stock by location', rows: fromQuery(queries.stockByLocation), columns: fromQuery('StockByLocationColumns'), titleField: 'location', pageSize: 5, ...localeOfData }),
37
+ component('InventoryItemPage-movements', 'dataList', { label: 'Movement history', rows: fromQuery(queries.movements), columns: fromQuery(inventoryQueriesOf(InventoryEntityKind.Movement).columns), titleField: 'item', pageSize: 5, ...localeOfData }),
38
+ ],
39
+ activity: [component('InventoryItemPage-activity', 'activityFeed', { label: 'Activity', entries: fromQuery(queries.activity), ...localeOfData })],
40
+ aside: [component('InventoryItemPage-tasks', 'checklistSection', { label: 'Cycle counts', sections: fromQuery(queries.tasks), ...localeOfData })],
41
+ },
42
+ displayName: 'Inventory item page',
43
+ description: 'One item: key facts, its fields and supplier, its stock by location and its movement history.',
44
+ metadata: inventoryMetadata('InventoryItemPage', 'Detail', [TemplateScope.Feature, TemplateScope.Subfeature]),
45
+ };
@@ -0,0 +1,12 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="320" height="200" viewBox="0 0 320 200" role="img" aria-label="Inventory adjust stock">
2
+ <rect x="0" y="0" width="320" height="200" rx="8" fill="#f4f5f7"/>
3
+ <rect x="12" y="12" width="296" height="20" rx="4" fill="#0f766e"/>
4
+ <rect x="12" y="40" width="64" height="148" rx="4" fill="#d5d9df"/>
5
+ <rect x="84" y="40" width="224" height="148" rx="4" fill="#e6e9ee"/>
6
+ <rect x="114" y="62" width="164" height="108" rx="4" fill="#ffffff" stroke="#d5d9df"/>
7
+ <rect x="124" y="70" width="60" height="6" rx="3" fill="#0f766e"/>
8
+ <rect x="124" y="88" width="144" height="14" rx="4" fill="#ffffff" stroke="#d5d9df"/>
9
+ <rect x="124" y="108" width="144" height="14" rx="4" fill="#ffffff" stroke="#d5d9df"/>
10
+ <rect x="124" y="140" width="54" height="20" rx="4" fill="#0f766e"/>
11
+ <rect x="184" y="140" width="54" height="20" rx="4" fill="#d5d9df"/>
12
+ </svg>
@@ -0,0 +1,17 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="320" height="200" viewBox="0 0 320 200" role="img" aria-label="Inventory check in and out">
2
+ <rect x="0" y="0" width="320" height="200" rx="8" fill="#f4f5f7"/>
3
+ <rect x="12" y="12" width="296" height="20" rx="4" fill="#0f766e"/>
4
+ <rect x="12" y="40" width="64" height="148" rx="4" fill="#d5d9df"/>
5
+ <rect x="84" y="40" width="224" height="148" rx="4" fill="#ffffff" stroke="#d5d9df"/>
6
+ <rect x="94" y="48" width="60" height="6" rx="3" fill="#0f766e"/>
7
+ <rect x="94" y="66" width="98" height="24" rx="4" fill="#ffffff" stroke="#d5d9df"/>
8
+ <rect x="94" y="60" width="30" height="4" rx="2" fill="#9aa3b2"/>
9
+ <rect x="202" y="66" width="98" height="24" rx="4" fill="#ffffff" stroke="#d5d9df"/>
10
+ <rect x="202" y="60" width="30" height="4" rx="2" fill="#9aa3b2"/>
11
+ <rect x="94" y="102" width="98" height="24" rx="4" fill="#ffffff" stroke="#d5d9df"/>
12
+ <rect x="94" y="96" width="30" height="4" rx="2" fill="#9aa3b2"/>
13
+ <rect x="202" y="102" width="98" height="24" rx="4" fill="#ffffff" stroke="#d5d9df"/>
14
+ <rect x="202" y="96" width="30" height="4" rx="2" fill="#9aa3b2"/>
15
+ <rect x="94" y="160" width="50" height="20" rx="4" fill="#0f766e"/>
16
+ <rect x="150" y="160" width="50" height="20" rx="4" fill="#d5d9df"/>
17
+ </svg>
@@ -0,0 +1,14 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="320" height="200" viewBox="0 0 320 200" role="img" aria-label="Inventory dashboard">
2
+ <rect x="0" y="0" width="320" height="200" rx="8" fill="#f4f5f7"/>
3
+ <rect x="12" y="12" width="296" height="20" rx="4" fill="#0f766e"/>
4
+ <rect x="12" y="40" width="64" height="148" rx="4" fill="#d5d9df"/>
5
+ <rect x="84" y="40" width="70" height="30" rx="4" fill="#ffffff" stroke="#d5d9df"/>
6
+ <rect x="160" y="40" width="70" height="30" rx="4" fill="#ffffff" stroke="#d5d9df"/>
7
+ <rect x="236" y="40" width="70" height="30" rx="4" fill="#ffffff" stroke="#d5d9df"/>
8
+ <rect x="84" y="78" width="108" height="52" rx="4" fill="#ffffff" stroke="#d5d9df"/>
9
+ <rect x="200" y="78" width="108" height="52" rx="4" fill="#ffffff" stroke="#d5d9df"/>
10
+ <rect x="84" y="138" width="224" height="50" rx="4" fill="#ffffff" stroke="#d5d9df"/>
11
+ <rect x="92" y="108" width="12" height="18" rx="2" fill="#0f766e"/>
12
+ <rect x="110" y="100" width="12" height="26" rx="2" fill="#0f766e"/>
13
+ <rect x="128" y="92" width="12" height="34" rx="2" fill="#0f766e"/>
14
+ </svg>
@@ -0,0 +1,29 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="320" height="200" viewBox="0 0 320 200" role="img" aria-label="Inventory item gallery">
2
+ <rect x="0" y="0" width="320" height="200" rx="8" fill="#f4f5f7"/>
3
+ <rect x="12" y="12" width="296" height="20" rx="4" fill="#0f766e"/>
4
+ <rect x="12" y="40" width="64" height="148" rx="4" fill="#d5d9df"/>
5
+ <rect x="84" y="40" width="68" height="70" rx="4" fill="#ffffff" stroke="#d5d9df"/>
6
+ <rect x="88" y="44" width="60" height="30" rx="4" fill="#d5d9df"/>
7
+ <rect x="90" y="82" width="40" height="5" rx="3" fill="#0f766e"/>
8
+ <rect x="90" y="94" width="52" height="5" rx="3" fill="#9aa3b2"/>
9
+ <rect x="160" y="40" width="68" height="70" rx="4" fill="#ffffff" stroke="#d5d9df"/>
10
+ <rect x="164" y="44" width="60" height="30" rx="4" fill="#d5d9df"/>
11
+ <rect x="166" y="82" width="40" height="5" rx="3" fill="#0f766e"/>
12
+ <rect x="166" y="94" width="52" height="5" rx="3" fill="#9aa3b2"/>
13
+ <rect x="236" y="40" width="68" height="70" rx="4" fill="#ffffff" stroke="#d5d9df"/>
14
+ <rect x="240" y="44" width="60" height="30" rx="4" fill="#d5d9df"/>
15
+ <rect x="242" y="82" width="40" height="5" rx="3" fill="#0f766e"/>
16
+ <rect x="242" y="94" width="52" height="5" rx="3" fill="#9aa3b2"/>
17
+ <rect x="84" y="116" width="68" height="70" rx="4" fill="#ffffff" stroke="#d5d9df"/>
18
+ <rect x="88" y="120" width="60" height="30" rx="4" fill="#d5d9df"/>
19
+ <rect x="90" y="158" width="40" height="5" rx="3" fill="#0f766e"/>
20
+ <rect x="90" y="170" width="52" height="5" rx="3" fill="#9aa3b2"/>
21
+ <rect x="160" y="116" width="68" height="70" rx="4" fill="#ffffff" stroke="#d5d9df"/>
22
+ <rect x="164" y="120" width="60" height="30" rx="4" fill="#d5d9df"/>
23
+ <rect x="166" y="158" width="40" height="5" rx="3" fill="#0f766e"/>
24
+ <rect x="166" y="170" width="52" height="5" rx="3" fill="#9aa3b2"/>
25
+ <rect x="236" y="116" width="68" height="70" rx="4" fill="#ffffff" stroke="#d5d9df"/>
26
+ <rect x="240" y="120" width="60" height="30" rx="4" fill="#d5d9df"/>
27
+ <rect x="242" y="158" width="40" height="5" rx="3" fill="#0f766e"/>
28
+ <rect x="242" y="170" width="52" height="5" rx="3" fill="#9aa3b2"/>
29
+ </svg>
@@ -0,0 +1,13 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="320" height="200" viewBox="0 0 320 200" role="img" aria-label="Inventory items">
2
+ <rect x="0" y="0" width="320" height="200" rx="8" fill="#f4f5f7"/>
3
+ <rect x="12" y="12" width="296" height="20" rx="4" fill="#0f766e"/>
4
+ <rect x="12" y="40" width="64" height="148" rx="4" fill="#d5d9df"/>
5
+ <rect x="84" y="40" width="224" height="148" rx="4" fill="#ffffff" stroke="#d5d9df"/>
6
+ <rect x="94" y="48" width="60" height="6" rx="3" fill="#0f766e"/>
7
+ <rect x="94" y="70" width="206" height="6" rx="3" fill="#9aa3b2"/>
8
+ <rect x="94" y="87" width="168" height="6" rx="3" fill="#9aa3b2"/>
9
+ <rect x="94" y="104" width="206" height="6" rx="3" fill="#9aa3b2"/>
10
+ <rect x="94" y="121" width="168" height="6" rx="3" fill="#9aa3b2"/>
11
+ <rect x="94" y="138" width="206" height="6" rx="3" fill="#9aa3b2"/>
12
+ <rect x="94" y="155" width="168" height="6" rx="3" fill="#9aa3b2"/>
13
+ </svg>
@@ -0,0 +1,18 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="320" height="200" viewBox="0 0 320 200" role="img" aria-label="Inventory item page">
2
+ <rect x="0" y="0" width="320" height="200" rx="8" fill="#f4f5f7"/>
3
+ <rect x="12" y="12" width="296" height="20" rx="4" fill="#0f766e"/>
4
+ <rect x="12" y="40" width="64" height="148" rx="4" fill="#d5d9df"/>
5
+ <rect x="84" y="40" width="224" height="30" rx="4" fill="#ffffff" stroke="#d5d9df"/>
6
+ <rect x="90" y="47" width="46" height="16" rx="3" fill="#d5d9df"/>
7
+ <rect x="144" y="47" width="46" height="16" rx="3" fill="#d5d9df"/>
8
+ <rect x="198" y="47" width="46" height="16" rx="3" fill="#d5d9df"/>
9
+ <rect x="252" y="47" width="46" height="16" rx="3" fill="#d5d9df"/>
10
+ <rect x="84" y="78" width="140" height="110" rx="4" fill="#ffffff" stroke="#d5d9df"/>
11
+ <rect x="92" y="90" width="120" height="6" rx="3" fill="#9aa3b2"/>
12
+ <rect x="92" y="107" width="98" height="6" rx="3" fill="#9aa3b2"/>
13
+ <rect x="92" y="124" width="120" height="6" rx="3" fill="#9aa3b2"/>
14
+ <rect x="92" y="141" width="98" height="6" rx="3" fill="#9aa3b2"/>
15
+ <rect x="92" y="158" width="120" height="6" rx="3" fill="#9aa3b2"/>
16
+ <rect x="232" y="78" width="76" height="52" rx="4" fill="#ffffff" stroke="#d5d9df"/>
17
+ <rect x="232" y="136" width="76" height="52" rx="4" fill="#ffffff" stroke="#d5d9df"/>
18
+ </svg>
@@ -0,0 +1,20 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="320" height="200" viewBox="0 0 320 200" role="img" aria-label="Inventory locations">
2
+ <rect x="0" y="0" width="320" height="200" rx="8" fill="#f4f5f7"/>
3
+ <rect x="12" y="12" width="296" height="20" rx="4" fill="#0f766e"/>
4
+ <rect x="12" y="40" width="64" height="148" rx="4" fill="#d5d9df"/>
5
+ <rect x="84" y="40" width="66" height="148" rx="4" fill="#ffffff" stroke="#d5d9df"/>
6
+ <rect x="90" y="54" width="54" height="6" rx="3" fill="#9aa3b2"/>
7
+ <rect x="90" y="71" width="44" height="6" rx="3" fill="#9aa3b2"/>
8
+ <rect x="90" y="88" width="54" height="6" rx="3" fill="#9aa3b2"/>
9
+ <rect x="90" y="105" width="44" height="6" rx="3" fill="#9aa3b2"/>
10
+ <rect x="90" y="122" width="54" height="6" rx="3" fill="#9aa3b2"/>
11
+ <rect x="90" y="139" width="44" height="6" rx="3" fill="#9aa3b2"/>
12
+ <rect x="158" y="40" width="150" height="148" rx="4" fill="#ffffff" stroke="#d5d9df"/>
13
+ <rect x="166" y="48" width="60" height="6" rx="3" fill="#0f766e"/>
14
+ <rect x="166" y="70" width="134" height="6" rx="3" fill="#9aa3b2"/>
15
+ <rect x="166" y="87" width="109" height="6" rx="3" fill="#9aa3b2"/>
16
+ <rect x="166" y="104" width="134" height="6" rx="3" fill="#9aa3b2"/>
17
+ <rect x="166" y="121" width="109" height="6" rx="3" fill="#9aa3b2"/>
18
+ <rect x="166" y="138" width="134" height="6" rx="3" fill="#9aa3b2"/>
19
+ <rect x="166" y="155" width="109" height="6" rx="3" fill="#9aa3b2"/>
20
+ </svg>
@@ -0,0 +1,13 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="320" height="200" viewBox="0 0 320 200" role="img" aria-label="Inventory movements">
2
+ <rect x="0" y="0" width="320" height="200" rx="8" fill="#f4f5f7"/>
3
+ <rect x="12" y="12" width="296" height="20" rx="4" fill="#0f766e"/>
4
+ <rect x="12" y="40" width="64" height="148" rx="4" fill="#d5d9df"/>
5
+ <rect x="84" y="40" width="224" height="148" rx="4" fill="#ffffff" stroke="#d5d9df"/>
6
+ <rect x="94" y="48" width="60" height="6" rx="3" fill="#0f766e"/>
7
+ <rect x="94" y="70" width="206" height="6" rx="3" fill="#9aa3b2"/>
8
+ <rect x="94" y="87" width="168" height="6" rx="3" fill="#9aa3b2"/>
9
+ <rect x="94" y="104" width="206" height="6" rx="3" fill="#9aa3b2"/>
10
+ <rect x="94" y="121" width="168" height="6" rx="3" fill="#9aa3b2"/>
11
+ <rect x="94" y="138" width="206" height="6" rx="3" fill="#9aa3b2"/>
12
+ <rect x="94" y="155" width="168" height="6" rx="3" fill="#9aa3b2"/>
13
+ </svg>
@@ -0,0 +1,12 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="320" height="200" viewBox="0 0 320 200" role="img" aria-label="Inventory quick create item">
2
+ <rect x="0" y="0" width="320" height="200" rx="8" fill="#f4f5f7"/>
3
+ <rect x="12" y="12" width="296" height="20" rx="4" fill="#0f766e"/>
4
+ <rect x="12" y="40" width="64" height="148" rx="4" fill="#d5d9df"/>
5
+ <rect x="84" y="40" width="224" height="148" rx="4" fill="#e6e9ee"/>
6
+ <rect x="114" y="62" width="164" height="108" rx="4" fill="#ffffff" stroke="#d5d9df"/>
7
+ <rect x="124" y="70" width="60" height="6" rx="3" fill="#0f766e"/>
8
+ <rect x="124" y="88" width="144" height="14" rx="4" fill="#ffffff" stroke="#d5d9df"/>
9
+ <rect x="124" y="108" width="144" height="14" rx="4" fill="#ffffff" stroke="#d5d9df"/>
10
+ <rect x="124" y="140" width="54" height="20" rx="4" fill="#0f766e"/>
11
+ <rect x="184" y="140" width="54" height="20" rx="4" fill="#d5d9df"/>
12
+ </svg>
@@ -0,0 +1,12 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="320" height="200" viewBox="0 0 320 200" role="img" aria-label="Inventory quick create supplier">
2
+ <rect x="0" y="0" width="320" height="200" rx="8" fill="#f4f5f7"/>
3
+ <rect x="12" y="12" width="296" height="20" rx="4" fill="#0f766e"/>
4
+ <rect x="12" y="40" width="64" height="148" rx="4" fill="#d5d9df"/>
5
+ <rect x="84" y="40" width="224" height="148" rx="4" fill="#e6e9ee"/>
6
+ <rect x="114" y="62" width="164" height="108" rx="4" fill="#ffffff" stroke="#d5d9df"/>
7
+ <rect x="124" y="70" width="60" height="6" rx="3" fill="#0f766e"/>
8
+ <rect x="124" y="88" width="144" height="14" rx="4" fill="#ffffff" stroke="#d5d9df"/>
9
+ <rect x="124" y="108" width="144" height="14" rx="4" fill="#ffffff" stroke="#d5d9df"/>
10
+ <rect x="124" y="140" width="54" height="20" rx="4" fill="#0f766e"/>
11
+ <rect x="184" y="140" width="54" height="20" rx="4" fill="#d5d9df"/>
12
+ </svg>
@@ -0,0 +1,13 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="320" height="200" viewBox="0 0 320 200" role="img" aria-label="Inventory suppliers">
2
+ <rect x="0" y="0" width="320" height="200" rx="8" fill="#f4f5f7"/>
3
+ <rect x="12" y="12" width="296" height="20" rx="4" fill="#0f766e"/>
4
+ <rect x="12" y="40" width="64" height="148" rx="4" fill="#d5d9df"/>
5
+ <rect x="84" y="40" width="224" height="148" rx="4" fill="#ffffff" stroke="#d5d9df"/>
6
+ <rect x="94" y="48" width="60" height="6" rx="3" fill="#0f766e"/>
7
+ <rect x="94" y="70" width="206" height="6" rx="3" fill="#9aa3b2"/>
8
+ <rect x="94" y="87" width="168" height="6" rx="3" fill="#9aa3b2"/>
9
+ <rect x="94" y="104" width="206" height="6" rx="3" fill="#9aa3b2"/>
10
+ <rect x="94" y="121" width="168" height="6" rx="3" fill="#9aa3b2"/>
11
+ <rect x="94" y="138" width="206" height="6" rx="3" fill="#9aa3b2"/>
12
+ <rect x="94" y="155" width="168" height="6" rx="3" fill="#9aa3b2"/>
13
+ </svg>
@@ -0,0 +1,14 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="320" height="200" viewBox="0 0 320 200" role="img" aria-label="Inventory and Assets blueprint">
2
+ <rect x="0" y="0" width="320" height="200" rx="8" fill="#f4f5f7"/>
3
+ <rect x="12" y="12" width="296" height="20" rx="4" fill="#0f766e"/>
4
+ <rect x="12" y="40" width="64" height="148" rx="4" fill="#d5d9df"/>
5
+ <rect x="84" y="40" width="70" height="30" rx="4" fill="#ffffff" stroke="#d5d9df"/>
6
+ <rect x="160" y="40" width="70" height="30" rx="4" fill="#ffffff" stroke="#d5d9df"/>
7
+ <rect x="236" y="40" width="70" height="30" rx="4" fill="#ffffff" stroke="#d5d9df"/>
8
+ <rect x="84" y="78" width="224" height="110" rx="4" fill="#ffffff" stroke="#d5d9df"/>
9
+ <rect x="94" y="90" width="200" height="6" rx="3" fill="#9aa3b2"/>
10
+ <rect x="94" y="107" width="164" height="6" rx="3" fill="#9aa3b2"/>
11
+ <rect x="94" y="124" width="200" height="6" rx="3" fill="#9aa3b2"/>
12
+ <rect x="94" y="141" width="164" height="6" rx="3" fill="#9aa3b2"/>
13
+ <rect x="94" y="158" width="200" height="6" rx="3" fill="#9aa3b2"/>
14
+ </svg>