feat: extract review and list workflow step
Quality / test (push) Canceled after 0s

This commit is contained in:
2026-09-10 06:03:48 -04:00
parent 82b012faa1
commit ae1605c82d
5 changed files with 87 additions and 35 deletions
@@ -0,0 +1,9 @@
.review-list-step {
align-content: start;
}
.review-list-step__intro {
margin: var(--space-2) 0 0;
color: var(--color-text-muted);
font-size: var(--text-sm);
}
@@ -0,0 +1,16 @@
import ReviewListStep from './ReviewListStep.vue';
export default { title: 'Molecules/ReviewListStep', component: ReviewListStep };
const inventory = [
{ id: 'copy-1', status: 'ACTIVE' },
{ id: 'copy-2', status: 'ARCHIVED' },
];
export const Ready = {
args: { inventoryItemId: 'copy-1', askingPrice: '2499', inventory, isSaving: false },
};
export const Empty = {
args: { inventoryItemId: '', askingPrice: '', inventory, isSaving: false },
};
@@ -0,0 +1,50 @@
<script setup>
defineProps({
inventoryItemId: { type: String, required: true },
askingPrice: { type: String, required: true },
inventory: { type: Array, required: true },
isSaving: { type: Boolean, default: false },
});
defineEmits(['update:inventoryItemId', 'update:askingPrice', 'submit']);
</script>
<template>
<form id="workflow-listing" class="showcase-panel review-list-step" @submit.prevent="$emit('submit')">
<div>
<p class="catalog-kicker">Step 6</p>
<h2>Review and List</h2>
<p class="review-list-step__intro">Confirm the physical copy and asking price. Images, condition, and product identity are checked before publishing.</p>
</div>
<label class="fixture-label" for="listing-inventory">Inventory copy</label>
<select
id="listing-inventory"
:value="inventoryItemId"
class="fixture-input"
required
@change="$emit('update:inventoryItemId', $event.target.value)"
>
<option value="" disabled>Select a physical copy</option>
<option v-for="item in inventory" :key="item.id" :value="item.id">
{{ item.id }} · {{ item.status }}
</option>
</select>
<label class="fixture-label" for="listing-price">Asking price (cents)</label>
<input
id="listing-price"
:value="askingPrice"
class="fixture-input"
type="number"
min="1"
required
@input="$emit('update:askingPrice', $event.target.value)"
/>
<button class="button button--primary" type="submit" :disabled="isSaving">
Create listing draft
</button>
</form>
</template>
<style scoped lang="scss">
@use './ReviewListStep.scss';
</style>
+9 -34
View File
@@ -9,6 +9,7 @@ import ProviderMappingStep from "@/components/molecules/ProviderMappingStep.vue"
import InventoryCopyStep from "@/components/molecules/InventoryCopyStep.vue"; import InventoryCopyStep from "@/components/molecules/InventoryCopyStep.vue";
import InventoryImagesStep from "@/components/molecules/InventoryImagesStep.vue"; import InventoryImagesStep from "@/components/molecules/InventoryImagesStep.vue";
import PricingReviewStep from "@/components/molecules/PricingReviewStep.vue"; import PricingReviewStep from "@/components/molecules/PricingReviewStep.vue";
import ReviewListStep from "@/components/molecules/ReviewListStep.vue";
import { import {
createAdminInventory, createAdminInventory,
createAdminProduct, createAdminProduct,
@@ -714,41 +715,15 @@ onMounted(load);
@update:condition-id="conditionId = $event" @update:condition-id="conditionId = $event"
@submit="createInventory" @submit="createInventory"
/> />
<form id="workflow-listing" class="showcase-panel" @submit.prevent="createListing"> <ReviewListStep
<h2>Create listing draft</h2> :inventory-item-id="listingInventoryId"
<label class="fixture-label" for="listing-inventory" :asking-price="askingPrice"
>Inventory copy</label :inventory="inventory"
> :is-saving="isSaving"
<select @update:inventory-item-id="listingInventoryId = $event"
id="listing-inventory" @update:asking-price="askingPrice = $event"
v-model="listingInventoryId" @submit="createListing"
class="fixture-input"
required
>
<option value="" disabled>Select a physical copy</option>
<option v-for="item in inventory" :key="item.id" :value="item.id">
{{ item.id }} · {{ item.status }}
</option>
</select>
<label class="fixture-label" for="listing-price"
>Asking price (cents)</label
>
<input
id="listing-price"
v-model="askingPrice"
class="fixture-input"
type="number"
min="1"
required
/> />
<button
class="button button--primary"
type="submit"
:disabled="isSaving"
>
Create listing
</button>
</form>
<form class="showcase-panel" @submit.prevent="recordSale"> <form class="showcase-panel" @submit.prevent="recordSale">
<h2>Record sale</h2> <h2>Record sale</h2>
<label class="fixture-label" for="sale-inventory">Inventory copy</label> <label class="fixture-label" for="sale-inventory">Inventory copy</label>
+2
View File
@@ -172,6 +172,8 @@ Remaining roadmap areas are approved external provider credentials/adapters, bro
- Physical inventory creation is now an extracted `InventoryCopyStep` molecule with Product and condition selection states, while preserving the existing seller-scoped create-copy API workflow. - Physical inventory creation is now an extracted `InventoryCopyStep` molecule with Product and condition selection states, while preserving the existing seller-scoped create-copy API workflow.
- Image management is now surfaced as an extracted `InventoryImagesStep` molecule with missing-image status and direct links to the existing upload/processing manager route. - Image management is now surfaced as an extracted `InventoryImagesStep` molecule with missing-image status and direct links to the existing upload/processing manager route.
- Pricing is now an extracted `PricingReviewStep` molecule covering observations, provider refresh, and reasoned manual overrides while preserving existing pricing API behavior. - Pricing is now an extracted `PricingReviewStep` molecule covering observations, provider refresh, and reasoned manual overrides while preserving existing pricing API behavior.
- Review and listing is now an extracted `ReviewListStep` molecule covering physical-copy selection and asking-price confirmation while preserving existing draft creation and publication lifecycle behavior.
- The guided inventory workflow now has extracted Product, Source Mapping, Physical Copy, Images, Pricing, and Review/List frontend stages, each with colocated Storybook coverage.
- Public catalog sorting now supports latest manual/calculated market value low-to-high and high-to-low, with null values placed last. - Public catalog sorting now supports latest manual/calculated market value low-to-high and high-to-low, with null values placed last.
- Public catalog filters now collapse behind an accessible mobile disclosure, show an active-filter count, and provide a reset action while preserving URL synchronization. - Public catalog filters now collapse behind an accessible mobile disclosure, show an active-filter count, and provide a reset action while preserving URL synchronization.