guesstimate/client/src/routes/project/task-categories-table.tsx

113 lines
4.3 KiB
TypeScript
Raw Normal View History

2020-07-09 13:00:42 +02:00
import React, { FunctionComponent, useState, MouseEvent, ChangeEvent } from "react";
2020-04-21 20:45:47 +02:00
import { Project } from "../../models/project";
2020-04-22 22:07:52 +02:00
import style from './style.module.css';
2020-04-22 22:48:47 +02:00
import { ProjectReducerActions, updateTaskCategoryCost, updateTaskCategoryLabel, removeTaskCategory, addTaskCategory } from "../../hooks/use-project-reducer";
2020-04-21 20:45:47 +02:00
import EditableText from "../../components/editable-text";
2020-04-22 22:48:47 +02:00
import { TaskCategoryID, createTaskCategory } from "../../models/task";
2020-04-21 20:45:47 +02:00
import { getCurrency, getTaskCategoryCost } from "../../models/params";
export interface TaskCategoriesTableProps {
2020-04-22 22:48:47 +02:00
project: Project
dispatch: (action: ProjectReducerActions) => void
2020-04-21 20:45:47 +02:00
}
2020-07-09 13:00:42 +02:00
const TaskCategoriesTable: FunctionComponent<TaskCategoriesTableProps> = ({ project, dispatch }) => {
2020-04-22 22:48:47 +02:00
const [ newTaskCategory, setNewTaskCategory ] = useState(createTaskCategory());
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));
};
2020-04-21 20:45:47 +02:00
2020-07-09 13:00:42 +02:00
const onNewTaskCategoryCostChange = (evt: ChangeEvent) => {
2020-04-22 22:48:47 +02:00
const costPerTimeUnit = parseFloat((evt.currentTarget as HTMLInputElement).value);
setNewTaskCategory(newTaskCategory => ({ ...newTaskCategory, costPerTimeUnit }));
};
2020-04-21 20:45:47 +02:00
2020-07-09 13:00:42 +02:00
const onNewTaskCategoryLabelChange = (evt: ChangeEvent) => {
2020-04-22 22:48:47 +02:00
const label = (evt.currentTarget as HTMLInputElement).value;
setNewTaskCategory(newTaskCategory => ({ ...newTaskCategory, label }));
};
2020-04-21 20:45:47 +02:00
2020-07-09 13:00:42 +02:00
const onNewTaskCategoryAddClick = (evt: MouseEvent) => {
2020-04-22 22:48:47 +02:00
dispatch(addTaskCategory(newTaskCategory));
setNewTaskCategory(createTaskCategory());
};
return (
2020-07-09 13:00:42 +02:00
<div className="table-container">
<label className="label is-size-5">Catégories de tâche</label>
<table className={`table is-bordered is-striped" ${style.middleTable}`}>
2020-04-22 22:48:47 +02:00
<thead>
<tr>
2020-07-09 13:00:42 +02:00
<th className={`${style.noBorder} is-narrow`}></th>
2020-04-22 22:48:47 +02:00
<th>Catégorie</th>
<th>Coût par unité de temps</th>
</tr>
</thead>
<tbody>
{
Object.values(project.params.taskCategories).map(tc => {
return (
<tr key={`task-category-${tc.id}`}>
<td>
<button
onClick={onTaskCategoryRemove.bind(null, tc.id)}
2020-07-09 13:00:42 +02:00
className="button is-danger is-small is-outlined">
2020-04-22 22:48:47 +02:00
🗑
</button>
</td>
<td>
<EditableText value={tc.label}
onChange={onTaskCategoryLabelChange.bind(null, tc.id)} />
</td>
<td>
<EditableText value={`${getTaskCategoryCost(tc)}`}
render={value=> (<span>{value} {getCurrency(project)}</span>)}
onChange={onTaskCategoryCostChange.bind(null, tc.id)} />
</td>
</tr>
);
})
}
</tbody>
<tfoot>
<tr>
2020-07-09 13:00:42 +02:00
<td className={`${style.noBorder}`}></td>
2020-04-22 22:48:47 +02:00
<td colSpan={2}>
2020-07-09 13:00:42 +02:00
<div className="field has-addons">
<p className="control is-expanded">
<input className="input" type="text" placeholder="Nouvelle catégorie"
2020-04-22 22:48:47 +02:00
value={newTaskCategory.label} onChange={onNewTaskCategoryLabelChange} />
</p>
2020-07-09 13:00:42 +02:00
<p className="control">
<input className="input" type="number"
2020-04-22 22:48:47 +02:00
value={newTaskCategory.costPerTimeUnit} onChange={onNewTaskCategoryCostChange} />
</p>
2020-07-09 13:00:42 +02:00
<p className="control">
<a className="button is-static">{getCurrency(project)}</a>
2020-04-22 22:48:47 +02:00
</p>
2020-07-09 13:00:42 +02:00
<p className="control">
<a className="button is-primary" onClick={onNewTaskCategoryAddClick}>
2020-04-22 22:48:47 +02:00
Ajouter
</a>
</p>
</div>
</td>
</tr>
</tfoot>
</table>
</div>
);
2020-04-21 20:45:47 +02:00
};
2020-04-22 22:48:47 +02:00
2020-04-21 20:45:47 +02:00
export default TaskCategoriesTable;