Skip to content

Seller Profile Page — Design

Overview

Implement the seller public profile page (/seller/:id). Currently a stub showing only "Продавец #ID". Must display seller info, stats, and product listings per wireframe specs.

API

GET /store/sellers/{id} — Seller profile:

json
{
  "data": {
    "id": 17,
    "display_name": "леха",
    "avatar_url": "https://api.partizap.ru/avatars/17/...",
    "city_id": null,
    "rating": 0,
    "reviews_count": 0,
    "products_count": 2,
    "created_at": "2026-02-08T06:56:05+03:00"
  }
}

GET /store/sellers/{id}/products — Seller's active products (cursor pagination).

Page Structure

File: app/pages/seller/[id].vueLayout: default | SSR: yes | Middleware: none

Data Loading

  • useAsyncData for seller profile — parallel with products
  • useCursorPagination for products list via GET /store/sellers/{id}/products
  • On 404 — showError({ statusCode: 404 })
  • SEO: useSeoMeta({ title: seller.display_name })

Profile Header

Flex block:

  • Left: UAvatar 80px, seller.avatar_url, fallback to initials from display_name
  • Center:
    • Name: display_nametext-xl font-bold
    • Rating: star icon + rating + "(N отзывов)" — clickable, switches to Reviews tab. If rating === 0 → "Нет оценок"
    • Meta line 1: location icon + city name (resolve city_id via geo store). If city_id === null → hide line
    • Meta line 2: calendar icon + "На сайте с {month year}" from created_at
  • Right (desktop): Button "Написать" → toast "Скоро будет доступно"
  • Mobile: Full-width button "Написать продавцу" below header

Stats Block

3 cards in a row (flex gap-4):

  1. "Объявлений" — products_count
  2. "Рейтинг" — rating with star (or "—" if 0)
  3. "Отзывов" — reviews_count

Card style: number large on top, label small below. Mobile: 3 in row, compact.

Tabs

UTabs with 2 items:

  • "Объявления (N)" — products_count
  • "Отзывы (N)" — reviews_count

Listings Tab

  • Grid: grid grid-cols-2 lg:grid-cols-4 gap-4
  • Each item: EntitiesProductCard (existing component)
  • "Показать ещё" button via useCursorPagination
  • Empty state: icon + "У продавца пока нет активных объявлений"

Reviews Tab

  • Placeholder: message icon + "Отзывы скоро будут доступны"
  • Centered, text-muted

"Write Message" Button

  • useToast().add({ title: 'Скоро будет доступно', description: 'Система сообщений в разработке' })

City Resolution

city_id is a number. To display city name:

  • Check useGeoStore for cached regions/cities
  • If not found, fetch from geo API (regions → cities) or leave hidden
  • Simplest approach: fetch all regions, find matching city — or store city name on geo store if previously selected

Loading State

Skeleton: avatar circle + text lines + 3 stat placeholders + grid of card skeletons (4 desktop / 2 mobile).

i18n Keys

Add to i18n/locales/ru.json under seller:

seller.products — "Объявления"
seller.reviews — "Отзывы"
seller.listings — "Объявлений"
seller.rating — "Рейтинг"
seller.reviewsCount — "Отзывов"
seller.noRating — "Нет оценок"
seller.memberSince — "На сайте с {date}"
seller.noProducts — "У продавца пока нет активных объявлений"
seller.reviewsComingSoon — "Отзывы скоро будут доступны"
seller.writeMessage — "Написать"
seller.writeMessageMobile — "Написать продавцу"
seller.messagingComingSoon — "Скоро будет доступно"
seller.messagingDescription — "Система сообщений в разработке"

Decisions Log

QuestionDecision
"Написать" button without messaging APIShow button, toast "Скоро будет доступно"
Reviews tab without reviews APIShow tab with placeholder "Отзывы скоро будут доступны"
Stats cards content3 cards: объявлений, рейтинг, отзывов (from real API fields)
Products pagination"Показать ещё" button via useCursorPagination