¡Te damos la bienvenida a este reto!

1

¡Bienvenido al mundo de JavaScript!

Día 1

2

Variables, funciones y sintaxis básica

3

Tipos de datos

4

Playground - Retorna el tipo

5

Tipos de datos - pt 2

Día 2

6

Operadores

7

Hoisting y coerción

8

Playground - Calcula la propina

9

Alcance de las variables

Día 3

10

Condicionales

11

Playground - Calcula años bisiestos

12

Switch

13

Playground - Obten información de mascotas según su tipo

14

Ciclos

15

Playground - Dibuja un triangulo

Día 4

16

Arrays

17

Playground - Encuentra al michi mas famoso

18

Objetos

19

Playground - Obten el promedio de los estudiantes

Día 5 - Checkpoint

20

Playground - encuentra el palindromo más grande

Día 6

21

Reasignación y redeclaración

22

Modo estricto

Día 7

23

Debugging y manejo de errores

24

Programación funcional

Quiz: Día 7

Día 8

25

Closures

26

Playground - Crea una calculadora con closures

27

Higher order functions

28

Playground - Crea tu propio método map

Día 9

29

ECMAScript

30

TC39

Quiz: Día 9

Día 10 - Checkpoint

31

ES6

32

ES7

33

Playground - Task planner

Día 11

34

Asincronismo

35

Playground - Promesas

36

Manejando el asincronismo

37

Playground - Resuelve el callback hell usando promesas

38

Playground - Resuelve el callback hell usando async/await

Día 12

39

Arrays a profundidad

40

Métodos de arrays: Every, Find y findIndex

41

Playground - Válida el formulario

Día 13

42

Métodos de arrays: Includes, Join y concat

43

Playground - agrupa los productos

44

Métodos de arrays: Flat y FlatMap

45

Playground - Encuentra la ubicación del valor buscado

Día 14

46

Mutable functions

47

Playground - Modifica una lista de compras

48

Métodos de arrays: sort

49

Playground - Ordena los productos

Día 15 - Checkpoint

50

Playground - Sistema de reservaciones de un hotel

Día 16

51

Programación orientada a objetos en JavaScript

52

Objetos literales

53

Playground - Congela el objeto recursivamente

Día 17

54

Prototipos en JavaScript

55

Playground - Modifica el prototype de los arrays

56

Playground - Crea un auto usando clases

Día 18

57

Abstracción en JavaScript

58

Playground - Sistema de carrito de compras

59

Encapsulamiento en JavaScript

60

Playground - Encapsula datos de los usuarios

Día 19

61

Herencia en JavaScript

62

Playground - Jerarquía de animales

63

Polimorfismo en JavaScript

64

Playground - Sistema de pagos

Día 20 - Checkpoint

65

Playground - Agenda de vuelos

Día 21

66

Patrones de diseño

67

Sinlgeton y Factory pattern en JavaScript

68

Playground - Implementa singleton en un chat

Día 22

69

Adapter y Decorator pattern en JavaScript

70

Playground - Personaliza productos de una tienda

71

Builder y Protype pattern en JavaScript

72

Playground - Mejora el código usando builder pattern

Día 23

73

Facade y proxy pattern en JavaScript

74

Playground - Proxy en servicio de mensajería

75

Chain of responsability y Observer pattern en JavaScript

76

Playground - Implementación de Observador en Newsletter

Día 24 - Checkpoint

77

Playground - Crea un task manager con patrones de diseño

Día 25

78

Estructuras de datos en JavaScript

79

Playground - Crea tu propia implementación de un array

80

Hash tables en JavaScript

81

Playground - Implementación de una HashTable para Contactos

Día 26

82

Set en JavaScript

83

Playground - Remueve duplicados de una lista

84

Maps en JavaScript

85

Playground - Crea un organizador de tareas

Día 27

86

Singly Linked List en JavaScript

87

Playground - Agrega métodos a la singly linked list

88

Playground - Implementación de una singly linked list

Día 28

89

Stacks en JavaScript

90

Playground - Crea un stack para una playlist

Día 29

91

Queues en JavaScript

92

Playground - Crea una cola de emails

Día 30

93

¡Lo lograste!

Live Class

94

30 días de JS con Juan DC

95

30 días de JS con Nicobytes

96

30 días de JS con GNDX

97

30 días de JS con LeoCode

98

30 días de JS con Teffcode

99

Sesión: Cierre de los 30 días de JavaScript

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

No se trata de lo que quieres comprar, sino de quién quieres ser. Invierte en tu educación con el precio especial

Antes: $249

Currency
$209

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Suscríbete

Termina en:

11 Días
19 Hrs
3 Min
26 Seg

Playground - Task planner

33/99

Aportes 74

Preguntas 4

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

🛡️🛡️Escudo anti-spoiler🛡️🛡️

/
Quiero darte la bienvenida a tu segundo checkpoint, este desafío que incluye un grado más alto de dificultad. Al ser una semana relativamente teórica hemos preparado un ejercicio no tan difícil 😉
/
Esperamos que lo disfrutes y pongas a prueba tus conocimientos, sin más, te dejo con un gif aleatorio para después explicarte la solución propuesta ¡Buena suerte!
/

/
Esta explicación va a llevar un rato, espero no te pierdas

export function createTaskPlanner() {
  // Empezamos con un array vacío
  // aquí almacenaremos las tareas
  let tasks = [];

  // retornamos las funciones 
  // que servirán para manipular el array
  return {
    // La función de agregar tareas debe recibir una tarea
    addTask(task) {
      // Por lógica al añadir una nueva tarea inicia sin estar completada
      task.completed = false;
      // Una vez modificada la enviamos al array
      tasks.push(task);
    },

    //  Ahora la función para remover tareas
    removeTask(value) {
       // Dependiendo si el valor es un número o un string
      if (typeof value === "number") {
        // Si es un número, filtramos todas las tareas que no tengan el mismo valor
        //  y luego lo reasignamos al array de tareas
        tasks = tasks.filter((task) => task.id !== value);
      } else {
        // En caso de ser un string, hacemos lo mismo pero con la propiedad de .name
        tasks = tasks.filter((task) => task.name !== value);
      }
    },

    // Para obtener las tareas simplemente las retornamos
    getTasks() {
      return tasks;
    },

     // Para obtener las tareas pendientes o completadas simplemente las filtramos
    // y retornamos el resultado
    getPendingTasks() {
      return tasks.filter((task) => !task.completed);
    },

    getCompletedTasks() {
      return tasks.filter((task) => task.completed);
    },

    // Para marcar una tarea dependiendo el valor recibido
    markTaskAsCompleted(value) {
      // primero declaramos la variable de index
      // la cual tendrá el indice de la posición del elemento
      let index;

     // buscamos el indice dependiendo el valor
      if (typeof value === "number") {
        // buscamos por index dependiendo si es por id
        index = tasks.findIndex((task) => task.id === value);
      } else {
        // O por name
        index = tasks.findIndex((task) => task.name === value);
      }

      // Al final con ese indice modificamos la propiedad de completed a true
      tasks[index].completed = true;
    },

    getSortedTasksByPriority() {
      // Para ordenar las tareas sin modificar el array original
     // solamente hacemos una copia del array y ejecutamos sort sobre este
      const sortedTasks = [...tasks].sort((a, b) => a.priority - b.priority);
      // Al final lo retornamos
      return sortedTasks;
    },

    filterTasksByTag(tag) {
      // Filtramos las tareas que incluyan cierto tag
      return tasks.filter((task) => task.tags.includes(tag));
    },

    updateTask(taskId, updates) {
     
      // obtenemos el id como lo hicimos previamente
      const index = tasks.findIndex((task) => task.id === taskId);
      // agregamos las propiedades extras destructurando ambos objetos
      tasks[index] = { ...tasks[index], ...updates };
    },
  };
}

Un checkpoint un tanto más amplio para seguir practicando 💪
¿Y tu? ¿Cómo lo hiciste?

Solución… 😄
.
Para comenzar, creamos un array de tareas vacía. Posteriormente realizamos las función correspondientes del reto.
.
En ‘addTask’ simplemente agregamos la propiedad completed al hacer:
.

task.completed = false;

.
Puesto que si la propiedad no existe, al asignarla de esa manera se le añade dinámicamente. Luego añadimos la tarea al array de tarea.
.
En ‘removeTask’ utilizamos la función splice:
.

tasks.splice(
      tasks.findIndex((task) => task.id == value || task.name === value),
      1);

.
Esta función recibe 2 parámetro, la primera es la posición desde donde queremos eliminar elementos de un array, y la segunda es la cantidad de elementos que queremos eliminar, en este caso 1.
.
Es por ello que utilizamos la función findIndex() para encontrar la tarea que tenga el value igual al id o al name de la tarea.
.

tasks.findIndex((task) => task.id == value || task.name === value), 1);

.
‘getTask’ solo retorna el array de tareas. ‘getPendingTask’ y ‘getCompletedTask’ utilizan la función filter() para devolver las tareas que tengan la propiedad completed en el estado correspondiente.
.
Para ‘markTaskAsCompleted’ guardamos en una variable el resultado de buscar la tarea por su id o name mediante la función find(). Si la tarea existe lo marcamos como completado accediendo a la propiedad completed cambiandolo a true.
.
‘getSortedTasksByPriority’ utiliza la función sort() en el cual ordenamos las tareas según su prioridad, de menor a mayor. Es importante hacer una copia del array para no alterar al array original, por lo que utilizamos […NombreDelArray] para ello.
.
‘filterTasksByTag(tag)’ utiliza filter() donde accedemos a la propiedad tags para encontrar una coincidencia, (siendo tags un array) mediante la función include() .
.
‘updateTask’ actuamos de forma similar a ‘markTaskAsCompleted’ pero para pasar las propiedades que queremos cambiar ‘updates’ a la tarea encontrada, debemos utilizar Object.assign().
.
Object.assign() tiene 2 parametro, el primero es el objeto al que queremos cambiar sus propiedades, y el segundo son las propiedades que queremos cambiar.
.
Por ejemplo si update fuera {id: 4, name: “Pedro”} en task o la tarea solo se cambiarían esas propiedades, las demás (priority, tags y completed) no cambian.
.
Finalmente, retornamos un objeto con el nombre de las funciones implementadas.
.
Código:
.

export function createTaskPlanner() {
  // Array de todas las tareas
  let tasks = [];

  // Añadimos una tarea al array de tareas
  function addTask(task) {
    task.completed = false;
    tasks.push(task);
  }

  /* Removemos una tarea a partir del índice del
  elemento que coincida en name o id con value */
  function removeTask(value) {
    tasks.splice(
      tasks.findIndex((task) => task.id == value || task.name === value),
      1
    );
  }

  // Retornamos el array de tareas 
  function getTasks() { 
    return tasks;
  }

  /* Filtramos y retornamos las tareas que tengan
  la propiedad completed false */
  function getPendingTasks() {
    return tasks.filter((task) => !task.completed);
  }

  /* Filtramos y retornamos las tareas que tengan
  la propiedad completed true */
  function getCompletedTasks() {
    return tasks.filter((task) => task.completed);
  }

  /* Encontramos la tarea que queremos marcar como
  competado, si existe la propiedad completed
  será igual a true */
  function markTaskAsCompleted(value) {
    let task = tasks.find((task) => task.id == value || task.name === value);
    if (task) { 
      task.completed = true;
    }
  }

  // Ordenamos y retornamos el array de tareas ordenado
  function getSortedTasksByPriority() {
    return [...tasks].sort((a, b) => a.priority - b.priority);
  }

  // Filtramos las tareas por tag
  function filterTasksByTag(tag) { 
    return tasks.filter((task) => task.tags.includes(tag));
  }

  /* Actualizamos las propiedades de updates con la
  tarea que coincida con taskId */
  function updateTask(taskId, updates) { 
    let task = tasks.find((task) => task.id == taskId);
    if (task) {
      Object.assign(task, updates);
    }
  }

  return {
    addTask,
    removeTask,
    getTasks,
    getPendingTasks,
    getCompletedTasks,
    markTaskAsCompleted,
    getSortedTasksByPriority,
    filterTasksByTag,
    updateTask
  }
}

Uno difícil, estuvo largo pero interesante.
Al momento de hacer la prueba, sortTasksByPriority() es en realidad getSortedTasksByPriority(), ya lo están corrigiendo.
.
.
.
.
.
.
.
spoilers:

<export function createTaskPlanner() {
    let taskArray = [];

    return {
        addTask: (task) => {
            task.completed = false, taskArray.push(task)
        },
        
        removeTask: (value) => {taskArray.forEach((ele, ind) => {
            if(ele.id === value || ele.name === value){
                taskArray.splice(ind, 1)
            }  
        })},
        
        getTasks: () => {return taskArray},
        
        getPendingTasks: () => {
            return taskArray.filter((ele) => !ele.completed)
        },
        
        getCompletedTasks: () => {
            return taskArray.filter((ele) => ele.completed)
        },
        
        markTaskAsCompleted: (value) => {taskArray.forEach((ele, ind) => {
            if(ele.id === value || ele.name === value){
                return ele.completed = true
            }
        })},
        
        //sortTasksByPriority()
        getSortedTasksByPriority: () => {
            const sortedArray = [...taskArray]
            .sort((a, b) => a.priority - b.priority);
            return sortedArray
        },
        
        filterTasksByTag: (tag) => {
            return taskArray.filter((ele) => ele.tags.includes(tag))
        },

        updateTask: (taskId, updates) => {taskArray.forEach((ele, ind) => {
            if(ele.id === taskId){
                const newTask = Object.assign({}, ele, updates);
                taskArray.splice(taskArray[ind], 1, newTask)
            }
        })}
    }
}> 

Les comparto la solución usando clases y reutilizando el metodo de buscar clases, tratando de usar RORO

🥵

🥵

🥵

export function createTaskPlanner() {
  return new TaskPlanner();
}

class TaskPlanner {
  tasks = [];
  addTask(task = {
    id,
    name,
    priority,
    tags
  }) {

    let newTask = { ...task };

    newTask.completed = false;
    this.tasks.push(newTask);
  }

  removeTask(needle) {

    let task = this.getTasks({
      needle
    });
    if (task >= 0) {
      this.tasks.splice(task,1);
    }

  }

  getTasks(params = {
    completed: undefined,
    order: undefined,
    tag: undefined,
    needle: undefined
  }) { 
    switch (true) {
      case params.completed === true:
        return this.tasks.filter(task => task.completed);
        break;
      case params.order != undefined && params.order != "": 
        let tasksOrdered = [ ...this.tasks ];
        return tasksOrdered.sort((a, b) => a[params.order] - b[params.order])
        break;
      case typeof params.tag === "string" && params.tag.length != "":
        return this.tasks.filter(task =>
          task.tags.some(tag => tag === params.tag)
        );
        break;
      case typeof params.needle === "number" || (typeof params.needle === "string" && params.needle != ""):
        return this.tasks.findIndex((value) => {
          return value.id == params.needle || value.name === params.needle;
        });
        break;
      default:
        return this.tasks;
        break;
    }

  }
  getCompletedTasks() {
    return this.getTasks({
      completed: true
    });
  }

  getSortedTasksByPriority() {
    return this.getTasks({
      order: "priority"
    });
  }

  filterTasksByTag(tag) {
    return this.getTasks({
      tag: tag
    });
  }
  markTaskAsCompleted(needle) {
    let task = this.getTasks({
      needle
    });

    if (task >= 0) {

      this.tasks[task].completed = true;
      return this.tasks;
    }
  }

  updateTask(taskId, updates) {
    let task = this.getTasks({
      needle: taskId
    });
    let newTask = { ...this.tasks[task], ...updates };
    this.tasks.splice(task, 1, newTask);
  }
}


.
.
.
.
.
.

export function createTaskPlanner() {
    let taskList = [];

    const addTask = (task) => {
        task.completed = false;
        taskList.push(task);
    }
    const removeTask = (value) => taskList.splice(taskList.findIndex((task) => task.id == value || task.name === value), 1); 
    const getTasks = () => taskList;
    const getPendingTasks = () => taskList.filter((task) => !task.completed);
    const getCompletedTasks = () =>  taskList.filter((task) => task.completed);    
    const markTaskAsCompleted = (value) => {
        const i = taskList.findIndex((task) => task.id == value || task.name === value);
        taskList[i].completed = true;
    }
    const getSortedTasksByPriority = () => [...taskList].sort((a, b) => a.priority - b.priority);
    const filterTasksByTag = (tag) => taskList.filter((task) => task.tags.includes(tag));      
    const updateTask = (taskId, updates) => {
        const i = taskList.findIndex((task) => task.id === taskId);
        taskList[i] = {...taskList[i], ...updates};
    }

    return { addTask, removeTask, getTasks, getPendingTasks, getCompletedTasks, markTaskAsCompleted, getSortedTasksByPriority, filterTasksByTag, updateTask}
}  

Hola!. Muy buen ejercicio, gracias. Comparto mi solución comentada
.
.
.
Antes un par de aportes de mejora:
-Creo que las getCompleted y getPending no corren bien en el simulador; traen todo o nada
-El mark completed sólo deja marcar una task a la vez
-Sería bueno poner explícito el orden del sorting ascendente/descendente porNumero/porDificultad
.
.
.

export function createTaskPlanner() {
  let tasks = []
  return{
    // spread el objeto entrante, agrega la key completed y conforma el nuevo objeto
    addTask(task){tasks.push({...task, completed: false})},
    // filtra para True cuando el id o el name NO coinciden
    removeTask(val){
      tasks = tasks.filter(t=> !(val == t.id || val == t.name));
    },
    getTasks(){
      return tasks;
    },
    getPendingTasks(){
      return tasks.filter(t=> t.completed == false);
    },
    getCompletedTasks(){
      return tasks.filter(t=> t.completed == true);
    },
    // trae el elemento que tiene id o tiene name y le pone true a su 'completed'
    markTaskAsCompleted(val){
      tasks.find(t=> val == t.id || val == t.name).completed = true;
    },
    // reconstruye un arreglo desde el original y lo organiza descendentemente
    getSortedTasksByPriority(){
      return [...tasks].sort((a,b)=>a.priority - b.priority);
    },
    // filtra con True para cuando alguno (some) de los elementos en los tags de la task cumple la condición
    filterTasksByTag(tag){
      return tasks.filter(tk=> tk.tags.some(tg=>tg == tag));
    },
    // toma la task que coincide con el id. Itera sobre el objeto update y actualiza las propiedades
    updateTask(taskId, updates){
      let task = tasks.find(t=>t.id == taskId);
      for(let key in updates) task[key] = updates[key];
    },
  }
}

👾 Mi solución

🚧
🚧
🚧
🚧
🚧
🚧
🚧
🚧
🚧
🚧
🚧
🚧
🚧
🚧
🚧
🚧
🚧
🚧
🚧

export function createTaskPlanner() {
  // Tu código aquí 👈
  let tasksList = []
  return {
    // crear tarea
    addTask: (task) => {
      task.completed = false
      tasksList.push(task)
      //console.log(task)
    },

    // eliminar tarea
    removeTask: (value) => {
      tasksList = tasksList.filter((task) => {
        if (task.id !== parseInt(value) && task.name !== value) return task
        console.log(task)
      })
    },

    // listar todas las tareas
    getTasks: () => tasksList,

    // listar las tareas pendientes
    getPendingTasks: () => tasksList.filter((task) => !task.completed),

    // listar las tareas completadas
    getCompletedTasks: () => tasksList.filter((task) => task.completed),

    // marcar una tarea como completada
    markTaskAsCompleted: (value) => {
      const index = tasksList.findIndex(
        (task) => task.id === parseInt(value) || task.name === value
      )
      tasksList[index].completed = true
      console.log(tasksList)
    },

    // listar las tareas por prioridad
    getSortedTasksByPriority: () =>
      [...tasksList].sort((a, b) => a.priority - b.priority),

    // filtrar las tareas por etiqueta
    filterTasksByTag: (tag) =>
      tasksList.filter((task) => task.tags.includes(tag)),

    // actualizar una tarea
    updateTask: (taskId, updates) => {
      tasksList = tasksList.map((task) => {
        if (task.id !== taskId) return task

        const taskUpdated = {
          ...task,
          ...updates,
        }
        console.log(taskUpdated)
        return taskUpdated
      })
    },
  }
}

Aquí está mi solución, en este ejercicio aumentó la dificultad, excelente el reto!!!
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.


export function createTaskPlanner() {
  let tasks = [];
  return {
    addTask: task => {
      task.completed = false;
      tasks.push(task);
    },
    removeTask: value => {
      tasks.splice(tasks.findIndex(task => task.id === value || task.name === value), 1);
    },
    getTasks: () => tasks,
    getPendingTasks: () => {
      tasks.filter(task => !task.completed);
    },
    getCompletedTasks: () => {
      return tasks.filter(task => task.completed);
    },
    markTaskAsCompleted: value => {
      tasks.find(task => task.id === value || task.name === value).completed = true;
    },
    getSortedTasksByPriority: () => {
      return [...tasks].sort((a, b) => a.priority - b.priority);
    },
    filterTasksByTag: tag => {
      return tasks.filter(task => task.tags.includes(tag));
    },
    updateTask: (taskId, updates) => {
      let taskToUpdate = tasks.find(task => task.id === taskId);
      if(taskToUpdate)
        for(const key in updates)
          taskToUpdate[key] = updates[key];
    },
  };
}

HEY! NO TE RINDAS!

PERO SI YA NO TIENES TIEMPO TE PASO MI SOLUCIÓN:

function createTaskPlanner() {
  let arrayTasks = [];
  function addTask(task) {
    task.completed = false;
    arrayTasks.push(task);
  }
  function removeTask(value) {
    let eraseTask = arrayTasks.find(element => element.id == value || element.name == value);
    arrayTasks.splice(arrayTasks.indexOf(eraseTask), 1);
  }
  function getTasks() {
    return arrayTasks;
  }
  function getPendingTasks() {
    return arrayTasks.filter(element => element.completed == false);
  }
  function getCompletedTasks() {
    return arrayTasks.filter(element => element.completed == true);
  }
  function markTaskAsCompleted(value) {
    let searchTask = arrayTasks.find(element => element.id == value || element.name == value);
    searchTask.completed = true;
  }
  function getSortedTasksByPriority() {
    let copyTasks = [...arrayTasks];
    return copyTasks.sort((a, b) => a.priority - b.priority);
  }
  function filterTasksByTag(tag) {
    return arrayTasks.filter(element => element.tags.some(elem => elem == tag));
  }
  function updateTask(taskId, updates) {
    let modifyTask = arrayTasks.find(element => element.id == taskId);
    Object.assign(modifyTask, updates);
  }
  return {
    addTask,
    removeTask,
    getTasks,
    getPendingTasks,
    getCompletedTasks,
    markTaskAsCompleted,
    getSortedTasksByPriority,
    filterTasksByTag,
    updateTask
  }
}

const planner = createTaskPlanner();

planner.addTask({
  id: 1,
  name: "Comprar leche",
  priority: 1,
  tags: ["shopping", "home"]
});

planner.addTask({
  id: 2,
  name: "Llamar a Juan",
  priority: 3,
  tags: ["personal"]
});

planner.markTaskAsCompleted("Llamar a Juan");

De la solución debuggee y puse console.logs para que puedan ir probando que devuelve cada método.

function createTaskPlanner() {
  let tasks = [];
  return {
     addTask(task) {
      task.completed = false;
      tasks.push(task);
      //console.log(tasks);
    },
    removeTask(value){
      if(typeof value === "number"){
        tasks = tasks.filter((task) => task.id !== value);
        console.log("RemoveTaskPlannerFilter", tasks);
      } else {
        tasks = tasks.filter((task) => task.name !== value);
        console.log("RemoveTaskPlannerElse", tasks);
      }
    },
    getTasks() {
      return tasks;
    },
    getPendingTasks() {
      return tasks.filter((task)=> !task.completed);
    },
    getCompletedTask() {
      return tasks.filter((task)=> task.completed);
    },
    markTaskAsCompleted(value) {
      let index;
      if(typeof value === "number"){
        index = tasks.findIndex((task) => task.id === value);
      } else {
        index = tasks.findIndex((task) => task.name === value);
      }
      tasks[index].completed = true;
      console.log('Modified position: ', tasks[index]);
    },
    getSortedTasksByPriority () {
      const sortedTasks = [...tasks].sort((a, b) => a.priority - b.priority);
      return sortedTasks;
    },
    filterTasksByTag(tag) {
      return tasks.filter((task) => task?.tags?.includes(tag));
    },

    updateTask(taskId, updates) {
      const i = tasks.findIndex((task) => task.id === taskId);
      tasks[i] = {...tasks[i], ...updates};
    },
  };
}

const planner = createTaskPlanner();
// Adding values to tasks array
planner.addTask({
  id: 1,
  name: "Comprar leche",
  priority: 3,
  tags: ["shopping", "home"],
  completed: true,
});
planner.addTask({
  id: 2,
  name: "Llamar a Juan",
  priority: 1,
  tags: ["personal"],
  completed: false,
});
planner.addTask({
  id: 3,
  name: "Llamar a Belinda",
  priority: 2,
  tags: ["personal, introvert"],
  completed: true,
});
// Results
// console.log('AddTaskPlanner', planner.tasks);
// console.log('RemoveTaskPlanner', planner.removeTask('Comprar leche'));
// console.log(planner.removeTask(1));
// console.log('GetTaskPlanner', planner.getTasks());
// console.log('GetPendingTaskPlanner', planner.getPendingTasks());
// console.log('GetCompletedTaskPlanner', planner.getCompletedTask());
// planner.markTaskAsCompleted("Llamar a Juan")
// console.log(planner.getSortedTasksByPriority());
// console.log('FilterTaskByTagPlanner', planner.filterTasksByTag('personal'));
// planner.updateTask(2, {anotherPropierty: true})
// console.log('UpdateTagPlanner', planner.getTasks());
export function createTaskPlanner() {
  // Tu código aquí 👈
  const tasks = []
  return {
    addTask: (task) => {
      task.completed = false;
      tasks.push(task)
    },
    removeTask: function (value) {
      const taskIndex = this.getTaskIndexByIdOrName(value)
      if (taskIndex == null) return;
      tasks.splice(taskIndex, 1)
    },
    getTaskIndexByIdOrName: (value) => {
      return tasks.findIndex(task => task.id === value || task.name === value)
    },
    getTasks: () => {
      return tasks;
    },
    getPendingTasks: () => {
      return tasks.filter(task => !task.completed);
    },
    getCompletedTasks: () => {
      return tasks.filter(task => task.completed);
    },
    filterTasksByTag: (tag) => {
      return tasks.filter(task => task.tags.includes(tag));
    },
    markTaskAsCompleted: function (value) {
      const taskIndex = this.getTaskIndexByIdOrName(value)
      if (taskIndex == null) return;
      tasks[taskIndex].completed = true;
    },
    getSortedTasksByPriority: function () {
      return [...tasks].sort((a, b) => a.priority - b.priority)
    },
    updateTask: (taskId, updates) => {
      const taskIndex = tasks.findIndex(task => task.id === taskId)
      // Update
      tasks[taskIndex] = {
        ...tasks[taskIndex],
        ...updates
      }
    }

  }
}

🛡️🛡️🛡️Escudo anti spoilers🛡️🛡️🛡️

Task Planner

export function createTaskPlanner() {
  // Tu código aquí 👈
  const tasks = [];
  function addTask(task) {
    task.completed = false;
    tasks.push(task);
  }

  function removeTask(value) {
    tasks.forEach((task, it) => {
      if (task.name == value || task.id == value) {
        tasks.splice(it, 1);
      }
    });
  }

  function getTasks() {
    return tasks;
  }

  function getPendingTasks() {
    const result = [];
    tasks.forEach((task) => {
      if (!task.completed) {
        result.push(task);
      }
    });
    return result;
  }

  function getCompletedTasks() {
    const result = [];
    tasks.forEach((task) => {
      if (task.completed) {
        result.push(task);
      }
    });
    return result;
  }

  function markTaskAsCompleted(value) {
    tasks.forEach((task) => {
      if (task.name == value || task.id == value) {
        task.completed = true;
      }
    });
  }

  function getSortedTasksByPriority() {
    const result = [];
    for (let i = 1; i <= 3; i++) {
      tasks.forEach((task) => {
        if (task.priority == i) {
          result.push(task);
        }
      });
    }
    return result;
  }

  function filterTasksByTag(tag) {
    const result = [];
    tasks.forEach((task) => {
      task.tags.forEach((t) => {
        if (t == tag) {
          result.push(task);
        }
      });
    });
    return result;
  }

  function updateTask(taskId, updates) {
    tasks.forEach((task) => {
      if (task.id == taskId) {
        Object.entries(updates).forEach((up) => {
          task[up[0]] = up[1];
        });
      }
    });
  }

  return {
    addTask,
    removeTask,
    getTasks,
    getPendingTasks,
    getCompletedTasks,
    markTaskAsCompleted,
    getSortedTasksByPriority,
    filterTasksByTag,
    updateTask,
  };
}

Solución!

export function createTaskPlanner() {
  const arrTask = [];
  return {
    addTask: (val) => arrTask.push({ ...val, completed: false }),
    removeTask: (val) => {
      const index = arrTask.findIndex((el) => el.id == val || el.name == val);
      if (index !== -1) arrTask.splice(index, 1);
    },
    getTasks: () => arrTask,
    getPendingTasks: () => arrTask.filter(el => !el.completed),
    getCompletedTasks: () => arrTask.filter(el => !!el.completed),
    markTaskAsCompleted: (val) => {
      const index = arrTask.findIndex((el) => el.id == val || el.name == val);
      if (index !== -1) arrTask[index].completed = true;
    },
    getSortedTasksByPriority: () => [...arrTask].sort((a, b) => a.priority - b.priority),
    filterTasksByTag: (val) => [...arrTask].filter(el => el.tags.includes(val)),
    updateTask: (val, updates) => {
      const index = arrTask.findIndex((el) => el.id == val || el.name == val);
      if (index !== -1) arrTask[index] = { ...arrTask[index], ...updates }
    },
  }
}
export function createTaskPlanner() {
  // Tu código aquí 👈
  let tareas = [];
  const addTask = (task) => {
    task.completed = false;
    tareas.push(task)
  }

  const removeTask = (value) => {
    if (typeof value === "number") {
      tareas = tareas.filter(tarea => tarea.id !== value);
    } else {
      tareas = tareas.filter(tarea => tarea.name !== value);
    }
  }

  const getTasks = () => {
    return tareas;
  }

  const getPendingTasks = () => tareas.filter(tarea => !tarea.completed);

  const getCompletedTasks = () => tareas.filter(tarea => tarea.completed);

  const markTaskAsCompleted = (value) => {
    let index;
    if (typeof value === "number") {
      index = tareas.findIndex(tarea => tarea.id === value);
    } else {
      index = tareas.findIndex(tarea => tarea.name === value);
    }
    tareas[index].completed = true;
  }

  const getSortedTasksByPriority = () => {
    return [...tareas].sort((a, b) => a.priority - b.priority);
  }

  const filterTasksByTag = (tag) => {
    return tareas.filter(tarea => tarea.tags.includes(tag));
  }

  const updateTask = (taskId, updates) => {
    let index;
    index = tareas.findIndex(tarea => tarea.id === taskId);
    tareas[index] = {
      ...tareas[index], ...updates
    };
  }

  return {
    addTask,
    removeTask,
    getTasks,
    getPendingTasks,
    getCompletedTasks,
    markTaskAsCompleted,
    getSortedTasksByPriority,
    filterTasksByTag,
    updateTask
  };
}

Mi código

function createTaskPlanner() {
  let taskList = []

  return {
    addTask: (task) => {
      taskList.push({
        ...task,
        completed: false
      })
    },
    removeTask: (value) => {
      taskList = taskList.filter((task) => task.id !== value && task.name !== value)
    },
    getTasks: () => taskList,
    getPendingTasks: () => taskList.filter((task) => task.completed === false),
    getCompletedTasks: () => taskList.filter((task) => task.completed === true),
    markTaskAsCompleted: (value) => {
      let taskSearched = taskList.find((task) => task.id === value || task.name === value)
      if (taskSearched !== undefined)
        taskSearched.completed=true
    },
    getSortedTasksByPriority: () => taskList.toSorted((a, b) => a.priority - b.priority),
    filterTasksByTag: (tag) => taskList.filter((task) => task.tags.includes(tag)),
    updateTask: (taskId, updates) => {
      const index = taskList.findIndex((task) => task.id === taskId);
      taskList[index] = { ...taskList[index], ...updates };
    }
  }
}

Les comparto mi solución :
.
.
.
.
.
.
.
.
.
.
.
.
Aqui:

export function createTaskPlanner() {
  // Tu código aquí 👈

  let taskList = [];

  /* Funciones */
  const findInTaskListBy = (filterFunc, recognitionValue) => {
    let result = taskList.reduce((accumulator, task) => {
      const findedTask = filterFunc(recognitionValue, task);
      if (findedTask != undefined) {
        accumulator = [...accumulator, findedTask];
      }
      return accumulator;
    }, []);
    return result;
  };

  function idOrNameOfTask(idOrName, task) {
    if (task.id == idOrName || task.name == idOrName) {
      return task;
    }
  };

  function completedTask(trueOrFalse, task) {

    if (task.completed == trueOrFalse) {
      return task;
    }
  };
  function tagInclude(searchedTag, task) {

    if (task.tags.includes(searchedTag)) {
      return task;
    }
  };


  /*Inicio de Return */
  return {
    addTask(task) {
      task["completed"] = false;
      taskList.push(task);
    },
    removeTask(value) {
      const idRemoveTask = findInTaskListBy(idOrNameOfTask, value);
      console.log('RemoveTask: ', idRemoveTask);
      idRemoveTask == undefined ? console.log('No hemos encontrado la tarea')
        : taskList.splice(idRemoveTask, 1);

    },
    getTasks() {
      return taskList;
    },
    getPendingTasks() {
      const pendingTaskArray = findInTaskListBy(completedTask, false);

      return pendingTaskArray;
    },
    getCompletedTasks() {
      const completedTaskArray = findInTaskListBy(completedTask, true);

      return completedTaskArray;
    },
    markTaskAsCompleted(value) {
      const findedTask = findInTaskListBy(idOrNameOfTask, value);
      const indexUp = taskList.indexOf(findedTask[0]);

      taskList[indexUp].completed = true;
    },
    getSortedTasksByPriority() {
      const taskListCopy = [...taskList];
      const sortedTaskList = taskListCopy.sort((valueA, valueB) => { return valueA.priority - valueB.priority });

      return sortedTaskList;
    },
    filterTasksByTag(tag) {
      const filteredTaskArray = findInTaskListBy(tagInclude, tag);

      return filteredTaskArray;
    },
    updateTask(taskId, updates) {
      let updatedTask = findInTaskListBy(idOrNameOfTask, taskId);
      const indexUp = taskList.indexOf(updatedTask[0]);

      taskList[indexUp] = { ...updatedTask[0], ...updates };

    },
  };

}

my solution:

export function createTaskPlanner() {
  const tasks = []

  function addTask(task) {
    task.completed = false;
    tasks.push(task);
  }
  function removeTask(value) {
    for (let i = 0; i < tasks.length; i++) {
      if (tasks[i].id === value || tasks[i].name === value) {
        tasks.splice(i, 1);
      }
    }
  }
  function getTasks() {
    return tasks.slice();
  }
  function getPendingTasks() {
    return tasks.filter((task) => !task.completed);
  }
  function getCompletedTasks() {
    return tasks.filter((task) => task.completed);
  }
  function markTaskAsCompleted(value) {
    const task = tasks.find((task) => task.id === value || task.name === value);
    if (task) {
      task.completed = true;
    }
  }
  function getSortedTasksByPriority() {
    let orderedTasksList = [...tasks]
    return orderedTasksList.sort((a, b) => a.priority - b.priority);
  }

  function filterTasksByTag(tag) {
    return tasks.filter((task) => task.tags.includes(tag));
  }

  function updateTask(taskId, updates) {
    const task = tasks.find(task => task.id === taskId);
    if (task) {
      Object.assign(task, updates);
    }
  }

  return {
    addTask,
    removeTask,
    getTasks,
    getPendingTasks,
    getCompletedTasks,
    markTaskAsCompleted,
    getSortedTasksByPriority,
    filterTasksByTag,
    updateTask
  };
}
export function createTaskPlanner() {
  let tareas = [];
  function addTask(task) {
    task['completed'] = false;
    tareas.push(task)
  }
  function removeTask(value) {
    if (typeof value === 'number') {
      tareas = tareas.filter((tarea) => tarea.id !== value);
    } else {
      tareas = tareas.filter((tarea) => tarea.name !== value);
    }
  }
  function getTasks() {
    return tareas;
  }
  function getPendingTasks() {
    return tareas.filter((tarea) => tarea.completed === false);
  }
  function getCompletedTasks() {
    return tareas.filter((tarea) => tarea.completed === true);
  }
  function markTaskAsCompleted(value) {
    let result
    if (typeof value === 'number') {
      result = tareas.find(tarea => tarea.id === value);
    } else {
      result = tareas.find(tarea => tarea.name === value);
    }
    result['completed'] = true;
  }
  function getSortedTasksByPriority() {
    const newList = [...tareas].sort(function (a, b) { return a.priority - b.priority })
    return newList;
  }
  function filterTasksByTag(tag) {
    return tareas.filter((tarea) => tarea.tags.includes(tag));
  }
  function updateTask(id, updates) {
    const result = tareas.findIndex((task) => task.id === id);
    tareas[result] = { ...tareas[result], ...updates };
  }
  return {
    addTask,
    removeTask,
    getTasks,
    getPendingTasks,
    getCompletedTasks,
    markTaskAsCompleted,
    getSortedTasksByPriority,
    filterTasksByTag,
    updateTask
  }
}

Mi solución

function createTaskPlanner() {
  let tasksList = [];
  return {
    addTask(task) {
      task.completed = false;
      tasksList.push(task);
    },
    removeTask(value) {
      const eliminatedTask = tasksList.find(task => task.id == value);
      const removeIndex = tasksList.findIndex(task => task.id == value);
      tasksList.splice(removeIndex, 1);
      return eliminatedTask;
    },
    getTasks() {
      return tasksList;
    },
    getPendingTasks() {
      const pendingTasks = tasksList.filter(task => task.completed == false);
      return pendingTasks;
    },
    getCompletedTasks() {
      const completedTasks = tasksList.filter(task => task.completed == true);
      return completedTasks;
    }, 
    markTaskAsCompleted(value) {
      const taskIndex = tasksList.findIndex(task => task.id == value || task.name == value);
      tasksList[taskIndex].completed = true;
    },
    getSortedTasksByPriority() {
      const priorityTasks = [...tasksList].sort((a, b) => a.priority - b.priority);
      return priorityTasks;
    },
    filterTasksByTag(tag) {
      const tagTasks = tasksList.filter(task => {
        if (task.tags.includes(tag) == true) {
          return task;
        }
      })
      return tagTasks;
    },
    updateTask(taskId, updates) {
      const updateIndex = tasksList.findIndex(task => task.id == taskId);
      tasksList[updateIndex] = {...tasksList[updateIndex], ...updates};
    }
  }
}

🛡️🛡️Escudo anti-spoilers🛡️🛡️

Mi solución al reto:

export function createTaskPlanner() {
 let tasks = [];
 return {
   addTask: (task) => {
     task.completed = false;
     tasks.push(task)
   },
   removeTask: (value) => {
     tasks = tasks.filter((t) => t.id !== value && t.name !== value)
   },
   getTasks: () => {
     return tasks;
   },
   getPendingTasks: () => {
     return tasks.filter(t => !t.completed)
   },
   getCompletedTasks: () => {
     return tasks.filter(t => t.completed)
   },
   markTaskAsCompleted: (value) => {
     tasks = tasks.map((t) => {
       if (t.id === value || t.name === value) {
         t.completed = true;
       }
       return t;
     })
   },
   getSortedTasksByPriority: () => {
     return [...tasks].sort((a, b) => a.priority > b.priority)
   },
   filterTasksByTag: (tag) => {
     return tasks.filter((t) => {
       return t.tags.indexOf(tag) >= 0;
     })
   },
   updateTask: (taskId, updates) => {
     const index = tasks.findIndex(task => task.id === taskId);
     tasks[index] = { ...tasks[index], ...updates };
   }
 };
}

Les comparto mi solución:

.
.
.
.
.
.
.
.
.
.
.
.

export function createTaskPlanner() {
  // Tu código aquí 👈
  const tasks = [];
  return {
    "addTask": function (task) {
      task.completed = false;
      tasks.push(task);
    },
    "removeTask": function (value) {
      return tasks.splice(tasks.indexOf(tasks.find((task => task.id === value))), 1);
    },
    "getTasks": function () {
      return tasks;
    },
    "getPendingTasks": function () {
      return tasks.filter((task) => task.completed === false);
    },
    "getCompletedTasks": function () {
      return tasks.filter((task) => task.completed === true);
    },
    "markTaskAsCompleted": function (value) {
      let index = tasks.indexOf(tasks.find((task => (task.id === value || task.name === value))));
      return tasks[index].completed = true;
    },
    "getSortedTasksByPriority": function () {
      const aux = [...tasks].sort((a, b) => a.priority - b.priority);
      return aux;
    },
    "filterTasksByTag": function (tag) {
      return tasks.filter((task) => task.tags.includes(tag));
    },
    "updateTask": function (taskId, updates) {
      let index = tasks.indexOf(tasks.find((task => task.id === taskId)));
      tasks[index] = { ...tasks[index], ...updates }
    }
  };
}

export function createTaskPlanner() {
  // Día 10 💚
  const myTasks = []
  const addTask = (task) => {
    task['completed'] = false
    return myTasks.push(task)
  }

  const removeTask = (value) => {
    myTasks.forEach(task => {
      if (value === task.name || parseInt(value) === task.id) {
        myTasks.splice(myTasks.indexOf(task), 1)
      }
    })
  }

  const getTasks = () => myTasks

  const getPendingTasks = () => myTasks.filter(task => task.completed === false)

  const getCompletedTasks = () => myTasks.filter(task => task.completed === true)

  const markTaskAsCompleted = (value) => {
    myTasks.forEach(task => {
      if (task.name === value || task.id === parseInt(value)) {
        task.completed = true
      }
    })
  }

  const getSortedTasksByPriority = () => {
    const orderedArray = myTasks.map(task => [task.priority, task])
    orderedArray.sort()
    return orderedArray.map(element => element[1])

  }

  const filterTasksByTag = (tag) => {
    return myTasks.filter(task => task.tags.indexOf(tag) !== -1 ? true : false)
  }
  
  const updateTask = (taskId, updates) => {

    const index = myTasks.findIndex((task) => task.id === taskId);
    myTasks[index] = { ...myTasks[index], ...updates };
  }


  return {
    addTask,
    removeTask,
    getTasks,
    getPendingTasks,
    getCompletedTasks,
    markTaskAsCompleted,
    getSortedTasksByPriority,
    filterTasksByTag,
    updateTask
  }
}

export function createTaskPlanner() {
  // Tu código aquí 👈
  let tareas = [];
  function addTask(task){
    tareas.push(task)
    task.completed = false
  } 
  function removeTask(value) {
    if (typeof value === "number") {
      let indexToRemove = tareas.findIndex(obj => obj.id === value);
      tareas.splice(indexToRemove,1)
    }
    else if (typeof value === "string") {
      tareas = tareas.filter(obj => obj.name !== value); 
    }
  }
  function getTasks() {
    return tareas
  }
  function getPendingTasks() {
    return tareas.filter(obj => obj.completed === false)
  }
  function getCompletedTasks() {
    return tareas.filter(obj => obj.completed === true)
  }
  function markTaskAsCompleted(value) {
    const task = tareas.find(task => task.id === value || task.name === value);
    if (task) {
      task.completed = true;
    }
  }
  function getSortedTasksByPriority() {
    return [...tareas].sort((a, b) => a.priority - b.priority);
  }
  function filterTasksByTag(tag) {
    return tareas.filter(task => task.tags.includes(tag));
  }
  function updateTask(taskId, updates) {
    const task = tareas.find(task => task.id === taskId);
    if (task) {
      Object.assign(task, updates);
    }
  }
  return {
    addTask,
    removeTask,
    getTasks,
    getPendingTasks,
    getCompletedTasks,
    markTaskAsCompleted,
    getSortedTasksByPriority,
    filterTasksByTag,
    updateTask
  };
}

Hola Comparto la solución al Reto.

export function createTaskPlanner() {
  const tasks = [];

  const findById = function (value) {
    return tasks.findIndex((task) => task.id === value);
  };

  const findByName = function (value) {
    return tasks.findIndex((task) => task.name === value);
  };

  const findTask = function (value) {
    if (typeof value === "number") {
      return findById(value);
    } else {
      return findByName(value);
    }
  };

  const addTask = function (task) {
    task.completed = false;
    tasks.push(task);
  };

  const getTasks = function () {
    return tasks;
  };

  const removeTask = function (value) {
    const taskIndexRemove = findTask(value);

    tasks.splice(taskIndexRemove, 1);
  };

  const markTaskAsCompleted = function (value) {
    const taskIndexCompleted = findTask(value);
    let taskAsCompleted = tasks[taskIndexCompleted];
    taskAsCompleted.completed = true;
    tasks.splice(taskIndexCompleted, 1, taskAsCompleted);
  };

  const filterTasksByTag = function (value) {
    const taskFilter = tasks.filter((task) => {
      const tagsFind = task.tags.filter((tag) => tag === value);
      return tagsFind !== undefined && tagsFind.length > 0;
    });

    return taskFilter;
  };

  const getSortedTasksByPriority = function () {
    const sortedTasks = [...tasks];
    sortedTasks.sort((taskA, taskB) => taskA.priority - taskB.priority);
    return sortedTasks;
  }

  const getCompletedTasks = function () {
    return tasks.filter(task => task.completed);
  }

  const updateTask = function (taskId, updates) {
    const updateTaskIndex = findById(taskId);
    let updateTask = tasks[updateTaskIndex];

    for (const key in updates) {
      updateTask[key] = updates[key];
    }

    tasks.splice(updateTaskIndex, 1, updateTask);
  }

  return {
    addTask,
    getTasks,
    removeTask,
    markTaskAsCompleted,
    filterTasksByTag,
    getSortedTasksByPriority,
    getCompletedTasks,
    updateTask
  };
}

Me costo mucho pero aqui mi codigo

function createTaskPlanner() {
    let tasks = []
    return {
        addTask(task){
            task.completed = false
            tasks.push(task)
            return tasks
        },
        removeTask(value){
            for (const tarea of tasks) {
                for (const propiedad in tarea) {
                    if (tarea[propiedad] == value){
                        tasks.pop(tarea)
                    }
                    }
                }
                
            },
        getTasks(){
            return tasks
        },
        getPendingTasks(){
            let pendingTasks = []
            for (const tarea of tasks) {
                if (tarea.completed == false){
                    pendingTasks.push(tarea)
                }
                }
            return pendingTasks
        },
        getCompletedTasks(){
            let completedTasks = []
            for (const tarea of tasks) {
                if (tarea.completed == true){
                    completedTasks.push(tarea)
                }
                }
            return completedTasks
        },
        markTaskAsCompleted(value){
            for (const tarea of tasks) {
                for (const propiedad in tarea) {
                    if (tarea[propiedad] == value){
                        tarea.completed = true
                    }
                    }
                }
        },
        getSortedTasksByPriority(){
            let sorted = []
                function addSorted(prioridad){
                    for (const tarea of tasks) {
                        if (tarea.priority == prioridad){
                            sorted.push(tarea)
                            }
                        }
                }
                addSorted(1)
                addSorted(2)
                addSorted(3)
                return sorted
        },
        filterTasksByTag(tag){
            let filerByTag = []
            for (const tarea of tasks) {
                    for (const tagg of tarea.tags) {
                        if (tagg == tag){
                            filerByTag.push(tarea)
                        }
                    }
                } 
            return filerByTag
        },
        updateTask(taskId, updates){
            for (let tarea of tasks) {
                if (tarea.id == taskId){
                    for (const newPropiedad in updates) {
                        tarea[newPropiedad] = updates[newPropiedad]
                    }  
                    }
                }
            } 
        }
    }

Spoiler
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.Por cierto, este ejercicio estuvo muy retador.

export function createTaskPlanner() {
let arrayTareas = [];

return {
addTask(task) {
let tarea = { …task };
tarea.completed = false;

  arrayTareas.push(tarea);
  return arrayTareas;
},

removeTask(value) {
  for (let tarea of arrayTareas) {
    const { id, name } = tarea;
    let indice = arrayTareas.indexOf(tarea);
    if (id === value) {
      arrayTareas.splice(indice, 1);
    } else if (name === value) {
      arrayTareas.splice(indice, 1);
    }
  }
  return arrayTareas;
},

getTasks() {
  return arrayTareas;
},

getPendingTasks() {
  let arrayAux = [...arrayTareas];
  let aa = [];
  for (let tarea of arrayAux) {
    if (tarea.completed === false) {
      aa.push(tarea);
    }
  }
  return aa;
},

getCompletedTasks() {
  let completas = [];
  for (let tarea of arrayTareas) {
    if (tarea.completed === true) {
      completas.push(tarea);
    }
  }
  return completas;
},

markTaskAsCompleted(value) {
  for (let tarea of arrayTareas) {
    const { id, name } = tarea;
    if (value === id) {
      tarea.completed = true;
    } else if (name === value) {
      tarea.completed = true;
    }
  }
},

getSortedTasksByPriority() {
  let tareas = [...arrayTareas];
  tareas.sort((a, b) => a - b);
  return tareas.reverse();
},

filterTasksByTag(tag) {
  let filtro = [];

  for (let tarea of arrayTareas) {
    const { tags } = tarea;

    for (let tagg of tags) {
      if (tagg === tag) {
        filtro.push(tarea);
      }
    }
  }
  return filtro;
},

updateTask(taskId, updates) {
  const position = arrayTareas.findIndex((t) => taskId === t.id);
  const tarea = arrayTareas[position];
  arrayTareas[position] = {
    ...tarea,
    ...updates
  }
},

};
}

Me costo un poco, y el apartado de update me toco ayudarme con chatGPT
Espero que les sirva como referencia para hacer lo de ustedes

// Tu código aquí 👈
    //id, name, priority, tags y completed 
    let taskData = []

    const addTask = (taskAdd)=> {
        taskAdd.completed=false;
        taskData.push(taskAdd)
    }
    
    const removeTask = (value)=> {
        if (typeof(value)==typeof(1))taskData = taskData.filter(elemento =>elemento.id!=value)
        if (typeof(value)==typeof('1'))taskData = taskData.filter(elemento =>elemento.name!=value)
    }
    
    const getTasks = () => taskData

    const getPendingTasks = () =>taskData.filter(elemento =>elemento.completed==false)
    const getCompletedTasks = () =>taskData.filter(elemento =>elemento.completed==true)

    const markTaskAsCompleted = (value)=> {
        taskData.map(elemento =>{
            if (typeof(value)==typeof(1) && elemento.id == value) elemento.completed = true //: elemento.completed = false 
            if (typeof(value)==typeof('1') && elemento.name == value) elemento.completed = true //: elemento.completed = false
        })
    }

    const getSortedTasksByPriority = () => {
        let taskPriority=[]
        let a = taskData.filter(elemento =>elemento.priority==1)
        let b = taskData.filter(elemento =>elemento.priority==2)
        let c = taskData.filter(elemento =>elemento.priority==3)
        taskPriority=taskPriority.concat(a)
        taskPriority=taskPriority.concat(b)
        taskPriority=taskPriority.concat(c)
        return taskPriority
    }

    const filterTasksByTag = tag =>taskData.filter(elemento =>elemento.tags.includes(tag))

    const updateTask = (taskId,updates) =>{
        const taskIndex = taskData.findIndex((task) => task.id === taskId);
        if (taskIndex !== -1) {
            taskData[taskIndex] = { ...taskData[taskIndex], ...updates };
        }
    }

    return{
        addTask,
        removeTask,
        getTasks,
        getPendingTasks,
        getCompletedTasks,
        markTaskAsCompleted,
        getSortedTasksByPriority,
        filterTasksByTag,
        updateTask
    }

A continuación mi solución:

P.D: muy buenos retos, buscando manera de solucionarlo es que se me quedan grabados los puntos importantes de las clases

SPOILER

export function createTaskPlanner() {
  let tareas = [];
  return {
    addTask(task) {
      tareas.push(
        {
          ...task,
          completed: false
        }
      )
    },

    removeTask(value) {
      let indice = tareas.indexOf(tareas.find(t => t.id === value || t.name === value));
      tareas.splice(indice, 1);
    },

    getTasks() {
      return tareas;
    },

    getPendingTasks() {
      let pendientes = tareas.filter(t => !t.completed);
      return pendientes;
    },

    getCompletedTasks() {
      let completas = tareas.filter(t => t.completed);
      return completas;
    },

    markTaskAsCompleted(value) {
      tareas.find(t => t.id === value || t.name === value).completed = true;
    },

    filterTasksByTag(tag) {
      let cumple = [];
      tareas.forEach(function (t) {
        let res = [];
        res = t.tags.filter(n => n === tag);
        if (res.length > 0) {
          cumple.push(t)
        }
      })
      return cumple;
    },

    updateTask(taskId, updates) {
      let tarea = tareas.find(t => t.id === taskId);
      let indice = tareas.indexOf(tarea);
      let nue = { ...tarea, ...updates };
      tareas.splice(indice, 1, nue);
    },

    getSortedTasksByPriority() {
      let arr1 = [];
      let arr2 = [];
      let arr3 = [];
      let prioridad;
      tareas.forEach(function (t) {
        prioridad = t.priority;
        switch (prioridad) {
          case 1: arr1.push(t);
            break;
          case 2: arr2.push(t);
            break;
          case 3: arr3.push(t);
            break;
        }
      })
      return [...arr1, ...arr2, ...arr3];
    }
  }
}

Quiero inmortalizar mi causa de sufrimiento:

export function createTaskPlanner() {
  let tasksArray = [];
  return {
    addTask(task) {
      task.completed = false;
      tasksArray.push(task);
    },
    removeTask(value) {
      const indexOf = tasksArray.findIndex(task => {
        task.id === value || task.name === value
      });
      tasksArray.splice(indexOf, 1);
    },
    getTasks() {
      return tasksArray;
    },
    getPendingTasks() {
      return tasksArray.filter(task => 
        task.completed === false
      )
    },
    getCompletedTasks() {
      return tasksArray.filter(task => 
        task.completed
      )
    },
    markTaskAsCompleted(value) {
      const indexOf = tasksArray.findIndex(task => 
        task.id === value || task.name === value
      );
      tasksArray[indexOf].completed = true
    },
    getSortedTasksByPriority() {
      const priorityArray = [...tasksArray].sort((a, b) => 
        a.priority - b.priority
      );
      return priorityArray;
    },
    filterTasksByTag(tag) {
      return tasksArray.filter(task => task.tags.includes(tag))
    },
    updateTask(taskId, updates) {
      const indexOf = tasksArray.findIndex(task => 
        task.id === taskId
      );
      tasksArray[indexOf] = {
        ...tasksArray[indexOf], ...updates
      }
    }
  }
}

Hola, aquí está mi código. El único punto que no pude verifcar es el que dice “Should not modify the original array”.

function createTaskPlanner() {
  // Tu código aquí 👈
  let tasks=[];
  return {
    addTask(task){
        let act=task
        act['completed']=false;
        return tasks.push(act);
    }, 
      removeTask(value){
        let toRemove=tasks.findIndex(x=>x.id===value);
        tasks.splice(toRemove,1);
      },
      getTasks(){
        return tasks;

      },
      getPendingTasks(){
        return tasks.map(x=>x.completed===false);

      },
      getCompletedTasks(){
        return tasks.map(x=>x.completed===true);

      },
      markTaskAsCompleted(value){
        let toMarkCompleted=tasks.findIndex(x=>x.id===value | x.name===value);
        tasks[toMarkCompleted].completed=true;

      },
      getSortedTasksByPriority(){
        return [...tasks].sort((a,b)=>{
          return a.priority - b.priority;
        });
      },
      filterTasksByTag(tag){
        return tasks.filter(x=>x.tags.includes(tag));  
      },
      updateTask(taskId, updates){
        let updateIndex=tasks.findIndex(x=>x.id===taskId);
        for( let key of Object.keys(updates)){
          tasks[updateIndex][key]=updates[key];
        }
        return tasks[updateIndex];
        
      }
  };
}

Gracias por el reto muy intresante!
Acá dejo mi solución 👇

export function createTaskPlanner() {
  let tasks = [];

  const addTask = (task) => tasks.push({ ...task, completed: false });
  const removeTask = (value) => tasks = tasks
    .filter(task => !(task.id == value || task.name == value));
  const getTasks = () => tasks;
  const getPendingTasks = () => tasks.filter(task => !task.completed);
  const getCompletedTasks = () => tasks.filter(task => task.completed);
  const markTaskAsCompleted = (value) => tasks
    .find(task => (task.id === value || task.name === value)).completed = true;
  const getSortedTasksByPriority = () => [...tasks].sort((a, b) => a.priority - b.priority);
  const filterTasksByTag = (tag) => tasks
    .filter(task => task.tags.find(_tag => _tag === tag));
  const updateTask = (taskId, updates) => {
    let idx = tasks.findIndex(task => task.id === taskId)
    tasks[idx] = { ...tasks[idx], ...updates }
  }

  return {
    addTask,
    removeTask,
    getTasks,
    getPendingTasks,
    getCompletedTasks,
    markTaskAsCompleted,
    getSortedTasksByPriority,
    filterTasksByTag,
    updateTask,
  }
}

Hay que tener cuidado cuando se escribe muchas lineas de código, se puede quedar estancado con un typeerror solo por no hacer las pruebas. Aquí dejo mi hermoso código, que lo disfruten… 😃

function createTaskPlanner() {
  
  let tasks = [];
  const addTask = (task) => {
    return tasks.push({ ...task, completed: false });
  }

  function findtask(value) {

    let findtask;
    if (typeof value === "string") {
      findtask = tasks.findIndex((task) => {      
        return task.name === value
      });

      notfind(findtask);
    } else if (typeof value === "number") {

      findtask = tasks.findIndex(task => task.id === value);
      notfind(findtask);
    }
    return findtask;
  }
  const removeTask = (value) => {

    if (typeof value === "number") {

      tasks = tasks.filter((task) => task.id !== value);
    } else {

      tasks = tasks.filter((task) => task.name !== value);
    }
  
    return tasks; 
  }

  function notfind(value) {
    if (value < 0) {
      throw new Error("No se encontro esa tarea");
    }
  }
  const getTasks = () => {
    return tasks;
  }

  const getPendingTasks = () => {
    return tasks.filter(task => task.completed === false);
  }
  const getCompletedTasks = () => {
    return tasks.filter(task => task.completed === true);
  }

  const markTaskAsCompleted = (value) => {

    tasks[findtask(value)].completed = true;
    return tasks[findtask(value)];
  }

  const getSortedTasksByPriority = () => {
    
  let copytasks =[...tasks].sort((a, b) => a.priority - b.priority);
    return copytasks;
  }
  const filterTasksByTag = (tag) => {
    return tasks.filter(task => task.tags.includes(tag));
  }
  const updateTask = (taskId, updates) => {
    tasks[findtask(taskId)] = { ...tasks[findtask(taskId)], ...updates };
    
    return tasks[findtask(taskId)];

  }
  return {
    updateTask,
    filterTasksByTag,
    getSortedTasksByPriority,
    markTaskAsCompleted,
    getCompletedTasks,
    getPendingTasks,
    getTasks,
    addTask,
    removeTask
  }
}

Solución

function createTaskPlanner() {

	const tasksArray = []
	
  function addTask(task) {
  	tasksArray.push({...task, completed: false})
    console.log("New task added: ", task.name)
  }
  
  function removeTask(value) {
  	
    const removingTaskId = tasksArray
    	.findIndex(task => task.id === value || task.name === value)
    
    const removedTask = tasksArray[removingTaskId]
    
    tasksArray.splice(removingTaskId, 1)
    
    console.log("Removed task: ", removedTask.name)
  }
  
  function getTasks() {
  
  	console.log(tasksArray)
    return tasksArray
    
  }
  
  function getPendingTasks() {
  
  	const pendingTasks = tasksArray.filter(task => task.completed === false)
    
    console.log(pendingTasks)
    return pendingTasks
  }
  
  function markTaskAsCompleted(value) {
  
  	const completedTaskIndex = tasksArray.findIndex(task => task.id === value || task.name === value)
    tasksArray[completedTaskIndex].completed = true
    
  }
  function getSortedTasksByPriority() {
  	const sortedTasks = tasksArray.sort((taskA, taskB) => {
    	return taskA.priority - taskB.priority
    }) 
  	
    console.log(sortedTasks)
    return sortedTasks
  }
  
  function filterTasksByTag(tag) {
  
  	const taggedTasks = tasksArray.filter(task => task.tags.includes(tag))
    console.log(taggedTasks)
    return taggedTasks
    
  }
  
  function updateTask(taskId, updates) {}
  function getCompletedTasks() {
  	const completedTasks = tasksArray.filter(task => task.completed === true)
    console.log(completedTasks)
    return completedTasks
  }

  return {
  	addTask,
    removeTask,
    getTasks,
    getPendingTasks,
    markTaskAsCompleted,
    getSortedTasksByPriority,
    filterTasksByTag,
    updateTask,
    getCompletedTasks,
  }
}

Hola, les comparto mi solución pero antes…
ESCUDO ANTI SPOILERS!
.
.
.
.
.
.
.
.
.
.
.
.
.
.

Dejo mi solución
.
.
.
.
.
.
.
.
.
.
.

export function createTaskPlanner() {
  // Tu código aquí 👈
  let tasks = []
  return {
    addTask(task) {
      task.completed = false;
      tasks.push(task);
    },

    removeTask(value) {
      typeof value === 'string' ? tasks = tasks.filter(val => val.name !== value) : tasks = tasks.filter(val => val.id !== value);
    },

    getTasks() {
      return tasks;
    },

    getPendingTasks() {
      const pendingTasks = tasks.filter(task => task.completed === false);
      return pendingTasks;

    },

    getCompletedTasks() {
      const completedTasks = tasks.filter(task => task.completed === true);
      return completedTasks;

    },

    markTaskAsCompleted(value) {
      if (typeof value === 'string') {
        const task = tasks.find(element => element.name === value);
        task.completed = true;
      } else {
        const task = tasks.find(element => element.id === value);
        task.completed = true;
      }
    },

    filterTasksByTag(tag) {
      const filteredTasks = tasks.filter(task => task.tags.includes(tag));
      console.log(filteredTasks);
      return filteredTasks;
    },

    updateTask(taskId, updates) {
      const index = tasks.findIndex((task) => task.id === taskId);
      tasks[index] = { ...tasks[index], ...updates };
    },

    getSortedTasksByPriority() {
      const tasksSortedByPriority = [];
      const veryUrgentTasks = tasks.filter(task => task.priority === 1);
      const urgentTasks = tasks.filter(task => task.priority === 2);
      const notUrgentTasks = tasks.filter(task => task.priority === 3);
      veryUrgentTasks.forEach(task => {
        tasksSortedByPriority.push(task)
      });
      urgentTasks.forEach(task => {
        tasksSortedByPriority.push(task)
      });
      notUrgentTasks.forEach(task => {
        tasksSortedByPriority.push(task)
      });
      return tasksSortedByPriority;
    }
  }
}

Esta sería mi solución:

<script>function createTaskPlanner() {
  const tasks = [];
  const addTask = (task) => {
    task.completed = false;
    tasks.push(task);
  }
  const removeTask = (value) => {
    const task = tasks.find(t => t.name === value || t.id === value);
    if (task) {
       tasks.splice(tasks.indexOf(task), 1);
    }
  }
  const getTasks = () => tasks;
  const getPendingTasks = () => tasks.filter(task => !task.completed);
  const markTaskAsCompleted = (value) => {
    const task = tasks.find(t => t.name === value || t.id == value);
    if (task) {
      task.completed = true;
    }
  }
//aquí tuve dificultades porque me no noté que estaba modificando mi array base por mostrarlo ordenado, lo que me daba errores al momento de validar, finalmente di cuenta que solo necesitaba usar "[...task].sort..." en lugar de solo "task.sort..."
  const getSortedTasksByPriority = () => [...tasks].sort((a, b) => a.priority - b.priority);
  const getCompletedTasks = () => tasks.filter(task => task.completed);
  const filterTasksByTag = (tag) => tasks.filter((task) => task.tags && task.tags.some(t=>t===tag));
  const updateTask = (taskId, updates) => {
    const task = tasks.find(task => task.id = taskId);
    if (task) {
      tasks.splice(tasks.indexOf(task), 1, Object.assign({}, task, updates))
    }
  };
  return {
    addTask,
    removeTask,
    getTasks,
    getPendingTasks,
    markTaskAsCompleted,
    getSortedTasksByPriority,
    filterTasksByTag,
    updateTask,
    getCompletedTasks,
  }
}
</script> 
function createTaskPlanner() {

  let taskPlanners = [];

  const addTask = task => {
    task.completed = false; taskPlanners.push(task)
  };

  const removeTask = task => taskPlanners = taskPlanners.filter(item => (item.name !== task && item.id !== task));

  const getTasks = () => taskPlanners;

  const getPendingTasks = () => taskPlanners.filter(item => !item.completed);

  const getCompletedTasks = () => taskPlanners.filter(item => item.completed);

  const markTaskAsCompleted = task => {
    const find = taskPlanners.find(item => (item.name === task || item.id === task)); 
    find.completed = true
  };

  const getSortedTasksByPriority = () => [...taskPlanners].sort((a, b) => a.priority - b.priority);

  const filterTasksByTag = tag => taskPlanners.filter(({tags}) => tags.includes(tag));

  const updateTask = (taskId, updates) => {
    const index = taskPlanners.findIndex(({id}) => id === taskId);
    if (index !== -1) {
      taskPlanners = [].concat(taskPlanners);
      return taskPlanners[index] = Object.assign({}, taskPlanners[index], updates);
    }
  };
  

  return {
    addTask,
    getTasks,
    removeTask,
    getPendingTasks,
    getCompletedTasks,
    markTaskAsCompleted,
    getSortedTasksByPriority,
    filterTasksByTag,
    updateTask
  }
}

Esta es mi solución al reto:
.
.
.
.
.
.
.
.
.
.
.
.

export function createTaskPlanner() {
  let taskList = [];

  const addTask = (task) => {
    task.completed = false;
    taskList.push(task);
    return taskList;
  }

  const removeTask = (value) => {
    let newArry = taskList.filter(v => { return v.id != value && v.name !== value} );
    taskList = newArry;
    return taskList;
  }

  const getTasks = () => {
    return taskList;
  }

  const getCompletedTasks = () => {
    return taskList.filter(t => t.completed === true);
  }

  const getPendingTasks = () => {
    return taskList.filter(t => t.completed === false);
  }

  const markTaskAsCompleted = (value) => {
    let task = taskList.find(t => { return t.id == value || t.name == value });
    if (task) {
      task.completed = true;
    }
    return taskList;
  }

  const getSortedTasksByPriority = () => {
    let auxArray = taskList.slice();
    return auxArray.sort((f, s) => f.priority - s.priority);
  }

  const filterTasksByTag = (tag) => {
    return taskList.filter(item => item.tags.includes(tag));
  }

  const updateTask = (taskId, updates) => {
    
    let taskIndex = taskList.findIndex(t => t.id == taskId);
    taskList[taskIndex] = {...taskList[taskIndex], ...updates}
    return taskList;
  }

  return { addTask, removeTask, getTasks, getCompletedTasks, markTaskAsCompleted, getSortedTasksByPriority, filterTasksByTag, updateTask, getPendingTasks }
}

Creo que termine de entender con esta practica lo que clousere y scope, me tarde pero lo hice

Imagen anti-spoiler

let arrayTareas = [];

  function addTask(task) {
    arrayTareas.push({
      ...task,
      completed: false,
    });

    // arrayTareas.forEach((element) => (element.completed = false)); aca el probema es que a q todos los elementos del array cambiara a false
    return arrayTareas;
  }

  function removeTask(value) {
    const typeValue = typeof value;
    for (let tareas = 0; tareas < arrayTareas.length; tareas++) {
      if (typeValue === 'number' && value === arrayTareas[tareas].id) {
        arrayTareas.splice(arrayTareas[tareas], 1);
      } else if (typeValue === 'string' && value === arrayTareas[tareas].name) {
        arrayTareas.splice(arrayTareas[tareas], 1);
      }
    }
  }

  function getTasks() {
    return arrayTareas;
  }

  function getPendingTasks() {
    const pending = arrayTareas.filter(function (pendingTask) {
      return pendingTask.completed === false;
    });
    return pending;
  }

  function getCompletedTasks() {
    const completada = arrayTareas.filter(function (completeTask) {
      return completeTask.completed === true;
    });
    return completada;
  }

  function markTaskAsCompleted(value) {
    const typeValue = typeof value;
    for (let tareas = 0; tareas < arrayTareas.length; tareas++) {
      if (typeValue === 'number' && value === arrayTareas[tareas].id) {
        arrayTareas[tareas].completed = true;
      } else if (typeValue === 'string' && value === arrayTareas[tareas].name) {
        arrayTareas[tareas].completed = true;
      }
    }
    return arrayTareas;
  }

  function getSortedTasksByPriority() {
    const copiaArray = [...arrayTareas];
    const arrayOrdenadoProridad = copiaArray.sort(
      (a, b) => a.priority - b.priority
    );
    return arrayOrdenadoProridad;
  }

  function filterTasksByTag(tag) {
    const filtradoPorTag = arrayTareas.filter((etiqueta) =>
      etiqueta.tags.includes(tag)
    );
    return filtradoPorTag;
  }

  function updateTask(taskId, updates) {
    for (let element = 0; element < arrayTareas.length; element++) {
      if (arrayTareas[element].id === taskId) {
        arrayTareas[element] = { ...arrayTareas[element], ...updates };
      }
    }
  }

  return {
    addTask,
    removeTask,
    getTasks,
    getPendingTasks,
    getCompletedTasks,
    markTaskAsCompleted,
    getSortedTasksByPriority,
    filterTasksByTag,
    updateTask,
  };
function createTaskPlanner() {
    //  agregar, eliminar y marcar como completadas las tareas, así como también mostrar un registro de las mismas. 
    let tasksArray = []

    return {
        addTask: (task) => {
            task.completed = false
            tasksArray.push(task)
            console.log('Tarea agregada: ', task);
            console.table(tasksArray);
        },
        removeTask: (id) => {
            let idArray = []
            // hacer un arreglo con los ids
            console.log('Remover tareas con el id ', id);
            idArray = tasksArray.map((element)=>{
                return element.id
            })
            index = idArray.indexOf(id)
            let taskDeleted = tasksArray.splice(index, 1)
            console.log('Tarea eliminada: ', taskDeleted);
            console.table(tasksArray);
        },
        getTask: () =>  tasksArray,

        getPendingTask: () => {
            const pendingTasks = tasksArray.filter((element) => element.completed == false) 
            console.log('Tareas pendientes: ', pendingTasks);
            return pendingTasks
        },
        getCompletedTask: () => {
            const completedTasks = tasksArray.filter((element) => element.completed == true) 
            console.log(completedTasks);
            return completedTasks
        },
        markTaskAsCompleted: (value) => {
            console.log('Marcar tarea completada');
            let index
            if (typeof value === 'string') {
                let namesArray = []
                // hacer un arreglo con los names
                namesArray = tasksArray.map((element)=>{
                    return element.name
                })
                // encontramos el indice del arreglo
                index = namesArray.indexOf(value)

            } else {
                // hacer un arreglo con los names
                let idArray = tasksArray.map((element)=>{
                    return element.id
                })
                // encontramos el indice del arreglo
                index = idArray.indexOf(value)
            }
            // modificar el elemento con el index encontrado
            tasksArray[index].completed = true
        },

        getSortedTaskByPriority: ()=> {
            console.log('Devuelve copia de tareas ordenadas según su prioridad');
            let tasksArrayCopy = tasksArray.sort((a, b) => b.priority - a.priority)
            return tasksArrayCopy
        },

        filterTaskByTag: (valTag)=> {
            console.log('Filtra las tareas por una etiqueta específica');
            const taskArrayByTag = []

            tasksArray.forEach( element => {
                let result = element.tags.indexOf(valTag)
                if (result != -1){
                    taskArrayByTag.push(element)
                }
            })  
            
            return taskArrayByTag
        },

        updateTask: (taskId, updatesObj) => {
            let idArray = []
            // hacer un arreglo con los ids
            idArray = tasksArray.map((element)=>{
                return element.id
            })

            let index = idArray.indexOf(taskId)
            
            tasksArray[index].name = updatesObj.name,
            tasksArray[index].priority = updatesObj.priority,
            tasksArray[index].tags = updatesObj.tags

            return tasksArray
        }
    }
  }
  
const planner = createTaskPlanner()

// agregamos tres tareas
planner.addTask({
    id: 1,
    name: "Comprar leche",
    priority: 1,
    tags: ["shopping", "home"]
});


planner.addTask({
    id: 2,
    name: "Llamar a Juan",
    priority: 2,
    tags: ["personal"]
});

planner.addTask({
    id: 3,
    name: "Sacar a los perros",
    priority: 3,
    tags: ["soltarlos", "amarrarlos", "pasearlos", "darles de comer"]
});

// remover una tarea
planner.removeTask(1)

// devuelve el arreglo de tareas
const task = planner.getTask()
console.log('Arreglo de tareas: ', task);

// tareas pendientes
console.table(planner.getPendingTask());

// tareas completadas
console.table(planner.getCompletedTask())

// marcar tarea como completada
planner.markTaskAsCompleted("Sacar a los perros")
console.log(planner.getCompletedTask())

// ordenar el arreglo
console.table(planner.getSortedTaskByPriority())

// filtrar por tag
console.log(planner.filterTaskByTag('amarrarlos'))

// actualizar tarea por id
const updated = planner.updateTask(2, {
    name: "Comprar leche",
    completed: false,
    priority: 4,
    tags: ["shopping", "home"]
})

console.table(updated)

Uno de los retos más tardados, me llevo horas pero al fin quedo:

export function createTaskPlanner() {
  let tasks = [];

  function addTask(task) {
    task = { ...task, ...{ "completed": false } };
    tasks.push(task);
    return tasks;
  }

  function removeTask(value) {
    const encontrado = tasks.findIndex(n => n.id === value || n.name === value);
    tasks.splice(encontrado);
    return tasks;
  }

  function getTasks() {
    return tasks;
  }

  function getPendingTasks() {
    let pendingTasks = []
    for (const prop in tasks) {
      if (tasks[prop].completed === false) {
        pendingTasks.push(tasks[prop]);
      }
    }
    return pendingTasks;
  }

  function getCompletedTasks() {
    let completedTasks = []
    for (const prop in tasks) {
      if (tasks[prop].completed === true) {
        completedTasks.push(tasks[prop]);
      }
    }
    return completedTasks;
  }

  function markTaskAsCompleted(value) {
    const encontrado = tasks.findIndex(n => n.id === value || n.name === value);
    tasks[encontrado].completed = true;
    return tasks;
  }

  function getSortedTasksByPriority() {
    let priorityTasks = [...tasks];
    priorityTasks.sort((a, b) => a.priority - b.priority);
    return priorityTasks;
  }

  function filterTasksByTag(tag) {
    let filterTasks = []
    for (const prop in tasks) {
      for (const element of tasks[prop].tags) {
        if (element === tag) {
          filterTasks.push(tasks[prop]);
        }
      }
    }
    return filterTasks;
  }

  function updateTask(taskId, updates) {
    const encontrado = tasks.findIndex(n => n.id === taskId);
    let taskUpdate = [tasks[encontrado]];
    tasks[encontrado] = { ...taskUpdate[0], ...updates };
    return tasks;
  }

  return { addTask, removeTask, getTasks, getPendingTasks, getCompletedTasks, markTaskAsCompleted, getSortedTasksByPriority, filterTasksByTag, updateTask };
  }

aqui mi unico y original codigo;

export function createTaskPlanner() {
  let tasks = []
  function addTask(task) {
    task.completed = false
    tasks.push(task)
  }
  function removeTask(value) {
    const itemToRemove = tasks.findIndex(item => value === item.id || value === item.name)

    itemToRemove != -1 ? tasks.splice(itemToRemove, 1) : 'item not found'
  }
  function getTasks() {
    return tasks
  }
  function getPendingTasks() {
    const pendingTasks = tasks.map(item => {
      if (item.completed === false)
        return item
    })
    return pendingTasks.filter(item => item != undefined)
  }
  function getCompletedTasks() {
    const completedTasks = tasks.map(item => {
      if (item.completed === true)
        return item
    })
    return completedTasks.filter(item => item != undefined)
  }
  function markTaskAsCompleted(value) {
    const itemToMark = tasks.findIndex(item => value === item.id || value === item.name)
    tasks[itemToMark].completed = true
  }
  function getSortedTasksByPriority() {
    const newArray = tasks.map(x => x)
    newArray.sort((a, b) => a.priority - b.priority)
    return newArray
  }
  function filterTasksByTag(tag) {
    const itemsAreFiltered = tasks.filter(item => item.tags.includes(tag))
    return itemsAreFiltered
  }
  function updateTask(taskId, updates) {
    const itemToUpdate = tasks.findIndex(item => taskId === item.id)
    tasks[itemToUpdate] = { ...tasks[itemToUpdate], ...updates }
  }
  return {
    addTask,
    removeTask,
    getTasks,
    getPendingTasks,
    getCompletedTasks,
    markTaskAsCompleted,
    getSortedTasksByPriority,
    filterTasksByTag,
    updateTask
  }
}

++
+
+
++
+
+
+
++

export function createTaskPlanner() {
  let tasks = [];
  return {
    addTask(task) {
      let newTask = task;
      newTask["completed"] = false;
      console.log(newTask)
      tasks.push(newTask);
    },
    removeTask(valor) {
      let counter = 0;
      for (const [key, value] of Object.entries(tasks)) {
        console.log("0", counter, value.name, value.name === valor);
        if (value.id === valor) {
          if (counter === 0) {
            tasks.shift();
          }
          else {
            tasks.slice(counter - 1, counter);
          }
        }
        else if (value.name === valor) {
          if (counter === 0) {
            tasks.shift();
          }
          else {
            tasks.slice(counter - 1, counter);
          }
        }
        counter++;
      };
    },
    getTasks() {
      return tasks;
    },
    getPendingTasks() {
      let pendingTasks = [];
      for (const [key, value] of Object.entries(tasks)) {
        if (!value.completed) {
          pendingTasks.push(value);
        }
      };
      return pendingTasks;
    },
    getCompletedTasks() {
      let completedTasks = [];
      for (const [key, value] of Object.entries(tasks)) {
        if (value.completed) {
          completedTasks.push(value);
        }
      };
      return completedTasks;
    },
    markTaskAsCompleted(valor) {
      let counter = 0;
      for (const [key, value] of Object.entries(tasks)) {
        if (value.id === valor) {
          if (counter === 0) {
            tasks[counter].completed = true;
          }
          else {
            tasks[counter].completed = true;
          }
        }
        else if (value.name === valor) {
          if (counter === 0) {
            tasks[counter].completed = true;
          }
          else {
            tasks[counter].completed = true;
          }
        }
        counter++;
      };
    },
    getSortedTasksByPriority() {
      let tareas = [];
      let tareasMuyUrgente = [];
      for (const [key, value] of Object.entries(tasks)) {
        if (value.priority === 1) {
          tareasMuyUrgente.push(value);
        }
        else if (value.priority === 2) {
          tareas.unshift(value);
        }
        else if (value.priority === 3) {
          tareas.push(value);
        }
      }
      tareas = [...tareasMuyUrgente, ...tareas];
      console.log(tareas, "123");
      return tareas;
    },
    filterTasksByTag(tag) {
      let tasksByTag = [];
      for (const [key, value] of Object.entries(tasks)) {
        console.log(value.tags)
        for (let x = 0; x < value.tags.length; x++) {
          if (value.tags[x] === tag) {
            tasksByTag.push(value);
          }
        }
      }
      return tasksByTag;
    },
    updateTask(taskId, updates) {
      let update = updates;
      for (const [key, value] of Object.entries(tasks)) {
        console.log(key);
        if (value.id === taskId) {

          if (update.name != undefined) {
            tasks[key].name = update.name;
            delete update.name;
          }

          if (update.priority != undefined) {
            tasks[key].priority = update.priority;
            delete update.priority;
          }

          if (update.tags != undefined) {
            tasks[key].tags = update.tags;
            delete update.tags;
          }

          if (update.completed != undefined) {
            tasks[key].completed = update.completed;
            delete update.completed;
          }
          console.log(Object.entries(update).length != 0, update);
          if (Object.entries(update).length != 0) {
            Object.assign(tasks[key], update);
          }
        }
      }
    }

  }
}

Mi aporte:

export function createTaskPlanner() {
  let tasks = [];
  function addTask(task) {
    const obj = {
      id: task.id,
      name: task.name,
      priority: task.priority,
      tags: task.tags,
      completed: false
    }
    tasks.push(obj);
  }

  function removeTask(value) {
    let index;
    if (typeof value === 'number') {
      index = tasks.findIndex(el => el.id === value);
    } else if (typeof value === 'string') {
      index = tasks.findIndex(el => el.name === value);
    }

    if (index !== undefined && index !== null) {
      tasks.splice(index, 1);
    }
  }

  function getTasks() {
    return tasks;
  }

  function getPendingTasks() {
    let pendingTasks = tasks.filter(el => el.completed === false);
    return pendingTasks;
  }

  function getCompletedTasks() {
    let completedTask = tasks.filter(el => el.completed === true);
    return completedTask;
  }

  function markTaskAsCompleted(value) {
    let index;
    if (typeof value === 'number') {
      index = tasks.findIndex(el => el.id === value);
    } else if (typeof value === 'string') {
      index = tasks.findIndex(el => el.name === value);
    }

    if (index !== undefined && index !== null) {
      tasks[index].completed = true;
    }
  }

  function getSortedTasksByPriority() {
    let order = [...tasks]
    order.sort(function (a, b) {
      return a.priority - b.priority
    });

    return order;
  }

  function filterTasksByTag(tag) {
    let newTasks = [];
    tasks.forEach(el => {
      let flag = el.tags.includes(tag);
      if (flag) {
        newTasks.push(el);
      }
    });

    return newTasks;
  }

  function updateTask(taskId, updates) {
    let index;
    index = tasks.findIndex(el => el.id === taskId);
    tasks[index] = { ...tasks[index], ...updates };
  }

  return { addTask, removeTask, getTasks, getPendingTasks, getCompletedTasks, markTaskAsCompleted, getSortedTasksByPriority, filterTasksByTag, updateTask };
}

aquí mi solución al reto PLANIFICADOR DE TAREAS:

<function createTaskPlanner() {
    let tasks=[];
    return {
        'addTask': (task) => {
            const newTask = new Object();
            newTask.id=task.id;
            newTask.name=task.name;
            newTask.priority=task.priority;
            newTask.tags=task.tags;
            newTask.completed=false;
            
            const index = tasks.findIndex(item => item.id==task.id);
            if (index==-1){  //verifica que id no exista ya
                return tasks.push(newTask);
            }
            else{
                console.log('el id ya existe ');
                return index;
            }
        },
        'removeTask': (value)=> {
            const index = tasks.findIndex(task => task.id==value);
            return tasks.splice(index, 1);
        },
        'getTasks':() => {
            return tasks;
        },
        'getPendingTasks':()=> {
            return tasks.filter(task => !task.completed);
        },
        'getCompletedTasks':()=> {
            return tasks.filter(task => task.completed);
        },
        'markTaskAsCompleted':(value) => {
            const index = tasks.findIndex(task => task.name==value || task.id==value);
            if (index>-1)
                return tasks[index].completed=true;
            else
                return `La tarea con name o id = ${value} no existe`;
        },
        'getSortedTasksByPriority': () => {
            let tasksByPriority= [...tasks];
            return tasksByPriority.sort((a, b) => a.priority-b.priority);
        },
        'filterTasksByTag':(tag) => {
            return tasks.filter(task => task.tags.includes(tag));
        },
        'updateTask':(taskId, updates) => {
            const index = tasks.findIndex(item => item.id === taskId);
            if(index>-1){
                tasks[index] = {
                    ...tasks[index],
                    ...updates,
                };
            }else
                return `La tarea con id = ${value} no existe`;
        }

    }
};> 

Aquí mi solución

export function createTaskPlanner() {
  // Tu código aquí 👈
  const tasks = [];
  return {
    addTask: task => {
      tasks.push({
        ...task,
        completed: false,
      });
    },

    removeTask: value =>
      tasks.splice(
        tasks.findIndex(task => {
          return task.id === value || task.name === value;
        }),
        1
      ),

    getTasks: () => tasks,

    getPendingTasks: () => tasks.filter(task => !task.completed),

    getCompletedTasks: () => tasks.filter(task => task.completed == true),

    markTaskAsCompleted: value => {
      let index = tasks.findIndex(task => task.id === value || task.name === value)
      tasks[index].completed = true;
    },

    getSortedTasksByPriority: () => {
      return tasks.slice(0).sort((t1, t2) => t1.priority - t2.priority);
    },

    filterTasksByTag: tag => {
      return tasks.filter(task => task.tags.includes(tag));
    },

    updateTask: (taskId, updates) => {
      let index = tasks.findIndex(task => task.id === taskId);
      tasks[index] = {...tasks[index], ...updates}
    },
  };
}

mmm the solution:

function createTaskPlanner() {
  let tasks = [];
  function addTask(task){
    task.completed = false;
    tasks.push(task);
  }

  function removeTask(value) {
    let index = null;
    if(typeof value == "number"){
      index = tasks.findIndex(task => task.id === value);
    }else{
      index = tasks.findIndex(task => task.name === value);
    }
    if(index > -1) {
      tasks.splice(index, 1);
    }
    return index;
  }

  function getTasks() {
    return tasks;
  }

  function getPendingTasks() {
    let pedingtasks = [];
    tasks.forEach(task => {
      if(task.completed == false) {
        pedingtasks.push(task);
      }
    });
    return pedingtasks;
  }

  function getCompletedTasks() {
    let completedTasks = [];
    tasks.forEach(task => {
      if(task.completed == true) {
        completedTasks.push(task);
      }
    });
    return completedTasks;
  }

  function markTaskAsCompleted(value) {
    if(typeof value == "number"){
      index = tasks.findIndex(task => task.id === value);
    }else{
      index = tasks.findIndex(task => task.name === value);
    }
    tasks[index].completed = true;
    return tasks[index];
  }

  function getSortedTasksByPriority() {
    let tasksbypriority = [];
    let priorities = [];
    for(let i=0; i<tasks.length; i++) {
      if(!priorities.includes(tasks[i].priority)){
        priorities.push(tasks[i].priority);
      }
    }

    priorities.sort().forEach(priority => {
      tasks.forEach(task => {
        if(task.priority === priority){
          tasksbypriority.push(task)
        }
      })
    });
    
    return tasksbypriority;
  }

  function filterTasksByTag(tag) {
    let taskbytag = [];
    tasks.forEach(task => {
      if(task.tags.includes(tag)){
        taskbytag.push(task);
      }
    });
    return taskbytag;
  }

  function updateTask(taskId, updates) {
    index = tasks.findIndex(task => task.id === taskId);
    tasks[index] = { ...tasks[index], ...updates }
    return tasks[index];
  }
  return {
    addTask,
    removeTask,
    getTasks,
    getPendingTasks,
    getCompletedTasks,
    markTaskAsCompleted,
    getSortedTasksByPriority,
    filterTasksByTag,
    updateTask
  }
}

Después de varias correcciones, pude realizar el ejercicio

xport function createTaskPlanner() {
  let tasks = []
 
  const addTask=(task) => {
      task.completed = false
      tasks.push(task)
    }
  const removeTask=(value) => {
      const idx = tasks.findIndex(item => item.id === value || item.name === value)      
      if (idx > - 1)
        tasks.splice(idx, 1)
      return tasks
    }
  const getTasks= () => tasks
  const getPendingTasks= () => tasks.filter(task => task.completed === false)
  const getCompletedTasks= () => tasks.filter(task => task.completed === true)
  const markTaskAsCompleted=(value) => {
      const idx = tasks.findIndex(item => item.id === value || item.name === value)
      if (idx > - 1)
        tasks[idx].completed = true      
      return tasks 
    }
  const getSortedTasksByPriority=() => {
      taskspriority=[...tasks]
      taskspriority.sort(
        (task1, task2) => task1.priority - task2.priority
      )
      return taskspriority
    }
  const filterTasksByTag=(tag) => tasks.filter(task => task.tags.includes(tag))
  const updateTask=(taskId, updates)=>{
      const idx = tasks.findIndex(item => item.id === taskId)
      if (idx > - 1)
        tasks[idx] = { ...tasks[idx], updates }    
    }
  return { 
    addTask,
    removeTask,
    getTasks,
    getPendingTasks,
    getCompletedTasks,
    markTaskAsCompleted,
    getSortedTasksByPriority,
    filterTasksByTag,
    updateTask
  }
}

comparto mi solución compañeros:
.
.
.
.
.
.
.
.
.

  // Tu código aquí 👈
  const tasks = [];

  return {
    addTask: (task) => {
      tasks.push({...task, completed: false})
    },
    removeTask: (value) => {
      // value es o el id o el nombre.
      if ((typeof value) === "number") {
        const x = tasks.findIndex(it => it.id === value)
        if (x != -1) {
          tasks.splice(x, 1);
        }
      }
      else if ((typeof value) === "string") {
        const x = tasks.findIndex(it => it.name === value)
        if (x != -1) {
          tasks.splice(x, 1);
        }
      }
    },
    getTasks: () => tasks,
    getPendingTasks: () => {
      const result = tasks.filter(item => !item.completed);
      return result;
    },
    getCompletedTasks: () => {
      const result = tasks.filter(item => item.completed);
      return result;
    },
    markTaskAsCompleted: (value) => {
      // value puede ser numero o string.
      if ((typeof value) === "number") {
        const x = tasks.findIndex(it => it.id === value)
        if (x != -1) {
          const aux = tasks[x];
          tasks[x] = { ...aux, completed: true }
        }
      }
      else if ((typeof value) === "string") {
        const x = tasks.findIndex(it => it.name === value)
        if (x != -1) {
          const aux = tasks[x];
          tasks[x] = { ...aux, completed: true }
        }
      }
    },
    getSortedTasksByPriority: () => {
      const newArray = [...tasks];
      newArray.sort((a, b) => {
        return a.priority - b.priority;
      })
      return newArray;
    },
    filterTasksByTag: (tag) => {
      return tasks.filter(item => item.tags.includes(tag))
    },
    updateTask: (taskId, updates) => {
      const i = tasks.findIndex(tk => tk.id === taskId)
      if (i != -1) {
        const aux = tasks[i];
        tasks[i] = { ...aux, ...updates}
      }
    }
  }
}

Comparto mi solución:

export function createTaskPlanner() {
  const tasks = [];
  const addTask = (task) => {
    tasks.push({ ...task, completed: false })
  }
  const removeTask = (value) => {
    const index = tasks.findIndex((task) => task.id === value || task.name === value);
    tasks.splice(index, 1);
  }
  const getTasks = () => tasks;

  const getPendingTasks = () => tasks.filter((task) => task.completed === false);
  const getCompletedTasks = () => tasks.filter((task) => task.completed === true);

  const markTaskAsCompleted = (value) => {
    const index = tasks.findIndex((task) => task.id === value || task.name === value);
    tasks[index] = { ...tasks[index], completed: true }
  }

  const getSortedTasksByPriority = () => {
    const sorted = [...tasks];
    sorted.sort((a, b) => a.priority - b.priority);
    return sorted;
  }
  const filterTasksByTag = (tag) => tasks.filter(task => task.tags.includes(tag));
  const updateTask = (taskId, updates) => {
    const index = tasks.findIndex((task) => task.id === taskId);
    tasks[index] = { ...tasks[index], ...updates }
  }

  return {
    addTask,
    removeTask,
    getTasks,
    getPendingTasks,
    getCompletedTasks,
    markTaskAsCompleted,
    getSortedTasksByPriority,
    filterTasksByTag,
    updateTask
  }
}

Es increible el nivel de optimizacion que se obtiene con algunas estructuras del estilo del update, wow, sencillamente wow.
.
.
.
.
.
.
.
.
.
.
.
export function createTaskPlanner() {
let tareas = [];

return {
addTask(task) {

  task.completed = false;
  tareas.push(task);
  return task;

},
removeTask(value) {
  if (typeof (value) == 'number') {
    tareas = tareas.filter(t => t.id != value);
  } else {
    tareas = tareas.filter(t => t.name != value);
  }
},
getTasks() {
  return tareas;
},
getPendingTasks() {
  return tareas.filter(t => t.completed == false);
},
getCompletedTasks() {
  return tareas.filter(t => t.completed == true);
},
markTaskAsCompleted(value) {
  if (typeof (value) == 'number') {
    return tareas.filter(t => t.id == value).forEach(t => t.completed = true);
  } else {
    return tareas.filter(t => t.name == value).forEach(t => t.completed = true);
  }
},
getSortedTasksByPriority() {
  //Detalle consultado de respuesta, nota menta, sort modifica elarray que ordena (visto enperspectiva es obvio xD)
  const sortedTasks = [...tareas].sort((a, b) => parseFloat(a.priority) - parseFloat(b.priority));
  return sortedTasks;
},
filterTasksByTag(tag) {
  return tareas.filter(
    t => t.tags.some(tg => tg == tag)
  );
},
updateTask(taskId, updates) {
  //tomado del resultado, daba un error que aun no entiendo de extender task. Increible lo compacto de este codigo.
  const index = tareas.findIndex((t) => t.id === taskId);
  tareas[index] = { ...tareas[index], ...updates }; 
  /*actualizar = tareas.filter(t => t.id == taskId);
  if (actualizar) {
    if (updates.id) actualizar.id = updates.id;
    if (updates.name) actualizar.name = updates.name;
    if (updates.priority) actualizar.priority = updates.priority;
    if (updates.tags) actualizar.tags = updates.tags;
    if (updates.completed) actualizar.completed = updates.completed;
  }
  return actualizar;
  */
}

}

}

MI SOLUCION 💪
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

export function createTaskPlanner() {
  let tasks = [];
  return {
    addTask(task) {
      task.completed = false;
      tasks.push(task);
    },
    removeTask(value) {
      tasks = tasks.filter(task =>
        typeof value === "number" ?
          task.id != value : task.name != value);
    },
    getTasks() {
      return tasks;
    },
    getPendingTasks() {
      return tasks.filter(task => !task.completed);
    },
    getCompletedTasks() {
      return tasks.filter(task => task.completed);
    },
    markTaskAsCompleted(value) {
      let key = typeof value === "number" ?
        tasks.findIndex(task => task.id === value) :
        tasks.findIndex(task => task.name === value);
      tasks[key].completed = true;
    },
    getSortedTasksByPriority() {
      return [...tasks].sort((a, b) => a.priority - b.priority);
    },
    filterTasksByTag(tag) {
      return tasks.filter(task => task.tags.includes(tag));
    },
    updateTask(taskId, updates) {
      let key = tasks.findIndex(task => task.id === taskId);
      tasks[key] = { ...tasks[key], ...updates };
    }
  };
}

¡Hola, Desafío cumplido 😃!

Mi solución,
Se detalla hasta abajo.⬇

export   function createTaskPlanner() {

  let mylist = [];

  return   {
    addTask(ptask) {
      ptask.completed = false;
      mylist.push(ptask);
    },
    getTasks() {
      return (mylist);
    },
    getPendingTasks()
    {
      return (mylist.filter((item) => { item.completed === false }));
    },
    removeTask(value)
    {
      if (typeof (value) === "number")
        mylist = mylist.filter((item) => { item.id !== value });
      else
        mylist = mylist.filter((item) => { item.name !== value });
    },
    getCompletedTasks() {
      return (mylist.filter((item) =>  item.completed ));
    },
    markTaskAsCompleted(value) {
      let index = (typeof value === "number") ? mylist.findIndex(item => item.id === value) : mylist.findIndex((item) => item.name === value);
      mylist[index].completed = true;
    },
    getSortedTasksByPriority() {
      const newTasks = [...mylist].sort((a, b) => a.priority - b.priority);

      return newTasks;
    },
    filterTasksByTag(tag) {
      return mylist.filter((item) => item.tags.includes(tag));
    },
    updateTask(taskId, updates) {
      const index = mylist.findIndex((item) => item.id === taskId);

      mylist[index] = { ...mylist[index], ...updates };
    }
  }


}

🦆
🦆
🦆
🦆
🦆
🦆
🦆
🦆

Solucion

.
.
.
.
.
.
.
.
.
.
.
.

export function createTaskPlanner() {
  // Tu código aquí 👈
  let taskList = [];
  const addTask = task => {
    task.completed = false;
    taskList.push(task);
  } 
  const removeTask = value => {
      if (typeof value === 'string') {
        taskList = taskList.filter(task => task.name !== value);
      } else {
        taskList = taskList.filter(element => element.id !== value);
      }
  }
  const getTasks = () => {
    return taskList;
  }

  const getPendingTasks = () => {
    return taskList.filter(task => !task.completed);
  }

  const getCompletedTasks = () => {
    return taskList.filter(task => task.completed);
  }

  const markTaskAsCompleted = value => {
    taskList = taskList.map(task => {
      let newValue = typeof value === 'string' ? task.name : task.id;
      if (newValue === value) {
        task.completed = true;
      }
        return task;
    });  
  }

  const getSortedTasksByPriority = () => {
    return [...taskList].sort((a, b) => a.priority - b.priority);  
  }

  const filterTasksByTag = tag => {
    return taskList.filter(task => task.tags.includes(tag));
  }

  const updateTask = (taskId, updates) => {
    const index = taskList.findIndex(task => task.id === taskId)
    taskList[index] = { ...taskList[index], ...updates };
  }

  return {
    addTask,
    removeTask,
    getTasks,
    getPendingTasks,
    getCompletedTasks,
    markTaskAsCompleted,
    getSortedTasksByPriority,
    filterTasksByTag,
    updateTask
  }
}

Gracias a este ejercicio aprendí mucho de recorrido de arrays y de prototipos. Aquí mi solución:
.
.
.
.
.

function createTaskPlanner() {
  let tasks = [];
  let methods = {
    addTask : ({ id, name, priority, tags = [], completed = false }) =>{
      let task = { id, name, priority, tags, completed}
      if (task.completed == false) { tasks.push(task)}      
    },
    removeTask: (value) => {
      const taskObjFound = findTask(value)
      if (taskObjFound.taskFound) { tasks.splice(taskObjFound.indexTask,1)}
    },
    getTasks: () => { return tasks },
    getPendingTasks: () => { return tasks.filter(task => task.completed == false) },
    getCompletedTasks: () => { return tasks.filter(task => task.completed == true) },
    markTaskAsCompleted: (value) => {
      const taskObjFound = findTask(value)
      if (taskObjFound.taskFound.completed != true) {taskObjFound.taskFound.completed=true}
    },
    getSortedTasksByPriority: () => {
      let sortedTasks = [...tasks]
      sortedTasks.sort((a, b) => { return a.priority - b.priority })
      return sortedTasks
    },
    filterTasksByTag: (tag) => {
      return tasks.filter((task) => {
        return task.tags.includes(tag)
      })
    },
    updateTask: (taskId, updates) => {
      const taskObjFound = findTask(taskId)
      const updatedTask = Object.assign({}, taskObjFound.taskFound, updates)
      Object.assign(tasks[taskObjFound.indexTask],updatedTask)      
    }
  }
  function findTask(value) {
    const taskFound = tasks.find((task) => { return (task.id == value || task.name == value) })
    const indexTask = tasks.indexOf(taskFound)
    return { taskFound, indexTask}
  }
  return methods
}

Este ejercicio estaba medio complicadete pero más que eso algo extenso.

Mi solución:

export function createTaskPlanner() {
  let allTasks = []
  return {
    addTask: function (task) {
      allTasks.push({ ...task, completed: false })
    },
    removeTask: function (value) {
      allTasks = allTasks.filter((task) => {
        if (task.name === value || task.id === value) return false
        return true
      })
    },
    getTasks: function () {
      return allTasks
    },
    getPendingTasks: function () {
      return allTasks.filter((task) => task.completed === false)
    },
    getCompletedTasks: function () {
      return allTasks.filter((task) => task.completed === true)
    },
    markTaskAsCompleted: function (value) {
      allTasks.forEach(task => {
        if (task.name === value || task.id === value) task.completed = true
      })
    },
    getSortedTasksByPriority: function () {
      let deepCopy = JSON.parse(JSON.stringify(allTasks))
      return deepCopy.sort((a, b) => a.priority - b.priority)
    },
    filterTasksByTag: function (tag) {
      return allTasks.filter((task) => {
        if (task.tags.includes(tag)) return true
        return false
      })
    },
    updateTask: function (taskId, updates) {
      allTasks = allTasks.map(task => {
        if (task.id === taskId) {
          return { ...task, ...updates }
        }
        return task
      })
    }
  }
}

Solución

export function createTaskPlanner() {
  // Tu código aquí 👈
  let tasks = [];

  function addTask(task) {
    task.completed = false;
    tasks.push(task);
  }
  function removeTask(value) {
    tasks = tasks.filter(t => (t.id != value && t.name != value));
  }
  function getTasks() {
    return tasks;
  }
  function getPendingTasks() {
    return tasks.filter(t => t.completed === false)
  }
  function getCompletedTasks() {
    return tasks.filter(t => t.completed === true)
  }
  function markTaskAsCompleted(value) {
    tasks.find(function (task) {
      if (task.id == value || task.name == value)
        task.completed = true;
    });
  }
  function getSortedTasksByPriority() {
    let sortedTasks = [...tasks];
    return sortedTasks.sort((b, a) => b.priority - a.priority);
  }
  function filterTasksByTag(tag) {
    let filterTasks = [];
    tasks.forEach(function(task) {
      let taskAdd = task.tags.find(t => t == tag);
      if (taskAdd) {
        filterTasks.push(task);
      }        
    })
    return filterTasks;
  }
  function updateTask(taskId, updates) {
    let index = tasks.findIndex(t => t.id === taskId);
    tasks[index] = { ...tasks[index], ...updates };
  }

  return {
    addTask,
    removeTask,
    getTasks,
    getPendingTasks,
    getCompletedTasks,
    markTaskAsCompleted,
    getSortedTasksByPriority,
    filterTasksByTag,
    updateTask
  }
}

MI solución:

export function createTaskPlanner() {
  const task = [];
  return {
    addTask:(a)=>{a.completed=false;task.push(a)},
    getTasks:()=>task,
    removeTask:(a)=>{task.forEach(e=>{if(a==e.id || a==e.name)task.splice(task.indexOf(e), task.indexOf(e)+1);}) },
    getPendingTasks:(a)=>task.filter((o)=>o.completed==false),
    getCompletedTasks:(a)=>task.filter((o)=>o.completed==true),
    markTaskAsCompleted:(a)=>{task.forEach(e=>{if(a==e.id || a==e.name) e.completed=true;}) },
    getSortedTasksByPriority:(a)=>task.slice().sort((a,b)=>a.priority-b.priority),
    filterTasksByTag:(a)=>{return task.filter(e=>{if(e.tags.includes(a))return e;}) },
    updateTask:(a,b)=>{return task.map(e=>{if(a==e.id){ return Object.assign(e,b);};}) },
  }
}

Hola, dejo mi solucion
Caminito anti spoilers
🚗
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Llegamos 📍

export function createTaskPlanner() {
  // Tu código aquí 👈
  let tasks = [];
  const addTask = (task) => tasks.push({ ...task, completed: false });
  const removeTask = (value) => {
    const index = tasks.findIndex((item) => item.id === value || item.name === value)
    tasks.splice(index, 1)
  };
  const getTasks = () => tasks;
  const getPendingTasks = () => tasks.filter((item) => !item.completed);
  const getCompletedTasks = () => tasks.filter((item) => item.completed);
  const markTaskAsCompleted = (value) => {
    const index = tasks.findIndex((item) => item.id === value || item.name === value)
    tasks[index].completed = true;
  };
  const getSortedTasksByPriority = () => {
    const result = [...tasks];
    function compare_priority(a, b) {
      if (a.priority < b.priority) return -1;
      if (a.priority > b.priority) return 1;
      return 0;
    }
    return result.sort(compare_priority)
  };
  const filterTasksByTag = (value) => tasks.filter((item) => item.tags.includes(value))//.filter((tag) => tag === value));
  const updateTask = (taskId, updates) => {
    const index = tasks.findIndex((item) => item.id === taskId)
    tasks[index] = { ...tasks[index], ...updates}
  };
  return {
    addTask,
    removeTask,
    getTasks,
    getPendingTasks,
    getCompletedTasks,
    markTaskAsCompleted,
    getSortedTasksByPriority,
    filterTasksByTag,
    updateTask
  }
}

Me costó pero al final lo logré ✍(◔◡◔)
Lo único que me fallaba al final es que con la función sort(), se modificaba la lista original y tenía que retornar una copia de la lista. Hasta que ví la documentación de sort le entendí. (╯▽╰ )

export function createTaskPlanner() {
  let tasks = [];
  return {
    addTask: function (task) {
      tasks.push({ ...task, completed: false });
    },
    removeTask:function(value){
      tasks = tasks.filter((task) => task.id != value && task.name != value);
    },
    getPendingTasks:function(){
      return tasks.filter((task)=> task.completed != true);
    },
    getTasks: function () {
      return tasks;
    },
    markTaskAsCompleted:function(value){
      tasks.find((task) => task.id == value || task.name == value ).completed = true;
    },
    getCompletedTasks:function(){
      return tasks.filter((task) => task.completed==true);
    },
    getSortedTasksByPriority(){
      return [...tasks].sort((b,a)=> b.priority - a.priority);
    },
    filterTasksByTag:function(tagsearch){
      let filters = [];
     tasks.forEach(task =>{
        let res = task.tags.find(tag => tag == tagsearch);
        if(res){
          filters.push(task);
        }
     });
     return filters;
    },
    updateTask:function(taskId, updates){
      let index = tasks.findIndex(task =>task.id == taskId );
      tasks[index] = {...tasks[index],...updates};
    }
  }
}

tuve algun typo con los nombres de los metodos y una tonta confusión con el retorno de find y filter pero aquí esta mi solucion:

Spoiler
.
.
.
.
.
.
.
.
.
.
.
.

export function createTaskPlanner() {
  let taskArray = [];

  return {
    addTask: (taskObj) => {
      taskObj.completed = false;
      taskArray.push(taskObj);
    },
    removeTask: (taskNameOrId) => {
      let taskToRemoveIndex = taskArray.findIndex(task => task.name == taskNameOrId || task.id == taskNameOrId);
      taskArray.splice(taskToRemoveIndex, 1);
    },
    getTasks: () => taskArray,
    getPendingTasks: () => taskArray.filter(task => task.completed == false),
    getCompletedTasks: () => taskArray.filter(task => task.completed == true),
    markTaskAsCompleted: (taskNameOrId) => {
      let taskIndex = taskArray.findIndex(task => task.name == taskNameOrId || task.id == taskNameOrId);
      taskArray[taskIndex].completed = true;
    },
    getSortedTasksByPriority: () => {
      let sortedTaskByPriority = [...taskArray].sort((a, b) => a.priority - b.priority);
      return sortedTaskByPriority;
    },
    filterTasksByTag: (taskTag) => {
      return taskArray.filter(task => task.tags.includes(taskTag));
    },
    updateTask: (taskId, updates) => {
      let task = taskArray.find(task => task.id == taskId);
      for (const prop in updates) {
        task[prop] = updates[prop];
      }
    }
  }
}

Este estuvo muy entretenido. Adjunto mi solución
.
.
.
.
.
.
.
.
.
.

export function createTaskPlanner() {
  const allTasks = []

  // to use in other functions
  function findTaskIndex(taskIdOrName) {
    const taskIndex = allTasks.findIndex(task => {
      if (typeof taskIdOrName === 'number') {
        return task.id === taskIdOrName
      }
      return task.name.toLowerCase() === taskIdOrName.toLowerCase()
    })
    return taskIndex
  }

  return {
    addTask(task) {
      allTasks.push({ ...task, completed: false })
    },
    
    getTasks() {
      return allTasks
    },

    removeTask(taskIdOrName) {
      allTasks.splice(findTaskIndex(taskIdOrName), 1)
    },

    getPendingTasks() {
      return allTasks.filter(task => !task.completed)
    },

    getCompletedTasks() {
      return allTasks.filter(task => task.completed)
    },

    markTaskAsCompleted(taskIdOrName) {
      allTasks[findTaskIndex(taskIdOrName)].completed = true
    },

    updateTask(taskIdOrName, updatedTask) {
      allTasks[findTaskIndex(taskIdOrName)] = {
        ...allTasks[findTaskIndex(taskIdOrName)],
        ...updatedTask
      }
    },

    filterTasksByTag(tagToFilter) {
      return allTasks.filter(task => task.tags.find(tag => tag === tagToFilter))
    },

    getSortedTasksByPriority() {
      const sortedTasks = [...allTasks]
      return sortedTasks.sort((a, b) => a.priority - b.priority)
    }
  }
}

Aqui mi solucion donde use metodos como filter(), map() y sort(). Cualquier comentario o pregunta es bienvenido.
.
.
.
.
.
.
.
.
.

export function createTaskPlanner() {
  let tareas = [];

  function addTask(task) {
    task.completed = false;
    tareas.push(task);
  }

  function removeTask(value) {
    tareas = tareas.filter((obj) => obj.id !== value && obj.name !== value);
  }

  function getTasks() {
    return tareas;
  }

  function getPendingTasks() {
    return tareas.filter((obj) => obj.completed === false);
  }

  function getCompletedTasks() {
    return tareas.filter((obj) => obj.completed === true);
  }

  function markTaskAsCompleted(value) {
    tareas = tareas.map((obj) => {
      if (obj.id === value || obj.name === value) {
        obj.completed = true;
      }
      return obj;
    })
  }

  function getSortedTasksByPriority() {
    return [...tareas].sort((a, b) => a.priority - b.priority);
  }

  function filterTasksByTag(tag) {
    let filter = tareas.filter((obj) => {
      for (let h = 0; h < obj.tags.length; h++) {
        if (obj.tags[h] === tag) {
          return obj;
        }
      }
    })

    return filter;
  }

  function updateTask(taskId, updates) {
    const index = tareas.findIndex((task) => task.id === taskId);
    Object.assign(tareas[index], updates)
  }

  return {
    addTask,
    removeTask,
    getTasks,
    getPendingTasks,
    getCompletedTasks,
    markTaskAsCompleted,
    getSortedTasksByPriority,
    filterTasksByTag,
    updateTask
  }
}
export function createTaskPlanner() {
  let tasks = [];

  return {
    addTask: (task) => tasks.push({ ...task, completed: false }),
    removeTask: (value) => tasks = tasks.filter(({ id, name }) => !(id === value || name === value)),
    getTasks: () => tasks,
    getPendingTasks: () => tasks.filter(({ completed }) => !completed),
    getCompletedTasks: () => tasks.filter(({ completed }) => completed),
    markTaskAsCompleted: (value) => tasks = tasks.map((task) => (task.name == value || task.id == value) ? { ...task, completed: true } : task),
    getSortedTasksByPriority: () => [...tasks].sort((a, b) => a.priority - b.priority),
    filterTasksByTag: (tag) => tasks.filter(({ tags }) => tags.includes(tag)),
    updateTask: (taskId, updates) => tasks = tasks.map((task) => (task.id === taskId) ? { ...task, ...updates } : task),
  }
}

El reto se ve largo; pero si es posible lograrlo! Los animo a intentar, ir poco a poco, roma no se construyó en un día!
.
.
.
.
Aqui mi solución
.
.
.
.
.

.

export function createTaskPlanner() {
  let tareas = [];
  return {
    addTask: function (task) { task.completed = false; tareas.push(task) },
    removeTask: function (value) {
      tareas.forEach(item => item.id || item.name == value, tareas.splice(this.item))
    },
    getTasks: function () { return tareas },
    getPendingTasks: function () { return tareas.filter(tarea => tarea.completed == false); },
    getCompletedTasks: () => {
      return tareas.filter(({ completed }) => completed)
    },
    markTaskAsCompleted: function (value) {
      tareas.forEach(function (tarea) {
        if (tarea.id || tarea.name == value) {
          tarea.completed = true
        }
      })
    },
    getSortedTasksByPriority: function () {
      let tasks = [].concat(tareas).sort((a, b) => a.priority - b.priority);
      return tasks
    },
    filterTasksByTag: function (tag) {
      return tareas.filter(function (tarea) {
        return tarea.tags.includes(tag);
      })
    },
    updateTask: function (taskId, updates) {
      const index = tareas.findIndex(item => item.id === taskId)
      tareas[index] = { ...tareas[index], ...updates };
    },
  }
}

Estuvo mucho más difícil que los anteriores pero aporto mi solución!
.
.
.
.
.
.
.
.
.
Tuve que agregar una sección de código que verifique si ya existe [‘completed’] en la tarea que llega como parámetro, ya que por alguna razón se ejecuta cada vez que realizo cualquier acción y vuelve a poner en false todas las tareas

export function createTaskPlanner() {
  let tareas = []
  return {

    //Agrega una nueva tarea, primero filtra si esa tarea ya tiene definido 'completed', si aún no está definido lo inicia con false
    addTask: function (task) {
      if (task['completed'] === undefined) {
        task['completed'] = false
      }
      tareas.push(task)
    },

    //A partir de un valor obtenido como parámetro chequea si coincide con el nombre o la ID y lo elimina del arreglo de tareas
    removeTask: function (value) {
      for (let i = 0; i < tareas.length; i++) {
        if (value == tareas[i]['name'] || value == tareas[i]['id']) {
          tareas.splice(i,1)
        }
      }
    },

    //retorna el arreglo de tareas
    getTasks: function() {
      return tareas
    },

    //Recorre el arreglo de tareas y chequea si 'completed' es verdadero o falso. Si es falso, lo agrega a la lista de tareas no completadas
    getPendingTasks: function(){
      let noCompletadas = []
      for (const tarea of tareas) {
        if (!tarea['completed']) {
          noCompletadas.push(tarea)
        }
      }
      return noCompletadas
    },

    //Recorre el arreglo de tareas y chequea si 'completed' es verdadero o falso. Si es verdadero, lo agrega a la lista de tareas completadas
    getCompletedTasks: function () {
      let completadas = []
      for (const tarea of tareas) {
        if (tarea['completed']) {
          completadas.push(tarea)
        }
      }
      return completadas
    },

    //Recorre la lista de tareas una por una y cuando encuentra una coincidencia la marca como verdadera
    markTaskAsCompleted: function(value){
      for (const tarea of tareas) {
        if (value == tarea['name'] || value == tarea['id']) {
          tarea['completed'] = true
          }
        }
    },

    //Organiza de mayor a menor prioridad. Utilizando el método slice() para generar una copia del arreglo de tareas y luego ordenarlo, ya que el método sort() modifica el arreglo original 
    getSortedTasksByPriority: function () {
      let ordenado = tareas.slice().sort((tarea1, tarea2) => (tarea1.priority < tarea2.priority) ? -1 : (tarea1.priority > tarea2.priority) ? 1 : 0)
      return ordenado
    },

    //Recorre todas las tareas, y si dentro de los tags de una tarea está el tag recibido como parámetro lo devuelve en un nuevo arreglo
    filterTasksByTag: function (tag) {
      return tareas.filter((tarea) => tarea.tags.includes(tag))
    },

    //Recorre todo el arreglo hasta encontrar una coincidencia y actualiza los datos de la tarea con los que se encuentran en updates. También recorre updates para encontrar y aplicar todas las actualizaciones
    updateTask: function (taskId, updates) {
      for (const tarea of tareas) {
        if (taskId === tarea['id']) {
          for (const [nombre, dato] of Object.entries(updates)) {
            tarea[nombre] = dato
          }
          break
        }
      }
    }

  }
}

export function createTaskPlanner() {

  let taskList = [];

  return {
    addTask: function (task) { //ok
      task.completed = false;
      taskList.push(task);
    },
    removeTask: function (value) {//ok

      for (let i = 0; i < taskList.length; i++) {
        if (taskList[i].id === value || taskList[i].name === value) {
          taskList.splice(i, 1);
        }
      }
    },
    getTasks: function () {//ok
      return taskList;
    },
    getPendingTask: function () {//ok
      let pending = [];
      for (t of taskList) {
        if (!t.completed) pending.push(t);
      }
      return pending;
    },
    getCompletedTasks: function () {//ok
      let completedTask = [];
      for (let t of taskList) {
        if (t.completed) completedTask.push(t);
      }
      return completedTask;
    },
    markTaskAsCompleted: function (value) {//ok

      for (let i = 0; i < taskList.length; i++) {
        if (taskList[i].id === value || taskList[i].name === value) {
          taskList[i].completed = true;
        }
      }
    },
    getSortedTasksByPriority: function () {
      let sortedList = [...taskList];

     sortedList.sort((a, b) =>
        a.priority - b.priority
      )
      return sortedList;
    },
    filterTasksByTag: function (tag) {

      let filtered = [];
      for (let i = 0; i < taskList.length; i++) {
        for (let j = 0; j < taskList[i].tags.length; j++) {
          if (taskList[i].tags[j] === tag) {
            filtered.push(taskList[i]);
            break;
          }
        }
      }
      return filtered;
    },
    updateTask: function (taskId, updates) {
      for (let i = 0; i < taskList.length; i++) {
        if (taskList[i].id === taskId) {
          taskList[i] = { ...taskList[i], ...updates };

          break;
        }
      }
    }
  }
}

.
. ----------------------------------------------
. USENME COMO ESCUDO
. ANTI SPOILER
. ----------------------------------------------
.
.
.
.
.

.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.

export function createTaskPlanner() {
  let tasks = []

  return {

    addTask: (task) => {
      tasks.push({ ...task, completed: false })
    },

    removeTask: (value) => {
      tasks = tasks.filter(({ id, name }) => !(id === value || name === value)
      )
    },

    getTasks: () => tasks,

    getPendingTasks: () => {
      return tasks.filter(({ completed }) => !completed)
    },

    getCompletedTasks: () => {
      return tasks.filter(({ completed }) => completed)
    },

    markTaskAsCompleted: (value) => {

      tasks = tasks.map((task) => {

        let { id, name, priority, tags } = task

        return (name == value || id == value) ? {
          id, name, priority, tags, completed: true
        } : task

      })

    },

    getSortedTasksByPriority: () => {
      let copyTasks = [...tasks]

      return copyTasks.sort((a, b) => a.priority - b.priority)
    },

    filterTasksByTag: (tag) => {
      return tasks.filter(({ tags }) => tags.includes(tag))
    },

    updateTask: (taskId, updates) => {
      tasks = tasks.map((task) =>
        (task.id === taskId) ? { ...task, ...updates } : task
      )
    }

  }
}

se que podria hacerlo mejor usar menos spreed pero queria usarlo.