Initial commit from monorepo
This commit is contained in:
95
app/components/catalog/SupplierCard.vue
Normal file
95
app/components/catalog/SupplierCard.vue
Normal file
@@ -0,0 +1,95 @@
|
||||
<template>
|
||||
<component
|
||||
:is="linkable ? NuxtLink : 'div'"
|
||||
:to="linkable ? localePath(`/catalog/suppliers/${supplier.teamUuid || supplier.uuid}`) : undefined"
|
||||
class="block"
|
||||
:class="{ 'cursor-pointer': selectable }"
|
||||
@click="selectable && $emit('select')"
|
||||
>
|
||||
<Card
|
||||
padding="small"
|
||||
:interactive="linkable || selectable"
|
||||
:class="[
|
||||
isSelected && 'ring-2 ring-primary ring-offset-2'
|
||||
]"
|
||||
>
|
||||
<div class="flex flex-col gap-1">
|
||||
<!-- Logo -->
|
||||
<div v-if="supplier.logo" class="w-12 h-12 mb-1">
|
||||
<img :src="supplier.logo" :alt="supplier.name || ''" class="w-full h-full object-contain rounded">
|
||||
</div>
|
||||
<div v-else class="w-12 h-12 bg-primary/10 text-primary font-bold rounded flex items-center justify-center text-lg mb-1">
|
||||
{{ supplier.name?.charAt(0) }}
|
||||
</div>
|
||||
<!-- Title -->
|
||||
<Text size="base" weight="semibold" class="truncate">{{ supplier.name }}</Text>
|
||||
<!-- Badges -->
|
||||
<div class="flex flex-wrap gap-1">
|
||||
<span v-if="supplier.isVerified" class="badge badge-neutral badge-dash text-xs">
|
||||
{{ t('catalogSupplier.badges.verified') }}
|
||||
</span>
|
||||
<span class="badge badge-neutral badge-dash text-xs">
|
||||
{{ reliabilityLabel }}
|
||||
</span>
|
||||
</div>
|
||||
<!-- Country below -->
|
||||
<Text tone="muted" size="sm">
|
||||
{{ countryFlag }} {{ supplier.country || t('catalogMap.labels.country_unknown') }}
|
||||
</Text>
|
||||
</div>
|
||||
</Card>
|
||||
</component>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { NuxtLink } from '#components'
|
||||
|
||||
interface Supplier {
|
||||
uuid?: string | null
|
||||
teamUuid?: string | null
|
||||
name?: string | null
|
||||
country?: string | null
|
||||
countryCode?: string | null
|
||||
logo?: string | null
|
||||
onTimeRate?: number | null
|
||||
offersCount?: number | null
|
||||
isVerified?: boolean | null
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
supplier: Supplier
|
||||
selectable?: boolean
|
||||
isSelected?: boolean
|
||||
}>()
|
||||
|
||||
defineEmits<{
|
||||
(e: 'select'): void
|
||||
}>()
|
||||
|
||||
const localePath = useLocalePath()
|
||||
const { t } = useI18n()
|
||||
|
||||
const linkable = computed(() => !props.selectable && (props.supplier.teamUuid || props.supplier.uuid))
|
||||
|
||||
const reliabilityLabel = computed(() => {
|
||||
if (props.supplier.onTimeRate !== undefined && props.supplier.onTimeRate !== null) {
|
||||
return t('catalogSupplier.labels.on_time', { percent: Math.round(props.supplier.onTimeRate * 100) })
|
||||
}
|
||||
if (props.supplier.isVerified) {
|
||||
return t('catalogSupplier.labels.trusted_partner')
|
||||
}
|
||||
return t('catalogSupplier.labels.on_time_default')
|
||||
})
|
||||
|
||||
// ISO code to emoji flag
|
||||
const isoToEmoji = (code: string): string => {
|
||||
return code.toUpperCase().split('').map(char => String.fromCodePoint(0x1F1E6 - 65 + char.charCodeAt(0))).join('')
|
||||
}
|
||||
|
||||
const countryFlag = computed(() => {
|
||||
if (props.supplier.countryCode) {
|
||||
return isoToEmoji(props.supplier.countryCode)
|
||||
}
|
||||
return '🌍'
|
||||
})
|
||||
</script>
|
||||
Reference in New Issue
Block a user