前回の記事では、栽培管理アプリの設計について書きましたが、今回は実際に基本機能を実装していきました。
設計を形にしていく過程で、いくつか新しい課題や気づきもあったので、その辺りも含めて書いていきます。
実装した基本機能
前回設計したフェーズ1の機能を、ほぼ実装できました。
1. データベースのマイグレーション
まず、前回設計したテーブル構造を実際のデータベースに反映しました。
主な変更:
cult_fieldsに作物情報のカラムを追加(current_crop_name,current_crop_started_at,current_crop_ended_at)cult_plantingsテーブルを削除(作物情報をcult_fieldsに統合)cult_logsに詳細項目を追加(amount,work_minutes,memo,fertilizer_typeなど)- 作業マスタ関連のテーブルを作成(
cult_work_types,cult_crop_work_settings,cult_pesticide_usage)
すべてのテーブルにRLS(Row Level Security)ポリシーを設定して、ユーザーごとにデータを分離しています。
2. ハウス新規登録機能
ハウスを登録する画面を作りました。

機能:
- 単棟ハウスと連棟ハウスの両方に対応
- 幅・長さ・畝数を入力すると、畝が自動生成される
- 連棟の場合は、2〜6棟まで選択可能
Next.js 16のApp Routerを使っているので、以下の3ファイル構成にしました:
page.tsx: Server Component(認証チェック、初期データ取得)Client.tsx: Client Component(UIロジック)actions.ts: Server Actions(データベース登録処理)
この構成、最初は「ファイルが増えて面倒だな」と思ったんですが、役割がクリアに分かれるので逆に管理しやすいです。
3. メイン画面(パターンA)の実装
畝を選択して作業記録するメイン画面を作りました。
前回、パターンAとパターンBの2つを試すと書きましたが、まずパターンA(フッター固定)から実装しました。

UIの特徴:
- ハウスカードはアコーディオン式(閉じた状態/開いた状態を切り替え)
- 畝をタップすると選択状態(緑色にハイライト)
- 複数の畝を選択可能
- 「全選択」「全解除」ボタンあり
- 画面下部に作業アイコン(灌水、施肥、防除、その他)を固定
直近作業の表示:
ハウスを開いたときに、各畝の直近作業が表示されます。
直近作業:
畝1: 12/1
畝2: 12/1 12/1 12/1
畝3: 12/1 12/1
畝4: 12/1
各作業種類(灌水、施肥、防除など)ごとに、最新1件だけを表示しています。
これによって、「あれ、もう1週間も水やってないな」みたいなことが一目でわかるように。
履歴詳細の表示方法:
さらに履歴アイコンをタップすると、
画面下部に固定エリアを作って、タップしたら詳細が表示されるように。

畝を選択しているときは作業メニュー、履歴アイコンを選択しているときは履歴詳細。両方選択していれば、両方表示されます。
画像では、12/1の畝2を選択→施肥記録の詳細を表示。
肥料名、農薬名はまだ表示されてないので、後々実装予定。
4. 作業記録の保存
Server Actionを使って、作業記録をデータベースに保存する処理を実装しました。
処理内容:
- 選択された畝ごとに、個別のレコードを作成
- 使用量の計算(合計量入力 or 畝単位入力を選択可能)
- 施肥の場合は、肥料タイプ(液肥/固形)も保存
登録が成功したら、「作業記録を登録しました!」というメッセージが1.5秒間表示されてから、モーダルが自動で閉じます。
最初はメッセージなしで閉じるだけだったんですが、「ちゃんと登録されたのか不安」という気持ちになったので、メッセージを追加しました。
5. 作業履歴一覧ページ
記録した作業を確認する一覧ページも作りました。

機能:
- テーブル形式で表示(日付、ハウス、畝、作業、使用量、時間、メモ)
- ハウスと作業種類でフィルタ可能
- 作業時間の合計を表示
まだ細かい修正点はありますが、とりあえず動く状態にはなりました。
農薬マスタの設計で詰まった話
基本機能の実装が進んだので、次は「肥料・農薬マスタの管理」に取り掛かろうとしました。
最初の設計
肥料マスタ:
- 肥料名
- 種類(液肥/固形)
- メモ欄
農薬マスタ:
- 農薬名
- 種類(殺菌/殺虫/展着剤/葉面散布)
- 希釈倍率
- 使用回数制限
- 対象病害虫
- メモ欄
問題1: 農薬のデータが多すぎる
農薬は種類が多すぎるため、手動で全部登録するのは面倒。
問題2: 同じ農薬でも、対象によって倍率が違う
さらに厄介なのが、「同じ農薬でも、対象病害虫によって希釈倍率が違う」ということ。
例えば:
ジクワット・パラコート液剤(除草剤)
- 野菜類(一年生雑草): 600〜1000倍
- アスパラガス(一年生雑草): 600〜1000倍
- アスパラガス(スギナ): 1000〜2000倍
同じ農薬なのに、スギナに対しては倍率が違うんです。
これ、マスタに「希釈倍率」をどう登録すればいいんでしょう?
解決策: 農薬マスタと詳細を分離
調べてみたら、農林水産省の「農薬登録情報提供システム」からCSVでデータをダウンロードできることがわかりました。
ただし、このCSVデータは「農薬名」と「対象病害虫」の組み合わせごとに1行になっています。
つまり、同じ農薬でも対象病害虫が違えば別の行になる。
そこで、テーブル設計を以下のように変更することにしました。
農薬マスタテーブル (cult_pesticides):
- 農薬名
- 種類(殺菌/殺虫/展着剤/葉面散布)
- メモ欄
希釈倍率や使用回数は、マスタには入れない。
農薬適用詳細テーブル (cult_pesticide_applications):
- 農薬ID(マスタへの参照)
- 対象病害虫名
- 使用方法
- 使用時期
- 希釈倍率(最小・最大)
- 使用回数制限
こうすることで、同じ農薬でも対象病害虫ごとに異なる倍率を管理できます。
作業記録時のUI
防除作業を記録するときは、以下のような流れになります。
1. 畝を選択: 畝1, 畝2
2. 農薬を選択(マスタから):
[▼ジクワット・パラコート液剤]
3. 対象病害虫を選択(詳細から):
[ ] 野菜類(一年生雑草) - 600〜1000倍
[ ] アスパラガス(一年生雑草) - 600〜1000倍
[✓] アスパラガス(スギナ) - 1000〜2000倍
4. 希釈倍率が自動表示:
推奨倍率: 1000〜2000倍
実際の倍率を入力: [1500] 倍
5. 使用量を入力:
原液: [100] ml
→ 散布量: 150L(自動計算)
「農薬を選ぶ」→「対象病害虫を選ぶ」→「倍率が自動で入る」という流れ。
これなら、間違った倍率で使用するミスを防げます。
CSVインポート機能
農水省のデータをCSVでダウンロードして、アプリにアップロードすれば、自動で整理してデータベースに登録する機能を作る予定です。
処理の流れ:
- CSVをアップロード
- 同じ農薬名でグループ化
- 農薬マスタに1件登録
- 対象病害虫ごとに詳細テーブルに登録
これで、手動で何十件も登録する手間が省けます。
今後の予定
次にやること
- 農薬・肥料マスタのマイグレーションSQL作成
- CSVインポート機能の実装
- 農薬マスタ管理画面(一覧・編集・削除)
- 防除作業記録UIの実装
後回しにしたこと
以下は、一旦後回しにすることにしました。
- パターンBの実装: パターンAで十分使えそうなので、後回し
- モバイル最適化: 基本的にはモバイルファーストで作っているので、細かい調整は後で
- カレンダービュー: あったら便利だけど、なくても困らない
- 天気自動取得: OpenWeatherMap APIを使えば実装できるけど、優先度は低い
- 農場マップ機能: ドラッグ&ドロップで配置できたら楽しそうだけど、今は不要
将来対応したいこと
- 肥料・農薬の複数混合使用(2〜3種類を混ぜて使う)
- 複数ハウスにまたがる畝選択(使用頻度は低いけど、あると便利かも)
