diff --git a/apps/api/prisma/seed.ts b/apps/api/prisma/seed.ts index fd874e0..7d60ac2 100644 --- a/apps/api/prisma/seed.ts +++ b/apps/api/prisma/seed.ts @@ -9,18 +9,36 @@ const BLOCKS = [ { path: '/blocks/navigation', name: 'Шапка / Навигация', - version: 'v1.0', + version: 'v1.3', isInPreview: true, changelog: [ + { version: 'v1.3', date: '24.03.2026', changes: [ + 'Подменю: выпадающие списки при hover', + 'Hover-эффект: бежевый фон #f5f0e6', + 'Пункты подчёркнуты, без разделителей', + 'Все пункты чёрного цвета #000', + ]}, + { version: 'v1.2', date: '24.03.2026', changes: [ + 'Убрана рамка и тень вокруг шапки', + '3 столбца: логотип | ссылки | телефон+кнопка', + 'Реальный логотип logo-main.png', + ]}, + { version: 'v1.1', date: '24.03.2026', changes: [ + 'Адрес: «К. Цеткин, 9», ссылки, телефон 25px, меню 18px', + ]}, { version: 'v1.0', date: '23.03.2026', changes: ['Топ-бар, логотип, главное меню из 8 пунктов'] }, ], }, { path: '/blocks/hero', name: 'Hero-баннер', - version: 'v1.2', + version: 'v1.3', isInPreview: true, changelog: [ + { version: 'v1.3', date: '24.03.2026', changes: [ + 'Счётчик: «Поделиться ✉ 98572» (было «👁 98 573 просмотра»)', + 'Убраны кнопки VK/FB/TW', + ]}, { version: 'v1.2', date: '24.03.2026', changes: [ 'H1: цвет #cb9768, размер 36px (было ~20px #53514e)', 'Заголовок баннера: 22px #333 (было 16px #111827)', @@ -36,9 +54,13 @@ const BLOCKS = [ { path: '/blocks/ceo', name: 'Вводный текст (CEO-блок)', - version: 'v1.0', + version: 'v1.1', isInPreview: false, changelog: [ + { version: 'v1.1', date: '24.03.2026', changes: [ + 'Адрес: «ул. Цитная, 9» → «ул. Клары Цеткин, 9»', + 'Цвет ссылок: #52b4bd (было #0089c3)', + ]}, { version: 'v1.0', date: '23.03.2026', changes: ['Текст специализации клиники, вопросы-стимулы'] }, ], }, @@ -76,9 +98,13 @@ const BLOCKS = [ { path: '/blocks/contact-forms', name: 'Формы записи', - version: 'v1.1', + version: 'v1.2', isInPreview: true, changelog: [ + { version: 'v1.2', date: '24.03.2026', changes: [ + 'Кнопка: bb-btn-lg 18px bold (было bb-btn-md 14px)', + 'border-radius кнопки: 4px (было 7px)', + ]}, { version: 'v1.1', date: '24.03.2026', changes: [ 'H2: 36px #000000', 'Фон формы 1: #b8e6ed → #d4f6f8', @@ -107,9 +133,18 @@ const BLOCKS = [ { path: '/blocks/contact', name: 'Подвал / Контакт', - version: 'v1.0', + version: 'v1.1', isInPreview: false, changelog: [ + { version: 'v1.1', date: '24.03.2026', changes: [ + 'Колонка «О клинике»: 13 ссылок по реальному сайту (было 7)', + 'Колонка «Заболевания»: 5 категорий (было 6 конкретных диагнозов)', + 'Колонка «Вопрос-ответ»: 6 пунктов по реальному сайту', + 'Колонка «Операции»: 11 операций (было 6)', + 'Два адреса: Клары Цеткин 9 + Газеты Звезда 31А', + 'Два графика работы по филиалам', + 'Соцсети: добавлен Дзен', + ]}, { version: 'v1.0', date: '23.03.2026', changes: ['4 колонки ссылок, адрес, часы работы'] }, ], }, diff --git a/apps/web/app/blocks/ceo/page.tsx b/apps/web/app/blocks/ceo/page.tsx index c35fa59..298e9a9 100644 --- a/apps/web/app/blocks/ceo/page.tsx +++ b/apps/web/app/blocks/ceo/page.tsx @@ -1,6 +1,7 @@ import type { Metadata } from "next"; import { LlmBlock, LlmSection, LlmTable, LlmRules } from "@/components/llm/LlmBlock"; import { BlockMetaBar } from "@/components/ui/BlockMetaBar"; +import { type ChangelogEntry } from "@/components/ui/BlockChangelog"; import { CeoBlock, CEO_QUESTIONS } from "@/components/blocks/CeoBlock"; export const metadata: Metadata = { @@ -10,7 +11,7 @@ export const metadata: Metadata = { const LLM_CEO_TEXT = ` БЛОК: Вводный текст клиники (CEO-блок) Источник: perm.oclinica.ru/lor — секция после баннера -Версия: v1.0 +Версия: v1.1 НАЗНАЧЕНИЕ: Информационный блок под hero-баннером. Рассказывает о специализации клиники @@ -49,6 +50,17 @@ const LLM_CEO_TEXT = ` `.trim(); +const CHANGELOG: ChangelogEntry[] = [ + { + version: "v1.1", + date: "24.03.2026", + changes: [ + "Адрес: «ул. Цитная, 9» заменён на «ул. Клары Цеткин, 9»", + "Цвет ссылок: #52b4bd (было #0089c3)", + ], + }, +]; + export default function CeoPage() { return (
@@ -63,7 +75,7 @@ export default function CeoPage() {

Вводный текст (CEO-блок)

- +

Блок после hero-баннера на perm.oclinica.ru/lor. Описание специализации клиники + вопросы-стимулы для пациентов. @@ -152,7 +164,7 @@ export default function CeoPage() { {/* LLM блок */} - + Формы записи - +

Два блока форм с perm.oclinica.ru/lor — запись на приём и запрос стоимости операции.

@@ -126,7 +134,7 @@ export default function ContactFormsPage() { {/* LLM блок */} - + @@ -84,7 +101,7 @@ export default function ContactFooterPage() {

Подвал (Footer)

- +

Подвал сайта с perm.oclinica.ru — 4 колонки ссылок, логотип, адрес, часы работы, соцсети.

@@ -122,7 +139,7 @@ export default function ContactFooterPage() { {/* LLM блок */} - + Hero-баннер - +

Главный баннер страницы раздела ЛОР — perm.oclinica.ru/lor. Двухколоночный блок, единый светло-кремовый фон{" "} #f9f4e7. @@ -161,7 +169,7 @@ export default function HeroPage() { {/* LLM блок */} - + @@ -58,7 +93,7 @@ export default function NavigationPage() {

Шапка и навигация

- +

Точное воспроизведение шапки с perm.oclinica.ru/lor. Три зоны: топ-бар, логотип, главное меню.

@@ -69,7 +104,7 @@ export default function NavigationPage() {

Живой пример

-
+
@@ -79,28 +114,19 @@ export default function NavigationPage() {

Анатомия шапки

-
+
{[ { - zone: "1. Топ-бар", + zone: "1. Верхняя панель", bg: "#f0f9ff", - height: "~40px", - color: "Фон: #fff", - desc: "Адрес, ссылки на разделы клиники, телефон, кнопка «Заказать звонок» (pill)", - }, - { - zone: "2. Логотип", - bg: "#f0fdf4", - height: "~64px", - color: "Фон: #fff", - desc: "Иконка-кружок (#0089c3) + название клиники двумя строками + подпись мелким", + desc: "Три столбца: логотип (logo-main.png) | три ссылки вертикально с 📍 (К. Цеткин 9, Клиника кашля, Центр диагностики) | телефон 25px + кнопка «Заказать звонок» (pill)", + details: "Фон: #fff · Без рамок · Ссылки: #52b4bd, подчёркнутые", }, { - zone: "3. Навигация", + zone: "2. Главное меню", bg: "#fefce8", - height: "~46px", - color: "Фон: #fff, border-top", - desc: "8 горизонтальных пунктов, активный = #0089c3, остальные = #53514e", + desc: "8 горизонтальных пунктов: Клиника | ЛОР врачи | Заболевания | Вопрос-ответ | ЛОР операции | Сурдология | Цены | Контакты", + details: "Фон: #fff · border-top · 18px · Активный: #0089c3, остальные: #000", }, ].map((z) => (

- H: {z.height} · {z.color} + {z.details}

))} @@ -127,29 +153,49 @@ export default function NavigationPage() {

Пункты главного меню

-
- {NAV_ITEMS.map((item, i) => ( - - {item} - {i === 0 && ( - - (активный) - - )} - - ))} +
+
+ {NAV_ITEMS.map((item, i) => ( +
+ + {item.label} + {item.submenu.length > 0 && ( + + )} + + {item.submenu.length > 0 && ( +
+ {item.submenu.map((sub) => ( + + {sub} + + ))} +
+ )} +
+ ))} +

- Порядок пунктов фиксирован. Hover и активный пункт — цвет #0089c3 (--brand-053m). + Порядок фиксирован. Все пункты чёрные (#000), подчёркнуты. Hover — бежевый фон #f5f0e6. ▾ — выпадающее подменю при наведении.

@@ -161,9 +207,13 @@ export default function NavigationPage() {
{[ { label: "Фон шапки", value: "#ffffff", token: "—" }, - { label: "Ссылки меню", value: "#53514e", token: "--brand-073m" }, - { label: "Активный / hover", value: "#0089c3", token: "--brand-053m" }, + { label: "Пункты меню", value: "#000000", token: "—" }, + { label: "Hover фон меню", value: "#f5f0e6", token: "bb-nav-item:hover" }, + { label: "Ссылки адресов", value: "#52b4bd", token: "—" }, { label: "Кнопка «Заказать»", value: "#e9e4d4", token: "bb-btn-pill" }, + { label: "Подменю фон", value: "#ffffff", token: "—" }, + { label: "Подменю hover", value: "#f5f0e6", token: "bb-nav-sub-item:hover" }, + { label: "Телефон", value: "#000000", token: "25px, bold" }, ].map((t) => (
{/* LLM блок */} - + @@ -204,7 +253,7 @@ export default function NavigationPage() { headers={["Элемент", "Цвет", "Токен"]} rows={[ ["Фон шапки", "#ffffff", "—"], - ["Ссылки меню (default)", "#53514e", "--brand-073m"], + ["Ссылки меню (default)", "#000000", "—"], ["Активный пункт / hover", "#0089c3", "--brand-053m"], ["Кнопка «Заказать звонок»", "#e9e4d4 / border #d5cfbd", "bb-btn-pill"], ["Телефон", "#111827, font-weight bold", "—"], diff --git a/apps/web/app/globals.css b/apps/web/app/globals.css index da33c22..9c3db49 100644 --- a/apps/web/app/globals.css +++ b/apps/web/app/globals.css @@ -80,8 +80,8 @@ body { background: #FFA39C; color: #fff; border-color: #FF847B; - border-radius: 7px; - font-weight: bold; + border-radius: 4px; + font-weight: 700; box-shadow: 0px 0px 5px rgba(0,0,0,0.4), 0px 3px 5px rgba(0,0,0,0.25); } @@ -109,6 +109,20 @@ body { border-radius: 25px; } +/* ─── Навигация сайта ────────────────────────────────────────── */ +.bb-nav-item { + transition: background 0.15s; +} +.bb-nav-item:hover { + background: #f5f0e6; +} +.bb-nav-sub-item { + transition: background 0.1s; +} +.bb-nav-sub-item:hover { + background: #f5f0e6; +} + /* ─── Форм-контролы (Sprint 3) ───────────────────────────────── */ .bb-input, .bb-textarea, diff --git a/apps/web/components/blocks/CeoBlock.tsx b/apps/web/components/blocks/CeoBlock.tsx index f89e279..1fd71ff 100644 --- a/apps/web/components/blocks/CeoBlock.tsx +++ b/apps/web/components/blocks/CeoBlock.tsx @@ -20,10 +20,10 @@ export function CeoBlock() { >

Клиника ухо, нос специализируется на оториноларингологии – лечении взрослых и детей - с ЛОР заболеваниями. ЛОР клиника представлена на двух адресах:{" "} - ул. Цитная, 9,{" "} - ул. Г. Звезда, 31а.{" "} - Это Клиника лечения кашля и аллергии. + с ЛОР заболеваниями. ЛОР клиника ухо, горло, нос в Перми представлена по двум адресам:{" "} + ул. Клары Цеткин, 9 |{" "} + ул. Г. Звезда, 31а.{" "} + Это Клиника лечения кашля и аллергии.

diff --git a/apps/web/components/blocks/ContactFormsBlock.tsx b/apps/web/components/blocks/ContactFormsBlock.tsx index c748952..48daf83 100644 --- a/apps/web/components/blocks/ContactFormsBlock.tsx +++ b/apps/web/components/blocks/ContactFormsBlock.tsx @@ -36,7 +36,7 @@ export function ContactFormsBlock() { Отправляя данные, я даю согласие на обработку персональных данных -
@@ -74,7 +74,7 @@ export function ContactFormsBlock() { Отправляя данные, я даю согласие на обработку персональных данных -
diff --git a/apps/web/components/blocks/FooterBlock.tsx b/apps/web/components/blocks/FooterBlock.tsx index 085fbea..7233c64 100644 --- a/apps/web/components/blocks/FooterBlock.tsx +++ b/apps/web/components/blocks/FooterBlock.tsx @@ -1,24 +1,37 @@ const FOOTER_COLUMNS = [ { title: "О клинике", - links: ["Лицензия", "Миссия", "Врачи", "Вакансии", "История", "Образовательная деятельность", "При инфо"], + links: [ + "Врачи", "Цены", "Контакты", "Новости", "Отзывы", "История", + "Официальная информация", "Оборудование", "Слуховые аппараты", + "ЛОР конференции", "Вакансии", "Клиника кашля и аллергии", "Доверенность", + ], }, { title: "Заболевания", - links: ["Ринит", "Отит", "Гайморит", "Тонзиллит", "Полипы носа", "Искривление перегородки"], + links: [ + "Заболевания уха", "Заболевания горла", "Заболевания носа", + "У детей", "У беременных", + ], }, { title: "Вопрос-ответ", links: [ - "Что нужно знать до операции на ухо", - "Что нужно знать до операции на нос", - "Отзывы до и после лечения у детей", - "Что нужно знать при лечении у детей", + "Вопросы-ответы по заболеваниям уха", + "Вопросы-ответы по заболеваниям горла", + "Вопросы-ответы по заболеваниям носа", + "Вопросы-ответы по детским заболеваниям", + "Вопросы-ответы по операциям", + "Задать свой вопрос?", ], }, { title: "Операции", - links: ["Септопластика", "Турбинопластика", "Тонзиллэктомия", "Аденотомия", "Тимпанопластика", "Мирингопластика"], + links: [ + "Аденотомия", "Вазотомия", "Мастоидэктомия", "Мирингопластика", + "Оссикулопластика", "Септопластика", "Стапедопластика", + "Тимпанопластика", "Тонзиллотомия", "Микрогайморотомия", "Полипотомия", + ], }, ]; @@ -43,8 +56,8 @@ export function FooterBlock() {
  • {link} @@ -61,33 +74,23 @@ export function FooterBlock() { style={{ background: "#fff" }} > {/* Логотип */} -
    -
    - ✚ -
    -
    -
    - Клиника
    ухо, горло, нос -
    -
    - им. проф. Е.Н.Оленевой -
    -
    +
    + Клиника ухо, горло, нос
    - {/* Адрес и соцсети */} + {/* Адреса и соцсети */}
    -

    - Мы находимся по адресу: Пермь, ул. Г. Звезда, 31а -

    +
    +

    Мы находимся по адресам:

    +

    г. Пермь, ул. Клары Цеткин, 9

    +

    г. Пермь, ул. Газеты Звезда, 31А

    +
    - {["VK", "OK", "YT", "TG"].map((s) => ( + {["VK", "YT", "TG", "OK", "Дзен"].map((s) => (
    - {/* Часы работы */} -
    -

    - Часы работы: + {/* Часы работы — два филиала */} +

    +

    + Время работы клиники:

    -

    Пн–пт: 9:00–21:00

    -

    Сб: 9:00–18:00

    -

    Вс: выходной

    +
    +

    Газеты Звезда 31а

    +

    пн – пт: с 09.00 до 21.00

    +

    сб – вс: с 09:00 до 19:00

    +
    +
    +

    Клары Цеткин 9

    +

    пн – сб: с 09.00 до 17.00

    +

    вс – выходной

    +
    diff --git a/apps/web/components/blocks/HeroBlock.tsx b/apps/web/components/blocks/HeroBlock.tsx index 3ef9fec..cccda9b 100644 --- a/apps/web/components/blocks/HeroBlock.tsx +++ b/apps/web/components/blocks/HeroBlock.tsx @@ -75,26 +75,17 @@ export function HeroBlock() {
    {/* Под баннером: соцсети + просмотры */} -
    - - Поделиться: - - {["VK", "FB", "TW"].map((s) => ( - - ))} - - 👁 98 573 просмотра - +
    +
    ); diff --git a/apps/web/components/blocks/NavigationBlock.tsx b/apps/web/components/blocks/NavigationBlock.tsx index 336d1d9..a3a6cf3 100644 --- a/apps/web/components/blocks/NavigationBlock.tsx +++ b/apps/web/components/blocks/NavigationBlock.tsx @@ -1,81 +1,93 @@ -export const NAV_ITEMS = [ - "Клиника", - "ЛОР врачи", - "Заболевания", - "Вопрос-ответ", - "ЛОР-операции", - "Сурдология", - "Цены", - "Контакты", -]; +"use client"; + +import { NAV_ITEMS } from "./navData"; +export { NAV_ITEMS }; + +function NavItem({ item, isActive }: { item: (typeof NAV_ITEMS)[number]; isActive: boolean }) { + const hasSubmenu = item.submenu.length > 0; -export function NavigationBlock() { return ( -
    - {/* Топ-бар */} -
    + - + ); +} + +export function NavigationBlock() { + return ( +
    + {/* Верхняя панель: три столбца — логотип | ссылки | телефон+кнопка */} +
    + {/* Столбец 1: Логотип */} +
    + Клиника ухо, горло, нос +
    + + {/* Столбец 2: Три ссылки вертикально — прижат к логотипу */} + -
    - + + {/* Столбец 3: Телефон + кнопка вертикально — прижат вправо */} +
    + /342/ 255-53-84 - -
    -
    - - {/* Логотип */} -
    -
    -
    - ✚ -
    -
    -
    - Клиника
    ухо, горло, нос -
    -
    - им. проф. Е.Н.Оленевой -
    -
    +
    {/* Главное меню */} -
    diff --git a/apps/web/components/blocks/navData.ts b/apps/web/components/blocks/navData.ts new file mode 100644 index 0000000..eae8c8f --- /dev/null +++ b/apps/web/components/blocks/navData.ts @@ -0,0 +1,34 @@ +export const NAV_ITEMS = [ + { + label: "Клиника", + submenu: [ + "О клинике", "Официальная информация", "История", "Оборудование", + "Новости", "Отзывы", "ЛОР конференции", "Вакансии", "Доверенность", + "Клиника лечения кашля и аллергии", "Налоговый вычет", + ], + }, + { label: "ЛОР врачи", submenu: [] as string[] }, + { + label: "Заболевания", + submenu: ["Горло", "Ухо", "Нос", "У детей", "У беременных", "Диагностика"], + }, + { + label: "Вопрос-ответ", + submenu: [ + "Вопросы по заболеваниям уха", "Вопросы по заболеваниям горла", + "Вопросы по заболеваниям носа", "Вопросы по детским заболеваниям", + "Вопросы по операциям", "Задать свой вопрос?", + ], + }, + { + label: "ЛОР операции", + submenu: [ + "Аденотомия", "Вазотомия", "Мастоидэктомия", "Тимпанопластика 1 типа", + "Тимпанопластика 2 типа", "Оссикулопластика", "Септопластика", + "Стапедопластика", "Тонзиллотомия", "Полипотомия", "Микрогайморотомия", + ], + }, + { label: "Сурдология", submenu: [] as string[] }, + { label: "Цены", submenu: [] as string[] }, + { label: "Контакты", submenu: [] as string[] }, +]; diff --git a/apps/web/components/ui/BlockMetaBar.tsx b/apps/web/components/ui/BlockMetaBar.tsx index 3c8b6e1..493f68d 100644 --- a/apps/web/components/ui/BlockMetaBar.tsx +++ b/apps/web/components/ui/BlockMetaBar.tsx @@ -37,6 +37,7 @@ export function BlockMetaBar({ path, defaultVersion, defaultIsInPreview, default const [editing, setEditing] = useState(false); const [versionInput, setVersionInput] = useState(defaultVersion); const [saving, setSaving] = useState(false); + const [savingVersion, setSavingVersion] = useState(false); const [togglingPreview, setTogglingPreview] = useState(false); const [apiDown, setApiDown] = useState(false); const [localPreview, setLocalPreview] = useState(defaultIsInPreview); @@ -79,6 +80,22 @@ export function BlockMetaBar({ path, defaultVersion, defaultIsInPreview, default } } + async function saveFullVersion() { + if (apiDown) return; + setSavingVersion('saving'); + try { + const updated = await patch({ version: defaultVersion, changelog: defaultChangelog }); + if (updated) { + setMeta(updated); + setVersionInput(updated.version); + } + setSavingVersion('done'); + setTimeout(() => setSavingVersion(false), 1500); + } catch { + setSavingVersion(false); + } + } + async function togglePreview() { if (apiDown) { const newVal = !localPreview; @@ -180,6 +197,30 @@ export function BlockMetaBar({ path, defaultVersion, defaultIsInPreview, default : "Не в превью"} + · + + {/* Save version button */} + + {/* Subtle offline dot instead of "API офлайн" text */} {apiDown && (