From 240ca07318c865c34b46a2de41f9ffac2f922293 Mon Sep 17 00:00:00 2001 From: Antonio Contreras LEMONCODE Date: Tue, 28 Apr 2020 18:04:01 +0200 Subject: [PATCH 01/13] Create employee list api, employee list api model and employee list mock data from api folder --- .../api/employee-list.api-model.ts | 7 ++++++ .../employee-list/api/employee-list.api.ts | 6 +++++ .../api/employee-list.mock-data.ts | 25 +++++++++++++++++++ src/pods/employee-list/api/index.ts | 1 + .../employee-list/employee-list.component.tsx | 3 +-- 5 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 src/pods/employee-list/api/employee-list.api-model.ts create mode 100644 src/pods/employee-list/api/employee-list.api.ts create mode 100644 src/pods/employee-list/api/employee-list.mock-data.ts create mode 100644 src/pods/employee-list/api/index.ts diff --git a/src/pods/employee-list/api/employee-list.api-model.ts b/src/pods/employee-list/api/employee-list.api-model.ts new file mode 100644 index 0000000..370394f --- /dev/null +++ b/src/pods/employee-list/api/employee-list.api-model.ts @@ -0,0 +1,7 @@ +export interface Employee { + id: string; + active: boolean; + name: string; + email: string; + lastDateIncurred: string; +} diff --git a/src/pods/employee-list/api/employee-list.api.ts b/src/pods/employee-list/api/employee-list.api.ts new file mode 100644 index 0000000..5a17d40 --- /dev/null +++ b/src/pods/employee-list/api/employee-list.api.ts @@ -0,0 +1,6 @@ +import { Employee } from './employee-list.api-model'; +import { mockEmployeeList } from './employee-list.mock-data'; + +export const getEmployeeList = async (): Promise => { + return mockEmployeeList; +}; diff --git a/src/pods/employee-list/api/employee-list.mock-data.ts b/src/pods/employee-list/api/employee-list.mock-data.ts new file mode 100644 index 0000000..7318ef9 --- /dev/null +++ b/src/pods/employee-list/api/employee-list.mock-data.ts @@ -0,0 +1,25 @@ +import { Employee } from './employee-list.api-model'; + +export const mockEmployeeList: Employee[] = [ + { + id: '1', + active: true, + name: 'Daniel Perez', + email: 'daniel.perez@empresa.com', + lastDateIncurred: '2020-02-02T00:00:00', + }, + { + id: '2', + active: true, + name: 'Jose Gomez', + email: 'jose.gomez@empresa.com', + lastDateIncurred: '2020-02-05T00:00:00', + }, + { + id: '3', + active: false, + name: 'Manuel Ruiz', + email: 'jose.gomez@empresa.com', + lastDateIncurred: '2020-02-06T00:00:00', + }, +]; diff --git a/src/pods/employee-list/api/index.ts b/src/pods/employee-list/api/index.ts new file mode 100644 index 0000000..c57e8cd --- /dev/null +++ b/src/pods/employee-list/api/index.ts @@ -0,0 +1 @@ +export * from './employee-list.api'; diff --git a/src/pods/employee-list/employee-list.component.tsx b/src/pods/employee-list/employee-list.component.tsx index f3550ba..5e140ce 100644 --- a/src/pods/employee-list/employee-list.component.tsx +++ b/src/pods/employee-list/employee-list.component.tsx @@ -21,9 +21,8 @@ export const EmployeeListComponent: React.FunctionComponent = () => { return ( <>

Hello Employee list component

-

Go to edit employee page

) => ( From ea60a7777706ce990ec25548e454f57b41de61ba Mon Sep 17 00:00:00 2001 From: Antonio Contreras LEMONCODE Date: Tue, 28 Apr 2020 19:12:57 +0200 Subject: [PATCH 02/13] Create employee list container, employee list mappers and employee list view model and fix others components --- .../employee-list/employee-list.component.tsx | 21 ++++++-------- .../employee-list/employee-list.container.tsx | 29 +++++++++++++++++++ .../employee-list/employee-list.mappers.ts | 14 +++++++++ src/pods/employee-list/employee-list.vm.ts | 7 +++++ src/pods/employee-list/index.ts | 2 +- src/scenes/employee-list.scene.tsx | 4 +-- 6 files changed, 62 insertions(+), 15 deletions(-) create mode 100644 src/pods/employee-list/employee-list.container.tsx create mode 100644 src/pods/employee-list/employee-list.mappers.ts create mode 100644 src/pods/employee-list/employee-list.vm.ts diff --git a/src/pods/employee-list/employee-list.component.tsx b/src/pods/employee-list/employee-list.component.tsx index 5e140ce..16b5287 100644 --- a/src/pods/employee-list/employee-list.component.tsx +++ b/src/pods/employee-list/employee-list.component.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import { useHistory } from 'react-router-dom'; import { routes } from 'core/router'; import { TableContainer, @@ -7,23 +6,21 @@ import { RowRendererProps, } from 'common/components/table'; import { Typography } from '@material-ui/core'; +import { Employee } from './employee-list.vm'; -export const EmployeeListComponent: React.FunctionComponent = () => { - const history = useHistory(); - const goToEmployee = ( - event: React.MouseEvent - ) => { - event.preventDefault(); - history.push({ - pathname: routes.editEmployee('1'), - }); - }; +interface Props { + employees: Employee[]; +} + +export const EmployeeListComponent: React.FunctionComponent = ({ + employees, +}) => { return ( <>

Hello Employee list component

) => ( {props.row.name} diff --git a/src/pods/employee-list/employee-list.container.tsx b/src/pods/employee-list/employee-list.container.tsx new file mode 100644 index 0000000..2621f44 --- /dev/null +++ b/src/pods/employee-list/employee-list.container.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { EmployeeListComponent } from './employee-list.component'; +import { getEmployeeList } from './api'; +import { Employee } from './employee-list.vm'; +import { useSnackbarContext } from 'common/components'; +import { trackPromise } from 'react-promise-tracker'; +import { mapEmployeeListFromApiToVm } from './employee-list.mappers'; + +export const EmployeeListContainer: React.FunctionComponent = () => { + const [employees, setEmployees] = React.useState([]); + const { showMessage } = useSnackbarContext(); + + const onLoadEmployeeList = async () => { + try { + const apiEmployeeList = await trackPromise(getEmployeeList()); + const viewModelEmloyeeList = mapEmployeeListFromApiToVm(apiEmployeeList); + setEmployees(viewModelEmloyeeList); + } catch (error) { + error && + showMessage('Ha ocurrido un error al cargar los empleados', 'error'); + } + }; + + React.useEffect(() => { + onLoadEmployeeList(); + }, []); + + return ; +}; diff --git a/src/pods/employee-list/employee-list.mappers.ts b/src/pods/employee-list/employee-list.mappers.ts new file mode 100644 index 0000000..22eff74 --- /dev/null +++ b/src/pods/employee-list/employee-list.mappers.ts @@ -0,0 +1,14 @@ +import { mapToCollection } from 'common/mappers'; +import * as apiModel from './api/employee-list.api-model'; +import * as viewModel from './employee-list.vm'; + +const mapEmployeeFromApiToVm = ( + employee: apiModel.Employee +): viewModel.Employee => ({ + ...employee, +}); + +export const mapEmployeeListFromApiToVm = ( + employees: apiModel.Employee[] +): viewModel.Employee[] => + mapToCollection(employees, e => mapEmployeeFromApiToVm(e)); diff --git a/src/pods/employee-list/employee-list.vm.ts b/src/pods/employee-list/employee-list.vm.ts new file mode 100644 index 0000000..370394f --- /dev/null +++ b/src/pods/employee-list/employee-list.vm.ts @@ -0,0 +1,7 @@ +export interface Employee { + id: string; + active: boolean; + name: string; + email: string; + lastDateIncurred: string; +} diff --git a/src/pods/employee-list/index.ts b/src/pods/employee-list/index.ts index 366d073..522f3e0 100644 --- a/src/pods/employee-list/index.ts +++ b/src/pods/employee-list/index.ts @@ -1 +1 @@ -export * from './employee-list.component'; +export * from './employee-list.container'; diff --git a/src/scenes/employee-list.scene.tsx b/src/scenes/employee-list.scene.tsx index cdc00af..bdddfbf 100644 --- a/src/scenes/employee-list.scene.tsx +++ b/src/scenes/employee-list.scene.tsx @@ -1,11 +1,11 @@ import React from 'react'; import { AppLayout } from 'layouts'; -import { EmployeeListComponent } from 'pods/employee-list'; +import { EmployeeListContainer } from 'pods/employee-list'; export const EmployeeListScene: React.FunctionComponent = () => { return ( - + ); }; From d17febe2e391d59a00c3c039d962d20b1ecf1325 Mon Sep 17 00:00:00 2001 From: Antonio Contreras LEMONCODE Date: Wed, 29 Apr 2020 12:30:26 +0200 Subject: [PATCH 03/13] Create employee row component and fix employee list component, employee list container and employee list mock data --- src/common/components/index.ts | 1 + .../api/employee-list.mock-data.ts | 35 +++++++++++++++++++ .../components/employee-row.component.tsx | 25 +++++++++++++ src/pods/employee-list/components/index.ts | 1 + .../employee-list/employee-list.component.tsx | 27 ++++++++------ .../employee-list/employee-list.container.tsx | 2 +- 6 files changed, 79 insertions(+), 12 deletions(-) create mode 100644 src/pods/employee-list/components/employee-row.component.tsx create mode 100644 src/pods/employee-list/components/index.ts diff --git a/src/common/components/index.ts b/src/common/components/index.ts index 53196cc..537dc0f 100644 --- a/src/common/components/index.ts +++ b/src/common/components/index.ts @@ -4,3 +4,4 @@ export * from './form'; export * from './snackbar'; export * from './spinner'; export * from './table'; +export * from './search-bar'; diff --git a/src/pods/employee-list/api/employee-list.mock-data.ts b/src/pods/employee-list/api/employee-list.mock-data.ts index 7318ef9..9df0ea0 100644 --- a/src/pods/employee-list/api/employee-list.mock-data.ts +++ b/src/pods/employee-list/api/employee-list.mock-data.ts @@ -22,4 +22,39 @@ export const mockEmployeeList: Employee[] = [ email: 'jose.gomez@empresa.com', lastDateIncurred: '2020-02-06T00:00:00', }, + { + id: '4', + active: true, + name: 'Ramón Gomez', + email: 'ramon.gomez@empresa.com', + lastDateIncurred: '2020-05-02T00:00:00', + }, + { + id: '5', + active: false, + name: 'María Lopez', + email: 'maria.lopez@empresa.com', + lastDateIncurred: '2020-08-05T00:00:00', + }, + { + id: '6', + active: true, + name: 'Manuel Ortiz', + email: 'manuel.ortiz@empresa.com', + lastDateIncurred: '2020-06-06T00:00:00', + }, + { + id: '7', + active: false, + name: 'David Martos', + email: 'david.martos@empresa.com', + lastDateIncurred: '2020-08-14T00:00:00', + }, + { + id: '8', + active: true, + name: 'Luz Roca', + email: 'luz.roca@empresa.com', + lastDateIncurred: '2020-06-20T00:00:00', + }, ]; diff --git a/src/pods/employee-list/components/employee-row.component.tsx b/src/pods/employee-list/components/employee-row.component.tsx new file mode 100644 index 0000000..cde8b44 --- /dev/null +++ b/src/pods/employee-list/components/employee-row.component.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import { + RowRendererProps, + RowComponent, + CellComponent, +} from 'common/components'; +import { Employee } from '../employee-list.vm'; + +type Props = RowRendererProps; + +export const EmployeeRowComponent: React.FunctionComponent = ({ + row, + onEdit, + onDelete, +}) => { + return ( + + {row.active} + {row.id} + {row.name} + {row.email} + {row.lastDateIncurred} + + ); +}; diff --git a/src/pods/employee-list/components/index.ts b/src/pods/employee-list/components/index.ts new file mode 100644 index 0000000..53f9ade --- /dev/null +++ b/src/pods/employee-list/components/index.ts @@ -0,0 +1 @@ +export * from './employee-row.component'; diff --git a/src/pods/employee-list/employee-list.component.tsx b/src/pods/employee-list/employee-list.component.tsx index 16b5287..6270489 100644 --- a/src/pods/employee-list/employee-list.component.tsx +++ b/src/pods/employee-list/employee-list.component.tsx @@ -2,30 +2,35 @@ import React from 'react'; import { routes } from 'core/router'; import { TableContainer, - RowComponent, RowRendererProps, -} from 'common/components/table'; -import { Typography } from '@material-ui/core'; + useSearchBar, +} from 'common/components'; import { Employee } from './employee-list.vm'; +import { EmployeeRowComponent } from './components'; interface Props { - employees: Employee[]; + employeeList: Employee[]; } export const EmployeeListComponent: React.FunctionComponent = ({ - employees, + employeeList, }) => { + const { filteredList, onSearch, search } = useSearchBar(employeeList, [ + 'name', + ]); return ( <> -

Hello Employee list component

) => ( - - {props.row.name} - + rows={filteredList} + rowRenderer={(rowProps: RowRendererProps) => ( + )} + enableSearch={true} + search={search} + onSearch={onSearch} + enablePagination={true} + pageSize={5} /> ); diff --git a/src/pods/employee-list/employee-list.container.tsx b/src/pods/employee-list/employee-list.container.tsx index 2621f44..d37a550 100644 --- a/src/pods/employee-list/employee-list.container.tsx +++ b/src/pods/employee-list/employee-list.container.tsx @@ -25,5 +25,5 @@ export const EmployeeListContainer: React.FunctionComponent = () => { onLoadEmployeeList(); }, []); - return ; + return ; }; From 289b4dee997446b20c00f4d10926db3e5caf8735 Mon Sep 17 00:00:00 2001 From: Antonio Contreras LEMONCODE Date: Wed, 29 Apr 2020 12:53:19 +0200 Subject: [PATCH 04/13] Add edit and delete icon buttons --- .../employee-list/api/employee-list.mock-data.ts | 2 +- .../components/employee-row.component.tsx | 13 ++++++++++++- src/pods/employee-list/employee-list.component.tsx | 5 +++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/pods/employee-list/api/employee-list.mock-data.ts b/src/pods/employee-list/api/employee-list.mock-data.ts index 9df0ea0..9f59e4a 100644 --- a/src/pods/employee-list/api/employee-list.mock-data.ts +++ b/src/pods/employee-list/api/employee-list.mock-data.ts @@ -19,7 +19,7 @@ export const mockEmployeeList: Employee[] = [ id: '3', active: false, name: 'Manuel Ruiz', - email: 'jose.gomez@empresa.com', + email: 'manuel.ruiz@empresa.com', lastDateIncurred: '2020-02-06T00:00:00', }, { diff --git a/src/pods/employee-list/components/employee-row.component.tsx b/src/pods/employee-list/components/employee-row.component.tsx index cde8b44..5365f9e 100644 --- a/src/pods/employee-list/components/employee-row.component.tsx +++ b/src/pods/employee-list/components/employee-row.component.tsx @@ -5,6 +5,9 @@ import { CellComponent, } from 'common/components'; import { Employee } from '../employee-list.vm'; +import IconButton from '@material-ui/core/IconButton'; +import EditIcon from '@material-ui/icons/Edit'; +import DeleteIcon from '@material-ui/icons/Delete'; type Props = RowRendererProps; @@ -19,7 +22,15 @@ export const EmployeeRowComponent: React.FunctionComponent = ({ {row.id} {row.name} {row.email} - {row.lastDateIncurred} + + {row.lastDateIncurred} + onEdit(row.id)}> + + + onDelete(row)}> + + +
); }; diff --git a/src/pods/employee-list/employee-list.component.tsx b/src/pods/employee-list/employee-list.component.tsx index 6270489..f4d1983 100644 --- a/src/pods/employee-list/employee-list.component.tsx +++ b/src/pods/employee-list/employee-list.component.tsx @@ -26,6 +26,11 @@ export const EmployeeListComponent: React.FunctionComponent = ({ rowRenderer={(rowProps: RowRendererProps) => ( )} + onCreate={() => console.log} + labels={{ + searchPlaceholder: 'Buscar empleados', + createButton: 'Nuevo empleado', + }} enableSearch={true} search={search} onSearch={onSearch} From 66fdb2552742ed8f5f0f89b2a58862aa961b4bd6 Mon Sep 17 00:00:00 2001 From: Antonio Contreras LEMONCODE Date: Wed, 29 Apr 2020 13:19:39 +0200 Subject: [PATCH 05/13] Added feature to create and edit employees --- .../employee-list/employee-list.component.tsx | 7 ++++++- .../employee-list/employee-list.container.tsx | 19 ++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/pods/employee-list/employee-list.component.tsx b/src/pods/employee-list/employee-list.component.tsx index f4d1983..c99d0c6 100644 --- a/src/pods/employee-list/employee-list.component.tsx +++ b/src/pods/employee-list/employee-list.component.tsx @@ -10,10 +10,14 @@ import { EmployeeRowComponent } from './components'; interface Props { employeeList: Employee[]; + onCreate: () => void; + onEdit: (id: string) => void; } export const EmployeeListComponent: React.FunctionComponent = ({ employeeList, + onCreate, + onEdit, }) => { const { filteredList, onSearch, search } = useSearchBar(employeeList, [ 'name', @@ -26,7 +30,8 @@ export const EmployeeListComponent: React.FunctionComponent = ({ rowRenderer={(rowProps: RowRendererProps) => ( )} - onCreate={() => console.log} + onCreate={onCreate} + onEdit={onEdit} labels={{ searchPlaceholder: 'Buscar empleados', createButton: 'Nuevo empleado', diff --git a/src/pods/employee-list/employee-list.container.tsx b/src/pods/employee-list/employee-list.container.tsx index d37a550..d1af976 100644 --- a/src/pods/employee-list/employee-list.container.tsx +++ b/src/pods/employee-list/employee-list.container.tsx @@ -5,10 +5,13 @@ import { Employee } from './employee-list.vm'; import { useSnackbarContext } from 'common/components'; import { trackPromise } from 'react-promise-tracker'; import { mapEmployeeListFromApiToVm } from './employee-list.mappers'; +import { useHistory } from 'react-router-dom'; +import { routes } from 'core/router'; export const EmployeeListContainer: React.FunctionComponent = () => { const [employees, setEmployees] = React.useState([]); const { showMessage } = useSnackbarContext(); + const history = useHistory(); const onLoadEmployeeList = async () => { try { @@ -21,9 +24,23 @@ export const EmployeeListContainer: React.FunctionComponent = () => { } }; + const handleCreate = () => { + history.push(routes.editEmployee('0')); + }; + + const handleEdit = (id: string) => { + history.push(routes.editEmployee(id)); + }; + React.useEffect(() => { onLoadEmployeeList(); }, []); - return ; + return ( + + ); }; From 70b0420fbeb17e4cc811520168ad2f493b30cabd Mon Sep 17 00:00:00 2001 From: Antonio Contreras LEMONCODE Date: Wed, 29 Apr 2020 16:02:25 +0200 Subject: [PATCH 06/13] Implement delete employee --- .../employee-list/api/employee-list.api.ts | 9 ++++++++- .../employee-list/employee-list.component.tsx | 18 ++++++++++++++++-- .../employee-list/employee-list.container.tsx | 13 ++++++++++++- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/pods/employee-list/api/employee-list.api.ts b/src/pods/employee-list/api/employee-list.api.ts index 5a17d40..4cd5a38 100644 --- a/src/pods/employee-list/api/employee-list.api.ts +++ b/src/pods/employee-list/api/employee-list.api.ts @@ -1,6 +1,13 @@ import { Employee } from './employee-list.api-model'; import { mockEmployeeList } from './employee-list.mock-data'; +let employeeList = [...mockEmployeeList]; + export const getEmployeeList = async (): Promise => { - return mockEmployeeList; + return employeeList; +}; + +export const deleteEmployee = async (id: string): Promise => { + employeeList = employeeList.filter(e => e.id !== id); + return true; }; diff --git a/src/pods/employee-list/employee-list.component.tsx b/src/pods/employee-list/employee-list.component.tsx index c99d0c6..7254c2d 100644 --- a/src/pods/employee-list/employee-list.component.tsx +++ b/src/pods/employee-list/employee-list.component.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import { routes } from 'core/router'; import { TableContainer, RowRendererProps, @@ -12,16 +11,26 @@ interface Props { employeeList: Employee[]; onCreate: () => void; onEdit: (id: string) => void; + onDelete: (id: string) => void; } export const EmployeeListComponent: React.FunctionComponent = ({ employeeList, onCreate, onEdit, + onDelete, }) => { const { filteredList, onSearch, search } = useSearchBar(employeeList, [ 'name', ]); + + const renderContent = ({ itemName }) => { + return ( +
+ ¿Seguro que quiere borrar a {itemName}? +
+ ); + }; return ( <> = ({ )} onCreate={onCreate} onEdit={onEdit} + onDelete={onDelete} labels={{ - searchPlaceholder: 'Buscar empleados', + searchPlaceholder: 'Buscar empleado', createButton: 'Nuevo empleado', + deleteTitle: 'Eliminar Empleado', + deleteContent: props => renderContent(props), + closeButton: 'Cancelar', + acceptButton: 'Aceptar', }} enableSearch={true} search={search} diff --git a/src/pods/employee-list/employee-list.container.tsx b/src/pods/employee-list/employee-list.container.tsx index d1af976..9d491ff 100644 --- a/src/pods/employee-list/employee-list.container.tsx +++ b/src/pods/employee-list/employee-list.container.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { EmployeeListComponent } from './employee-list.component'; -import { getEmployeeList } from './api'; +import { getEmployeeList, deleteEmployee } from './api'; import { Employee } from './employee-list.vm'; import { useSnackbarContext } from 'common/components'; import { trackPromise } from 'react-promise-tracker'; @@ -32,6 +32,16 @@ export const EmployeeListContainer: React.FunctionComponent = () => { history.push(routes.editEmployee(id)); }; + const handleDelete = async (id: string) => { + const errorMessage = 'Error al eliminar un empleado'; + try { + const isDelete = await trackPromise(deleteEmployee(id)); + isDelete ? onLoadEmployeeList() : showMessage(errorMessage, 'error'); + } catch (error) { + error && showMessage(errorMessage, 'error'); + } + }; + React.useEffect(() => { onLoadEmployeeList(); }, []); @@ -41,6 +51,7 @@ export const EmployeeListContainer: React.FunctionComponent = () => { employeeList={employees} onCreate={handleCreate} onEdit={handleEdit} + onDelete={handleDelete} /> ); }; From 524dea79ecb183446cb836af2e160e55f7972ca4 Mon Sep 17 00:00:00 2001 From: Antonio Contreras LEMONCODE Date: Wed, 29 Apr 2020 17:29:03 +0200 Subject: [PATCH 07/13] Fix components --- .../components/employee-row.component.tsx | 10 ++- .../employee-list/employee-list.component.tsx | 61 +++++++++---------- 2 files changed, 32 insertions(+), 39 deletions(-) diff --git a/src/pods/employee-list/components/employee-row.component.tsx b/src/pods/employee-list/components/employee-row.component.tsx index 5365f9e..7ac17be 100644 --- a/src/pods/employee-list/components/employee-row.component.tsx +++ b/src/pods/employee-list/components/employee-row.component.tsx @@ -4,18 +4,16 @@ import { RowComponent, CellComponent, } from 'common/components'; -import { Employee } from '../employee-list.vm'; import IconButton from '@material-ui/core/IconButton'; import EditIcon from '@material-ui/icons/Edit'; import DeleteIcon from '@material-ui/icons/Delete'; +import { Employee } from '../employee-list.vm'; type Props = RowRendererProps; -export const EmployeeRowComponent: React.FunctionComponent = ({ - row, - onEdit, - onDelete, -}) => { +export const EmployeeRowComponent: React.FunctionComponent = props => { + const { row, onEdit, onDelete } = props; + return ( {row.active} diff --git a/src/pods/employee-list/employee-list.component.tsx b/src/pods/employee-list/employee-list.component.tsx index 7254c2d..0c5a9bb 100644 --- a/src/pods/employee-list/employee-list.component.tsx +++ b/src/pods/employee-list/employee-list.component.tsx @@ -14,48 +14,43 @@ interface Props { onDelete: (id: string) => void; } -export const EmployeeListComponent: React.FunctionComponent = ({ - employeeList, - onCreate, - onEdit, - onDelete, -}) => { +export const EmployeeListComponent: React.FunctionComponent = props => { + const { employeeList, onCreate, onEdit, onDelete } = props; const { filteredList, onSearch, search } = useSearchBar(employeeList, [ 'name', ]); const renderContent = ({ itemName }) => { return ( -
+ <> ¿Seguro que quiere borrar a {itemName}? -
+ ); }; + return ( - <> - ) => ( - - )} - onCreate={onCreate} - onEdit={onEdit} - onDelete={onDelete} - labels={{ - searchPlaceholder: 'Buscar empleado', - createButton: 'Nuevo empleado', - deleteTitle: 'Eliminar Empleado', - deleteContent: props => renderContent(props), - closeButton: 'Cancelar', - acceptButton: 'Aceptar', - }} - enableSearch={true} - search={search} - onSearch={onSearch} - enablePagination={true} - pageSize={5} - /> - + ) => ( + + )} + onCreate={onCreate} + onEdit={onEdit} + onDelete={onDelete} + labels={{ + searchPlaceholder: 'Buscar empleado', + createButton: 'Nuevo empleado', + deleteTitle: 'Eliminar Empleado', + deleteContent: props => renderContent(props), + closeButton: 'Cancelar', + acceptButton: 'Aceptar', + }} + enableSearch={true} + search={search} + onSearch={onSearch} + enablePagination={true} + pageSize={5} + /> ); }; From 75bc71ee8055d887dd98a231508d642636f28fc8 Mon Sep 17 00:00:00 2001 From: Antonio Contreras LEMONCODE Date: Wed, 29 Apr 2020 18:17:05 +0200 Subject: [PATCH 08/13] FIx components --- .../employee-list/components/employee-row.component.tsx | 8 +++++--- src/pods/employee-list/employee-list.component.tsx | 8 ++++++-- src/pods/employee-list/employee-list.container.tsx | 4 ++-- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/pods/employee-list/components/employee-row.component.tsx b/src/pods/employee-list/components/employee-row.component.tsx index 7ac17be..f8480f5 100644 --- a/src/pods/employee-list/components/employee-row.component.tsx +++ b/src/pods/employee-list/components/employee-row.component.tsx @@ -11,9 +11,11 @@ import { Employee } from '../employee-list.vm'; type Props = RowRendererProps; -export const EmployeeRowComponent: React.FunctionComponent = props => { - const { row, onEdit, onDelete } = props; - +export const EmployeeRowComponent: React.FunctionComponent = ({ + row, + onEdit, + onDelete, +}) => { return ( {row.active} diff --git a/src/pods/employee-list/employee-list.component.tsx b/src/pods/employee-list/employee-list.component.tsx index 0c5a9bb..44273f9 100644 --- a/src/pods/employee-list/employee-list.component.tsx +++ b/src/pods/employee-list/employee-list.component.tsx @@ -14,8 +14,12 @@ interface Props { onDelete: (id: string) => void; } -export const EmployeeListComponent: React.FunctionComponent = props => { - const { employeeList, onCreate, onEdit, onDelete } = props; +export const EmployeeListComponent: React.FunctionComponent = ({ + employeeList, + onCreate, + onEdit, + onDelete, +}) => { const { filteredList, onSearch, search } = useSearchBar(employeeList, [ 'name', ]); diff --git a/src/pods/employee-list/employee-list.container.tsx b/src/pods/employee-list/employee-list.container.tsx index 9d491ff..462d896 100644 --- a/src/pods/employee-list/employee-list.container.tsx +++ b/src/pods/employee-list/employee-list.container.tsx @@ -35,8 +35,8 @@ export const EmployeeListContainer: React.FunctionComponent = () => { const handleDelete = async (id: string) => { const errorMessage = 'Error al eliminar un empleado'; try { - const isDelete = await trackPromise(deleteEmployee(id)); - isDelete ? onLoadEmployeeList() : showMessage(errorMessage, 'error'); + const isDeleted = await trackPromise(deleteEmployee(id)); + isDeleted ? onLoadEmployeeList() : showMessage(errorMessage, 'error'); } catch (error) { error && showMessage(errorMessage, 'error'); } From 56dba2c490fba8dbf15e5e168d7cded96c3591c9 Mon Sep 17 00:00:00 2001 From: Antonio Contreras LEMONCODE Date: Wed, 29 Apr 2020 18:21:05 +0200 Subject: [PATCH 09/13] Add checkbox common component --- .../form/checkbox/checkbox.component.tsx | 55 +++++++++++++++++++ .../form/checkbox/checkbox.styles.ts | 6 ++ src/common/components/form/checkbox/index.ts | 1 + src/common/components/form/index.ts | 1 + 4 files changed, 63 insertions(+) create mode 100644 src/common/components/form/checkbox/checkbox.component.tsx create mode 100644 src/common/components/form/checkbox/checkbox.styles.ts create mode 100644 src/common/components/form/checkbox/index.ts diff --git a/src/common/components/form/checkbox/checkbox.component.tsx b/src/common/components/form/checkbox/checkbox.component.tsx new file mode 100644 index 0000000..7fc3d9c --- /dev/null +++ b/src/common/components/form/checkbox/checkbox.component.tsx @@ -0,0 +1,55 @@ +import React from 'react'; +import { useField } from 'formik'; +import Checkbox, { CheckboxProps } from '@material-ui/core/Checkbox'; +import FormControlLabel from '@material-ui/core/FormControlLabel'; +import FormControl from '@material-ui/core/FormControl'; +import FormHelperText from '@material-ui/core/FormHelperText'; +import * as classes from './checkbox.styles'; + +interface Props extends CheckboxProps { + label?: string; + labelPlacement?: 'end' | 'start' | 'top' | 'bottom'; + error?: boolean; + helperText?: string; +} + +export const CheckboxComponent: React.FunctionComponent = props => { + const { + label, + labelPlacement, + error, + name, + checked, + onChange, + onBlur, + ...checkboxProps + } = props; + const [field, meta] = Boolean(name) ? useField(name) : []; + const hasError = error || Boolean(meta && meta.touched && meta.error); + const helperText = Boolean(field) ? meta?.error : props.helperText; + + return ( + + + } + label={label} + labelPlacement={labelPlacement} + /> + + {hasError && {helperText}} + + ); +}; diff --git a/src/common/components/form/checkbox/checkbox.styles.ts b/src/common/components/form/checkbox/checkbox.styles.ts new file mode 100644 index 0000000..ddac534 --- /dev/null +++ b/src/common/components/form/checkbox/checkbox.styles.ts @@ -0,0 +1,6 @@ +import { css } from 'emotion'; +import { theme } from 'core/theme'; + +export const root = css` + justify-content: flex-end; +`; diff --git a/src/common/components/form/checkbox/index.ts b/src/common/components/form/checkbox/index.ts new file mode 100644 index 0000000..34dc2db --- /dev/null +++ b/src/common/components/form/checkbox/index.ts @@ -0,0 +1 @@ +export * from './checkbox.component'; diff --git a/src/common/components/form/index.ts b/src/common/components/form/index.ts index 01821f5..8615482 100644 --- a/src/common/components/form/index.ts +++ b/src/common/components/form/index.ts @@ -1,2 +1,3 @@ export * from './form.component'; export * from './text-field.component'; +export * from './checkbox'; From 0a78384f1afc81f233645c4a43df883835eea88d Mon Sep 17 00:00:00 2001 From: Antonio Contreras LEMONCODE Date: Wed, 29 Apr 2020 18:40:59 +0200 Subject: [PATCH 10/13] Use ckecked component --- .../employee-list/api/employee-list.mock-data.ts | 16 ++++++++-------- .../components/employee-row.component.tsx | 5 ++++- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/pods/employee-list/api/employee-list.mock-data.ts b/src/pods/employee-list/api/employee-list.mock-data.ts index 9f59e4a..4748445 100644 --- a/src/pods/employee-list/api/employee-list.mock-data.ts +++ b/src/pods/employee-list/api/employee-list.mock-data.ts @@ -6,55 +6,55 @@ export const mockEmployeeList: Employee[] = [ active: true, name: 'Daniel Perez', email: 'daniel.perez@empresa.com', - lastDateIncurred: '2020-02-02T00:00:00', + lastDateIncurred: '02/02/2020', }, { id: '2', active: true, name: 'Jose Gomez', email: 'jose.gomez@empresa.com', - lastDateIncurred: '2020-02-05T00:00:00', + lastDateIncurred: '05/02/2020', }, { id: '3', active: false, name: 'Manuel Ruiz', email: 'manuel.ruiz@empresa.com', - lastDateIncurred: '2020-02-06T00:00:00', + lastDateIncurred: '06/02/2020', }, { id: '4', active: true, name: 'Ramón Gomez', email: 'ramon.gomez@empresa.com', - lastDateIncurred: '2020-05-02T00:00:00', + lastDateIncurred: '02/05/2020', }, { id: '5', active: false, name: 'María Lopez', email: 'maria.lopez@empresa.com', - lastDateIncurred: '2020-08-05T00:00:00', + lastDateIncurred: '05/08/2020', }, { id: '6', active: true, name: 'Manuel Ortiz', email: 'manuel.ortiz@empresa.com', - lastDateIncurred: '2020-06-06T00:00:00', + lastDateIncurred: '06/06/2020', }, { id: '7', active: false, name: 'David Martos', email: 'david.martos@empresa.com', - lastDateIncurred: '2020-08-14T00:00:00', + lastDateIncurred: '14/08/2020', }, { id: '8', active: true, name: 'Luz Roca', email: 'luz.roca@empresa.com', - lastDateIncurred: '2020-06-20T00:00:00', + lastDateIncurred: '20/06/2020', }, ]; diff --git a/src/pods/employee-list/components/employee-row.component.tsx b/src/pods/employee-list/components/employee-row.component.tsx index f8480f5..ef4cc99 100644 --- a/src/pods/employee-list/components/employee-row.component.tsx +++ b/src/pods/employee-list/components/employee-row.component.tsx @@ -3,6 +3,7 @@ import { RowRendererProps, RowComponent, CellComponent, + CheckboxComponent, } from 'common/components'; import IconButton from '@material-ui/core/IconButton'; import EditIcon from '@material-ui/icons/Edit'; @@ -18,7 +19,9 @@ export const EmployeeRowComponent: React.FunctionComponent = ({ }) => { return ( - {row.active} + + + {row.id} {row.name} {row.email} From 9c383fa598b91ad172bdae1b3f7fc047fa72fa05 Mon Sep 17 00:00:00 2001 From: Antonio Contreras LEMONCODE Date: Wed, 29 Apr 2020 18:58:21 +0200 Subject: [PATCH 11/13] Remove checkbox common component and use checkbox material ui --- .../form/checkbox/checkbox.component.tsx | 55 ------------------- .../form/checkbox/checkbox.styles.ts | 6 -- src/common/components/form/checkbox/index.ts | 1 - src/common/components/form/index.ts | 1 - .../components/employee-row.component.tsx | 4 +- .../employee-list/employee-list.mappers.ts | 4 +- 6 files changed, 4 insertions(+), 67 deletions(-) delete mode 100644 src/common/components/form/checkbox/checkbox.component.tsx delete mode 100644 src/common/components/form/checkbox/checkbox.styles.ts delete mode 100644 src/common/components/form/checkbox/index.ts diff --git a/src/common/components/form/checkbox/checkbox.component.tsx b/src/common/components/form/checkbox/checkbox.component.tsx deleted file mode 100644 index 7fc3d9c..0000000 --- a/src/common/components/form/checkbox/checkbox.component.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import React from 'react'; -import { useField } from 'formik'; -import Checkbox, { CheckboxProps } from '@material-ui/core/Checkbox'; -import FormControlLabel from '@material-ui/core/FormControlLabel'; -import FormControl from '@material-ui/core/FormControl'; -import FormHelperText from '@material-ui/core/FormHelperText'; -import * as classes from './checkbox.styles'; - -interface Props extends CheckboxProps { - label?: string; - labelPlacement?: 'end' | 'start' | 'top' | 'bottom'; - error?: boolean; - helperText?: string; -} - -export const CheckboxComponent: React.FunctionComponent = props => { - const { - label, - labelPlacement, - error, - name, - checked, - onChange, - onBlur, - ...checkboxProps - } = props; - const [field, meta] = Boolean(name) ? useField(name) : []; - const hasError = error || Boolean(meta && meta.touched && meta.error); - const helperText = Boolean(field) ? meta?.error : props.helperText; - - return ( - - - } - label={label} - labelPlacement={labelPlacement} - /> - - {hasError && {helperText}} - - ); -}; diff --git a/src/common/components/form/checkbox/checkbox.styles.ts b/src/common/components/form/checkbox/checkbox.styles.ts deleted file mode 100644 index ddac534..0000000 --- a/src/common/components/form/checkbox/checkbox.styles.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { css } from 'emotion'; -import { theme } from 'core/theme'; - -export const root = css` - justify-content: flex-end; -`; diff --git a/src/common/components/form/checkbox/index.ts b/src/common/components/form/checkbox/index.ts deleted file mode 100644 index 34dc2db..0000000 --- a/src/common/components/form/checkbox/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './checkbox.component'; diff --git a/src/common/components/form/index.ts b/src/common/components/form/index.ts index 8615482..01821f5 100644 --- a/src/common/components/form/index.ts +++ b/src/common/components/form/index.ts @@ -1,3 +1,2 @@ export * from './form.component'; export * from './text-field.component'; -export * from './checkbox'; diff --git a/src/pods/employee-list/components/employee-row.component.tsx b/src/pods/employee-list/components/employee-row.component.tsx index ef4cc99..a09ecd1 100644 --- a/src/pods/employee-list/components/employee-row.component.tsx +++ b/src/pods/employee-list/components/employee-row.component.tsx @@ -3,8 +3,8 @@ import { RowRendererProps, RowComponent, CellComponent, - CheckboxComponent, } from 'common/components'; +import Checkbox from '@material-ui/core/Checkbox'; import IconButton from '@material-ui/core/IconButton'; import EditIcon from '@material-ui/icons/Edit'; import DeleteIcon from '@material-ui/icons/Delete'; @@ -20,7 +20,7 @@ export const EmployeeRowComponent: React.FunctionComponent = ({ return ( - + {row.id} {row.name} diff --git a/src/pods/employee-list/employee-list.mappers.ts b/src/pods/employee-list/employee-list.mappers.ts index 22eff74..67dcbd6 100644 --- a/src/pods/employee-list/employee-list.mappers.ts +++ b/src/pods/employee-list/employee-list.mappers.ts @@ -9,6 +9,6 @@ const mapEmployeeFromApiToVm = ( }); export const mapEmployeeListFromApiToVm = ( - employees: apiModel.Employee[] + employeeList: apiModel.Employee[] ): viewModel.Employee[] => - mapToCollection(employees, e => mapEmployeeFromApiToVm(e)); + mapToCollection(employeeList, e => mapEmployeeFromApiToVm(e)); From a9ba02061f3d9866f964c3ef0bca6750069ab505 Mon Sep 17 00:00:00 2001 From: Antonio Contreras LEMONCODE Date: Wed, 29 Apr 2020 19:31:24 +0200 Subject: [PATCH 12/13] Create employee list mappers spec --- .../employee-list/employee-list.container.tsx | 3 +- .../employee-list.mappers.spec.ts | 110 ++++++++++++++++++ 2 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 src/pods/employee-list/employee-list.mappers.spec.ts diff --git a/src/pods/employee-list/employee-list.container.tsx b/src/pods/employee-list/employee-list.container.tsx index 462d896..19b9b2d 100644 --- a/src/pods/employee-list/employee-list.container.tsx +++ b/src/pods/employee-list/employee-list.container.tsx @@ -7,6 +7,7 @@ import { trackPromise } from 'react-promise-tracker'; import { mapEmployeeListFromApiToVm } from './employee-list.mappers'; import { useHistory } from 'react-router-dom'; import { routes } from 'core/router'; +const editEmployeeId = '0'; export const EmployeeListContainer: React.FunctionComponent = () => { const [employees, setEmployees] = React.useState([]); @@ -25,7 +26,7 @@ export const EmployeeListContainer: React.FunctionComponent = () => { }; const handleCreate = () => { - history.push(routes.editEmployee('0')); + history.push(routes.editEmployee(editEmployeeId)); }; const handleEdit = (id: string) => { diff --git a/src/pods/employee-list/employee-list.mappers.spec.ts b/src/pods/employee-list/employee-list.mappers.spec.ts new file mode 100644 index 0000000..bda525b --- /dev/null +++ b/src/pods/employee-list/employee-list.mappers.spec.ts @@ -0,0 +1,110 @@ +import * as apiModel from './api/employee-list.api-model'; +import * as viewModel from './employee-list.vm'; +import { mapEmployeeListFromApiToVm } from './employee-list.mappers'; + +describe('./pods/employee-list', () => { + it('should return empty array when feeding undefined employee list', () => { + // Arrange + const employeeList = undefined; + + // Act + const result = mapEmployeeListFromApiToVm(employeeList); + + // Assert + expect(result).toEqual([]); + }); + + it('should return empty array when feeding null employee list', () => { + // Arrange + const employeeList = null; + + // Act + const result = mapEmployeeListFromApiToVm(employeeList); + + // Assert + expect(result).toEqual([]); + }); + + it('should return empty array when feeding empty array employee list', () => { + // Arrange + const employeeList = []; + + // Act + const result = mapEmployeeListFromApiToVm(employeeList); + + // Assert + expect(result).toEqual([]); + }); + + it('should return one item with values when passing one item with values', () => { + // Arrange + const employeeList: apiModel.Employee[] = [ + { + id: 'test id', + active: true, + name: 'test name', + email: 'test@email.com', + lastDateIncurred: '02/02/2020', + }, + ]; + + const expectedResult: viewModel.Employee[] = [ + { + id: 'test id', + active: true, + name: 'test name', + email: 'test@email.com', + lastDateIncurred: '02/02/2020', + }, + ]; + + // Act + const result = mapEmployeeListFromApiToVm(employeeList); + + // Assert + expect(result).toEqual(expectedResult); + }); + + it('should return two item with values when passing two item with values', () => { + // Arrange + const employeeList: apiModel.Employee[] = [ + { + id: 'test id 1', + active: true, + name: 'test name 1', + email: 'test@email.com', + lastDateIncurred: '02/02/2020', + }, + { + id: 'test id 2', + active: true, + name: 'test name 2', + email: 'test@email.com', + lastDateIncurred: '02/02/2020', + }, + ]; + + const expectedResult: viewModel.Employee[] = [ + { + id: 'test id 1', + active: true, + name: 'test name 1', + email: 'test@email.com', + lastDateIncurred: '02/02/2020', + }, + { + id: 'test id 2', + active: true, + name: 'test name 2', + email: 'test@email.com', + lastDateIncurred: '02/02/2020', + }, + ]; + + // Act + const result = mapEmployeeListFromApiToVm(employeeList); + + // Assert + expect(result).toEqual(expectedResult); + }); +}); From 2b254e54b52b3fc08bf0679899d453fbfc1c2921 Mon Sep 17 00:00:00 2001 From: Antonio Contreras LEMONCODE Date: Wed, 29 Apr 2020 19:43:44 +0200 Subject: [PATCH 13/13] Fix test configuration --- config/test/jest.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/config/test/jest.js b/config/test/jest.js index b26f1cc..d33e89f 100644 --- a/config/test/jest.js +++ b/config/test/jest.js @@ -2,13 +2,6 @@ module.exports = { rootDir: '../../', preset: 'ts-jest', restoreMocks: true, - moduleNameMapper: { - '^common-app(.*)$': '/src/common-app/$1', - '^common(.*)$': '/src/common/$1', - '^core(.*)$': '/src/core/$1', - '^layouts(.*)$': '/src/layouts/$1', - '^pods(.*)$': '/src/pods/$1', - '^scenes(.*)$': '/src/scenes/$1', - }, + moduleDirectories: ['/src', 'node_modules'], setupFilesAfterEnv: ['/config/test/setup.ts'], };