Add KycProfileCard component with full company info
Some checks failed
Build Docker Image / build (push) Has been cancelled
Some checks failed
Build Docker Image / build (push) Has been cancelled
- New KycProfileCard shows full KYC profile data (INN, OGRN, director, capital, activities) - Added to offer detail page /catalog/suppliers/[supplierId]/[productId]/[hubId] - Uses kycProfileFull endpoint for authorized detailed company info
This commit is contained in:
@@ -27,6 +27,7 @@
|
|||||||
:unit="getOfferData(option.sourceUuid)?.unit"
|
:unit="getOfferData(option.sourceUuid)?.unit"
|
||||||
:stages="getRouteStages(option)"
|
:stages="getRouteStages(option)"
|
||||||
:kyc-profile-uuid="getKycProfileUuid(option.sourceUuid)"
|
:kyc-profile-uuid="getKycProfileUuid(option.sourceUuid)"
|
||||||
|
@select="navigateToOffer(option.sourceUuid)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -68,6 +69,7 @@ import type { RouteStageItem } from '~/components/RouteStagesList.vue'
|
|||||||
import { GetOfferDocument, GetSupplierProfileByTeamDocument } from '~/composables/graphql/public/exchange-generated'
|
import { GetOfferDocument, GetSupplierProfileByTeamDocument } from '~/composables/graphql/public/exchange-generated'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
const localePath = useLocalePath()
|
||||||
const searchStore = useSearchStore()
|
const searchStore = useSearchStore()
|
||||||
const { execute } = useGraphQL()
|
const { execute } = useGraphQL()
|
||||||
|
|
||||||
@@ -175,6 +177,16 @@ const getKycProfileUuid = (offerUuid?: string | null) => {
|
|||||||
return supplier?.kycProfileUuid || null
|
return supplier?.kycProfileUuid || null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Navigate to offer detail page
|
||||||
|
const navigateToOffer = (offerUuid?: string | null) => {
|
||||||
|
if (!offerUuid) return
|
||||||
|
const offer = offersData.value.get(offerUuid)
|
||||||
|
if (!offer?.teamUuid || !productUuid.value || !destinationUuid.value) return
|
||||||
|
|
||||||
|
// Navigate to /catalog/suppliers/[supplierId]/[productId]/[hubId]
|
||||||
|
navigateTo(localePath(`/catalog/suppliers/${offer.teamUuid}/${productUuid.value}/${destinationUuid.value}`))
|
||||||
|
}
|
||||||
|
|
||||||
// Load offer details for prices
|
// Load offer details for prices
|
||||||
const loadOfferDetails = async (options: ProductRouteOption[]) => {
|
const loadOfferDetails = async (options: ProductRouteOption[]) => {
|
||||||
if (options.length === 0) {
|
if (options.length === 0) {
|
||||||
|
|||||||
155
app/components/KycProfileCard.vue
Normal file
155
app/components/KycProfileCard.vue
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
<template>
|
||||||
|
<Card v-if="kycProfileUuid" padding="md">
|
||||||
|
<!-- Loading -->
|
||||||
|
<div v-if="pending" class="flex items-center gap-2">
|
||||||
|
<Spinner size="sm" />
|
||||||
|
<Text tone="muted" size="sm">Загрузка данных о компании...</Text>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Error or no data -->
|
||||||
|
<div v-else-if="!profileData" class="text-sm text-base-content/60">
|
||||||
|
Данные о компании недоступны
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Profile data -->
|
||||||
|
<Stack v-else gap="4">
|
||||||
|
<!-- Header -->
|
||||||
|
<div class="flex items-start justify-between">
|
||||||
|
<div>
|
||||||
|
<Text weight="semibold" size="lg">{{ profileData.name }}</Text>
|
||||||
|
<div class="flex items-center gap-2 mt-1">
|
||||||
|
<span v-if="profileData.companyType" class="badge badge-outline badge-sm">
|
||||||
|
{{ profileData.companyType }}
|
||||||
|
</span>
|
||||||
|
<span v-if="profileData.registrationYear" class="text-xs text-base-content/60">
|
||||||
|
с {{ profileData.registrationYear }} г.
|
||||||
|
</span>
|
||||||
|
<span v-if="profileData.isActive" class="badge badge-success badge-xs">Активна</span>
|
||||||
|
<span v-else class="badge badge-error badge-xs">Неактивна</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Details grid -->
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
<!-- INN -->
|
||||||
|
<div v-if="profileData.inn">
|
||||||
|
<Text tone="muted" size="sm">ИНН</Text>
|
||||||
|
<Text weight="medium">{{ profileData.inn }}</Text>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- OGRN -->
|
||||||
|
<div v-if="profileData.ogrn">
|
||||||
|
<Text tone="muted" size="sm">ОГРН</Text>
|
||||||
|
<Text weight="medium">{{ profileData.ogrn }}</Text>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Director -->
|
||||||
|
<div v-if="profileData.director">
|
||||||
|
<Text tone="muted" size="sm">Руководитель</Text>
|
||||||
|
<Text weight="medium">{{ profileData.director }}</Text>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Capital -->
|
||||||
|
<div v-if="profileData.capital">
|
||||||
|
<Text tone="muted" size="sm">Уставный капитал</Text>
|
||||||
|
<Text weight="medium">{{ profileData.capital }}</Text>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Address -->
|
||||||
|
<div v-if="profileData.address" class="md:col-span-2">
|
||||||
|
<Text tone="muted" size="sm">Адрес</Text>
|
||||||
|
<Text weight="medium">{{ profileData.address }}</Text>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Activities -->
|
||||||
|
<div v-if="profileData.activities?.length" class="md:col-span-2">
|
||||||
|
<Text tone="muted" size="sm">Виды деятельности</Text>
|
||||||
|
<div class="flex flex-wrap gap-1 mt-1">
|
||||||
|
<span
|
||||||
|
v-for="(activity, idx) in profileData.activities.slice(0, 5)"
|
||||||
|
:key="idx"
|
||||||
|
class="badge badge-ghost badge-sm"
|
||||||
|
>
|
||||||
|
{{ activity }}
|
||||||
|
</span>
|
||||||
|
<span v-if="profileData.activities.length > 5" class="text-xs text-base-content/60">
|
||||||
|
+{{ profileData.activities.length - 5 }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Footer: sources and last updated -->
|
||||||
|
<div class="flex items-center justify-between text-xs text-base-content/50 pt-2 border-t border-base-200">
|
||||||
|
<span v-if="profileData.sources?.length">
|
||||||
|
Источники: {{ profileData.sources.join(', ') }}
|
||||||
|
</span>
|
||||||
|
<span v-if="profileData.lastUpdated">
|
||||||
|
Обновлено: {{ formatDate(profileData.lastUpdated) }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</Stack>
|
||||||
|
</Card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { GetKycProfileFullDocument } from '~/composables/graphql/public/kyc-generated'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
kycProfileUuid?: string | null
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const { execute } = useGraphQL()
|
||||||
|
|
||||||
|
const profileData = ref<{
|
||||||
|
inn?: string | null
|
||||||
|
ogrn?: string | null
|
||||||
|
name?: string | null
|
||||||
|
companyType?: string | null
|
||||||
|
registrationYear?: number | null
|
||||||
|
isActive?: boolean | null
|
||||||
|
address?: string | null
|
||||||
|
director?: string | null
|
||||||
|
capital?: string | null
|
||||||
|
activities?: string[] | null
|
||||||
|
sources?: string[] | null
|
||||||
|
lastUpdated?: string | null
|
||||||
|
} | null>(null)
|
||||||
|
|
||||||
|
const pending = ref(false)
|
||||||
|
|
||||||
|
const loadProfile = async () => {
|
||||||
|
if (!props.kycProfileUuid) return
|
||||||
|
pending.value = true
|
||||||
|
try {
|
||||||
|
const data = await execute(
|
||||||
|
GetKycProfileFullDocument,
|
||||||
|
{ profileUuid: props.kycProfileUuid },
|
||||||
|
'public',
|
||||||
|
'kyc'
|
||||||
|
)
|
||||||
|
profileData.value = data?.kycProfileFull || null
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error loading KYC profile:', error)
|
||||||
|
} finally {
|
||||||
|
pending.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(() => props.kycProfileUuid, (uuid) => {
|
||||||
|
if (uuid) {
|
||||||
|
loadProfile()
|
||||||
|
} else {
|
||||||
|
profileData.value = null
|
||||||
|
}
|
||||||
|
}, { immediate: true })
|
||||||
|
|
||||||
|
const formatDate = (dateStr: string) => {
|
||||||
|
try {
|
||||||
|
return new Date(dateStr).toLocaleDateString('ru-RU')
|
||||||
|
} catch {
|
||||||
|
return dateStr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -45,11 +45,12 @@
|
|||||||
<div v-if="supplier?.isVerified" class="badge badge-success badge-sm ml-auto">Верифицирован</div>
|
<div v-if="supplier?.isVerified" class="badge badge-success badge-sm ml-auto">Верифицирован</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- KYC Info -->
|
|
||||||
<SupplierInfoBlock v-if="supplier?.kycProfileUuid" :kyc-profile-uuid="supplier.kycProfileUuid" />
|
|
||||||
</Stack>
|
</Stack>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
<!-- KYC Profile Card (full company info) -->
|
||||||
|
<KycProfileCard v-if="supplier?.kycProfileUuid" :kyc-profile-uuid="supplier.kycProfileUuid" />
|
||||||
|
|
||||||
<!-- Price Chart -->
|
<!-- Price Chart -->
|
||||||
<Card padding="md">
|
<Card padding="md">
|
||||||
<div class="h-48">
|
<div class="h-48">
|
||||||
|
|||||||
Reference in New Issue
Block a user