Refine counterparty profile layout

This commit is contained in:
Ruslan Bakiev
2026-04-06 21:38:14 +07:00
parent 6ed821a295
commit 77015ed243

View File

@@ -255,179 +255,234 @@ onBeforeUnmount(() => {
<template> <template>
<section class="space-y-6"> <section class="space-y-6">
<NuxtLink to="/profile" class="link link-hover text-sm"> Назад в профиль</NuxtLink> <NuxtLink to="/profile" class="link link-hover text-sm"> Назад в профиль</NuxtLink>
<div class="space-y-2">
<div class="flex flex-wrap items-center justify-between gap-3">
<h1 class="text-3xl font-extrabold text-[#0f2f20]">Карточка контрагента</h1> <h1 class="text-3xl font-extrabold text-[#0f2f20]">Карточка контрагента</h1>
<span
class="inline-flex items-center rounded-full px-3 py-1 text-xs font-bold uppercase tracking-[0.16em]"
:class="profileIsComplete ? 'bg-[#e8f6ee] text-[#0d854a]' : 'bg-[#fff3dc] text-[#b06b00]'"
>
{{ profileIsComplete ? 'Заполнено' : 'Нужно заполнить' }}
</span>
</div>
<div class="surface-card rounded-3xl p-5"> <p class="max-w-3xl text-sm leading-6 text-[#355947]">
<p class="text-sm text-[#355947]"> Заполните реквизиты компании, банка и подписанта. После этого карточку можно будет использовать в заказах без ручного добивания данных.
Заполните реквизиты, чтобы оформить заявки и получить полный функционал личного кабинета.
</p> </p>
</div>
<div class="mt-4 space-y-4"> <div class="space-y-4">
<section> <section class="surface-card rounded-3xl p-5 md:p-6">
<h2 class="mb-3 text-base font-bold">1. Контрагент (DaData)</h2> <div class="mb-5 space-y-1">
<h2 class="text-xl font-black tracking-[-0.02em] text-[#123824]">Данные компании</h2>
<p class="text-sm leading-6 text-[#5c7b69]">
Найдите компанию через DaData или заполните реквизиты вручную.
</p>
</div>
<div class="grid gap-4">
<div ref="partyDropdownRef" class="relative"> <div ref="partyDropdownRef" class="relative">
<fieldset class="fieldset"> <label class="block space-y-2">
<legend class="fieldset-legend">Поиск компании</legend> <span class="text-sm font-semibold text-[#355947]">Поиск компании</span>
<div class="relative">
<input <input
v-model="companySearch" v-model="companySearch"
type="text" type="text"
class="input w-full" class="input manager-field w-full pr-11"
placeholder="Введите название или ИНН" placeholder="Введите название компании или ИНН"
@input="schedulePartySuggest" @input="schedulePartySuggest"
@focus="partyOpen = partySuggestions.length > 0" @focus="partyOpen = partySuggestions.length > 0"
> >
</fieldset> <span v-if="partyLoading" class="loading loading-spinner loading-sm absolute right-4 top-1/2 -translate-y-1/2 text-[#5c7b69]" />
</div>
<span v-if="partyLoading" class="loading loading-spinner loading-sm absolute right-3 top-1/2 -translate-y-1/2" /> </label>
<div <div
v-if="partyOpen && partySuggestions.length > 0" v-if="partyOpen && partySuggestions.length > 0"
class="absolute z-30 mt-2 max-h-72 w-full overflow-auto rounded-box bg-base-100 p-2" class="absolute z-30 mt-2 max-h-72 w-full overflow-auto rounded-[1.4rem] border border-[#e1ebe4] bg-white p-2 shadow-[0_24px_48px_rgba(18,56,36,0.12)]"
> >
<button <button
v-for="item in partySuggestions" v-for="item in partySuggestions"
:key="`${item.value}-${item.data?.inn || ''}`" :key="`${item.value}-${item.data?.inn || ''}`"
type="button" type="button"
class="btn btn-ghost mb-1 h-auto min-h-0 w-full justify-start whitespace-normal px-3 py-2 text-left" class="mb-1 w-full rounded-2xl px-4 py-3 text-left transition hover:bg-[#f5faf7]"
@click="applyPartySuggestion(item)" @click="applyPartySuggestion(item)"
> >
<span> <span class="block text-sm font-semibold text-[#123824]">{{ item.value }}</span>
<span class="block text-sm font-semibold">{{ item.value }}</span> <span class="mt-1 block text-xs text-[#5c7b69]">
<span class="block text-xs opacity-70">ИНН: {{ item.data?.inn || '—' }} <span v-if="item.data?.kpp"> КПП: {{ item.data.kpp }}</span></span> ИНН: {{ item.data?.inn || '—' }}<span v-if="item.data?.kpp"> КПП: {{ item.data.kpp }}</span>
</span> </span>
</button> </button>
</div> </div>
</div> </div>
<fieldset class="fieldset"> <div class="grid gap-4 md:grid-cols-2">
<legend class="fieldset-legend">Краткое наименование</legend> <label class="block space-y-2">
<input v-model="counterpartyForm.companyName" type="text" class="input w-full" > <span class="text-sm font-semibold text-[#355947]">Краткое наименование</span>
</fieldset> <input v-model="counterpartyForm.companyName" type="text" class="input manager-field w-full">
</label>
<fieldset class="fieldset"> <label class="block space-y-2">
<legend class="fieldset-legend">Полное наименование</legend> <span class="text-sm font-semibold text-[#355947]">Полное наименование</span>
<input v-model="counterpartyForm.companyFullName" type="text" class="input w-full" > <input v-model="counterpartyForm.companyFullName" type="text" class="input manager-field w-full">
</fieldset> </label>
<div class="grid gap-3 sm:grid-cols-3">
<fieldset class="fieldset">
<legend class="fieldset-legend">ИНН</legend>
<input v-model="counterpartyForm.inn" type="text" class="input w-full" >
</fieldset>
<fieldset class="fieldset">
<legend class="fieldset-legend">КПП</legend>
<input v-model="counterpartyForm.kpp" type="text" class="input w-full" >
</fieldset>
<fieldset class="fieldset">
<legend class="fieldset-legend">ОГРН</legend>
<input v-model="counterpartyForm.ogrn" type="text" class="input w-full" >
</fieldset>
</div> </div>
<fieldset class="fieldset"> <div class="grid gap-4 md:grid-cols-3">
<legend class="fieldset-legend">Юридический адрес</legend> <label class="block space-y-2">
<textarea v-model="counterpartyForm.legalAddress" class="textarea min-h-24 w-full" /> <span class="text-sm font-semibold text-[#355947]">ИНН</span>
</fieldset> <input v-model="counterpartyForm.inn" type="text" class="input manager-field w-full">
</label>
<label class="block space-y-2">
<span class="text-sm font-semibold text-[#355947]">КПП</span>
<input v-model="counterpartyForm.kpp" type="text" class="input manager-field w-full">
</label>
<label class="block space-y-2">
<span class="text-sm font-semibold text-[#355947]">ОГРН</span>
<input v-model="counterpartyForm.ogrn" type="text" class="input manager-field w-full">
</label>
</div>
<label class="block space-y-2">
<span class="text-sm font-semibold text-[#355947]">Юридический адрес</span>
<textarea v-model="counterpartyForm.legalAddress" class="textarea manager-field min-h-28 w-full" />
</label>
</div>
</section> </section>
<div class="divider my-0" /> <section class="surface-card rounded-3xl p-5 md:p-6">
<div class="mb-5 space-y-1">
<section> <h2 class="text-xl font-black tracking-[-0.02em] text-[#123824]">Банковские реквизиты</h2>
<h2 class="mb-3 text-base font-bold">2. Банк (DaData)</h2> <p class="text-sm leading-6 text-[#5c7b69]">
Подтяните банк по справочнику или внесите реквизиты вручную.
</p>
</div>
<div class="grid gap-4">
<div ref="bankDropdownRef" class="relative"> <div ref="bankDropdownRef" class="relative">
<fieldset class="fieldset"> <label class="block space-y-2">
<legend class="fieldset-legend">Поиск банка</legend> <span class="text-sm font-semibold text-[#355947]">Поиск банка</span>
<div class="relative">
<input <input
v-model="bankSearch" v-model="bankSearch"
type="text" type="text"
class="input w-full" class="input manager-field w-full pr-11"
placeholder="Введите название банка" placeholder="Введите название банка"
@input="scheduleBankSuggest" @input="scheduleBankSuggest"
@focus="bankOpen = bankSuggestions.length > 0" @focus="bankOpen = bankSuggestions.length > 0"
> >
</fieldset> <span v-if="bankLoading" class="loading loading-spinner loading-sm absolute right-4 top-1/2 -translate-y-1/2 text-[#5c7b69]" />
</div>
<span v-if="bankLoading" class="loading loading-spinner loading-sm absolute right-3 top-1/2 -translate-y-1/2" /> </label>
<div <div
v-if="bankOpen && bankSuggestions.length > 0" v-if="bankOpen && bankSuggestions.length > 0"
class="absolute z-30 mt-2 max-h-72 w-full overflow-auto rounded-box bg-base-100 p-2" class="absolute z-30 mt-2 max-h-72 w-full overflow-auto rounded-[1.4rem] border border-[#e1ebe4] bg-white p-2 shadow-[0_24px_48px_rgba(18,56,36,0.12)]"
> >
<button <button
v-for="item in bankSuggestions" v-for="item in bankSuggestions"
:key="`${item.value}-${item.data?.bic || ''}`" :key="`${item.value}-${item.data?.bic || ''}`"
type="button" type="button"
class="btn btn-ghost mb-1 h-auto min-h-0 w-full justify-start whitespace-normal px-3 py-2 text-left" class="mb-1 w-full rounded-2xl px-4 py-3 text-left transition hover:bg-[#f5faf7]"
@click="applyBankSuggestion(item)" @click="applyBankSuggestion(item)"
> >
<span> <span class="block text-sm font-semibold text-[#123824]">{{ item.value }}</span>
<span class="block text-sm font-semibold">{{ item.value }}</span> <span class="mt-1 block text-xs text-[#5c7b69]">БИК: {{ item.data?.bic || '—' }}</span>
<span class="block text-xs opacity-70">БИК: {{ item.data?.bic || '—' }}</span>
</span>
</button> </button>
</div> </div>
</div> </div>
<fieldset class="fieldset"> <div class="grid gap-4 md:grid-cols-2">
<legend class="fieldset-legend">Банк</legend> <label class="block space-y-2">
<input v-model="counterpartyForm.bankName" type="text" class="input w-full" > <span class="text-sm font-semibold text-[#355947]">Банк</span>
</fieldset> <input v-model="counterpartyForm.bankName" type="text" class="input manager-field w-full">
</label>
<div class="grid gap-3 sm:grid-cols-2"> <label class="block space-y-2">
<fieldset class="fieldset"> <span class="text-sm font-semibold text-[#355947]">БИК</span>
<legend class="fieldset-legend">БИК</legend> <input v-model="counterpartyForm.bik" type="text" class="input manager-field w-full">
<input v-model="counterpartyForm.bik" type="text" class="input w-full" > </label>
</fieldset>
<fieldset class="fieldset">
<legend class="fieldset-legend">Корр. счет</legend>
<input v-model="counterpartyForm.correspondentAccount" type="text" class="input w-full" >
</fieldset>
</div> </div>
<fieldset class="fieldset"> <div class="grid gap-4 md:grid-cols-2">
<legend class="fieldset-legend">Расчетный счет</legend> <label class="block space-y-2">
<input v-model="counterpartyForm.checkingAccount" type="text" class="input w-full" > <span class="text-sm font-semibold text-[#355947]">Корреспондентский счет</span>
</fieldset> <input v-model="counterpartyForm.correspondentAccount" type="text" class="input manager-field w-full">
</label>
<label class="block space-y-2">
<span class="text-sm font-semibold text-[#355947]">Расчетный счет</span>
<input v-model="counterpartyForm.checkingAccount" type="text" class="input manager-field w-full">
</label>
</div>
</div>
</section> </section>
<div class="divider my-0" /> <section class="surface-card rounded-3xl p-5 md:p-6">
<div class="mb-5 space-y-1">
<h2 class="text-xl font-black tracking-[-0.02em] text-[#123824]">Подписанты и основания</h2>
<p class="text-sm leading-6 text-[#5c7b69]">
Укажите, кто подписывает документы и на каком основании действует.
</p>
</div>
<section> <div class="grid gap-4">
<h2 class="mb-3 text-base font-bold">3. Подписант и основание</h2> <div class="grid gap-4 md:grid-cols-2">
<label class="block space-y-2">
<span class="text-sm font-semibold text-[#355947]">ФИО подписанта</span>
<input
v-model="counterpartyForm.signerFullName"
type="text"
class="input manager-field w-full"
placeholder="Иванов Иван Иванович"
>
</label>
<fieldset class="fieldset"> <label class="block space-y-2">
<legend class="fieldset-legend">ФИО подписанта</legend> <span class="text-sm font-semibold text-[#355947]">Должность</span>
<input v-model="counterpartyForm.signerFullName" type="text" class="input w-full" placeholder="Иванов Иван Иванович" > <input
</fieldset> v-model="counterpartyForm.signerPosition"
type="text"
class="input manager-field w-full"
placeholder="Генеральный директор"
>
</label>
</div>
<fieldset class="fieldset"> <label class="block space-y-2">
<legend class="fieldset-legend">Должность</legend> <span class="text-sm font-semibold text-[#355947]">Основание полномочий</span>
<input v-model="counterpartyForm.signerPosition" type="text" class="input w-full" placeholder="Генеральный директор" >
</fieldset>
<fieldset class="fieldset">
<legend class="fieldset-legend">Основание полномочий</legend>
<textarea <textarea
v-model="counterpartyForm.signerBasis" v-model="counterpartyForm.signerBasis"
class="textarea min-h-24 w-full" class="textarea manager-field min-h-28 w-full"
placeholder="Действует на основании Устава" placeholder="Действует на основании Устава"
/> />
</fieldset> </label>
<button class="btn btn-primary mt-4 w-full" :disabled="saveCounterpartyMutation.loading.value || !profileIsComplete" @click="saveCounterpartyProfile">
{{ saveCounterpartyMutation.loading.value ? 'Сохраняем' : 'Сохранить' }}
</button>
<p v-if="profileUpdatedAt" class="mt-2 text-xs opacity-70">Обновлено: {{ new Date(profileUpdatedAt).toLocaleString() }}</p>
</section>
</div> </div>
<div v-if="profileFeedback" class="alert mt-4" :class="profileFeedbackTone === 'success' ? 'alert-success' : 'alert-error'"> <div class="mt-6 flex flex-col gap-3 border-t border-[#edf2ee] pt-5 md:flex-row md:items-center md:justify-between">
<div class="space-y-1">
<p class="text-sm font-semibold text-[#123824]">
{{ profileIsComplete ? 'Карточка готова к использованию в заказах.' : 'Заполните обязательные поля, чтобы сохранить карточку.' }}
</p>
<p v-if="profileUpdatedAt" class="text-xs text-[#6f8579]">
Обновлено: {{ new Date(profileUpdatedAt).toLocaleString() }}
</p>
</div>
<button
class="btn h-12 w-full rounded-full border-0 bg-[#123824] px-7 text-white shadow-[0_18px_34px_rgba(18,56,36,0.18)] hover:bg-[#0f2f20] disabled:border-0 disabled:bg-[#cfd8d2] disabled:text-[#6f8579] md:w-auto"
:disabled="saveCounterpartyMutation.loading.value || !profileIsComplete"
@click="saveCounterpartyProfile"
>
{{ saveCounterpartyMutation.loading.value ? 'Сохраняем…' : 'Сохранить карточку' }}
</button>
</div>
</section>
<div v-if="profileFeedback" class="alert" :class="profileFeedbackTone === 'success' ? 'alert-success' : 'alert-error'">
{{ profileFeedback }} {{ profileFeedback }}
</div> </div>
</div> </div>