Add missing translations for LocationsContent, Notifications, KYCFormRussia, TopBar
Some checks failed
Build Docker Image / build (push) Failing after 47s

This commit is contained in:
Ruslan Bakiev
2026-01-22 17:45:57 +07:00
parent ba49a8d24f
commit eb664c0387
12 changed files with 158 additions and 43 deletions

View File

@@ -4,13 +4,13 @@
<!-- Company Section -->
<div class="card bg-base-100 border border-base-300 shadow-sm">
<div class="card-body gap-4">
<h3 class="card-title text-base-content">Company details</h3>
<h3 class="card-title text-base-content">{{ t('kycRussia.form.companyDetails') }}</h3>
<div class="space-y-4">
<!-- Company search with DADATA -->
<div>
<label class="block text-sm font-medium text-base-content mb-2">
Organization search
{{ t('kycRussia.form.organizationSearch') }}
</label>
<CompanySearchRussia v-model="formData.company" @select="onCompanySelect" />
</div>
@@ -18,7 +18,7 @@
<!-- Company details (auto-filled from DADATA) -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label class="block text-sm font-medium text-base-content mb-2">INN</label>
<label class="block text-sm font-medium text-base-content mb-2">{{ t('kycRussia.form.inn') }}</label>
<input
v-model="formData.company.inn"
class="input input-bordered w-full"
@@ -26,7 +26,7 @@
/>
</div>
<div>
<label class="block text-sm font-medium text-base-content mb-2">KPP</label>
<label class="block text-sm font-medium text-base-content mb-2">{{ t('kycRussia.form.kpp') }}</label>
<input
v-model="formData.company.kpp"
class="input input-bordered w-full"
@@ -36,7 +36,7 @@
</div>
<div>
<label class="block text-sm font-medium text-base-content mb-2">OGRN</label>
<label class="block text-sm font-medium text-base-content mb-2">{{ t('kycRussia.form.ogrn') }}</label>
<input
v-model="formData.company.ogrn"
class="input input-bordered w-full"
@@ -45,7 +45,7 @@
</div>
<div>
<label class="block text-sm font-medium text-base-content mb-2">Address</label>
<label class="block text-sm font-medium text-base-content mb-2">{{ t('kycRussia.form.address') }}</label>
<textarea
v-model="formData.company.address"
class="textarea textarea-bordered w-full min-h-[120px]"
@@ -60,13 +60,13 @@
<!-- Bank Section -->
<div class="card bg-base-100 border border-base-300 shadow-sm">
<div class="card-body gap-4">
<h3 class="card-title text-base-content">Bank details</h3>
<h3 class="card-title text-base-content">{{ t('kycRussia.form.bankDetails') }}</h3>
<div class="space-y-4">
<!-- Bank search with DADATA -->
<div>
<label class="block text-sm font-medium text-base-content mb-2">
Bank search
{{ t('kycRussia.form.bankSearch') }}
</label>
<BankSearchRussia v-model="formData.bank" @select="onBankSelect" />
</div>
@@ -74,7 +74,7 @@
<!-- Bank details -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label class="block text-sm font-medium text-base-content mb-2">BIC</label>
<label class="block text-sm font-medium text-base-content mb-2">{{ t('kycRussia.form.bic') }}</label>
<input
v-model="formData.bank.bik"
class="input input-bordered w-full"
@@ -82,7 +82,7 @@
/>
</div>
<div>
<label class="block text-sm font-medium text-base-content mb-2">Corr. account</label>
<label class="block text-sm font-medium text-base-content mb-2">{{ t('kycRussia.form.corrAccount') }}</label>
<input
v-model="formData.bank.correspondentAccount"
class="input input-bordered w-full"
@@ -97,41 +97,41 @@
<!-- Contact Section -->
<div class="card bg-base-100 border border-base-300 shadow-sm">
<div class="card-body gap-4">
<h3 class="card-title text-base-content">Contact details</h3>
<h3 class="card-title text-base-content">{{ t('kycRussia.form.contactDetails') }}</h3>
<div class="space-y-4">
<div>
<label class="block text-sm font-medium text-base-content mb-2">
Contact person *
{{ t('kycRussia.form.contactPerson') }} *
</label>
<input
v-model="formData.contact.person"
type="text"
required
class="input input-bordered w-full"
placeholder="Full name of company representative"
:placeholder="t('kycRussia.form.placeholders.contactPerson')"
/>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label class="block text-sm font-medium text-base-content mb-2">Email *</label>
<label class="block text-sm font-medium text-base-content mb-2">{{ t('kycRussia.form.email') }} *</label>
<input
v-model="formData.contact.email"
type="email"
required
class="input input-bordered w-full"
placeholder="email@company.ru"
:placeholder="t('kycRussia.form.placeholders.email')"
/>
</div>
<div>
<label class="block text-sm font-medium text-base-content mb-2">Phone *</label>
<label class="block text-sm font-medium text-base-content mb-2">{{ t('kycRussia.form.phone') }} *</label>
<input
v-model="formData.contact.phone"
type="tel"
required
class="input input-bordered w-full"
placeholder="+7 (xxx) xxx-xx-xx"
:placeholder="t('kycRussia.form.placeholders.phone')"
/>
</div>
</div>
@@ -146,7 +146,7 @@
:disabled="loading || !isFormValid"
class="btn btn-primary"
>
{{ loading ? 'Sending...' : 'Submit for review' }}
{{ loading ? t('kycRussia.form.sending') : t('kycRussia.form.submit') }}
</button>
</div>
</form>
@@ -154,6 +154,8 @@
</template>
<script setup lang="ts">
const { t } = useI18n()
const emit = defineEmits<{
submit: [data: any]
}>()

View File

@@ -2,14 +2,14 @@
<Stack gap="8">
<!-- My addresses (for authenticated users) -->
<Stack v-if="isAuthenticated && teamAddresses?.length" gap="4">
<PageHeader title="My addresses">
<PageHeader :title="t('locations.myAddresses')">
<template #actions>
<NuxtLink
:to="localePath('/clientarea/addresses')"
class="btn btn-sm btn-ghost gap-2"
>
<Icon name="lucide:settings" size="16" />
Manage
{{ t('locations.manage') }}
</NuxtLink>
</template>
</PageHeader>
@@ -26,7 +26,7 @@
<Stack direction="row" align="center" gap="2">
<Icon name="lucide:map-pin" size="18" class="text-primary" />
<Text size="base" weight="semibold">{{ addr.name }}</Text>
<Pill v-if="addr.isDefault" variant="outline" size="sm">Default</Pill>
<Pill v-if="addr.isDefault" variant="outline" size="sm">{{ t('locations.default') }}</Pill>
</Stack>
<Text tone="muted" size="sm">{{ addr.address }}</Text>
</Stack>
@@ -36,7 +36,7 @@
<!-- Terminals and logistics hubs -->
<Stack gap="4">
<PageHeader title="Terminals and logistics hubs" />
<PageHeader :title="t('locations.terminalsAndHubs')" />
<div v-if="pending" class="flex items-center justify-center p-8">
<span class="loading loading-spinner loading-lg" />
@@ -44,15 +44,15 @@
<Alert v-else-if="error" variant="error">
<Stack gap="2">
<Heading :level="4" weight="semibold">Load error</Heading>
<Button @click="refresh()">Try again</Button>
<Heading :level="4" weight="semibold">{{ t('locations.loadError') }}</Heading>
<Button @click="refresh()">{{ t('locations.tryAgain') }}</Button>
</Stack>
</Alert>
<EmptyState
v-else-if="!locationsData?.length"
title="No locations"
description="Logistics hubs not added yet"
:title="t('locations.noLocations')"
:description="t('locations.noHubsDescription')"
/>
<Grid v-else :cols="1" :md="2" :lg="3" :gap="4">
@@ -71,6 +71,7 @@
<script setup lang="ts">
import { GetNodesDocument } from '~/composables/graphql/public/geo-generated'
const { t } = useI18n()
const searchStore = useSearchStore()
const { isAuthenticated } = useAuth()
const localePath = useLocalePath()

View File

@@ -47,14 +47,14 @@
>
<!-- Header -->
<div class="flex items-center justify-between px-6 py-4 border-b border-base-300">
<h3 class="text-lg font-semibold text-base-content">Notifications</h3>
<h3 class="text-lg font-semibold text-base-content">{{ t('notifications.title') }}</h3>
<div class="flex items-center gap-3">
<button
v-if="unreadCount > 0"
@click="handleMarkAllAsRead"
class="text-sm text-primary hover:text-primary/80 font-medium"
>
Mark all as read
{{ t('notifications.markAllAsRead') }}
</button>
<button
@click="isOpen = false"
@@ -82,7 +82,7 @@
<svg class="w-12 h-12 text-base-content/30 mb-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6 6 0 10-12 0v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" />
</svg>
<p class="text-sm text-base-content/60">No notifications</p>
<p class="text-sm text-base-content/60">{{ t('notifications.empty') }}</p>
</div>
<!-- Notification Items -->
@@ -107,7 +107,7 @@
<!-- Content -->
<div class="flex-1 min-w-0">
<p class="text-sm text-base-content line-clamp-2">
{{ notification.content || notification.payload?.body || 'New notification' }}
{{ notification.content || notification.payload?.body || t('notifications.new') }}
</p>
<p class="mt-1 text-xs text-base-content/60">
{{ formatTime(notification.createdAt) }}
@@ -125,7 +125,7 @@
@click="isOpen = false"
class="text-xs text-primary hover:text-primary/80 font-medium"
>
All notifications
{{ t('notifications.viewAll') }}
</NuxtLink>
</div>
</div>
@@ -136,6 +136,8 @@
<script setup lang="ts">
import { onClickOutside } from '@vueuse/core'
const { t } = useI18n()
const props = defineProps<{
subscriberId: string
}>()
@@ -192,10 +194,10 @@ const formatTime = (dateString: string) => {
const diffHours = Math.floor(diffMins / 60)
const diffDays = Math.floor(diffHours / 24)
if (diffMins < 1) return 'Just now'
if (diffMins < 60) return `${diffMins} min ago`
if (diffHours < 24) return `${diffHours} h ago`
if (diffDays < 7) return `${diffDays} d ago`
if (diffMins < 1) return t('notifications.time.justNow')
if (diffMins < 60) return t('notifications.time.minutesAgo', { n: diffMins })
if (diffHours < 24) return t('notifications.time.hoursAgo', { n: diffHours })
if (diffDays < 7) return t('notifications.time.daysAgo', { n: diffDays })
return date.toLocaleDateString('ru-RU', { day: 'numeric', month: 'short' })
}

View File

@@ -45,10 +45,10 @@
tabindex="0"
class="dropdown-content menu bg-base-100 rounded-box z-50 w-72 p-2 shadow-lg border border-base-300 mt-1"
>
<li class="menu-title"><span>Quick actions</span></li>
<li><a @click="navigateToAction('/catalog')">Find materials</a></li>
<li><a @click="navigateToAction('/clientarea/orders')">My orders</a></li>
<li><a @click="navigateToAction('/clientarea/profile')">Profile settings</a></li>
<li class="menu-title"><span>{{ t('topbar.quickActions') }}</span></li>
<li><a @click="navigateToAction('/catalog')">{{ t('topbar.findMaterials') }}</a></li>
<li><a @click="navigateToAction('/clientarea/orders')">{{ t('topbar.myOrders') }}</a></li>
<li><a @click="navigateToAction('/clientarea/profile')">{{ t('topbar.profileSettings') }}</a></li>
</ul>
</div>
@@ -110,7 +110,7 @@
<details>
<summary>
<Icon name="lucide:globe" size="16" />
Language
{{ t('topbar.language') }}
</summary>
<ul>
<li v-for="loc in locales" :key="loc.code">
@@ -161,7 +161,7 @@ defineProps<{
}>()
const localePath = useLocalePath()
const { locale, locales } = useI18n()
const { t, locale, locales } = useI18n()
const switchLocalePath = useSwitchLocalePath()
const locationStore = useLocationStore()

View File

@@ -18,6 +18,29 @@
"title": "Request sent successfully",
"description": "Your verification request has been accepted. Result will be ready within 1-2 business days.",
"cta": "View request status →"
},
"form": {
"companyDetails": "Company details",
"organizationSearch": "Organization search",
"inn": "INN",
"kpp": "KPP",
"ogrn": "OGRN",
"address": "Address",
"bankDetails": "Bank details",
"bankSearch": "Bank search",
"bic": "BIC",
"corrAccount": "Corr. account",
"contactDetails": "Contact details",
"contactPerson": "Contact person",
"email": "Email",
"phone": "Phone",
"sending": "Sending...",
"submit": "Submit for review",
"placeholders": {
"contactPerson": "Full name of company representative",
"email": "email@company.ru",
"phone": "+7 (xxx) xxx-xx-xx"
}
}
}
}

View File

@@ -9,6 +9,14 @@
"search_placeholder": "City name",
"regions": "Federal Districts",
"all_regions": "All Regions",
"all_countries": "All countries"
"all_countries": "All countries",
"myAddresses": "My addresses",
"manage": "Manage",
"default": "Default",
"terminalsAndHubs": "Terminals and logistics hubs",
"loadError": "Load error",
"tryAgain": "Try again",
"noLocations": "No locations",
"noHubsDescription": "Logistics hubs not added yet"
}
}

View File

@@ -0,0 +1,15 @@
{
"notifications": {
"title": "Notifications",
"markAllAsRead": "Mark all as read",
"empty": "No notifications",
"viewAll": "All notifications",
"new": "New notification",
"time": {
"justNow": "Just now",
"minutesAgo": "{n} min ago",
"hoursAgo": "{n} h ago",
"daysAgo": "{n} d ago"
}
}
}

View File

@@ -0,0 +1,9 @@
{
"topbar": {
"quickActions": "Quick actions",
"findMaterials": "Find materials",
"myOrders": "My orders",
"profileSettings": "Profile settings",
"language": "Language"
}
}

View File

@@ -18,6 +18,29 @@
"title": "Заявка успешно отправлена",
"description": "Ваша заявка на верификацию принята. Результат будет готов в течение 1-2 рабочих дней.",
"cta": "Посмотреть статус заявки →"
},
"form": {
"companyDetails": "Данные компании",
"organizationSearch": "Поиск организации",
"inn": "ИНН",
"kpp": "КПП",
"ogrn": "ОГРН",
"address": "Адрес",
"bankDetails": "Банковские реквизиты",
"bankSearch": "Поиск банка",
"bic": "БИК",
"corrAccount": "Корр. счёт",
"contactDetails": "Контактные данные",
"contactPerson": "Контактное лицо",
"email": "Email",
"phone": "Телефон",
"sending": "Отправка...",
"submit": "Отправить на проверку",
"placeholders": {
"contactPerson": "ФИО представителя компании",
"email": "email@company.ru",
"phone": "+7 (xxx) xxx-xx-xx"
}
}
}
}

View File

@@ -9,6 +9,14 @@
"search_placeholder": "Название города",
"regions": "Федеральные округа",
"all_regions": "Все регионы",
"all_countries": "Все страны"
"all_countries": "Все страны",
"myAddresses": "Мои адреса",
"manage": "Управление",
"default": "По умолчанию",
"terminalsAndHubs": "Терминалы и логистические хабы",
"loadError": "Ошибка загрузки",
"tryAgain": "Попробовать снова",
"noLocations": "Нет локаций",
"noHubsDescription": "Логистические хабы ещё не добавлены"
}
}

View File

@@ -0,0 +1,15 @@
{
"notifications": {
"title": "Уведомления",
"markAllAsRead": "Отметить все как прочитанные",
"empty": "Нет уведомлений",
"viewAll": "Все уведомления",
"new": "Новое уведомление",
"time": {
"justNow": "Только что",
"minutesAgo": "{n} мин назад",
"hoursAgo": "{n} ч назад",
"daysAgo": "{n} д назад"
}
}
}

View File

@@ -0,0 +1,9 @@
{
"topbar": {
"quickActions": "Быстрые действия",
"findMaterials": "Найти материалы",
"myOrders": "Мои заказы",
"profileSettings": "Настройки профиля",
"language": "Язык"
}
}