Files
webapp/app/pages/clientarea/kyc/index.vue
Ruslan Bakiev 2dbe600d8a
All checks were successful
Build Docker Image / build (push) Successful in 4m3s
refactor: remove all any types, add strict GraphQL scalar typing
- Add strictScalars: true to codegen.ts with proper scalar mappings
  (Date, Decimal, JSONString, JSON, UUID, BigInt → string/Record)
- Replace all ref<any[]> with proper GraphQL-derived types
- Add type guards for null filtering in arrays
- Fix bugs exposed by typing (locationLatitude vs latitude, etc.)
- Add interfaces for external components (MapboxSearchBox)

This enables end-to-end type safety from GraphQL schema to frontend.
2026-01-27 11:34:12 +07:00

157 lines
5.8 KiB
Vue

<template>
<div>
<Alert v-if="error" variant="error" class="mb-4">
<Stack gap="2">
<Heading :level="4" weight="semibold">{{ t('kycOverview.errors.title') }}</Heading>
<Text tone="muted">{{ error }}</Text>
<Button @click="loadKYCStatus">{{ t('kycOverview.errors.retry') }}</Button>
</Stack>
</Alert>
<Card v-else-if="loading" tone="muted" padding="lg">
<Stack align="center" justify="center" gap="3">
<Spinner />
<Text tone="muted">{{ t('kycOverview.states.loading') }}</Text>
</Stack>
</Card>
<template v-else>
<Stack gap="6">
<!-- Список существующих заявок -->
<Stack v-if="kycRequests.length > 0" gap="4">
<Heading :level="2">{{ t('kycOverview.list.title') }}</Heading>
<Grid :cols="1" :md="2" :lg="3" :gap="4">
<Card v-for="request in kycRequests" :key="request.uuid" padding="lg">
<Stack gap="3">
<Stack direction="row" gap="2" align="center" justify="between">
<Heading :level="4" weight="semibold">{{ request.teamName || t('kycOverview.list.unnamed') }}</Heading>
<Pill :variant="getStatusVariant(request)" :tone="getStatusTone(request)">
{{ getStatusText(request) }}
</Pill>
</Stack>
<Text tone="muted" size="base">
{{ t('kycOverview.list.submitted') }}: {{ formatDate(request.createdAt) }}
</Text>
<Text tone="muted" size="base">
{{ t('kycOverview.list.country') }}: {{ request.countryCode }}
</Text>
</Stack>
</Card>
</Grid>
</Stack>
<!-- Добавить новую заявку -->
<Stack gap="4">
<Heading :level="2">{{ t('kycOverview.choose_country.title') }}</Heading>
<Grid :cols="1" :md="2" :lg="3" :gap="4">
<Card padding="lg" interactive @click="selectCountry('russia')">
<Stack gap="3">
<Stack direction="row" gap="2" align="center">
<IconCircle tone="primary">🇷🇺</IconCircle>
<Heading :level="4" weight="semibold">{{ t('kycOverview.countries.russia.title') }}</Heading>
</Stack>
<Text tone="muted" size="base">
{{ t('kycOverview.countries.russia.description') }}
</Text>
<Stack direction="row" align="center" justify="between">
<Pill variant="primary">{{ t('kycOverview.countries.russia.badge') }}</Pill>
<Text tone="muted" weight="semibold"></Text>
</Stack>
</Stack>
</Card>
<Card padding="lg" tone="muted">
<Stack gap="3">
<Stack direction="row" gap="2" align="center">
<IconCircle tone="neutral">🇰🇿</IconCircle>
<Heading :level="4" weight="semibold">{{ t('kycOverview.countries.kazakhstan.title') }}</Heading>
</Stack>
<Text tone="muted" size="base">
{{ t('kycOverview.countries.kazakhstan.description') }}
</Text>
<Stack direction="row" align="center" justify="between">
<Pill variant="outline" tone="warning">{{ t('kycOverview.countries.kazakhstan.badge') }}</Pill>
<Text tone="muted" weight="semibold"></Text>
</Stack>
</Stack>
</Card>
</Grid>
<Stack gap="2">
<Heading :level="4" weight="semibold">{{ t('kycOverview.info.title') }}</Heading>
<Text tone="muted" size="base"> {{ t('kycOverview.info.point1') }}</Text>
<Text tone="muted" size="base"> {{ t('kycOverview.info.point2') }}</Text>
<Text tone="muted" size="base"> {{ t('kycOverview.info.point3') }}</Text>
</Stack>
</Stack>
</Stack>
</template>
</div>
</template>
<script setup lang="ts">
import { GetKycRequestsRussiaDocument, type GetKycRequestsRussiaQueryResult } from '~/composables/graphql/user/kyc-generated'
type KycRequest = NonNullable<NonNullable<GetKycRequestsRussiaQueryResult['kycRequests']>[number]>
definePageMeta({
layout: 'topnav',
middleware: ['auth-oidc']
})
const { t } = useI18n()
const loading = ref(true)
const error = ref<string | null>(null)
const kycRequests = ref<KycRequest[]>([])
const selectCountry = (country: string) => {
if (country === 'russia') {
navigateTo('/clientarea/kyc/russia')
}
}
const getStatusVariant = (request: KycRequest) => {
if (request.approvedAt) return 'primary'
return 'outline'
}
const getStatusTone = (request: KycRequest) => {
if (request.approvedAt) return 'success'
return 'warning'
}
const getStatusText = (request: KycRequest) => {
if (request.approvedAt) return t('kycOverview.list.status.approved')
return t('kycOverview.list.status.pending')
}
const formatDate = (dateStr: string) => {
if (!dateStr) return ''
const date = new Date(dateStr)
return date.toLocaleDateString()
}
const loadKYCStatus = async () => {
try {
loading.value = true
error.value = null
const { data, error: kycError } = await useServerQuery('kyc-requests', GetKycRequestsRussiaDocument, {}, 'user', 'kyc')
if (kycError.value) throw kycError.value
const requests = data.value?.kycRequests || []
// Сортируем по дате создания (новые первые)
kycRequests.value = [...requests]
.filter((r): r is KycRequest => r !== null)
.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime())
} catch (err: unknown) {
error.value = t('kycOverview.errors.load_failed')
} finally {
loading.value = false
}
}
await loadKYCStatus()
</script>