From c39b0c0821d736046b95d831686ee27e4e2c40f0 Mon Sep 17 00:00:00 2001 From: Web-serfer Date: Wed, 8 Apr 2026 21:11:36 +0500 Subject: [PATCH] =?UTF-8?q?=D0=9D=D0=BE=D0=B2=D1=8B=D0=B5=20=D0=B8=D0=B7?= =?UTF-8?q?=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/base/CTA.astro | 209 ++++++++++++++++++ frontend/src/components/base/Pagination.astro | 178 +++++++++++++++ frontend/src/components/cases/CasesList.astro | 137 ++++-------- .../services/ServiceCategories.astro | 96 ++------ frontend/src/pages/blog/index.astro | 87 ++------ frontend/src/pages/blog/page/[page].astro | 87 ++------ frontend/src/pages/contacts.astro | 30 +-- frontend/src/pages/reviews.astro | 37 +++- frontend/src/pages/services.astro | 13 ++ 9 files changed, 512 insertions(+), 362 deletions(-) create mode 100644 frontend/src/components/base/CTA.astro create mode 100644 frontend/src/components/base/Pagination.astro diff --git a/frontend/src/components/base/CTA.astro b/frontend/src/components/base/CTA.astro new file mode 100644 index 0000000..89c334b --- /dev/null +++ b/frontend/src/components/base/CTA.astro @@ -0,0 +1,209 @@ +--- +import Button from '@components/base/Button.astro'; + +interface CTAProps { + icon?: 'chat' | 'consult' | 'help' | 'phone'; + title: string; + description: string; + btnText?: string; + btnHref?: string; + variant?: 'default' | 'consultation'; +} + +const { + icon = 'chat', + title, + description, + btnText, + btnHref = "#contact", + variant = 'default' +} = Astro.props as CTAProps; + +const iconPaths: Record = { + chat: '', + consult: '', + help: '', + phone: '' +}; +--- + +
+
+
+
+
+ +
+

{title}

+

{description}

+ {btnText && ( + + )} +
+
+
+ + + + diff --git a/frontend/src/components/base/Pagination.astro b/frontend/src/components/base/Pagination.astro new file mode 100644 index 0000000..e6d8111 --- /dev/null +++ b/frontend/src/components/base/Pagination.astro @@ -0,0 +1,178 @@ +--- +export interface PaginationProps { + currentPage: number; + totalPages: number; + baseUrl: string; + showPrevNext?: boolean; +} + +const { + currentPage, + totalPages, + baseUrl, + showPrevNext = true +} = Astro.props as PaginationProps; + +const getPageUrl = (page: number) => { + if (page === 1) return baseUrl; + return `${baseUrl}/page/${page}`; +}; + +const getPages = () => { + const pages: (number | string)[] = []; + for (let i = 1; i <= totalPages; i++) { + if (i === 1 || i === totalPages || (i >= currentPage - 1 && i <= currentPage + 1)) { + pages.push(i); + } else if (pages[pages.length - 1] !== '...') { + pages.push('...'); + } + } + return pages; +}; +--- + + + + diff --git a/frontend/src/components/cases/CasesList.astro b/frontend/src/components/cases/CasesList.astro index 0bfb43d..7a0c4ca 100644 --- a/frontend/src/components/cases/CasesList.astro +++ b/frontend/src/components/cases/CasesList.astro @@ -1,5 +1,6 @@ --- -import Button from '@components/base/Button.astro'; +import Pagination from '@components/base/Pagination.astro'; +import CTA from '@components/base/CTA.astro'; interface Case { id: number; @@ -96,8 +97,25 @@ const { sum: "280 000 ₽", href: "/cases/casco-damage-claim" } - ] as Case[] -} = Astro.props; + ] as Case[], + currentPage = 1, + casesPerPage = 4, + baseUrl = "/cases" +} = Astro.props as { + sectionSubtitle?: string; + sectionTitle?: string; + sectionDescription?: string; + filterLabel?: string; + cases?: Case[]; + currentPage?: number; + casesPerPage?: number; + baseUrl?: string; +}; + +const totalPages = Math.ceil(cases.length / casesPerPage); +const startIndex = (currentPage - 1) * casesPerPage; +const endIndex = startIndex + casesPerPage; +const paginatedCases = cases.slice(startIndex, endIndex); // Получаем уникальные категории const categories = ["Все", ...Array.from(new Set(cases.map((c: Case) => c.category)))]; @@ -130,7 +148,7 @@ const categories = ["Все", ...Array.from(new Set(cases.map((c: Case) => c.cat
- {cases.map((caseItem: Case, index: number) => ( + {paginatedCases.map((caseItem: Case, index: number) => (
@@ -204,19 +222,22 @@ const categories = ["Все", ...Array.from(new Set(cases.map((c: Case) => c.cat ))}
+ + {totalPages > 1 && ( + + )} + -
-
- - - -
-

Нужна помощь с похожей ситуацией?

-

Расскажите о вашей проблеме — мы найдём решение. Первая консультация бесплатно.

- -
+
@@ -347,7 +368,7 @@ const categories = ["Все", ...Array.from(new Set(cases.map((c: Case) => c.cat display: flex; flex-direction: column; gap: 2.5rem; - margin-bottom: 5rem; + margin-bottom: 3rem; } /* --- Карточка кейса --- */ @@ -592,72 +613,6 @@ const categories = ["Все", ...Array.from(new Set(cases.map((c: Case) => c.cat color: var(--color-accent); } - /* --- CTA --- */ - .cases-cta { - text-align: center; - padding: 3.5rem 2.5rem; - background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-light) 100%); - border-radius: 20px; - box-shadow: var(--shadow-xl); - position: relative; - overflow: hidden; - } - - .cases-cta::before { - content: ''; - position: absolute; - top: -50%; - right: -20%; - width: 60%; - height: 150%; - background: radial-gradient(circle, var(--color-accent-glow) 0%, transparent 70%); - pointer-events: none; - } - - .cases-cta__icon { - width: 64px; - height: 64px; - margin: 0 auto 1.5rem; - background: rgba(234, 194, 110, 0.15); - border-radius: 16px; - display: flex; - align-items: center; - justify-content: center; - color: var(--color-accent); - position: relative; - z-index: 1; - } - - .cases-cta__icon svg { - width: 32px; - height: 32px; - } - - .cases-cta__title { - font-size: 1.75rem; - font-weight: 700; - color: #ffffff; - margin: 0 0 0.75rem 0; - position: relative; - z-index: 1; - } - - .cases-cta__desc { - font-size: 1.05rem; - color: rgba(255, 255, 255, 0.75); - margin: 0 0 2rem 0; - max-width: 600px; - margin-left: auto; - margin-right: auto; - position: relative; - z-index: 1; - } - - .cases-cta .btn { - position: relative; - z-index: 1; - } - /* --- Анимации --- */ .animate-on-scroll { opacity: 0; @@ -736,18 +691,6 @@ const categories = ["Все", ...Array.from(new Set(cases.map((c: Case) => c.cat align-items: flex-start; gap: 0.75rem; } - - .cases-cta { - padding: 2.5rem 1.5rem; - } - - .cases-cta__title { - font-size: 1.5rem; - } - - .cases-cta__desc { - font-size: 0.95rem; - } } @media (max-width: 480px) { @@ -781,10 +724,6 @@ const categories = ["Все", ...Array.from(new Set(cases.map((c: Case) => c.cat flex-direction: column; gap: 0.75rem; } - - .cases-cta { - padding: 2rem 1.25rem; - } } @media (prefers-reduced-motion: reduce) { diff --git a/frontend/src/components/services/ServiceCategories.astro b/frontend/src/components/services/ServiceCategories.astro index 2a64deb..154b341 100644 --- a/frontend/src/components/services/ServiceCategories.astro +++ b/frontend/src/components/services/ServiceCategories.astro @@ -1,5 +1,6 @@ --- import Button from '@components/base/Button.astro'; +import Pagination from '@components/base/Pagination.astro'; interface ServiceCategory { id: string; @@ -133,8 +134,19 @@ const { } ] } - ] as ServiceCategory[] -} = Astro.props; + ] as ServiceCategory[], + currentPage = 1, + servicesPerPage = 6, + baseUrl = "/services" +} = Astro.props as { + sectionSubtitle?: string; + sectionTitle?: string; + sectionDescription?: string; + categories?: ServiceCategory[]; + currentPage?: number; + servicesPerPage?: number; + baseUrl?: string; +}; ---
@@ -212,15 +224,6 @@ const { ))} - - -
-

Не нашли нужную услугу?

-

Позвоните — разберём вашу ситуацию бесплатно

- -
@@ -629,51 +632,6 @@ const { color: var(--color-accent); } - /* --- Нижний CTA --- */ - .section-cta { - margin-top: 5rem; - text-align: center; - padding: 3rem 2rem; - background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-light) 100%); - border-radius: 20px; - box-shadow: var(--shadow-xl); - position: relative; - overflow: hidden; - } - - .section-cta::before { - content: ''; - position: absolute; - top: -50%; - right: -20%; - width: 60%; - height: 150%; - background: radial-gradient(circle, var(--color-accent-glow) 0%, transparent 70%); - pointer-events: none; - } - - .cta-text-main { - font-size: 1.5rem; - font-weight: 700; - color: #ffffff; - margin: 0 0 0.5rem 0; - position: relative; - z-index: 1; - } - - .cta-text-sub { - font-size: 1rem; - color: rgba(255, 255, 255, 0.7); - margin: 0 0 1.5rem 0; - position: relative; - z-index: 1; - } - - .section-cta .btn { - position: relative; - z-index: 1; - } - /* --- Адаптивность --- */ @media (max-width: 1200px) { .services-grid { @@ -755,19 +713,6 @@ const { justify-content: flex-end; width: 100%; } - - .section-cta { - padding: 2rem 1.5rem; - margin-top: 3rem; - } - - .cta-text-main { - font-size: 1.25rem; - } - - .cta-text-sub { - font-size: 0.9rem; - } } @media (max-width: 480px) { @@ -810,19 +755,6 @@ const { .service-title { font-size: 1.1rem; } - - .section-cta { - padding: 1.5rem 1rem; - border-radius: 16px; - } - - .cta-text-main { - font-size: 1.1rem; - } - - .cta-text-sub { - font-size: 0.85rem; - } } /* @media (prefers-reduced-motion: reduce) */ diff --git a/frontend/src/pages/blog/index.astro b/frontend/src/pages/blog/index.astro index 9c5befa..f9470a8 100644 --- a/frontend/src/pages/blog/index.astro +++ b/frontend/src/pages/blog/index.astro @@ -5,6 +5,8 @@ import PageHero from '@components/base/PageHero.astro'; import BlogCategories from '@components/blog/BlogCategories.astro'; import BlogCard from '@components/blog/BlogCard.astro'; import BlogPagination from '@components/blog/BlogPagination.astro'; +import Pagination from '@components/base/Pagination.astro'; +import CTA from '@components/base/CTA.astro'; import SearchModal from '@components/base/SearchModal.astro'; import { blogPosts, categories } from '@data/blogData'; @@ -64,24 +66,21 @@ const paginatedPosts = blogPosts.slice(startIndex, endIndex); - + -
-
-
-

Нужна консультация юриста?

-

- Не нашли ответ на свой вопрос? Запишитесь на бесплатную консультацию — мы поможем разобраться в вашей ситуации -

- -
-
-
+ @@ -102,66 +101,6 @@ const paginatedPosts = blogPosts.slice(startIndex, endIndex); transition: opacity 0.3s ease, transform 0.3s ease; } - /* ===== CTA ===== */ - .blog-cta { - padding: 5rem 0; - background: linear-gradient(135deg, #0a2540 0%, #1e3a5f 100%); - position: relative; - overflow: hidden; - } - - .blog-cta::before { - content: ''; - position: absolute; - bottom: -30%; - left: -10%; - width: 500px; - height: 500px; - background: radial-gradient(circle, rgba(212, 175, 55, 0.1) 0%, transparent 70%); - border-radius: 50%; - } - - .cta-content { - position: relative; - z-index: 1; - text-align: center; - max-width: 600px; - margin: 0 auto; - } - - .cta-title { - font-size: clamp(1.75rem, 4vw, 2.5rem); - font-weight: 800; - color: #ffffff; - margin: 0 0 1rem; - letter-spacing: -0.02em; - } - - .cta-text { - color: rgba(255, 255, 255, 0.75); - font-size: 1.1rem; - line-height: 1.6; - margin: 0 0 2rem; - } - - .cta-button { - background: linear-gradient(135deg, #d4af37 0%, #eac26e 100%); - color: #1e293b; - border: none; - padding: 1rem 2.5rem; - border-radius: 0.75rem; - font-size: 1.1rem; - font-weight: 700; - cursor: pointer; - transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); - box-shadow: 0 4px 15px rgba(212, 175, 55, 0.3); - } - - .cta-button:hover { - transform: translateY(-3px); - box-shadow: 0 8px 25px rgba(212, 175, 55, 0.4); - } - /* ===== RESPONSIVE ===== */ @media (max-width: 1024px) { .blog-grid { diff --git a/frontend/src/pages/blog/page/[page].astro b/frontend/src/pages/blog/page/[page].astro index 904585c..002aa53 100644 --- a/frontend/src/pages/blog/page/[page].astro +++ b/frontend/src/pages/blog/page/[page].astro @@ -5,6 +5,8 @@ import PageHero from '@components/base/PageHero.astro'; import BlogCategories from '@components/blog/BlogCategories.astro'; import BlogCard from '@components/blog/BlogCard.astro'; import BlogPagination from '@components/blog/BlogPagination.astro'; +import Pagination from '@components/base/Pagination.astro'; +import CTA from '@components/base/CTA.astro'; import SearchModal from '@components/base/SearchModal.astro'; import { blogPosts, categories } from '@data/blogData'; @@ -65,24 +67,21 @@ const paginatedPosts = blogPosts.slice(startIndex, endIndex); - + -
-
-
-

Нужна консультация юриста?

-

- Не нашли ответ на свой вопрос? Запишитесь на бесплатную консультацию — мы поможем разобраться в вашей ситуации -

- -
-
-
+ @@ -103,66 +102,6 @@ const paginatedPosts = blogPosts.slice(startIndex, endIndex); transition: opacity 0.3s ease, transform 0.3s ease; } - /* ===== CTA ===== */ - .blog-cta { - padding: 5rem 0; - background: linear-gradient(135deg, #0a2540 0%, #1e3a5f 100%); - position: relative; - overflow: hidden; - } - - .blog-cta::before { - content: ''; - position: absolute; - bottom: -30%; - left: -10%; - width: 500px; - height: 500px; - background: radial-gradient(circle, rgba(212, 175, 55, 0.1) 0%, transparent 70%); - border-radius: 50%; - } - - .cta-content { - position: relative; - z-index: 1; - text-align: center; - max-width: 600px; - margin: 0 auto; - } - - .cta-title { - font-size: clamp(1.75rem, 4vw, 2.5rem); - font-weight: 800; - color: #ffffff; - margin: 0 0 1rem; - letter-spacing: -0.02em; - } - - .cta-text { - color: rgba(255, 255, 255, 0.75); - font-size: 1.1rem; - line-height: 1.6; - margin: 0 0 2rem; - } - - .cta-button { - background: linear-gradient(135deg, #d4af37 0%, #eac26e 100%); - color: #1e293b; - border: none; - padding: 1rem 2.5rem; - border-radius: 0.75rem; - font-size: 1.1rem; - font-weight: 700; - cursor: pointer; - transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); - box-shadow: 0 4px 15px rgba(212, 175, 55, 0.3); - } - - .cta-button:hover { - transform: translateY(-3px); - box-shadow: 0 8px 25px rgba(212, 175, 55, 0.4); - } - /* ===== RESPONSIVE ===== */ @media (max-width: 1024px) { .blog-grid { diff --git a/frontend/src/pages/contacts.astro b/frontend/src/pages/contacts.astro index ab3e004..4221f0c 100644 --- a/frontend/src/pages/contacts.astro +++ b/frontend/src/pages/contacts.astro @@ -2,6 +2,7 @@ import Layout from '@layouts/Layout.astro'; import { SITE_URL, COMPANY } from '@constants'; import PageHero from '@components/base/PageHero.astro'; +import CTA from '@components/base/CTA.astro'; // Логика авторизации (пока статичная переменная) const isAuthorized = false; // Измените на true, чтобы увидеть форму @@ -174,21 +175,12 @@ const isAuthorized = false; // Измените на true, чтобы увиде -
-
-
-

- Нужна срочная помощь? -

-

- Запишитесь на бесплатную консультацию прямо сейчас — мы перезвоним в течение 15 минут -

- -
-
-
+