feat(ui): unify logistics-style side panel flow

This commit is contained in:
Ruslan Bakiev
2026-04-21 10:46:35 +07:00
parent d3183bf6ad
commit 54aac790ee
8 changed files with 544 additions and 422 deletions

View File

@@ -0,0 +1,82 @@
<script setup lang="ts">
const props = withDefaults(defineProps<{
managerStage?: boolean
}>(), {
managerStage: false,
})
const { toLocalized } = useLocalizedNavigation()
const footerLinks = [
{ label: 'Главная', to: '/' },
{ label: 'Заказы', to: '/clientarea/orders' },
{ label: 'Кабинет', to: '/clientarea/profile' },
]
const socialLinks = [
{ label: 'Instagram', href: 'https://instagram.com', icon: 'M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 16a4 4 0 110-8 4 4 0 010 8z' },
{ label: 'YouTube', href: 'https://youtube.com', icon: 'M23.498 6.186a3.016 3.016 0 00-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 00.502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 002.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 002.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z' },
{ label: 'Telegram', href: 'https://t.me', icon: 'M11.944 0A12 12 0 000 12a12 12 0 0012 12 12 12 0 0012-12A12 12 0 0012 0z' },
]
const currentYear = new Date().getFullYear()
</script>
<template>
<footer
class="-mt-px overflow-hidden border-t-0 text-white"
:class="props.managerStage ? 'bg-transparent' : 'bg-[#10223b] [background-image:radial-gradient(circle_at_82%_18%,rgba(244,89,69,0.45),rgba(244,89,69,0)_34%),linear-gradient(130deg,#10223b_0%,#193450_100%)]'"
>
<div
class="mx-auto max-w-[1280px] px-3 pb-10 md:px-4 md:pb-12"
:class="props.managerStage ? 'pt-0 md:pt-0' : 'pt-5 md:pt-6'"
>
<div
class="grid gap-4 rounded-[26px] border p-5 md:p-6"
:class="props.managerStage
? 'border-white/12 bg-white/4 [backdrop-filter:blur(10px)]'
: 'border-white/20 bg-[rgba(11,24,42,0.26)] [backdrop-filter:blur(6px)]'"
>
<div>
<h2 class="m-0 text-[clamp(1.6rem,3.4vw,2.6rem)] font-black leading-[1.08]">Готовы к следующей поставке?</h2>
<p class="mt-3 max-w-[720px] leading-6 text-white/85">
Получайте предложения в реальном времени, сравнивайте условия и запускайте закупку прямо в Optovia.
</p>
</div>
<div class="flex flex-wrap gap-2.5">
<a href="tel:+74957402842" class="inline-flex items-center rounded-full border border-white/25 bg-white/10 px-3.5 py-2 text-[0.92rem] font-bold text-white transition-colors hover:bg-white/20">+7 (495) 740-28-42</a>
<a href="mailto:sales@optovia.ru" class="inline-flex items-center rounded-full border border-white/25 bg-white/10 px-3.5 py-2 text-[0.92rem] font-bold text-white transition-colors hover:bg-white/20">sales@optovia.ru</a>
</div>
<nav class="flex flex-wrap gap-2" aria-label="Footer navigation">
<NuxtLink
v-for="link in footerLinks"
:key="link.to"
:to="toLocalized(link.to)"
class="rounded-full border border-white/25 px-3 py-2 text-[0.88rem] text-white/90 transition-colors hover:bg-white/15 hover:text-white"
>
{{ link.label }}
</NuxtLink>
</nav>
<div class="flex items-center gap-2.5" aria-label="Social networks">
<a
v-for="s in socialLinks"
:key="s.label"
:href="s.href"
target="_blank"
rel="noopener noreferrer"
:aria-label="s.label"
class="inline-flex h-[2.2rem] w-[2.2rem] items-center justify-center rounded-full border border-white/30 bg-white/10 text-white/95 transition-colors hover:bg-white/20"
>
<svg viewBox="0 0 24 24" fill="currentColor" class="h-4 w-4"><path :d="s.icon" /></svg>
</a>
</div>
</div>
<div class="mt-4 px-1 text-[0.78rem] text-white/70">
<p>&copy; {{ currentYear }} Optovia. Все права защищены.</p>
</div>
</div>
</footer>
</template>

View File

@@ -0,0 +1,86 @@
<script setup lang="ts">
const props = withDefaults(defineProps<{
title?: string
initialCollapsed?: boolean
collapsible?: boolean
positionClass?: string
topOffsetClass?: string
bottomOffsetClass?: string
widthClass?: string
}>(), {
title: '',
initialCollapsed: false,
collapsible: true,
positionClass: 'left-4',
topOffsetClass: 'top-[96px]',
bottomOffsetClass: 'bottom-4',
widthClass: 'w-[min(calc(100vw-1rem),440px)] md:w-[420px] xl:w-[460px]',
})
const collapsed = ref(props.initialCollapsed)
function toggleCollapsed() {
collapsed.value = !collapsed.value
}
</script>
<template>
<div class="pointer-events-none fixed z-40" :class="[positionClass, topOffsetClass, bottomOffsetClass]">
<section
class="pointer-events-auto flex h-full flex-col overflow-hidden rounded-[28px] border-0 bg-[#f3eee6] text-[#2f2418] shadow-[0_28px_70px_rgba(38,29,18,0.18)]"
:class="collapsible && collapsed ? 'w-16 rounded-full' : widthClass"
style="transition: width 260ms ease;"
>
<template v-if="collapsible && collapsed">
<button
type="button"
class="flex h-full w-full cursor-pointer flex-col items-center justify-between px-3 py-3 text-left transition hover:bg-[#eee6dc]"
:aria-expanded="String(!collapsed)"
:aria-label="$t('ui.expand_panel')"
@click="toggleCollapsed"
>
<span class="flex h-10 w-10 items-center justify-center rounded-full bg-white text-[#5f4b33] transition">
<svg viewBox="0 0 24 24" fill="none" class="h-4 w-4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="m9 6 6 6-6 6" />
</svg>
</span>
<p v-if="title" class="origin-center whitespace-nowrap -rotate-90 text-[11px] font-bold uppercase tracking-[0.14em] text-[#6f6353]">
{{ title }}
</p>
<div class="h-10 w-10" aria-hidden="true" />
</button>
</template>
<template v-else>
<header v-if="title || $slots.header" class="flex shrink-0 items-start justify-between gap-3 border-b border-[#ded3c2] bg-[#f3eee6] px-5 py-4">
<div class="min-w-0 flex-1">
<slot name="header">
<h1 v-if="title" class="truncate text-xl font-black text-[#2f2418] md:text-2xl">{{ title }}</h1>
</slot>
</div>
<button
v-if="collapsible"
type="button"
class="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-white text-[#5f4b33] transition hover:bg-[#fbf8f4]"
:aria-label="$t('ui.collapse_panel')"
@click="toggleCollapsed"
>
<svg viewBox="0 0 24 24" fill="none" class="h-4 w-4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="m15 18-6-6 6-6" />
</svg>
</button>
</header>
<div class="min-h-0 flex-1 overflow-y-auto p-4 md:p-5">
<slot />
</div>
<footer v-if="$slots.footer" class="shrink-0 border-t border-[#ded3c2] bg-[#f3eee6] px-4 py-4 md:px-5 md:py-5">
<slot name="footer" />
</footer>
</template>
</section>
</div>
</template>