Added my shop page and ability to add, edit and delete employees.
This commit is contained in:
@@ -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 (
|
||||
<div>
|
||||
<Popover
|
||||
content={
|
||||
<Barcode
|
||||
value={value}
|
||||
background="transparent"
|
||||
displayValue={false}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Tag>{t("general.labels.barcode")}</Tag>
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -72,6 +72,12 @@ export default ({
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
|
||||
<Menu.Item key="shop">
|
||||
<Link to="/manage/shop">
|
||||
{t("menus.header.shop")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.SubMenu
|
||||
title={
|
||||
<div>
|
||||
|
||||
@@ -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(
|
||||
</div>
|
||||
);
|
||||
|
||||
const tombstoneSubtitle = (
|
||||
<div>
|
||||
<Tag color="red">
|
||||
{job.owner ? (
|
||||
<Link to={`/manage/owners/${job.owner.id}`}>
|
||||
{`${job.ownr_co_nm || ""}${job.ownr_fn || ""} ${job.ownr_ln || ""}`}
|
||||
</Link>
|
||||
) : (
|
||||
t("jobs.errors.noowner")
|
||||
)}
|
||||
</Tag>
|
||||
|
||||
<Tag color="green">
|
||||
{job.vehicle ? (
|
||||
<Link to={`/manage/vehicles/${job.vehicle.id}`}>
|
||||
{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")}
|
||||
</Link>
|
||||
) : null}
|
||||
</Tag>
|
||||
</div>
|
||||
);
|
||||
|
||||
const statusmenu = (
|
||||
<Menu
|
||||
onClick={e => {
|
||||
@@ -137,10 +112,32 @@ export default connect(
|
||||
border: "1px solid rgb(235, 237, 240)"
|
||||
}}
|
||||
title={tombstoneTitle}
|
||||
subTitle={tombstoneSubtitle}
|
||||
//subTitle={tombstoneSubtitle}
|
||||
tags={
|
||||
<span key="job-status">
|
||||
{job.status ? <Tag color="blue">{job.status}</Tag> : null}
|
||||
<Tag color="red">
|
||||
{job.owner ? (
|
||||
<Link to={`/manage/owners/${job.owner.id}`}>
|
||||
{`${job.ownr_co_nm || ""}${job.ownr_fn || ""} ${job.ownr_ln ||
|
||||
""}`}
|
||||
</Link>
|
||||
) : (
|
||||
t("jobs.errors.noowner")
|
||||
)}
|
||||
</Tag>
|
||||
<Tag color="green">
|
||||
{job.vehicle ? (
|
||||
<Link to={`/manage/vehicles/${job.vehicle.id}`}>
|
||||
{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")}
|
||||
</Link>
|
||||
) : null}
|
||||
</Tag>
|
||||
<BarcodePopup value={job.id} />
|
||||
</span>
|
||||
}
|
||||
extra={menuExtra}
|
||||
|
||||
@@ -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 (
|
||||
<Form onSubmit={handleSubmit} autoComplete={"off"}>
|
||||
<Button type="primary" htmlType="submit">
|
||||
{t("general.actions.save")}
|
||||
</Button>
|
||||
|
||||
<Form.Item label={t("employees.fields.first_name")}>
|
||||
{getFieldDecorator("first_name", {
|
||||
initialValue: selectedEmployee.first_name,
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: t("general.validation.required")
|
||||
}
|
||||
]
|
||||
})(<Input name="first_name" />)}
|
||||
</Form.Item>
|
||||
<Form.Item label={t("employees.fields.last_name")}>
|
||||
{getFieldDecorator("last_name", {
|
||||
initialValue: selectedEmployee.last_name,
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: t("general.validation.required")
|
||||
}
|
||||
]
|
||||
})(<Input name="last_name" />)}
|
||||
</Form.Item>
|
||||
<Form.Item label={t("employees.fields.employee_number")}>
|
||||
{getFieldDecorator("employee_number", {
|
||||
initialValue: selectedEmployee.employee_number,
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: t("general.validation.required")
|
||||
}
|
||||
]
|
||||
})(<Input name="employee_number" />)}
|
||||
</Form.Item>
|
||||
<Form.Item label={t("employees.fields.active")}>
|
||||
{getFieldDecorator("active", {
|
||||
initialValue: selectedEmployee.active,
|
||||
valuePropName: "checked"
|
||||
})(<Switch name="active" />)}
|
||||
</Form.Item>
|
||||
<Form.Item label={t("employees.fields.flat_rate")}>
|
||||
{getFieldDecorator("flat_rate", {
|
||||
initialValue: selectedEmployee.flat_rate,
|
||||
valuePropName: "checked"
|
||||
})(<Switch name="active" />)}
|
||||
</Form.Item>
|
||||
<Form.Item label={t("employees.fields.hire_date")}>
|
||||
{getFieldDecorator("hire_date", {
|
||||
initialValue: selectedEmployee.hire_date
|
||||
? moment(selectedEmployee.hire_date)
|
||||
: null,
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: t("general.validation.required")
|
||||
}
|
||||
]
|
||||
})(<DatePicker name="hire_date" />)}
|
||||
</Form.Item>
|
||||
<Form.Item label={t("employees.fields.termination_date")}>
|
||||
{getFieldDecorator("termination_date", {
|
||||
initialValue: selectedEmployee.termination_date
|
||||
? moment(selectedEmployee.termination_date)
|
||||
: null
|
||||
})(<DatePicker name="termination_date" />)}
|
||||
</Form.Item>
|
||||
{
|
||||
//TODO Make this a picklist.
|
||||
}
|
||||
<Form.Item label={t("employees.fields.cost_center")}>
|
||||
{getFieldDecorator("cost_center", {
|
||||
initialValue: selectedEmployee.cost_center,
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: t("general.validation.required")
|
||||
}
|
||||
]
|
||||
})(<Input name="cost_center" />)}
|
||||
</Form.Item>
|
||||
<Form.Item label={t("employees.fields.base_rate")}>
|
||||
{getFieldDecorator("base_rate", {
|
||||
initialValue: selectedEmployee.base_rate,
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: t("general.validation.required")
|
||||
}
|
||||
]
|
||||
})(<InputNumber name="base_rate" />)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
@@ -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 (
|
||||
<div>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
setSelectedEmployee({});
|
||||
}}
|
||||
>
|
||||
{t("employees.actions.new")}
|
||||
</Button>
|
||||
<List
|
||||
loading={loading}
|
||||
itemLayout="horizontal"
|
||||
dataSource={employees}
|
||||
renderItem={item => (
|
||||
<List.Item
|
||||
actions={[
|
||||
<Button key="edit" onClick={() => setSelectedEmployee(item)}>
|
||||
{t("general.actions.edit")}
|
||||
</Button>,
|
||||
<Button key="delete" onClick={() => handleDelete(item.id)}>
|
||||
{t("general.actions.delete")}
|
||||
</Button>
|
||||
]}
|
||||
>
|
||||
<List.Item.Meta
|
||||
title={`${item.first_name || ""} ${item.last_name ||
|
||||
""} | ${item.employee_number || ""}`}
|
||||
description={
|
||||
<span>
|
||||
{item.cost_center} @{" "}
|
||||
<CurrencyFormatter>{item.base_rate}</CurrencyFormatter>
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -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 (
|
||||
<Row>
|
||||
<Col span={6}>
|
||||
<ShopEmployeesListComponent
|
||||
employees={employees}
|
||||
loading={loading}
|
||||
setSelectedEmployee={setSelectedEmployee}
|
||||
handleDelete={handleDelete}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col span={18}>
|
||||
<ShopEmployeesFormComponent
|
||||
handleSubmit={handleSubmit}
|
||||
form={form}
|
||||
selectedEmployee={selectedEmployee}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
@@ -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 <AlertComponent message={error.message} type="error" />;
|
||||
|
||||
return (
|
||||
<ShopEmployeeComponent
|
||||
handleSubmit={handleSubmit}
|
||||
handleDelete={handleDelete}
|
||||
form={form}
|
||||
loading={loading}
|
||||
employeeState={employeeState}
|
||||
employees={data ? data.employees : []}
|
||||
/>
|
||||
);
|
||||
}
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
null
|
||||
)(Form.create({ name: "ShopEmployeesContainer" })(ShopEmployeesContainer));
|
||||
@@ -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({
|
||||
|
||||
48
client/src/graphql/employees.queries.jsx
Normal file
48
client/src/graphql/employees.queries.jsx
Normal file
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -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 <AlertComponent message={error.message} type='error' />;
|
||||
if (error) return <AlertComponent message={error.message} type="error" />;
|
||||
return (
|
||||
<Col span={22} offset={1}>
|
||||
<div>
|
||||
<JobsList
|
||||
loading={loading}
|
||||
selectedJob={selectedJob}
|
||||
@@ -31,6 +30,6 @@ export default function JobsPage({ match, location }) {
|
||||
jobs={data ? data.jobs : null}
|
||||
/>
|
||||
<JobDetailCards selectedJob={selectedJob} />
|
||||
</Col>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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 }) {
|
||||
<Layout>
|
||||
<ChatWindowContainer />
|
||||
|
||||
<Content className="content-container" style={{ margin: "0px" }}>
|
||||
<Content
|
||||
className="content-container"
|
||||
style={{ padding: "0em 4em 4em" }}
|
||||
>
|
||||
<ErrorBoundary>
|
||||
<Suspense
|
||||
fallback={
|
||||
@@ -113,6 +118,8 @@ export default function Manage({ match }) {
|
||||
path={`${match.path}/available`}
|
||||
component={JobsAvailablePage}
|
||||
/>
|
||||
|
||||
<Route exact path={`${match.path}/shop/`} component={ShopPage} />
|
||||
</Suspense>
|
||||
</ErrorBoundary>
|
||||
</Content>
|
||||
|
||||
@@ -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 (
|
||||
<OwnersPageComponent />
|
||||
)
|
||||
const { t } = useTranslation();
|
||||
useEffect(() => {
|
||||
document.title = t("titles.owners");
|
||||
}, [t]);
|
||||
|
||||
return <OwnersPageComponent />;
|
||||
}
|
||||
|
||||
25
client/src/pages/shop/shop.page.component.jsx
Normal file
25
client/src/pages/shop/shop.page.component.jsx
Normal file
@@ -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 (
|
||||
<Tabs>
|
||||
<Tabs.TabPane tab="Shop Info" key="info">
|
||||
Shop INfo
|
||||
</Tabs.TabPane>
|
||||
<Tabs.TabPane tab="Employees" key="employees">
|
||||
<ShopEmployeesContainer />
|
||||
</Tabs.TabPane>
|
||||
<Tabs.TabPane tab="Licensing" key="licensing">
|
||||
Licensing
|
||||
</Tabs.TabPane>
|
||||
</Tabs>
|
||||
);
|
||||
}
|
||||
@@ -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 <VehiclesPageComponent />;
|
||||
}
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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": {
|
||||
|
||||
Reference in New Issue
Block a user