iT邦幫忙

2022 iThome 鐵人賽

DAY 23
0

昨天我們把 Blog 部分結束
今天接著看 Program 的部分

Program 分為「探索課程頁」和「課程內頁」
我們今天一樣先從探索頁開始

ProgramCollectionPage

程式碼我們一樣先上

import { Button as ChakraButton, Icon, SkeletonText } from '@chakra-ui/react'
// ~中間略~

export const StyledButton = styled(ChakraButton)`
    // ~中間略~
`

const ProgramCollectionPage: React.VFC = () => {
  const { formatMessage } = useIntl()

  const [defaultActive] = useQueryParam('active', StringParam)
  const [queryTitle] = useQueryParam('title', StringParam)
  const [noSelector] = useQueryParam('noSelector', BooleanParam)
  const [noBanner] = useQueryParam('noBanner', BooleanParam)
  const [permitted] = useQueryParam('permitted', BooleanParam)

  const { settings } = useApp()
  const { pageTitle } = useNav()
  const { currentLocale } = useContext(LocaleContext)

  const { loadingPrograms, errorPrograms, programs } = usePublishedProgramCollection({
    isPrivate: permitted ? undefined : false,
    categoryId: defaultActive || undefined,
  })

  const [selectedCategoryId, setSelectedCategoryId] = useState<string | null>(defaultActive || null)

  const categories: Category[] = sortBy(prop('position'))(
    uniqBy(category => category.id, flatten(programs.map(program => program.categories).filter(notEmpty))),
  )

  const filteredPrograms = programs.filter(
    program =>
      (!selectedCategoryId || program.categories?.some(category => category.id === selectedCategoryId)) &&
      (!program.supportLocales || program.supportLocales.find(locale => locale === currentLocale)),
  )

  useEffect(() => {
    if (defaultActive) {
      setSelectedCategoryId(defaultActive)
    }
  }, [defaultActive])

  useEffect(() => {
    ReactGA.ga('send', 'pageview')
  }, [])

  const programCollectionPageTitle = queryTitle || pageTitle || formatMessage(productMessages.program.title.explore)

  return (
    <DefaultLayout white>
      <ProgramCollectionPageHelmet title={programCollectionPageTitle} programs={filteredPrograms} />
      <StyledBanner>
        <div className="container">
          <StyledBannerTitle>
            <Icon as={AiFillAppstore} className="mr-3" />
            <span>{programCollectionPageTitle}</span>
          </StyledBannerTitle>
          {!noSelector && (
            <StyledButton
              colorScheme="primary"
              variant={selectedCategoryId === null ? 'solid' : 'outline'}
              className="mb-2"
              onClick={() => setSelectedCategoryId(null)}
            >
              {formatMessage(commonMessages.button.allCategory)}
            </StyledButton>
          )}
          {!noSelector &&
            categories.map(category => (
              <StyledButton
                key={category.id}
                colorScheme="primary"
                variant={selectedCategoryId === category.id ? 'solid' : 'outline'}
                className="ml-2 mb-2"
                onClick={() => setSelectedCategoryId(category.id)}
              >
                {category.name}
              </StyledButton>
            ))}
        </div>
      </StyledBanner>

      <StyledCollection>
        <div className="container">
          {!noBanner && settings['program_collection_banner.enabled'] === 'true' && (
            <ProgramCollectionBanner
              link={settings['program_collection_banner.link']}
              imgUrls={{
                0: settings['program_collection_banner.img_url@0'],
                425: settings['program_collection_banner.img_url@425'],
              }}
            />
          )}
          {loadingPrograms ? (
            <SkeletonText mt="1" noOfLines={4} spacing="4" />
          ) : !!errorPrograms ? (
            <div>{formatMessage(commonMessages.status.readingFail)}</div>
          ) : (
            <ProgramCollection programs={filteredPrograms} />
          )}
        </div>
      </StyledCollection>
    </DefaultLayout>
  )
}

export default ProgramCollectionPage

和文章探索頁的排版不同
在課程探索頁的排版相較更為簡潔俐落
不囉唆,上圖

最上方為 Banner 區
但如果仔細看程式碼的話
Banner 區其實只有放「標題」和「分類按鈕」

在 ProgramCollectionPage 使用了非常多「useQueryParam」
用來判斷,當有不同的 URL 參數時,顯示對應條件的畫面

下方顯示的是各個課程的列表
他這邊有做 conditional rendering
如果今天「program_collection_banner.enabled」的設定是打開的
則顯示「ProgramCollectionBanner」這個元件
但以目前這個範例,它的設定使沒有被啟用的
故顯示「ProgramCollection」這個元件

但在專案中目前都是以「ProgramCollection」為主
「ProgramCollectionBanner」已經不怎麼使用

我們明天重點看一下「ProgramCollection」和 「ProgramCard」這兩個元件


上一篇
Blog (2)
下一篇
Program (2)
系列文
從 Open Source 專案學習 React 開發 - 以 lodestar-app 為例30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言