Files
notion-theme/gitbook/components/NavPostList.js

166 lines
4.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { siteConfig } from '@/lib/config'
import { useGlobal } from '@/lib/global'
import { useRouter } from 'next/router'
import { useEffect, useState } from 'react'
import CONFIG from '../config'
import BlogPostCard from './BlogPostCard'
import NavPostItem from './NavPostItem'
/**
* 部落格列表滾動分頁
* @param posts 所有文章
* @param tags 所有標籤
* @returns {JSX.Element}
* @constructor
*/
const NavPostList = props => {
const { filteredNavPages } = props
const { locale, currentSearch } = useGlobal()
const router = useRouter()
// 依分類將文章歸成資料夾
const categoryFolders = groupArticles(filteredNavPages)
// 存放被展開的群組
const [expandedGroups, setExpandedGroups] = useState([])
// 是否採用排他折疊,一次只展開一個資料夾
const GITBOOK_EXCLUSIVE_COLLAPSE = siteConfig(
'GITBOOK_EXCLUSIVE_COLLAPSE',
null,
CONFIG
)
useEffect(() => {
// 展開資料夾
setTimeout(() => {
const currentPath = decodeURIComponent(router.asPath.split('?')[0])
const defaultOpenIndex = getDefaultOpenIndexByPath(
categoryFolders,
currentPath
)
setExpandedGroups([defaultOpenIndex])
}, 500)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [router, filteredNavPages])
// 切換折疊項目,當陣列狀態改變時觸發
const toggleItem = index => {
let newExpandedGroups = [...expandedGroups] // 建立新的展開群組陣列
// 若 expandedGroups 中不存在則加入,存在則移除
if (expandedGroups.includes(index)) {
// 若 expandedGroups 中包含 index則移除
newExpandedGroups = newExpandedGroups.filter(
expandedIndex => expandedIndex !== index
)
} else {
// 若 expandedGroups 中不含 index則加入
newExpandedGroups.push(index)
}
// 是否排他
if (GITBOOK_EXCLUSIVE_COLLAPSE) {
// 若折疊選單為排他模式,僅保留目前群組其餘關閉
newExpandedGroups = newExpandedGroups.filter(
expandedIndex => expandedIndex === index
)
}
// 更新展開群組陣列
setExpandedGroups(newExpandedGroups)
}
// 無資料時
if (!categoryFolders || categoryFolders.length === 0) {
// 空白內容
return (
<div className='flex w-full items-center justify-center min-h-screen mx-auto md:-mt-20'>
<p className='text-gray-500 dark:text-gray-300'>
{locale.COMMON.NO_RESULTS_FOUND}{' '}
{currentSearch && <div>{currentSearch}</div>}
</p>
</div>
)
}
// 文章首頁對應路徑
const href = siteConfig('GITBOOK_INDEX_PAGE') + ''
const homePost = {
id: '-1',
title: siteConfig('DESCRIPTION'),
href: href.indexOf('/') !== 0 ? '/' + href : href
}
return (
<div
id='posts-wrapper'
className='w-full flex-grow space-y-0.5 pr-4 tracking-wider'>
{/* 當前文章 */}
<BlogPostCard className='mb-4' post={homePost} />
{/* 文章列表 */}
{categoryFolders?.map((group, index) => (
<NavPostItem
key={index}
group={group}
onHeightChange={props.onHeightChange}
expanded={expandedGroups.includes(index)} // 將展開狀態傳給子元件
toggleItem={() => toggleItem(index)} // 將切換函式傳給子元件
/>
))}
</div>
)
}
// 依分類將文章歸成資料夾
function groupArticles(filteredNavPages) {
if (!filteredNavPages) {
return []
}
const groups = []
const AUTO_SORT = siteConfig('GITBOOK_AUTO_SORT', true, CONFIG)
for (let i = 0; i < filteredNavPages.length; i++) {
const item = filteredNavPages[i]
const categoryName = item?.category ? item?.category : '' // 將 category 轉成字串
let existingGroup = null
// 啟用自動分組排序;會把相同分類歸到同一個資料夾,忽略 Notion 中的排序
if (AUTO_SORT) {
existingGroup = groups.find(group => group.category === categoryName) // 尋找同名的最後一個群組
} else {
existingGroup = groups[groups.length - 1] // 取得最後一個群組
}
// 新增資料
if (existingGroup && existingGroup.category === categoryName) {
existingGroup.items.push(item)
} else {
groups.push({ category: categoryName, items: [item] })
}
}
return groups
}
/**
* 查看當前路徑需要展開的選單索引
* 若皆不符合則回傳 0即預設展開第一個
* @param {*} categoryFolders
* @param {*} path
* @returns {number} 需展開的選單索引
*/
function getDefaultOpenIndexByPath(categoryFolders, path) {
// 找出符合條件的第一個索引
const index = categoryFolders.findIndex(group => {
return group.items.some(post => path === post.href)
})
// 若找到符合條件的索引則回傳
if (index !== -1) {
return index
}
return 0
}
export default NavPostList