プロジェクトの進捗を報告します!(Next.js)
Posted date at 2024-12-27現在開発している社内アプリケーションの進捗について共有します。アプリケーションの目的、実装予定の機能、使用技術及び制作過程を記載します。
🚀アプリケーションについて
🐡何をするアプリケーションか
PV製品の制作過程で使用するチェックシートの管理を行います。チェックシートの作成から、入力、確認、承認、印刷、PDFの保管までの一連の業務フローを実現します。
🐡実装する機能
実装予定(済も含む)の機能です。権限単位でのチェックシートへの操作を厳密に管理します。
・認証(Google認証)、認可(閲覧のみ、入力、工程確認、検査担当、検査承認、システム管理など)
・フロー/通知機能(メールの送信、ドラッグ&ドロップによる割り当て)
・マスタ設定(ユーザ、フロー・通知、プロフィール、チェックリスト)
・入力制限(前工程が終わってないと入力できない、一度承認したら、承認者が解除しないと変更で
きないなど)
・帳票作成(PDF生成、ストレージへの保存(版管理))
🐡技術スタック・設計
大きいものを記載します。モダンな技術スタックを使用しています。
🚀進捗
40%程だと思っています。ユーザ認証とユーザ管理、プロフィール管理、フロー・通知設定、チェックシートマスタ(初期値やリストの作成機能)機能の実装が終わり、これからメインとなるチェックシートの作成、編集機能に入ります。未実装機能は以下の通りです。
・チェックシート一覧、検索機能
・チェックシート新規作成、編集(入力、完了・承認・印刷など)機能、削除機能
・PDF生成・保管・表示機能(ストレージ保存・履歴管理)
・通知機能(ユーザの通知設定に基づくメール送信)
🚀実装した機能
実装した機能をデモと併せて示します。
🐡新しく試したこと(2024.12.27時点)
・セッションにDBの情報(権限、社員情報、通知設定情報など)を持たせる
・クライアントサイドでuseSWRを使う
・Suspenseによるスケルトンローダーを実装する
・カンバンボードを実装する
・TailwindCSS、shadcn/ui、zustandを使う
・バックエンドを三層アーキテクチャで実装する
・リファクタリングを細かく実施する
・OGP画像を設定する
🐡ログイン画面と認証
アニメーションを作成しました。認証はNextAuthを使用しています。セッションにDBの情報をお持たせています。セッション情報を利用して、メニューのクリック制御やページ遷移の制限を実現しています。
社員情報はログイン時に社員マスタから取得しています。ユーザ管理機能、プロフィール設定からも設定可能です。
🐡ユーザ管理
検査担当以上の権限のあるユーザが他のユーザを事前に登録したり、権限の変更をしたりできるようにしています。
🐡プロフィール設定
アプリを開いたときに表示したいページを設定したり、共有メールを使用している場合はどの社員で使用するかを設定できるようにしています。
🐡フロー/通知設定
チェックシートがどの状態になったときに通知を送るのかを設定できるようにしています。カンバンボードで分かりやすく操作できるようにしてみました。状態管理はzustandを使用しています。
🐡チェックシートマスタ設定機能(制作途中)
チェックシートを新規で作成するときの、初期値(ひな型)を設定する機能を作っています。リストアイテムの追加・削除や入力の初期値を設定できるようにしています。
🚀補足SuspenseとuseSWRによるスケルトンローダーの実装
上記の動画の中でのスケルトンローダーは以下のようにクライアントコンポーネントで実装しています。スケルトンローダーは自前ですが、shadcn/uiやmaterialuiがコンポーネントを提供していますのでそれを使用すれば比較的簡単に実装できます。
useSWRのsuspenseオプションにtrueをセットすることで、SuspenseでPromiseを検知できるようになるため、ローディング表示を宣言的に書くことができます(isLoadingの条件分岐よりもきれいに書けるということです)。
//SWRの設定-suspense:trueを設定するのがキーポイント import useSWR from "swr"; import { CheckSheetMasterType } from "@/types/checksheet"; import { getCheckSheetMaster } from "@/lib/api/checksheet/master/getCheckSheetMaster"; export function useCheckSheetMaster(checkSheetId: string) { const { data, error, isLoading, mutate,//データの再取得やキャッシュの更新に使用 } = useSWR<CheckSheetMasterType, Error>( checkSheetId ? `/api/checksheet-master/${checkSheetId}` : null, () => getCheckSheetMaster(checkSheetId), { errorRetryCount: 3, // 最大リトライ回数 errorRetryInterval: 1000, // リトライ間隔(ms) }, { suspense: true }//Suspenseでローディングを検知させる際に設定する return { data, error, isLoading, isError: !!error, mutate, }; }
/*フェッチ関数を呼び出すコンポーネント*/ const CheckSheetEditArea: FC<Props> = (props) => { const { data: masterData, error, isLoading, isError, mutate: refresh, } = useCheckSheetMaster(checkSheetId);
/*スケルトンローダーを呼び出すコンポーネント */ <Suspense fallback={<CardSkeleton />}> <CheckSheetEditArea checkSheetId={checkSheetId} setCheckSheetId={setCheckSheetId} division={division} setDivision={setDivision} user={user} /> </Suspense>
🚀まとめ
中途半端な入力アプリケーションを提供するのではなく、拡張性のある完成度の高いものを作るように心がけています。特にチェックシートの種類が将来的に増えたときの追加作業を見越して、マスタのデータ定義を何度も作り直しおり、想像以上に時間がかかっています。zodのスキーマ定義が少し得意になりました。
←ホームに戻る