내가 한 노력들

[ Laravel + Vue.js ] 나만의 To Do List 만들기 - D-Day계산 / 중요 관리 본문

IT 공부/Laravel

[ Laravel + Vue.js ] 나만의 To Do List 만들기 - D-Day계산 / 중요 관리

JONGI-N CHOI 2021. 8. 30. 18:49

To Do를 보여주는 부분에 대한 기능 구현에 대한 부분 설명

 

저번글에서는 DB에서 Data를 받아서 title이름을 보여주는 것 까지 했었다.

 

 

D-Day 계산 

우측 하단에 D-Day를 보여주는 란이 있다. 

Deadline이 설정되었을 때, 현재 날짜에서 Deadline까지 남은 날짜를 계산해서 보여주는 것, 만약에 Deadline을 설정하지 않았을 경우에는 Deadline을 설정해달라는 문구가 나오도록 했다.

 

 

우선 들어가기전에 JS에서 날짜를 받아오는 방법

import dayjs from 'dayjs'

const today = dayjs().format("YYYY-MM-DD"); //오늘 날짜를 출력

 

날짜를 초로 변경하는 법

 const todaySec = new Date(today[0], today[1], today[2]).getTime();

 

위의 두가지 방법을 이용해서 Deadline 날짜를 시간초로 변경, 현재 날짜를 시간초로 변경해서 그 값을 빼줍니다.

그러면, 그 시간초의 차이를 구할 수 있고 그 값을 다시 날짜 단위로 변경하게 되면, 남은 일 수를 구할 수 있습니다.

 

data(){
        const today = dayjs().format("YYYY-MM-DD").split('-').map(str => Number(str));
        const deadline = dayjs().format(this.toDo.deadline).split('-').map(str => Number(str));
        
        return {
            today: new Date(today[0], today[1], today[2]).getTime(),
            deadline: new Date(deadline[0], deadline[1], deadline[2]).getTime(),
            elapsedDay: '',
            //
        }
    },

    created() {
        const elapsedMSec = this.deadline - this.today;
        this.elapsedDay = elapsedMSec / 1000 / 60 / 60 / 24;
    },

data에서 우선 오늘날짜와,  deadline의 날짜를 변수에 저장하고 초로 변경을합니다.

 

그 값을 가지고 created에서 계산을 해서 D-Day로 변경하는 코드입니다.

 

<div>
        <div                    
            class="grid grid-cols-6 border-2 rounded hover:bg-gray-400 my-2"     
        >
            <div class="col-span-5 p-2" :style="hiddenText" @click="onClickToDetail(toDo.id)" :class="{ Done : !mode }">{{ toDo.title }}</div>
            <div class="col-span-1 pl-20" >
                <svg v-if="!IsImportant" @click="changeImportant(toDo.id)" xmlns="http://www.w3.org/2000/svg" width="45" height="45" viewBox="-25 -25 100 100"><path d="M48.856 22.731a3.56 3.56 0 00.906-3.671 3.56 3.56 0 00-2.892-2.438l-12.092-1.757a1.58 1.58 0 01-1.19-.865L28.182 3.043a3.56 3.56 0 00-3.212-1.996 3.56 3.56 0 00-3.211 1.996L16.352 14c-.23.467-.676.79-1.191.865L3.069 16.623A3.557 3.557 0 00.178 19.06a3.56 3.56 0 00.906 3.671l8.749 8.528c.373.364.544.888.456 1.4L8.224 44.702a3.559 3.559 0 001.424 3.502 3.552 3.552 0 003.772.273l10.814-5.686a1.583 1.583 0 011.472 0l10.815 5.686a3.568 3.568 0 003.772-.273 3.559 3.559 0 001.424-3.502L39.651 32.66a1.582 1.582 0 01.456-1.4l8.749-8.529zM37.681 32.998l2.065 12.042a1.553 1.553 0 01-.629 1.547 1.558 1.558 0 01-1.665.121l-10.815-5.687a3.588 3.588 0 00-3.334.001L12.49 46.708a1.56 1.56 0 01-1.666-.121 1.554 1.554 0 01-.629-1.547l2.065-12.042a3.581 3.581 0 00-1.03-3.17l-8.75-8.529a1.55 1.55 0 01-.4-1.621c.19-.586.667-.988 1.276-1.077l12.091-1.757a3.576 3.576 0 002.697-1.959l5.407-10.957a1.551 1.551 0 011.418-.881c.616 0 1.146.329 1.419.881l5.407 10.957a3.575 3.575 0 002.696 1.959l12.092 1.757a1.552 1.552 0 011.276 1.077c.19.585.041 1.191-.4 1.621l-8.749 8.528a3.58 3.58 0 00-1.029 3.171z"/></svg>
                <svg v-else @click="changeImportant(toDo.id)" width="45" height="45" viewBox="-12.5 -12.5 45 45" xmlns="http://www.w3.org/2000/svg"><path d="M23.363 8.584l-7.378-1.127L12.678.413c-.247-.526-1.11-.526-1.357 0L8.015 7.457.637 8.584c-.606.093-.848.83-.423 1.265l5.36 5.494-1.267 7.767c-.101.617.558 1.08 1.103.777L12 20.245l6.59 3.643c.54.3 1.205-.154 1.103-.777l-1.267-7.767 5.36-5.494c.425-.436.182-1.173-.423-1.266z" fill="#ffc107"/></svg>
            </div>
            <!-- <span>{{ toDo.deadline !== null ? toDo.deadline : undefined_deadline }}</span> -->
            <div class="col-span-6 text-end p-2" @click="onClickToDetail(toDo.id)">{{ mode ? printDDay() : "Done"}}</div>
        </div>
    </div>

위의 코드가 현재 To Do를 보여주는 부분이 Template 코드

 

 

<div class="col-span-6 text-end p-2" @click="onClickToDetail(toDo.id)">{{ mode ? printDDay() : "Done"}}</div>

위의 코드는 D-Day부분을 담당하는 코드

 

mode 변수란 것을 이용해서 true일 경우에는 함수 printDDay라는 함수를 실행, false일 때는, "Done"이라는 문자를 표시

 

 

printDDay() {
            this.toDo.deadline !== null  ? `D - ${this.elapsedDay}` :  "時間を設定してください。";
            if ( this.toDo.deadline !== null ) {
                if ( this.elapsedDay < 0 ) {
                    return "Deadlineがもう過ぎました。";
                } else {
                    return `D - ${this.elapsedDay}`;
                }
            } else {
                return "Deadlineを設定してください。";
            }            
        },

위의 코드가 printDDay함수

 

if문을 이용해서 Deadline가 설정되어 있을 경우, if문을 한번 더 사용합니다.

그 이유는, D-Day의 값이 0보다 작을 경우에는 이미 마감일을 지나버렸기 때문에, 마감일이 지났다는 문구를 보여주기 위해서입니다. 

0보다 크거나 같을 때에는 D-Day값을 보여줍니다.

 

그리고, Deadline이 설정되어 있지 않을 경우에는, Deadline을 설정해달라는 문구를 보여줍니다. 

 

 


중요표시 

리스트를 확인해봤을 떄, 중요표시 한 것은 노랑색 별표 모양, 중요표시를 안한 것은 색이없는 별모양을 확인할 수 있습니다. 

 

우선, 노랑색 별문양의 svg파일과 , 색이없는 별문양의 이미지를 두개 준비합니다. 

 

방법은 간단

 

v-if를 이용해서, DB에 중요 체크가 되어있는지 안되어있는지를 확인해서 상황에 맞는 svg 이미지를 보여주면 됨

 

migration파일

Schema::create('to_do_lists', function (Blueprint $table) {
            $table->boolean('important_is')->default(0);
			//
        });

migration을 보면, important_is라는 속성으로 boolean타입으로 1일 떈, 중요상태 / 0일 땐 중요하지 않은 상태로 구분

 

data(){
        return {
            IsImportant: this.toDo.important_is,
        }
    },

DB에서 받아온 To Do의 important_is값을 IsImportant라는 변수에 넣어서 사용합니다.

 

<div class="col-span-1 pl-20" >
	<svg v-if="!IsImportant" @click="changeImportant(toDo.id)"> //생략
    <svg v-else @click="changeImportant(toDo.id)"> //생략
 </div>

v-if="IsImportant" 해서 현재 1(true)일땐 노랑색 별모양 svg태그 

0(false)일 땐, 텅빈 별모양이 보이도록

 

 

중요 설정

그리고 별모양을 클릭하면, 중요표시를 풀었다가 설정했다가 할 수 있다.

 

그것은 @Click을 사용 

 

<svg v-else @click="changeImportant(toDo.id)"> //생략

위의 svg태그를 보면 @Click 이벤트를 이용해서 changeImportant()함수를 실행시키는 것을 확인 가능

 

 

changeImportant(id) {
            axios.get('api/todo/important', {
                params: {
                    id: id
                }
            }).then(res => {
                this.IsImportant = res.data.ToDoList.important_is;
                this.$emit('reGetList');
            })
        },

changeImportant 함수는 axios.get을 이용합니다. 

 

api,php

Route::get('/todo/important', [ToDoListController::class, 'important']);

axios 통신을 통해서 ToDoListController의 important 함수를 실행합니다.

 

 

ToDoListController.php

public function important() {
        $ToDoList = ToDoList::find(request('id'));
        $ToDoList->important_is = !($ToDoList->important_is);
        $ToDoList->save();

        return response()->json([
            'ToDoList' => $ToDoList
        ], 200);
    }

important함수에서는 axios에서 params로 받아온 id를 이용해서, ToDoList 테이블에서 id값을 이용해서 Data를 받아옵니다.

 

그래서, 그 데이터의 important_is값을 !연산자를 이용해서, boolean을 변경합니다. 

그리고 save()저장을 하고, json으로 다시 response를 해줍니다.

 

changeImportant(id) {
            axios.get('api/todo/important', {
                params: {
                    id: id
                }
            }).then(res => {
                this.IsImportant = res.data.ToDoList.important_is;
                this.$emit('reGetList');
            })
        },

그러면, axios에서 통신을 성공을하고 then부분의 코드가 실행이 되는데

 

IsImportant변수에 변경된 내용을 다시 최신화해주고 

 

$emit을 이용해서 부모 컴포넌트에 알립니다. 

 

reGetList() {
            this.getResult(1, this.categoryStatus);
        },

reGetList()함수는 다시 데이터를 불러오는 겁니다.

 

그래서, important정보가 변경될 때마다, 새롭게 데이터를 받아와서 최신화 합니다. 

 

$list_arr = ToDoList::where('completion_is', request('currentState'))->orderBy('important_is', 'DESC')->orderBy('id', 'ASC')->paginate(5);

DB에서 Data를 받아올 때에는 orderBy를 이용해서 항상 important_is 속성을 내림차순으로 가져오기 때문에, 

중요표시한 것을 위에 위치하도록 가져오게 됨

 

 

그러면 이젠 별표시를 누를 때마다, 자동적으로 해당 To Do가 위로 업로드되게 됩니다.