概要
長ったらしいタイトルになってしまったが、ようは「タスクカテゴリがStudy or Other」のように指定したい場合の実行方法をまとめる。
前提
下記の内容が完了していること。
現状の確認
タスクカテゴリは検索時に1個だけ指定できる仕様になってしまっている。
これだともちろん単独のタスクカテゴリのタスクだけ見たい場合は問題ないが、カテゴリを複数選択しながらチェックしたい場合にかなり不便となる。
方法
まずは現在プルダウンで単一のカテゴリしか指定できない部分を修正する。
-
app/routes/_index.tsx
を下記のように修正し、プルダウンからチェックボックスに変更し、複数のカテゴリ情報をクエリパラメーターに乗せられるように実装app/routes/_index.tsximport type { MetaFunction } from "@remix-run/cloudflare"; import { useNavigate, useLoaderData } from "@remix-run/react"; import { useState } from "react"; import { loader } from "./task-category-masters-loader"; export { loader }; export const meta: MetaFunction = () => { return [ { title: "Top" }, { name: "description", content: "Top", }, ]; }; export default function Index() { const navigate = useNavigate(); const [isDeleted, setIsDeleted] = useState(false); const [isComplete, setIsComplete] = useState(false); const [taskCategoryMasterIds, setTaskCategoryMasterId] = useState<string[]>([]); // 初期値を空配列に設定 const handleSearchClick = () => { const queryParams = new URLSearchParams(); if (isDeleted) { queryParams.append("isDeleted", isDeleted.toString()); } if (isComplete) { queryParams.append("isComplete", isComplete.toString()); } if (taskCategoryMasterIds.length >= 1) { // 配列の要素が1つ以上あるかで配列の中身をチェック taskCategoryMasterIds.map((taskCategoryMasterId) => { queryParams.append("taskCategoryMasterId", taskCategoryMasterId.toString()); }); } navigate(`/tasks?${queryParams.toString()}`); // クエリパラメーターを含めて遷移 }; interface TaskCategoryMaster { id: string; name: string; } const taskCategoryMasters = useLoaderData<TaskCategoryMaster[]>(); const handleCheckboxChange = (id: string) => { setTaskCategoryMasterId((prevIds) => prevIds.includes(id) ? prevIds.filter((prevId) => prevId !== id) : [...prevIds, id] ); }; return ( <div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.8" }}> <div> <h2>タスク管理</h2> <div> <label> <input type="checkbox" checked={isDeleted} onChange={(e) => setIsDeleted(e.target.checked)} /> 削除済みを表示 </label> </div> <div> <label> <input type="checkbox" checked={isComplete} onChange={(e) => setIsComplete(e.target.checked)} /> 完了済みを表示 </label> </div> <div> <div>カテゴリ</div> {taskCategoryMasters.map((taskCategoryMaster: TaskCategoryMaster) => ( <label key={taskCategoryMaster.id}> <input type="checkbox" value={taskCategoryMaster.id} checked={taskCategoryMasterIds.includes(taskCategoryMaster.id)} onChange={() => handleCheckboxChange(taskCategoryMaster.id)} /> {taskCategoryMaster.name} </label> ))} </div> <button onClick={handleSearchClick}>検索する</button> </div> </div> ); }
-
app/routes/tasks-loader.ts
を下記のように修正し、複数のクエリパラメーターを受け取り、SQLのクエリに起こせるように実装app/routes/tasks-loader.tsimport type { LoaderFunctionArgs } from "@remix-run/cloudflare"; export const loader = async ({ context, request }: LoaderFunctionArgs) => { const url = new URL(request.url); const searchParams = url.searchParams; const isCompleteParam: unknown = searchParams.get("isComplete"); const isComplete: boolean = isCompleteParam === "true" ? true : false; const isDeletedParam: unknown = searchParams.get("isDeleted"); const isDeleted: boolean = isDeletedParam === "true" ? true : false; const taskCategoryMasterIdParams: string[] = searchParams.getAll("taskCategoryMasterId"); const taskCategoryMasterIds: number[] = taskCategoryMasterIdParams.map(id => Number(id)); const isTrue = 1; // フラグONの意味 マジックナンバー申し訳ない。。 try { const tasks = await context.db.tasks.findMany({ where: { ...(isComplete && { is_complete: isTrue }), ...(isDeleted && { deleted_at: {not: null}}), ...(taskCategoryMasterIds.length > 0 && { task_category_master_id: { in: taskCategoryMasterIds } }), }, }); return tasks; } catch (error) { console.error("Failed to load tasks:", error); throw new Response("Internal Server Error", { status: 500 }); } }
-
下記のように複合条件でクエリパラメーターが発行され、一覧側画面が問題なく表示されれば完了