作成日: 2023-10-21T10:16:06.982Z
前回は一通り画面を作りました。今回は編集の処理を中心に書いていきます。
このアプリも残りわずかで完成というところまで来ました。
頑張っていきましょう!!!!
編集ボタンをクリックすると、
入力することができる。この間に、チェックボックスを押すことはできない。
入力してクリックしたら編集が完了する。
チェックボックスを押すと完了タスクの方に移動する。
putTodo:"http://localhost:8080/todo/updateTodo/"
APIを叩くコードを書きます。
今回はPUTメソッドを使います。
ですが、今までやってきたコードとあまり変わりはないかなと思います。
それでは「api」フォルダのtodo.tsを開いてください。
//todo編集
export const changeTodo=async(userid:string,data:todoType)=>{
const res=await fetch(`${linkName.putTodo}${userid}`,{
method:"PUT",
headers:{
'Content-Type':'application/json'
},
body:JSON.stringify(data)
});
const resData=await res.json();
return resData.data as todoType[];
}
基本的には今までのAPIの叩き方と変わりません。
methodをPUTにして引数で受け取ったデータをbodyにして叩くコードになります。
まずはeditButtonの編集です。muiを活用しましょう。
編集中の時と編集していない時でアイコンを分けます。
さらにAPIを叩いている関数を呼び出す部分も書いています。
import EditRoundedIcon from '@mui/icons-material/EditRounded';
import DoneOutlineIcon from '@mui/icons-material/DoneOutline';
import { IconButton } from '@mui/material';
import { Dispatch, SetStateAction } from 'react';
import { todoType } from '@/shared/type';
import { changeTodo } from '@/api/todo';
interface props{
isEdit:boolean;
setIsEdit:Dispatch<SetStateAction<boolean>>;
userid:string|null;
setTodo:Dispatch<SetStateAction<todoType[]>>;
isComplete:boolean;
value:string;
todo:todoType
}
const EditButton = ({
isEdit,
setIsEdit,
userid,
setTodo,
isComplete,
value,
todo,
}:props) => {
const doneHandleClick=async()=>{
const newData:todoType={
id:todo.id,
todo:value,
checked:todo.checked,
}
const data:todoType[]=await changeTodo(userid as string,newData);
if(isComplete){
setTodo(data.filter(item=>item.checked===1));
}else{
setTodo(data.filter(item=>item.checked===0));
}
setIsEdit(false);
}
const editHandleClick=()=>{
setIsEdit(true);
}
return (
<div>
{isEdit?(
<IconButton
onClick={()=>doneHandleClick()}
disabled={value?false:true}
>
<DoneOutlineIcon/>
</IconButton>
):(
<IconButton
onClick={()=>editHandleClick()}
>
<EditRoundedIcon/>
</IconButton>
)}
</div>
);
}
export default EditButton;
編集の完了ボタンが押されたら編集中という状態を変えるだけでなくAPIを叩く関数を呼び出しています。
編集してない時の場合はボタンが押されたら状態を変えるだけでOKです。
この編集中かそうでないかはチェックボックスのコンポーネントでも使います。
チェックされたかされてないかで完了タスクに移動するかしないかを決めます。
編集中の状態も渡し、活性化にするか非活性化にするかを判断させます。
また、上記同様にAPIを叩く関数を呼び出す処理を含んだ関数を宣言します。
import { changeTodo } from "@/api/todo";
import { todoType } from "@/shared/type";
import { Checkbox } from "@mui/material";
import { Dispatch, SetStateAction } from "react";
interface props{
isEdit:boolean;
todo:todoType;
setIsComplete:Dispatch<SetStateAction<todoType[]>>;
setIsImcomplete:Dispatch<SetStateAction<todoType[]>>;
userid:string|null;
isChecked:boolean;
}
const CheckButton = ({
isEdit,
todo,
setIsComplete,
setIsImcomplete,
userid,
isChecked
}:props) => {
const handleChange=async()=>{
const newIsChecked:number=todo.checked===0?1:0;
const newTodo:todoType={
id:todo.id,
todo:todo.todo,
checked:newIsChecked
};
const data:todoType[]=await changeTodo(userid as string,newTodo);
setIsComplete(data.filter(item=>item.checked===1));
setIsImcomplete(data.filter(item=>item.checked===0));
}
return (
<div>
<Checkbox
disabled={isEdit}
onChange={()=>handleChange()}
checked={isChecked}
/>
</div>
);
}
export default CheckButton;
コードを除く感じだと今までの内容がわかっていれば難しくはないんじゃないかな?って思います。
propsが増えたのとその他の処理もちょくちょく増えたので、編集していきましょう。
おそらく開いたらエラーが吐かれているかと思います。
import { todoType } from "@/shared/type";
import styles from "./style.css";
import EditButton from "../editButton";
import CheckButton from "../checkButton";
import DeleteButton from "../deleteButton";
import { Dispatch, SetStateAction, useState } from "react";
import EditTextField from "../editTextField";
interface props{
todo:todoType;
setTodo:Dispatch<SetStateAction<todoType[]>>;
userid:string|null;
isComplete:boolean;
setIsComplete:Dispatch<SetStateAction<todoType[]>>;
setIsImcomplete:Dispatch<SetStateAction<todoType[]>>;
isChecked:boolean;
}
const TodoItem = ({
todo,
userid,
isComplete,
setTodo,
setIsComplete,
setIsImcomplete,
isChecked,
}:props) => {
const [isEdit,setIsEdit]=useState<boolean>(false);
const [inputText,setInputText]=useState<string>(todo.todo)
return (
<div className={styles.itemBox}>
<div className={styles.textbox}>
{isEdit?(
<EditTextField
value={inputText}
setValue={setInputText}
/>
):(
<p>{todo.todo}</p>
)}
</div>
<div className={styles.editButtons}>
<EditButton
isEdit={isEdit}
setIsEdit={setIsEdit}
userid={userid}
setTodo={setTodo}
isComplete={isComplete}
value={inputText}
todo={todo}
/>
<CheckButton
isEdit={isEdit}
todo={todo}
setIsComplete={setIsComplete}
setIsImcomplete={setIsImcomplete}
userid={userid}
isChecked={isChecked}
/>
<DeleteButton
/>
</div>
</div>
);
}
export default TodoItem;
編集中かそうでないかの状態変数と編集の際に書き込んだデータを保持しておく状態変数が追加されています。
この状態変数を使って文字列が何もなかったら完了ボタンは押せないようにしています。
これは、、、editButtonの時の話ですね笑
ここでまた新しくEditTextFieldというものが出てきたのでこのコンポーネントを作っていきます。
上記のフォルダを作成してコードを書いていきます。
import { TextField } from "@mui/material";
import { ChangeEvent, Dispatch, SetStateAction } from "react";
interface props{
value:string;
setValue:Dispatch<SetStateAction<string>>;
}
const EditTextField = ({value,setValue}:props) => {
const handleChange=(e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>)=>{
setValue(e.target.value);
}
return (
<TextField
id="standard-basic"
label=""
variant="standard"
value={value}
onChange={(e)=>handleChange(e)}
/>
);
}
export default EditTextField;
muiって本当に便利ですよね。
textFieldの値が変わった時に状態変数に代入するくらい処理でほとんど難しいことはしていません。
最後にtodoListの編集をしていきます。
といってもpropsが変わっただけです。(確かそうだった気がします。。。)
'use client'
import { getTodo } from "@/api/todo";
import ja from "@/shared/ja";
import { todoToggleType, todoType } from "@/shared/type";
import { Dispatch, SetStateAction, useEffect, useState } from "react";
import Imcomplete from "../isComplete";
import styles from "./style.css";
import TodoItem from "../todoItem";
import { isCmptoggleItems } from "@/shared/data";
import IsComplete from "../isComplete";
interface props{
id:string|null;
todos:todoType[];
setTodo:Dispatch<SetStateAction<todoType[]>>;
imcompleteData:todoType[];
setImcompleteData:Dispatch<SetStateAction<todoType[]>>;
completeData:todoType[];
setCompleteData:Dispatch<SetStateAction<todoType[]>>;
toggle:string;
}
const TodoList = ({
id,
todos,
setTodo,
completeData,
imcompleteData,
setCompleteData,
setImcompleteData,
toggle
}:props) => {
const [loadingMsg,setLodingMsg]=useState<string>(ja.todo.logingMsg);
const firstFunction=async(userId:string)=>{
const data:todoType[]=await getTodo(userId);
setTodo(data);
setImcompleteData(data.filter((item:todoType)=>item.checked===0));
setCompleteData(data.filter((item:todoType)=>item.checked===1));
}
useEffect(()=>{
if(id){
firstFunction(id);
setLodingMsg("");
}else{
setLodingMsg(ja.todo.logingMsg)
}
},[id])
return (
<>
{loadingMsg?(
<div>
<p>{loadingMsg}</p>
</div>
):toggle===isCmptoggleItems[0].value?(
<div className={styles.containar}>
<IsComplete
title={ja.todo.imcomplete}
isComplete={false}
numOfimCmp={imcompleteData.length}
>
{imcompleteData.map((item:todoType)=>(
<div key={item.id}>
<TodoItem
todo={item}
setTodo={setImcompleteData}
userid={id}
isComplete={false}
setIsComplete={setCompleteData}
setIsImcomplete={setImcompleteData}
isChecked={false}
/>
</div>
))}
</IsComplete>
</div>
):(
<div className={styles.containar}>
<IsComplete
title={ja.todo.complete}
isComplete={true}
numOfimCmp={completeData.length}
>
{completeData.map((item:todoType)=>(
<div key={item.id}>
<TodoItem
todo={item}
userid={id}
setTodo={setCompleteData}
isComplete={true}
setIsComplete={setCompleteData}
setIsImcomplete={setImcompleteData}
isChecked={true}
/>
</div>
))}
</IsComplete>
</div>
)}
</>
);
}
export default TodoList;
なんか足らない気がしますが、これで一応編集部分はできたはずです。
この通りにやっていってなんかエラーが出たら報告してください。。。
数時間前にこのコードを書いたのですが、まとめるのが難しいです。
というかどこからどうやって書いたっけ現象が多々起きました。
今日はこれで終わりです。次回でラストです。
todo削除。