iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 21
0

上一個章節,我們完成了將資料轉變為列表頁、內頁,今天我們要來把昨天做的內頁再做一些微調,新增一個時間顯示的邏輯,並且將 Gatsby-theme-events 工作區的設定檔從 Hard Code 的狀態解放出來。

時間顯示邏輯

首先,我們先回到 gatsby-theme-events 工作區中的 components/event.js 中,我們希望把原本顯示時間的方式調整得更容易讓人理解些,我們會調整成以下的形式

  • 如果是單天的活動,就會只顯示 某年某月某日
  • 如果是多天的活動,則顯示 某月某日至 某年某日 ( 結束日 )
  • 如果是跨月份的活動,則會顯示 某月某日至 某年某月某日 ( 結束日 )

既然我們已經定義好顯示邏輯了,就讓我們開始吧!

首先我們先定義一個 getDate 函式,用來處理時間、時區的判斷

const getDate = (date, { day = true, month = true, year = true } = {}) =>
  date.toLocaleDateString("Asia/Taipei", {
    day: day ? "numeric" : undefined,
    month: month ? "long" : undefined,
    year: year ? "numeric" : undefined,
  })

再來定義一個 EventDate 函式來決定我們要回傳什麼樣的格式到畫面上

const EventDate = ({ startDate, endDate }) => {
  const start = new Date(startDate)
  const end = new Date(endDate)
  const isOneDay = start.toDateString() === end.toDateString()
  return (
    <>
      <time dateTime={start.toISOString()}>
        {getDate(start, { year: isOneDay })}
      </time>
      {!isOneDay && (
        <>
          –
          <time dateTime={end.toISOString()}>
            {getDate(end, { month: start.getMonth() !== end.getMonth() })}
          </time>
        </>
      )}
    </>
  )
}

最後我們只要將原先在 JSX 的這個段落

<p>
  {startDate}-{endDate}
</p>

修改為我們上面做好的元件,並把開始跟結束時間作為 props 傳入就可以囉

<p>
   <EventDate startDate={startDate} endDate={endDate} />
</p>

對於 Date 不熟悉的讀者們,可以參考 Date - MDN

將主題配置調整為動態

不知道各位讀者是否還記得,我們在 Gatsby-node 與 Gatsby-config 中,我們有寫死一些參數,例如 contentPath 這個變數我們就設定為 data,而 basePath 也被我們指定為根目錄。

現在我們要將這些選項改為動態傳入的,因為我們現在在 gatsby-theme-events 工作區的任務已經告一個段落了,往後我們主要都會在 Site 工作區裡做修改。

首先,我們先來調整 gatsby-theme-events 工作區的 gatsby-config.js ,原先我們的 config 長得如下

module.exports = {
  plugins: [
    {
      resolve: "gatsby-source-filesystem",
      options: {
        path: "data",
      },
    },
    {
      resolve: "gatsby-transformer-yaml",
      options: {
        typeName: "Event",
      },
    },
  ],
}

現在我們要調整為這個 module 會接受參數,並且參數都帶有預設值,來增加 module 的靈活度

module.exports = ({ contentPath = "data", basePath = "/" }) => ({
  plugins: [
    {
      resolve: "gatsby-source-filesystem",
      options: {
        path: contentPath,
      },
    },
    {
      resolve: "gatsby-transformer-yaml",
      options: {
        typeName: "Event",
      },
    },
  ],
})

接著我們來調整 gatsby-node.js 檔,所有的函示我們都多接收一個 options 參數,並在函式內給予變數一個預設值,因為程式碼較長,筆者這邊只列出異動區塊的前後比較。

修改前:

exports.onPreBootstrap = ({ reporter }, options) => {
const contentPath = "data"

exports.createResolvers = ({ createResolvers }) => {
  const basePath = "/"

exports.createPages = async ({ actions, graphql, reporter }) => {
  const basePath = "/"
  

修改後:

exports.onPreBootstrap = ({ reporter }, options) => {
const contentPath = options.contentPath || "data"

exports.createResolvers = ({ createResolvers }, options) => {
  const basePath = options.basePath || "/"

exports.createPages = async ({ actions, graphql, reporter }, options) => {
  const basePath = options.basePath || "/"

調整完畢後,我們回到 Site 工作區,同樣的,我們在 Site 工作區內新增一支 Gatsby-config.js 檔,檔案內容如下

module.exports = {
  plugins: [
    {
      resolve: "gatsby-theme-events",
      options: {
        contentPath: "events",
        basePath: "/events",
      },
    },
  ],
}

其實與原先 Gatsby-theme-events 中的 gatsby-config.js 非常類似,只是多了 Options ,也因為這樣的設定,有了以下兩點變化

  • 我們的 Site 不會在我們預設的 data 中找尋資料,而是在 events 目錄中
  • 原先根目錄是我們的列表頁,這邊因為我們 basePath 的設定,所以列表頁的路由會變成 /events

接著我們輸入以下指令來確認是否能正常運行吧!

yarn workspace site develop

順利開起來的讀者,應該會觀察到有兩件事情偷偷的發生了

  1. 你的 Site 目錄下多了 events 的資料夾
  2. 我們到 Gatsby 自訂的 404 頁面,發現多了一個 /events 的頁面

但因為我們還沒在 Site 工作區中放任何的資料,所以先讓我們把 events.yml 複製到 Site 的 events 下吧!

貼上後我們重啟開發伺服器,就能看見資料已經完整的呈現在頁面上囉!
而且路由就如紅框處所示,為 /events,也不是原本的 / 了呢

https://ithelp.ithome.com.tw/upload/images/20201006/20109495CQSokfOuBU.png

明天,就會是這個建立自己主題系列的最後一個章節,我們預計使用 Chakra 這套 UI Library 來將我們的專案弄的水噹噹,並且推到 NPM 上供大家使用。

參考資料

Gatsby - building a Theme


上一篇
[Day 20] - 建立屬於自己的主題 ( 三 )
下一篇
[Day 22] - 建立屬於自己的主題 ( 五 )
系列文
雖然你不是木村拓哉,但它也可以讓你變很行 - Gatsby.js30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言