TERUSIの技術勉強まとめ(コーディング編)

編集部分の作成

作成日: 2023-10-21T10:16:06.982Z

はじめに

前回は一通り画面を作りました。今回は編集の処理を中心に書いていきます。
このアプリも残りわずかで完成というところまで来ました。
頑張っていきましょう!!!!

完成イメージ


編集ボタンをクリックすると、

入力することができる。この間に、チェックボックスを押すことはできない。
入力してクリックしたら編集が完了する。

チェックボックスを押すと完了タスクの方に移動する。

実装開始

1 リンクファイルにリンクを追加

putTodo:"http://localhost:8080/todo/updateTodo/"

2 apiを叩くコードを作成

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にして叩くコードになります。

3 editButtonの編集

まずは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です。
この編集中かそうでないかはチェックボックスのコンポーネントでも使います。

4 checkButtonの編集

チェックされたかされてないかで完了タスクに移動するかしないかを決めます。
編集中の状態も渡し、活性化にするか非活性化にするかを判断させます。
また、上記同様に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;

コードを除く感じだと今までの内容がわかっていれば難しくはないんじゃないかな?って思います。

5 todoItemの編集

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というものが出てきたのでこのコンポーネントを作っていきます。

6 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の値が変わった時に状態変数に代入するくらい処理でほとんど難しいことはしていません。

7 todoListの編集

最後に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削除。