-
{{ supplierDisplay }}
-
- {{ t('catalogOfferCard.labels.origin_label') }}: {{ originDisplay }}
-
-
{{ productName }}
+
+
+
+
+
+
+
+
{{ supplierDisplay }}
+
+
+
+
+ {{ originDisplay }}
+
+
+
+
+ {{ productName }}
+
+
+
+
+ {{ quantityDisplay }}
+
-
+
+
{{ priceDisplay }}
@@ -17,13 +34,13 @@
-
-
+
+
+
+
+ {{ row.distanceLabel }}
+
+
@@ -35,6 +52,7 @@ const props = withDefaults(defineProps<{
supplierName?: string
productName?: string
pricePerUnit?: number | null
+ quantity?: number | string | null
currency?: string | null
unit?: string | null
stages?: RouteStage[]
@@ -60,13 +78,25 @@ const originDisplay = computed(() => {
})
const priceDisplay = computed(() => {
- if (!props.pricePerUnit) return null
+ if (props.pricePerUnit == null) return null
const currSymbol = getCurrencySymbol(props.currency)
const unitName = getUnitName(props.unit)
- const formattedPrice = props.pricePerUnit.toLocaleString()
+ const formattedPrice = Number(props.pricePerUnit).toLocaleString()
return `${currSymbol}${formattedPrice}/${unitName}`
})
+const quantityDisplay = computed(() => {
+ if (props.quantity == null || props.quantity === '') return null
+ const quantityValue = Number(props.quantity)
+ if (Number.isNaN(quantityValue)) return null
+ const formattedQuantity = quantityValue.toLocaleString()
+ const unitName = getUnitName(props.unit)
+ return t('catalogOfferCard.labels.quantity_with_unit', {
+ quantity: formattedQuantity,
+ unit: unitName
+ })
+})
+
const getCurrencySymbol = (currency?: string | null) => {
switch (currency?.toUpperCase()) {
case 'USD': return '$'
@@ -80,14 +110,44 @@ const getCurrencySymbol = (currency?: string | null) => {
const getUnitName = (unit?: string | null) => {
switch (unit?.toLowerCase()) {
case 'т':
+ case 't':
case 'ton':
case 'tonne':
- return 'тонна'
+ return t('catalogOfferCard.labels.default_unit')
case 'кг':
case 'kg':
- return 'кг'
+ return t('catalogOfferCard.labels.unit_kg')
default:
- return 'тонна'
+ return t('catalogOfferCard.labels.default_unit')
}
}
+
+const formatDistance = (km?: number | null) => {
+ if (km == null) return null
+ const formatted = Math.round(km).toLocaleString()
+ return t('catalogOfferCard.labels.distance_km', { km: formatted })
+}
+
+const getTransportIcon = (type?: string | null) => {
+ switch (type) {
+ case 'rail':
+ return 'lucide:train-front'
+ case 'sea':
+ return 'lucide:ship'
+ case 'road':
+ case 'auto':
+ default:
+ return 'lucide:truck'
+ }
+}
+
+const routeRows = computed(() =>
+ (props.stages || [])
+ .filter(stage => stage?.distanceKm != null)
+ .map(stage => ({
+ icon: getTransportIcon(stage?.transportType),
+ distanceLabel: formatDistance(stage?.distanceKm)
+ }))
+ .filter(row => !!row.distanceLabel)
+)
diff --git a/app/components/catalog/QuotePanel.vue b/app/components/catalog/QuotePanel.vue
index 6dfe02b..50d16f5 100644
--- a/app/components/catalog/QuotePanel.vue
+++ b/app/components/catalog/QuotePanel.vue
@@ -31,6 +31,7 @@
:location-name="offer.locationName || offer.locationCountry"
:product-name="offer.productName"
:price-per-unit="offer.pricePerUnit ? Number(offer.pricePerUnit) : null"
+ :quantity="offer.quantity"
:currency="offer.currency"
:unit="offer.unit"
:stages="[]"
diff --git a/i18n/locales/en/catalogOfferCard.json b/i18n/locales/en/catalogOfferCard.json
index fe669aa..57b8f61 100644
--- a/i18n/locales/en/catalogOfferCard.json
+++ b/i18n/locales/en/catalogOfferCard.json
@@ -3,6 +3,8 @@
"labels": {
"quantity_with_unit": "{quantity} {unit}",
"default_unit": "t",
+ "unit_kg": "kg",
+ "distance_km": "{km} km",
"country_unknown": "Not specified",
"supplier_unknown": "Supplier",
"origin_label": "From",
diff --git a/i18n/locales/ru/catalogOfferCard.json b/i18n/locales/ru/catalogOfferCard.json
index 310d74f..b645558 100644
--- a/i18n/locales/ru/catalogOfferCard.json
+++ b/i18n/locales/ru/catalogOfferCard.json
@@ -3,6 +3,8 @@
"labels": {
"quantity_with_unit": "{quantity} {unit}",
"default_unit": "т",
+ "unit_kg": "кг",
+ "distance_km": "{km} км",
"country_unknown": "Не указана",
"supplier_unknown": "Поставщик",
"origin_label": "Откуда",