3D間取りの管理機能追加(削除・検索・非表示・物件名)と生成エンジンのChatGPT切替

done

セッション開始:2026/06/08 16:48

planning developing done

目的 / なぜ必要か

3D間取りの一覧・運用を改善するため、 削除・物件名検索・一覧非表示・物件名編集の各機能を追加する。あわせて、3D間取りの 生成エンジンGoogle Gemini から ChatGPT(OpenAI)へ切り替える

スコープ

やること

  • 削除:3D間取りの論理削除。ただし生成前のみ可能
  • 検索物件名の部分一致+「非表示を含める」トグル
  • 一覧非表示一覧非表示isUnlisted)のON/OFF
  • 物件名編集:専用ページ(/edit/name)。空欄で作成日時を表示
  • 生成エンジン切替:Gemini → ChatGPT(OpenAI)

やらないこと

  • 生成済み(生成開始後)の3D間取りの削除 → 「一覧非表示」で代替
  • 物理削除(deletedAt による論理削除のみ)
  • 生成日時(generationEndedAt)でのフォールバック表示 → 作成日時を採用
  • Gemini 実装の削除(フォルダ退避+コメントアウトで温存)
  • 検索の生成完了絞り込み・月絞り込みのUI(アクション側は実装済みだが未配線)

決定事項(仕様)

削除の可否 生成前のみ削除可generationStartedAt !== null なら SolidFloorPlanGenerationHasAlreadyStarted で失敗。生成済みは一覧非表示で隠す運用。
削除方式 論理削除deletedAt に現在時刻)。削除ボタンは編集3画面(details / styles / room-images)下部に配置し、確認ダイアログ付き。
物件名の呼称 UI 表記は 「物件名」に統一(旧「部屋名」を改名)。ラベル/ヘルプ文言/検索プレースホルダ/詳細の編集ボタンの4箇所。
物件名のフォールバック 物件名が空(null)のとき、表示は 作成日時(createdAtを使用。ヘルプ文言も「作成日時が使用されます」に統一(内部は createdAt)。
物件名の保存 空欄入力は null に変換して保存(name?: string | null)。
一覧非表示 isUnlisted(既定 false)。詳細画面のスイッチでON/OFF。一覧では EyeOff アイコンを重畳表示。
検索(物件名) Prisma contains による部分一致。URL クエリ ?name=
検索(非表示を含める) 既定は表示中のみisUnlisted: false)。トグルONで ?includeUnlisted=1 → 絞り込みを外し全件表示。
生成エンジン ChatGPT(OpenAI)へ切替。model: "gpt-5.5"image_generation ツール(Responses API)。Gemini は lib/gemini/ へ退避し温存。
instructions スキーマ kindchatgpt / gemini)で系統を分け、各 version を持つ。保存時の kind は現状 "chatgpt" ハードコード(課題参照)。

UI イメージ(修正後)

一覧:検索フォーム+非表示バッジ

物件名で検索
非表示を含める
検索する
非表示
○○マンション 101
表示中
2026/06/08 15:42

詳細:一覧表示スイッチ+物件名編集導線

一覧に表示
物件名を編集する

編集(各ステップ)下部:削除ボタン


削除する

※ 生成開始後は押下しても「生成が既に開始」エラーで削除不可。

実装内容(影響範囲)

DB prisma/schema/solid-floor-plan.prisma

isUnlisted Boolean @default(false) 追加(マイグレーション 20260608154235_solid_floor_plans)。

新規 apps/user/actions/solid-floor-plan/delete-solid-floor-plan.ts

論理削除アクション。generationStartedAt !== null で失敗。所有者・組織・deletedAt: null でスコープ。

変更 apps/user/actions/solid-floor-plan/list-solid-floor-plan.ts

検索オプション { name?, hasGenerationFinished?, month?, isUnlisted? } を受け取り where 構築。namecontains。(hasGenerationFinished / month はUI未配線)

変更 apps/user/actions/solid-floor-plan/update-solid-floor-plan.ts

name?: string | null(空→null)と isUnlisted? を受理。

新規 .../search-form/{index,schema}.tsx + _fields/{name-field,include-unlisted-field}.tsx

検索フォーム。_fields/ 分割+schema.ts 集約+createSearchParams でクエリ組み立て(既存規約に踏襲)。

新規 .../edit/name/page.tsx + _components/solid-floor-plan-update-form/{index,schema}.tsx

物件名編集ページ。保存後は詳細へ戻る。

新規 .../_components/is-listed-switch/index.tsx + components/delete-button/solid-floor-plan/index.tsx

一覧表示スイッチ(共通 IsListedSwitch ラップ)と削除ボタン(共通 DeleteButton ラップ、確認ダイアログ)。

新規 .../generate-image/lib/chatgpt/index.ts + apps/user/lib/chatgpt/upload-file.ts

ChatGPT(OpenAI)での画像生成。files.create(purpose: "vision") でアップロードし responses.createimage_generation で生成、結果を S3 へ保存。

変更/退避 .../generate-image/lib/gemini/index.ts(旧 generate-image-with-gemini.ts)/packages/database/.../instructions-schema/{chatgpt,gemini}/v1.ts

Gemini 実装をフォルダ退避し温存。instructions スキーマを chatgpt / gemini の2系統に再編。generate/route.tskind: "chatgpt" で保存。

レビューでの指摘・修正

用語:「部屋名」→「物件名」へ統一

実装は全箇所「部屋名」だったが、正式名称は「物件名」。ラベル・ヘルプ文言・検索プレースホルダ・詳細の編集ボタンを「物件名」へ修正。

文言:空欄時のフォールバックは「作成日時」

ヘルプ文言は「生成した日時」だったが、表示ロジックは createdAt(作成日時)を使用。文言を「作成日時が使用されます」に修正し、コードに整合させた。

現状維持と判断した点

  • 削除の可否ルール(生成前のみ):現状の実装どおりで確定。
  • generate/route.tskind: "chatgpt" ハードコード:現状維持(デシンク懸念は課題へ)。
  • instructionsSchemaz.union:現状維持(discriminatedUnion("kind") 化は見送り)。
  • server-only の付与:不要と判断し追加せず。