1
0
mirror of https://github.com/morris/vanilla-todo.git synced 2025-08-20 12:51:43 +02:00

refactor for pure functional business logic

This commit is contained in:
Morris Brodersen
2023-11-30 11:42:02 +01:00
parent 2815a1eb4c
commit dd8dc8c4af
15 changed files with 449 additions and 252 deletions

212
public/scripts/TodoLogic.js Normal file
View File

@@ -0,0 +1,212 @@
import { formatDateId } from './util.js';
import { uuid } from './uuid.js';
export class TodoLogic {
static initTodoData(now = new Date()) {
return {
items: [],
customLists: [],
at: formatDateId(now),
customAt: 0,
};
}
static getTodoListsByDay(data, range) {
const listsByDay = [];
for (let i = 0; i < 2 * range; ++i) {
const t = new Date(data.at);
t.setDate(t.getDate() - range + i);
const id = formatDateId(t);
listsByDay.push({
id,
items: TodoLogic.getTodoItemsForList(data, id),
position: -range + i,
});
}
return listsByDay;
}
static getTodoItemsForList(data, listId) {
return data.items
.filter((item) => item.listId === listId)
.sort((a, b) => a.index - b.index);
}
static addTodoItem(data, input) {
let index = 0;
for (const item of data.items) {
if (item.listId === input.listId) {
index = Math.max(index, item.index + 1);
}
}
return {
...data,
items: [
...data.items,
{
...input,
id: uuid(),
index,
done: false,
},
],
};
}
static checkTodoItem(data, input) {
return {
...data,
items: data.items.map((item) =>
item.id === input.id ? { ...item, done: input.done } : item,
),
};
}
static editTodoItem(data, input) {
return {
...data,
items: data.items.map((item) =>
item.id === input.id ? { ...item, label: input.label } : item,
),
};
}
static moveTodoItem(data, input) {
const itemToMove = data.items.find((item) => item.id === input.id);
// Reinsert item at target list and index
let list = data.items.filter(
(item) => item.listId === input.listId && item.id !== input.id,
);
list.splice(input.index, 0, { ...itemToMove, listId: input.listId });
list = TodoLogic.setIndexes(list);
// Reinsert updated list
let items = data.items.filter(
(item) => item.listId !== input.listId && item.id !== input.id,
);
items = [...items, ...list];
return {
...data,
items,
};
}
static deleteTodoItem(data, input) {
return {
...data,
items: data.items.filter((item) => item.id !== input.id),
};
}
//
static getCustomTodoLists(data) {
return data.customLists
.map((list) => ({
id: list.id,
index: list.index,
title: list.title,
items: TodoLogic.getTodoItemsForList(data, list.id),
}))
.sort((a, b) => a.index - b.index);
}
static addCustomTodoList(data) {
let index = 0;
for (const customList of data.customLists) {
index = Math.max(index, customList.index + 1);
}
return {
...data,
customLists: [
...data.customLists,
{
id: uuid(),
index,
title: '',
},
],
};
}
static editCustomTodoList(data, input) {
return {
...data,
customLists: data.customLists.map((customList) =>
customList.id === input.id
? { ...customList, title: input.title }
: customList,
),
};
}
static moveCustomTodoList(data, input) {
const customListToMove = data.customLists.find(
(customList) => customList.id === input.id,
);
let customLists = data.customLists
.filter((customList) => customList.id !== input.id)
.sort((a, b) => a.index - b.index);
customLists.splice(input.index, 0, customListToMove);
customLists = TodoLogic.setIndexes(customLists);
return {
...data,
customLists,
};
}
static deleteCustomTodoList(data, input) {
return {
...data,
customLists: data.customLists.filter(
(customList) => customList.id !== input.id,
),
};
}
//
static seekDays(data, delta) {
const t = new Date(`${data.at}T00:00:00`);
t.setDate(t.getDate() + delta);
return { ...data, at: formatDateId(t) };
}
static seekToToday(data) {
return { ...data, at: formatDateId(new Date()) };
}
static seekToDate(data, date) {
return { ...data, at: formatDateId(date) };
}
static seekCustomTodoLists(data, delta) {
return {
...data,
customAt: Math.max(
0,
Math.min(data.customLists.length - 1, data.customAt + delta),
),
};
}
//
static setIndexes(array) {
return array.map((item, index) =>
item.index === index ? item : { ...item, index },
);
}
}