new-marketplace

Форк
0
/
layout.tsx 
143 строки · 5.2 Кб
1
/* eslint-disable react-hooks/exhaustive-deps */
2
'use client';
3

4
import { useRouter } from 'next/navigation';
5
import { useEventListener, useMountEffect, useUnmountEffect } from 'primereact/hooks';
6
import React, { useContext, useEffect, useRef } from 'react';
7
import { classNames } from 'primereact/utils';
8
import AppFooter from './AppFooter';
9
import AppSidebar from './AppSidebar';
10
import AppTopbar from './AppTopbar';
11
import AppConfig from './AppConfig';
12
import { LayoutContext } from './context/layoutcontext';
13
import { PrimeReactContext } from 'primereact/api';
14
import { ChildContainerProps, LayoutState, AppTopbarRef } from '@/types';
15
import { usePathname, useSearchParams } from 'next/navigation';
16

17
const Layout = ({ children }: ChildContainerProps) => {
18
    const { layoutConfig, layoutState, setLayoutState } = useContext(LayoutContext);
19
    const { setRipple } = useContext(PrimeReactContext);
20
    const topbarRef = useRef<AppTopbarRef>(null);
21
    const sidebarRef = useRef<HTMLDivElement>(null);
22
    const [bindMenuOutsideClickListener, unbindMenuOutsideClickListener] = useEventListener({
23
        type: 'click',
24
        listener: (event) => {
25
            const isOutsideClicked = !(
26
                sidebarRef.current?.isSameNode(event.target as Node) ||
27
                sidebarRef.current?.contains(event.target as Node) ||
28
                topbarRef.current?.menubutton?.isSameNode(event.target as Node) ||
29
                topbarRef.current?.menubutton?.contains(event.target as Node)
30
            );
31

32
            if (isOutsideClicked) {
33
                hideMenu();
34
            }
35
        }
36
    });
37

38
    const pathname = usePathname();
39
    const searchParams = useSearchParams();
40
    useEffect(() => {
41
        hideMenu();
42
        hideProfileMenu();
43
    }, [pathname, searchParams]);
44

45
    const [bindProfileMenuOutsideClickListener, unbindProfileMenuOutsideClickListener] = useEventListener({
46
        type: 'click',
47
        listener: (event) => {
48
            const isOutsideClicked = !(
49
                topbarRef.current?.topbarmenu?.isSameNode(event.target as Node) ||
50
                topbarRef.current?.topbarmenu?.contains(event.target as Node) ||
51
                topbarRef.current?.topbarmenubutton?.isSameNode(event.target as Node) ||
52
                topbarRef.current?.topbarmenubutton?.contains(event.target as Node)
53
            );
54

55
            if (isOutsideClicked) {
56
                hideProfileMenu();
57
            }
58
        }
59
    });
60

61
    const hideMenu = () => {
62
        setLayoutState((prevLayoutState: LayoutState) => ({
63
            ...prevLayoutState,
64
            overlayMenuActive: false,
65
            staticMenuMobileActive: false,
66
            menuHoverActive: false
67
        }));
68
        unbindMenuOutsideClickListener();
69
        unblockBodyScroll();
70
    };
71

72
    const hideProfileMenu = () => {
73
        setLayoutState((prevLayoutState: LayoutState) => ({
74
            ...prevLayoutState,
75
            profileSidebarVisible: false
76
        }));
77
        unbindProfileMenuOutsideClickListener();
78
    };
79

80
    const blockBodyScroll = (): void => {
81
        if (document.body.classList) {
82
            document.body.classList.add('blocked-scroll');
83
        } else {
84
            document.body.className += ' blocked-scroll';
85
        }
86
    };
87

88
    const unblockBodyScroll = (): void => {
89
        if (document.body.classList) {
90
            document.body.classList.remove('blocked-scroll');
91
        } else {
92
            document.body.className = document.body.className.replace(new RegExp('(^|\\b)' + 'blocked-scroll'.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
93
        }
94
    };
95

96
    useEffect(() => {
97
        if (layoutState.overlayMenuActive || layoutState.staticMenuMobileActive) {
98
            bindMenuOutsideClickListener();
99
        }
100

101
        layoutState.staticMenuMobileActive && blockBodyScroll();
102
    }, [layoutState.overlayMenuActive, layoutState.staticMenuMobileActive]);
103

104
    useEffect(() => {
105
        if (layoutState.profileSidebarVisible) {
106
            bindProfileMenuOutsideClickListener();
107
        }
108
    }, [layoutState.profileSidebarVisible]);
109

110
    useUnmountEffect(() => {
111
        unbindMenuOutsideClickListener();
112
        unbindProfileMenuOutsideClickListener();
113
    });
114

115
    const containerClass = classNames('layout-wrapper', {
116
        'layout-overlay': layoutConfig.menuMode === 'overlay',
117
        'layout-static': layoutConfig.menuMode === 'static',
118
        'layout-static-inactive': layoutState.staticMenuDesktopInactive && layoutConfig.menuMode === 'static',
119
        'layout-overlay-active': layoutState.overlayMenuActive,
120
        'layout-mobile-active': layoutState.staticMenuMobileActive,
121
        'p-input-filled': layoutConfig.inputStyle === 'filled',
122
        'p-ripple-disabled': !layoutConfig.ripple
123
    });
124

125
    return (
126
        <React.Fragment>
127
            <div className={containerClass}>
128
                <AppTopbar ref={topbarRef} />
129
                <div ref={sidebarRef} className="layout-sidebar">
130
                    <AppSidebar />
131
                </div>
132
                <div className="layout-main-container">
133
                    <div className="layout-main">{children}</div>
134
                    <AppFooter />
135
                </div>
136
                <AppConfig />
137
                <div className="layout-mask"></div>
138
            </div>
139
        </React.Fragment>
140
    );
141
};
142

143
export default Layout;
144

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.