feature/feature/IO-3554-Form-Row-Layout - Responsive overhaul

This commit is contained in:
Dave
2026-02-26 15:56:57 -05:00
parent 226cc801ae
commit fd6f46e39d
99 changed files with 807 additions and 443 deletions

View File

@@ -18,3 +18,4 @@ VITE_PUBLIC_POSTHOG_KEY=phc_xtLmBIu0rjWwExY73Oj5DTH1bGbwq1G1Y8jnlTceien
VITE_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com VITE_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
VITE_APP_AMP_URL=https://vp8k908qy2.execute-api.ca-central-1.amazonaws.com VITE_APP_AMP_URL=https://vp8k908qy2.execute-api.ca-central-1.amazonaws.com
VITE_APP_AMP_KEY=6228a598e57cd66875cfd41604f1f891 VITE_APP_AMP_KEY=6228a598e57cd66875cfd41604f1f891
VITE_APP_ENABLE_RESPONSIVE_TABLE_FILTERING=false

View File

@@ -20,3 +20,4 @@ VITE_PUBLIC_POSTHOG_KEY=phc_xtLmBIu0rjWwExY73Oj5DTH1bGbwq1G1Y8jnlTceien
VITE_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com VITE_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
VITE_APP_AMP_URL=https://vp8k908qy2.execute-api.ca-central-1.amazonaws.com VITE_APP_AMP_URL=https://vp8k908qy2.execute-api.ca-central-1.amazonaws.com
VITE_APP_AMP_KEY=46b1193a867d4e3131ae4c3a64a3fc78 VITE_APP_AMP_KEY=46b1193a867d4e3131ae4c3a64a3fc78
VITE_APP_ENABLE_RESPONSIVE_TABLE_FILTERING=false

View File

@@ -47,7 +47,7 @@
"i18next": "^25.8.13", "i18next": "^25.8.13",
"i18next-browser-languagedetector": "^8.2.1", "i18next-browser-languagedetector": "^8.2.1",
"immutability-helper": "^3.1.1", "immutability-helper": "^3.1.1",
"libphonenumber-js": "^1.12.37", "libphonenumber-js": "^1.12.38",
"lightningcss": "^1.31.1", "lightningcss": "^1.31.1",
"logrocket": "^12.0.0", "logrocket": "^12.0.0",
"markerjs2": "^2.32.7", "markerjs2": "^2.32.7",
@@ -55,7 +55,7 @@
"normalize-url": "^8.1.1", "normalize-url": "^8.1.1",
"object-hash": "^3.0.0", "object-hash": "^3.0.0",
"phone": "^3.1.71", "phone": "^3.1.71",
"posthog-js": "^1.354.1", "posthog-js": "^1.355.0",
"prop-types": "^15.8.1", "prop-types": "^15.8.1",
"query-string": "^9.3.1", "query-string": "^9.3.1",
"raf-schd": "^4.0.3", "raf-schd": "^4.0.3",
@@ -4861,9 +4861,9 @@
} }
}, },
"node_modules/@posthog/types": { "node_modules/@posthog/types": {
"version": "1.354.1", "version": "1.355.0",
"resolved": "https://registry.npmjs.org/@posthog/types/-/types-1.354.1.tgz", "resolved": "https://registry.npmjs.org/@posthog/types/-/types-1.355.0.tgz",
"integrity": "sha512-/d2ubZOcRbKJU5PWSkt8AwR3l/CCv5vPf4RDHIpGptI6ezDf5sTFWdqF088ziS7J3CB03Pax/ubAqsgJUfIy9A==", "integrity": "sha512-g9YNcIzSe+BJFKjuea7Hr0DiN83XlmqBXRpIyEJ7t9jVAK2Srf67Y2rI0ZjeNXe2LasOyOvoy7RgnSPBXbNZGw==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/@protobufjs/aspromise": { "node_modules/@protobufjs/aspromise": {
@@ -12906,9 +12906,9 @@
} }
}, },
"node_modules/libphonenumber-js": { "node_modules/libphonenumber-js": {
"version": "1.12.37", "version": "1.12.38",
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.37.tgz", "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.38.tgz",
"integrity": "sha512-rDU6bkpuMs8YRt/UpkuYEAsYSoNuDEbrE41I3KNvmXREGH6DGBJ8Wbak4by29wNOQ27zk4g4HL82zf0OGhwRuw==", "integrity": "sha512-vwzxmasAy9hZigxtqTbFEwp8ZdZ975TiqVDwj5bKx5sR+zi5ucUQy9mbVTkKM9GzqdLdxux/hTw2nmN5J7POMA==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/lightningcss": { "node_modules/lightningcss": {
@@ -15049,9 +15049,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/posthog-js": { "node_modules/posthog-js": {
"version": "1.354.1", "version": "1.355.0",
"resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.354.1.tgz", "resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.355.0.tgz",
"integrity": "sha512-ncHYOOglHAsy5H9xogwmfBeqOF8bK58+b2VRv5SdnqiCfUBndo5pgAU9z2zS5MJuXuYbbpbBN0fGafHwmdr+5Q==", "integrity": "sha512-RpxHyodlr9wuqoZOct8DDg50SGq3SQmUWxYu+G1eOO+PvWsr5N2ZZdhE/rpv2zZccPdbXdgIy3M1pa574Nps7w==",
"license": "SEE LICENSE IN LICENSE", "license": "SEE LICENSE IN LICENSE",
"dependencies": { "dependencies": {
"@opentelemetry/api": "^1.9.0", "@opentelemetry/api": "^1.9.0",
@@ -15060,7 +15060,7 @@
"@opentelemetry/resources": "^2.2.0", "@opentelemetry/resources": "^2.2.0",
"@opentelemetry/sdk-logs": "^0.208.0", "@opentelemetry/sdk-logs": "^0.208.0",
"@posthog/core": "1.23.1", "@posthog/core": "1.23.1",
"@posthog/types": "1.354.1", "@posthog/types": "1.355.0",
"core-js": "^3.38.1", "core-js": "^3.38.1",
"dompurify": "^3.3.1", "dompurify": "^3.3.1",
"fflate": "^0.4.8", "fflate": "^0.4.8",

View File

@@ -46,7 +46,7 @@
"i18next": "^25.8.13", "i18next": "^25.8.13",
"i18next-browser-languagedetector": "^8.2.1", "i18next-browser-languagedetector": "^8.2.1",
"immutability-helper": "^3.1.1", "immutability-helper": "^3.1.1",
"libphonenumber-js": "^1.12.37", "libphonenumber-js": "^1.12.38",
"lightningcss": "^1.31.1", "lightningcss": "^1.31.1",
"logrocket": "^12.0.0", "logrocket": "^12.0.0",
"markerjs2": "^2.32.7", "markerjs2": "^2.32.7",
@@ -54,7 +54,7 @@
"normalize-url": "^8.1.1", "normalize-url": "^8.1.1",
"object-hash": "^3.0.0", "object-hash": "^3.0.0",
"phone": "^3.1.71", "phone": "^3.1.71",
"posthog-js": "^1.354.1", "posthog-js": "^1.355.0",
"prop-types": "^15.8.1", "prop-types": "^15.8.1",
"query-string": "^9.3.1", "query-string": "^9.3.1",
"raf-schd": "^4.0.3", "raf-schd": "^4.0.3",

View File

@@ -1,7 +1,7 @@
import { ApolloProvider } from "@apollo/client/react"; import { ApolloProvider } from "@apollo/client/react";
import * as Sentry from "@sentry/react"; import * as Sentry from "@sentry/react";
import { SplitFactoryProvider, useSplitClient } from "@splitsoftware/splitio-react"; import { SplitFactoryProvider, useSplitClient } from "@splitsoftware/splitio-react";
import { ConfigProvider } from "antd"; import { ConfigProvider, Grid } from "antd";
import enLocale from "antd/es/locale/en_US"; import enLocale from "antd/es/locale/en_US";
import { useEffect, useMemo } from "react"; import { useEffect, useMemo } from "react";
import { CookiesProvider } from "react-cookie"; import { CookiesProvider } from "react-cookie";
@@ -43,10 +43,47 @@ function AppContainer() {
const currentUser = useSelector(selectCurrentUser); const currentUser = useSelector(selectCurrentUser);
const isDarkMode = useSelector(selectDarkMode); const isDarkMode = useSelector(selectDarkMode);
const screens = Grid.useBreakpoint();
const isPhone = !screens.md;
const isUltraWide = Boolean(screens.xxxl);
const theme = useMemo(() => getTheme(isDarkMode), [isDarkMode]); const theme = useMemo(() => {
const baseTheme = getTheme(isDarkMode);
return {
...baseTheme,
token: {
...(baseTheme.token || {}),
screenXXXL: 2160
},
components: {
...(baseTheme.components || {}),
Table: {
...(baseTheme.components?.Table || {}),
cellFontSizeSM: isPhone ? 12 : 13,
cellFontSizeMD: isPhone ? 13 : isUltraWide ? 15 : 14,
cellFontSize: isUltraWide ? 15 : 14,
cellPaddingInlineSM: isPhone ? 8 : 10,
cellPaddingInlineMD: isPhone ? 10 : 14,
cellPaddingInline: isUltraWide ? 20 : 16,
cellPaddingBlockSM: isPhone ? 8 : 10,
cellPaddingBlockMD: isPhone ? 10 : 12,
cellPaddingBlock: isUltraWide ? 14 : 12,
selectionColumnWidth: isPhone ? 44 : 52
}
}
};
}, [isDarkMode, isPhone, isUltraWide]);
const antdInput = useMemo(() => ({ autoComplete: "new-password" }), []); const antdInput = useMemo(() => ({ autoComplete: "new-password" }), []);
const antdTable = useMemo(() => ({ scroll: { x: "max-content" } }), []);
const antdPagination = useMemo(
() => ({
showSizeChanger: !isPhone,
totalBoundaryShowSizeChanger: 100
}),
[isPhone]
);
const antdForm = useMemo( const antdForm = useMemo(
() => ({ () => ({
@@ -122,7 +159,16 @@ function AppContainer() {
return ( return (
<CookiesProvider> <CookiesProvider>
<ApolloProvider client={client}> <ApolloProvider client={client}>
<ConfigProvider input={antdInput} locale={enLocale} theme={theme} form={antdForm}> <ConfigProvider
input={antdInput}
locale={enLocale}
theme={theme}
form={antdForm}
table={antdTable}
pagination={antdPagination}
componentSize={isPhone ? "small" : isUltraWide ? "large" : "middle"}
popupOverflow="viewport"
>
<GlobalLoadingBar /> <GlobalLoadingBar />
<SplitFactoryProvider config={config}> <SplitFactoryProvider config={config}>
<SplitClientProvider> <SplitClientProvider>

View File

@@ -68,7 +68,7 @@ const currentTheme = import.meta.env.DEV ? devTheme : prodTheme;
const getTheme = (isDarkMode) => ({ const getTheme = (isDarkMode) => ({
algorithm: isDarkMode ? darkAlgorithm : defaultAlgorithm, algorithm: isDarkMode ? darkAlgorithm : defaultAlgorithm,
...defaultsDeep(currentTheme, defaultTheme) ...defaultsDeep({}, currentTheme, defaultTheme(isDarkMode))
}); });
export default getTheme; export default getTheme;

View File

@@ -1,4 +1,4 @@
import { Card, Checkbox, Input, Space, Table } from "antd"; import { Card, Checkbox, Input, Space } from "antd";
import queryString from "query-string"; import queryString from "query-string";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -16,6 +16,7 @@ import PayableExportAll from "../payable-export-all-button/payable-export-all-bu
import PayableExportButton from "../payable-export-button/payable-export-button.component"; import PayableExportButton from "../payable-export-button/payable-export-button.component";
import BillMarkSelectedExported from "../payable-mark-selected-exported/payable-mark-selected-exported.component"; import BillMarkSelectedExported from "../payable-mark-selected-exported/payable-mark-selected-exported.component";
import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component"; import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import useLocalStorage from "./../../utils/useLocalStorage"; import useLocalStorage from "./../../utils/useLocalStorage";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
@@ -179,11 +180,12 @@ export function AccountingPayablesTableComponent({ bodyshop, loading, bills, ref
</Space> </Space>
} }
> >
<Table <ResponsiveTable
loading={loading} loading={loading}
dataSource={dataSource} dataSource={dataSource}
pagination={{ placement: "top", pageSize: exportPageLimit, showSizeChanger: false }} pagination={{ placement: "top", pageSize: exportPageLimit, showSizeChanger: false }}
columns={columns} columns={columns}
mobileColumnKeys={["vendorname", "invoice_number", "ro_number", "total", "actions"]}
rowKey="id" rowKey="id"
onChange={handleTableChange} onChange={handleTableChange}
rowSelection={{ rowSelection={{

View File

@@ -1,4 +1,4 @@
import { Card, Input, Space, Table } from "antd"; import { Card, Input, Space } from "antd";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
@@ -17,6 +17,7 @@ import PaymentExportButton from "../payment-export-button/payment-export-button.
import PaymentMarkSelectedExported from "../payment-mark-selected-exported/payment-mark-selected-exported.component"; import PaymentMarkSelectedExported from "../payment-mark-selected-exported/payment-mark-selected-exported.component";
import PaymentsExportAllButton from "../payments-export-all-button/payments-export-all-button.component"; import PaymentsExportAllButton from "../payments-export-all-button/payments-export-all-button.component";
import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component"; import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component";
import ResponsiveTable from "../responsive-table/responsive-table.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop bodyshop: selectBodyshop
@@ -192,11 +193,12 @@ export function AccountingPayablesTableComponent({ bodyshop, loading, payments,
</Space> </Space>
} }
> >
<Table <ResponsiveTable
loading={loading} loading={loading}
dataSource={dataSource} dataSource={dataSource}
pagination={{ placement: "top", pageSize: exportPageLimit, showSizeChanger: false }} pagination={{ placement: "top", pageSize: exportPageLimit, showSizeChanger: false }}
columns={columns} columns={columns}
mobileColumnKeys={["ro_number", "date", "owner", "amount", "actions"]}
rowKey="id" rowKey="id"
onChange={handleTableChange} onChange={handleTableChange}
rowSelection={{ rowSelection={{

View File

@@ -1,4 +1,4 @@
import { Button, Card, Input, Space, Table } from "antd"; import { Button, Card, Input, Space } from "antd";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
@@ -17,6 +17,7 @@ import JobsExportAllButton from "../jobs-export-all-button/jobs-export-all-butto
import JobMarkSelectedExported from "../jobs-mark-selected-exported/jobs-mark-selected-exported"; import JobMarkSelectedExported from "../jobs-mark-selected-exported/jobs-mark-selected-exported";
import OwnerNameDisplay, { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component"; import OwnerNameDisplay, { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component";
import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component"; import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component";
import ResponsiveTable from "../responsive-table/responsive-table.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop bodyshop: selectBodyshop
@@ -209,11 +210,12 @@ export function AccountingReceivablesTableComponent({ bodyshop, loading, jobs, r
</Space> </Space>
} }
> >
<Table <ResponsiveTable
loading={loading} loading={loading}
dataSource={dataSource} dataSource={dataSource}
pagination={{ placement: "top", pageSize: exportPageLimit, showSizeChanger: false }} pagination={{ placement: "top", pageSize: exportPageLimit, showSizeChanger: false }}
columns={columns} columns={columns}
mobileColumnKeys={["ro_number", "status", "owner", "clm_total", "actions"]}
rowKey="id" rowKey="id"
onChange={handleTableChange} onChange={handleTableChange}
rowSelection={{ rowSelection={{

View File

@@ -1,5 +1,5 @@
import { useState } from "react"; import { useState } from "react";
import { Table } from "antd"; import ResponsiveTable from "../responsive-table/responsive-table.component";
import { alphaSort } from "../../utils/sorters"; import { alphaSort } from "../../utils/sorters";
import { DateTimeFormatter } from "../../utils/DateFormatter"; import { DateTimeFormatter } from "../../utils/DateFormatter";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -62,11 +62,12 @@ export default function AuditTrailListComponent({ loading, data }) {
}; };
return ( return (
<Table <ResponsiveTable
{...formItemLayout} {...formItemLayout}
loading={loading} loading={loading}
pagination={{ placement: "top", defaultPageSize: pageLimit }} pagination={{ placement: "top", defaultPageSize: pageLimit }}
columns={columns} columns={columns}
mobileColumnKeys={[" created", "operation", " old_val", "useremail"]}
rowKey="id" rowKey="id"
dataSource={data} dataSource={data}
onChange={handleTableChange} onChange={handleTableChange}

View File

@@ -1,4 +1,4 @@
import { Table } from "antd"; import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { DateTimeFormatter } from "../../utils/DateFormatter"; import { DateTimeFormatter } from "../../utils/DateFormatter";
@@ -47,11 +47,12 @@ export default function EmailAuditTrailListComponent({ loading, data }) {
}; };
return ( return (
<Table <ResponsiveTable
{...formItemLayout} {...formItemLayout}
loading={loading} loading={loading}
pagination={{ placement: "top", defaultPageSize: pageLimit }} pagination={{ placement: "top", defaultPageSize: pageLimit }}
columns={columns} columns={columns}
mobileColumnKeys={[" created", "useremail"]}
rowKey="id" rowKey="id"
dataSource={data} dataSource={data}
onChange={handleTableChange} onChange={handleTableChange}

View File

@@ -1,4 +1,5 @@
import { Form, Input, Table } from "antd"; import { Form, Input } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import CurrencyFormatter from "../../utils/CurrencyFormatter"; import CurrencyFormatter from "../../utils/CurrencyFormatter";
@@ -108,7 +109,14 @@ export default function BillFormLinesExtended({ lineData, discount, form, respon
<Form.Item noStyle name="billlineskeys"> <Form.Item noStyle name="billlineskeys">
<button onClick={() => console.log(form.getFieldsValue())}>form</button> <button onClick={() => console.log(form.getFieldsValue())}>form</button>
<Input onChange={(e) => setSearch(e.target.value)} allowClear /> <Input onChange={(e) => setSearch(e.target.value)} allowClear />
<Table pagination={false} size="small" columns={columns} rowKey="id" dataSource={data} /> <ResponsiveTable
pagination={false}
size="small"
columns={columns}
mobileColumnKeys={["line_desc", "oem_partno", "part_type", "act_price"]}
rowKey="id"
dataSource={data}
/>
</Form.Item> </Form.Item>
); );
} }

View File

@@ -1,5 +1,5 @@
import { EditFilled, SyncOutlined } from "@ant-design/icons"; import { EditFilled, SyncOutlined } from "@ant-design/icons";
import { Button, Card, Checkbox, Input, Space, Table } from "antd"; import { Button, Card, Checkbox, Input, Space } from "antd";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { FaTasks } from "react-icons/fa"; import { FaTasks } from "react-icons/fa";
@@ -18,6 +18,7 @@ import BillDetailEditReturnComponent from "../bill-detail-edit/bill-detail-edit-
import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component"; import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component";
import LockerWrapperComponent from "../lock-wrapper/lock-wrapper.component"; import LockerWrapperComponent from "../lock-wrapper/lock-wrapper.component";
import PrintWrapperComponent from "../print-wrapper/print-wrapper.component"; import PrintWrapperComponent from "../print-wrapper/print-wrapper.component";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import UpsellComponent, { upsellEnum } from "../upsell/upsell.component"; import UpsellComponent, { upsellEnum } from "../upsell/upsell.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
@@ -237,12 +238,13 @@ export function BillsListTableComponent({
</Space> </Space>
} }
> >
<Table <ResponsiveTable
loading={billsQuery.loading} loading={billsQuery.loading}
scroll={{ scroll={{
x: true // y: "50rem" x: true // y: "50rem"
}} }}
columns={columns} columns={columns}
mobileColumnKeys={["vendorname", "invoice_number", "date", "total", "actions"]}
rowKey="id" rowKey="id"
dataSource={hasBillsAccess ? filteredBills : []} dataSource={hasBillsAccess ? filteredBills : []}
onChange={handleTableChange} onChange={handleTableChange}

View File

@@ -3,7 +3,8 @@ import { QUERY_ALL_VENDORS } from "../../graphql/vendors.queries";
import { useQuery } from "@apollo/client/react"; import { useQuery } from "@apollo/client/react";
import queryString from "query-string"; import queryString from "query-string";
import { useLocation, useNavigate } from "react-router-dom"; import { useLocation, useNavigate } from "react-router-dom";
import { Input, Table } from "antd"; import { Input } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { alphaSort } from "../../utils/sorters"; import { alphaSort } from "../../utils/sorters";
import AlertComponent from "../alert/alert.component"; import AlertComponent from "../alert/alert.component";
@@ -79,7 +80,7 @@ export default function BillsVendorsList() {
: (data && data.vendors) || []; : (data && data.vendors) || [];
return ( return (
<Table <ResponsiveTable
loading={loading} loading={loading}
title={() => { title={() => {
return ( return (
@@ -91,6 +92,7 @@ export default function BillsVendorsList() {
dataSource={dataSource} dataSource={dataSource}
pagination={{ placement: "top" }} pagination={{ placement: "top" }}
columns={columns} columns={columns}
mobileColumnKeys={["name", "cost_center", "city"]}
rowKey="id" rowKey="id"
onChange={handleTableChange} onChange={handleTableChange}
rowSelection={{ rowSelection={{

View File

@@ -1,4 +1,5 @@
import { Card, Input, Table } from "antd"; import { Card, Input } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { alphaSort } from "../../utils/sorters"; import { alphaSort } from "../../utils/sorters";
@@ -103,10 +104,11 @@ export default function ContractsCarsComponent({ loading, data, selectedCarId, h
/> />
} }
> >
<Table <ResponsiveTable
loading={loading} loading={loading}
pagination={{ placement: "top" }} pagination={{ placement: "top" }}
columns={columns} columns={columns}
mobileColumnKeys={["status", "fleetnumber", "readiness", "year"]}
rowKey="id" rowKey="id"
dataSource={filteredData} dataSource={filteredData}
onChange={handleTableChange} onChange={handleTableChange}

View File

@@ -1,4 +1,5 @@
import { Card, Input, Table } from "antd"; import { Card, Input } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useMemo, useState } from "react"; import { useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { alphaSort } from "../../utils/sorters"; import { alphaSort } from "../../utils/sorters";
@@ -127,10 +128,11 @@ export default function ContractsJobsComponent({ loading, data, selectedJob, han
/> />
} }
> >
<Table <ResponsiveTable
loading={loading} loading={loading}
pagination={{ placement: "top", defaultPageSize: pageLimit, defaultCurrent: defaultCurrent }} pagination={{ placement: "top", defaultPageSize: pageLimit, defaultCurrent: defaultCurrent }}
columns={columns} columns={columns}
mobileColumnKeys={["ro_number", "owner", "status", "vehicle", "plate_no"]}
rowKey="id" rowKey="id"
dataSource={filteredData} dataSource={filteredData}
onChange={handleTableChange} onChange={handleTableChange}

View File

@@ -1,5 +1,6 @@
import { useLazyQuery } from "@apollo/client/react"; import { useLazyQuery } from "@apollo/client/react";
import { Button, Form, Modal, Table } from "antd"; import { Button, Form, Modal } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useEffect } from "react"; import { useEffect } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
@@ -64,7 +65,7 @@ export function ContractsFindModalContainer({ contractFinderModal, toggleModalVi
{t("general.labels.search")} {t("general.labels.search")}
</Button> </Button>
{error && <AlertComponent type="error" title={JSON.stringify(error)} />} {error && <AlertComponent type="error" title={JSON.stringify(error)} />}
<Table <ResponsiveTable
loading={loading} loading={loading}
columns={[ columns={[
{ {
@@ -124,6 +125,7 @@ export function ContractsFindModalContainer({ contractFinderModal, toggleModalVi
render: (text, record) => <DateTimeFormatter>{record.actualreturn}</DateTimeFormatter> render: (text, record) => <DateTimeFormatter>{record.actualreturn}</DateTimeFormatter>
} }
]} ]}
mobileColumnKeys={["agreementnumber", "job.ro_number", "driver_ln", "status"]}
rowKey="id" rowKey="id"
dataSource={data?.cccontracts} dataSource={data?.cccontracts}
/> />

View File

@@ -1,5 +1,5 @@
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { Button, Card, Input, Space, Table, Typography } from "antd"; import { Button, Card, Input, Space, Typography } from "antd";
import queryString from "query-string"; import queryString from "query-string";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -14,6 +14,7 @@ import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors";
import { pageLimit } from "../../utils/config"; import { pageLimit } from "../../utils/config";
import ResponsiveTable from "../responsive-table/responsive-table.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop bodyshop: selectBodyshop
@@ -170,13 +171,14 @@ export function ContractsList({ bodyshop, loading, contracts, refetch, total, se
} }
> >
<ContractsFindModalContainer /> <ContractsFindModalContainer />
<Table <ResponsiveTable
loading={loading} loading={loading}
scroll={{ scroll={{
x: "50%" //y: "40rem" x: "50%" //y: "40rem"
}} }}
pagination={{ placement: "top", pageSize: pageLimit, current: parseInt(page || 1, 10), total: total }} pagination={{ placement: "top", pageSize: pageLimit, current: parseInt(page || 1, 10), total: total }}
columns={columns} columns={columns}
mobileColumnKeys={["agreementnumber", "driver_ln", "status", "scheduledreturn"]}
rowKey="id" rowKey="id"
dataSource={contracts} dataSource={contracts}
onChange={handleTableChange} onChange={handleTableChange}

View File

@@ -1,4 +1,5 @@
import { Card, Table } from "antd"; import { Card } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import queryString from "query-string"; import queryString from "query-string";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useLocation, useNavigate } from "react-router-dom"; import { Link, useLocation, useNavigate } from "react-router-dom";
@@ -73,10 +74,11 @@ export default function CourtesyCarContractListComponent({ contracts, totalContr
return ( return (
<Card title={t("menus.header.courtesycars-contracts")}> <Card title={t("menus.header.courtesycars-contracts")}>
<Table <ResponsiveTable
scroll={{ x: true }} scroll={{ x: true }}
pagination={{ placement: "top", pageSize: pageLimit, current: parseInt(page || 1), total: totalContracts }} pagination={{ placement: "top", pageSize: pageLimit, current: parseInt(page || 1), total: totalContracts }}
columns={columns} columns={columns}
mobileColumnKeys={["agreementnumber", "driver_ln", "status", "job.ro_number"]}
rowKey="id" rowKey="id"
dataSource={contracts} dataSource={contracts}
onChange={handleTableChange} onChange={handleTableChange}

View File

@@ -1,5 +1,6 @@
import { SyncOutlined, WarningFilled } from "@ant-design/icons"; import { SyncOutlined, WarningFilled } from "@ant-design/icons";
import { Button, Card, Dropdown, Input, Space, Table, Tooltip } from "antd"; import { Button, Card, Dropdown, Input, Space, Tooltip } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import dayjs from "../../utils/day"; import dayjs from "../../utils/day";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -275,10 +276,11 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) {
</Space> </Space>
} }
> >
<Table <ResponsiveTable
loading={loading} loading={loading}
pagination={{ placement: "top" }} pagination={{ placement: "top" }}
columns={columns} columns={columns}
mobileColumnKeys={["status", "fleetnumber", "vin", "readiness"]}
rowKey="id" rowKey="id"
dataSource={tableData} dataSource={tableData}
onChange={handleTableChange} onChange={handleTableChange}

View File

@@ -1,5 +1,6 @@
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { Button, Card, Table } from "antd"; import { Button, Card } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import queryString from "query-string"; import queryString from "query-string";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -86,10 +87,11 @@ export default function CsiResponseListPaginated({ refetch, loading, responses,
return ( return (
<Card extra={<Button onClick={() => refetch()} icon={<SyncOutlined />} />}> <Card extra={<Button onClick={() => refetch()} icon={<SyncOutlined />} />}>
<Table <ResponsiveTable
loading={loading} loading={loading}
pagination={{ placement: "top", pageSize: pageLimit, current: parseInt(state.page || 1), total: total }} pagination={{ placement: "top", pageSize: pageLimit, current: parseInt(state.page || 1), total: total }}
columns={columns} columns={columns}
mobileColumnKeys={["ro_number", "owner_name", "completedon"]}
rowKey="id" rowKey="id"
dataSource={responses} dataSource={responses}
onChange={handleTableChange} onChange={handleTableChange}

View File

@@ -1,4 +1,5 @@
import { Card, Table, Tag } from "antd"; import { Card, Tag } from "antd";
import ResponsiveTable from "../../responsive-table/responsive-table.component";
import axios from "axios"; import axios from "axios";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -182,10 +183,11 @@ export default function JobLifecycleDashboardComponent({ data, bodyshop, ...card
</div> </div>
</Card> </Card>
<Card style={{ marginTop: "5px" }} type="inner" title={t("job_lifecycle.titles.top_durations")}> <Card style={{ marginTop: "5px" }} type="inner" title={t("job_lifecycle.titles.top_durations")}>
<Table <ResponsiveTable
size="small" size="small"
pagination={false} pagination={false}
columns={columns} columns={columns}
mobileColumnKeys={["status", "humanReadable", "averageHumanReadable", "statusCount"]}
rowKey={(record) => record.status} rowKey={(record) => record.status}
dataSource={lifecycleData.summations.sort((a, b) => b.value - a.value).slice(0, 3)} dataSource={lifecycleData.summations.sort((a, b) => b.value - a.value).slice(0, 3)}
/> />

View File

@@ -1,4 +1,5 @@
import { Card, Input, Space, Table, Typography } from "antd"; import { Card, Input, Space, Typography } from "antd";
import ResponsiveTable from "../../responsive-table/responsive-table.component";
import axios from "axios"; import axios from "axios";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -104,30 +105,31 @@ export default function DashboardMonthlyJobCosting({ data, ...cardProps }) {
> >
<LoadingSkeleton loading={loading}> <LoadingSkeleton loading={loading}>
<div style={{ height: "100%" }}> <div style={{ height: "100%" }}>
<Table <ResponsiveTable
onChange={handleTableChange} onChange={handleTableChange}
pagination={{ placement: "top", defaultPageSize: pageLimit }} pagination={{ placement: "top", defaultPageSize: pageLimit }}
columns={columns} columns={columns}
mobileColumnKeys={["cost_center", "sales", "costs", "gpdollars"]}
scroll={{ x: true, y: "calc(100% - 4em)" }} scroll={{ x: true, y: "calc(100% - 4em)" }}
rowKey="id" rowKey="id"
style={{ height: "100%" }} style={{ height: "100%" }}
dataSource={filteredData} dataSource={filteredData}
summary={() => ( summary={() => (
<Table.Summary.Row> <ResponsiveTable.Summary.Row>
<Table.Summary.Cell> <ResponsiveTable.Summary.Cell>
<Typography.Title level={4}>{t("general.labels.totals")}</Typography.Title> <Typography.Title level={4}>{t("general.labels.totals")}</Typography.Title>
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell> <ResponsiveTable.Summary.Cell>
{Dinero(costingData?.allSummaryData && costingData.allSummaryData.totalSales).toFormat()} {Dinero(costingData?.allSummaryData && costingData.allSummaryData.totalSales).toFormat()}
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell> <ResponsiveTable.Summary.Cell>
{Dinero(costingData?.allSummaryData && costingData.allSummaryData.totalCost).toFormat()} {Dinero(costingData?.allSummaryData && costingData.allSummaryData.totalCost).toFormat()}
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell> <ResponsiveTable.Summary.Cell>
{Dinero(costingData?.allSummaryData && costingData.allSummaryData.gpdollars).toFormat()} {Dinero(costingData?.allSummaryData && costingData.allSummaryData.gpdollars).toFormat()}
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell></Table.Summary.Cell> <ResponsiveTable.Summary.Cell></ResponsiveTable.Summary.Cell>
</Table.Summary.Row> </ResponsiveTable.Summary.Row>
)} )}
/> />
</div> </div>

View File

@@ -1,5 +1,6 @@
import { BranchesOutlined, ExclamationCircleFilled, PauseCircleOutlined } from "@ant-design/icons"; import { BranchesOutlined, ExclamationCircleFilled, PauseCircleOutlined } from "@ant-design/icons";
import { Card, Space, Switch, Table, Tooltip, Typography } from "antd"; import { Card, Space, Switch, Tooltip, Typography } from "antd";
import ResponsiveTable from "../../responsive-table/responsive-table.component";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
@@ -359,10 +360,11 @@ export default function DashboardScheduledDeliveryToday({ data, ...cardProps })
{...cardProps} {...cardProps}
> >
<div style={{ height: "100%" }}> <div style={{ height: "100%" }}>
<Table <ResponsiveTable
onChange={handleTableChange} onChange={handleTableChange}
pagination={false} pagination={false}
columns={isTvModeScheduledDelivery ? tvColumns : columns} columns={isTvModeScheduledDelivery ? tvColumns : columns}
mobileColumnKeys={["ro_number", "owner", "status", "vehicle"]}
scroll={{ x: true, y: "calc(100% - 2em)" }} scroll={{ x: true, y: "calc(100% - 2em)" }}
rowKey="id" rowKey="id"
style={{ height: "85%" }} style={{ height: "85%" }}

View File

@@ -1,5 +1,6 @@
import { BranchesOutlined, ExclamationCircleFilled, PauseCircleOutlined } from "@ant-design/icons"; import { BranchesOutlined, ExclamationCircleFilled, PauseCircleOutlined } from "@ant-design/icons";
import { Card, Space, Switch, Table, Tooltip, Typography } from "antd"; import { Card, Space, Switch, Tooltip, Typography } from "antd";
import ResponsiveTable from "../../responsive-table/responsive-table.component";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
@@ -364,10 +365,11 @@ export default function DashboardScheduledInToday({ data, ...cardProps }) {
{...cardProps} {...cardProps}
> >
<div style={{ height: "100%" }}> <div style={{ height: "100%" }}>
<Table <ResponsiveTable
onChange={handleTableChange} onChange={handleTableChange}
pagination={false} pagination={false}
columns={isTvModeScheduledIn ? tvColumns : columns} columns={isTvModeScheduledIn ? tvColumns : columns}
mobileColumnKeys={["ro_number", "owner", "vehicle", "start"]}
scroll={{ x: true, y: "calc(100% - 2em)" }} scroll={{ x: true, y: "calc(100% - 2em)" }}
rowKey="id" rowKey="id"
style={{ height: "85%" }} style={{ height: "85%" }}

View File

@@ -1,5 +1,6 @@
import { BranchesOutlined, ExclamationCircleFilled, PauseCircleOutlined } from "@ant-design/icons"; import { BranchesOutlined, ExclamationCircleFilled, PauseCircleOutlined } from "@ant-design/icons";
import { Card, Space, Switch, Table, Tooltip, Typography } from "antd"; import { Card, Space, Switch, Tooltip, Typography } from "antd";
import ResponsiveTable from "../../responsive-table/responsive-table.component";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
@@ -359,10 +360,11 @@ export default function DashboardScheduledOutToday({ data, ...cardProps }) {
{...cardProps} {...cardProps}
> >
<div style={{ height: "100%" }}> <div style={{ height: "100%" }}>
<Table <ResponsiveTable
onChange={handleTableChange} onChange={handleTableChange}
pagination={false} pagination={false}
columns={isTvModeScheduledOut ? tvColumns : columns} columns={isTvModeScheduledOut ? tvColumns : columns}
mobileColumnKeys={["ro_number", "owner", "status", "vehicle"]}
scroll={{ x: true, y: "calc(100% - 2em)" }} scroll={{ x: true, y: "calc(100% - 2em)" }}
rowKey="id" rowKey="id"
style={{ height: "85%" }} style={{ height: "85%" }}

View File

@@ -1,5 +1,6 @@
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { Button, Card, Form, Input, Table } from "antd"; import { Button, Card, Form, Input } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
@@ -78,7 +79,7 @@ export function DmsAllocationsSummaryAp({ socket, bodyshop, billids, title }) {
dataIndex: "Lines", dataIndex: "Lines",
key: "Lines", key: "Lines",
render: (text, record) => ( render: (text, record) => (
<table style={{ tableLayout: "auto", width: "100%" }}> <ResponsiveTable style={{ tableLayout: "auto", width: "100%" }}>
<tr> <tr>
<th>{t("bills.fields.invoice_number")}</th> <th>{t("bills.fields.invoice_number")}</th>
<th>{t("bodyshop.fields.dms.dms_acctnumber")}</th> <th>{t("bodyshop.fields.dms.dms_acctnumber")}</th>
@@ -91,7 +92,7 @@ export function DmsAllocationsSummaryAp({ socket, bodyshop, billids, title }) {
<td>{l.Amount}</td> <td>{l.Amount}</td>
</tr> </tr>
))} ))}
</table> </ResponsiveTable>
) )
} }
]; ];
@@ -115,9 +116,10 @@ export function DmsAllocationsSummaryAp({ socket, bodyshop, billids, title }) {
/> />
} }
> >
<Table <ResponsiveTable
pagination={{ placement: "top", defaultPageSize: pageLimit }} pagination={{ placement: "top", defaultPageSize: pageLimit }}
columns={columns} columns={columns}
mobileColumnKeys={["status", "reference", "Lines"]}
rowKey={(record) => `${record.InvoiceNumber}${record.Account}`} rowKey={(record) => `${record.InvoiceNumber}${record.Account}`}
dataSource={allocationsSummary} dataSource={allocationsSummary}
locale={{ emptyText: t("dms.labels.refreshallocations") }} locale={{ emptyText: t("dms.labels.refreshallocations") }}

View File

@@ -1,4 +1,5 @@
import { Alert, Button, Card, Table, Typography } from "antd"; import { Alert, Button, Card, Typography } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { useCallback, useEffect, useRef, useState } from "react"; import { useCallback, useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -116,9 +117,10 @@ export function DmsAllocationsSummary({ mode, socket, bodyshop, jobId, title, on
<Alert type="warning" title={t("jobs.labels.dms.disablebillwip")} /> <Alert type="warning" title={t("jobs.labels.dms.disablebillwip")} />
)} )}
<Table <ResponsiveTable
pagination={{ placement: "top", defaultPageSize: pageLimit }} pagination={{ placement: "top", defaultPageSize: pageLimit }}
columns={columns} columns={columns}
mobileColumnKeys={["center", "sale", "cost", "sale_dms_acctnumber"]}
rowKey="center" rowKey="center"
dataSource={allocationsSummary} dataSource={allocationsSummary}
locale={{ emptyText: t("dms.labels.refreshallocations") }} locale={{ emptyText: t("dms.labels.refreshallocations") }}
@@ -135,15 +137,17 @@ export function DmsAllocationsSummary({ mode, socket, bodyshop, jobId, title, on
const hasNonZeroSaleTotal = totals.totalSale.getAmount() !== 0; const hasNonZeroSaleTotal = totals.totalSale.getAmount() !== 0;
return ( return (
<Table.Summary.Row> <ResponsiveTable.Summary.Row>
<Table.Summary.Cell> <ResponsiveTable.Summary.Cell>
<Typography.Title level={4}>{t("general.labels.totals")}</Typography.Title> <Typography.Title level={4}>{t("general.labels.totals")}</Typography.Title>
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell>{hasNonZeroSaleTotal ? totals.totalSale.toFormat() : null}</Table.Summary.Cell> <ResponsiveTable.Summary.Cell>
<Table.Summary.Cell /> {hasNonZeroSaleTotal ? totals.totalSale.toFormat() : null}
<Table.Summary.Cell /> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell /> <ResponsiveTable.Summary.Cell />
</Table.Summary.Row> <ResponsiveTable.Summary.Cell />
<ResponsiveTable.Summary.Cell />
</ResponsiveTable.Summary.Row>
); );
}} }}
/> />

View File

@@ -1,4 +1,5 @@
import { Alert, Button, Card, Table, Tabs, Typography } from "antd"; import { Alert, Button, Card, Tabs, Typography } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -261,9 +262,10 @@ export function RrAllocationsSummary({ socket, bodyshop, jobId, title, onAllocat
into taxable / non-taxable segments. into taxable / non-taxable segments.
</Typography.Paragraph> </Typography.Paragraph>
<Table <ResponsiveTable
pagination={false} pagination={false}
columns={roggColumns} columns={roggColumns}
mobileColumnKeys={["jobNo", "opCode", "breakOut", "itemType"]}
rowKey="key" rowKey="key"
dataSource={roggRows} dataSource={roggRows}
locale={{ emptyText: "No ROGOG lines would be generated." }} locale={{ emptyText: "No ROGOG lines would be generated." }}
@@ -286,19 +288,23 @@ export function RrAllocationsSummary({ socket, bodyshop, jobId, title, onAllocat
const hasCostTotal = Number(roggTotals.totalDlrCost) !== 0; const hasCostTotal = Number(roggTotals.totalDlrCost) !== 0;
return ( return (
<Table.Summary.Row> <ResponsiveTable.Summary.Row>
<Table.Summary.Cell index={0}> <ResponsiveTable.Summary.Cell index={0}>
<Typography.Title level={5}>{t("general.labels.totals")}</Typography.Title> <Typography.Title level={5}>{t("general.labels.totals")}</Typography.Title>
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell index={1} /> <ResponsiveTable.Summary.Cell index={1} />
<Table.Summary.Cell index={2} /> <ResponsiveTable.Summary.Cell index={2} />
<Table.Summary.Cell index={3} /> <ResponsiveTable.Summary.Cell index={3} />
<Table.Summary.Cell index={4} /> <ResponsiveTable.Summary.Cell index={4} />
<Table.Summary.Cell index={5} /> <ResponsiveTable.Summary.Cell index={5} />
<Table.Summary.Cell index={6} /> <ResponsiveTable.Summary.Cell index={6} />
<Table.Summary.Cell index={7}>{hasCustTotal ? roggTotals.totalCustPrice : null}</Table.Summary.Cell> <ResponsiveTable.Summary.Cell index={7}>
<Table.Summary.Cell index={8}>{hasCostTotal ? roggTotals.totalDlrCost : null}</Table.Summary.Cell> {hasCustTotal ? roggTotals.totalCustPrice : null}
</Table.Summary.Row> </ResponsiveTable.Summary.Cell>
<ResponsiveTable.Summary.Cell index={8}>
{hasCostTotal ? roggTotals.totalDlrCost : null}
</ResponsiveTable.Summary.Cell>
</ResponsiveTable.Summary.Row>
); );
}} }}
/> />
@@ -313,9 +319,10 @@ export function RrAllocationsSummary({ socket, bodyshop, jobId, title, onAllocat
<Typography.Paragraph type="secondary" style={{ marginBottom: 8 }}> <Typography.Paragraph type="secondary" style={{ marginBottom: 8 }}>
This mirrors the shell that would be sent for ROLABOR when all financials are carried in GOG. This mirrors the shell that would be sent for ROLABOR when all financials are carried in GOG.
</Typography.Paragraph> </Typography.Paragraph>
<Table <ResponsiveTable
pagination={false} pagination={false}
columns={rolaborColumns} columns={rolaborColumns}
mobileColumnKeys={["jobNo", "opCode", "breakOut", "itemType"]}
rowKey="key" rowKey="key"
dataSource={rolaborRows} dataSource={rolaborRows}
locale={{ emptyText: "No ROLABOR lines would be generated." }} locale={{ emptyText: "No ROLABOR lines would be generated." }}

View File

@@ -1,5 +1,6 @@
import { useLazyQuery } from "@apollo/client/react"; import { useLazyQuery } from "@apollo/client/react";
import { Button, Input, Modal, Table } from "antd"; import { Button, Input, Modal } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
@@ -60,7 +61,7 @@ export function DmsCdkVehicles({ form, job }) {
okButtonProps={{ disabled: !selectedModel }} okButtonProps={{ disabled: !selectedModel }}
> >
{error && <AlertComponent title={error.message} type="error" />} {error && <AlertComponent title={error.message} type="error" />}
<Table <ResponsiveTable
title={() => ( title={() => (
<Input.Search <Input.Search
onSearch={(val) => callSearch({ variables: { search: val } })} onSearch={(val) => callSearch({ variables: { search: val } })}
@@ -69,6 +70,7 @@ export function DmsCdkVehicles({ form, job }) {
/> />
)} )}
columns={columns} columns={columns}
mobileColumnKeys={["make", "model", "makecode", "modelcode"]}
loading={loading} loading={loading}
rowKey="id" rowKey="id"
dataSource={data ? data.search_dms_vehicles : []} dataSource={data ? data.search_dms_vehicles : []}

View File

@@ -1,4 +1,5 @@
import { Button, Checkbox, Col, Table } from "antd"; import { Button, Checkbox, Col } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { alphaSort } from "../../utils/sorters"; import { alphaSort } from "../../utils/sorters";
@@ -72,7 +73,7 @@ export default function CDKCustomerSelector({ bodyshop, socket }) {
return ( return (
<Col span={24}> <Col span={24}>
<Table <ResponsiveTable
title={() => ( title={() => (
<div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}> <div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
<Button onClick={onUseSelected} disabled={!selectedCustomer}> <Button onClick={onUseSelected} disabled={!selectedCustomer}>
@@ -86,6 +87,7 @@ export default function CDKCustomerSelector({ bodyshop, socket }) {
)} )}
pagination={{ placement: "top" }} pagination={{ placement: "top" }}
columns={columns} columns={columns}
mobileColumnKeys={["id", "vinOwner", "name1", "address"]}
rowKey={rowKey} rowKey={rowKey}
dataSource={customerList} dataSource={customerList}
rowSelection={{ rowSelection={{

View File

@@ -1,4 +1,5 @@
import { Button, Checkbox, Col, Table } from "antd"; import { Button, Checkbox, Col } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { alphaSort } from "../../utils/sorters"; import { alphaSort } from "../../utils/sorters";
@@ -78,7 +79,7 @@ export default function FortellisCustomerSelector({ bodyshop, jobid, socket }) {
return ( return (
<Col span={24}> <Col span={24}>
<Table <ResponsiveTable
title={() => ( title={() => (
<div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}> <div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
<Button onClick={onUseSelected} disabled={!selectedCustomer}> <Button onClick={onUseSelected} disabled={!selectedCustomer}>
@@ -92,6 +93,7 @@ export default function FortellisCustomerSelector({ bodyshop, jobid, socket }) {
)} )}
pagination={{ placement: "top" }} pagination={{ placement: "top" }}
columns={columns} columns={columns}
mobileColumnKeys={["id", "vinOwner", "firstName", "address"]}
rowKey={(r) => r.customerId} rowKey={(r) => r.customerId}
dataSource={customerList} dataSource={customerList}
rowSelection={{ rowSelection={{

View File

@@ -1,4 +1,5 @@
import { Button, Col, Table } from "antd"; import { Button, Col } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { alphaSort } from "../../utils/sorters"; import { alphaSort } from "../../utils/sorters";
@@ -66,7 +67,7 @@ export default function PBSCustomerSelector({ bodyshop, socket }) {
return ( return (
<Col span={24}> <Col span={24}>
<Table <ResponsiveTable
title={() => ( title={() => (
<div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}> <div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
<Button onClick={onUseSelected} disabled={!selectedCustomer}> <Button onClick={onUseSelected} disabled={!selectedCustomer}>
@@ -80,6 +81,7 @@ export default function PBSCustomerSelector({ bodyshop, socket }) {
)} )}
pagination={{ placement: "top" }} pagination={{ placement: "top" }}
columns={columns} columns={columns}
mobileColumnKeys={["ContactId", "name1", "address"]}
rowKey={(r) => r.ContactId} rowKey={(r) => r.ContactId}
dataSource={customerList} dataSource={customerList}
rowSelection={{ rowSelection={{

View File

@@ -1,4 +1,5 @@
import { Alert, Button, Checkbox, message, Modal, Space, Table } from "antd"; import { Alert, Button, Checkbox, message, Modal, Space } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useEffect, useMemo, useState } from "react"; import { useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { alphaSort } from "../../utils/sorters"; import { alphaSort } from "../../utils/sorters";
@@ -72,14 +73,14 @@ export default function RRCustomerSelector({
if (!socket) return; if (!socket) return;
const handleRrSelectCustomer = (list) => { const handleRrSelectCustomer = (list) => {
const normalized = normalizeRrList(list); const normalized = normalizeRrList(list);
// If list is empty, it means early RO exists and customer selection should be skipped // If list is empty, it means early RO exists and customer selection should be skipped
// Don't open the modal in this case // Don't open the modal in this case
if (normalized.length === 0) { if (normalized.length === 0) {
setRefreshing(false); setRefreshing(false);
return; return;
} }
setOpen(true); setOpen(true);
setCustomerList(normalized); setCustomerList(normalized);
const firstOwner = normalized.find((r) => r.vinOwner)?.custNo; const firstOwner = normalized.find((r) => r.vinOwner)?.custNo;
@@ -195,8 +196,8 @@ export default function RRCustomerSelector({
description={ description={
<div style={{ display: "flex", flexDirection: "column", gap: 8 }}> <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
<div> <div>
We created the Repair Order. Please validate the totals and taxes in the DMS system. When done, We created the Repair Order. Please validate the totals and taxes in the DMS system. When done, click{" "}
click <strong>Finished</strong> to finalize and mark this export as complete. <strong>Finished</strong> to finalize and mark this export as complete.
</div> </div>
<div> <div>
<Space> <Space>
@@ -215,14 +216,8 @@ export default function RRCustomerSelector({
} }
return ( return (
<Modal <Modal open={open} onCancel={handleClose} footer={null} width={800} title={t("dms.selectCustomer")}>
open={open} <ResponsiveTable
onCancel={handleClose}
footer={null}
width={800}
title={t("dms.selectCustomer")}
>
<Table
title={() => ( title={() => (
<div style={{ display: "flex", flexDirection: "column", gap: 8 }}> <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
{/* Open RO limit banner */} {/* Open RO limit banner */}
@@ -304,6 +299,7 @@ export default function RRCustomerSelector({
)} )}
pagination={{ placement: "top" }} pagination={{ placement: "top" }}
columns={columns} columns={columns}
mobileColumnKeys={["custNo", "vinOwner", "name", "address"]}
rowKey={(r) => r.custNo} rowKey={(r) => r.custNo}
dataSource={customerList} dataSource={customerList}
rowSelection={{ rowSelection={{

View File

@@ -1,5 +1,6 @@
import { ReloadOutlined } from "@ant-design/icons"; import { ReloadOutlined } from "@ant-design/icons";
import { Alert, Button, Form, Input, InputNumber, Modal, Radio, Select, Space, Table, Typography } from "antd"; import { Alert, Button, Form, Input, InputNumber, Modal, Radio, Select, Space, Typography } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useEffect, useMemo, useState } from "react"; import { useEffect, useMemo, useState } from "react";
// Simple customer selector table // Simple customer selector table
@@ -26,7 +27,14 @@ function CustomerSelectorTable({ customers, onSelect, isSubmitting }) {
return ( return (
<div> <div>
<Table columns={columns} dataSource={customers} rowKey="custNo" pagination={false} size="small" /> <ResponsiveTable
columns={columns}
mobileColumnKeys={["name", "select", "custNo", "vinOwner"]}
dataSource={customers}
rowKey="custNo"
pagination={false}
size="small"
/>
<div style={{ marginTop: 16, display: "flex", gap: 8 }}> <div style={{ marginTop: 16, display: "flex", gap: 8 }}>
<Button <Button
type="primary" type="primary"

View File

@@ -1,5 +1,5 @@
import { EditFilled, FileAddFilled, SyncOutlined } from "@ant-design/icons"; import { EditFilled, FileAddFilled, SyncOutlined } from "@ant-design/icons";
import { Button, Card, Input, Space, Table, Typography } from "antd"; import { Button, Card, Input, Space, Typography } from "antd";
import queryString from "query-string"; import queryString from "query-string";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
@@ -10,6 +10,7 @@ import CurrencyFormatter from "../../utils/CurrencyFormatter";
import InventoryBillRo from "../inventory-bill-ro/inventory-bill-ro.component"; import InventoryBillRo from "../inventory-bill-ro/inventory-bill-ro.component";
import InventoryLineDelete from "../inventory-line-delete/inventory-line-delete.component"; import InventoryLineDelete from "../inventory-line-delete/inventory-line-delete.component";
import { pageLimit } from "../../utils/config"; import { pageLimit } from "../../utils/config";
import ResponsiveTable from "../responsive-table/responsive-table.component";
const mapStateToProps = createStructuredSelector({}); const mapStateToProps = createStructuredSelector({});
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
@@ -185,10 +186,11 @@ export function JobsList({ refetch, loading, jobs, total, setInventoryUpsertCont
</Space> </Space>
} }
> >
<Table <ResponsiveTable
loading={loading} loading={loading}
pagination={{ placement: "top", pageSize: pageLimit, current: parseInt(page || 1), total: total }} pagination={{ placement: "top", pageSize: pageLimit, current: parseInt(page || 1), total: total }}
columns={columns} columns={columns}
mobileColumnKeys={["line_desc", "actual_price", "consumedbyjob", "actions"]}
rowKey="id" rowKey="id"
dataSource={jobs} dataSource={jobs}
onChange={handleTableChange} onChange={handleTableChange}

View File

@@ -1,6 +1,7 @@
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { useQuery } from "@apollo/client/react"; import { useQuery } from "@apollo/client/react";
import { Button, Card, Col, Row, Table, Tag } from "antd"; import { Button, Card, Col, Row, Tag } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
@@ -163,12 +164,24 @@ export function JobAuditTrail({ bodyshop, jobId }) {
/> />
} }
> >
<Table loading={loading} columns={columns} rowKey="id" dataSource={data ? data.audit_trail : []} /> <ResponsiveTable
loading={loading}
columns={columns}
mobileColumnKeys={["status", "created", "useremail", "operation"]}
rowKey="id"
dataSource={data ? data.audit_trail : []}
/>
</Card> </Card>
</Col> </Col>
<Col span={24}> <Col span={24}>
<Card title={t("jobs.labels.emailaudit")}> <Card title={t("jobs.labels.emailaudit")}>
<Table loading={loading} columns={emailColumns} rowKey="id" dataSource={data ? data.email_audit_trail : []} /> <ResponsiveTable
loading={loading}
columns={emailColumns}
mobileColumnKeys={["status", "created", "useremail", "operation"]}
rowKey="id"
dataSource={data ? data.email_audit_trail : []}
/>
</Card> </Card>
</Col> </Col>
</Row> </Row>

View File

@@ -1,5 +1,6 @@
import { useEffect } from "react"; import { useEffect } from "react";
import { Alert, Card, Table } from "antd"; import { Alert, Card } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { t } from "i18next"; import { t } from "i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
@@ -68,7 +69,15 @@ export function JobCloseRGuardPpd({ job, warningCallback }) {
return ( return (
<Card title={t("jobs.labels.ppdnotexported")}> <Card title={t("jobs.labels.ppdnotexported")}>
<Table dataSource={linesWithPPD} columns={columns} pagination={false} rowKey="id" bordered size="small" /> <ResponsiveTable
dataSource={linesWithPPD}
columns={columns}
mobileColumnKeys={["line_desc", "ppd", "act_price", "act_price_before_ppc"]}
pagination={false}
rowKey="id"
bordered
size="small"
/>
{linesWithPPD.length > 0 && ( {linesWithPPD.length > 0 && (
<Alert style={{ margin: "8px 0px" }} type="warning" title={t("jobs.labels.outstanding_ppd")} /> <Alert style={{ margin: "8px 0px" }} type="warning" title={t("jobs.labels.outstanding_ppd")} />
)} )}

View File

@@ -1,6 +1,7 @@
import { useEffect } from "react"; import { useEffect } from "react";
import { Alert, Card, Table } from "antd"; import { Alert, Card } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { t } from "i18next"; import { t } from "i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
@@ -62,7 +63,15 @@ export function JobCloseRGuardSublet({ job, warningCallback }) {
return ( return (
<Card title={t("jobs.labels.subletsnotcompleted")}> <Card title={t("jobs.labels.subletsnotcompleted")}>
<Table dataSource={subletsNotDone} columns={columns} pagination={false} rowKey="id" bordered size="small" /> <ResponsiveTable
dataSource={subletsNotDone}
columns={columns}
mobileColumnKeys={["line_desc", "act_price", "part_qty", "notes"]}
pagination={false}
rowKey="id"
bordered
size="small"
/>
{subletsNotDone.length > 0 && ( {subletsNotDone.length > 0 && (
<Alert style={{ margin: "8px 0px" }} type="warning" title={t("jobs.labels.outstanding_sublets")} /> <Alert style={{ margin: "8px 0px" }} type="warning" title={t("jobs.labels.outstanding_sublets")} />
)} )}

View File

@@ -1,4 +1,5 @@
import { Input, Space, Table, Typography } from "antd"; import { Input, Space, Typography } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { alphaSort } from "../../utils/sorters"; import { alphaSort } from "../../utils/sorters";
@@ -65,7 +66,7 @@ export default function JobCostingPartsTable({ data, summaryData }) {
return ( return (
<div> <div>
<Table <ResponsiveTable
title={() => { title={() => {
return ( return (
<Space wrap> <Space wrap>
@@ -87,18 +88,19 @@ export default function JobCostingPartsTable({ data, summaryData }) {
onChange={handleTableChange} onChange={handleTableChange}
pagination={{ placement: "top", defaultPageSize: pageLimit }} pagination={{ placement: "top", defaultPageSize: pageLimit }}
columns={columns} columns={columns}
mobileColumnKeys={["cost_center", "sales", "costs", "gpdollars", "gppercent"]}
rowKey="id" rowKey="id"
dataSource={filteredData} dataSource={filteredData}
summary={() => ( summary={() => (
<Table.Summary.Row> <ResponsiveTable.Summary.Row>
<Table.Summary.Cell> <ResponsiveTable.Summary.Cell>
<Typography.Title level={4}>{t("general.labels.totals")}</Typography.Title> <Typography.Title level={4}>{t("general.labels.totals")}</Typography.Title>
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell>{Dinero(summaryData.totalSales).toFormat()}</Table.Summary.Cell> <ResponsiveTable.Summary.Cell>{Dinero(summaryData.totalSales).toFormat()}</ResponsiveTable.Summary.Cell>
<Table.Summary.Cell>{Dinero(summaryData.totalCost).toFormat()}</Table.Summary.Cell> <ResponsiveTable.Summary.Cell>{Dinero(summaryData.totalCost).toFormat()}</ResponsiveTable.Summary.Cell>
<Table.Summary.Cell>{Dinero(summaryData.gpdollars).toFormat()}</Table.Summary.Cell> <ResponsiveTable.Summary.Cell>{Dinero(summaryData.gpdollars).toFormat()}</ResponsiveTable.Summary.Cell>
<Table.Summary.Cell></Table.Summary.Cell> <ResponsiveTable.Summary.Cell></ResponsiveTable.Summary.Cell>
</Table.Summary.Row> </ResponsiveTable.Summary.Row>
)} )}
/> />
</div> </div>

View File

@@ -1,4 +1,4 @@
import { Table } from "antd"; import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import JobLineNotePopup from "../job-line-note-popup/job-line-note-popup.component"; import JobLineNotePopup from "../job-line-note-popup/job-line-note-popup.component";
import PartsStatusPie from "../parts-status-pie/parts-status-pie.component"; import PartsStatusPie from "../parts-status-pie/parts-status-pie.component";
@@ -101,7 +101,12 @@ function JobDetailCardsPartsComponent({ loading, data, jobRO }) {
<div> <div>
<CardTemplate loading={loading} title={t("jobs.labels.cards.parts")}> <CardTemplate loading={loading} title={t("jobs.labels.cards.parts")}>
<PartsStatusPie joblines_status={joblines_status} /> <PartsStatusPie joblines_status={joblines_status} />
<Table rowKey="id" columns={columns} dataSource={filteredJobLines || []} /> <ResponsiveTable
rowKey="id"
columns={columns}
mobileColumnKeys={["status", "line_desc", "part_type", "part_qty"]}
dataSource={filteredJobLines || []}
/>
</CardTemplate> </CardTemplate>
</div> </div>
); );

View File

@@ -11,7 +11,8 @@ import {
import { PageHeader } from "@ant-design/pro-layout"; import { PageHeader } from "@ant-design/pro-layout";
import { useMutation } from "@apollo/client/react"; import { useMutation } from "@apollo/client/react";
import { gql } from "@apollo/client"; import { gql } from "@apollo/client";
import { Button, Dropdown, Input, Modal, Select, Space, Table, Tag, Typography } from "antd"; import { Button, Dropdown, Input, Modal, Select, Space, Tag, Typography } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import axios from "axios"; import axios from "axios";
import { useMemo, useState } from "react"; import { useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -688,8 +689,9 @@ export function JobLinesComponent({
} }
/> />
<Table <ResponsiveTable
columns={columns} columns={columns}
mobileColumnKeys={["status", "line_desc", "actions", "line_no"]}
rowKey="id" rowKey="id"
loading={loading} loading={loading}
pagination={false} pagination={false}

View File

@@ -1,6 +1,7 @@
import { useQuery } from "@apollo/client/react"; import { useQuery } from "@apollo/client/react";
import { gql } from "@apollo/client"; import { gql } from "@apollo/client";
import { Badge, Card, Space, Table, Tag } from "antd"; import { Badge, Card, Space, Tag } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import axios from "axios"; import axios from "axios";
import { isEmpty } from "lodash"; import { isEmpty } from "lodash";
import { useCallback, useEffect, useState } from "react"; import { useCallback, useEffect, useState } from "react";
@@ -311,12 +312,13 @@ export function JobLifecycleComponent({ bodyshop, job, statuses }) {
</> </>
} }
> >
<Table <ResponsiveTable
style={{ style={{
overflow: "auto", overflow: "auto",
width: "100%" width: "100%"
}} }}
columns={columns} columns={columns}
mobileColumnKeys={["value", "start", "start_readable", "end"]}
dataSource={lifecycleData.lifecycle} dataSource={lifecycleData.lifecycle}
rowKey="start" rowKey="start"
/> />

View File

@@ -1,5 +1,6 @@
import { EditFilled } from "@ant-design/icons"; import { EditFilled } from "@ant-design/icons";
import { Button, Card, Space, Table } from "antd"; import { Button, Card, Space } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import Dinero from "dinero.js"; import Dinero from "dinero.js";
import { useMemo, useState } from "react"; import { useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -186,8 +187,9 @@ export function JobPayments({ job, bodyshop, setPaymentContext, setCardPaymentCo
</Space> </Space>
} }
> >
<Table <ResponsiveTable
columns={columns} columns={columns}
mobileColumnKeys={["date", "amount", "actions", "payer"]}
rowKey="id" rowKey="id"
pagination={false} pagination={false}
onChange={handleTableChange} onChange={handleTableChange}
@@ -199,18 +201,18 @@ export function JobPayments({ job, bodyshop, setPaymentContext, setCardPaymentCo
expandedRowRender: (record) => <PaymentExpandedRowComponent record={record} bodyshop={bodyshop} /> expandedRowRender: (record) => <PaymentExpandedRowComponent record={record} bodyshop={bodyshop} />
}} }}
summary={() => ( summary={() => (
<Table.Summary.Row> <ResponsiveTable.Summary.Row>
<Table.Summary.Cell> <ResponsiveTable.Summary.Cell>
<strong>{t("payments.labels.totalpayments")}</strong> <strong>{t("payments.labels.totalpayments")}</strong>
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell /> <ResponsiveTable.Summary.Cell />
<Table.Summary.Cell> <ResponsiveTable.Summary.Cell>
<strong>{total.toFormat()}</strong> <strong>{total.toFormat()}</strong>
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell /> <ResponsiveTable.Summary.Cell />
<Table.Summary.Cell /> <ResponsiveTable.Summary.Cell />
<Table.Summary.Cell /> <ResponsiveTable.Summary.Cell />
</Table.Summary.Row> </ResponsiveTable.Summary.Row>
)} )}
/> />
</Card> </Card>

View File

@@ -1,4 +1,5 @@
import { Checkbox, Table, Typography } from "antd"; import { Checkbox, Typography } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import CurrencyFormatter from "../../utils/CurrencyFormatter"; import CurrencyFormatter from "../../utils/CurrencyFormatter";
@@ -79,11 +80,12 @@ export default function JobReconciliationBillsTable({ billLineState, invoiceLine
return ( return (
<div> <div>
<Typography.Title level={4}>{t("bills.labels.bills")}</Typography.Title> <Typography.Title level={4}>{t("bills.labels.bills")}</Typography.Title>
<Table <ResponsiveTable
pagination={false} pagination={false}
size="small" size="small"
scroll={{ y: "60vh" }} scroll={{ y: "60vh" }}
columns={columns} columns={columns}
mobileColumnKeys={["line_desc", "from", "actual_price", "actual_cost"]}
rowKey="id" rowKey="id"
dataSource={invoiceLineData} dataSource={invoiceLineData}
onChange={handleTableChange} onChange={handleTableChange}

View File

@@ -1,4 +1,5 @@
import { Table, Typography } from "antd"; import { Typography } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import CurrencyFormatter from "../../utils/CurrencyFormatter"; import CurrencyFormatter from "../../utils/CurrencyFormatter";
@@ -96,9 +97,10 @@ export default function JobReconcilitionPartsTable({ jobLineState, jobLineData }
return ( return (
<div> <div>
<Typography.Title level={4}>{t("jobs.labels.lines")}</Typography.Title> <Typography.Title level={4}>{t("jobs.labels.lines")}</Typography.Title>
<Table <ResponsiveTable
pagination={false} pagination={false}
columns={columns} columns={columns}
mobileColumnKeys={["status", "line_desc", "total", "oem_partno"]}
size="small" size="small"
scroll={{ y: "60vh" }} scroll={{ y: "60vh" }}
rowKey="id" rowKey="id"

View File

@@ -1,4 +1,5 @@
import { Space, Table } from "antd"; import { Space } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import Dinero from "dinero.js"; import Dinero from "dinero.js";
import { useMemo, useState } from "react"; import { useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -104,8 +105,9 @@ export default function JobTotalsTableLabor({ job }) {
setState({ ...state, filteredInfo: filters, sortedInfo: sorter }); setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
}; };
return ( return (
<Table <ResponsiveTable
columns={columns} columns={columns}
mobileColumnKeys={["total", "profitcenter_labor", "rate", "mod_lb_hrs"]}
rowKey="id" rowKey="id"
pagination={false} pagination={false}
onChange={handleTableChange} onChange={handleTableChange}
@@ -115,29 +117,29 @@ export default function JobTotalsTableLabor({ job }) {
}} }}
summary={() => ( summary={() => (
<> <>
<Table.Summary.Row> <ResponsiveTable.Summary.Row>
<Table.Summary.Cell> <ResponsiveTable.Summary.Cell>
<strong>{t("jobs.labels.labor_rates_subtotal")}</strong> <strong>{t("jobs.labels.labor_rates_subtotal")}</strong>
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell /> <ResponsiveTable.Summary.Cell />
<Table.Summary.Cell> <ResponsiveTable.Summary.Cell>
{(job.job_totals.rates.mapa.hours + job.job_totals.rates.mash.hours).toFixed(1)} {(job.job_totals.rates.mapa.hours + job.job_totals.rates.mash.hours).toFixed(1)}
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
{InstanceRenderManager({ {InstanceRenderManager({
imex: null, imex: null,
rome: ( rome: (
<> <>
<Table.Summary.Cell /> <ResponsiveTable.Summary.Cell />
<Table.Summary.Cell /> <ResponsiveTable.Summary.Cell />
</> </>
) )
})} })}
<Table.Summary.Cell align="right"> <ResponsiveTable.Summary.Cell align="right">
<strong>{Dinero(job.job_totals.rates.rates_subtotal).toFormat()}</strong> <strong>{Dinero(job.job_totals.rates.rates_subtotal).toFormat()}</strong>
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
</Table.Summary.Row> </ResponsiveTable.Summary.Row>
<Table.Summary.Row> <ResponsiveTable.Summary.Row>
<Table.Summary.Cell> <ResponsiveTable.Summary.Cell>
<Space> <Space>
{t("jobs.labels.mapa")} {t("jobs.labels.mapa")}
{InstanceRenderManager({ {InstanceRenderManager({
@@ -156,34 +158,34 @@ export default function JobTotalsTableLabor({ job }) {
}) })
})} })}
</Space> </Space>
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell align="right"> <ResponsiveTable.Summary.Cell align="right">
<CurrencyFormatter>{job.job_totals.rates.mapa.rate}</CurrencyFormatter> <CurrencyFormatter>{job.job_totals.rates.mapa.rate}</CurrencyFormatter>
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell>{job.job_totals.rates.mapa.hours.toFixed(1)}</Table.Summary.Cell> <ResponsiveTable.Summary.Cell>{job.job_totals.rates.mapa.hours.toFixed(1)}</ResponsiveTable.Summary.Cell>
{InstanceRenderManager({ {InstanceRenderManager({
imex: ( imex: (
<Table.Summary.Cell align="right"> <ResponsiveTable.Summary.Cell align="right">
{Dinero(job.job_totals.rates.mapa.total).toFormat()} {Dinero(job.job_totals.rates.mapa.total).toFormat()}
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
), ),
rome: ( rome: (
<> <>
<Table.Summary.Cell align="right"> <ResponsiveTable.Summary.Cell align="right">
{Dinero(job.job_totals.rates.mapa.base).toFormat()} {Dinero(job.job_totals.rates.mapa.base).toFormat()}
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell align="right"> <ResponsiveTable.Summary.Cell align="right">
{Dinero(job.job_totals.rates.mapa.adjustment).toFormat()} {Dinero(job.job_totals.rates.mapa.adjustment).toFormat()}
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell align="right"> <ResponsiveTable.Summary.Cell align="right">
{Dinero(job.job_totals.rates.mapa.total).toFormat()} {Dinero(job.job_totals.rates.mapa.total).toFormat()}
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
</> </>
) )
})} })}
</Table.Summary.Row> </ResponsiveTable.Summary.Row>
<Table.Summary.Row> <ResponsiveTable.Summary.Row>
<Table.Summary.Cell> <ResponsiveTable.Summary.Cell>
<Space wrap> <Space wrap>
{t("jobs.labels.mash")} {t("jobs.labels.mash")}
{InstanceRenderManager({ {InstanceRenderManager({
@@ -202,51 +204,51 @@ export default function JobTotalsTableLabor({ job }) {
}) })
})} })}
</Space> </Space>
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell align="right"> <ResponsiveTable.Summary.Cell align="right">
<CurrencyFormatter>{job.job_totals.rates.mash.rate}</CurrencyFormatter> <CurrencyFormatter>{job.job_totals.rates.mash.rate}</CurrencyFormatter>
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell>{job.job_totals.rates.mash.hours.toFixed(1)}</Table.Summary.Cell> <ResponsiveTable.Summary.Cell>{job.job_totals.rates.mash.hours.toFixed(1)}</ResponsiveTable.Summary.Cell>
{InstanceRenderManager({ {InstanceRenderManager({
imex: ( imex: (
<Table.Summary.Cell align="right"> <ResponsiveTable.Summary.Cell align="right">
{Dinero(job.job_totals.rates.mash.total).toFormat()} {Dinero(job.job_totals.rates.mash.total).toFormat()}
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
), ),
rome: ( rome: (
<> <>
<Table.Summary.Cell align="right"> <ResponsiveTable.Summary.Cell align="right">
{Dinero(job.job_totals.rates.mash.base).toFormat()} {Dinero(job.job_totals.rates.mash.base).toFormat()}
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell align="right"> <ResponsiveTable.Summary.Cell align="right">
{Dinero(job.job_totals.rates.mash.adjustment).toFormat()} {Dinero(job.job_totals.rates.mash.adjustment).toFormat()}
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell align="right"> <ResponsiveTable.Summary.Cell align="right">
{Dinero(job.job_totals.rates.mash.total).toFormat()} {Dinero(job.job_totals.rates.mash.total).toFormat()}
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
</> </>
) )
})} })}
</Table.Summary.Row> </ResponsiveTable.Summary.Row>
<Table.Summary.Row> <ResponsiveTable.Summary.Row>
<Table.Summary.Cell> <ResponsiveTable.Summary.Cell>
<strong>{t("jobs.labels.rates_subtotal")}</strong> <strong>{t("jobs.labels.rates_subtotal")}</strong>
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell /> <ResponsiveTable.Summary.Cell />
<Table.Summary.Cell /> <ResponsiveTable.Summary.Cell />
{InstanceRenderManager({ {InstanceRenderManager({
imex: null, imex: null,
rome: ( rome: (
<> <>
<Table.Summary.Cell /> <ResponsiveTable.Summary.Cell />
<Table.Summary.Cell /> <ResponsiveTable.Summary.Cell />
</> </>
) )
})} })}
<Table.Summary.Cell align="right"> <ResponsiveTable.Summary.Cell align="right">
<strong>{Dinero(job.job_totals.rates.subtotal).toFormat()}</strong> <strong>{Dinero(job.job_totals.rates.subtotal).toFormat()}</strong>
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
</Table.Summary.Row> </ResponsiveTable.Summary.Row>
</> </>
)} )}
/> />

View File

@@ -1,4 +1,4 @@
import { Table } from "antd"; import ResponsiveTable from "../responsive-table/responsive-table.component";
import Dinero from "dinero.js"; import Dinero from "dinero.js";
import { useMemo, useState } from "react"; import { useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -65,8 +65,9 @@ export default function JobTotalsTableOther({ job }) {
setState({ ...state, filteredInfo: filters, sortedInfo: sorter }); setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
}; };
return ( return (
<Table <ResponsiveTable
columns={columns} columns={columns}
mobileColumnKeys={["total", "key"]}
rowKey="key" rowKey="key"
pagination={false} pagination={false}
onChange={handleTableChange} onChange={handleTableChange}
@@ -76,24 +77,24 @@ export default function JobTotalsTableOther({ job }) {
}} }}
summary={() => ( summary={() => (
<> <>
<Table.Summary.Row> <ResponsiveTable.Summary.Row>
<Table.Summary.Cell> <ResponsiveTable.Summary.Cell>
<strong>{t("jobs.labels.additionaltotal")}</strong> <strong>{t("jobs.labels.additionaltotal")}</strong>
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell align="right"> <ResponsiveTable.Summary.Cell align="right">
<strong>{Dinero(job.job_totals.additional.total).toFormat()}</strong> <strong>{Dinero(job.job_totals.additional.total).toFormat()}</strong>
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
</Table.Summary.Row> </ResponsiveTable.Summary.Row>
<Table.Summary.Row> <ResponsiveTable.Summary.Row>
<Table.Summary.Cell> <ResponsiveTable.Summary.Cell>
<strong>{t("jobs.labels.subletstotal")}</strong> <strong>{t("jobs.labels.subletstotal")}</strong>
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell align="right"> <ResponsiveTable.Summary.Cell align="right">
<strong>{Dinero(job.job_totals.parts.sublets.total).toFormat()}</strong> <strong>{Dinero(job.job_totals.parts.sublets.total).toFormat()}</strong>
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
</Table.Summary.Row> </ResponsiveTable.Summary.Row>
</> </>
)} )}
/> />

View File

@@ -1,4 +1,4 @@
import { Table } from "antd"; import ResponsiveTable from "../responsive-table/responsive-table.component";
import Dinero from "dinero.js"; import Dinero from "dinero.js";
import { useMemo, useState } from "react"; import { useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -64,8 +64,9 @@ export default function JobTotalsTableParts({ job }) {
setState({ ...state, filteredInfo: filters, sortedInfo: sorter }); setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
}; };
return ( return (
<Table <ResponsiveTable
columns={columns} columns={columns}
mobileColumnKeys={["total", "id"]}
rowKey="id" rowKey="id"
pagination={false} pagination={false}
onChange={handleTableChange} onChange={handleTableChange}
@@ -75,36 +76,38 @@ export default function JobTotalsTableParts({ job }) {
}} }}
summary={() => ( summary={() => (
<> <>
<Table.Summary.Row> <ResponsiveTable.Summary.Row>
<Table.Summary.Cell>{t("jobs.labels.prt_dsmk_total")}</Table.Summary.Cell> <ResponsiveTable.Summary.Cell>{t("jobs.labels.prt_dsmk_total")}</ResponsiveTable.Summary.Cell>
<Table.Summary.Cell align="right"> <ResponsiveTable.Summary.Cell align="right">
{Dinero(job.job_totals.parts.parts.prt_dsmk_total).toFormat()} {Dinero(job.job_totals.parts.parts.prt_dsmk_total).toFormat()}
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
</Table.Summary.Row> </ResponsiveTable.Summary.Row>
<Table.Summary.Row> <ResponsiveTable.Summary.Row>
<Table.Summary.Cell> <ResponsiveTable.Summary.Cell>
<strong>{t("jobs.labels.partstotal")}</strong> <strong>{t("jobs.labels.partstotal")}</strong>
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell align="right"> <ResponsiveTable.Summary.Cell align="right">
<strong>{Dinero(job.job_totals.parts.parts.total).toFormat()}</strong> <strong>{Dinero(job.job_totals.parts.parts.total).toFormat()}</strong>
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
</Table.Summary.Row> </ResponsiveTable.Summary.Row>
{ {
//TODO:AIO This shoudl only be in the US version. need to verify whether this causes problems for the CA version. //TODO:AIO This shoudl only be in the US version. need to verify whether this causes problems for the CA version.
insuranceAdjustments.length > 0 && ( insuranceAdjustments.length > 0 && (
<Table.Summary.Row> <ResponsiveTable.Summary.Row>
<Table.Summary.Cell colSpan={24}>{t("jobs.labels.profileadjustments")}</Table.Summary.Cell> <ResponsiveTable.Summary.Cell colSpan={24}>
</Table.Summary.Row> {t("jobs.labels.profileadjustments")}
</ResponsiveTable.Summary.Cell>
</ResponsiveTable.Summary.Row>
) )
} }
{insuranceAdjustments.map((adj, idx) => ( {insuranceAdjustments.map((adj, idx) => (
<Table.Summary.Row key={idx}> <ResponsiveTable.Summary.Row key={idx}>
<Table.Summary.Cell>{t(`jobs.fields.${adj.id.toLowerCase()}`)}</Table.Summary.Cell> <ResponsiveTable.Summary.Cell>{t(`jobs.fields.${adj.id.toLowerCase()}`)}</ResponsiveTable.Summary.Cell>
<Table.Summary.Cell align="right">{adj.amount.toFormat()}</Table.Summary.Cell> <ResponsiveTable.Summary.Cell align="right">{adj.amount.toFormat()}</ResponsiveTable.Summary.Cell>
</Table.Summary.Row> </ResponsiveTable.Summary.Row>
))} ))}
</> </>
)} )}

View File

@@ -1,4 +1,4 @@
import { Table } from "antd"; import ResponsiveTable from "../responsive-table/responsive-table.component";
import Dinero from "dinero.js"; import Dinero from "dinero.js";
import { useMemo } from "react"; import { useMemo } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -245,8 +245,9 @@ export function JobTotalsTableTotals({ bodyshop, job }) {
]; ];
return ( return (
<Table <ResponsiveTable
columns={columns} columns={columns}
mobileColumnKeys={["total", "key"]}
rowKey="key" rowKey="key"
showHeader={false} showHeader={false}
pagination={false} pagination={false}

View File

@@ -1,5 +1,5 @@
import { DownloadOutlined, SyncOutlined } from "@ant-design/icons"; import { DownloadOutlined, SyncOutlined } from "@ant-design/icons";
import { Button, Card, Input, Space, Table } from "antd"; import { Button, Card, Input, Space } from "antd";
import axios from "axios"; import axios from "axios";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -9,6 +9,7 @@ import { useNotification } from "../../contexts/Notifications/notificationContex
import { selectPartnerVersion } from "../../redux/application/application.selectors"; import { selectPartnerVersion } from "../../redux/application/application.selectors";
import { alphaSort } from "../../utils/sorters"; import { alphaSort } from "../../utils/sorters";
import { logImEXEvent } from "../../firebase/firebase.utils.js"; import { logImEXEvent } from "../../firebase/firebase.utils.js";
import ResponsiveTable from "../responsive-table/responsive-table.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser //currentUser: selectCurrentUser
@@ -141,10 +142,11 @@ export function JobsAvailableScan({ partnerVersion, refetch }) {
</Space> </Space>
} }
> >
<Table <ResponsiveTable
loading={loading} loading={loading}
pagination={{ placement: "top" }} pagination={{ placement: "top" }}
columns={columns} columns={columns}
mobileColumnKeys={["cieca_id", "owner", "vehicle", "actions"]}
rowKey="id" rowKey="id"
dataSource={data} dataSource={data}
onChange={handleTableChange} onChange={handleTableChange}

View File

@@ -1,6 +1,6 @@
import { DeleteFilled, DownloadOutlined, PlusCircleFilled, SyncOutlined } from "@ant-design/icons"; import { DeleteFilled, DownloadOutlined, PlusCircleFilled, SyncOutlined } from "@ant-design/icons";
import { useMutation } from "@apollo/client/react"; import { useMutation } from "@apollo/client/react";
import { Alert, Button, Card, Input, Space, Table } from "antd"; import { Alert, Button, Card, Input, Space } from "antd";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
@@ -13,6 +13,7 @@ import { TimeAgoFormatter } from "../../utils/DateFormatter";
import { alphaSort } from "../../utils/sorters"; import { alphaSort } from "../../utils/sorters";
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx"; import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
import { logImEXEvent } from "../../firebase/firebase.utils.js"; import { logImEXEvent } from "../../firebase/firebase.utils.js";
import ResponsiveTable from "../responsive-table/responsive-table.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop bodyshop: selectBodyshop
@@ -209,7 +210,14 @@ export function JobsAvailableComponent({ bodyshop, loading, data, refetch, addJo
</Space> </Space>
} }
> >
<Table loading={loading} columns={columns} rowKey="id" dataSource={availableJobs} onChange={handleTableChange} /> <ResponsiveTable
loading={loading}
columns={columns}
mobileColumnKeys={["cieca_id", "job_id", "ownr_name", "vehicle_info", "actions"]}
rowKey="id"
dataSource={availableJobs}
onChange={handleTableChange}
/>
</Card> </Card>
); );
} }

View File

@@ -1,4 +1,5 @@
import { Card, Input, Table } from "antd"; import { Card, Input } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useContext, useState } from "react"; import { useContext, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import JobCreateContext from "../../pages/jobs-create/jobs-create.context"; import JobCreateContext from "../../pages/jobs-create/jobs-create.context";
@@ -95,11 +96,12 @@ export default function JobsCreateOwnerInfoSearchComponent({ loading, owners })
/> />
} }
> >
<Table <ResponsiveTable
loading={loading} loading={loading}
scroll={{ x: true }} scroll={{ x: true }}
pagination={{ placement: "top" }} pagination={{ placement: "top" }}
columns={columns} columns={columns}
mobileColumnKeys={["ownr_ln", "ownr_ph1", "ownr_ph2", "ownr_fn"]}
rowKey="id" rowKey="id"
dataSource={owners} dataSource={owners}
onChange={handleTableChange} onChange={handleTableChange}

View File

@@ -1,5 +1,6 @@
import { PlusOutlined, SearchOutlined } from "@ant-design/icons"; import { PlusOutlined, SearchOutlined } from "@ant-design/icons";
import { Button, Input, Popover, Table } from "antd"; import { Button, Input, Popover } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import PredefinedVehicles from "./predefined-vehicles.js"; import PredefinedVehicles from "./predefined-vehicles.js";
@@ -22,9 +23,9 @@ export default function JobsCreateVehicleInfoPredefined({ disabled, form }) {
const popContent = () => ( const popContent = () => (
<div> <div>
<Table <ResponsiveTable
size="small" size="small"
title={() => <Input.Search onSearch={(value) => setSearch(value)} enterButton/>} title={() => <Input.Search onSearch={(value) => setSearch(value)} enterButton />}
dataSource={filteredPredefinedVehicles} dataSource={filteredPredefinedVehicles}
columns={[ columns={[
{ {
@@ -61,6 +62,7 @@ export default function JobsCreateVehicleInfoPredefined({ disabled, form }) {
) )
} }
]} ]}
mobileColumnKeys={["make", "model", "select"]}
/> />
</div> </div>
); );

View File

@@ -1,4 +1,5 @@
import { Card, Input, Space, Table } from "antd"; import { Card, Input, Space } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useContext, useState } from "react"; import { useContext, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
@@ -68,11 +69,12 @@ export default function JobsCreateVehicleInfoSearchComponent({ loading, vehicles
</Space> </Space>
} }
> >
<Table <ResponsiveTable
loading={loading} loading={loading}
scroll={{ x: true }} scroll={{ x: true }}
pagination={{ placement: "top" }} pagination={{ placement: "top" }}
columns={columns} columns={columns}
mobileColumnKeys={["v_vin", "description", "plate"]}
rowKey="id" rowKey="id"
dataSource={vehicles} dataSource={vehicles}
onChange={handleTableChange} onChange={handleTableChange}

View File

@@ -1,5 +1,6 @@
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { Button, Checkbox, Divider, Input, Space, Table } from "antd"; import { Button, Checkbox, Divider, Input, Space } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
@@ -171,7 +172,7 @@ export default function JobsFindModalComponent({
return ( return (
<div> <div>
<Table <ResponsiveTable
title={() => ( title={() => (
<div style={{ display: "flex" }}> <div style={{ display: "flex" }}>
{t("jobs.labels.existing_jobs")} {t("jobs.labels.existing_jobs")}
@@ -191,6 +192,7 @@ export default function JobsFindModalComponent({
)} )}
pagination={{ placement: "bottom" }} pagination={{ placement: "bottom" }}
columns={columns} columns={columns}
mobileColumnKeys={["ro_number", "owner", "status", "vehicle"]}
rowKey="id" rowKey="id"
loading={jobsListLoading} loading={jobsListLoading}
dataSource={jobsList} dataSource={jobsList}

View File

@@ -1,5 +1,5 @@
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { Button, Card, Input, Space, Table, Typography } from "antd"; import { Button, Card, Input, Space, Typography } from "antd";
import axios from "axios"; import axios from "axios";
import _ from "lodash"; import _ from "lodash";
import queryString from "query-string"; import queryString from "query-string";
@@ -15,6 +15,7 @@ import { alphaSort, statusSort } from "../../utils/sorters";
import useLocalStorage from "../../utils/useLocalStorage"; import useLocalStorage from "../../utils/useLocalStorage";
import StartChatButton from "../chat-open-button/chat-open-button.component"; import StartChatButton from "../chat-open-button/chat-open-button.component";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { logImEXEvent } from "../../firebase/firebase.utils"; import { logImEXEvent } from "../../firebase/firebase.utils";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
@@ -238,7 +239,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
</Space> </Space>
} }
> >
<Table <ResponsiveTable
loading={loading || searchLoading} loading={loading || searchLoading}
pagination={ pagination={
search?.search search?.search
@@ -254,6 +255,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
} }
} }
columns={columns} columns={columns}
mobileColumnKeys={["ro_number", "ownr_ln", "status", "vehicle"]}
rowKey="id" rowKey="id"
dataSource={search?.search ? openSearchResults : jobs} dataSource={search?.search ? openSearchResults : jobs}
onChange={handleTableChange} onChange={handleTableChange}

View File

@@ -1,6 +1,6 @@
import { BranchesOutlined, ExclamationCircleFilled, PauseCircleOutlined, SyncOutlined } from "@ant-design/icons"; import { BranchesOutlined, ExclamationCircleFilled, PauseCircleOutlined, SyncOutlined } from "@ant-design/icons";
import { useQuery } from "@apollo/client/react"; import { useQuery } from "@apollo/client/react";
import { Button, Card, Grid, Input, Space, Table, Tooltip } from "antd"; import { Button, Card, Input, Space, Tooltip } from "antd";
import queryString from "query-string"; import queryString from "query-string";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -16,6 +16,7 @@ import useLocalStorage from "../../utils/useLocalStorage";
import AlertComponent from "../alert/alert.component"; import AlertComponent from "../alert/alert.component";
import ChatOpenButton from "../chat-open-button/chat-open-button.component"; import ChatOpenButton from "../chat-open-button/chat-open-button.component";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { OwnerNameDisplayFunction } from "./../owner-name-display/owner-name-display.component"; import { OwnerNameDisplayFunction } from "./../owner-name-display/owner-name-display.component";
import { logImEXEvent } from "../../firebase/firebase.utils"; import { logImEXEvent } from "../../firebase/firebase.utils";
@@ -28,7 +29,6 @@ const mapDispatchToProps = () => ({});
export function JobsList({ bodyshop }) { export function JobsList({ bodyshop }) {
const searchParams = queryString.parse(useLocation().search); const searchParams = queryString.parse(useLocation().search);
const { selected } = searchParams; const { selected } = searchParams;
const screens = Grid.useBreakpoint();
const { loading, error, data, refetch } = useQuery(QUERY_ALL_ACTIVE_JOBS, { const { loading, error, data, refetch } = useQuery(QUERY_ALL_ACTIVE_JOBS, {
variables: { variables: {
statuses: bodyshop.md_ro_statuses.active_statuses || ["Open", "Open*"] statuses: bodyshop.md_ro_statuses.active_statuses || ["Open", "Open*"]
@@ -296,15 +296,6 @@ export function JobsList({ bodyshop }) {
// }, // },
]; ];
const scrollMapper = {
xs: true,
sm: true,
md: true,
lg: "100%",
xl: "100%",
xxl: "100%"
};
return ( return (
<Card <Card
id="active-jobs-list" id="active-jobs-list"
@@ -323,25 +314,13 @@ export function JobsList({ bodyshop }) {
</Space> </Space>
} }
> >
<Table <ResponsiveTable
loading={loading} loading={loading}
pagination={{ defaultPageSize: 50 }} pagination={{ defaultPageSize: 50 }}
columns={columns} columns={columns}
rowKey="id" rowKey="id"
dataSource={jobs} dataSource={jobs}
scroll={{ mobileColumnKeys={["ro_number", "owner", "status", "vehicle"]}
x: screens.xxl
? scrollMapper.xxl
: screens.xl
? scrollMapper.xl
: screens.lg
? scrollMapper.lg
: screens.md
? scrollMapper.md
: screens.sm
? scrollMapper.sm
: scrollMapper.xs
}}
rowSelection={{ rowSelection={{
onSelect: (record) => { onSelect: (record) => {
handleOnRowClick(record); handleOnRowClick(record);

View File

@@ -1,5 +1,6 @@
import { AuditOutlined, DeleteFilled, EditFilled, EyeInvisibleFilled, WarningFilled } from "@ant-design/icons"; import { AuditOutlined, DeleteFilled, EditFilled, EyeInvisibleFilled, WarningFilled } from "@ant-design/icons";
import { Button, Card, Form, Input, Space, Table } from "antd"; import { Button, Card, Form, Input, Space } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
@@ -185,7 +186,14 @@ export function JobNotesComponent({
</Button> </Button>
} }
> >
<Table loading={loading} columns={columns} rowKey="id" dataSource={data} onChange={handleTableChange} /> <ResponsiveTable
loading={loading}
columns={columns}
mobileColumnKeys={["actions", "icons", "type", "text"]}
rowKey="id"
dataSource={data}
onChange={handleTableChange}
/>
</Card> </Card>
</div> </div>
); );

View File

@@ -1,6 +1,6 @@
import { BranchesOutlined, ExclamationCircleFilled, PauseCircleOutlined, SyncOutlined } from "@ant-design/icons"; import { BranchesOutlined, ExclamationCircleFilled, PauseCircleOutlined, SyncOutlined } from "@ant-design/icons";
import { useQuery } from "@apollo/client/react"; import { useQuery } from "@apollo/client/react";
import { Button, Card, Grid, Input, Space, Table, Tooltip } from "antd"; import { Button, Card, Input, Space, Tooltip } from "antd";
import queryString from "query-string"; import queryString from "query-string";
import { useMemo, useState } from "react"; import { useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -17,6 +17,7 @@ import useLocalStorage from "../../utils/useLocalStorage";
import AlertComponent from "../alert/alert.component"; import AlertComponent from "../alert/alert.component";
import ChatOpenButton from "../chat-open-button/chat-open-button.component"; import ChatOpenButton from "../chat-open-button/chat-open-button.component";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
import ResponsiveTable from "../responsive-table/responsive-table.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop bodyshop: selectBodyshop
@@ -25,7 +26,6 @@ const mapStateToProps = createStructuredSelector({
export function JobsReadyList({ bodyshop }) { export function JobsReadyList({ bodyshop }) {
const searchParams = queryString.parse(useLocation().search); const searchParams = queryString.parse(useLocation().search);
const { selected } = searchParams; const { selected } = searchParams;
const screens = Grid.useBreakpoint();
const readyStatuses = useMemo(() => { const readyStatuses = useMemo(() => {
if (bodyshop.md_ro_statuses.ready_statuses) return bodyshop.md_ro_statuses.ready_statuses; if (bodyshop.md_ro_statuses.ready_statuses) return bodyshop.md_ro_statuses.ready_statuses;
@@ -280,15 +280,6 @@ export function JobsReadyList({ bodyshop }) {
// }, // },
]; ];
const scrollMapper = {
xs: true,
sm: true,
md: true,
lg: "100%",
xl: "100%",
xxl: "100%"
};
return ( return (
<Card <Card
title={t("titles.bc.jobs-ready")} title={t("titles.bc.jobs-ready")}
@@ -307,25 +298,13 @@ export function JobsReadyList({ bodyshop }) {
</Space> </Space>
} }
> >
<Table <ResponsiveTable
loading={loading} loading={loading}
pagination={{ defaultPageSize: pageLimit }} pagination={{ defaultPageSize: pageLimit }}
columns={columns} columns={columns}
rowKey="id" rowKey="id"
dataSource={jobs} dataSource={jobs}
scroll={{ mobileColumnKeys={["ro_number", "owner", "status", "vehicle"]}
x: screens.xxl
? scrollMapper.xxl
: screens.xl
? scrollMapper.xl
: screens.lg
? scrollMapper.lg
: screens.md
? scrollMapper.md
: screens.sm
? scrollMapper.sm
: scrollMapper.xs
}}
rowSelection={{ rowSelection={{
onSelect: (record) => { onSelect: (record) => {
handleOnRowClick(record); handleOnRowClick(record);

View File

@@ -1,5 +1,6 @@
import { EditFilled } from "@ant-design/icons"; import { EditFilled } from "@ant-design/icons";
import { Alert, Card, Col, Row, Space, Table, Typography } from "antd"; import { Alert, Card, Col, Row, Space, Typography } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useEffect, useMemo, useState } from "react"; import { useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
@@ -196,8 +197,9 @@ export function LaborAllocationsTable({
<Row gutter={[16, 16]}> <Row gutter={[16, 16]}>
<Col span={24}> <Col span={24}>
<Card title={t("jobs.labels.laborallocations")}> <Card title={t("jobs.labels.laborallocations")}>
<Table <ResponsiveTable
columns={columns} columns={columns}
mobileColumnKeys={["line_desc", "total", "cost_center", "hrs_claimed"]}
rowKey={(record) => `${record.cost_center} ${record.mod_lbr_ty}`} rowKey={(record) => `${record.cost_center} ${record.mod_lbr_ty}`}
pagination={false} pagination={false}
onChange={handleTableChange} onChange={handleTableChange}
@@ -215,16 +217,22 @@ export function LaborAllocationsTable({
x: true x: true
}} }}
summary={() => ( summary={() => (
<Table.Summary.Row> <ResponsiveTable.Summary.Row>
<Table.Summary.Cell> <ResponsiveTable.Summary.Cell>
<Typography.Title level={4} style={{ margin: 0, lineHeight: 1 }}> <Typography.Title level={4} style={{ margin: 0, lineHeight: 1 }}>
{t("general.labels.totals")} {t("general.labels.totals")}
</Typography.Title> </Typography.Title>
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell align="right">{summary.hrs_total.toFixed(1)}</Table.Summary.Cell> <ResponsiveTable.Summary.Cell align="right">
<Table.Summary.Cell align="right">{summary.hrs_claimed.toFixed(1)}</Table.Summary.Cell> {summary.hrs_total.toFixed(1)}
<Table.Summary.Cell align="right">{summary.adjustments.toFixed(1)}</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell align="right"> <ResponsiveTable.Summary.Cell align="right">
{summary.hrs_claimed.toFixed(1)}
</ResponsiveTable.Summary.Cell>
<ResponsiveTable.Summary.Cell align="right">
{summary.adjustments.toFixed(1)}
</ResponsiveTable.Summary.Cell>
<ResponsiveTable.Summary.Cell align="right">
<Typography.Text <Typography.Text
style={{ style={{
fontWeight: "bold", fontWeight: "bold",
@@ -233,8 +241,8 @@ export function LaborAllocationsTable({
> >
{(Math.abs(summary.difference) < 0.05 ? 0 : summary.difference).toFixed(1)} {(Math.abs(summary.difference) < 0.05 ? 0 : summary.difference).toFixed(1)}
</Typography.Text> </Typography.Text>
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
</Table.Summary.Row> </ResponsiveTable.Summary.Row>
)} )}
/> />
</Card> </Card>
@@ -242,8 +250,9 @@ export function LaborAllocationsTable({
{convertedLines && convertedLines.length > 0 && ( {convertedLines && convertedLines.length > 0 && (
<Col span={24}> <Col span={24}>
<Card title={t("jobs.labels.convertedtolabor")}> <Card title={t("jobs.labels.convertedtolabor")}>
<Table <ResponsiveTable
columns={convertedTableCols} columns={convertedTableCols}
mobileColumnKeys={["line_desc", "total", "cost_center", "hrs_claimed"]}
rowKey="id" rowKey="id"
pagination={false} pagination={false}
dataSource={hasTimeTicketAccess ? convertedLines : []} dataSource={hasTimeTicketAccess ? convertedLines : []}

View File

@@ -1,4 +1,5 @@
import { Alert, Button, Card, Col, Row, Space, Table, Typography } from "antd"; import { Alert, Button, Card, Col, Row, Space, Typography } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import axios from "axios"; import axios from "axios";
import _ from "lodash"; import _ from "lodash";
@@ -251,8 +252,9 @@ export function PayrollLaborAllocationsTable({
</Space> </Space>
} }
> >
<Table <ResponsiveTable
columns={columns} columns={columns}
mobileColumnKeys={["line_desc", "employeeid", "mod_lbr_ty", "rate"]}
rowKey={(record) => `${record.employeeid} ${record.mod_lbr_ty}`} rowKey={(record) => `${record.employeeid} ${record.mod_lbr_ty}`}
pagination={false} pagination={false}
onChange={handleTableChange} onChange={handleTableChange}
@@ -270,16 +272,16 @@ export function PayrollLaborAllocationsTable({
}) })
}} }}
summary={() => ( summary={() => (
<Table.Summary.Row> <ResponsiveTable.Summary.Row>
<Table.Summary.Cell> <ResponsiveTable.Summary.Cell>
<Typography.Title level={4}>{t("general.labels.totals")}</Typography.Title> <Typography.Title level={4}>{t("general.labels.totals")}</Typography.Title>
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell></Table.Summary.Cell> <ResponsiveTable.Summary.Cell></ResponsiveTable.Summary.Cell>
<Table.Summary.Cell>{summary.hrs_total.toFixed(5)}</Table.Summary.Cell> <ResponsiveTable.Summary.Cell>{summary.hrs_total.toFixed(5)}</ResponsiveTable.Summary.Cell>
<Table.Summary.Cell>{summary.hrs_claimed.toFixed(5)}</Table.Summary.Cell> <ResponsiveTable.Summary.Cell>{summary.hrs_claimed.toFixed(5)}</ResponsiveTable.Summary.Cell>
<Table.Summary.Cell>{summary.difference.toFixed(5)}</Table.Summary.Cell> <ResponsiveTable.Summary.Cell>{summary.difference.toFixed(5)}</ResponsiveTable.Summary.Cell>
</Table.Summary.Row> </ResponsiveTable.Summary.Row>
)} )}
/> />
</Card> </Card>
@@ -287,8 +289,9 @@ export function PayrollLaborAllocationsTable({
{convertedLines && convertedLines.length > 0 && ( {convertedLines && convertedLines.length > 0 && (
<Col span={24}> <Col span={24}>
<Card title={t("jobs.labels.convertedtolabor")}> <Card title={t("jobs.labels.convertedtolabor")}>
<Table <ResponsiveTable
columns={convertedTableCols} columns={convertedTableCols}
mobileColumnKeys={["line_desc", "employeeid", "mod_lbr_ty", "rate"]}
rowKey="id" rowKey="id"
pagination={false} pagination={false}
dataSource={convertedLines} dataSource={convertedLines}

View File

@@ -7,7 +7,7 @@ export default function LayoutFormRow({
children, children,
grow = false, grow = false,
noDivider = false, noDivider = false,
gutter = [16, 16], gutter = [16, 16], // Responsive gutter: horizontal, vertical
rowProps, rowProps,
// Optional overrides if you ever need per-section customization // Optional overrides if you ever need per-section customization
@@ -63,30 +63,60 @@ export default function LayoutFormRow({
} }
const count = items.length; const count = items.length;
const spanFor = (min) => Math.max(min, Math.floor(24 / count));
// Mobile-first: stack on xs // Modern responsive strategy leveraging Ant Design 6:
const baseCol = { // - xs (phone <576px): Always stack vertically
xs: { span: 24 }, // - sm (tablet 576-768px): 2 columns for better readability
sm: { span: grow ? spanFor(12) : 12 }, // - md (tablet 768-992px): 3 columns for tablets
md: { span: grow ? spanFor(8) : 8 }, // - lg+ (desktop >992px): Dynamic flex-based columns that adapt to screen width
lg: { span: grow ? spanFor(6) : 6 }, // Target: 1366px → 4 cols, 1920px → 6 cols, 2560px → 8 cols, 4K → capped at 8-9 cols
xl: { span: grow ? spanFor(4) : 4 }, // Note: xxl uses higher min-width to naturally cap maximum columns
xxl: { span: grow ? spanFor(4) : 4 } const baseCol = (() => {
}; if (grow) {
// Grow mode: use flex with reasonable min-widths
return {
xs: 24,
sm: 12, // Fixed 2 cols on small tablets
md: 8, // Fixed 3 cols on large tablets
lg: { flex: `1 1 320px` }, // Dynamic: ~3 cols at 1200px
xl: { flex: `1 1 280px` }, // Dynamic: ~4 cols at 1366px, ~6 cols at 1920px
xxl: { flex: `1 1 380px` } // Dynamic: ~6 cols at 2560px, ~9 cols at 4K (capped)
};
} else {
// Fixed mode: Use flex without grow to maintain uniform widths across rows
// xxl uses larger min-width to cap maximum columns on 4K/ultrawide
const minWidthLg = count <= 2 ? 500 : count === 3 ? 380 : 320; // 3 cols at 1200px
const minWidthXl = count <= 2 ? 480 : count === 3 ? 360 : 280; // 4 cols at 1366px, ~6 at 1920px
const minWidthXxl = count <= 2 ? 500 : count === 3 ? 400 : 380; // ~6 cols at 2560px, ~9 at 4K (natural cap)
return {
xs: 24,
sm: 12, // Fixed 2 columns on tablet
md: count === 1 ? 24 : count === 2 ? 12 : 8, // Fixed 1-3 cols on large tablet
lg: count === 1 ? 24 : { flex: `0 0 ${minWidthLg}px` }, // Fixed width on desktop
xl: count === 1 ? 24 : { flex: `0 0 ${minWidthXl}px` }, // Fixed width on large desktop
xxl: count === 1 ? 24 : { flex: `0 0 ${minWidthXxl}px` } // Fixed width on ultrawide
};
}
})();
const getColPropsForChild = (child) => { const getColPropsForChild = (child) => {
if (!isValidElement(child)) return baseCol; if (!isValidElement(child)) return baseCol;
// Back-compat with old pattern: child.props.span can override Col sizing // Back-compat: child.props.span can override Col sizing
const spanOverride = child.props?.span; const spanOverride = child.props?.span;
if (typeof spanOverride === "number") return { span: spanOverride }; if (typeof spanOverride === "number") return { span: spanOverride };
if (spanOverride && typeof spanOverride === "object") return spanOverride; if (spanOverride && typeof spanOverride === "object") return spanOverride;
// Optional explicit override: <Field col={{ md:{span:12}, ... }} /> // Explicit override: <Field col={{ md:{span:12}, ... }} />
const colOverride = child.props?.col; const colOverride = child.props?.col;
if (colOverride && typeof colOverride === "object") { if (colOverride && typeof colOverride === "object") {
return { ...baseCol, ...colOverride }; // Deep merge: allow partial overrides while keeping baseCol defaults
const merged = { ...baseCol };
Object.keys(colOverride).forEach((bp) => {
merged[bp] = typeof colOverride[bp] === "object" ? { ...baseCol[bp], ...colOverride[bp] } : colOverride[bp];
});
return merged;
} }
return baseCol; return baseCol;

View File

@@ -24,7 +24,7 @@ html[data-theme="dark"] {
.imex-form-row { .imex-form-row {
width: 100%; width: 100%;
/* Match old Divider title typography */ /* Match old Divider title typography */
.ant-card-head-title { .ant-card-head-title {
font-weight: 500; font-weight: 500;
@@ -47,18 +47,33 @@ html[data-theme="dark"] {
background: var(--imex-form-surface); background: var(--imex-form-surface);
} }
/* Optional: slightly tighter on phones */ /* Optional: tighter spacing on phones for better space usage */
@media (max-width: 575px) { @media (max-width: 575px) {
.ant-card-head { .ant-card-head {
padding-inline: 12px; padding-inline: 12px;
padding-block: 12px;
} }
.ant-card-body { .ant-card-body {
padding: 12px; padding: 12px;
} }
} }
/* Common form nicety */ /* Tablet optimization: slightly reduce padding */
@media (min-width: 576px) and (max-width: 991px) {
.ant-card-body {
padding: 14px;
}
}
/* Ensure form items use full column width */
.ant-col > * { .ant-col > * {
width: 100%; width: 100%;
} }
/* Better form item spacing on mobile */
@media (max-width: 575px) {
.ant-form-item {
margin-bottom: 12px;
}
}
} }

View File

@@ -1,6 +1,7 @@
import { useMutation, useQuery } from "@apollo/client/react"; import { useMutation, useQuery } from "@apollo/client/react";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { Alert, Button, Card, Checkbox, Divider, Form, Space, Switch, Table, Typography } from "antd"; import { Alert, Button, Card, Checkbox, Divider, Form, Space, Switch, Typography } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
@@ -204,7 +205,14 @@ const NotificationSettingsForm = ({ currentUser, bodyshop }) => {
<Alert title={t("notifications.labels.employee-notification")} type="warning" /> <Alert title={t("notifications.labels.employee-notification")} type="warning" />
</div> </div>
)} )}
<Table dataSource={dataSource} columns={columns} pagination={false} bordered rowKey="key" /> <ResponsiveTable
dataSource={dataSource}
columns={columns}
mobileColumnKeys={["email", "scenario", "app", "fcm"]}
pagination={false}
bordered
rowKey="key"
/>
<Divider /> <Divider />
</Card> </Card>
</Form> </Form>

View File

@@ -1,4 +1,4 @@
import { Card, Table } from "antd"; import { Card } from "antd";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
@@ -11,6 +11,7 @@ import { alphaSort, dateSort, statusSort } from "../../utils/sorters";
import OwnerDetailUpdateJobsComponent from "../owner-detail-update-jobs/owner-detail-update-jobs.component"; import OwnerDetailUpdateJobsComponent from "../owner-detail-update-jobs/owner-detail-update-jobs.component";
import { selectIsPartsEntry } from "../../redux/application/application.selectors"; import { selectIsPartsEntry } from "../../redux/application/application.selectors";
import getPartsBasePath from "../../utils/getPartsBasePath.js"; import getPartsBasePath from "../../utils/getPartsBasePath.js";
import ResponsiveTable from "../responsive-table/responsive-table.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
@@ -109,9 +110,10 @@ function OwnerDetailJobsComponent({ bodyshop, owner, isPartsEntry }) {
/> />
} }
> >
<Table <ResponsiveTable
pagination={{ placement: "bottom" }} pagination={{ placement: "bottom" }}
columns={columns} columns={columns}
mobileColumnKeys={["ro_number", "vehicleid", "status", "actual_completion"]}
scroll={{ x: true }} scroll={{ x: true }}
rowKey="id" rowKey="id"
dataSource={owner.jobs} dataSource={owner.jobs}

View File

@@ -1,6 +1,7 @@
import { Checkbox, Divider, Table } from "antd"; import { Checkbox, Divider } from "antd";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import PhoneFormatter from "../../utils/PhoneFormatter"; import PhoneFormatter from "../../utils/PhoneFormatter";
import ResponsiveTable from "../responsive-table/responsive-table.component";
export default function OwnerFindModalComponent({ export default function OwnerFindModalComponent({
selectedOwner, selectedOwner,
@@ -75,9 +76,10 @@ export default function OwnerFindModalComponent({
return ( return (
<div> <div>
<Table <ResponsiveTable
pagination={{ placement: "bottom" }} pagination={{ placement: "bottom" }}
columns={columns} columns={columns}
mobileColumnKeys={["ownr_ln", "ownr_fn", "ownr_ph1", "ownr_ph2"]}
rowKey="id" rowKey="id"
loading={ownersListLoading} loading={ownersListLoading}
dataSource={ownersList} dataSource={ownersList}

View File

@@ -1,5 +1,5 @@
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { Button, Card, Input, Space, Table, Typography } from "antd"; import { Button, Card, Input, Space, Typography } from "antd";
import queryString from "query-string"; import queryString from "query-string";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -7,6 +7,7 @@ import { Link, useLocation, useNavigate } from "react-router-dom";
import PhoneFormatter from "../../utils/PhoneFormatter"; import PhoneFormatter from "../../utils/PhoneFormatter";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
import { pageLimit } from "../../utils/config"; import { pageLimit } from "../../utils/config";
import ResponsiveTable from "../responsive-table/responsive-table.component";
export default function OwnersListComponent({ loading, owners, total, refetch }) { export default function OwnersListComponent({ loading, owners, total, refetch }) {
const search = queryString.parse(useLocation().search); const search = queryString.parse(useLocation().search);
@@ -116,10 +117,11 @@ export default function OwnersListComponent({ loading, owners, total, refetch })
</Space> </Space>
} }
> >
<Table <ResponsiveTable
loading={loading} loading={loading}
pagination={{ placement: "top", pageSize: pageLimit, current: parseInt(page || 1, 10), total: total }} pagination={{ placement: "top", pageSize: pageLimit, current: parseInt(page || 1, 10), total: total }}
columns={columns} columns={columns}
mobileColumnKeys={["name", "ownr_ph1", "ownr_ph2"]}
rowKey="id" rowKey="id"
scroll={{ x: true }} scroll={{ x: true }}
dataSource={owners} dataSource={owners}

View File

@@ -1,5 +1,6 @@
import { useMutation } from "@apollo/client/react"; import { useMutation } from "@apollo/client/react";
import { Button, Card, Col, Row, Table } from "antd"; import { Button, Card, Col, Row } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import dayjs from "../../utils/day"; import dayjs from "../../utils/day";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { UPDATE_PARTS_DISPATCH_LINE } from "../../graphql/parts-dispatch.queries"; import { UPDATE_PARTS_DISPATCH_LINE } from "../../graphql/parts-dispatch.queries";
@@ -67,7 +68,12 @@ export default function PartsDispatchExpander({ dispatch }) {
<Card> <Card>
<Row gutter={[16, 16]}> <Row gutter={[16, 16]}>
<Col span={24}> <Col span={24}>
<Table rowKey={"id"} dataSource={dispatch.parts_dispatch_lines} columns={columns} /> <ResponsiveTable
rowKey={"id"}
dataSource={dispatch.parts_dispatch_lines}
columns={columns}
mobileColumnKeys={["quantity", "joblineid", "accepted_at"]}
/>
</Col> </Col>
</Row> </Row>
</Card> </Card>

View File

@@ -1,5 +1,6 @@
import { MinusCircleTwoTone, PlusCircleTwoTone, SyncOutlined } from "@ant-design/icons"; import { MinusCircleTwoTone, PlusCircleTwoTone, SyncOutlined } from "@ant-design/icons";
import { Button, Card, Input, Space, Table } from "antd"; import { Button, Card, Input, Space } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
@@ -106,7 +107,7 @@ export function PartDispatchTableComponent({ bodyshop, job, billsQuery }) {
</Space> </Space>
} }
> >
<Table <ResponsiveTable
loading={billsQuery.loading} loading={billsQuery.loading}
scroll={{ scroll={{
x: true // y: "50rem" x: true // y: "50rem"
@@ -123,6 +124,7 @@ export function PartDispatchTableComponent({ bodyshop, job, billsQuery }) {
) )
}} }}
columns={columns} columns={columns}
mobileColumnKeys={["number", "employeeid", "percent_accepted", "actions"]}
rowKey="id" rowKey="id"
dataSource={billsQuery.data ? billsQuery.data.parts_dispatch : []} dataSource={billsQuery.data ? billsQuery.data.parts_dispatch : []}
onChange={handleTableChange} onChange={handleTableChange}

View File

@@ -1,7 +1,8 @@
import { DeleteFilled } from "@ant-design/icons"; import { DeleteFilled } from "@ant-design/icons";
import { PageHeader } from "@ant-design/pro-layout"; import { PageHeader } from "@ant-design/pro-layout";
import { useLazyQuery, useMutation } from "@apollo/client/react"; import { useLazyQuery, useMutation } from "@apollo/client/react";
import { Button, Drawer, Grid, Popconfirm, Space, Table } from "antd"; import { Button, Drawer, Grid, Popconfirm, Space } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import queryString from "query-string"; import queryString from "query-string";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -66,7 +67,7 @@ export function PartsOrderListTableDrawerComponent({
isPartsEntry isPartsEntry
}) { }) {
const screens = Grid.useBreakpoint(); const screens = Grid.useBreakpoint();
const bpoints = { const bpoints = {
xs: "100%", xs: "100%",
sm: "100%", sm: "100%",
@@ -75,7 +76,7 @@ export function PartsOrderListTableDrawerComponent({
xl: "75%", xl: "75%",
xxl: "65%" xxl: "65%"
}; };
let drawerPercentage = "100%"; let drawerPercentage = "100%";
if (screens.xxl) drawerPercentage = bpoints.xxl; if (screens.xxl) drawerPercentage = bpoints.xxl;
else if (screens.xl) drawerPercentage = bpoints.xl; else if (screens.xl) drawerPercentage = bpoints.xl;
@@ -368,11 +369,12 @@ export function PartsOrderListTableDrawerComponent({
} }
extra={recordActions(record)} extra={recordActions(record)}
/> />
<Table <ResponsiveTable
scroll={{ scroll={{
x: true //y: "50rem" x: true //y: "50rem"
}} }}
columns={columns} columns={columns}
mobileColumnKeys={["status", "line_desc", "actions", "quantity"]}
rowKey="id" rowKey="id"
dataSource={record.parts_order_lines} dataSource={record.parts_order_lines}
onChange={handleTableChange} onChange={handleTableChange}

View File

@@ -1,6 +1,6 @@
import { DeleteFilled, EyeFilled, SyncOutlined } from "@ant-design/icons"; import { DeleteFilled, EyeFilled, SyncOutlined } from "@ant-design/icons";
import { useMutation } from "@apollo/client/react"; import { useMutation } from "@apollo/client/react";
import { Button, Card, Checkbox, Input, Popconfirm, Space, Table } from "antd"; import { Button, Card, Checkbox, Input, Popconfirm, Space } from "antd";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { FaTasks } from "react-icons/fa"; import { FaTasks } from "react-icons/fa";
@@ -21,6 +21,7 @@ import PrintWrapper from "../print-wrapper/print-wrapper.component";
import PartsOrderDrawer from "./parts-order-list-table-drawer.component"; import PartsOrderDrawer from "./parts-order-list-table-drawer.component";
import ShareToTeamsButton from "../share-to-teams/share-to-teams.component.jsx"; import ShareToTeamsButton from "../share-to-teams/share-to-teams.component.jsx";
import { bodyshopHasDmsKey } from "../../utils/dmsUtils.js"; import { bodyshopHasDmsKey } from "../../utils/dmsUtils.js";
import ResponsiveTable from "../responsive-table/responsive-table.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
jobRO: selectJobReadOnly, jobRO: selectJobReadOnly,
@@ -309,13 +310,14 @@ export function PartsOrderListTableComponent({
setPartsReceiveContext={setPartsReceiveContext} setPartsReceiveContext={setPartsReceiveContext}
setTaskUpsertContext={setTaskUpsertContext} setTaskUpsertContext={setTaskUpsertContext}
/> />
<Table <ResponsiveTable
loading={billsQuery.loading} loading={billsQuery.loading}
scroll={{ scroll={{
x: true x: true
//y: "50rem" //y: "50rem"
}} }}
columns={columns} columns={columns}
mobileColumnKeys={["vendorname", "order_number", "order_date", "actions"]}
rowKey="id" rowKey="id"
dataSource={filteredPartsOrders} dataSource={filteredPartsOrders}
onChange={handleTableChange} onChange={handleTableChange}

View File

@@ -1,4 +1,5 @@
import { Card, Table } from "antd"; import { Card } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
@@ -164,8 +165,9 @@ export function PartsQueueJobLinesComponent({ loading, jobLines }) {
return ( return (
<Card title={t("jobs.labels.parts_lines")}> <Card title={t("jobs.labels.parts_lines")}>
<Table <ResponsiveTable
columns={columns} columns={columns}
mobileColumnKeys={["status", "line_desc", "line_no", "oem_partno"]}
rowKey="id" rowKey="id"
loading={loading} loading={loading}
pagination={false} pagination={false}

View File

@@ -1,6 +1,6 @@
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { useQuery } from "@apollo/client/react"; import { useQuery } from "@apollo/client/react";
import { Button, Card, Checkbox, Input, Space, Table } from "antd"; import { Button, Card, Checkbox, Input, Space } from "antd";
import _ from "lodash"; import _ from "lodash";
import queryString from "query-string"; import queryString from "query-string";
import { useState } from "react"; import { useState } from "react";
@@ -19,6 +19,7 @@ import AlertComponent from "../alert/alert.component";
import JobRemoveFromPartsQueue from "../job-remove-from-parst-queue/job-remove-from-parts-queue.component"; import JobRemoveFromPartsQueue from "../job-remove-from-parst-queue/job-remove-from-parts-queue.component";
import OwnerNameDisplay, { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component"; import OwnerNameDisplay, { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component";
import ProductionListColumnComment from "../production-list-columns/production-list-columns.comment.component"; import ProductionListColumnComment from "../production-list-columns/production-list-columns.comment.component";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { logImEXEvent } from "../../firebase/firebase.utils"; import { logImEXEvent } from "../../firebase/firebase.utils";
import JobPartsReceived from "../job-parts-received/job-parts-received.component"; import JobPartsReceived from "../job-parts-received/job-parts-received.component";
@@ -310,7 +311,7 @@ export function PartsQueueListComponent({ bodyshop }) {
</Space> </Space>
} }
> >
<Table <ResponsiveTable
loading={loading} loading={loading}
pagination={{ pagination={{
placement: "top", placement: "top",
@@ -319,6 +320,7 @@ export function PartsQueueListComponent({ bodyshop }) {
// total: data && data.jobs_aggregate.aggregate.count, // total: data && data.jobs_aggregate.aggregate.count,
}} }}
columns={columns} columns={columns}
mobileColumnKeys={["ro_number", "ownr_ln", "status", "vehicle", "partsstatus"]}
rowKey="id" rowKey="id"
dataSource={jobs} dataSource={jobs}
style={{ height: "100%" }} style={{ height: "100%" }}

View File

@@ -1,6 +1,6 @@
import { EditFilled, SyncOutlined } from "@ant-design/icons"; import { EditFilled, SyncOutlined } from "@ant-design/icons";
import { useApolloClient } from "@apollo/client/react"; import { useApolloClient } from "@apollo/client/react";
import { Button, Card, Input, Space, Table, Typography } from "antd"; import { Button, Card, Input, Space, Typography } from "antd";
import axios from "axios"; import axios from "axios";
import queryString from "query-string"; import queryString from "query-string";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
@@ -19,6 +19,7 @@ import { alphaSort } from "../../utils/sorters";
import CaBcEtfTableModalContainer from "../ca-bc-etf-table-modal/ca-bc-etf-table-modal.container"; import CaBcEtfTableModalContainer from "../ca-bc-etf-table-modal/ca-bc-etf-table-modal.container";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
import PrintWrapperComponent from "../print-wrapper/print-wrapper.component"; import PrintWrapperComponent from "../print-wrapper/print-wrapper.component";
import ResponsiveTable from "../responsive-table/responsive-table.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser //currentUser: selectCurrentUser
@@ -258,7 +259,7 @@ export function PaymentsListPaginated({
</Space> </Space>
} }
> >
<Table <ResponsiveTable
loading={loading || searchLoading} loading={loading || searchLoading}
scroll={{ x: true }} scroll={{ x: true }}
pagination={ pagination={
@@ -275,6 +276,7 @@ export function PaymentsListPaginated({
} }
} }
columns={columns} columns={columns}
mobileColumnKeys={["ro_number", "owner", "date", "amount", "actions"]}
rowKey="id" rowKey="id"
dataSource={search?.search ? openSearchResults : payments} dataSource={search?.search ? openSearchResults : payments}
onChange={handleTableChange} onChange={handleTableChange}

View File

@@ -1,5 +1,6 @@
import { useQuery } from "@apollo/client/react"; import { useQuery } from "@apollo/client/react";
import { Input, Table, Typography } from "antd"; import { Input, Typography } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors";
@@ -132,8 +133,9 @@ function PhoneNumberConsentList({ bodyshop }) {
enterButton enterButton
/> />
<Table <ResponsiveTable
columns={columns} columns={columns}
mobileColumnKeys={["phone_number", "created_at"]}
dataSource={optOutData?.phone_number_opt_out} dataSource={optOutData?.phone_number_opt_out}
loading={optOutLoading /* || ownersLoading*/} loading={optOutLoading /* || ownersLoading*/}
rowKey="id" rowKey="id"

View File

@@ -1,4 +1,5 @@
import { Button, Card, Col, Input, Table, Typography } from "antd"; import { Button, Card, Col, Input, Typography } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -48,7 +49,14 @@ export default function ProfileShopsComponent({ loading, data, updateActiveShop
/> />
} }
> >
<Table pagination={false} loading={loading} columns={columns} rowKey="id" dataSource={filteredData} /> <ResponsiveTable
pagination={false}
loading={loading}
columns={columns}
mobileColumnKeys={["actions", "shopname", "active"]}
rowKey="id"
dataSource={filteredData}
/>
</Card> </Card>
</Col> </Col>
); );

View File

@@ -0,0 +1,52 @@
import { Grid, Table } from "antd";
import { useMemo } from "react";
function ResponsiveTable({ columns, mobileColumnKeys, scroll, ...rest }) {
const screens = Grid.useBreakpoint();
const isPhone = !screens.md;
const isResponsiveFilteringEnabled = ["1", "true", "yes", "on"].includes(
String(import.meta.env.VITE_APP_ENABLE_RESPONSIVE_TABLE_FILTERING || "")
.trim()
.toLowerCase()
);
const resolvedColumns = useMemo(() => {
if (
!isResponsiveFilteringEnabled ||
!Array.isArray(columns) ||
!isPhone ||
!Array.isArray(mobileColumnKeys) ||
mobileColumnKeys.length === 0
) {
return columns;
}
const visibleColumnKeys = new Set(mobileColumnKeys);
const filteredColumns = columns.filter((column) => {
const key = column?.key ?? column?.dataIndex;
// Keep columns with no stable key to avoid accidental loss.
if (key == null) return true;
if (Array.isArray(key)) {
return key.some((part) => visibleColumnKeys.has(part));
}
return visibleColumnKeys.has(key);
});
return filteredColumns.length > 0 ? filteredColumns : columns;
}, [columns, isPhone, isResponsiveFilteringEnabled, mobileColumnKeys]);
const resolvedScroll = scroll ?? { x: "max-content" };
return <Table columns={resolvedColumns} scroll={resolvedScroll} {...rest} />;
}
ResponsiveTable.Summary = Table.Summary;
ResponsiveTable.Column = Table.Column;
ResponsiveTable.ColumnGroup = Table.ColumnGroup;
ResponsiveTable.SELECTION_COLUMN = Table.SELECTION_COLUMN;
ResponsiveTable.EXPAND_COLUMN = Table.EXPAND_COLUMN;
export default ResponsiveTable;

View File

@@ -1,6 +1,7 @@
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { useQuery } from "@apollo/client/react"; import { useQuery } from "@apollo/client/react";
import { Button, Card, Input, Modal, Space, Table, Typography } from "antd"; import { Button, Card, Input, Modal, Space, Typography } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
@@ -140,8 +141,9 @@ export default function ScoreboardJobsList() {
</Space> </Space>
} }
> >
<Table <ResponsiveTable
columns={columns} columns={columns}
mobileColumnKeys={["ro_number", "owner", "vehicle", "date", "actions"]}
rowKey="id" rowKey="id"
dataSource={data ? data.scoreboard : []} dataSource={data ? data.scoreboard : []}
loading={loading} loading={loading}

View File

@@ -1,4 +1,5 @@
import { Card, Col, Row, Statistic, Table, Typography } from "antd"; import { Card, Col, Row, Statistic, Typography } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
@@ -98,8 +99,9 @@ export function ScoreboardTicketsStats({ data }) {
<Typography.Text type="secondary">{t("scoreboard.labels.calendarperiod")}</Typography.Text> <Typography.Text type="secondary">{t("scoreboard.labels.calendarperiod")}</Typography.Text>
</Col> </Col>
<Col md={24} lg={20}> <Col md={24} lg={20}>
<Table <ResponsiveTable
columns={columns} columns={columns}
mobileColumnKeys={["employee_number", "totalThisWeek", "totalLastWeek", "totalThisMonth"]}
rowKey="employee_number" rowKey="employee_number"
dataSource={tableData} dataSource={tableData}
id="employee_number" id="employee_number"

View File

@@ -1,7 +1,8 @@
import { DeleteFilled } from "@ant-design/icons"; import { DeleteFilled } from "@ant-design/icons";
import { useApolloClient, useMutation, useQuery } from "@apollo/client/react"; import { useApolloClient, useMutation, useQuery } from "@apollo/client/react";
import { useTreatmentsWithConfig } from "@splitsoftware/splitio-react"; import { useTreatmentsWithConfig } from "@splitsoftware/splitio-react";
import { Button, Card, Form, Input, InputNumber, Select, Switch, Table } from "antd"; import { Button, Card, Form, Input, InputNumber, Select, Switch } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useForm } from "antd/es/form/Form"; import { useForm } from "antd/es/form/Form";
import queryString from "query-string"; import queryString from "query-string";
import { useEffect } from "react"; import { useEffect } from "react";
@@ -380,9 +381,10 @@ export function ShopEmployeesFormComponent({ bodyshop }) {
</Form.List> </Form.List>
</Form> </Form>
<Table <ResponsiveTable
title={() => <ShopEmployeeAddVacation employee={data && data.employees_by_pk} />} title={() => <ShopEmployeeAddVacation employee={data && data.employees_by_pk} />}
columns={columns} columns={columns}
mobileColumnKeys={["start", "length", "actions"]}
rowKey={"id"} rowKey={"id"}
dataSource={data?.employees_by_pk?.employee_vacations ?? []} dataSource={data?.employees_by_pk?.employee_vacations ?? []}
/> />

View File

@@ -1,9 +1,10 @@
import { Button, Table } from "antd"; import { Button } from "antd";
import queryString from "query-string"; import queryString from "query-string";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useLocation, useNavigate } from "react-router-dom"; import { useLocation, useNavigate } from "react-router-dom";
import { alphaSort } from "../../utils/sorters"; import { alphaSort } from "../../utils/sorters";
import ResponsiveTable from "../responsive-table/responsive-table.component";
export default function ShopEmployeesListComponent({ loading, employees }) { export default function ShopEmployeesListComponent({ loading, employees }) {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -89,7 +90,7 @@ export default function ShopEmployeesListComponent({ loading, employees }) {
]; ];
return ( return (
<div> <div>
<Table <ResponsiveTable
title={() => { title={() => {
return ( return (
<Button <Button
@@ -106,6 +107,7 @@ export default function ShopEmployeesListComponent({ loading, employees }) {
loading={loading} loading={loading}
pagination={{ placement: "top" }} pagination={{ placement: "top" }}
columns={columns} columns={columns}
mobileColumnKeys={["employee_number", "employee_name", "active"]}
rowKey="id" rowKey="id"
dataSource={employees} dataSource={employees}
rowSelection={{ rowSelection={{

View File

@@ -1,7 +1,8 @@
import { Button, Table } from "antd"; import { Button } from "antd";
import queryString from "query-string"; import queryString from "query-string";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useLocation, useNavigate } from "react-router-dom"; import { useLocation, useNavigate } from "react-router-dom";
import ResponsiveTable from "../responsive-table/responsive-table.component";
export default function ShopEmployeeTeamsListComponent({ loading, employee_teams }) { export default function ShopEmployeeTeamsListComponent({ loading, employee_teams }) {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -27,7 +28,7 @@ export default function ShopEmployeeTeamsListComponent({ loading, employee_teams
return ( return (
<div> <div>
<Table <ResponsiveTable
title={() => { title={() => {
return ( return (
<Button <Button
@@ -44,6 +45,7 @@ export default function ShopEmployeeTeamsListComponent({ loading, employee_teams
loading={loading} loading={loading}
pagination={{ placement: "top" }} pagination={{ placement: "top" }}
columns={columns} columns={columns}
mobileColumnKeys={["name"]}
rowKey="id" rowKey="id"
dataSource={employee_teams} dataSource={employee_teams}
rowSelection={{ rowSelection={{

View File

@@ -1,5 +1,5 @@
import { useQuery } from "@apollo/client/react"; import { useQuery } from "@apollo/client/react";
import { Button, Table } from "antd"; import { Button } from "antd";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
@@ -7,6 +7,7 @@ import { QUERY_SHOP_ASSOCIATIONS } from "../../graphql/user.queries";
import { selectBodyshop } from "../../redux/user/user.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors";
import AlertComponent from "../alert/alert.component"; import AlertComponent from "../alert/alert.component";
import RbacWrapper from "../rbac-wrapper/rbac-wrapper.component"; import RbacWrapper from "../rbac-wrapper/rbac-wrapper.component";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import ShopUsersAuthEdit from "../shop-users-auth-edit/shop-users-auth-edit.component"; import ShopUsersAuthEdit from "../shop-users-auth-edit/shop-users-auth-edit.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
@@ -66,10 +67,11 @@ export function ShopInfoUsersComponent({ bodyshop }) {
} }
return ( return (
<div> <div>
<Table <ResponsiveTable
loading={loading} loading={loading}
pagination={{ placement: "top" }} pagination={{ placement: "top" }}
columns={columns} columns={columns}
mobileColumnKeys={["email", "authlevel", "actions"]}
rowKey="id" rowKey="id"
dataSource={data && data.associations} dataSource={data && data.associations}
/> />

View File

@@ -1,5 +1,5 @@
import { CarOutlined, SettingOutlined, SyncOutlined } from "@ant-design/icons"; import { CarOutlined, SettingOutlined, SyncOutlined } from "@ant-design/icons";
import { Button, Card, Input, Space, Table, Typography } from "antd"; import { Button, Card, Input, Space, Typography } from "antd";
import axios from "axios"; import axios from "axios";
import _ from "lodash"; import _ from "lodash";
import queryString from "query-string"; import queryString from "query-string";
@@ -20,6 +20,7 @@ import * as Sentry from "@sentry/react";
import getPartsBasePath from "../../utils/getPartsBasePath.js"; import getPartsBasePath from "../../utils/getPartsBasePath.js";
import { toggleDarkMode } from "../../redux/application/application.actions.js"; import { toggleDarkMode } from "../../redux/application/application.actions.js";
import { FaMoon, FaSun } from "react-icons/fa"; import { FaMoon, FaSun } from "react-icons/fa";
import ResponsiveTable from "../responsive-table/responsive-table.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
@@ -243,7 +244,7 @@ export function SimplifiedPartsJobsListComponent({
</Space> </Space>
} }
> >
<Table <ResponsiveTable
loading={loading || searchLoading} loading={loading || searchLoading}
pagination={ pagination={
search?.search search?.search
@@ -259,6 +260,7 @@ export function SimplifiedPartsJobsListComponent({
} }
} }
columns={columns} columns={columns}
mobileColumnKeys={["ro_number", "ownr_ln", "status", "vehicle", "partsstatus"]}
rowKey="id" rowKey="id"
dataSource={search?.search ? openSearchResults : jobs} dataSource={search?.search ? openSearchResults : jobs}
onChange={handleTableChange} onChange={handleTableChange}

View File

@@ -7,7 +7,7 @@ import {
PlusCircleFilled, PlusCircleFilled,
SyncOutlined SyncOutlined
} from "@ant-design/icons"; } from "@ant-design/icons";
import { Button, Card, Space, Switch, Table } from "antd"; import { Button, Card, Space, Switch } from "antd";
import queryString from "query-string"; import queryString from "query-string";
import { useCallback, useEffect } from "react"; import { useCallback, useEffect } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -20,6 +20,7 @@ import dayjs from "../../utils/day";
import ShareToTeamsButton from "../share-to-teams/share-to-teams.component.jsx"; import ShareToTeamsButton from "../share-to-teams/share-to-teams.component.jsx";
import PriorityLabel from "../../utils/tasksPriorityLabel.jsx"; import PriorityLabel from "../../utils/tasksPriorityLabel.jsx";
import { logImEXEvent } from "../../firebase/firebase.utils.js"; import { logImEXEvent } from "../../firebase/firebase.utils.js";
import ResponsiveTable from "../responsive-table/responsive-table.component";
/** /**
* Task List Component * Task List Component
@@ -345,7 +346,7 @@ function TaskListComponent({
return ( return (
<Card title={titleTranslation} extra={tasksExtra()}> <Card title={titleTranslation} extra={tasksExtra()}>
<Table <ResponsiveTable
loading={loading} loading={loading}
pagination={{ pagination={{
pageSize: pageLimit, pageSize: pageLimit,
@@ -355,8 +356,8 @@ function TaskListComponent({
showQuickJumper: true showQuickJumper: true
}} }}
columns={columns} columns={columns}
mobileColumnKeys={["title", "due_date", "priority", "toggleCompleted"]}
rowKey="id" rowKey="id"
scroll={{ x: true }}
dataSource={tasks} dataSource={tasks}
onChange={handleTableChange} onChange={handleTableChange}
expandable={{ expandable={{

View File

@@ -1,6 +1,6 @@
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { useQuery } from "@apollo/client/react"; import { useQuery } from "@apollo/client/react";
import { Button, Card, Input, Space, Table } from "antd"; import { Button, Card, Input, Space } from "antd";
import queryString from "query-string"; import queryString from "query-string";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -13,6 +13,7 @@ import { onlyUnique } from "../../utils/arrayHelper";
import { alphaSort } from "../../utils/sorters"; import { alphaSort } from "../../utils/sorters";
import AlertComponent from "../alert/alert.component"; import AlertComponent from "../alert/alert.component";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
import ResponsiveTable from "../responsive-table/responsive-table.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop bodyshop: selectBodyshop
@@ -170,10 +171,11 @@ export function TechLookupJobsList({ bodyshop }) {
</Space> </Space>
} }
> >
<Table <ResponsiveTable
loading={loading} loading={loading}
pagination={false} pagination={false}
columns={columns} columns={columns}
mobileColumnKeys={["ro_number", "owner", "status", "vehicle"]}
rowKey="id" rowKey="id"
dataSource={jobs} dataSource={jobs}
scroll={{ x: true }} scroll={{ x: true }}

View File

@@ -1,5 +1,6 @@
import { useQuery } from "@apollo/client/react"; import { useQuery } from "@apollo/client/react";
import { Button, Form, InputNumber, Modal, Radio, Select, Space, Table, Typography } from "antd"; import { Button, Form, InputNumber, Modal, Radio, Select, Space, Typography } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import Dinero from "dinero.js"; import Dinero from "dinero.js";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -98,7 +99,18 @@ export function TimeTicketListTeamPay({ bodyshop, context }) {
<Form.Item name="percent"> <Form.Item name="percent">
<Space.Compact> <Space.Compact>
<InputNumber min={0} max={100} precision={1} /> <InputNumber min={0} max={100} precision={1} />
<span style={{ padding: "0 11px", backgroundColor: "#fafafa", border: "1px solid #d9d9d9", borderLeft: 0, display: "flex", alignItems: "center" }}>%</span> <span
style={{
padding: "0 11px",
backgroundColor: "#fafafa",
border: "1px solid #d9d9d9",
borderLeft: 0,
display: "flex",
alignItems: "center"
}}
>
%
</span>
</Space.Compact> </Space.Compact>
</Form.Item> </Form.Item>
</LayoutFormRow> </LayoutFormRow>
@@ -134,7 +146,7 @@ export function TimeTicketListTeamPay({ bodyshop, context }) {
} }
return ( return (
<Table <ResponsiveTable
dataSource={data} dataSource={data}
rowKey={"employeeid"} rowKey={"employeeid"}
title={() => ( title={() => (
@@ -182,6 +194,7 @@ export function TimeTicketListTeamPay({ bodyshop, context }) {
key: "pay" key: "pay"
} }
]} ]}
mobileColumnKeys={["employee", "cost_center", "productivehrs", "pay"]}
/> />
); );
}} }}

View File

@@ -1,6 +1,7 @@
import { EditFilled, SyncOutlined } from "@ant-design/icons"; import { EditFilled, SyncOutlined } from "@ant-design/icons";
import { useTreatmentsWithConfig } from "@splitsoftware/splitio-react"; import { useTreatmentsWithConfig } from "@splitsoftware/splitio-react";
import { Button, Card, Checkbox, Space, Table } from "antd"; import { Button, Card, Checkbox, Space } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useMemo, useState } from "react"; import { useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
@@ -327,9 +328,10 @@ export function TimeTicketList({
</Space> </Space>
} }
> >
<Table <ResponsiveTable
loading={loading} loading={loading}
columns={columns} columns={columns}
mobileColumnKeys={["ro_number", "date", "actions", "committed_at"]}
rowKey="id" rowKey="id"
scroll={{ scroll={{
x: true x: true
@@ -340,23 +342,23 @@ export function TimeTicketList({
if (Enhanced_Payroll.treatment === "on") return null; if (Enhanced_Payroll.treatment === "on") return null;
if (Enhanced_Payroll.treatment === "off") if (Enhanced_Payroll.treatment === "off")
return ( return (
<Table.Summary.Row> <ResponsiveTable.Summary.Row>
<Table.Summary.Cell>{t("general.labels.totals")}</Table.Summary.Cell> <ResponsiveTable.Summary.Cell>{t("general.labels.totals")}</ResponsiveTable.Summary.Cell>
<Table.Summary.Cell /> <ResponsiveTable.Summary.Cell />
<Table.Summary.Cell /> <ResponsiveTable.Summary.Cell />
<Table.Summary.Cell>{totals.productivehrs.toFixed(1)}</Table.Summary.Cell> <ResponsiveTable.Summary.Cell>{totals.productivehrs.toFixed(1)}</ResponsiveTable.Summary.Cell>
<Table.Summary.Cell>{totals.actualhrs.toFixed(1)}</Table.Summary.Cell> <ResponsiveTable.Summary.Cell>{totals.actualhrs.toFixed(1)}</ResponsiveTable.Summary.Cell>
<Table.Summary.Cell> <ResponsiveTable.Summary.Cell>
{totals.actualhrs === 0 || !totals.actualhrs {totals.actualhrs === 0 || !totals.actualhrs
? "∞" ? "∞"
: `${((totals.productivehrs / totals.actualhrs) * 100).toFixed( : `${((totals.productivehrs / totals.actualhrs) * 100).toFixed(
2 2
)}% ${t("timetickets.labels.efficiency")}`} )}% ${t("timetickets.labels.efficiency")}`}
</Table.Summary.Cell> </ResponsiveTable.Summary.Cell>
<Table.Summary.Cell /> <ResponsiveTable.Summary.Cell />
<Table.Summary.Cell /> <ResponsiveTable.Summary.Cell />
<Table.Summary.Cell /> <ResponsiveTable.Summary.Cell />
</Table.Summary.Row> </ResponsiveTable.Summary.Row>
); );
}} }}
locale={{ locale={{

View File

@@ -1,4 +1,5 @@
import { Card, Col, Row, Table } from "antd"; import { Card, Col, Row } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import _ from "lodash"; import _ from "lodash";
import dayjs from "../../utils/day"; import dayjs from "../../utils/day";
import { useMemo, useState } from "react"; import { useMemo, useState } from "react";
@@ -213,12 +214,13 @@ const JobRelatedTicketsTable = ({ loading, jobTickets, startDate, endDate }) =>
return ( return (
<Card title={t("timetickets.labels.jobhours")}> <Card title={t("timetickets.labels.jobhours")}>
<Table <ResponsiveTable
loading={loading} loading={loading}
scroll={{ scroll={{
x: true // y: "50rem" x: true // y: "50rem"
}} }}
columns={columns} columns={columns}
mobileColumnKeys={["total", "actions", "empname", "actHrs"]}
rowKey="id" rowKey="id"
dataSource={data} dataSource={data}
onChange={handleTableChange} onChange={handleTableChange}
@@ -288,12 +290,13 @@ const ShiftRelatedTicketsTable = ({ loading, shiftTickets, startDate, endDate })
return ( return (
<Card title={t("timetickets.labels.clockhours")}> <Card title={t("timetickets.labels.clockhours")}>
<Table <ResponsiveTable
loading={loading} loading={loading}
scroll={{ scroll={{
x: true // y: "50rem" x: true // y: "50rem"
}} }}
columns={columns} columns={columns}
mobileColumnKeys={["total", "actions", "empname", "actHrs"]}
rowKey="id" rowKey="id"
dataSource={data} dataSource={data}
onChange={handleTableChange} onChange={handleTableChange}

View File

@@ -1,5 +1,6 @@
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { Button, Card, Space, Table, Tag } from "antd"; import { Button, Card, Space, Tag } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import Dinero from "dinero.js"; import Dinero from "dinero.js";
import queryString from "query-string"; import queryString from "query-string";
import { useState } from "react"; import { useState } from "react";
@@ -180,9 +181,10 @@ export function TtApprovalsListComponent({
</Space> </Space>
} }
> >
<Table <ResponsiveTable
loading={loading} loading={loading}
columns={columns} columns={columns}
mobileColumnKeys={["ro_number", "date", "employeeid", "cost_center"]}
rowKey="id" rowKey="id"
scroll={{ scroll={{
x: true x: true

View File

@@ -1,4 +1,4 @@
import { Card, Table } from "antd"; import { Card } from "antd";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
@@ -12,6 +12,7 @@ import OwnerNameDisplay, { OwnerNameDisplayFunction } from "../owner-name-displa
import VehicleDetailUpdateJobsComponent from "../vehicle-detail-update-jobs/vehicle-detail-update-jobs.component"; import VehicleDetailUpdateJobsComponent from "../vehicle-detail-update-jobs/vehicle-detail-update-jobs.component";
import { selectIsPartsEntry } from "../../redux/application/application.selectors"; import { selectIsPartsEntry } from "../../redux/application/application.selectors";
import getPartsBasePath from "../../utils/getPartsBasePath.js"; import getPartsBasePath from "../../utils/getPartsBasePath.js";
import ResponsiveTable from "../responsive-table/responsive-table.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
@@ -107,8 +108,9 @@ export function VehicleDetailJobsComponent({ vehicle, bodyshop, isPartsEntry })
/> />
} }
> >
<Table <ResponsiveTable
columns={columns} columns={columns}
mobileColumnKeys={["ro_number", "owner", "status", "actual_completion"]}
rowKey="id" rowKey="id"
scroll={{ x: true }} scroll={{ x: true }}
dataSource={vehicle.jobs} dataSource={vehicle.jobs}

View File

@@ -1,5 +1,5 @@
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { Button, Card, Input, Space, Table, Typography } from "antd"; import { Button, Card, Input, Space, Typography } from "antd";
import queryString from "query-string"; import queryString from "query-string";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -7,6 +7,7 @@ import { Link, useLocation, useNavigate } from "react-router-dom";
import VehicleVinDisplay from "../vehicle-vin-display/vehicle-vin-display.component"; import VehicleVinDisplay from "../vehicle-vin-display/vehicle-vin-display.component";
import { pageLimit } from "../../utils/config"; import { pageLimit } from "../../utils/config";
import { alphaSort } from "../../utils/sorters"; import { alphaSort } from "../../utils/sorters";
import ResponsiveTable from "../responsive-table/responsive-table.component";
export default function VehiclesListComponent({ loading, vehicles, total, refetch, basePath = "/manage" }) { export default function VehiclesListComponent({ loading, vehicles, total, refetch, basePath = "/manage" }) {
const search = queryString.parse(useLocation().search); const search = queryString.parse(useLocation().search);
@@ -103,10 +104,11 @@ export default function VehiclesListComponent({ loading, vehicles, total, refetc
</Space> </Space>
} }
> >
<Table <ResponsiveTable
loading={loading} loading={loading}
pagination={{ placement: "top", pageSize: pageLimit, current: parseInt(page || 1), total: total }} pagination={{ placement: "top", pageSize: pageLimit, current: parseInt(page || 1), total: total }}
columns={columns} columns={columns}
mobileColumnKeys={["v_vin", "description", "plate_no"]}
rowKey="id" rowKey="id"
scroll={{ x: true }} scroll={{ x: true }}
dataSource={vehicles} dataSource={vehicles}

View File

@@ -1,10 +1,11 @@
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { Button, Card, Input, Space, Table, Tag } from "antd"; import { Button, Card, Input, Space, Tag } from "antd";
import queryString from "query-string"; import queryString from "query-string";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useLocation } from "react-router-dom"; import { useLocation } from "react-router-dom";
import { alphaSort } from "../../utils/sorters"; import { alphaSort } from "../../utils/sorters";
import ResponsiveTable from "../responsive-table/responsive-table.component";
export default function VendorsListComponent({ handleNewVendor, loading, handleOnRowClick, vendors, refetch }) { export default function VendorsListComponent({ handleNewVendor, loading, handleOnRowClick, vendors, refetch }) {
const search = queryString.parse(useLocation().search); const search = queryString.parse(useLocation().search);
@@ -85,10 +86,11 @@ export default function VendorsListComponent({ handleNewVendor, loading, handleO
</Space> </Space>
} }
> >
<Table <ResponsiveTable
loading={loading} loading={loading}
pagination={{ placement: "top" }} pagination={{ placement: "top" }}
columns={columns} columns={columns}
mobileColumnKeys={["name", "phone", "city"]}
rowKey="id" rowKey="id"
onChange={handleTableChange} onChange={handleTableChange}
dataSource={filteredVendors} dataSource={filteredVendors}

View File

@@ -1,5 +1,5 @@
import { EditFilled, SyncOutlined } from "@ant-design/icons"; import { EditFilled, SyncOutlined } from "@ant-design/icons";
import { Button, Card, Checkbox, Input, Space, Table, Typography } from "antd"; import { Button, Card, Checkbox, Input, Space, Typography } from "antd";
import { useQuery } from "@apollo/client/react"; import { useQuery } from "@apollo/client/react";
import axios from "axios"; import axios from "axios";
import queryString from "query-string"; import queryString from "query-string";
@@ -18,6 +18,7 @@ import { pageLimit } from "../../utils/config";
import { alphaSort, dateSort } from "../../utils/sorters"; import { alphaSort, dateSort } from "../../utils/sorters";
import { QUERY_ALL_VENDORS } from "../../graphql/vendors.queries"; import { QUERY_ALL_VENDORS } from "../../graphql/vendors.queries";
import { logImEXEvent } from "../../firebase/firebase.utils"; import { logImEXEvent } from "../../firebase/firebase.utils";
import ResponsiveTable from "../../components/responsive-table/responsive-table.component";
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
setBillEnterContext: (context) => dispatch(setModalContext({ context: context, modal: "billEnter" })) setBillEnterContext: (context) => dispatch(setModalContext({ context: context, modal: "billEnter" }))
@@ -229,7 +230,7 @@ export function BillsListPage({ loading, data, refetch, total, setBillEnterConte
> >
<PartsOrderModalContainer /> <PartsOrderModalContainer />
<Table <ResponsiveTable
loading={loading || searchLoading} loading={loading || searchLoading}
// scroll={{ // scroll={{
// x: "50%", // y: "40rem" // x: "50%", // y: "40rem"
@@ -249,6 +250,7 @@ export function BillsListPage({ loading, data, refetch, total, setBillEnterConte
} }
} }
columns={columns} columns={columns}
mobileColumnKeys={["vendorname", "invoice_number", "ro_number", "total", "actions"]}
rowKey="id" rowKey="id"
dataSource={search?.search ? openSearchResults : data} dataSource={search?.search ? openSearchResults : data}
onChange={handleTableChange} onChange={handleTableChange}

View File

@@ -1,6 +1,6 @@
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { useQuery } from "@apollo/client/react"; import { useQuery } from "@apollo/client/react";
import { Button, Card, Checkbox, Input, Space, Table, Typography } from "antd"; import { Button, Card, Checkbox, Input, Space, Typography } from "antd";
import _ from "lodash"; import _ from "lodash";
import queryString from "query-string"; import queryString from "query-string";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -8,6 +8,7 @@ import { connect } from "react-redux";
import { Link, useLocation, useNavigate } from "react-router-dom"; import { Link, useLocation, useNavigate } from "react-router-dom";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import AlertComponent from "../../components/alert/alert.component"; import AlertComponent from "../../components/alert/alert.component";
import ResponsiveTable from "../../components/responsive-table/responsive-table.component";
import { QUERY_EXPORT_LOG_PAGINATED } from "../../graphql/accounting.queries"; import { QUERY_EXPORT_LOG_PAGINATED } from "../../graphql/accounting.queries";
import { DateTimeFormatter } from "../../utils/DateFormatter"; import { DateTimeFormatter } from "../../utils/DateFormatter";
import { pageLimit } from "../../utils/config"; import { pageLimit } from "../../utils/config";
@@ -186,7 +187,7 @@ export function ExportLogsPageComponent() {
</Space> </Space>
} }
> >
<Table <ResponsiveTable
loading={loading} loading={loading}
pagination={{ pagination={{
placement: "top", placement: "top",
@@ -195,6 +196,7 @@ export function ExportLogsPageComponent() {
total: data && data.search_exportlog_aggregate.aggregate.count total: data && data.search_exportlog_aggregate.aggregate.count
}} }}
columns={columns} columns={columns}
mobileColumnKeys={["created_at", "ro_number", "successful", "message"]}
rowKey="id" rowKey="id"
dataSource={data?.search_exportlog} dataSource={data?.search_exportlog}
style={{ height: "100%" }} style={{ height: "100%" }}

View File

@@ -1,6 +1,6 @@
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { useQuery } from "@apollo/client/react"; import { useQuery } from "@apollo/client/react";
import { Button, Card, Input, Space, Table, Typography } from "antd"; import { Button, Card, Input, Space, Typography } from "antd";
import _ from "lodash"; import _ from "lodash";
import queryString from "query-string"; import queryString from "query-string";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -8,6 +8,7 @@ import { connect } from "react-redux";
import { useLocation, useNavigate } from "react-router-dom"; import { useLocation, useNavigate } from "react-router-dom";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import AlertComponent from "../../components/alert/alert.component"; import AlertComponent from "../../components/alert/alert.component";
import ResponsiveTable from "../../components/responsive-table/responsive-table.component";
import { QUERY_PHONEBOOK_PAGINATED } from "../../graphql/phonebook.queries"; import { QUERY_PHONEBOOK_PAGINATED } from "../../graphql/phonebook.queries";
import { selectAuthLevel, selectBodyshop } from "../../redux/user/user.selectors"; import { selectAuthLevel, selectBodyshop } from "../../redux/user/user.selectors";
import ChatOpenButton from "../../components/chat-open-button/chat-open-button.component"; import ChatOpenButton from "../../components/chat-open-button/chat-open-button.component";
@@ -172,7 +173,7 @@ export function PhonebookPageComponent({ bodyshop, authLevel }) {
</Space> </Space>
} }
> >
<Table <ResponsiveTable
loading={loading} loading={loading}
pagination={{ pagination={{
placement: "top", placement: "top",
@@ -181,6 +182,7 @@ export function PhonebookPageComponent({ bodyshop, authLevel }) {
total: data && data.search_phonebook_aggregate.aggregate.count total: data && data.search_phonebook_aggregate.aggregate.count
}} }}
columns={columns} columns={columns}
mobileColumnKeys={["firstname", "lastname", "company", "phone1", "phone2"]}
rowKey="id" rowKey="id"
dataSource={data?.search_phonebook} dataSource={data?.search_phonebook}
//scroll={{ x: true }} //scroll={{ x: true }}

View File

@@ -1,6 +1,7 @@
import { useQuery } from "@apollo/client/react"; import { useQuery } from "@apollo/client/react";
import { useState } from "react"; import { useState } from "react";
import { Button, Card, Input, Space, Table } from "antd"; import { Button, Card, Input, Space } from "antd";
import ResponsiveTable from "../../components/responsive-table/responsive-table.component";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { QUERY_JOBS_TECH_ASIGNED_TO_BY_TEAM } from "../../graphql/jobs.queries"; import { QUERY_JOBS_TECH_ASIGNED_TO_BY_TEAM } from "../../graphql/jobs.queries";
@@ -188,10 +189,11 @@ export function TechAssignedProdJobs({ setTimeTicketTaskContext, technician, bod
</Space> </Space>
} }
> >
<Table <ResponsiveTable
loading={loading} loading={loading}
pagination={false} pagination={false}
columns={columns} columns={columns}
mobileColumnKeys={["ro_number", "owner", "status", "vehicle", "plate_no"]}
rowKey="id" rowKey="id"
dataSource={jobs} dataSource={jobs}
scroll={{ x: true }} scroll={{ x: true }}

View File

@@ -1,6 +1,7 @@
import { MinusCircleTwoTone, PlusCircleTwoTone, SyncOutlined } from "@ant-design/icons"; import { MinusCircleTwoTone, PlusCircleTwoTone, SyncOutlined } from "@ant-design/icons";
import { useQuery } from "@apollo/client/react"; import { useQuery } from "@apollo/client/react";
import { Button, Card, Space, Table } from "antd"; import { Button, Card, Space } from "antd";
import ResponsiveTable from "../../components/responsive-table/responsive-table.component";
import queryString from "query-string"; import queryString from "query-string";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
@@ -108,7 +109,7 @@ export function TechDispatchedParts({ technician, bodyshop }) {
</Space> </Space>
} }
> >
<Table <ResponsiveTable
loading={loading} loading={loading}
pagination={{ pagination={{
pageSize: 25, pageSize: 25,
@@ -117,6 +118,7 @@ export function TechDispatchedParts({ technician, bodyshop }) {
showSizeChanger: false showSizeChanger: false
}} }}
columns={columns} columns={columns}
mobileColumnKeys={["ro_number", "status", "vehicle", "actions"]}
rowKey="id" rowKey="id"
dataSource={parts_dispatch} dataSource={parts_dispatch}
scroll={{ x: true }} scroll={{ x: true }}