This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
.pricing-review-step {
|
||||
align-content: start;
|
||||
}
|
||||
|
||||
.pricing-review-step__intro {
|
||||
margin: var(--space-2) 0 0;
|
||||
color: var(--color-text-muted);
|
||||
font-size: var(--text-sm);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import PricingReviewStep from './PricingReviewStep.vue';
|
||||
|
||||
export default { title: 'Molecules/PricingReviewStep', component: PricingReviewStep };
|
||||
|
||||
const inventory = [{ id: 'copy-1' }, { id: 'copy-2' }];
|
||||
|
||||
export const Empty = {
|
||||
args: {
|
||||
inventoryItemId: '', provider: 'fixture-provider', sourceIdentifier: '', observedPrice: '',
|
||||
overridePrice: '', overrideReason: '', inventory, refreshStatus: '',
|
||||
},
|
||||
};
|
||||
|
||||
export const Refreshing = {
|
||||
args: {
|
||||
inventoryItemId: 'copy-1', provider: 'fixture-provider', sourceIdentifier: 'fixture-copy-1', observedPrice: '2500',
|
||||
overridePrice: '', overrideReason: '', inventory, refreshStatus: 'PROCESSING', isSaving: true,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,57 @@
|
||||
<script setup>
|
||||
defineProps({
|
||||
inventoryItemId: { type: String, required: true },
|
||||
provider: { type: String, required: true },
|
||||
sourceIdentifier: { type: String, required: true },
|
||||
observedPrice: { type: String, required: true },
|
||||
overridePrice: { type: String, required: true },
|
||||
overrideReason: { type: String, required: true },
|
||||
inventory: { type: Array, required: true },
|
||||
refreshStatus: { type: String, default: '' },
|
||||
isSaving: { type: Boolean, default: false },
|
||||
});
|
||||
|
||||
defineEmits([
|
||||
'update:inventoryItemId',
|
||||
'update:provider',
|
||||
'update:sourceIdentifier',
|
||||
'update:observedPrice',
|
||||
'update:overridePrice',
|
||||
'update:overrideReason',
|
||||
'calculate',
|
||||
'refresh',
|
||||
'override',
|
||||
]);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form id="workflow-pricing" class="showcase-panel pricing-review-step" @submit.prevent="$emit('calculate')">
|
||||
<div>
|
||||
<p class="catalog-kicker">Step 5</p>
|
||||
<h2>Check Pricing</h2>
|
||||
<p class="pricing-review-step__intro">Record a source, refresh market data, or add a reasoned private override before listing.</p>
|
||||
</div>
|
||||
<label class="fixture-label" for="pricing-inventory">Inventory copy</label>
|
||||
<select id="pricing-inventory" :value="inventoryItemId" class="fixture-input" required @change="$emit('update:inventoryItemId', $event.target.value)">
|
||||
<option value="" disabled>Select a copy</option>
|
||||
<option v-for="item in inventory" :key="item.id" :value="item.id">{{ item.id }}</option>
|
||||
</select>
|
||||
<label class="fixture-label" for="pricing-provider">Provider</label>
|
||||
<input id="pricing-provider" :value="provider" class="fixture-input" required @input="$emit('update:provider', $event.target.value)" />
|
||||
<label class="fixture-label" for="pricing-source">Source identifier</label>
|
||||
<input id="pricing-source" :value="sourceIdentifier" class="fixture-input" required @input="$emit('update:sourceIdentifier', $event.target.value)" />
|
||||
<label class="fixture-label" for="pricing-price">Observed price (cents)</label>
|
||||
<input id="pricing-price" :value="observedPrice" class="fixture-input" type="number" min="1" required @input="$emit('update:observedPrice', $event.target.value)" />
|
||||
<button class="button button--primary" type="submit" :disabled="isSaving">Add observation and calculate</button>
|
||||
<button class="button button--secondary" type="button" :disabled="isSaving" @click="$emit('refresh')">Refresh from provider<span v-if="refreshStatus"> ({{ refreshStatus }})</span></button>
|
||||
<label class="fixture-label" for="override-price">Manual value (cents)</label>
|
||||
<input id="override-price" :value="overridePrice" class="fixture-input" type="number" min="0" @input="$emit('update:overridePrice', $event.target.value)" />
|
||||
<label class="fixture-label" for="override-reason">Override reason</label>
|
||||
<input id="override-reason" :value="overrideReason" class="fixture-input" minlength="3" @input="$emit('update:overrideReason', $event.target.value)" />
|
||||
<button class="button button--secondary" type="button" :disabled="isSaving" @click="$emit('override')">Save manual value</button>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use './PricingReviewStep.scss';
|
||||
</style>
|
||||
@@ -8,6 +8,7 @@ import ProductIdentityStep from "@/components/molecules/ProductIdentityStep.vue"
|
||||
import ProviderMappingStep from "@/components/molecules/ProviderMappingStep.vue";
|
||||
import InventoryCopyStep from "@/components/molecules/InventoryCopyStep.vue";
|
||||
import InventoryImagesStep from "@/components/molecules/InventoryImagesStep.vue";
|
||||
import PricingReviewStep from "@/components/molecules/PricingReviewStep.vue";
|
||||
import {
|
||||
createAdminInventory,
|
||||
createAdminProduct,
|
||||
@@ -870,94 +871,26 @@ onMounted(load);
|
||||
Record acquisition
|
||||
</button>
|
||||
</form>
|
||||
<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
|
||||
>
|
||||
<select
|
||||
id="pricing-inventory"
|
||||
v-model="pricingInventoryId"
|
||||
class="fixture-input"
|
||||
required
|
||||
>
|
||||
<option value="" disabled>Select a copy</option>
|
||||
<option v-for="item in inventory" :key="item.id" :value="item.id">
|
||||
{{ item.id }}
|
||||
</option>
|
||||
</select>
|
||||
<label class="fixture-label" for="pricing-provider">Provider</label>
|
||||
<input
|
||||
id="pricing-provider"
|
||||
v-model="pricingProvider"
|
||||
class="fixture-input"
|
||||
required
|
||||
/>
|
||||
<label class="fixture-label" for="pricing-source"
|
||||
>Source identifier</label
|
||||
>
|
||||
<input
|
||||
id="pricing-source"
|
||||
v-model="pricingSource"
|
||||
class="fixture-input"
|
||||
required
|
||||
/>
|
||||
<label class="fixture-label" for="pricing-price"
|
||||
>Observed price (cents)</label
|
||||
>
|
||||
<input
|
||||
id="pricing-price"
|
||||
v-model="pricingPrice"
|
||||
class="fixture-input"
|
||||
type="number"
|
||||
min="1"
|
||||
required
|
||||
/>
|
||||
<button
|
||||
class="button button--primary"
|
||||
type="submit"
|
||||
:disabled="isSaving"
|
||||
>
|
||||
Add observation and calculate
|
||||
</button>
|
||||
<button
|
||||
class="button button--secondary"
|
||||
type="button"
|
||||
:disabled="isSaving"
|
||||
@click="refreshPricing"
|
||||
>
|
||||
Refresh from provider<span v-if="refreshStatus">
|
||||
({{ refreshStatus }})</span
|
||||
>
|
||||
</button>
|
||||
<label class="fixture-label" for="override-price"
|
||||
>Manual value (cents)</label
|
||||
>
|
||||
<input
|
||||
id="override-price"
|
||||
v-model="overridePrice"
|
||||
class="fixture-input"
|
||||
type="number"
|
||||
min="0"
|
||||
/>
|
||||
<label class="fixture-label" for="override-reason"
|
||||
>Override reason</label
|
||||
>
|
||||
<input
|
||||
id="override-reason"
|
||||
v-model="overrideReason"
|
||||
class="fixture-input"
|
||||
minlength="3"
|
||||
/>
|
||||
<button
|
||||
class="button button--secondary"
|
||||
type="button"
|
||||
:disabled="isSaving"
|
||||
@click="overridePricing"
|
||||
>
|
||||
Save manual value
|
||||
</button>
|
||||
</form>
|
||||
<PricingReviewStep
|
||||
:inventory-item-id="pricingInventoryId"
|
||||
:provider="pricingProvider"
|
||||
:source-identifier="pricingSource"
|
||||
:observed-price="pricingPrice"
|
||||
:override-price="overridePrice"
|
||||
:override-reason="overrideReason"
|
||||
:inventory="inventory"
|
||||
:refresh-status="refreshStatus"
|
||||
:is-saving="isSaving"
|
||||
@update:inventory-item-id="pricingInventoryId = $event"
|
||||
@update:provider="pricingProvider = $event"
|
||||
@update:source-identifier="pricingSource = $event"
|
||||
@update:observed-price="pricingPrice = $event"
|
||||
@update:override-price="overridePrice = $event"
|
||||
@update:override-reason="overrideReason = $event"
|
||||
@calculate="calculatePricing"
|
||||
@refresh="refreshPricing"
|
||||
@override="overridePricing"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<section class="admin-list" aria-labelledby="products-title">
|
||||
|
||||
@@ -171,6 +171,7 @@ Remaining roadmap areas are approved external provider credentials/adapters, bro
|
||||
- Source mapping is now an extracted `ProviderMappingStep` molecule with Product/Provider/PRODUCT-vs-SEARCH mapping states, while preserving existing mapping loading and save behavior.
|
||||
- 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.
|
||||
- Pricing is now an extracted `PricingReviewStep` molecule covering observations, provider refresh, and reasoned manual overrides while preserving existing pricing API behavior.
|
||||
- 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.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user