From 868e2af9f367c18a1ef7c9818f7ff19c6a9ff2c9 Mon Sep 17 00:00:00 2001 From: psst54 Date: Thu, 5 Sep 2024 16:15:56 +0900 Subject: [PATCH 1/4] feat: define basic subject, task model --- js/index.js | 13 ++++++++++++- js/models/subject.js | 10 ++++++++++ js/models/task.js | 7 +++++++ js/viewModels/subjectViewModel.js | 14 ++++++++++++++ js/viewModels/taskViewModel.js | 0 5 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 js/models/subject.js create mode 100644 js/models/task.js create mode 100644 js/viewModels/subjectViewModel.js create mode 100644 js/viewModels/taskViewModel.js diff --git a/js/index.js b/js/index.js index 4ff0861..5029ab4 100644 --- a/js/index.js +++ b/js/index.js @@ -1 +1,12 @@ -console.log('작성 시작'); +document.addEventListener('DOMContentLoaded', () => { + const subjectViewModel = new SubjectViewModel(); + + const openSubject1 = new Subject('Opened Subject 1'); + openSubject1.addTask(new Task('task 1')); + openSubject1.addTask(new Task('task 2')); + subjectViewModel.addCard(openSubject1); + + const openSubject2 = new Subject('Opened Subject 2'); + openSubject2.addTask(new Task('task 1')); + subjectViewModel.addCard(openSubject2); +}); diff --git a/js/models/subject.js b/js/models/subject.js new file mode 100644 index 0000000..8ccf6f8 --- /dev/null +++ b/js/models/subject.js @@ -0,0 +1,10 @@ +class Subject { + constructor(title = 'New Subject') { + this.title = title; + this.taskList = []; + } + + addTask(task) { + this.taskList.push(task); + } +} diff --git a/js/models/task.js b/js/models/task.js new file mode 100644 index 0000000..d2e57b7 --- /dev/null +++ b/js/models/task.js @@ -0,0 +1,7 @@ +class Task { + constructor(title) { + this.title = title; + } + + render() {} +} diff --git a/js/viewModels/subjectViewModel.js b/js/viewModels/subjectViewModel.js new file mode 100644 index 0000000..a0bd6a9 --- /dev/null +++ b/js/viewModels/subjectViewModel.js @@ -0,0 +1,14 @@ +class SubjectViewModel { + constructor() { + this.subjectList = []; + } + + addSubject(subject) { + this.subjectList.push(subject); + this.render(); + } + + render() { + // render 로직 + } +} diff --git a/js/viewModels/taskViewModel.js b/js/viewModels/taskViewModel.js new file mode 100644 index 0000000..e69de29 From 56b80ad7c6f5d5e4f0fc3901e0a0e2ef77acd79b Mon Sep 17 00:00:00 2001 From: psst54 Date: Thu, 5 Sep 2024 16:52:41 +0900 Subject: [PATCH 2/4] feat: render subject card --- index.html | 55 ++++--------------------------- js/constant.js | 2 ++ js/index.js | 13 +++++--- js/models/subject.js | 11 ++++++- js/models/task.js | 2 -- js/viewModels/subjectViewModel.js | 26 ++++++++++++++- 6 files changed, 52 insertions(+), 57 deletions(-) create mode 100644 js/constant.js diff --git a/index.html b/index.html index cdba29c..41fab25 100644 --- a/index.html +++ b/index.html @@ -23,38 +23,7 @@

Open


- +
@@ -62,26 +31,14 @@

Done


-
    -
  • -

    Card Title 1

    -
    -
      -
    1. - -

      task 1

      -
    2. -
    3. - -

      task 2

      -
    4. -
    -
    -
  • -
+
    + + + + diff --git a/js/constant.js b/js/constant.js new file mode 100644 index 0000000..d01d417 --- /dev/null +++ b/js/constant.js @@ -0,0 +1,2 @@ +const OPEN = 'open'; +const DONE = 'done'; diff --git a/js/index.js b/js/index.js index 5029ab4..bd1c0fd 100644 --- a/js/index.js +++ b/js/index.js @@ -1,12 +1,17 @@ document.addEventListener('DOMContentLoaded', () => { const subjectViewModel = new SubjectViewModel(); - const openSubject1 = new Subject('Opened Subject 1'); + const openSubject1 = new Subject('Opened Subject 1', OPEN); openSubject1.addTask(new Task('task 1')); openSubject1.addTask(new Task('task 2')); - subjectViewModel.addCard(openSubject1); + subjectViewModel.addSubject(openSubject1); - const openSubject2 = new Subject('Opened Subject 2'); + const openSubject2 = new Subject('Opened Subject 2', OPEN); openSubject2.addTask(new Task('task 1')); - subjectViewModel.addCard(openSubject2); + subjectViewModel.addSubject(openSubject2); + + const doneSubject1 = new Subject('Done Subject 1', DONE); + doneSubject1.addTask(new Task('task 1')); + doneSubject1.addTask(new Task('task 2')); + subjectViewModel.addSubject(doneSubject1); }); diff --git a/js/models/subject.js b/js/models/subject.js index 8ccf6f8..5c81b31 100644 --- a/js/models/subject.js +++ b/js/models/subject.js @@ -1,10 +1,19 @@ class Subject { - constructor(title = 'New Subject') { + constructor(title = 'New Subject', state = OPEN) { this.title = title; this.taskList = []; + this.state = state; } addTask(task) { this.taskList.push(task); } + + getTitle() { + return this.title; + } + + getState() { + return this.state; + } } diff --git a/js/models/task.js b/js/models/task.js index d2e57b7..6eed485 100644 --- a/js/models/task.js +++ b/js/models/task.js @@ -2,6 +2,4 @@ class Task { constructor(title) { this.title = title; } - - render() {} } diff --git a/js/viewModels/subjectViewModel.js b/js/viewModels/subjectViewModel.js index a0bd6a9..2709a7f 100644 --- a/js/viewModels/subjectViewModel.js +++ b/js/viewModels/subjectViewModel.js @@ -9,6 +9,30 @@ class SubjectViewModel { } render() { - // render 로직 + const columnList = [OPEN, DONE]; + + columnList.forEach((column) => { + const subjectListElement = document.getElementById( + `${column}-subject-list` + ); + subjectListElement.innerHTML = ''; + + this.subjectList.forEach((subject) => { + if (subject.getState() !== column) return; + + const subjectElement = document.createElement('li'); + subjectElement.classList.add('card'); + subjectElement.innerHTML = ` +
    +

    ${subject.getTitle()}

    +
    +
    +
      +
    +
    + `; + subjectListElement.appendChild(subjectElement); + }); + }); } } From 5e17bce280aea2049a44989be50ddddfef90ecb3 Mon Sep 17 00:00:00 2001 From: psst54 Date: Thu, 5 Sep 2024 22:47:36 +0900 Subject: [PATCH 3/4] feat: render subject tasks --- index.html | 1 + js/index.js | 13 +++++++------ js/models/subject.js | 9 +++++++++ js/models/task.js | 7 ++++++- js/viewModels/subjectViewModel.js | 25 +++++++++++++++++++++++-- js/viewModels/taskViewModel.js | 17 +++++++++++++++++ 6 files changed, 63 insertions(+), 9 deletions(-) diff --git a/index.html b/index.html index 41fab25..bfcfe3a 100644 --- a/index.html +++ b/index.html @@ -40,5 +40,6 @@

    Done

    + diff --git a/js/index.js b/js/index.js index bd1c0fd..273f474 100644 --- a/js/index.js +++ b/js/index.js @@ -1,17 +1,18 @@ document.addEventListener('DOMContentLoaded', () => { - const subjectViewModel = new SubjectViewModel(); + const taskViewModel = new TaskViewModel(); + const subjectViewModel = new SubjectViewModel(taskViewModel); const openSubject1 = new Subject('Opened Subject 1', OPEN); - openSubject1.addTask(new Task('task 1')); - openSubject1.addTask(new Task('task 2')); + taskViewModel.addTask('task 1', openSubject1.getId()); + taskViewModel.addTask('task 2', openSubject1.getId()); subjectViewModel.addSubject(openSubject1); const openSubject2 = new Subject('Opened Subject 2', OPEN); - openSubject2.addTask(new Task('task 1')); + taskViewModel.addTask('task 1', openSubject2.getId()); subjectViewModel.addSubject(openSubject2); const doneSubject1 = new Subject('Done Subject 1', DONE); - doneSubject1.addTask(new Task('task 1')); - doneSubject1.addTask(new Task('task 2')); + taskViewModel.addTask('task 1', doneSubject1.getId()); + taskViewModel.addTask('task 2', doneSubject1.getId()); subjectViewModel.addSubject(doneSubject1); }); diff --git a/js/models/subject.js b/js/models/subject.js index 5c81b31..23efc1c 100644 --- a/js/models/subject.js +++ b/js/models/subject.js @@ -3,6 +3,7 @@ class Subject { this.title = title; this.taskList = []; this.state = state; + this.id = Math.random().toString(36).substring(2); // [todo] make random id function } addTask(task) { @@ -16,4 +17,12 @@ class Subject { getState() { return this.state; } + + getTaskList() { + return this.taskList; + } + + getId() { + return this.id; + } } diff --git a/js/models/task.js b/js/models/task.js index 6eed485..ea37578 100644 --- a/js/models/task.js +++ b/js/models/task.js @@ -1,5 +1,10 @@ class Task { - constructor(title) { + constructor(title, subjectId) { this.title = title; + this.subjectId = subjectId; + } + + getTitle() { + return this.title; } } diff --git a/js/viewModels/subjectViewModel.js b/js/viewModels/subjectViewModel.js index 2709a7f..89f1ee9 100644 --- a/js/viewModels/subjectViewModel.js +++ b/js/viewModels/subjectViewModel.js @@ -1,6 +1,7 @@ class SubjectViewModel { - constructor() { + constructor(taskViewModel) { this.subjectList = []; + this.taskViewModel = taskViewModel; } addSubject(subject) { @@ -18,6 +19,8 @@ class SubjectViewModel { subjectListElement.innerHTML = ''; this.subjectList.forEach((subject) => { + const subjectId = subject.getId(); + const taskListElementId = `${subjectId}-task-list`; if (subject.getState() !== column) return; const subjectElement = document.createElement('li'); @@ -27,12 +30,30 @@ class SubjectViewModel {

    ${subject.getTitle()}

    -
      +
    `; subjectListElement.appendChild(subjectElement); + + const taskListElement = document.getElementById(taskListElementId); + this.renderTasks(subjectId, taskListElement); }); }); } + + renderTasks(subjectId, taskListElement) { + this.taskViewModel.getTasksBySubject(subjectId).forEach((task) => { + const taskElement = document.createElement('li'); + taskElement.className = 'task'; + const checkboxElement = document.createElement('input'); + checkboxElement.type = 'checkbox'; + const titleElement = document.createElement('p'); + titleElement.innerText = task.getTitle(); + + taskElement.appendChild(checkboxElement); + taskElement.appendChild(titleElement); + taskListElement.appendChild(taskElement); + }); + } } diff --git a/js/viewModels/taskViewModel.js b/js/viewModels/taskViewModel.js index e69de29..48b2a2b 100644 --- a/js/viewModels/taskViewModel.js +++ b/js/viewModels/taskViewModel.js @@ -0,0 +1,17 @@ +class TaskViewModel { + constructor() { + this.taskList = new Map(); + } + + addTask(title, subjectId) { + const task = new Task(title, subjectId); + if (!this.taskList.has(subjectId)) { + this.taskList.set(subjectId, []); + } + this.taskList.get(subjectId).push(task); + } + + getTasksBySubject(subjectId) { + return this.taskList.get(subjectId) || []; + } +} From 7c45c22412c98c19afc7ee9075f50b6c8f7c47d1 Mon Sep 17 00:00:00 2001 From: psst54 Date: Thu, 5 Sep 2024 22:48:53 +0900 Subject: [PATCH 4/4] docs: edit terms --- todo.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/todo.md b/todo.md index c35f4fa..34bb4ce 100644 --- a/todo.md +++ b/todo.md @@ -4,14 +4,14 @@ | -------- | ---------------------------------- | ----------------------------------- | | high | **기본 레이아웃** | 헤더, column(open, done) 배치 | | | | CSS 스타일 적용 | -| high | **데이터 구조 작성** | 카드 및 태스크 class 정의 | -| high | **카드 추가** | 카드 추가 버튼과 모달 구현 | -| | | 카드 추가 버튼 이벤트 핸들러 작성 | -| high | **카드 삭제** | 카드 삭제 버튼 구현 | -| | | 카드 삭제 버튼 이벤트 핸들러 작성 | -| high | **카드 상태 토글** | 카드 완료 체크박스 추가 | -| | | 카드 상태에 따른 스타일 변경 | -| | | 카드 상태 변경 이벤트 핸들러 작성 | +| high | **데이터 구조 작성** | 목표 및 태스크 class 정의 | +| high | **목표 추가** | 목표 추가 버튼과 모달 구현 | +| | | 목표 추가 버튼 이벤트 핸들러 작성 | +| high | **목표 삭제** | 목표 삭제 버튼 구현 | +| | | 목표 삭제 버튼 이벤트 핸들러 작성 | +| high | **목표 상태 토글** | 목표 완료 체크박스 추가 | +| | | 목표 상태에 따른 스타일 변경 | +| | | 목표 상태 변경 이벤트 핸들러 작성 | | high | **태스크 추가** | 태스크 input 필드 구현 | | | | submit 이벤트 핸들러 작성 | | high | **태스크 삭제** | 태스크 삭제 버튼 구현 |