This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
.inventory-workflow {
|
||||
margin: var(--space-6) 0 var(--space-8);
|
||||
border: var(--border-thin) solid var(--color-border);
|
||||
border-radius: var(--radius-lg);
|
||||
background: var(--color-surface);
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.inventory-workflow__steps {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(6, minmax(10rem, 1fr));
|
||||
min-width: 680px;
|
||||
gap: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.inventory-workflow__step {
|
||||
border-right: var(--border-thin) solid var(--color-border);
|
||||
}
|
||||
|
||||
.inventory-workflow__step:last-child {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
.inventory-workflow__step a {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: var(--space-2);
|
||||
min-height: 76px;
|
||||
padding: var(--space-3);
|
||||
color: var(--color-text-subtle);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.inventory-workflow__step a:hover,
|
||||
.inventory-workflow__step a:focus-visible {
|
||||
background: var(--color-surface-muted);
|
||||
}
|
||||
|
||||
.inventory-workflow__index {
|
||||
display: grid;
|
||||
flex: 0 0 28px;
|
||||
place-items: center;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border: var(--border-thin) solid var(--color-border-strong);
|
||||
border-radius: var(--radius-full);
|
||||
color: var(--color-text-muted);
|
||||
font-size: var(--text-sm);
|
||||
font-weight: var(--weight-bold);
|
||||
}
|
||||
|
||||
.inventory-workflow__step strong,
|
||||
.inventory-workflow__step small {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.inventory-workflow__step small {
|
||||
margin-top: var(--space-1);
|
||||
color: var(--color-text-muted);
|
||||
font-size: var(--text-xs);
|
||||
}
|
||||
|
||||
.inventory-workflow__step--complete .inventory-workflow__index {
|
||||
border-color: var(--color-success-500);
|
||||
color: var(--color-success-text);
|
||||
}
|
||||
|
||||
.inventory-workflow__step--current .inventory-workflow__index {
|
||||
border-color: var(--color-interactive);
|
||||
color: var(--color-interactive-text);
|
||||
box-shadow: var(--glow-selection);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import InventoryWorkflowStepper from './InventoryWorkflowStepper.vue';
|
||||
|
||||
export default { title: 'Molecules/InventoryWorkflowStepper', component: InventoryWorkflowStepper };
|
||||
|
||||
export const InProgress = {
|
||||
args: {
|
||||
steps: [
|
||||
{ id: 'workflow-product', label: 'Product', description: 'Identify item', status: 'complete' },
|
||||
{ id: 'workflow-mapping', label: 'Sources', description: 'Link markets', status: 'current' },
|
||||
{ id: 'workflow-inventory', label: 'Copy', description: 'Add physical copy', status: 'pending' },
|
||||
{ id: 'workflow-images', label: 'Images', description: 'Add photos', status: 'pending' },
|
||||
{ id: 'workflow-pricing', label: 'Pricing', description: 'Check value', status: 'pending' },
|
||||
{ id: 'workflow-listing', label: 'List', description: 'Publish offer', status: 'pending' },
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export const Complete = {
|
||||
args: {
|
||||
steps: [
|
||||
{ id: 'workflow-product', label: 'Product', description: 'Identify item', status: 'complete' },
|
||||
{ id: 'workflow-mapping', label: 'Sources', description: 'Link markets', status: 'complete' },
|
||||
{ id: 'workflow-inventory', label: 'Copy', description: 'Add physical copy', status: 'complete' },
|
||||
{ id: 'workflow-images', label: 'Images', description: 'Add photos', status: 'complete' },
|
||||
{ id: 'workflow-pricing', label: 'Pricing', description: 'Check value', status: 'complete' },
|
||||
{ id: 'workflow-listing', label: 'List', description: 'Publish offer', status: 'complete' },
|
||||
],
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
<script setup>
|
||||
defineProps({
|
||||
steps: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<nav class="inventory-workflow" aria-label="Inventory creation workflow">
|
||||
<ol class="inventory-workflow__steps">
|
||||
<li v-for="(step, index) in steps" :key="step.id" :class="['inventory-workflow__step', `inventory-workflow__step--${step.status}`]">
|
||||
<a :href="`#${step.id}`">
|
||||
<span class="inventory-workflow__index">{{ index + 1 }}</span>
|
||||
<span>
|
||||
<strong>{{ step.label }}</strong>
|
||||
<small>{{ step.description }}</small>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use './InventoryWorkflowStepper.scss';
|
||||
</style>
|
||||
@@ -4,6 +4,7 @@ import { RouterLink } from "vue-router";
|
||||
|
||||
import { useAuth } from "@/composables/useAuth.js";
|
||||
import AdminListingStatus from "@/components/molecules/AdminListingStatus.vue";
|
||||
import InventoryWorkflowStepper from "@/components/molecules/InventoryWorkflowStepper.vue";
|
||||
import {
|
||||
createAdminInventory,
|
||||
createAdminProduct,
|
||||
@@ -62,6 +63,35 @@ const acquisitions = ref([]);
|
||||
const dashboard = ref(null);
|
||||
const valuations = ref({});
|
||||
const hasValuations = computed(() => Object.keys(valuations.value).length > 0);
|
||||
const workflowSteps = computed(() => {
|
||||
const completed = [
|
||||
products.value.length > 0,
|
||||
providerMappings.value.length > 0,
|
||||
inventory.value.length > 0,
|
||||
Boolean(dashboard.value && inventory.value.length && dashboard.value.counts.missingImages === 0),
|
||||
hasValuations.value,
|
||||
listings.value.some(({ status }) => status === "AVAILABLE"),
|
||||
];
|
||||
const currentIndex = completed.findIndex((isComplete) => !isComplete);
|
||||
const steps = [
|
||||
["workflow-product", "Product", "Identify item"],
|
||||
["workflow-mapping", "Sources", "Link markets"],
|
||||
["workflow-inventory", "Copy", "Add physical copy"],
|
||||
["workflow-images", "Images", "Add photos"],
|
||||
["workflow-pricing", "Pricing", "Check value"],
|
||||
["workflow-listing", "List", "Publish offer"],
|
||||
];
|
||||
return steps.map(([id, label, description], index) => ({
|
||||
id,
|
||||
label,
|
||||
description,
|
||||
status: completed[index]
|
||||
? "complete"
|
||||
: index === currentIndex
|
||||
? "current"
|
||||
: "pending",
|
||||
}));
|
||||
});
|
||||
const categories = ref([]);
|
||||
const conditions = ref([]);
|
||||
const isLoading = ref(true);
|
||||
@@ -642,8 +672,10 @@ onMounted(load);
|
||||
</dl>
|
||||
</section>
|
||||
|
||||
<InventoryWorkflowStepper :steps="workflowSteps" />
|
||||
|
||||
<div class="admin-workspace-grid">
|
||||
<form class="showcase-panel" @submit.prevent="createProduct">
|
||||
<form id="workflow-product" class="showcase-panel" @submit.prevent="createProduct">
|
||||
<h2>Add product</h2>
|
||||
<label class="fixture-label" for="product-name">Name</label>
|
||||
<input
|
||||
@@ -676,7 +708,7 @@ onMounted(load);
|
||||
Create product
|
||||
</button>
|
||||
</form>
|
||||
<form class="showcase-panel" @submit.prevent="createProviderMapping">
|
||||
<form id="workflow-mapping" class="showcase-panel" @submit.prevent="createProviderMapping">
|
||||
<h2>Link provider mapping</h2>
|
||||
<label class="fixture-label" for="mapping-product">Product</label>
|
||||
<select
|
||||
@@ -730,7 +762,7 @@ onMounted(load);
|
||||
Save provider mapping
|
||||
</button>
|
||||
</form>
|
||||
<form class="showcase-panel" @submit.prevent="createInventory">
|
||||
<form id="workflow-inventory" class="showcase-panel" @submit.prevent="createInventory">
|
||||
<h2>Add inventory copy</h2>
|
||||
<label class="fixture-label" for="inventory-product">Product</label>
|
||||
<select
|
||||
@@ -772,7 +804,7 @@ onMounted(load);
|
||||
Create copy
|
||||
</button>
|
||||
</form>
|
||||
<form class="showcase-panel" @submit.prevent="createListing">
|
||||
<form id="workflow-listing" class="showcase-panel" @submit.prevent="createListing">
|
||||
<h2>Create listing draft</h2>
|
||||
<label class="fixture-label" for="listing-inventory"
|
||||
>Inventory copy</label
|
||||
@@ -929,7 +961,7 @@ onMounted(load);
|
||||
Record acquisition
|
||||
</button>
|
||||
</form>
|
||||
<form class="showcase-panel" @submit.prevent="calculatePricing">
|
||||
<form id="workflow-pricing" class="showcase-panel" @submit.prevent="calculatePricing">
|
||||
<h2 id="pricing-title">Calculate market value</h2>
|
||||
<label class="fixture-label" for="pricing-inventory"
|
||||
>Inventory copy</label
|
||||
@@ -1047,6 +1079,7 @@ onMounted(load);
|
||||
class="admin-list"
|
||||
aria-labelledby="inventory-title"
|
||||
>
|
||||
<span id="workflow-images" aria-hidden="true"></span>
|
||||
<h2 id="inventory-title">Physical inventory</h2>
|
||||
<div class="admin-list__actions">
|
||||
<button
|
||||
|
||||
Reference in New Issue
Block a user