mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-28 11:36:44 +00:00
[PUI] Instance hook (#5564)
* Custom hook for fetching instance data from the server * Refactor pages to use new hookr * Allow useInstance hook to handle parameters
This commit is contained in:
parent
fe68598c1b
commit
ad8df52b73
58
src/frontend/src/hooks/UseInstance.tsx
Normal file
58
src/frontend/src/hooks/UseInstance.tsx
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
import { useCallback, useState } from 'react';
|
||||||
|
|
||||||
|
import { api } from '../App';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom hook for loading a single instance of an instance from the API
|
||||||
|
*
|
||||||
|
* - Queries the API for a single instance of an object, and returns the result.
|
||||||
|
* - Provides a callback function to refresh the instance
|
||||||
|
*
|
||||||
|
* To use this hook:
|
||||||
|
* const { instance, refreshInstance } = useInstance(url: string, pk: number)
|
||||||
|
*/
|
||||||
|
export function useInstance(
|
||||||
|
url: string,
|
||||||
|
pk: string | undefined,
|
||||||
|
params: any = {}
|
||||||
|
) {
|
||||||
|
const [instance, setInstance] = useState<any>({});
|
||||||
|
|
||||||
|
const instanceQuery = useQuery({
|
||||||
|
queryKey: ['instance', url, pk, params],
|
||||||
|
enabled: pk != null && pk != undefined && pk.length > 0,
|
||||||
|
queryFn: async () => {
|
||||||
|
return api
|
||||||
|
.get(url + pk + '/', {
|
||||||
|
params: params
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
switch (response.status) {
|
||||||
|
case 200:
|
||||||
|
setInstance(response.data);
|
||||||
|
return response.data;
|
||||||
|
default:
|
||||||
|
setInstance({});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
setInstance({});
|
||||||
|
console.error(`Error fetching instance ${url}${pk}:`, error);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
refetchOnMount: false,
|
||||||
|
refetchOnWindowFocus: false
|
||||||
|
});
|
||||||
|
|
||||||
|
const refreshInstance = useCallback(
|
||||||
|
function () {
|
||||||
|
instanceQuery.refetch();
|
||||||
|
},
|
||||||
|
[instanceQuery]
|
||||||
|
);
|
||||||
|
|
||||||
|
return { instance, refreshInstance, instanceQuery };
|
||||||
|
}
|
@ -26,6 +26,7 @@ import { AttachmentTable } from '../../components/tables/AttachmentTable';
|
|||||||
import { BuildOrderTable } from '../../components/tables/build/BuildOrderTable';
|
import { BuildOrderTable } from '../../components/tables/build/BuildOrderTable';
|
||||||
import { StockItemTable } from '../../components/tables/stock/StockItemTable';
|
import { StockItemTable } from '../../components/tables/stock/StockItemTable';
|
||||||
import { NotesEditor } from '../../components/widgets/MarkdownEditor';
|
import { NotesEditor } from '../../components/widgets/MarkdownEditor';
|
||||||
|
import { useInstance } from '../../hooks/UseInstance';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detail page for a single Build Order
|
* Detail page for a single Build Order
|
||||||
@ -33,30 +34,12 @@ import { NotesEditor } from '../../components/widgets/MarkdownEditor';
|
|||||||
export default function BuildDetail() {
|
export default function BuildDetail() {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
|
|
||||||
// Build data
|
const {
|
||||||
const [build, setBuild] = useState<any>({});
|
instance: build,
|
||||||
|
refreshInstance,
|
||||||
useEffect(() => {
|
instanceQuery
|
||||||
setBuild({});
|
} = useInstance('/build/', id, {
|
||||||
}, [id]);
|
part_detail: true
|
||||||
|
|
||||||
// Query hook for fetching build data
|
|
||||||
const buildQuery = useQuery(['build', id ?? -1], async () => {
|
|
||||||
let url = `/build/${id}/`;
|
|
||||||
|
|
||||||
return api
|
|
||||||
.get(url, {
|
|
||||||
params: {
|
|
||||||
part_detail: true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((response) => {
|
|
||||||
setBuild(response.data);
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error(error);
|
|
||||||
setBuild({});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const buildPanels: PanelType[] = useMemo(() => {
|
const buildPanels: PanelType[] = useMemo(() => {
|
||||||
@ -162,7 +145,7 @@ export default function BuildDetail() {
|
|||||||
]}
|
]}
|
||||||
actions={[<PlaceholderPill key="1" />]}
|
actions={[<PlaceholderPill key="1" />]}
|
||||||
/>
|
/>
|
||||||
<LoadingOverlay visible={buildQuery.isFetching} />
|
<LoadingOverlay visible={instanceQuery.isFetching} />
|
||||||
<PanelGroup panels={buildPanels} />
|
<PanelGroup panels={buildPanels} />
|
||||||
</Stack>
|
</Stack>
|
||||||
</>
|
</>
|
||||||
|
@ -15,6 +15,7 @@ import { PageDetail } from '../../components/nav/PageDetail';
|
|||||||
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
|
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
|
||||||
import { PartCategoryTable } from '../../components/tables/part/PartCategoryTable';
|
import { PartCategoryTable } from '../../components/tables/part/PartCategoryTable';
|
||||||
import { PartListTable } from '../../components/tables/part/PartTable';
|
import { PartListTable } from '../../components/tables/part/PartTable';
|
||||||
|
import { useInstance } from '../../hooks/UseInstance';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detail view for a single PartCategory instance.
|
* Detail view for a single PartCategory instance.
|
||||||
@ -24,27 +25,10 @@ import { PartListTable } from '../../components/tables/part/PartTable';
|
|||||||
export default function CategoryDetail({}: {}) {
|
export default function CategoryDetail({}: {}) {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
|
|
||||||
const [category, setCategory] = useState<any>({});
|
const { instance: category, refreshInstance } = useInstance(
|
||||||
|
'/part/category/',
|
||||||
useEffect(() => {
|
id
|
||||||
setCategory({});
|
);
|
||||||
}, [id]);
|
|
||||||
|
|
||||||
const categoryQuery = useQuery({
|
|
||||||
enabled: id != null && id != undefined,
|
|
||||||
queryKey: ['category', id],
|
|
||||||
queryFn: async () => {
|
|
||||||
return api
|
|
||||||
.get(`/part/category/${id}/`)
|
|
||||||
.then((response) => {
|
|
||||||
setCategory(response.data);
|
|
||||||
return response.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error('Error fetching category data:', error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const categoryPanels: PanelType[] = useMemo(
|
const categoryPanels: PanelType[] = useMemo(
|
||||||
() => [
|
() => [
|
||||||
@ -90,7 +74,7 @@ export default function CategoryDetail({}: {}) {
|
|||||||
title={t`Part Category`}
|
title={t`Part Category`}
|
||||||
detail={<Text>{category.name ?? 'Top level'}</Text>}
|
detail={<Text>{category.name ?? 'Top level'}</Text>}
|
||||||
breadcrumbs={
|
breadcrumbs={
|
||||||
id
|
category.pk
|
||||||
? [
|
? [
|
||||||
{ name: t`Parts`, url: '/part' },
|
{ name: t`Parts`, url: '/part' },
|
||||||
{ name: '...', url: '' },
|
{ name: '...', url: '' },
|
||||||
|
@ -1,13 +1,5 @@
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import {
|
import { Alert, Button, LoadingOverlay, Stack, Text } from '@mantine/core';
|
||||||
Alert,
|
|
||||||
Button,
|
|
||||||
Group,
|
|
||||||
LoadingOverlay,
|
|
||||||
Space,
|
|
||||||
Stack,
|
|
||||||
Text
|
|
||||||
} from '@mantine/core';
|
|
||||||
import {
|
import {
|
||||||
IconBuilding,
|
IconBuilding,
|
||||||
IconCurrencyDollar,
|
IconCurrencyDollar,
|
||||||
@ -41,6 +33,7 @@ import {
|
|||||||
NotesEditor
|
NotesEditor
|
||||||
} from '../../components/widgets/MarkdownEditor';
|
} from '../../components/widgets/MarkdownEditor';
|
||||||
import { editPart } from '../../functions/forms/PartForms';
|
import { editPart } from '../../functions/forms/PartForms';
|
||||||
|
import { useInstance } from '../../hooks/UseInstance';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detail view for a single Part instance
|
* Detail view for a single Part instance
|
||||||
@ -48,12 +41,11 @@ import { editPart } from '../../functions/forms/PartForms';
|
|||||||
export default function PartDetail() {
|
export default function PartDetail() {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
|
|
||||||
// Part data
|
const {
|
||||||
const [part, setPart] = useState<any>({});
|
instance: part,
|
||||||
|
refreshInstance,
|
||||||
useEffect(() => {
|
instanceQuery
|
||||||
setPart({});
|
} = useInstance('/part/', id);
|
||||||
}, [id]);
|
|
||||||
|
|
||||||
// Part data panels (recalculate when part data changes)
|
// Part data panels (recalculate when part data changes)
|
||||||
const partPanels: PanelType[] = useMemo(() => {
|
const partPanels: PanelType[] = useMemo(() => {
|
||||||
@ -153,22 +145,6 @@ export default function PartDetail() {
|
|||||||
];
|
];
|
||||||
}, [part]);
|
}, [part]);
|
||||||
|
|
||||||
// Query hook for fetching part data
|
|
||||||
const partQuery = useQuery(['part', id], async () => {
|
|
||||||
let url = `/part/${id}/`;
|
|
||||||
|
|
||||||
return api
|
|
||||||
.get(url)
|
|
||||||
.then((response) => {
|
|
||||||
setPart(response.data);
|
|
||||||
return response.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
setPart({});
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
function partAttachmentsTab(): React.ReactNode {
|
function partAttachmentsTab(): React.ReactNode {
|
||||||
return (
|
return (
|
||||||
<AttachmentTable
|
<AttachmentTable
|
||||||
@ -226,9 +202,7 @@ export default function PartDetail() {
|
|||||||
part.pk &&
|
part.pk &&
|
||||||
editPart({
|
editPart({
|
||||||
part_id: part.pk,
|
part_id: part.pk,
|
||||||
callback: () => {
|
callback: refreshInstance
|
||||||
partQuery.refetch();
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
@ -236,7 +210,7 @@ export default function PartDetail() {
|
|||||||
</Button>
|
</Button>
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<LoadingOverlay visible={partQuery.isFetching} />
|
<LoadingOverlay visible={instanceQuery.isFetching} />
|
||||||
<PanelGroup panels={partPanels} />
|
<PanelGroup panels={partPanels} />
|
||||||
</Stack>
|
</Stack>
|
||||||
</>
|
</>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user