diff --git a/frontend/linktree-frontend/src/app/[username]/page.tsx b/frontend/linktree-frontend/src/app/[username]/page.tsx index a8654ed..0583b99 100644 --- a/frontend/linktree-frontend/src/app/[username]/page.tsx +++ b/frontend/linktree-frontend/src/app/[username]/page.tsx @@ -5,6 +5,7 @@ import { notFound } from 'next/navigation' import Image from 'next/image' import Link from 'next/link' import { useEffect, useState, Fragment } from 'react' +import FontLoader from '../components/FontLoader' interface LinkItem { id: number @@ -337,11 +338,12 @@ export default function UserPage({ ) - // Карточки (большие карточки с описанием) const renderCardsLayout = () => (
-
Группы ссылок
+ {(designSettings.show_groups_title !== false) && ( +
Группы ссылок
+ )}
{data!.groups.map((group) => ( @@ -375,15 +377,32 @@ export default function UserPage({
-
+ {designSettings.group_overlay_enabled && ( +
+ )} +
{group.description && ( -

{group.description}

+

+ {group.description} +

)}
{group.links.map((link) => ( @@ -422,6 +441,7 @@ export default function UserPage({
))}
+
@@ -677,7 +697,9 @@ export default function UserPage({ const renderTimelineLayout = () => (
-
Группы ссылок
+ {(designSettings.show_groups_title !== false) && ( +
Группы ссылок
+ )}
{data!.groups.map((group, index) => ( @@ -706,15 +728,32 @@ export default function UserPage({
-
+ {designSettings.group_overlay_enabled && ( +
+ )} +
{group.description && ( -

{group.description}

+

+ {group.description} +

)} {group.links.slice(0, 5).map(link => ( 5 && ( +{group.links.length - 5} еще... )} +
{/* footer intentionally left empty for public page, mirrors dashboard structure */} @@ -759,7 +799,9 @@ export default function UserPage({ const renderMagazineLayout = () => (
-
Группы ссылок
+ {(designSettings.show_groups_title !== false) && ( +
Группы ссылок
+ )}
{data!.groups.map((group, index) => ( @@ -767,7 +809,8 @@ export default function UserPage({
-
+ {designSettings.group_overlay_enabled && group.background_image && ( +
+ )} +
{!group.background_image && ( group.icon_url && designSettings.show_group_icons ? (
)} +
@@ -799,7 +854,10 @@ export default function UserPage({
{group.name}
-

+

{group.description || `${group.links.length} ссылок в этой группе`}

@@ -902,7 +960,14 @@ export default function UserPage({ } return ( -
+ <> + {/* Динамическая загрузка шрифтов */} + +
{/* Обложка пользователя - растягиваем на всю ширину экрана */} {data.cover && ( @@ -1053,5 +1118,6 @@ export default function UserPage({
+ ) } diff --git a/frontend/linktree-frontend/src/app/components/CustomizationPanel.tsx b/frontend/linktree-frontend/src/app/components/CustomizationPanel.tsx index 2d04848..6d50c6b 100644 --- a/frontend/linktree-frontend/src/app/components/CustomizationPanel.tsx +++ b/frontend/linktree-frontend/src/app/components/CustomizationPanel.tsx @@ -673,15 +673,20 @@ export function CustomizationPanel({ isOpen, onClose, onSettingsUpdate }: Custom value={settings.font_family} onChange={(e) => handleChange('font_family', e.target.value)} > - - + + - - - - - - + + + + + + + + + + +
@@ -692,19 +697,25 @@ export function CustomizationPanel({ isOpen, onClose, onSettingsUpdate }: Custom onChange={(e) => handleChange('heading_font_family', e.target.value)} > - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + +
@@ -715,9 +726,20 @@ export function CustomizationPanel({ isOpen, onClose, onSettingsUpdate }: Custom onChange={(e) => handleChange('body_font_family', e.target.value)} > - - - + + + + + + + + + + + + + + diff --git a/frontend/linktree-frontend/src/app/components/FontLoader.tsx b/frontend/linktree-frontend/src/app/components/FontLoader.tsx new file mode 100644 index 0000000..de5c9c8 --- /dev/null +++ b/frontend/linktree-frontend/src/app/components/FontLoader.tsx @@ -0,0 +1,78 @@ +'use client' + +import { useEffect } from 'react' + +interface FontLoaderProps { + fontFamily?: string + headingFontFamily?: string + bodyFontFamily?: string +} + +const FontLoader = ({ fontFamily, headingFontFamily, bodyFontFamily }: FontLoaderProps) => { + useEffect(() => { + // Собираем уникальные шрифты для загрузки + const fontsToLoad = new Set() + + // Функция для извлечения названия шрифта из CSS font-family + const extractFontName = (fontFamilyString: string) => { + if (!fontFamilyString || fontFamilyString === 'sans-serif' || fontFamilyString === 'serif' || fontFamilyString === 'monospace') { + return null + } + + // Извлекаем первый шрифт из строки, убираем кавычки + const firstFont = fontFamilyString.split(',')[0].trim().replace(/['"]/g, '') + + // Проверяем, что это не системный шрифт + if (firstFont === 'sans-serif' || firstFont === 'serif' || firstFont === 'monospace') { + return null + } + + return firstFont + } + + // Добавляем шрифты в список загрузки + if (fontFamily) { + const font = extractFontName(fontFamily) + if (font) fontsToLoad.add(font) + } + + if (headingFontFamily) { + const font = extractFontName(headingFontFamily) + if (font) fontsToLoad.add(font) + } + + if (bodyFontFamily) { + const font = extractFontName(bodyFontFamily) + if (font) fontsToLoad.add(font) + } + + // Загружаем шрифты через Google Fonts + if (fontsToLoad.size > 0) { + const fontNames = Array.from(fontsToLoad) + + // Проверяем, не загружен ли уже этот набор шрифтов + const fontId = `font-loader-${fontNames.join('-').toLowerCase().replace(/\s+/g, '-')}` + + if (!document.getElementById(fontId)) { + const fontUrl = `https://fonts.googleapis.com/css2?${fontNames.map(font => + `family=${encodeURIComponent(font)}:wght@300;400;500;600;700` + ).join('&')}&display=swap&subset=latin,cyrillic` + + const link = document.createElement('link') + link.id = fontId + link.rel = 'stylesheet' + link.href = fontUrl + document.head.appendChild(link) + } + } + + // Cleanup function - удаляем неиспользуемые шрифты + return () => { + // В продакшене можно добавить логику очистки неиспользуемых шрифтов + } + }, [fontFamily, headingFontFamily, bodyFontFamily]) + + return null // Этот компонент не рендерит ничего видимого +} + +export default FontLoader \ No newline at end of file