iT邦幫忙

2022 iThome 鐵人賽

DAY 27
0

我昨天我們講到了購買流程
今天我們看看這些元件是怎麼做的

以課程為例,他會有不同的課程方案可供選擇

首先是價格的部分

<PriceLabel
    variant="full-detail"
    listPrice={listPrice}
    salePrice={isOnSale ? salePrice : undefined}
    downPrice={discountDownPrice}
    periodAmount={periodAmount}
    periodType={periodType}
    currencyId={currencyId}
/>

他需要傳入的 props 滿多的
包含要顯示的類型、價格、優惠價格、折扣價格、訂閱區間、訂閱長度和貨幣的ID
只要看到有關錢的東西,都能看到 PriceLabel
variant 可以選擇你想展示的價格型態
有「default」、「inline」和「full-detail」
根據不同場景去使用

在下面是顯示倒數的「CountDownTimeBlock」
一樣只要有用到倒數的地方,都能看到它
在這邊他是顯示優惠的倒數,而且在後台要把倒計時打開才會有

再來則是,方案的描述,一樣使用到我們之前講的「BraftContent」
會把 Editor 的文字轉成 HTML 的格式輸出到畫面上

最後則是購買按鍵
當過了購買的時間,按鈕是會 disable 掉
那如果你是買過這個方案,會顯示「進入課程」

接下來如果你都沒有購買
也會根據根據這個課程他是「永久方案」、「限時方案」和「訂閱方案」顯示不同的元件
明天我們再來仔細看這塊

今天的程式碼如下:

// ~上方略~

const ProgramPlanCard: React.VFC<{
  programId: string
  programPlan: ProgramPlan & {
    isSubscription: boolean
    groupBuyingPeople: number
  }
}> = ({ programId, programPlan }) => {
  const { formatMessage } = useIntl()
  const history = useHistory()
  const { isAuthenticated } = useAuth()
  const { setVisible: setAuthModalVisible } = useContext(AuthModalContext)
  const { program } = useProgram(programId)
  const { productGiftPlan } = useProductGiftPlan(`ProgramPlan_${programPlan?.id}`)
  const { enabledModules } = useApp()

  const { programPlanIds: enrolledProgramIds } = useEnrolledPlanIds()

  const { salePrice, listPrice, discountDownPrice, periodType, periodAmount, currency, isSubscription } = programPlan
  const currencyId = currency.id || 'TWD'
  const isOnSale = (programPlan.soldAt?.getTime() || 0) > Date.now()
  const enrolled = enrolledProgramIds.includes(programPlan.id)

  return (
    <StyledAdminCard key={programPlan.id}>
      <header>
        <h2 className="title">{programPlan.title}</h2>
        <StyledPriceBlock>
          <PriceLabel
            variant="full-detail"
            listPrice={listPrice}
            salePrice={isOnSale ? salePrice : undefined}
            downPrice={discountDownPrice}
            periodAmount={periodAmount}
            periodType={periodType}
            currencyId={currencyId}
          />
          {productGiftPlan.id && <GiftPlanTag />}
        </StyledPriceBlock>
        {programPlan.isCountdownTimerVisible && programPlan.soldAt && isOnSale && (
          <StyledCountDownBlock>
            <CountDownTimeBlock expiredAt={programPlan?.soldAt} />
          </StyledCountDownBlock>
        )}
      </header>
      <StyledBraftContent>
        <BraftContent>{programPlan.description}</BraftContent>
      </StyledBraftContent>
      {program?.isSoldOut ? (
        <Button isFullWidth isDisabled>
          {formatMessage(commonMessages.button.soldOut)}
        </Button>
      ) : enrolled ? (
        <Button
          variant="outline"
          colorScheme="primary"
          isFullWidth
          onClick={() => history.push(`/programs/${programId}/contents?back=programs_${programId}`)}
        >
          {formatMessage(commonMessages.button.enter)}
        </Button>
      ) : programPlan.isSubscription ? (
        <CheckoutProductModal
          renderTrigger={({ isLoading, onOpen, isSubscription }) => (
            <Button
              colorScheme="primary"
              isFullWidth
              isDisabled={isAuthenticated && isLoading}
              onClick={() => {
                if (!isAuthenticated) {
                  setAuthModalVisible?.(true)
                } else {
                  ReactGA.plugin.execute('ec', 'addProduct', {
                    id: programPlan.id,
                    name: programPlan.title,
                    category: 'ProgramPlan',
                    price: `${programPlan.listPrice}`,
                    quantity: '1',
                    currency: currencyId,
                  })
                  ReactGA.plugin.execute('ec', 'setAction', 'add')
                  ReactGA.ga('send', 'event', 'UX', 'click', 'add to cart')
                  onOpen?.()
                }
              }}
            >
              {isSubscription
                ? formatMessage(commonMessages.button.subscribeNow)
                : formatMessage(commonMessages.ui.purchase)}
            </Button>
          )}
          defaultProductId={`ProgramPlan_${programPlan.id}`}
          warningText={
            listPrice <= 0 || (typeof salePrice === 'number' && salePrice <= 0)
              ? formatMessage(productMessages.program.defaults.warningText)
              : ''
          }
        />
      ) : enabledModules.group_buying && programPlan.groupBuyingPeople > 1 ? (
        <CheckoutProductModal
          defaultProductId={`ProgramPlan_${programPlan.id}`}
          renderTrigger={({ isLoading, onOpen }) => (
            <Button
              colorScheme="primary"
              isFullWidth
              isDisabled={isAuthenticated && isLoading}
              onClick={() => {
                if (!isAuthenticated) {
                  setAuthModalVisible?.(true)
                } else {
                  ReactGA.plugin.execute('ec', 'addProduct', {
                    id: programPlan.id,
                    name: programPlan.title,
                    category: 'ProgramPlan',
                    price: `${programPlan.listPrice}`,
                    quantity: '1',
                    currency: currencyId,
                  })
                  ReactGA.plugin.execute('ec', 'setAction', 'add')
                  ReactGA.ga('send', 'event', 'UX', 'click', 'add to cart')
                  onOpen?.()
                }
              }}
            >
              {formatMessage(commonMessages.ui.groupBuy)}
            </Button>
          )}
        />
      ) : (
        <>
          <PaymentButton
            type="ProgramPlan"
            target={programPlan.id}
            price={isOnSale && salePrice ? salePrice : listPrice}
            currencyId={currency.id}
            isSubscription={isSubscription}
          ></PaymentButton>
        </>
      )}
    </StyledAdminCard>
  )
}

export default ProgramPlanCard

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

尚未有邦友留言

立即登入留言