Open5

cal.comコードリーディングメモ

ピン留めされたアイテム

https://cal.com/
The open source Calendly alternative.

https://github.com/calcom/cal.com
  • Next.js
  • React
  • Tailwind
  • Prisma

モチベ

  • 技術スタックが関心と近かったから読んで見る。
  • prismaを触ってみて、ORM的なオブジェクトを装飾してリッチにするようなコードを何処に書けばいいか解らなかったから

What?

扱う情報

  • 予定
    • 符号化しやすい?
  • 時間、相手
  • 目的:
    • 自分の予定を確認する
    • 相手に空いている予定を提示する
      • 勝手に予定を入れてもらう
      • どういう予定を入れられるかを予め設定する

interaction

  • カレンダーアプリとの連携
    • 既に設定されている予定とのやりとり
  • 予定閲覧
    • 取り込んだ、入れられた予定を閲覧できる
  • guestが提示されたイベント種別、空きスケジュールの中から予定を入れられる

memo

  • シンプルに便利、効率化のカテゴリ?
  • ある目的においての予定を組む、という点に特化したシステム

event types page


https://github.com/calcom/cal.com/blob/5f4bd87f0d17d89800d40921ab6e7173ecd35d10/apps/web/pages/event-types/index.tsx
  • trpcのsever少し把握
  • comonentに書き出すまでもない、ページ内部のcomponentは関数として書き出すと見やすくなる
  • sortの実装見てみた
    • 専用のmutationを用意している
    • sorted用のlistを生成して、それをrenderingしている
    • 自分だったら、シンプルなlistのみで、mutation後にrefreshする実装にしそう
      • query数は増えるから、performaceヘビー?な画面だったらcal.comの実装も検討する?

プレビュー画面

https://github.com/calcom/cal.com/blob/5f4bd87f0d17d89800d40921ab6e7173ecd35d10/apps/web/pages/[user]/[type].tsx

link: ${process.env.NEXT_PUBLIC_APP_URL}/${profile.slug}/${type.slug}
file: pages/[user]/[type].tsx
component: components/booking/pages/AvailabilityPage.tsx

  • tailwind css
    • これだけ細かい要素のcss構造を考えるのは大変そうだから、命名なしのメリットはやっぱりある気がする
    • style欄、パットみ長いけど、慣れればそれほどでもない?

eventType(prisma)の拡張

getServerProps上で。

const eventTypeObject =Object.assign({}, eventType, {
  periodStartDate: eventType.periodStartDate?.toString() ?? null,
  periodEndDate: eventType.periodEndDate?.toString() ?? null,
});
  • カレンダーの表示は grid layoutでやっている

  • useMemoの使い所

    • 毎度計算させたくない、特定のobjectに依存した処理
      • calendarのdays
  • router

    • 日付、時間の選択はrouterを使っている
    • 予約画面のurlは下記のように UrlObjectを定義して、Link.hrefに渡している
    const bookingUrl: BookingURL = {
      pathname: "book",
      query: {
        ...router.query,
        date: slot.time.format(),
        type: eventTypeId,
      },
    };
    
  • component内の関数について

    • reactを読んでいくときは
      • render部分 → component function内、とすると、component functionはできる限りスッキリさせておきたい
    • component function内に置く必要が処理はなるべく外に出しておくと良さそうと見通しが良くなりそう
  • dayjs

    • momentjs altanative
  • tremetry?

    • useTeremetry
      • useContextをwrapして、データ収集系の処理(Jitsu)を各componentから手軽に使えるようにしている
      • libじゃだめ?
        • componentがどういうcontextで呼ばれるか、に依存させることができる
        • 例えばtestから呼び出されたら何もしない、とか
        • TelemetryProvider で、createTelemetryClient、実際のデータ収集処理を設定している
ログインするとコメントできます