guesstimate/src/hooks/use-project-reducer.ts

159 lines
4.0 KiB
TypeScript

import { Project } from "../models/project";
import { Task, TaskID, EstimationConfidence } from "../models/task";
import { useReducer } from "preact/hooks";
export interface Action {
type: string
}
export type ProjectReducerActions =
AddTask |
RemoveTask |
UpdateTaskEstimation |
UpdateProjectLabel |
UpdateTaskLabel
export function useProjectReducer(project: Project) {
return useReducer(projectReducer, project);
}
export function projectReducer(project: Project, action: ProjectReducerActions): Project {
switch(action.type) {
case ADD_TASK:
return handleAddTask(project, action as AddTask);
case REMOVE_TASK:
return handleRemoveTask(project, action as RemoveTask);
case UPDATE_TASK_ESTIMATION:
return handleUpdateTaskEstimation(project, action as UpdateTaskEstimation);
case UPDATE_PROJECT_LABEL:
return handleUpdateProjectLabel(project, action as UpdateProjectLabel);
case UPDATE_TASK_LABEL:
return handleUpdateTaskLabel(project, action as UpdateTaskLabel);
}
return project;
}
export interface AddTask extends Action {
task: Task
}
export const ADD_TASK = "ADD_TASK";
export function addTask(task: Task): AddTask {
return { type: ADD_TASK, task };
}
export function handleAddTask(project: Project, action: AddTask): Project {
const task = { ...action.task };
return {
...project,
tasks: {
...project.tasks,
[task.id]: task,
}
};
}
export interface RemoveTask extends Action {
id: TaskID
}
export const REMOVE_TASK = "REMOVE_TASK";
export function removeTask(id: TaskID): RemoveTask {
return { type: REMOVE_TASK, id };
}
export function handleRemoveTask(project: Project, action: RemoveTask): Project {
const tasks = { ...project.tasks };
delete tasks[action.id];
return {
...project,
tasks
};
}
export interface UpdateTaskEstimation extends Action {
id: TaskID
confidence: string
value: number
}
export const UPDATE_TASK_ESTIMATION = "UPDATE_TASK_ESTIMATION";
export function updateTaskEstimation(id: TaskID, confidence: EstimationConfidence, value: number): UpdateTaskEstimation {
return { type: UPDATE_TASK_ESTIMATION, id, confidence, value };
}
export function handleUpdateTaskEstimation(project: Project, action: UpdateTaskEstimation): Project {
const estimations = {
...project.tasks[action.id].estimations,
[action.confidence]: action.value
};
if (estimations.likely <= estimations.optimistic) {
estimations.likely = estimations.optimistic + 1;
}
if (estimations.pessimistic <= estimations.likely) {
estimations.pessimistic = estimations.likely + 1;
}
return {
...project,
tasks: {
...project.tasks,
[action.id]: {
...project.tasks[action.id],
estimations: estimations,
}
}
};
}
export interface UpdateProjectLabel extends Action {
label: string
}
export const UPDATE_PROJECT_LABEL = "UPDATE_PROJECT_LABEL";
export function updateProjectLabel(label: string): UpdateProjectLabel {
return { type: UPDATE_PROJECT_LABEL, label };
}
export function handleUpdateProjectLabel(project: Project, action: UpdateProjectLabel): Project {
return {
...project,
label: action.label
};
}
export interface UpdateTaskLabel extends Action {
id: TaskID
label: string
}
export const UPDATE_TASK_LABEL = "UPDATE_TASK_LABEL";
export function updateTaskLabel(id: TaskID, label: string): UpdateTaskLabel {
return { type: UPDATE_TASK_LABEL, id, label };
}
export function handleUpdateTaskLabel(project: Project, action: UpdateTaskLabel): Project {
return {
...project,
tasks: {
...project.tasks,
[action.id]: {
...project.tasks[action.id],
label: action.label,
}
}
};
}