Refactor details grid component
This commit is contained in:
parent
9cab4c27f8
commit
8ca997f73b
|
|
@ -529,17 +529,19 @@ export function DetailsTableField({
|
|||
);
|
||||
}
|
||||
|
||||
export interface DetailsTableProps {
|
||||
item: any;
|
||||
fields: DetailsField[];
|
||||
title?: string;
|
||||
showIcons?: boolean;
|
||||
}
|
||||
|
||||
export function DetailsTable({
|
||||
item,
|
||||
fields,
|
||||
title,
|
||||
showIcons = true
|
||||
}: Readonly<{
|
||||
item: any;
|
||||
fields: DetailsField[];
|
||||
title?: string;
|
||||
showIcons?: boolean;
|
||||
}>) {
|
||||
}: Readonly<DetailsTableProps>) {
|
||||
const visibleFields = useMemo(() => {
|
||||
return fields.filter((field) => !field.hidden);
|
||||
}, [fields]);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,20 @@
|
|||
import { Paper, SimpleGrid } from '@mantine/core';
|
||||
import type React from 'react';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { DetailsTable, type DetailsTableProps } from './Details';
|
||||
|
||||
export type { DetailsTableProps };
|
||||
|
||||
export function ItemDetailsGrid({
|
||||
children,
|
||||
tables
|
||||
}: React.PropsWithChildren<{ tables?: DetailsTableProps[] }>) {
|
||||
const visibleTables = useMemo(
|
||||
() => tables?.filter((t) => t.fields.some((f) => !f.hidden)) ?? [],
|
||||
[tables]
|
||||
);
|
||||
|
||||
export function ItemDetailsGrid(props: React.PropsWithChildren<{}>) {
|
||||
return (
|
||||
<Paper p='xs'>
|
||||
<SimpleGrid
|
||||
|
|
@ -10,7 +23,10 @@ export function ItemDetailsGrid(props: React.PropsWithChildren<{}>) {
|
|||
spacing='xs'
|
||||
verticalSpacing='xs'
|
||||
>
|
||||
{props.children}
|
||||
{children}
|
||||
{visibleTables.map((props, index) => (
|
||||
<DetailsTable key={index} {...props} />
|
||||
))}
|
||||
</SimpleGrid>
|
||||
</Paper>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -5,15 +5,15 @@ import { t } from '@lingui/core/macro';
|
|||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useMemo } from 'react';
|
||||
import { useApi } from '../../contexts/ApiContext';
|
||||
import { type DetailsField, DetailsTable } from './Details';
|
||||
import type { DetailsField, DetailsTableProps } from './Details';
|
||||
|
||||
export function ParameterDetailsGrid({
|
||||
export function useParameterDetailsGrid({
|
||||
model_type,
|
||||
model_id
|
||||
}: Readonly<{
|
||||
model_type: ModelType;
|
||||
model_id: number | string | undefined;
|
||||
}>) {
|
||||
}>): DetailsTableProps {
|
||||
const api = useApi();
|
||||
|
||||
const { data: parameters = [] } = useQuery({
|
||||
|
|
@ -45,14 +45,10 @@ export function ParameterDetailsGrid({
|
|||
return { fields, item };
|
||||
}, [parameters]);
|
||||
|
||||
if (fields.length === 0) return null;
|
||||
|
||||
return (
|
||||
<DetailsTable
|
||||
title={t`Parameters`}
|
||||
fields={fields}
|
||||
item={item}
|
||||
showIcons={false}
|
||||
/>
|
||||
);
|
||||
return {
|
||||
title: t`Parameters`,
|
||||
fields: fields,
|
||||
item: item,
|
||||
showIcons: false
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { ModelType } from '@lib/enums/ModelType';
|
||||
import type { ReactNode } from 'react';
|
||||
import { PartPreviewComponent } from './models/PartPreview';
|
||||
import { PurchaseOrderPreviewComponent } from './models/PurchaseOrderPreview';
|
||||
import { StockPreviewComponent } from './models/StockPreview';
|
||||
|
||||
export interface PreviewType {
|
||||
|
|
@ -28,6 +29,8 @@ export function getPreviewComponentForModel({
|
|||
return PartPreviewComponent({ instance, modelId });
|
||||
case ModelType.stockitem:
|
||||
return StockPreviewComponent({ instance, modelId });
|
||||
case ModelType.purchaseorder:
|
||||
return PurchaseOrderPreviewComponent({ instance, modelId });
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -439,7 +439,13 @@ export default function BuildDetail() {
|
|||
];
|
||||
|
||||
return (
|
||||
<ItemDetailsGrid>
|
||||
<ItemDetailsGrid
|
||||
tables={[
|
||||
{ fields: tr, item: data },
|
||||
{ fields: bl, item: data },
|
||||
{ fields: br, item: data }
|
||||
]}
|
||||
>
|
||||
<Stack gap='xs'>
|
||||
<Grid grow>
|
||||
<DetailsImage
|
||||
|
|
@ -454,9 +460,6 @@ export default function BuildDetail() {
|
|||
</Grid>
|
||||
<TagsList tags={build.tags} />
|
||||
</Stack>
|
||||
<DetailsTable fields={tr} item={data} />
|
||||
<DetailsTable fields={bl} item={data} />
|
||||
<DetailsTable fields={br} item={data} />
|
||||
</ItemDetailsGrid>
|
||||
);
|
||||
}, [build, instanceQuery, partRequirements, partRequirementsQuery]);
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ export default function CompanyDetail(props: Readonly<CompanyDetailProps>) {
|
|||
];
|
||||
|
||||
return (
|
||||
<ItemDetailsGrid>
|
||||
<ItemDetailsGrid tables={[{ item: company, fields: tr }]}>
|
||||
<Stack gap='xs'>
|
||||
<Grid grow>
|
||||
<DetailsImage
|
||||
|
|
@ -176,7 +176,6 @@ export default function CompanyDetail(props: Readonly<CompanyDetailProps>) {
|
|||
</Grid>
|
||||
<TagsList tags={company.tags} />
|
||||
</Stack>
|
||||
<DetailsTable item={company} fields={tr} />
|
||||
</ItemDetailsGrid>
|
||||
);
|
||||
}, [company, instanceQuery]);
|
||||
|
|
|
|||
|
|
@ -134,7 +134,9 @@ export default function ManufacturerPartDetail() {
|
|||
];
|
||||
|
||||
return (
|
||||
<ItemDetailsGrid>
|
||||
<ItemDetailsGrid
|
||||
tables={[{ title: t`Manufacturer Details`, fields: tr, item: data }]}
|
||||
>
|
||||
<Stack gap='xs'>
|
||||
<Grid grow>
|
||||
<DetailsImage
|
||||
|
|
@ -152,7 +154,6 @@ export default function ManufacturerPartDetail() {
|
|||
</Grid>
|
||||
<TagsList tags={manufacturerPart.tags} />
|
||||
</Stack>
|
||||
<DetailsTable title={t`Manufacturer Details`} fields={tr} item={data} />
|
||||
</ItemDetailsGrid>
|
||||
);
|
||||
}, [manufacturerPart, instanceQuery]);
|
||||
|
|
|
|||
|
|
@ -222,7 +222,13 @@ export default function SupplierPartDetail() {
|
|||
];
|
||||
|
||||
return (
|
||||
<ItemDetailsGrid>
|
||||
<ItemDetailsGrid
|
||||
tables={[
|
||||
{ title: t`Supplier`, fields: bl, item: data },
|
||||
{ title: t`Packaging`, fields: br, item: data },
|
||||
{ title: t`Availability`, fields: tr, item: data }
|
||||
]}
|
||||
>
|
||||
<Stack gap='xs'>
|
||||
<Grid grow>
|
||||
<DetailsImage
|
||||
|
|
@ -240,9 +246,6 @@ export default function SupplierPartDetail() {
|
|||
</Grid>
|
||||
<TagsList tags={supplierPart.tags} />
|
||||
</Stack>
|
||||
<DetailsTable title={t`Supplier`} fields={bl} item={data} />
|
||||
<DetailsTable title={t`Packaging`} fields={br} item={data} />
|
||||
<DetailsTable title={t`Availability`} fields={tr} item={data} />
|
||||
</ItemDetailsGrid>
|
||||
);
|
||||
}, [supplierPart, instanceQuery.isFetching]);
|
||||
|
|
|
|||
|
|
@ -7,10 +7,7 @@ import { Paper, Skeleton, Stack } from '@mantine/core';
|
|||
import { IconInfoCircle } from '@tabler/icons-react';
|
||||
import { useMemo } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import {
|
||||
type DetailsField,
|
||||
DetailsTable
|
||||
} from '../../components/details/Details';
|
||||
import type { DetailsField } from '../../components/details/Details';
|
||||
import { ItemDetailsGrid } from '../../components/details/ItemDetails';
|
||||
import {} from '../../components/items/ActionDropdown';
|
||||
import { RoleTable, type RuleSet } from '../../components/items/RoleTable';
|
||||
|
|
@ -48,8 +45,9 @@ export default function GroupDetail() {
|
|||
];
|
||||
|
||||
return (
|
||||
<ItemDetailsGrid>
|
||||
<DetailsTable fields={tl} item={instance} title={t`Group Details`} />
|
||||
<ItemDetailsGrid
|
||||
tables={[{ fields: tl, item: instance, title: t`Group Details` }]}
|
||||
>
|
||||
<Paper p='xs' withBorder>
|
||||
<Stack gap='xs'>
|
||||
<StylishText size='lg'>{t`Group Roles`}</StylishText>
|
||||
|
|
|
|||
|
|
@ -6,10 +6,7 @@ import { Badge, Group, Skeleton, Stack } from '@mantine/core';
|
|||
import { IconInfoCircle } from '@tabler/icons-react';
|
||||
import { type ReactNode, useMemo } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import {
|
||||
type DetailsField,
|
||||
DetailsTable
|
||||
} from '../../components/details/Details';
|
||||
import type { DetailsField } from '../../components/details/Details';
|
||||
import { ItemDetailsGrid } from '../../components/details/ItemDetails';
|
||||
import {} from '../../components/items/ActionDropdown';
|
||||
import InstanceDetail from '../../components/nav/InstanceDetail';
|
||||
|
|
@ -171,13 +168,15 @@ export default function UserDetail() {
|
|||
instance.location;
|
||||
|
||||
return (
|
||||
<ItemDetailsGrid>
|
||||
<DetailsTable fields={tl} item={instance} title={t`User Information`} />
|
||||
<DetailsTable fields={tr} item={instance} title={t`User Permissions`} />
|
||||
{hasProfile && settings.isSet('DISPLAY_PROFILE_INFO') && (
|
||||
<DetailsTable fields={br} item={instance} title={t`User Profile`} />
|
||||
)}
|
||||
</ItemDetailsGrid>
|
||||
<ItemDetailsGrid
|
||||
tables={[
|
||||
{ fields: tl, item: instance, title: t`User Information` },
|
||||
{ fields: tr, item: instance, title: t`User Permissions` },
|
||||
...(hasProfile && settings.isSet('DISPLAY_PROFILE_INFO')
|
||||
? [{ fields: br, item: instance, title: t`User Profile` }]
|
||||
: [])
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}, [instance, userGroups, instanceQuery]);
|
||||
|
||||
|
|
|
|||
|
|
@ -20,10 +20,7 @@ import type { PanelType } from '@lib/types/Panel';
|
|||
import { useLocalStorage } from '@mantine/hooks';
|
||||
import AdminButton from '../../components/buttons/AdminButton';
|
||||
import StarredToggleButton from '../../components/buttons/StarredToggleButton';
|
||||
import {
|
||||
type DetailsField,
|
||||
DetailsTable
|
||||
} from '../../components/details/Details';
|
||||
import type { DetailsField } from '../../components/details/Details';
|
||||
import { ItemDetailsGrid } from '../../components/details/ItemDetails';
|
||||
import {
|
||||
DeleteItemAction,
|
||||
|
|
@ -169,10 +166,16 @@ export default function CategoryDetail() {
|
|||
];
|
||||
|
||||
return (
|
||||
<ItemDetailsGrid>
|
||||
{id && category?.pk && <DetailsTable item={category} fields={left} />}
|
||||
{id && category?.pk && <DetailsTable item={category} fields={right} />}
|
||||
</ItemDetailsGrid>
|
||||
<ItemDetailsGrid
|
||||
tables={
|
||||
id && category?.pk
|
||||
? [
|
||||
{ item: category, fields: left },
|
||||
{ item: category, fields: right }
|
||||
]
|
||||
: []
|
||||
}
|
||||
/>
|
||||
);
|
||||
}, [category, instanceQuery]);
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import {
|
|||
} from '../../components/details/Details';
|
||||
import { DetailsImage } from '../../components/details/DetailsImage';
|
||||
import { ItemDetailsGrid } from '../../components/details/ItemDetails';
|
||||
import { ParameterDetailsGrid } from '../../components/details/ParameterDetailsGrid';
|
||||
import { useParameterDetailsGrid } from '../../components/details/ParameterDetailsGrid';
|
||||
import { formatPriceRange } from '../../defaults/formatters';
|
||||
import { useInstance } from '../../hooks/UseInstance';
|
||||
|
||||
|
|
@ -322,10 +322,22 @@ export function PartDetailsPanel({
|
|||
return fields;
|
||||
}, [instance, data.latest_serial_number]);
|
||||
|
||||
const parametersTable = useParameterDetailsGrid({
|
||||
model_type: ModelType.part,
|
||||
model_id: instance?.pk
|
||||
});
|
||||
|
||||
if (!instance?.pk) return <Skeleton />;
|
||||
|
||||
return (
|
||||
<ItemDetailsGrid>
|
||||
<ItemDetailsGrid
|
||||
tables={[
|
||||
{ fields: tr, item: data },
|
||||
{ fields: bl, item: data },
|
||||
{ fields: br, item: data },
|
||||
parametersTable
|
||||
]}
|
||||
>
|
||||
<Stack gap='xs'>
|
||||
<Grid grow>
|
||||
<DetailsImage
|
||||
|
|
@ -353,13 +365,6 @@ export function PartDetailsPanel({
|
|||
<TagsList tags={instance.tags} />
|
||||
{additionalContent}
|
||||
</Stack>
|
||||
<DetailsTable fields={tr} item={data} />
|
||||
<DetailsTable fields={bl} item={data} />
|
||||
<DetailsTable fields={br} item={data} />
|
||||
<ParameterDetailsGrid
|
||||
model_type={ModelType.part}
|
||||
model_id={instance.pk}
|
||||
/>
|
||||
</ItemDetailsGrid>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -297,7 +297,13 @@ export default function ReturnOrderDetail() {
|
|||
];
|
||||
|
||||
return (
|
||||
<ItemDetailsGrid>
|
||||
<ItemDetailsGrid
|
||||
tables={[
|
||||
{ fields: tr, item: order },
|
||||
{ fields: bl, item: order },
|
||||
{ fields: br, item: order }
|
||||
]}
|
||||
>
|
||||
<Stack gap='xs'>
|
||||
<Grid grow>
|
||||
<DetailsImage
|
||||
|
|
@ -312,9 +318,6 @@ export default function ReturnOrderDetail() {
|
|||
</Grid>
|
||||
<TagsList tags={order.tags} />
|
||||
</Stack>
|
||||
<DetailsTable fields={tr} item={order} />
|
||||
<DetailsTable fields={bl} item={order} />
|
||||
<DetailsTable fields={br} item={order} />
|
||||
</ItemDetailsGrid>
|
||||
);
|
||||
}, [order, instanceQuery]);
|
||||
|
|
|
|||
|
|
@ -288,7 +288,13 @@ export default function SalesOrderDetail() {
|
|||
];
|
||||
|
||||
return (
|
||||
<ItemDetailsGrid>
|
||||
<ItemDetailsGrid
|
||||
tables={[
|
||||
{ fields: tr, item: order },
|
||||
{ fields: bl, item: order },
|
||||
{ fields: br, item: order }
|
||||
]}
|
||||
>
|
||||
<Stack gap='xs'>
|
||||
<Grid grow>
|
||||
<DetailsImage
|
||||
|
|
@ -303,9 +309,6 @@ export default function SalesOrderDetail() {
|
|||
</Grid>
|
||||
<TagsList tags={order.tags} />
|
||||
</Stack>
|
||||
<DetailsTable fields={tr} item={order} />
|
||||
<DetailsTable fields={bl} item={order} />
|
||||
<DetailsTable fields={br} item={order} />
|
||||
</ItemDetailsGrid>
|
||||
);
|
||||
}, [order, orderCurrency, instanceQuery]);
|
||||
|
|
|
|||
|
|
@ -222,7 +222,13 @@ export default function SalesOrderShipmentDetail() {
|
|||
|
||||
return (
|
||||
<>
|
||||
<ItemDetailsGrid>
|
||||
<ItemDetailsGrid
|
||||
tables={[
|
||||
{ fields: tr, item: data },
|
||||
{ fields: bl, item: data },
|
||||
{ fields: br, item: data }
|
||||
]}
|
||||
>
|
||||
<Stack gap='xs'>
|
||||
<Grid grow>
|
||||
<DetailsImage
|
||||
|
|
@ -243,9 +249,6 @@ export default function SalesOrderShipmentDetail() {
|
|||
</Grid>
|
||||
<TagsList tags={shipment.tags} />
|
||||
</Stack>
|
||||
<DetailsTable fields={tr} item={data} />
|
||||
<DetailsTable fields={bl} item={data} />
|
||||
<DetailsTable fields={br} item={data} />
|
||||
</ItemDetailsGrid>
|
||||
</>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -24,10 +24,7 @@ import { useBarcodeScanDialog } from '../../components/barcodes/BarcodeScanDialo
|
|||
import AdminButton from '../../components/buttons/AdminButton';
|
||||
import { PrintingActions } from '../../components/buttons/PrintingActions';
|
||||
import OrderCalendar from '../../components/calendar/OrderCalendar';
|
||||
import {
|
||||
type DetailsField,
|
||||
DetailsTable
|
||||
} from '../../components/details/Details';
|
||||
import type { DetailsField } from '../../components/details/Details';
|
||||
import { ItemDetailsGrid } from '../../components/details/ItemDetails';
|
||||
import {
|
||||
BarcodeActionDropdown,
|
||||
|
|
@ -185,10 +182,16 @@ export default function Stock() {
|
|||
];
|
||||
|
||||
return (
|
||||
<ItemDetailsGrid>
|
||||
{id && location?.pk && <DetailsTable item={location} fields={left} />}
|
||||
{id && location?.pk && <DetailsTable item={location} fields={right} />}
|
||||
</ItemDetailsGrid>
|
||||
<ItemDetailsGrid
|
||||
tables={
|
||||
id && location?.pk
|
||||
? [
|
||||
{ item: location, fields: left },
|
||||
{ item: location, fields: right }
|
||||
]
|
||||
: []
|
||||
}
|
||||
/>
|
||||
);
|
||||
}, [location, instanceQuery]);
|
||||
|
||||
|
|
|
|||
|
|
@ -377,7 +377,13 @@ export function StockDetailsPanel({
|
|||
return (
|
||||
<>
|
||||
{showSerialNav && findBySerialNumber.modal}
|
||||
<ItemDetailsGrid>
|
||||
<ItemDetailsGrid
|
||||
tables={[
|
||||
{ fields: tr, item: data },
|
||||
{ fields: bl, item: data },
|
||||
{ fields: br, item: data }
|
||||
]}
|
||||
>
|
||||
<Stack gap='xs'>
|
||||
<Grid grow>
|
||||
<DetailsImage
|
||||
|
|
@ -401,9 +407,6 @@ export function StockDetailsPanel({
|
|||
</Grid>
|
||||
<TagsList tags={instance?.tags} />
|
||||
</Stack>
|
||||
<DetailsTable fields={tr} item={data} />
|
||||
<DetailsTable fields={bl} item={data} />
|
||||
<DetailsTable fields={br} item={data} />
|
||||
</ItemDetailsGrid>
|
||||
</>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -234,7 +234,13 @@ export default function TransferOrderDetail() {
|
|||
];
|
||||
|
||||
return (
|
||||
<ItemDetailsGrid>
|
||||
<ItemDetailsGrid
|
||||
tables={[
|
||||
{ fields: tr, item: order },
|
||||
{ fields: bl, item: order },
|
||||
{ fields: br, item: order }
|
||||
]}
|
||||
>
|
||||
<Stack gap='xs'>
|
||||
<Grid grow>
|
||||
{/* TODO: what image do we show for a Transfer Order? */}
|
||||
|
|
@ -250,9 +256,6 @@ export default function TransferOrderDetail() {
|
|||
</Grid>
|
||||
<TagsList tags={order.tags} />
|
||||
</Stack>
|
||||
<DetailsTable fields={tr} item={order} />
|
||||
<DetailsTable fields={bl} item={order} />
|
||||
<DetailsTable fields={br} item={order} />
|
||||
</ItemDetailsGrid>
|
||||
);
|
||||
}, [order, instanceQuery]);
|
||||
|
|
|
|||
Loading…
Reference in New Issue