最近は、なんでもAIがコードを書いてくれる時代ですが、あえてAIを使わずにコードを書いてみました。もちろん、最終的にはAIにコードを見てもらいました☺️(私の心強い先生です!)
AIを使えば効率よく開発できますし、時間短縮にもなります。ただ、自分はまだ知識も経験も浅いため、基礎的な部分は自分の力で書けるようになりたいと思いました。この1つのアプリを作っただけで大きく変わるとは思いませんが、こうした経験を積み重ねることで、少しずつ成長できると信じています。
- Hookの宣言
- Timer記録
- 設計
勉強記録アプリについて
今回は、勉強記録アプリケーションを制作しています。GitHubのように、1年間単位で勉強した日が一目で分かるようなシンプルで分かりやすいUIを目指しています。

開発環境
今回の開発では、以下の技術を使用しています。
- Next.js(App Router)
- TypeScript
- Tailwind CSS
- localStorage
バックエンドは使用せず、まずはフロントのみで動くように構成しました。
設計
最初に、「どのような機能が必要なのか」を整理しました。その上で、コンポーネント・フック・タイプ・関数などを役割ごとに分けて設計しています。
- Page
→ 全体のレイアウト・表示管理 - Component
→ Timer、Grass などのUI - Hook
→ useTimer(時間の管理)、再利用可能 - Type
→ StudyRecord などのデータ構造 - Function
→ localStorageの保存・取得、フォーマット処理
Type定義
まずは、保存するデータの形を決めました。
Type定義
ID(固有番号)に加えて、日付・勉強内容・勉強時間を保存します。データの形を先に決めることで、その後の実装をスムーズに進めることができました。
このデータは画像のようにローカルストレージに保存します。

コードを見る
export type StudyRecord = {
id: string;
date: string;
startTime: number;
endTime: number;
duration: number;
title: string;
detail?: string;
};useTimer(カスタムフック)
タイマーのロジックは、カスタムフックとして分離しました。
コード説明
勉強開始時間と終了時間を記録して、勉強時間を計算します。
State変数宣言
- startTime
スタート時間を管理するStateです。(number または null) - isRunning
タイマーが動いているかどうかを判別します。
start()関数
isRunningがtrueの場合は処理しないDate.now()で現在時刻を取得- Stateを更新してタイマーを開始
end()関数
isRunningがfalse、またはstartTimeがnullの場合は処理しない- 現在時刻から
startTimeを引いて、経過時間を計算 isRunningをfalseに変更- 計算した値をreturn
コードを見る
function useTimer() {
const [startTime, setStartTime] = useState<number | null>(null);
const [isRunning, setIsRunning] = useState(false);
const start = () => {
if (isRunning) return;
const now = Date.now();
setStartTime(now);
setIsRunning(true);
};
const end = () => {
if (!isRunning || startTime == null) return;
const now = Date.now();
const duration = now - startTime;
setIsRunning(false);
return {
startTime,
endTime: now,
duration,
};
};
return { start, end, isRunning, startTime };
}コードのポイント
時間の管理は Date.now() を使い、ミリ秒単位でシンプルに扱うようにしました。
- 開始 → 現在時刻を保存
- 終了 → 差分で時間を計算
また、ロジックとUIを分離することで、再利用しやすく、見通しの良いコードになりました。
Page(UI)
UIはシンプルに、
- 勉強内容を入力
- Startで開始
- Endで終了
という流れにしました。

最小限の構成にすることで、まずは動くものを作ることを意識しました。
まとめ
今回は、勉強記録アプリの第一ステップとして、タイマー機能を実装しました。シンプルですが、アプリの土台になる重要な部分だと感じました。
次回は、記録したデータをlocalStorageに保存する処理についてまとめる予定です。
