diff --git a/src/frontend/src/components/render/ModelType.tsx b/src/frontend/src/components/render/ModelType.tsx
index 11699d603f..ab66a71da9 100644
--- a/src/frontend/src/components/render/ModelType.tsx
+++ b/src/frontend/src/components/render/ModelType.tsx
@@ -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
},
diff --git a/src/frontend/src/components/tables/purchasing/ManufacturerPartTable.tsx b/src/frontend/src/components/tables/purchasing/ManufacturerPartTable.tsx
index 2b2d03c758..2982e2e8e9 100644
--- a/src/frontend/src/components/tables/purchasing/ManufacturerPartTable.tsx
+++ b/src/frontend/src/components/tables/purchasing/ManufacturerPartTable.tsx
@@ -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}/`);
+ }
+ }
}}
/>
);
diff --git a/src/frontend/src/components/tables/purchasing/SupplierPartTable.tsx b/src/frontend/src/components/tables/purchasing/SupplierPartTable.tsx
index c0b7272668..2e2bd7278b 100644
--- a/src/frontend/src/components/tables/purchasing/SupplierPartTable.tsx
+++ b/src/frontend/src/components/tables/purchasing/SupplierPartTable.tsx
@@ -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}/`);
+ }
+ }
}}
/>
>
diff --git a/src/frontend/src/enums/ApiEndpoints.tsx b/src/frontend/src/enums/ApiEndpoints.tsx
index 24388bec07..0dc5b5368c 100644
--- a/src/frontend/src/enums/ApiEndpoints.tsx
+++ b/src/frontend/src/enums/ApiEndpoints.tsx
@@ -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',
diff --git a/src/frontend/src/pages/company/CompanyDetail.tsx b/src/frontend/src/pages/company/CompanyDetail.tsx
index 38c4c27f93..65b08a8eef 100644
--- a/src/frontend/src/pages/company/CompanyDetail.tsx
+++ b/src/frontend/src/pages/company/CompanyDetail.tsx
@@ -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: ,
- hidden: !company?.is_manufacturer
+ hidden: !company?.is_manufacturer,
+ content: company?.pk && (
+
+ )
},
{
name: 'supplied-parts',
label: t`Supplied Parts`,
icon: ,
- hidden: !company?.is_supplier
+ hidden: !company?.is_supplier,
+ content: company?.pk && (
+
+ )
},
{
name: 'purchase-orders',
diff --git a/src/frontend/src/pages/company/ManufacturerPartDetail.tsx b/src/frontend/src/pages/company/ManufacturerPartDetail.tsx
new file mode 100644
index 0000000000..4be641aa3a
--- /dev/null
+++ b/src/frontend/src/pages/company/ManufacturerPartDetail.tsx
@@ -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:
+ },
+ {
+ name: 'parameters',
+ label: t`Parameters`,
+ icon:
+ },
+ {
+ name: 'suppliers',
+ label: t`Suppliers`,
+ icon: ,
+ content: manufacturerPart?.pk ? (
+
+ ) : (
+
+ )
+ },
+ {
+ name: 'attachments',
+ label: t`Attachments`,
+ icon: ,
+ content: (
+
+ )
+ }
+ ];
+ }, [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 (
+
+
+
+
+
+ );
+}
diff --git a/src/frontend/src/pages/company/SupplierPartDetail.tsx b/src/frontend/src/pages/company/SupplierPartDetail.tsx
new file mode 100644
index 0000000000..161dcffec2
--- /dev/null
+++ b/src/frontend/src/pages/company/SupplierPartDetail.tsx
@@ -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:
+ },
+ {
+ name: 'stock',
+ label: t`Received Stock`,
+ icon:
+ },
+ {
+ name: 'purchaseorders',
+ label: t`Purchase Orders`,
+ icon:
+ },
+ {
+ name: 'pricing',
+ label: t`Pricing`,
+ icon:
+ }
+ ];
+ }, []);
+
+ 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 (
+
+
+
+
+
+ );
+}
diff --git a/src/frontend/src/router.tsx b/src/frontend/src/router.tsx
index dd82991751..c376dab343 100644
--- a/src/frontend/src/router.tsx
+++ b/src/frontend/src/router.tsx
@@ -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 = (
} />
} />
} />
+ } />
} />
+ }
+ />
} />
diff --git a/src/frontend/src/states/ApiState.tsx b/src/frontend/src/states/ApiState.tsx
index 86e986dc74..6c17f8c98f 100644
--- a/src/frontend/src/states/ApiState.tsx
+++ b/src/frontend/src/states/ApiState.tsx
@@ -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: