1 parent
0c8d74b21d
commit
a1e51e78f0
23 files changed
+522
-516
No files matched your search
@@ -1,12 +1,15 @@
|
||||
"use client"
|
||||
|
||||
import s from "./app.module.css"
|
||||
|
||||
import { useContext } from "react"
|
||||
import { Wrapper } from "../Wrapper"
|
||||
import { MenuContext } from "@/context/MenuContext"
|
||||
import { Footer } from "../Footer"
|
||||
import { Content } from "../Content"
|
||||
import { Breadcrumbs } from "../Breadcrumbs"
|
||||
import type { BreadcrumbPart, MenuItem } from "@/types"
|
||||
import { useRouter } from "next/router"
|
||||
import type { BreadcrumbPart } from "@/types"
|
||||
import { usePathname } from "next/navigation"
|
||||
import { useMobile } from "@/hooks/useMobile"
|
||||
import { Navigation } from "@/components/Navigation"
|
||||
import { Box } from "@/ui/Box"
|
||||
@@ -24,7 +27,7 @@ import Link from "next/link"
|
||||
import AccessibilityPanel from "../AccessibilityPanel"
|
||||
import useAccessibility from "@/hooks/useAccessibility"
|
||||
|
||||
const Gosuslugi = dynamic(import("../Gosuslugi").then(module => module.Gosuslugi), {
|
||||
const Gosuslugi = dynamic(() => import("../Gosuslugi").then(module => ({ default: module.Gosuslugi })), {
|
||||
ssr: false,
|
||||
})
|
||||
|
||||
@@ -32,103 +35,101 @@ export type AppProps = {
|
||||
showAuthor?: boolean
|
||||
contentStyle?: React.CSSProperties
|
||||
breadcrumbs?: BreadcrumbPart[]
|
||||
menu: MenuItem[]
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
export function App({ showAuthor = false, menu, ...props }: AppProps) {
|
||||
export function App({ showAuthor = false, ...props }: AppProps) {
|
||||
const hideBreadcrumbs = useMobile()
|
||||
const accessibility = useAccessibility()
|
||||
const router = useRouter()
|
||||
const pathname = usePathname()
|
||||
const menu = useContext(MenuContext)
|
||||
|
||||
return (
|
||||
<MenuContext.Provider value={menu}>
|
||||
<Wrapper
|
||||
header={(
|
||||
<header>
|
||||
{!accessibility ? null : (
|
||||
<AccessibilityPanel/>
|
||||
)}
|
||||
<Wrapper
|
||||
header={(
|
||||
<header>
|
||||
{!accessibility ? null : (
|
||||
<AccessibilityPanel/>
|
||||
)}
|
||||
|
||||
<div className={s.navigation}>
|
||||
<Navigation />
|
||||
</div>
|
||||
{hideBreadcrumbs || !props.breadcrumbs ? null : (
|
||||
<Box center>
|
||||
<Content>
|
||||
<Breadcrumbs
|
||||
items={props.breadcrumbs}
|
||||
path={router.asPath}
|
||||
/>
|
||||
</Content>
|
||||
</Box>
|
||||
)}
|
||||
</header>
|
||||
)}
|
||||
footer={(
|
||||
<Footer>
|
||||
<Box wrap gap={40} align={false} className={s.footerLinks}>
|
||||
<Panel ghost>
|
||||
<Contacts />
|
||||
</Panel>
|
||||
|
||||
<Panel ghost className={s.footerPanel}>
|
||||
<Title level={3}>
|
||||
Версия для слабовидящих
|
||||
</Title>
|
||||
<AccessibilityButton />
|
||||
</Panel>
|
||||
|
||||
<Panel ghost className={s.footerPanel}>
|
||||
<Title level={3}>
|
||||
Анкеты
|
||||
</Title>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<Link href={"https://bus.gov.ru/qrcode/rate/351942"}>
|
||||
Независимая оценка качества оказания услуг
|
||||
</Link>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<Link href={"https://forms.mkrf.ru/e/2579/xTPLeBU7/?ap_orgcode=600340071"}>
|
||||
Анкета Министерства культуры РФ
|
||||
</Link>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<Link href={"https://forms.yandex.ru/u/68ef8e9c90fa7b0bacf46e9d/"}>
|
||||
Анкета получателей образовательных услуг ДОП Кировского муниципального района Ленинградской области 2025
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</Panel>
|
||||
<div className={s.navigation}>
|
||||
<Navigation />
|
||||
</div>
|
||||
{hideBreadcrumbs || !props.breadcrumbs ? null : (
|
||||
<Box center>
|
||||
<Content>
|
||||
<Breadcrumbs
|
||||
items={props.breadcrumbs}
|
||||
path={pathname}
|
||||
/>
|
||||
</Content>
|
||||
</Box>
|
||||
)}
|
||||
</header>
|
||||
)}
|
||||
footer={(
|
||||
<Footer>
|
||||
<Box wrap gap={40} align={false} className={s.footerLinks}>
|
||||
<Panel ghost>
|
||||
<Contacts />
|
||||
</Panel>
|
||||
|
||||
<div className={s.gosuslugi}>
|
||||
<Gosuslugi />
|
||||
</div>
|
||||
<Panel ghost className={s.footerPanel}>
|
||||
<Title level={3}>
|
||||
Версия для слабовидящих
|
||||
</Title>
|
||||
<AccessibilityButton />
|
||||
</Panel>
|
||||
|
||||
<Box>
|
||||
<Copyright years={yearRange} />
|
||||
<Panel ghost className={s.footerPanel}>
|
||||
<Title level={3}>
|
||||
Анкеты
|
||||
</Title>
|
||||
|
||||
{!showAuthor ? null : (
|
||||
<>
|
||||
<Spacer as={"span"} />
|
||||
<Author />
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
</Footer>
|
||||
)}
|
||||
>
|
||||
<Box center>
|
||||
<Content style={props.contentStyle}>
|
||||
{props.children}
|
||||
</Content>
|
||||
</Box>
|
||||
</Wrapper>
|
||||
</MenuContext.Provider>
|
||||
<ul>
|
||||
<li>
|
||||
<Link href={"https://bus.gov.ru/qrcode/rate/351942"}>
|
||||
Независимая оценка качества оказания услуг
|
||||
</Link>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<Link href={"https://forms.mkrf.ru/e/2579/xTPLeBU7/?ap_orgcode=600340071"}>
|
||||
Анкета Министерства культуры РФ
|
||||
</Link>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<Link href={"https://forms.yandex.ru/u/68ef8e9c90fa7b0bacf46e9d/"}>
|
||||
Анкета получателей образовательных услуг ДОП Кировского муниципального района Ленинградской области 2025
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</Panel>
|
||||
</Box>
|
||||
|
||||
<div className={s.gosuslugi}>
|
||||
<Gosuslugi />
|
||||
</div>
|
||||
|
||||
<Box>
|
||||
<Copyright years={yearRange} />
|
||||
|
||||
{!showAuthor ? null : (
|
||||
<>
|
||||
<Spacer as={"span"} />
|
||||
<Author />
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
</Footer>
|
||||
)}
|
||||
>
|
||||
<Box center>
|
||||
<Content style={props.contentStyle}>
|
||||
{props.children}
|
||||
</Content>
|
||||
</Box>
|
||||
</Wrapper>
|
||||
)
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import { getResizedUrl } from "@/lib/image"
|
||||
import Link from "next/link"
|
||||
import { Box } from "@/ui/Box"
|
||||
|
||||
const Signature = dynamic(import("./Signature").then(m => m.Signature), {
|
||||
const Signature = dynamic(() => import("./Signature").then(m => ({ default: m.Signature })), {
|
||||
ssr: false,
|
||||
})
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
"use client"
|
||||
|
||||
import { HudozkaTitle } from "@/components/HudozkaTitle"
|
||||
import { PageGrid } from "@/components/PageGrid"
|
||||
import { useMobile } from "@/hooks/useMobile"
|
||||
import type { PageCardDto } from "@/types"
|
||||
|
||||
export type HomeContentProps = {
|
||||
items: PageCardDto[]
|
||||
}
|
||||
|
||||
export function HomeContent({ items }: HomeContentProps) {
|
||||
const mobile = useMobile()
|
||||
|
||||
return (
|
||||
<>
|
||||
{mobile ? null : (
|
||||
<HudozkaTitle
|
||||
style={{
|
||||
marginTop: "var(--size-m)",
|
||||
marginBottom: "var(--size-m)",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
<PageGrid items={items} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
"use client"
|
||||
|
||||
import s from "./styles.module.css"
|
||||
|
||||
import type { MenuItem } from "@/types"
|
||||
import * as NavigationMenu from "@radix-ui/react-navigation-menu"
|
||||
import classnames from "classnames/bind"
|
||||
import { useRouter } from "next/router"
|
||||
import { usePathname } from "next/navigation"
|
||||
import { ActiveLink } from "./ActiveLink"
|
||||
|
||||
let cx = classnames.bind(s)
|
||||
@@ -15,13 +17,13 @@ export type MenuProps = {
|
||||
}
|
||||
|
||||
export const Menu: React.FC<MenuProps> = ({ vertical = false, onItemClick, items }) => {
|
||||
const router = useRouter()
|
||||
const pathname = usePathname()
|
||||
return (
|
||||
<NavigationMenu.Root>
|
||||
<NavigationMenu.List className={cx(s.menu, { vertical })}>
|
||||
{
|
||||
items.map(item => {
|
||||
const current = router.asPath === item.href
|
||||
const current = pathname === item.href
|
||||
const href = current
|
||||
? undefined
|
||||
: item.href
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
"use client"
|
||||
|
||||
import s from "./nav.module.css"
|
||||
|
||||
import { Menu } from "../Menu"
|
||||
@@ -8,7 +10,7 @@ import { Spacer } from "../Spacer"
|
||||
import HudozkaLogo from "../HudozkaLogo"
|
||||
import { HudozkaTitle } from "../HudozkaTitle"
|
||||
import Link from "next/link"
|
||||
import { useRouter } from "next/router"
|
||||
import { usePathname } from "next/navigation"
|
||||
import { HiOutlineMenuAlt4, HiOutlineX } from "react-icons/hi"
|
||||
|
||||
export type MobileNavigationProps = {
|
||||
@@ -19,7 +21,7 @@ export type MobileNavigationProps = {
|
||||
export function MobileNavigation({ className, style }: MobileNavigationProps) {
|
||||
const menu = useContext(MenuContext)
|
||||
const detailsRef = useRef<HTMLDetailsElement>(null)
|
||||
const router = useRouter()
|
||||
const pathname = usePathname()
|
||||
|
||||
const close = useCallback(() => {
|
||||
if (detailsRef.current) {
|
||||
@@ -28,11 +30,8 @@ export function MobileNavigation({ className, style }: MobileNavigationProps) {
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
router.events.on("routeChangeStart", close)
|
||||
return () => {
|
||||
router.events.off("routeChangeStart", close)
|
||||
}
|
||||
}, [router.events, close])
|
||||
close()
|
||||
}, [pathname, close])
|
||||
|
||||
return (
|
||||
<nav className={className}>
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
"use client"
|
||||
|
||||
import { Page } from "@/components/Page"
|
||||
import { Html } from "@/components/Html"
|
||||
import { Youtube } from "@/components/Youtube"
|
||||
import { Picture } from "@/ui/Picture"
|
||||
import { FileCard } from "@/components/FileCard"
|
||||
import { PageGrid } from "@/components/PageGrid"
|
||||
import type { Tag, Token, Sign } from "@/types"
|
||||
|
||||
export type PageContentProps = {
|
||||
tags: Tag[]
|
||||
date?: string
|
||||
tokens: Token[]
|
||||
documentSignature: Sign
|
||||
}
|
||||
|
||||
export function PageContent({ tags, date, tokens, documentSignature }: PageContentProps) {
|
||||
return (
|
||||
<Page
|
||||
tags={tags}
|
||||
date={date ? new Date(date) : undefined}
|
||||
>
|
||||
<article className={"article"}>
|
||||
{tokens.map((x, i) => {
|
||||
switch (x.token) {
|
||||
case "html":
|
||||
return (
|
||||
<Html
|
||||
key={i}
|
||||
html={x.data}
|
||||
/>
|
||||
)
|
||||
|
||||
case "instagram":
|
||||
return (
|
||||
<Html
|
||||
key={i}
|
||||
html={x.data.embed}
|
||||
/>
|
||||
)
|
||||
|
||||
case "youtube":
|
||||
return (
|
||||
<Youtube
|
||||
key={i}
|
||||
url={x.data.url}
|
||||
/>
|
||||
)
|
||||
|
||||
case "image":
|
||||
return (
|
||||
<Picture
|
||||
key={i}
|
||||
src={x.data.src}
|
||||
alt={x.data.alt}
|
||||
width={x.data.width}
|
||||
height={x.data.height}
|
||||
caption={x.data.caption}
|
||||
blur={x.data.blur}
|
||||
wide={x.wide}
|
||||
/>
|
||||
)
|
||||
|
||||
case "file":
|
||||
return (
|
||||
<FileCard
|
||||
key={i}
|
||||
sign={documentSignature}
|
||||
{...x.data}
|
||||
/>
|
||||
)
|
||||
|
||||
case "grid":
|
||||
return (
|
||||
<PageGrid
|
||||
key={i}
|
||||
items={x.data.items}
|
||||
/>
|
||||
)
|
||||
|
||||
default:
|
||||
return (
|
||||
<pre key={i}>
|
||||
{JSON.stringify(x)}
|
||||
</pre>
|
||||
)
|
||||
}
|
||||
})}
|
||||
</article>
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
"use client"
|
||||
|
||||
import { MenuContext } from "@/context/MenuContext"
|
||||
import type { MenuItem } from "@/types"
|
||||
|
||||
export type ProvidersProps = {
|
||||
menu: MenuItem[]
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export function Providers({ menu, children }: ProvidersProps) {
|
||||
return (
|
||||
<MenuContext.Provider value={menu}>
|
||||
{children}
|
||||
</MenuContext.Provider>
|
||||
)
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
"use client"
|
||||
|
||||
import s from "./wrapper.module.css"
|
||||
|
||||
import cx from "classnames"
|
||||
|
||||
Reference in new issue
Block a user