Task categories edition

This commit is contained in:
wpetit 2020-04-22 22:48:47 +02:00
parent 5f0cad970e
commit b0bffe6fb8
2 changed files with 117 additions and 65 deletions

View File

@ -1,4 +1,5 @@
import { uuidV4 } from "../util/uuid" import { uuidV4 } from "../util/uuid"
import { defaults } from "./params";
export type TaskID = string export type TaskID = string
@ -24,14 +25,22 @@ export interface TaskCategory {
} }
export function newTask(label: string, category: TaskCategoryID): Task { export function newTask(label: string, category: TaskCategoryID): Task {
return { return {
id: uuidV4(), id: uuidV4(),
label, label,
category, category,
estimations: { estimations: {
[EstimationConfidence.Optimistic]: 0, [EstimationConfidence.Optimistic]: 0,
[EstimationConfidence.Likely]: 0, [EstimationConfidence.Likely]: 0,
[EstimationConfidence.Pessimistic]: 0, [EstimationConfidence.Pessimistic]: 0,
} }
}; };
}
export function createTaskCategory(): TaskCategory {
return {
id: uuidV4(),
costPerTimeUnit: defaults.costPerTimeUnit,
label: ""
};
} }

View File

@ -1,70 +1,113 @@
import { FunctionalComponent, h } from "preact"; import { FunctionalComponent, h } from "preact";
import { Project } from "../../models/project"; import { Project } from "../../models/project";
import style from './style.module.css'; import style from './style.module.css';
import { projectReducer, ProjectReducerActions, updateTaskCategoryCost, updateTaskCategoryLabel, removeTaskCategory } from "../../hooks/use-project-reducer"; import { ProjectReducerActions, updateTaskCategoryCost, updateTaskCategoryLabel, removeTaskCategory, addTaskCategory } from "../../hooks/use-project-reducer";
import EditableText from "../../components/editable-text"; import EditableText from "../../components/editable-text";
import { TaskCategoryID } from "../../models/task"; import { TaskCategoryID, createTaskCategory } from "../../models/task";
import ProjectTimeUnit from "../../components/project-time-unit";
import { getCurrency, getTaskCategoryCost } from "../../models/params"; import { getCurrency, getTaskCategoryCost } from "../../models/params";
import { useState } from "preact/hooks";
export interface TaskCategoriesTableProps { export interface TaskCategoriesTableProps {
project: Project project: Project
dispatch: (action: ProjectReducerActions) => void dispatch: (action: ProjectReducerActions) => void
} }
const TaskCategoriesTable: FunctionalComponent<TaskCategoriesTableProps> = ({ project, dispatch }) => { const TaskCategoriesTable: FunctionalComponent<TaskCategoriesTableProps> = ({ project, dispatch }) => {
const onTaskCategoryRemove = (categoryId: TaskCategoryID) => { const [ newTaskCategory, setNewTaskCategory ] = useState(createTaskCategory());
dispatch(removeTaskCategory(categoryId));
}; const onTaskCategoryRemove = (categoryId: TaskCategoryID) => {
dispatch(removeTaskCategory(categoryId));
};
const onTaskCategoryLabelChange = (categoryId: TaskCategoryID, value: string) => {
dispatch(updateTaskCategoryLabel(categoryId, value));
};
const onTaskCategoryCostChange = (categoryId: TaskCategoryID, value: string) => {
const cost = parseFloat(value);
dispatch(updateTaskCategoryCost(categoryId, cost));
};
const onTaskCategoryLabelChange = (categoryId: TaskCategoryID, value: string) => { const onNewTaskCategoryCostChange = (evt: Event) => {
dispatch(updateTaskCategoryLabel(categoryId, value)); const costPerTimeUnit = parseFloat((evt.currentTarget as HTMLInputElement).value);
}; setNewTaskCategory(newTaskCategory => ({ ...newTaskCategory, costPerTimeUnit }));
};
const onTaskCategoryCostChange = (categoryId: TaskCategoryID, value: string) => { const onNewTaskCategoryLabelChange = (evt: Event) => {
const cost = parseFloat(value); const label = (evt.currentTarget as HTMLInputElement).value;
dispatch(updateTaskCategoryCost(categoryId, cost)); setNewTaskCategory(newTaskCategory => ({ ...newTaskCategory, label }));
}; };
return ( const onNewTaskCategoryAddClick = (evt: Event) => {
<div class="table-container"> dispatch(addTaskCategory(newTaskCategory));
<label class="label">Catégories de tâche</label> setNewTaskCategory(createTaskCategory());
<table class={`table is-bordered is-striped" ${style.middleTable}`}> };
<thead>
<tr> return (
<th class={`${style.noBorder} is-narrow`}></th> <div class="table-container">
<th>Catégorie</th> <label class="label">Catégories de tâche</label>
<th>Coût par unité de temps</th> <table class={`table is-bordered is-striped" ${style.middleTable}`}>
</tr> <thead>
</thead> <tr>
<tbody> <th class={`${style.noBorder} is-narrow`}></th>
{ <th>Catégorie</th>
Object.values(project.params.taskCategories).map(tc => { <th>Coût par unité de temps</th>
return ( </tr>
<tr key={`task-category-${tc.id}`}> </thead>
<td> <tbody>
<button {
onClick={onTaskCategoryRemove.bind(null, tc.id)} Object.values(project.params.taskCategories).map(tc => {
class="button is-danger is-small is-outlined"> return (
🗑 <tr key={`task-category-${tc.id}`}>
</button> <td>
</td> <button
<td><EditableText value={tc.label} onClick={onTaskCategoryRemove.bind(null, tc.id)}
onChange={onTaskCategoryLabelChange.bind(null, tc.id)} /> class="button is-danger is-small is-outlined">
</td> 🗑
<td> </button>
<EditableText value={`${getTaskCategoryCost(tc)}`} </td>
render={value=> (<span>{value} {getCurrency(project)}</span>)} <td>
onChange={onTaskCategoryCostChange.bind(null, tc.id)} /> <EditableText value={tc.label}
</td> onChange={onTaskCategoryLabelChange.bind(null, tc.id)} />
</tr> </td>
); <td>
}) <EditableText value={`${getTaskCategoryCost(tc)}`}
} render={value=> (<span>{value} {getCurrency(project)}</span>)}
</tbody> onChange={onTaskCategoryCostChange.bind(null, tc.id)} />
</table> </td>
</div> </tr>
); );
})
}
</tbody>
<tfoot>
<tr>
<td class={`${style.noBorder}`}></td>
<td colSpan={2}>
<div class="field has-addons">
<p class="control is-expanded">
<input class="input" type="text" placeholder="Nouvelle catégorie"
value={newTaskCategory.label} onChange={onNewTaskCategoryLabelChange} />
</p>
<p class="control">
<input class="input" type="number"
value={newTaskCategory.costPerTimeUnit} onChange={onNewTaskCategoryCostChange} />
</p>
<p class="control">
<a class="button is-static">{getCurrency(project)}</a>
</p>
<p class="control">
<a class="button is-primary" onClick={onNewTaskCategoryAddClick}>
Ajouter
</a>
</p>
</div>
</td>
</tr>
</tfoot>
</table>
</div>
);
}; };
export default TaskCategoriesTable; export default TaskCategoriesTable;