ハコヅミを作る #15:チェックリストを「キャンプ」に育てる
ハコヅミの MVP では、キャンプ1回分の持ち物チェックを「チェックリスト」と呼んでいました。今回は、これをキャンプそのものの記録に育てます。
- 予定期間・実績期間
- キャンプ場(名前・住所・電話番号・URL・Google マップの URL)
- キャンプ場の画像、メモ
- あとからプランを変えること
Notion の「今後の機能強化」の「キャンプの予定登録」「キャンプ履歴」にあたります。Issue でいうと #64・#65・#68・#69・#82 の5つです。
できあがった画面
キャンプの画面の上に「キャンプ情報」の欄を置き、その下に今までの持ち物チェックを続けました。

キャンプの画面の上のほう。持ち物チェックはこの下に続く
画面は、この記事の時点のコードを手元で動かして撮ったものです。ギアは#7で Notion から取り込んだ実際のもので、キャンプ場は記事用の架空のものです。
一覧には、予定期間・キャンプ場・プランと、行ったあとなら実績期間を出します。

キャンプ一覧。予定期間の新しい順
camps という名前にしておいてよかった
MVP を作るとき、テーブル名を checklists ではなく camps にしていました(#1)。「あとから列を足すだけで、予定や履歴に発展できるように」という理由です。
今回、それがそのまま効きました。テーブルを作り直さず、camps に列を足すだけで済んでいます。
| 列 | 内容 | Issue |
|---|---|---|
planned_start_date・planned_end_date |
予定期間 | #64 |
actual_start_date・actual_end_date |
実績期間 | #64 |
campsite_name・campsite_address・campsite_phone |
キャンプ場 | #64 |
image_key |
キャンプ場の画像(R2 のキー) | #65 |
campsite_url・campsite_map_url |
キャンプ場の URL と地図 | #82 |
URL(/camps、/camps/[id])も変えず、画面の呼び方だけを「チェックリスト」から「キャンプ」に、持ち物の部分を「持ち物チェック」に変えました。
Issue の下書きで直した「日付」の意味
camps には、MVP のときから date(日付)の列がありました。チェックリストを作るときに入れる日付で、Claude Code が最初に作った Issue の下書きでは、これをそのまま「キャンプの日」として使う案になっていました。
下書きを読んで、ここを直しました。
- 今の
dateは、あくまで登録日。名前は変えず、登録した日を自動で入れる(入力欄はなくす) - キャンプの日は、別に予定期間(開始日〜終了日)を持つ
- 行ったあとの記録として、実績期間も持つ
- キャンプ場は、名前だけでなく住所と電話番号も
期間を開始日と終了日の組で持つのは、将来カレンダーで「いつからいつまで」を一度に選べるようにしたいからです。今回の画面は、開始日と終了日をそれぞれ入れる形にしています。
すでにあるキャンプの予定期間が空にならないよう、マイグレーションで登録日を入れています。drizzle-kit が作るのは列を足す SQL だけなので、データを埋める UPDATE は手で書き足しました。
ALTER TABLE `camps` ADD `planned_start_date` text;--> statement-breakpoint
ALTER TABLE `camps` ADD `planned_end_date` text;--> statement-breakpoint
...
UPDATE `camps` SET `planned_start_date` = `date`, `planned_end_date` = `date` WHERE `planned_start_date` IS NULL;
入力のルールも、ユニットテストできる形に切り出しました。
- 予定期間の終了日が空なら、開始日と同じ日(日帰り)
- 実績期間は、終了日だけを入れるのは不可。開始日だけなら日帰り
- 終了日が開始日より前は不可
- 表示は「2026-10-03〜2026-10-04」。同じ日なら1日だけ
1つの Issue を、3つに分けた
最初のメモには、画像やメモも入っていました。下書きを見て、次のように分けています。
- #64:呼び方の変更、予定期間・実績期間、キャンプ場
- #65:キャンプ場の画像(別の Issue に)
- メモは、「感想」にするか「キャンプ場のメモ」にするかを決めきれず、いったん対象外
画像は、ギアの画像(#12)の仕組みを使い回しました。画像の欄の部品は GearImageField から ImageField に名前を変えて共通にし、R2 のキーも users/<user_id>/camps/<キャンプの id>-<ランダムな ID>.<拡張子> と、ギアと同じ決まりにしています。ギアのときに「利用者ごとにまとめる」と決めておいたので、置き場所で迷うことはありませんでした。
登録したあとで、直せないものがあった
#64・#65 の受入確認のあと、使ってみて気づいたことがありました。
一旦、キャンプ情報を作成したら、その後にプランとメモを修正する方法が無い
予定期間やキャンプ場は編集画面で直せますが、プランとメモは登録のときにしか入れられませんでした。人数や泊数が変わってプランを変えたいときは、登録し直すしかありません。
メモ(#68)
メモの分け方は決めないまま、今のメモを編集画面で直せるようにしました。Notion の構想にあった「キャンプの感想メモ」も、感想専用の欄は作らず、このメモで兼ねることにしています。使っていくうちに分けたくなったら、そのとき考えます。
プランの変更(#69)
プランを変えるときに悩んだのは、持ち物チェックをどうするかです。
| 案 | 中身 |
|---|---|
| A | 前のチェックを、新しいプランにもあるギアだけ引き継ぐ |
| B | 新しいプランの中身で作り直し、チェックはすべて外す |
引き継いだほうが親切に見えますが、プランを変えるのは、人数や泊数が変わったときです。前のプランのつもりで積んだ荷物がそのまま「チェック済み」で残ると、要らないものまで積み込んでしまうおそれがあります。最初から荷物を見直してもらうほうが安全なので、B にしました。
その代わり、うっかり変えてしまわないよう、プランを変えて保存するときだけ確認を出します。
プランを変えると、持ち物チェックを作り直し、チェックはすべて外れます。よろしいですか?

キャンプ情報の編集画面。プランもメモもここで直せる
項目の入れ替えは、古い項目の削除と新しい項目の追加を1つのバッチで行います。途中で失敗して、項目が半端に残ることはありません。項目を作る処理は、登録のときと共通にしました。
キャンプ場の URL と地図(#82)
最後に、キャンプ場のホームページ(予約サイト)の URL と、Google マップの URL を足しました。チェックインの時間を確かめたり、現地までの道を開いたりするためです。
- キャンプ場の URL:
httpかhttpsで始まるものだけ - 地図の URL:Google マップの URL だけ(
www.google.com/maps、maps.google.com、maps.app.goo.gl、goo.gl/maps) - どちらも新しいタブで開く(
rel="noopener noreferrer")
地図の URL を Google マップに絞ったのは、「地図を開く」というリンクの先が、まったく別のサイトにならないようにするためです。スマホの共有で出てくる短い URL(maps.app.goo.gl)も通るようにしています。
おわりに
- 最初に
campsという名前にしておいたので、列を足すだけでキャンプの記録に育てられた dateは登録日のまま。キャンプの日は予定期間・実績期間として別に持つ- 大きくなりそうな Issue は、下書きの段階で分ける
- プランを変えたら、持ち物チェックは作り直してチェックを外す。積み込みのミスを防ぐほうを選んだ
5つの Issue は、開発環境での受入確認のあと、本番にもリリースしました。次回は、ガス缶や食材などの消耗品です。