diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index 782dc3401..e3f709fc7 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -618,12 +618,415 @@ + + employees + + + actions + + + new + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + + + errors + + + delete + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + save + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + validation + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + validationtitle + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + + + fields + + + active + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + base_rate + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + cost_center + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + employee_number + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + first_name + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + flat_rate + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + hire_date + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + last_name + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + termination_date + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + + + successes + + + delete + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + save + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + + + general actions + + delete + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + edit + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + reset false @@ -645,6 +1048,27 @@ + + save + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + @@ -671,6 +1095,27 @@ + + barcode + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + in false @@ -914,6 +1359,32 @@ + + validation + + + required + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + @@ -4143,6 +4614,27 @@ + + shop + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + vehicles false @@ -5228,6 +5720,27 @@ + + owners + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + profile false @@ -5270,6 +5783,27 @@ + + shop + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + vehicledetail false @@ -5291,6 +5825,27 @@ + + vehicles + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + diff --git a/client/package.json b/client/package.json index 496825c35..8310ddbeb 100644 --- a/client/package.json +++ b/client/package.json @@ -19,6 +19,7 @@ "node-sass": "^4.13.1", "react": "^16.12.0", "react-apollo": "^3.1.3", + "react-barcode": "^1.4.0", "react-big-calendar": "^0.23.0", "react-chartjs-2": "^2.9.0", "react-dom": "^16.12.0", diff --git a/client/src/components/barcode-popup/barcode-popup.component.jsx b/client/src/components/barcode-popup/barcode-popup.component.jsx new file mode 100644 index 000000000..7daceb4dc --- /dev/null +++ b/client/src/components/barcode-popup/barcode-popup.component.jsx @@ -0,0 +1,22 @@ +import { Tag, Popover } from "antd"; +import React from "react"; +import Barcode from "react-barcode"; +import { useTranslation } from "react-i18next"; +export default function BarcodePopupComponent({ value }) { + const { t } = useTranslation(); + return ( +
+ + } + > + {t("general.labels.barcode")} + +
+ ); +} diff --git a/client/src/components/header/header.component.jsx b/client/src/components/header/header.component.jsx index 0114f278e..478789c1e 100644 --- a/client/src/components/header/header.component.jsx +++ b/client/src/components/header/header.component.jsx @@ -72,6 +72,12 @@ export default ({ + + + {t("menus.header.shop")} + + + diff --git a/client/src/components/jobs-detail-header/jobs-detail-header.component.jsx b/client/src/components/jobs-detail-header/jobs-detail-header.component.jsx index 8a4760732..e554946df 100644 --- a/client/src/components/jobs-detail-header/jobs-detail-header.component.jsx +++ b/client/src/components/jobs-detail-header/jobs-detail-header.component.jsx @@ -20,6 +20,7 @@ import { createStructuredSelector } from "reselect"; import CarImage from "../../assets/car.svg"; import { selectBodyshop } from "../../redux/user/user.selectors"; import CurrencyFormatter from "../../utils/CurrencyFormatter"; +import BarcodePopup from "../barcode-popup/barcode-popup.component"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop @@ -49,32 +50,6 @@ export default connect( ); - const tombstoneSubtitle = ( -
- - {job.owner ? ( - - {`${job.ownr_co_nm || ""}${job.ownr_fn || ""} ${job.ownr_ln || ""}`} - - ) : ( - t("jobs.errors.noowner") - )} - - - - {job.vehicle ? ( - - {job.vehicle.v_model_yr || t("general.labels.na")}{" "} - {job.vehicle.v_make_desc || t("general.labels.na")}{" "} - {job.vehicle.v_model_desc || t("general.labels.na")} |{" "} - {job.vehicle.plate_no || t("general.labels.na")} |{" "} - {job.vehicle.v_vin || t("general.labels.na")} - - ) : null} - -
- ); - const statusmenu = ( { @@ -137,10 +112,32 @@ export default connect( border: "1px solid rgb(235, 237, 240)" }} title={tombstoneTitle} - subTitle={tombstoneSubtitle} + //subTitle={tombstoneSubtitle} tags={ {job.status ? {job.status} : null} + + {job.owner ? ( + + {`${job.ownr_co_nm || ""}${job.ownr_fn || ""} ${job.ownr_ln || + ""}`} + + ) : ( + t("jobs.errors.noowner") + )} + + + {job.vehicle ? ( + + {job.vehicle.v_model_yr || t("general.labels.na")}{" "} + {job.vehicle.v_make_desc || t("general.labels.na")}{" "} + {job.vehicle.v_model_desc || t("general.labels.na")} |{" "} + {job.vehicle.plate_no || t("general.labels.na")} |{" "} + {job.vehicle.v_vin || t("general.labels.na")} + + ) : null} + + } extra={menuExtra} diff --git a/client/src/components/shop-employees/shop-employees-form.component.jsx b/client/src/components/shop-employees/shop-employees-form.component.jsx new file mode 100644 index 000000000..cf7abfab7 --- /dev/null +++ b/client/src/components/shop-employees/shop-employees-form.component.jsx @@ -0,0 +1,112 @@ +import { Button, DatePicker, Form, Input, InputNumber, Switch } from "antd"; +import moment from "moment"; +import React from "react"; +import { useTranslation } from "react-i18next"; + +export default function ShopEmployeesFormComponent({ + form, + selectedEmployee, + handleSubmit +}) { + const { t } = useTranslation(); + const { getFieldDecorator } = form; + if (!selectedEmployee) return "//TODO No employee selected."; + return ( +
+ + + + {getFieldDecorator("first_name", { + initialValue: selectedEmployee.first_name, + rules: [ + { + required: true, + message: t("general.validation.required") + } + ] + })()} + + + {getFieldDecorator("last_name", { + initialValue: selectedEmployee.last_name, + rules: [ + { + required: true, + message: t("general.validation.required") + } + ] + })()} + + + {getFieldDecorator("employee_number", { + initialValue: selectedEmployee.employee_number, + rules: [ + { + required: true, + message: t("general.validation.required") + } + ] + })()} + + + {getFieldDecorator("active", { + initialValue: selectedEmployee.active, + valuePropName: "checked" + })()} + + + {getFieldDecorator("flat_rate", { + initialValue: selectedEmployee.flat_rate, + valuePropName: "checked" + })()} + + + {getFieldDecorator("hire_date", { + initialValue: selectedEmployee.hire_date + ? moment(selectedEmployee.hire_date) + : null, + rules: [ + { + required: true, + message: t("general.validation.required") + } + ] + })()} + + + {getFieldDecorator("termination_date", { + initialValue: selectedEmployee.termination_date + ? moment(selectedEmployee.termination_date) + : null + })()} + + { + //TODO Make this a picklist. + } + + {getFieldDecorator("cost_center", { + initialValue: selectedEmployee.cost_center, + rules: [ + { + required: true, + message: t("general.validation.required") + } + ] + })()} + + + {getFieldDecorator("base_rate", { + initialValue: selectedEmployee.base_rate, + rules: [ + { + required: true, + message: t("general.validation.required") + } + ] + })()} + +
+ ); +} diff --git a/client/src/components/shop-employees/shop-employees-list.component.jsx b/client/src/components/shop-employees/shop-employees-list.component.jsx new file mode 100644 index 000000000..9984eacee --- /dev/null +++ b/client/src/components/shop-employees/shop-employees-list.component.jsx @@ -0,0 +1,52 @@ +import { Button, List } from "antd"; +import React from "react"; +import { useTranslation } from "react-i18next"; +import CurrencyFormatter from "../../utils/CurrencyFormatter"; +export default function ShopEmployeesListComponent({ + loading, + employees, + setSelectedEmployee, + handleDelete +}) { + const { t } = useTranslation(); + return ( +
+ + ( + setSelectedEmployee(item)}> + {t("general.actions.edit")} + , + + ]} + > + + {item.cost_center} @{" "} + {item.base_rate} + + } + /> + + )} + /> +
+ ); +} diff --git a/client/src/components/shop-employees/shop-employees.component.jsx b/client/src/components/shop-employees/shop-employees.component.jsx new file mode 100644 index 000000000..44fc6e531 --- /dev/null +++ b/client/src/components/shop-employees/shop-employees.component.jsx @@ -0,0 +1,34 @@ +import { Col, Row } from "antd"; +import React from "react"; +import ShopEmployeesFormComponent from "./shop-employees-form.component"; +import ShopEmployeesListComponent from "./shop-employees-list.component"; +export default function ShopEmployeeComponent({ + form, + loading, + employees, + employeeState, + handleSubmit, + handleDelete +}) { + const [selectedEmployee, setSelectedEmployee] = employeeState; + return ( + + + + + + + + + + ); +} diff --git a/client/src/components/shop-employees/shop-employees.container.jsx b/client/src/components/shop-employees/shop-employees.container.jsx new file mode 100644 index 000000000..1d86e835f --- /dev/null +++ b/client/src/components/shop-employees/shop-employees.container.jsx @@ -0,0 +1,112 @@ +import { Form, notification } from "antd"; +import React, { useState } from "react"; +import { useMutation, useQuery } from "react-apollo"; +import { useTranslation } from "react-i18next"; +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { DELETE_EMPLOYEE, INSERT_EMPLOYEES, QUERY_EMPLOYEES, UPDATE_EMPLOYEE } from "../../graphql/employees.queries"; +import { selectBodyshop } from "../../redux/user/user.selectors"; +import AlertComponent from "../alert/alert.component"; +import ShopEmployeeComponent from "./shop-employees.component"; + + +const mapStateToProps = createStructuredSelector({ + bodyshop: selectBodyshop +}); + +function ShopEmployeesContainer({ form, bodyshop }) { + const { t } = useTranslation(); + const employeeState = useState(null); + const { loading, error, data, refetch } = useQuery(QUERY_EMPLOYEES, { + fetchPolicy: "network-only" + }); + + const [updateEmployee] = useMutation(UPDATE_EMPLOYEE); + const [insertEmployees] = useMutation(INSERT_EMPLOYEES); + const [deleteEmployee] = useMutation(DELETE_EMPLOYEE); + const handleDelete = id => { + deleteEmployee({ variables: { id: id } }) + .then(r => { + notification["success"]({ + message: t("employees.successes.delete") + }); + //TODO: Better way to reset the field decorators? + employeeState[1](null); + refetch().then(r => form.resetFields()); + }) + .catch(error => { + notification["error"]({ + message: t("employees.errors.delete") + }); + }); + }; + + const handleSubmit = e => { + e.preventDefault(); + + form.validateFieldsAndScroll((err, values) => { + if (err) { + notification["error"]({ + message: t("employees.errors.validationtitle"), + description: t("employees.errors.validation") + }); + } + if (!err) { + if (employeeState[0].id) { + //Update a record. + updateEmployee({ + variables: { id: employeeState[0].id, employee: values } + }) + .then(r => { + notification["success"]({ + message: t("employees.successes.save") + }); + //TODO: Better way to reset the field decorators? + employeeState[1](null); + refetch().then(r => form.resetFields()); + }) + .catch(error => { + notification["error"]({ + message: t("employees.errors.save") + }); + }); + } else { + //New record, insert it. + insertEmployees({ + variables: { employees: [{ ...values, shopid: bodyshop.id }] } + }).then(r => { + notification["success"]({ + message: t("employees.successes.save") + }); + //TODO: Better way to reset the field decorators? + employeeState[1](null); + refetch() + .then(r => form.resetFields()) + .catch(error => { + notification["error"]({ + message: t("employees.errors.save") + }); + }); + }); + } + } + }); + }; + + if (error) return ; + + return ( + + ); +} +export default connect( + mapStateToProps, + null +)(Form.create({ name: "ShopEmployeesContainer" })(ShopEmployeesContainer)); diff --git a/client/src/components/vehicles-list/vehicles-list.component.jsx b/client/src/components/vehicles-list/vehicles-list.component.jsx index 466adfe05..49362c74d 100644 --- a/client/src/components/vehicles-list/vehicles-list.component.jsx +++ b/client/src/components/vehicles-list/vehicles-list.component.jsx @@ -1,9 +1,8 @@ +import { Input, Table } from "antd"; import React, { useState } from "react"; import { useTranslation } from "react-i18next"; -import { alphaSort } from "../../utils/sorters"; import { Link } from "react-router-dom"; -import PhoneFormatter from "../../utils/PhoneFormatter"; -import { Table, Icon, Input } from "antd"; +import { alphaSort } from "../../utils/sorters"; export default function VehiclesListComponent({ loading, vehicles, refetch }) { const [state, setState] = useState({ diff --git a/client/src/graphql/employees.queries.jsx b/client/src/graphql/employees.queries.jsx new file mode 100644 index 000000000..1fb7ed1d9 --- /dev/null +++ b/client/src/graphql/employees.queries.jsx @@ -0,0 +1,48 @@ +import { gql } from "apollo-boost"; + +export const QUERY_EMPLOYEES = gql` + query QUERY_EMPLOYEES { + employees { + last_name + id + first_name + employee_number + active + termination_date + hire_date + flat_rate + cost_center + base_rate + } + } +`; + +export const INSERT_EMPLOYEES = gql` + mutation INSERT_EMPLOYEES($employees: [employees_insert_input!]!) { + insert_employees(objects: $employees) { + returning { + id + } + } + } +`; + +export const UPDATE_EMPLOYEE = gql` + mutation UPDATE_EMPLOYEE($id: uuid!, $employee: employees_set_input) { + update_employees(where: { id: { _eq: $id } }, _set: $employee) { + returning { + id + } + } + } +`; + +export const DELETE_EMPLOYEE = gql` + mutation DELETE_EMPLOYEE($id: uuid!) { + delete_employees(where: { id: { _eq: $id } }) { + returning { + id + } + } + } +`; diff --git a/client/src/pages/jobs/jobs.page.jsx b/client/src/pages/jobs/jobs.page.jsx index 13c2e116c..0befc896c 100644 --- a/client/src/pages/jobs/jobs.page.jsx +++ b/client/src/pages/jobs/jobs.page.jsx @@ -1,11 +1,10 @@ -import React, { useEffect, useState } from "react"; import { useQuery } from "@apollo/react-hooks"; -import AlertComponent from "../../components/alert/alert.component"; -import { Col } from "antd"; -import { QUERY_ALL_OPEN_JOBS } from "../../graphql/jobs.queries"; +import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; -import JobsList from "../../components/jobs-list/jobs-list.component"; +import AlertComponent from "../../components/alert/alert.component"; import JobDetailCards from "../../components/job-detail-cards/job-detail-cards.component"; +import JobsList from "../../components/jobs-list/jobs-list.component"; +import { QUERY_ALL_OPEN_JOBS } from "../../graphql/jobs.queries"; //TODO: Implement pagination for this. export default function JobsPage({ match, location }) { @@ -21,9 +20,9 @@ export default function JobsPage({ match, location }) { const { hash } = location; const [selectedJob, setSelectedJob] = useState(hash ? hash.substr(1) : null); - if (error) return ; + if (error) return ; return ( - +
- +
); } diff --git a/client/src/pages/manage/manage.page.jsx b/client/src/pages/manage/manage.page.jsx index 2201db8d2..9dd1d0de3 100644 --- a/client/src/pages/manage/manage.page.jsx +++ b/client/src/pages/manage/manage.page.jsx @@ -39,6 +39,8 @@ const OwnersContainer = lazy(() => import("../owners/owners.page.container")); const OwnersDetailContainer = lazy(() => import("../owners-detail/owners-detail.page.container") ); +const ShopPage = lazy(() => import("../shop/shop.page.component")); + const { Header, Content, Footer } = Layout; export default function Manage({ match }) { @@ -56,7 +58,10 @@ export default function Manage({ match }) { - + + + diff --git a/client/src/pages/owners/owners.page.container.jsx b/client/src/pages/owners/owners.page.container.jsx index 85c71f91a..172918110 100644 --- a/client/src/pages/owners/owners.page.container.jsx +++ b/client/src/pages/owners/owners.page.container.jsx @@ -1,8 +1,12 @@ -import React from 'react' -import OwnersPageComponent from './owners.page.component' +import React, { useEffect } from "react"; +import OwnersPageComponent from "./owners.page.component"; +import { useTranslation } from "react-i18next"; export default function OwnersPageContainer() { - return ( - - ) + const { t } = useTranslation(); + useEffect(() => { + document.title = t("titles.owners"); + }, [t]); + + return ; } diff --git a/client/src/pages/shop/shop.page.component.jsx b/client/src/pages/shop/shop.page.component.jsx new file mode 100644 index 000000000..86e5acfe6 --- /dev/null +++ b/client/src/pages/shop/shop.page.component.jsx @@ -0,0 +1,25 @@ +import { Tabs } from "antd"; +import React, { useEffect } from "react"; +import { useTranslation } from "react-i18next"; +import ShopEmployeesContainer from "../../components/shop-employees/shop-employees.container"; + +export default function ShopPage() { + const { t } = useTranslation(); + useEffect(() => { + document.title = t("titles.shop"); + }, [t]); + + return ( + + + Shop INfo + + + + + + Licensing + + + ); +} diff --git a/client/src/pages/vehicles/vehicles.page.container.jsx b/client/src/pages/vehicles/vehicles.page.container.jsx index 8d656af4b..086998bde 100644 --- a/client/src/pages/vehicles/vehicles.page.container.jsx +++ b/client/src/pages/vehicles/vehicles.page.container.jsx @@ -1,6 +1,10 @@ -import React from "react"; +import React, { useEffect } from "react"; import VehiclesPageComponent from "./vehicles.page.component"; - +import { useTranslation } from "react-i18next"; export default function VehiclesPageContainer() { + const { t } = useTranslation(); + useEffect(() => { + document.title = t("titles.vehicles"); + }, [t]); return ; } diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index e58fea7bf..b4832f728 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -55,12 +55,42 @@ "insert": "Uploaded document successfully. " } }, + "employees": { + "actions": { + "new": "New Employee" + }, + "errors": { + "delete": "Error encountered while deleting employee.", + "save": "Error encountered saving employee.", + "validation": "Please check all fields.", + "validationtitle": "Unable to save employee." + }, + "fields": { + "active": "Active?", + "base_rate": "Base Rate", + "cost_center": "Cost Center", + "employee_number": "Employee Number", + "first_name": "First Name", + "flat_rate": "Flat Rate (Disabled is Straight Time)", + "hire_date": "Hire Date", + "last_name": "Last Name", + "termination_date": "Termination Date" + }, + "successes": { + "delete": "Employee deleted successfully.", + "save": "Employee saved successfully." + } + }, "general": { "actions": { - "reset": "Reset to original." + "delete": "Delete", + "edit": "Edit", + "reset": "Reset to original.", + "save": "Save" }, "labels": { "actions": "Actions", + "barcode": "Barcode", "in": "In", "loading": "Loading...", "loadingapp": "Loading Bodyshop.app", @@ -76,6 +106,9 @@ }, "messages": { "unsavedchanges": "You have unsaved changes." + }, + "validation": { + "required": "This field is required. " } }, "joblines": { @@ -251,6 +284,7 @@ "jobs": "Jobs", "owners": "Owners", "schedule": "Schedule", + "shop": "My Shop", "vehicles": "Vehicles" }, "jobsdetail": { @@ -330,9 +364,12 @@ "jobsdetail": "Job {{ro_number}} | $t(titles.app)", "jobsdocuments": "Job Documents {{ro_number}} | $t(titles.app)", "manageroot": "Home | $t(titles.app)", + "owners": "All Owners | $t(titles.app)", "profile": "My Profile | $t(titles.app)", "schedule": "Schedule | $t(titles.app)", - "vehicledetail": "Vehicle Details {{vehicle}} | $t(titles.app)" + "shop": "My Shop | $t(titles.app)", + "vehicledetail": "Vehicle Details {{vehicle}} | $t(titles.app)", + "vehicles": "All Vehicles | $t(titles.app)" }, "user": { "actions": { diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index d9d0f2b4b..7bc56c0c8 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -55,12 +55,42 @@ "insert": "Documento cargado con éxito." } }, + "employees": { + "actions": { + "new": "Nuevo empleado" + }, + "errors": { + "delete": "Se encontró un error al eliminar al empleado.", + "save": "Se encontró un error al salvar al empleado.", + "validation": "Por favor verifique todos los campos.", + "validationtitle": "No se puede salvar al empleado." + }, + "fields": { + "active": "¿Activo?", + "base_rate": "Tasa básica", + "cost_center": "Centro de costos", + "employee_number": "Numero de empleado", + "first_name": "Nombre de pila", + "flat_rate": "Tarifa plana (deshabilitado es tiempo recto)", + "hire_date": "Fecha de contratación", + "last_name": "Apellido", + "termination_date": "Fecha de conclusión" + }, + "successes": { + "delete": "Empleado eliminado con éxito.", + "save": "Empleado guardado con éxito." + } + }, "general": { "actions": { - "reset": "Restablecer a original." + "delete": "Borrar", + "edit": "Editar", + "reset": "Restablecer a original.", + "save": "Salvar" }, "labels": { "actions": "Comportamiento", + "barcode": "código de barras", "in": "en", "loading": "Cargando...", "loadingapp": "Cargando Bodyshop.app", @@ -76,6 +106,9 @@ }, "messages": { "unsavedchanges": "Usted tiene cambios no guardados." + }, + "validation": { + "required": "Este campo es requerido." } }, "joblines": { @@ -251,6 +284,7 @@ "jobs": "Trabajos", "owners": "propietarios", "schedule": "Programar", + "shop": "Mi tienda", "vehicles": "Vehículos" }, "jobsdetail": { @@ -330,9 +364,12 @@ "jobsdetail": "Trabajo {{ro_number}} | $t(titles.app)", "jobsdocuments": "Documentos de trabajo {{ro_number}} | $ t (títulos.app)", "manageroot": "Casa | $t(titles.app)", + "owners": "Todos los propietarios | $t(titles.app)", "profile": "Mi perfil | $t(titles.app)", "schedule": "Horario | $t(titles.app)", - "vehicledetail": "Detalles del vehículo {{vehicle}} | $t(titles.app)" + "shop": "Mi tienda | $t(titles.app)", + "vehicledetail": "Detalles del vehículo {{vehicle}} | $t(titles.app)", + "vehicles": "Todos los vehiculos | $t(titles.app)" }, "user": { "actions": { diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 8316b3b07..8dfe552f3 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -55,12 +55,42 @@ "insert": "Document téléchargé avec succès." } }, + "employees": { + "actions": { + "new": "Nouvel employé" + }, + "errors": { + "delete": "Erreur rencontrée lors de la suppression de l'employé.", + "save": "Une erreur s'est produite lors de l'enregistrement de l'employé.", + "validation": "Veuillez cocher tous les champs.", + "validationtitle": "Impossible d'enregistrer l'employé." + }, + "fields": { + "active": "Actif?", + "base_rate": "Taux de base", + "cost_center": "Centre de coûts", + "employee_number": "Numéro d'employé", + "first_name": "Prénom", + "flat_rate": "Taux fixe (désactivé est le temps normal)", + "hire_date": "Date d'embauche", + "last_name": "Nom de famille", + "termination_date": "Date de résiliation" + }, + "successes": { + "delete": "L'employé a bien été supprimé.", + "save": "L'employé a enregistré avec succès." + } + }, "general": { "actions": { - "reset": "Rétablir l'original." + "delete": "Effacer", + "edit": "modifier", + "reset": "Rétablir l'original.", + "save": "sauvegarder" }, "labels": { "actions": "actes", + "barcode": "code à barre", "in": "dans", "loading": "Chargement...", "loadingapp": "Chargement de Bodyshop.app", @@ -76,6 +106,9 @@ }, "messages": { "unsavedchanges": "Vous avez des changements non enregistrés." + }, + "validation": { + "required": "Ce champ est requis." } }, "joblines": { @@ -251,6 +284,7 @@ "jobs": "Emplois", "owners": "Propriétaires", "schedule": "Programme", + "shop": "Mon magasin", "vehicles": "Véhicules" }, "jobsdetail": { @@ -330,9 +364,12 @@ "jobsdetail": "Travail {{ro_number}} | $t(titles.app)", "jobsdocuments": "Documents de travail {{ro_number}} | $ t (titres.app)", "manageroot": "Accueil | $t(titles.app)", + "owners": "Tous les propriétaires | $t(titles.app)", "profile": "Mon profil | $t(titles.app)", "schedule": "Horaire | $t(titles.app)", - "vehicledetail": "Détails du véhicule {{vehicle} | $t(titles.app)" + "shop": "Mon magasin | $t(titles.app)", + "vehicledetail": "Détails du véhicule {{vehicle} | $t(titles.app)", + "vehicles": "Tous les véhicules | $t(titles.app)" }, "user": { "actions": { diff --git a/client/yarn.lock b/client/yarn.lock index 20145098e..2d4f614b7 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -8000,6 +8000,11 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" +jsbarcode@^3.8.0: + version "3.11.0" + resolved "https://registry.yarnpkg.com/jsbarcode/-/jsbarcode-3.11.0.tgz#20623e008b101ef45d0cce9c8022cdf49be28547" + integrity sha512-/ozCd7wsa+VIHo9sUc03HneVEQrH7cVWfJolUT/WOW1m8mJ2e3iYZje6C9X3LFHdczlesqFHRpxLtbVsNtjyow== + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -11302,6 +11307,14 @@ react-app-polyfill@^1.0.6: regenerator-runtime "^0.13.3" whatwg-fetch "^3.0.0" +react-barcode@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/react-barcode/-/react-barcode-1.4.0.tgz#ebc85ff1b8b49ac4b947b7f3745d684c6c363902" + integrity sha512-xDxIc9WUTQPMcwc3kbCVsjh03WiPyynms9OSdsNSh2AAgB6XqMiy9hYWkCNHgdNdvurkvKB6hm25AZHXyQfvlQ== + dependencies: + jsbarcode "^3.8.0" + prop-types "^15.6.2" + react-big-calendar@^0.23.0: version "0.23.0" resolved "https://registry.yarnpkg.com/react-big-calendar/-/react-big-calendar-0.23.0.tgz#cc780481548fcefabb04cea05dd1a08456702a67" diff --git a/hasura/migrations/1581357049913_alter_table_public_employees_add_column_hire_date/down.yaml b/hasura/migrations/1581357049913_alter_table_public_employees_add_column_hire_date/down.yaml new file mode 100644 index 000000000..abfa592ca --- /dev/null +++ b/hasura/migrations/1581357049913_alter_table_public_employees_add_column_hire_date/down.yaml @@ -0,0 +1,3 @@ +- args: + sql: ALTER TABLE "public"."employees" DROP COLUMN "hire_date"; + type: run_sql diff --git a/hasura/migrations/1581357049913_alter_table_public_employees_add_column_hire_date/up.yaml b/hasura/migrations/1581357049913_alter_table_public_employees_add_column_hire_date/up.yaml new file mode 100644 index 000000000..1005ffd15 --- /dev/null +++ b/hasura/migrations/1581357049913_alter_table_public_employees_add_column_hire_date/up.yaml @@ -0,0 +1,3 @@ +- args: + sql: ALTER TABLE "public"."employees" ADD COLUMN "hire_date" date NULL; + type: run_sql diff --git a/hasura/migrations/1581357057407_alter_table_public_employees_add_column_termination_date/down.yaml b/hasura/migrations/1581357057407_alter_table_public_employees_add_column_termination_date/down.yaml new file mode 100644 index 000000000..d93fb1e04 --- /dev/null +++ b/hasura/migrations/1581357057407_alter_table_public_employees_add_column_termination_date/down.yaml @@ -0,0 +1,3 @@ +- args: + sql: ALTER TABLE "public"."employees" DROP COLUMN "termination_date"; + type: run_sql diff --git a/hasura/migrations/1581357057407_alter_table_public_employees_add_column_termination_date/up.yaml b/hasura/migrations/1581357057407_alter_table_public_employees_add_column_termination_date/up.yaml new file mode 100644 index 000000000..44c8b84a2 --- /dev/null +++ b/hasura/migrations/1581357057407_alter_table_public_employees_add_column_termination_date/up.yaml @@ -0,0 +1,3 @@ +- args: + sql: ALTER TABLE "public"."employees" ADD COLUMN "termination_date" date NULL; + type: run_sql diff --git a/hasura/migrations/1581357072694_alter_table_public_employees_add_column_base_rate/down.yaml b/hasura/migrations/1581357072694_alter_table_public_employees_add_column_base_rate/down.yaml new file mode 100644 index 000000000..bbe0e2124 --- /dev/null +++ b/hasura/migrations/1581357072694_alter_table_public_employees_add_column_base_rate/down.yaml @@ -0,0 +1,3 @@ +- args: + sql: ALTER TABLE "public"."employees" DROP COLUMN "base_rate"; + type: run_sql diff --git a/hasura/migrations/1581357072694_alter_table_public_employees_add_column_base_rate/up.yaml b/hasura/migrations/1581357072694_alter_table_public_employees_add_column_base_rate/up.yaml new file mode 100644 index 000000000..b0aee872f --- /dev/null +++ b/hasura/migrations/1581357072694_alter_table_public_employees_add_column_base_rate/up.yaml @@ -0,0 +1,3 @@ +- args: + sql: ALTER TABLE "public"."employees" ADD COLUMN "base_rate" numeric NULL; + type: run_sql diff --git a/hasura/migrations/1581357170091_alter_table_public_employees_add_column_cost_center/down.yaml b/hasura/migrations/1581357170091_alter_table_public_employees_add_column_cost_center/down.yaml new file mode 100644 index 000000000..01fa47327 --- /dev/null +++ b/hasura/migrations/1581357170091_alter_table_public_employees_add_column_cost_center/down.yaml @@ -0,0 +1,3 @@ +- args: + sql: ALTER TABLE "public"."employees" DROP COLUMN "cost_center"; + type: run_sql diff --git a/hasura/migrations/1581357170091_alter_table_public_employees_add_column_cost_center/up.yaml b/hasura/migrations/1581357170091_alter_table_public_employees_add_column_cost_center/up.yaml new file mode 100644 index 000000000..8067de290 --- /dev/null +++ b/hasura/migrations/1581357170091_alter_table_public_employees_add_column_cost_center/up.yaml @@ -0,0 +1,3 @@ +- args: + sql: ALTER TABLE "public"."employees" ADD COLUMN "cost_center" text NOT NULL; + type: run_sql diff --git a/hasura/migrations/1581357179730_alter_table_public_employees_alter_column_base_rate/down.yaml b/hasura/migrations/1581357179730_alter_table_public_employees_alter_column_base_rate/down.yaml new file mode 100644 index 000000000..d510666fa --- /dev/null +++ b/hasura/migrations/1581357179730_alter_table_public_employees_alter_column_base_rate/down.yaml @@ -0,0 +1,10 @@ +- args: + sql: ALTER TABLE ONLY "public"."employees" ALTER COLUMN "base_rate" SET DEFAULT + 0; + type: run_sql +- args: + sql: ALTER TABLE "public"."employees" ALTER COLUMN "base_rate" DROP NOT NULL; + type: run_sql +- args: + sql: COMMENT ON COLUMN "public"."employees"."base_rate" IS E'null' + type: run_sql diff --git a/hasura/migrations/1581357179730_alter_table_public_employees_alter_column_base_rate/up.yaml b/hasura/migrations/1581357179730_alter_table_public_employees_alter_column_base_rate/up.yaml new file mode 100644 index 000000000..0fb29a6fe --- /dev/null +++ b/hasura/migrations/1581357179730_alter_table_public_employees_alter_column_base_rate/up.yaml @@ -0,0 +1,10 @@ +- args: + sql: ALTER TABLE ONLY "public"."employees" ALTER COLUMN "base_rate" SET DEFAULT + 0; + type: run_sql +- args: + sql: ALTER TABLE "public"."employees" ALTER COLUMN "base_rate" SET NOT NULL; + type: run_sql +- args: + sql: COMMENT ON COLUMN "public"."employees"."base_rate" IS E'' + type: run_sql diff --git a/hasura/migrations/1581357246577_alter_table_public_employees_add_column_pay_type/down.yaml b/hasura/migrations/1581357246577_alter_table_public_employees_add_column_pay_type/down.yaml new file mode 100644 index 000000000..185cc9a8b --- /dev/null +++ b/hasura/migrations/1581357246577_alter_table_public_employees_add_column_pay_type/down.yaml @@ -0,0 +1,3 @@ +- args: + sql: ALTER TABLE "public"."employees" DROP COLUMN "pay_type"; + type: run_sql diff --git a/hasura/migrations/1581357246577_alter_table_public_employees_add_column_pay_type/up.yaml b/hasura/migrations/1581357246577_alter_table_public_employees_add_column_pay_type/up.yaml new file mode 100644 index 000000000..784b99b23 --- /dev/null +++ b/hasura/migrations/1581357246577_alter_table_public_employees_add_column_pay_type/up.yaml @@ -0,0 +1,4 @@ +- args: + sql: ALTER TABLE "public"."employees" ADD COLUMN "pay_type" integer NOT NULL DEFAULT + 0; + type: run_sql diff --git a/hasura/migrations/1581357269779_alter_table_public_employees_drop_column_pay_type/down.yaml b/hasura/migrations/1581357269779_alter_table_public_employees_drop_column_pay_type/down.yaml new file mode 100644 index 000000000..c1bc66684 --- /dev/null +++ b/hasura/migrations/1581357269779_alter_table_public_employees_drop_column_pay_type/down.yaml @@ -0,0 +1,9 @@ +- args: + sql: ALTER TABLE "public"."employees" ADD COLUMN "pay_type" int4 + type: run_sql +- args: + sql: ALTER TABLE "public"."employees" ALTER COLUMN "pay_type" DROP NOT NULL + type: run_sql +- args: + sql: ALTER TABLE "public"."employees" ALTER COLUMN "pay_type" SET DEFAULT 0 + type: run_sql diff --git a/hasura/migrations/1581357269779_alter_table_public_employees_drop_column_pay_type/up.yaml b/hasura/migrations/1581357269779_alter_table_public_employees_drop_column_pay_type/up.yaml new file mode 100644 index 000000000..bbbe455f0 --- /dev/null +++ b/hasura/migrations/1581357269779_alter_table_public_employees_drop_column_pay_type/up.yaml @@ -0,0 +1,3 @@ +- args: + sql: ALTER TABLE "public"."employees" DROP COLUMN "pay_type" CASCADE + type: run_sql diff --git a/hasura/migrations/1581357292599_alter_table_public_employees_add_column_flat_rate/down.yaml b/hasura/migrations/1581357292599_alter_table_public_employees_add_column_flat_rate/down.yaml new file mode 100644 index 000000000..11c760bb8 --- /dev/null +++ b/hasura/migrations/1581357292599_alter_table_public_employees_add_column_flat_rate/down.yaml @@ -0,0 +1,3 @@ +- args: + sql: ALTER TABLE "public"."employees" DROP COLUMN "flat_rate"; + type: run_sql diff --git a/hasura/migrations/1581357292599_alter_table_public_employees_add_column_flat_rate/up.yaml b/hasura/migrations/1581357292599_alter_table_public_employees_add_column_flat_rate/up.yaml new file mode 100644 index 000000000..1c81a7a12 --- /dev/null +++ b/hasura/migrations/1581357292599_alter_table_public_employees_add_column_flat_rate/up.yaml @@ -0,0 +1,4 @@ +- args: + sql: ALTER TABLE "public"."employees" ADD COLUMN "flat_rate" boolean NOT NULL + DEFAULT false; + type: run_sql diff --git a/hasura/migrations/1581357336859_update_permission_user_public_table_employees/down.yaml b/hasura/migrations/1581357336859_update_permission_user_public_table_employees/down.yaml new file mode 100644 index 000000000..d366a9964 --- /dev/null +++ b/hasura/migrations/1581357336859_update_permission_user_public_table_employees/down.yaml @@ -0,0 +1,35 @@ +- args: + role: user + table: + name: employees + schema: public + type: drop_insert_permission +- args: + permission: + check: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + columns: + - active + - employee_number + - first_name + - last_name + - created_at + - updated_at + - id + - shopid + localPresets: + - key: "" + value: "" + set: {} + role: user + table: + name: employees + schema: public + type: create_insert_permission diff --git a/hasura/migrations/1581357336859_update_permission_user_public_table_employees/up.yaml b/hasura/migrations/1581357336859_update_permission_user_public_table_employees/up.yaml new file mode 100644 index 000000000..0165fb887 --- /dev/null +++ b/hasura/migrations/1581357336859_update_permission_user_public_table_employees/up.yaml @@ -0,0 +1,40 @@ +- args: + role: user + table: + name: employees + schema: public + type: drop_insert_permission +- args: + permission: + check: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + columns: + - id + - created_at + - updated_at + - first_name + - last_name + - employee_number + - shopid + - active + - hire_date + - termination_date + - base_rate + - cost_center + - flat_rate + localPresets: + - key: "" + value: "" + set: {} + role: user + table: + name: employees + schema: public + type: create_insert_permission diff --git a/hasura/migrations/1581357342062_update_permission_user_public_table_employees/down.yaml b/hasura/migrations/1581357342062_update_permission_user_public_table_employees/down.yaml new file mode 100644 index 000000000..976c2df48 --- /dev/null +++ b/hasura/migrations/1581357342062_update_permission_user_public_table_employees/down.yaml @@ -0,0 +1,33 @@ +- args: + role: user + table: + name: employees + schema: public + type: drop_select_permission +- args: + permission: + allow_aggregations: false + columns: + - active + - employee_number + - first_name + - last_name + - created_at + - updated_at + - id + - shopid + computed_fields: [] + filter: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + role: user + table: + name: employees + schema: public + type: create_select_permission diff --git a/hasura/migrations/1581357342062_update_permission_user_public_table_employees/up.yaml b/hasura/migrations/1581357342062_update_permission_user_public_table_employees/up.yaml new file mode 100644 index 000000000..56719d451 --- /dev/null +++ b/hasura/migrations/1581357342062_update_permission_user_public_table_employees/up.yaml @@ -0,0 +1,38 @@ +- args: + role: user + table: + name: employees + schema: public + type: drop_select_permission +- args: + permission: + allow_aggregations: false + columns: + - active + - flat_rate + - hire_date + - termination_date + - base_rate + - cost_center + - employee_number + - first_name + - last_name + - created_at + - updated_at + - id + - shopid + computed_fields: [] + filter: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + role: user + table: + name: employees + schema: public + type: create_select_permission diff --git a/hasura/migrations/1581357346836_update_permission_user_public_table_employees/down.yaml b/hasura/migrations/1581357346836_update_permission_user_public_table_employees/down.yaml new file mode 100644 index 000000000..379b183ce --- /dev/null +++ b/hasura/migrations/1581357346836_update_permission_user_public_table_employees/down.yaml @@ -0,0 +1,35 @@ +- args: + role: user + table: + name: employees + schema: public + type: drop_update_permission +- args: + permission: + columns: + - active + - employee_number + - first_name + - last_name + - created_at + - updated_at + - id + - shopid + filter: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + localPresets: + - key: "" + value: "" + set: {} + role: user + table: + name: employees + schema: public + type: create_update_permission diff --git a/hasura/migrations/1581357346836_update_permission_user_public_table_employees/up.yaml b/hasura/migrations/1581357346836_update_permission_user_public_table_employees/up.yaml new file mode 100644 index 000000000..491b1073b --- /dev/null +++ b/hasura/migrations/1581357346836_update_permission_user_public_table_employees/up.yaml @@ -0,0 +1,40 @@ +- args: + role: user + table: + name: employees + schema: public + type: drop_update_permission +- args: + permission: + columns: + - active + - flat_rate + - hire_date + - termination_date + - base_rate + - cost_center + - employee_number + - first_name + - last_name + - created_at + - updated_at + - id + - shopid + filter: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + localPresets: + - key: "" + value: "" + set: {} + role: user + table: + name: employees + schema: public + type: create_update_permission