From 8a6f09b564d5d2f02d0a2605f6b52070a910aaa3 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Mon, 25 Apr 2022 12:57:12 +0200 Subject: chore: add a PageLayout component --- src/components/templates/page/page-layout.tsx | 166 ++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 src/components/templates/page/page-layout.tsx (limited to 'src/components/templates/page/page-layout.tsx') diff --git a/src/components/templates/page/page-layout.tsx b/src/components/templates/page/page-layout.tsx new file mode 100644 index 0000000..24c4e50 --- /dev/null +++ b/src/components/templates/page/page-layout.tsx @@ -0,0 +1,166 @@ +import Heading from '@components/atoms/headings/heading'; +import Sidebar from '@components/atoms/layout/sidebar'; +import PageFooter, { + type PageFooterProps, +} from '@components/molecules/layout/page-footer'; +import PageHeader, { + type PageHeaderProps, +} from '@components/molecules/layout/page-header'; +import Breadcrumb, { + type BreadcrumbItem, +} from '@components/molecules/nav/breadcrumb'; +import CommentForm from '@components/organisms/forms/comment-form'; +import CommentsList, { + type CommentsListProps, +} from '@components/organisms/layout/comments-list'; +import TableOfContents from '@components/organisms/widgets/table-of-contents'; +import useIsMounted from '@utils/hooks/use-is-mounted'; +import { FC, ReactNode, useRef } from 'react'; +import { useIntl } from 'react-intl'; +import Layout, { LayoutProps } from '../layout/layout'; +import styles from './page-layout.module.scss'; + +export type PageLayoutProps = { + /** + * True if the page accepts new comments. Default: false. + */ + allowComments?: boolean; + /** + * The breadcrumb items. + */ + breadcrumb: BreadcrumbItem[]; + /** + * The main content of the page. + */ + children: ReactNode; + /** + * The page comments + */ + comments?: CommentsListProps['comments']; + /** + * The footer metadata. + */ + footerMeta?: PageFooterProps['meta']; + /** + * The header metadata. + */ + headerMeta?: PageHeaderProps['meta']; + /** + * The page introduction. + */ + intro?: PageHeaderProps['intro']; + /** + * True if it is homepage. Default: false. + */ + isHome?: LayoutProps['isHome']; + /** + * The page title. + */ + title: PageHeaderProps['title']; + /** + * An array of widgets to put in the last sidebar. + */ + widgets?: ReactNode[]; + /** + * Show the table of contents. Default: false. + */ + withToC?: boolean; +}; + +/** + * PageLayout component + * + * Render the pages layout. + */ +const PageLayout: FC = ({ + children, + allowComments = false, + breadcrumb, + comments, + footerMeta, + headerMeta, + intro, + isHome = false, + widgets, + title, + withToC = false, +}) => { + const intl = useIntl(); + const commentsTitle = intl.formatMessage({ + defaultMessage: 'Comments', + description: 'PageLayout: comments title', + id: '+dJU3e', + }); + const commentFormTitle = intl.formatMessage({ + defaultMessage: 'Leave a comment', + description: 'PageLayout: comment form title', + id: 'kzIYoQ', + }); + + const bodyRef = useRef(null); + const isMounted = useIsMounted(bodyRef); + + const hasComments = Array.isArray(comments) && comments.length > 0; + const hasCommentsSection = hasComments || allowComments; + const articleModifier = hasCommentsSection + ? 'article--has-comments' + : 'article--no-comments'; + + const saveComment = () => { + return null; + }; + + return ( + + + + {withToC && ( + + {isMounted && bodyRef.current && ( + + )} + + )} +
+ {children} +
+ + + {widgets} + + {hasCommentsSection && ( +
+ {hasComments && ( +
+ {commentsTitle} + +
+ )} + {allowComments && ( +
+ +
+ )} +
+ )} +
+ ); +}; + +export default PageLayout; -- cgit v1.2.3