[PUI] Add missing pages (#6326)

* Add placeholder page for SupplierPartDetail

- All empty at this stage

* Adds ManufacturerPartDetail page

* Further updates to supplierpart and manufacturerpart support

* Cleanup unused vars

* More cleanup
This commit is contained in:
Oliver 2024-01-24 09:39:37 +11:00 committed by GitHub
parent 76410ef68d
commit f07d8a7a80
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 222 additions and 6 deletions

View File

@ -36,7 +36,7 @@ export const ModelInformationDict: ModelDictory = {
label: t`Supplier Part`,
label_multiple: t`Supplier Parts`,
url_overview: '/supplierpart',
url_detail: '/supplierpart/:pk/',
url_detail: '/purchasing/supplier-part/:pk/',
cui_detail: '/supplier-part/:pk/',
api_endpoint: ApiPaths.supplier_part_list
},
@ -44,7 +44,7 @@ export const ModelInformationDict: ModelDictory = {
label: t`Manufacturer Part`,
label_multiple: t`Manufacturer Parts`,
url_overview: '/manufacturerpart',
url_detail: '/manufacturerpart/:pk/',
url_detail: '/purchasing/manufacturer-part/:pk/',
cui_detail: '/manufacturer-part/:pk/',
api_endpoint: ApiPaths.manufacturer_part_list
},

View File

@ -1,5 +1,6 @@
import { t } from '@lingui/macro';
import { ReactNode, useCallback, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { ApiPaths } from '../../../enums/ApiEndpoints';
import { UserRoles } from '../../../enums/Roles';
@ -23,6 +24,7 @@ export function ManufacturerPartTable({ params }: { params: any }): ReactNode {
const table = useTable('manufacturerparts');
const user = useUserState();
const navigate = useNavigate();
// Construct table columns for this table
const tableColumns: TableColumn[] = useMemo(() => {
@ -127,7 +129,12 @@ export function ManufacturerPartTable({ params }: { params: any }): ReactNode {
manufacturer_detail: true
},
rowActions: rowActions,
tableActions: tableActions
tableActions: tableActions,
onRowClick: (record: any) => {
if (record?.pk) {
navigate(`/purchasing/manufacturer-part/${record.pk}/`);
}
}
}}
/>
);

View File

@ -1,6 +1,7 @@
import { t } from '@lingui/macro';
import { Text } from '@mantine/core';
import { ReactNode, useCallback, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { ApiPaths } from '../../../enums/ApiEndpoints';
import { UserRoles } from '../../../enums/Roles';
@ -26,6 +27,7 @@ export function SupplierPartTable({ params }: { params: any }): ReactNode {
const table = useTable('supplierparts');
const user = useUserState();
const navigate = useNavigate();
// Construct table columns for this table
const tableColumns: TableColumn[] = useMemo(() => {
@ -229,7 +231,12 @@ export function SupplierPartTable({ params }: { params: any }): ReactNode {
manufacturer_detail: true
},
rowActions: rowActions,
tableActions: tableActions
tableActions: tableActions,
onRowClick: (record: any) => {
if (record?.pk) {
navigate(`/purchasing/supplier-part/${record.pk}/`);
}
}
}}
/>
</>

View File

@ -66,6 +66,7 @@ export enum ApiPaths {
company_attachment_list = 'api-company-attachment-list',
supplier_part_list = 'api-supplier-part-list',
manufacturer_part_list = 'api-manufacturer-part-list',
manufacturer_part_attachment_list = 'api-manufacturer-part-attachment-list',
address_list = 'api-address-list',
contact_list = 'api-contact-list',

View File

@ -30,7 +30,9 @@ import { PanelType } from '../../components/nav/PanelGroup';
import { AddressTable } from '../../components/tables/company/AddressTable';
import { ContactTable } from '../../components/tables/company/ContactTable';
import { AttachmentTable } from '../../components/tables/general/AttachmentTable';
import { ManufacturerPartTable } from '../../components/tables/purchasing/ManufacturerPartTable';
import { PurchaseOrderTable } from '../../components/tables/purchasing/PurchaseOrderTable';
import { SupplierPartTable } from '../../components/tables/purchasing/SupplierPartTable';
import { ReturnOrderTable } from '../../components/tables/sales/ReturnOrderTable';
import { SalesOrderTable } from '../../components/tables/sales/SalesOrderTable';
import { StockItemTable } from '../../components/tables/stock/StockItemTable';
@ -77,13 +79,19 @@ export default function CompanyDetail(props: CompanyDetailProps) {
name: 'manufactured-parts',
label: t`Manufactured Parts`,
icon: <IconBuildingFactory2 />,
hidden: !company?.is_manufacturer
hidden: !company?.is_manufacturer,
content: company?.pk && (
<ManufacturerPartTable params={{ manufacturer: company.pk }} />
)
},
{
name: 'supplied-parts',
label: t`Supplied Parts`,
icon: <IconBuildingWarehouse />,
hidden: !company?.is_supplier
hidden: !company?.is_supplier,
content: company?.pk && (
<SupplierPartTable params={{ supplier: company.pk }} />
)
},
{
name: 'purchase-orders',

View File

@ -0,0 +1,98 @@
import { t } from '@lingui/macro';
import { LoadingOverlay, Skeleton, Stack } from '@mantine/core';
import {
IconBuildingWarehouse,
IconInfoCircle,
IconList,
IconPaperclip
} from '@tabler/icons-react';
import { useMemo } from 'react';
import { useParams } from 'react-router-dom';
import { PageDetail } from '../../components/nav/PageDetail';
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
import { AttachmentTable } from '../../components/tables/general/AttachmentTable';
import { SupplierPartTable } from '../../components/tables/purchasing/SupplierPartTable';
import { ApiPaths } from '../../enums/ApiEndpoints';
import { useInstance } from '../../hooks/UseInstance';
export default function ManufacturerPartDetail() {
const { id } = useParams();
const { instance: manufacturerPart, instanceQuery } = useInstance({
endpoint: ApiPaths.manufacturer_part_list,
pk: id,
hasPrimaryKey: true,
params: {
part_detail: true,
manufacturer_detail: true
}
});
const panels: PanelType[] = useMemo(() => {
return [
{
name: 'details',
label: t`Details`,
icon: <IconInfoCircle />
},
{
name: 'parameters',
label: t`Parameters`,
icon: <IconList />
},
{
name: 'suppliers',
label: t`Suppliers`,
icon: <IconBuildingWarehouse />,
content: manufacturerPart?.pk ? (
<SupplierPartTable
params={{
manufacturer_part: manufacturerPart.pk
}}
/>
) : (
<Skeleton />
)
},
{
name: 'attachments',
label: t`Attachments`,
icon: <IconPaperclip />,
content: (
<AttachmentTable
endpoint={ApiPaths.manufacturer_part_attachment_list}
model="manufacturer_part"
pk={manufacturerPart?.pk}
/>
)
}
];
}, [manufacturerPart]);
const breadcrumbs = useMemo(() => {
return [
{
name: t`Purchasing`,
url: '/purchasing/'
},
{
name: manufacturerPart?.manufacturer_detail?.name ?? t`Manufacturer`,
url: `/company/manufacturer/${manufacturerPart?.manufacturer_detail?.id}/`
}
];
}, [manufacturerPart]);
return (
<Stack spacing="xs">
<LoadingOverlay visible={instanceQuery.isFetching} />
<PageDetail
title={t`ManufacturerPart`}
subtitle={`${manufacturerPart.MPN} - ${manufacturerPart.part_detail?.name}`}
breadcrumbs={breadcrumbs}
imageUrl={manufacturerPart?.part_detail?.thumbnail}
/>
<PanelGroup pageKey="manufacturerpart" panels={panels} />
</Stack>
);
}

View File

@ -0,0 +1,80 @@
import { t } from '@lingui/macro';
import { LoadingOverlay, Stack } from '@mantine/core';
import {
IconCurrencyDollar,
IconInfoCircle,
IconPackages,
IconShoppingCart
} from '@tabler/icons-react';
import { useMemo } from 'react';
import { useParams } from 'react-router-dom';
import { PageDetail } from '../../components/nav/PageDetail';
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
import { ApiPaths } from '../../enums/ApiEndpoints';
import { useInstance } from '../../hooks/UseInstance';
export default function SupplierPartDetail() {
const { id } = useParams();
const { instance: supplierPart, instanceQuery } = useInstance({
endpoint: ApiPaths.supplier_part_list,
pk: id,
hasPrimaryKey: true,
params: {
part_detail: true,
supplier_detail: true
}
});
const panels: PanelType[] = useMemo(() => {
return [
{
name: 'details',
label: t`Details`,
icon: <IconInfoCircle />
},
{
name: 'stock',
label: t`Received Stock`,
icon: <IconPackages />
},
{
name: 'purchaseorders',
label: t`Purchase Orders`,
icon: <IconShoppingCart />
},
{
name: 'pricing',
label: t`Pricing`,
icon: <IconCurrencyDollar />
}
];
}, []);
const breadcrumbs = useMemo(() => {
return [
{
name: t`Purchasing`,
url: '/purchasing/'
},
{
name: supplierPart?.supplier_detail?.name ?? t`Supplier`,
url: `/company/supplier/${supplierPart?.supplier_detail?.pk ?? ''}`
}
];
}, [supplierPart]);
return (
<Stack spacing="xs">
<LoadingOverlay visible={instanceQuery.isFetching} />
<PageDetail
title={t`Supplier Part`}
subtitle={`${supplierPart.SKU} - ${supplierPart?.part_detail?.name}`}
breadcrumbs={breadcrumbs}
imageUrl={supplierPart?.part_detail?.thumbnail}
/>
<PanelGroup pageKey="supplierpart" panels={panels} />
</Stack>
);
}

View File

@ -28,6 +28,14 @@ export const ManufacturerDetail = Loadable(
lazy(() => import('./pages/company/ManufacturerDetail'))
);
export const SupplierPartDetail = Loadable(
lazy(() => import('./pages/company/SupplierPartDetail'))
);
export const ManufacturerPartDetail = Loadable(
lazy(() => import('./pages/company/ManufacturerPartDetail'))
);
export const CategoryDetail = Loadable(
lazy(() => import('./pages/part/CategoryDetail'))
);
@ -137,7 +145,12 @@ export const routes = (
<Route path="index/*" element={<PurchasingIndex />} />
<Route path="purchase-order/:id/*" element={<PurchaseOrderDetail />} />
<Route path="supplier/:id/*" element={<SupplierDetail />} />
<Route path="supplier-part/:id/*" element={<SupplierPartDetail />} />
<Route path="manufacturer/:id/*" element={<ManufacturerDetail />} />
<Route
path="manufacturer-part/:id/*"
element={<ManufacturerPartDetail />}
/>
</Route>
<Route path="company/:id/*" element={<CompanyDetail />} />
<Route path="sales/">

View File

@ -181,6 +181,8 @@ export function apiEndpoint(path: ApiPaths): string {
return 'company/part/';
case ApiPaths.manufacturer_part_list:
return 'company/part/manufacturer/';
case ApiPaths.manufacturer_part_attachment_list:
return 'company/part/manufacturer/attachment/';
case ApiPaths.stock_item_list:
return 'stock/';
case ApiPaths.stock_tracking_list: