diff --git a/public/images/classes/body-plastic.webp b/public/images/classes/body-plastic.webp deleted file mode 100644 index cba3ae5..0000000 Binary files a/public/images/classes/body-plastic.webp and /dev/null differ diff --git a/public/images/classes/exot-w.webp b/public/images/classes/exot-w.webp deleted file mode 100644 index f7e18e0..0000000 Binary files a/public/images/classes/exot-w.webp and /dev/null differ diff --git a/public/images/classes/exot.webp b/public/images/classes/exot.webp deleted file mode 100644 index b781d92..0000000 Binary files a/public/images/classes/exot.webp and /dev/null differ diff --git a/public/images/classes/master-class-1.webp b/public/images/classes/master-class-1.webp deleted file mode 100644 index 9e99571..0000000 Binary files a/public/images/classes/master-class-1.webp and /dev/null differ diff --git a/public/images/classes/master-class-2.webp b/public/images/classes/master-class-2.webp deleted file mode 100644 index cf7e641..0000000 Binary files a/public/images/classes/master-class-2.webp and /dev/null differ diff --git a/public/images/classes/master-class-3.webp b/public/images/classes/master-class-3.webp deleted file mode 100644 index 9984bcb..0000000 Binary files a/public/images/classes/master-class-3.webp and /dev/null differ diff --git a/public/images/classes/online-classes.webp b/public/images/classes/online-classes.webp deleted file mode 100644 index 3c6d4b7..0000000 Binary files a/public/images/classes/online-classes.webp and /dev/null differ diff --git a/public/images/classes/parter-1.webp b/public/images/classes/parter-1.webp deleted file mode 100644 index 14d2141..0000000 Binary files a/public/images/classes/parter-1.webp and /dev/null differ diff --git a/public/images/classes/parter-2.webp b/public/images/classes/parter-2.webp deleted file mode 100644 index 78e2952..0000000 Binary files a/public/images/classes/parter-2.webp and /dev/null differ diff --git a/public/images/classes/pole-dance.webp b/public/images/classes/pole-dance.webp deleted file mode 100644 index f00ce16..0000000 Binary files a/public/images/classes/pole-dance.webp and /dev/null differ diff --git a/public/images/logo.png b/public/images/logo.png deleted file mode 100644 index 686d617..0000000 Binary files a/public/images/logo.png and /dev/null differ diff --git a/public/images/logo.svg b/public/images/logo.svg deleted file mode 100644 index d1ab7e3..0000000 --- a/public/images/logo.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/public/images/master-classes/anastasia-chaley-1773587537984.webp b/public/images/master-classes/anastasia-chaley-1773587537984.webp deleted file mode 100644 index d5049d0..0000000 Binary files a/public/images/master-classes/anastasia-chaley-1773587537984.webp and /dev/null differ diff --git a/public/images/master-classes/exot-1773584463793.webp b/public/images/master-classes/exot-1773584463793.webp deleted file mode 100644 index b781d92..0000000 Binary files a/public/images/master-classes/exot-1773584463793.webp and /dev/null differ diff --git a/public/images/master-classes/exot-1773675117871.webp b/public/images/master-classes/exot-1773675117871.webp deleted file mode 100644 index b781d92..0000000 Binary files a/public/images/master-classes/exot-1773675117871.webp and /dev/null differ diff --git a/public/images/news/online-classes-1773605597711.webp b/public/images/news/online-classes-1773605597711.webp deleted file mode 100644 index 3c6d4b7..0000000 Binary files a/public/images/news/online-classes-1773605597711.webp and /dev/null differ diff --git a/public/images/news/saveclip-app-605404066-17852939781600031-474959415-1774477696991.jpg b/public/images/news/saveclip-app-605404066-17852939781600031-474959415-1774477696991.jpg deleted file mode 100644 index 2a5d46f..0000000 Binary files a/public/images/news/saveclip-app-605404066-17852939781600031-474959415-1774477696991.jpg and /dev/null differ diff --git a/public/images/news/saveclip-app-605404066-17852939781600031-474959415-1774511759934.jpg b/public/images/news/saveclip-app-605404066-17852939781600031-474959415-1774511759934.jpg deleted file mode 100644 index 2a5d46f..0000000 Binary files a/public/images/news/saveclip-app-605404066-17852939781600031-474959415-1774511759934.jpg and /dev/null differ diff --git a/public/images/news/saveclip-app-605404066-17852939781600031-474959415-1774515538630.jpg b/public/images/news/saveclip-app-605404066-17852939781600031-474959415-1774515538630.jpg deleted file mode 100644 index 2a5d46f..0000000 Binary files a/public/images/news/saveclip-app-605404066-17852939781600031-474959415-1774515538630.jpg and /dev/null differ diff --git a/public/images/news/saveclip-app-605404066-17852939781600031-474959415-1774515545926.jpg b/public/images/news/saveclip-app-605404066-17852939781600031-474959415-1774515545926.jpg deleted file mode 100644 index 2a5d46f..0000000 Binary files a/public/images/news/saveclip-app-605404066-17852939781600031-474959415-1774515545926.jpg and /dev/null differ diff --git a/public/images/news/saveclip-app-605404066-17852939781600031-474959415-1774516098008.jpg b/public/images/news/saveclip-app-605404066-17852939781600031-474959415-1774516098008.jpg deleted file mode 100644 index 2a5d46f..0000000 Binary files a/public/images/news/saveclip-app-605404066-17852939781600031-474959415-1774516098008.jpg and /dev/null differ diff --git a/public/images/news/saveclip-app-605404066-17852939781600031-474959415-1774516126607.jpg b/public/images/news/saveclip-app-605404066-17852939781600031-474959415-1774516126607.jpg deleted file mode 100644 index 2a5d46f..0000000 Binary files a/public/images/news/saveclip-app-605404066-17852939781600031-474959415-1774516126607.jpg and /dev/null differ diff --git a/public/images/news/saveclip-app-658751600-18313798510265536-337520394-1774441073467.jpg b/public/images/news/saveclip-app-658751600-18313798510265536-337520394-1774441073467.jpg deleted file mode 100644 index 975b0e2..0000000 Binary files a/public/images/news/saveclip-app-658751600-18313798510265536-337520394-1774441073467.jpg and /dev/null differ diff --git a/public/images/team/20190816-164735-1774466974671.jpg b/public/images/team/20190816-164735-1774466974671.jpg deleted file mode 100644 index d63f3a9..0000000 Binary files a/public/images/team/20190816-164735-1774466974671.jpg and /dev/null differ diff --git a/public/images/team/20190816-164735-1774466997272.jpg b/public/images/team/20190816-164735-1774466997272.jpg deleted file mode 100644 index d63f3a9..0000000 Binary files a/public/images/team/20190816-164735-1774466997272.jpg and /dev/null differ diff --git a/public/images/team/20190816-164735-1774467131281.jpg b/public/images/team/20190816-164735-1774467131281.jpg deleted file mode 100644 index d63f3a9..0000000 Binary files a/public/images/team/20190816-164735-1774467131281.jpg and /dev/null differ diff --git a/public/images/team/20190816-164735-1774467278915.jpg b/public/images/team/20190816-164735-1774467278915.jpg deleted file mode 100644 index d63f3a9..0000000 Binary files a/public/images/team/20190816-164735-1774467278915.jpg and /dev/null differ diff --git a/public/images/team/20190816-164735-1774467770193.jpg b/public/images/team/20190816-164735-1774467770193.jpg deleted file mode 100644 index d63f3a9..0000000 Binary files a/public/images/team/20190816-164735-1774467770193.jpg and /dev/null differ diff --git a/public/images/team/20190816-164735-1774467783564.jpg b/public/images/team/20190816-164735-1774467783564.jpg deleted file mode 100644 index d63f3a9..0000000 Binary files a/public/images/team/20190816-164735-1774467783564.jpg and /dev/null differ diff --git a/public/images/team/75398-original-1773399182323.jpg b/public/images/team/75398-original-1773399182323.jpg deleted file mode 100644 index b4c8131..0000000 Binary files a/public/images/team/75398-original-1773399182323.jpg and /dev/null differ diff --git a/public/images/team/75398-original-1773399182323.webp b/public/images/team/75398-original-1773399182323.webp deleted file mode 100644 index 1e0775a..0000000 Binary files a/public/images/team/75398-original-1773399182323.webp and /dev/null differ diff --git a/public/images/team/anastasia-chaley.webp b/public/images/team/anastasia-chaley.webp deleted file mode 100644 index d5049d0..0000000 Binary files a/public/images/team/anastasia-chaley.webp and /dev/null differ diff --git a/public/images/team/angel-1773234723454.PNG b/public/images/team/angel-1773234723454.PNG deleted file mode 100644 index 05af693..0000000 Binary files a/public/images/team/angel-1773234723454.PNG and /dev/null differ diff --git a/public/images/team/angel-1773234723454.webp b/public/images/team/angel-1773234723454.webp deleted file mode 100644 index 2950d5a..0000000 Binary files a/public/images/team/angel-1773234723454.webp and /dev/null differ diff --git a/public/images/team/angel-1773588817170.PNG b/public/images/team/angel-1773588817170.PNG deleted file mode 100644 index 05af693..0000000 Binary files a/public/images/team/angel-1773588817170.PNG and /dev/null differ diff --git a/public/images/team/angel-1773588817170.webp b/public/images/team/angel-1773588817170.webp deleted file mode 100644 index 2950d5a..0000000 Binary files a/public/images/team/angel-1773588817170.webp and /dev/null differ diff --git a/public/images/team/anna-taryba.webp b/public/images/team/anna-taryba.webp deleted file mode 100644 index 280f0f4..0000000 Binary files a/public/images/team/anna-taryba.webp and /dev/null differ diff --git a/public/images/team/elena-chigileychik.webp b/public/images/team/elena-chigileychik.webp deleted file mode 100644 index cba3ae5..0000000 Binary files a/public/images/team/elena-chigileychik.webp and /dev/null differ diff --git a/public/images/team/elena-tarasevic.webp b/public/images/team/elena-tarasevic.webp deleted file mode 100644 index c145611..0000000 Binary files a/public/images/team/elena-tarasevic.webp and /dev/null differ diff --git a/public/images/team/galina-savitskaya.webp b/public/images/team/galina-savitskaya.webp deleted file mode 100644 index d2c00ca..0000000 Binary files a/public/images/team/galina-savitskaya.webp and /dev/null differ diff --git a/public/images/team/irina-karpus.webp b/public/images/team/irina-karpus.webp deleted file mode 100644 index 88c8960..0000000 Binary files a/public/images/team/irina-karpus.webp and /dev/null differ diff --git a/public/images/team/irina-tretyukovich.webp b/public/images/team/irina-tretyukovich.webp deleted file mode 100644 index bce29f3..0000000 Binary files a/public/images/team/irina-tretyukovich.webp and /dev/null differ diff --git a/public/images/team/kristina-voytovich.webp b/public/images/team/kristina-voytovich.webp deleted file mode 100644 index ccc575c..0000000 Binary files a/public/images/team/kristina-voytovich.webp and /dev/null differ diff --git a/public/images/team/nadezhda-sukh.webp b/public/images/team/nadezhda-sukh.webp deleted file mode 100644 index a16b1ac..0000000 Binary files a/public/images/team/nadezhda-sukh.webp and /dev/null differ diff --git a/public/images/team/olga-demidova.webp b/public/images/team/olga-demidova.webp deleted file mode 100644 index 1505e23..0000000 Binary files a/public/images/team/olga-demidova.webp and /dev/null differ diff --git a/public/images/team/olga-grabovets.webp b/public/images/team/olga-grabovets.webp deleted file mode 100644 index 883d3e1..0000000 Binary files a/public/images/team/olga-grabovets.webp and /dev/null differ diff --git a/public/images/team/photo-2025-06-28-23-11-20-1773234496259.jpg b/public/images/team/photo-2025-06-28-23-11-20-1773234496259.jpg deleted file mode 100644 index 15ad8ff..0000000 Binary files a/public/images/team/photo-2025-06-28-23-11-20-1773234496259.jpg and /dev/null differ diff --git a/public/images/team/photo-2025-06-28-23-11-20-1773234496259.webp b/public/images/team/photo-2025-06-28-23-11-20-1773234496259.webp deleted file mode 100644 index 22f5e94..0000000 Binary files a/public/images/team/photo-2025-06-28-23-11-20-1773234496259.webp and /dev/null differ diff --git a/public/images/team/saveclip-app-605404066-17852939781600031-474959415-1774467916236.jpg b/public/images/team/saveclip-app-605404066-17852939781600031-474959415-1774467916236.jpg deleted file mode 100644 index 2a5d46f..0000000 Binary files a/public/images/team/saveclip-app-605404066-17852939781600031-474959415-1774467916236.jpg and /dev/null differ diff --git a/public/images/team/saveclip-app-605404066-17852939781600031-474959415-1774467928377.jpg b/public/images/team/saveclip-app-605404066-17852939781600031-474959415-1774467928377.jpg deleted file mode 100644 index 2a5d46f..0000000 Binary files a/public/images/team/saveclip-app-605404066-17852939781600031-474959415-1774467928377.jpg and /dev/null differ diff --git a/public/images/team/saveclip-app-605404066-17852939781600031-474959415-1774468027961.jpg b/public/images/team/saveclip-app-605404066-17852939781600031-474959415-1774468027961.jpg deleted file mode 100644 index 2a5d46f..0000000 Binary files a/public/images/team/saveclip-app-605404066-17852939781600031-474959415-1774468027961.jpg and /dev/null differ diff --git a/public/images/team/viktor-artyomov.webp b/public/images/team/viktor-artyomov.webp deleted file mode 100644 index 2989d5a..0000000 Binary files a/public/images/team/viktor-artyomov.webp and /dev/null differ diff --git a/public/images/team/yuliya-kniga.webp b/public/images/team/yuliya-kniga.webp deleted file mode 100644 index 31c11c1..0000000 Binary files a/public/images/team/yuliya-kniga.webp and /dev/null differ diff --git a/public/video/angel-dance-1774809610253.mp4 b/public/video/angel-dance-1774809610253.mp4 new file mode 100644 index 0000000..00c3377 Binary files /dev/null and b/public/video/angel-dance-1774809610253.mp4 differ diff --git a/public/video/ira.mp4 b/public/video/ira-1774809667083.mp4 similarity index 100% rename from public/video/ira.mp4 rename to public/video/ira-1774809667083.mp4 diff --git a/public/video/nadezda.mp4 b/public/video/nadezda.mp4 deleted file mode 100644 index 84f92d6..0000000 Binary files a/public/video/nadezda.mp4 and /dev/null differ diff --git a/public/video/nastya.mp4 b/public/video/nastya-1774811612332.mp4 similarity index 100% rename from public/video/nastya.mp4 rename to public/video/nastya-1774811612332.mp4 diff --git a/public/video/nastya-2.mp4 b/public/video/nastya-2.mp4 deleted file mode 100644 index cf0e4ce..0000000 Binary files a/public/video/nastya-2.mp4 and /dev/null differ diff --git a/src/app/admin/hero/page.tsx b/src/app/admin/hero/page.tsx index 556fea5..f2df523 100644 --- a/src/app/admin/hero/page.tsx +++ b/src/app/admin/hero/page.tsx @@ -6,7 +6,7 @@ import { InputField } from "../_components/FormField"; import { adminFetch } from "@/lib/csrf"; import { Upload, X, Loader2, Smartphone, Monitor, Star } from "lucide-react"; -const MAX_VIDEO_SIZE_MB = 8; +const MAX_VIDEO_SIZE_MB = 10; const MAX_VIDEO_SIZE_BYTES = MAX_VIDEO_SIZE_MB * 1024 * 1024; function formatFileSize(bytes: number): string { @@ -209,10 +209,8 @@ function VideoManager({ const syncToParent = useCallback( (updated: (string | null)[]) => { setSlots(updated); - // Only propagate when all 3 are filled - if (updated.every((s) => s !== null)) { - onChange(updated as string[]); - } + // Save all 3 slots (empty string for unfilled) to preserve positions + onChange(updated.map((s) => s || "")); }, [onChange] ); @@ -246,10 +244,10 @@ function VideoManager({ async function handleUpload(idx: number, file: File) { if (file.size > MAX_VIDEO_SIZE_BYTES) { const sizeMb = (file.size / (1024 * 1024)).toFixed(1); - setSizeWarning(`Видео ${sizeMb} МБ — рекомендуем до ${MAX_VIDEO_SIZE_MB} МБ для быстрой загрузки`); - } else { - setSizeWarning(null); + alert(`Видео ${sizeMb} МБ — максимум ${MAX_VIDEO_SIZE_MB} МБ. Сожмите видео и попробуйте снова.`); + return; } + setSizeWarning(null); setUploadingIdx(idx); try { const form = new FormData(); @@ -260,14 +258,21 @@ function VideoManager({ body: form, }); if (!res.ok) { - const err = await res.json(); - alert(err.error || "Ошибка загрузки"); + const text = await res.text(); + let msg = "Ошибка загрузки"; + try { + const err = JSON.parse(text); + msg = err.error || msg; + } catch { /* empty response */ } + alert(`${msg} (${res.status})`); return; } const { path } = await res.json(); const updated = [...slots]; updated[idx] = path; syncToParent(updated); + } catch (e) { + alert(`Ошибка сети: ${e instanceof Error ? e.message : "попробуйте снова"}`); } finally { setUploadingIdx(null); } @@ -276,8 +281,7 @@ function VideoManager({ function handleRemove(idx: number) { const updated = [...slots]; updated[idx] = null; - setSlots(updated); - // Don't propagate incomplete state — keep old saved videos in DB + syncToParent(updated); } const allFilled = slots.every((s) => s !== null); @@ -351,17 +355,17 @@ export default function HeroEditorPage() { update({ ...data, headline: v })} /> update({ ...data, subheadline: v })} /> update({ ...data, ctaText: v })} /> > diff --git a/src/app/api/admin/sections/[key]/route.ts b/src/app/api/admin/sections/[key]/route.ts index 75956a5..2bd8832 100644 --- a/src/app/api/admin/sections/[key]/route.ts +++ b/src/app/api/admin/sections/[key]/route.ts @@ -1,6 +1,5 @@ import { NextRequest, NextResponse } from "next/server"; import { getSection, setSection, SECTION_KEYS } from "@/lib/db"; -import { siteContent } from "@/data/content"; import { revalidatePath } from "next/cache"; import { invalidateContentCache } from "@/lib/content"; @@ -12,16 +11,10 @@ export async function GET(_request: NextRequest, { params }: Params) { return NextResponse.json({ error: "Invalid section key" }, { status: 400 }); } - let data = getSection(key); + const data = getSection(key); if (!data) { - // Auto-seed from fallback content if section doesn't exist yet - const fallback = (siteContent as unknown as Record)[key]; - if (fallback) { - setSection(key, fallback); - data = fallback; - } else { - return NextResponse.json({ error: "Section not found" }, { status: 404 }); - } + // Return empty object so admin editor can initialize fields + return NextResponse.json({}); } return NextResponse.json(data, { diff --git a/src/app/api/admin/upload/route.ts b/src/app/api/admin/upload/route.ts index bf8721c..3a75954 100644 --- a/src/app/api/admin/upload/route.ts +++ b/src/app/api/admin/upload/route.ts @@ -10,10 +10,19 @@ const IMAGE_FOLDERS = ["team", "master-classes", "news", "classes"]; const VIDEO_FOLDERS = ["hero"]; const ALL_FOLDERS = [...IMAGE_FOLDERS, ...VIDEO_FOLDERS]; const IMAGE_MAX_SIZE = 5 * 1024 * 1024; // 5MB -const VIDEO_MAX_SIZE = 50 * 1024 * 1024; // 50MB +const VIDEO_MAX_SIZE = 10 * 1024 * 1024; // 10MB export async function POST(request: NextRequest) { - const formData = await request.formData(); + let formData: FormData; + try { + formData = await request.formData(); + } catch (e) { + const msg = e instanceof Error ? e.message : "Upload failed"; + return NextResponse.json( + { error: msg.includes("size") || msg.includes("multipart") ? "Файл слишком большой (макс. 10 МБ)" : `Ошибка загрузки: ${msg}` }, + { status: 413 } + ); + } const file = formData.get("file") as File | null; const rawFolder = (formData.get("folder") as string) || "team"; const folder = ALL_FOLDERS.includes(rawFolder) ? rawFolder : "team"; @@ -26,16 +35,16 @@ export async function POST(request: NextRequest) { const allowedTypes = isVideoFolder ? VIDEO_TYPES : IMAGE_TYPES; if (!allowedTypes.includes(file.type)) { const msg = isVideoFolder - ? "Only MP4 and WebM videos are allowed" - : "Only JPEG, PNG, WebP, and AVIF are allowed"; + ? "Допустимы только MP4 и WebM" + : "Допустимы только JPEG, PNG, WebP и AVIF"; return NextResponse.json({ error: msg }, { status: 400 }); } const maxSize = isVideoFolder ? VIDEO_MAX_SIZE : IMAGE_MAX_SIZE; if (file.size > maxSize) { - const label = isVideoFolder ? "50MB" : "5MB"; + const label = isVideoFolder ? "10 МБ" : "5 МБ"; return NextResponse.json( - { error: `File too large (max ${label})` }, + { error: `Файл слишком большой (макс. ${label})` }, { status: 400 } ); } @@ -45,7 +54,7 @@ export async function POST(request: NextRequest) { const allowedExts = isVideoFolder ? VIDEO_EXTENSIONS : IMAGE_EXTENSIONS; if (!allowedExts.includes(ext)) { return NextResponse.json( - { error: "Invalid file extension" }, + { error: "Недопустимое расширение файла" }, { status: 400 } ); } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 00f7903..b72135a 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -22,13 +22,15 @@ const oswald = localFont({ }); export function generateMetadata(): Metadata { - const { meta } = getContent(); + const content = getContent(); + const title = content?.meta?.title || "BLACK HEART DANCE HOUSE"; + const description = content?.meta?.description || ""; return { - title: meta.title, - description: meta.description, + title, + description, openGraph: { - title: meta.title, - description: meta.description, + title, + description, locale: "ru_RU", type: "website", }, diff --git a/src/app/page.tsx b/src/app/page.tsx index c880aa3..1f69b84 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -33,24 +33,26 @@ export default function HomePage() { - - - - - {openDayData && } - - - - - - + {content?.hero && } + {content?.about && ( + + )} + {content?.classes && } + {content?.team && } + {openDayData && content?.popups && } + {content?.schedule && } + {content?.pricing && } + {content?.masterClasses && } + {content?.news && } + {content?.faq && } + {content?.contact && } diff --git a/src/components/sections/Hero.tsx b/src/components/sections/Hero.tsx index 7eafd71..dfaa441 100644 --- a/src/components/sections/Hero.tsx +++ b/src/components/sections/Hero.tsx @@ -20,9 +20,10 @@ export function Hero({ data: hero }: HeroProps) { const overlayRef = useRef(null); const readyCount = useRef(0); const [mounted, setMounted] = useState(false); - const videos = hero.videos?.length ? hero.videos : DEFAULT_VIDEOS; - const centerVideo = videos[Math.floor(videos.length / 2)] || videos[0]; - const totalVideos = videos.slice(0, 3).length + 1; // desktop (3) + mobile (1) + const hasVideos = hero.videos?.some(Boolean); + const videos = hasVideos ? hero.videos! : DEFAULT_VIDEOS; + const centerVideo = videos[1] || videos[0]; + const totalVideos = videos.slice(0, 3).filter(Boolean).length + 1; // desktop (filled) + mobile (1) const prefersReducedMotion = useRef(false); @@ -106,6 +107,7 @@ export function Hero({ data: hero }: HeroProps) { {/* Desktop: diagonal split with all videos */} {videos.slice(0, 3).map((src, i) => { + if (!src) return null; const positions = [ { left: "0%", width: "38%" }, { left: "31%", width: "38%" }, @@ -118,7 +120,7 @@ export function Hero({ data: hero }: HeroProps) { ]; return (