Updates
This commit is contained in:
parent
b84bdac78f
commit
ff7e4d4f3b
|
|
@ -7,7 +7,11 @@ import { ModelInformationDict } from '@lib/enums/ModelInformation';
|
|||
import type { ModelType } from '@lib/enums/ModelType';
|
||||
import type { UserRoles } from '@lib/enums/Roles';
|
||||
import { apiUrl } from '@lib/functions/Api';
|
||||
import { getDetailUrl, navigateToLink } from '@lib/functions/Navigation';
|
||||
import {
|
||||
eventModified,
|
||||
getDetailUrl,
|
||||
navigateToLink
|
||||
} from '@lib/functions/Navigation';
|
||||
import type { TableFilter } from '@lib/types/Filters';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { ActionIcon, Group, Text } from '@mantine/core';
|
||||
|
|
@ -171,7 +175,7 @@ export default function OrderCalendar({
|
|||
const onClickOrder = (info: EventClickArg) => {
|
||||
if (!info.event.id) return;
|
||||
|
||||
if (info.jsEvent.ctrlKey || info.jsEvent.metaKey || info.jsEvent.shiftKey) {
|
||||
if (eventModified(event as any)) {
|
||||
navigateToLink(
|
||||
getDetailUrl(model, info.event.id),
|
||||
navigate,
|
||||
|
|
|
|||
|
|
@ -28,10 +28,10 @@ export function AttributeGrid({
|
|||
<Table.Tbody>
|
||||
{valid.map((item) => (
|
||||
<Table.Tr key={item.label}>
|
||||
<Table.Td w='50%' fw='bold'>
|
||||
<Table.Td w='30%' fw='bold'>
|
||||
{item.label}
|
||||
</Table.Td>
|
||||
<Table.Td w='50%'>{item.value}</Table.Td>
|
||||
<Table.Td w='70%'>{item.value}</Table.Td>
|
||||
</Table.Tr>
|
||||
))}
|
||||
</Table.Tbody>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,20 @@
|
|||
import { Anchor, Divider, Drawer, LoadingOverlay, Stack } from '@mantine/core';
|
||||
import {
|
||||
ActionIcon,
|
||||
Anchor,
|
||||
Divider,
|
||||
Drawer,
|
||||
Group,
|
||||
LoadingOverlay,
|
||||
Stack,
|
||||
Tooltip
|
||||
} from '@mantine/core';
|
||||
|
||||
import { StylishText } from '@lib/components/StylishText';
|
||||
import { ModelInformationDict } from '@lib/enums/ModelInformation';
|
||||
import { eventModified } from '@lib/functions/Navigation';
|
||||
import { type ModelType, getDetailUrl, navigateToLink } from '@lib/index';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { IconArrowRight } from '@tabler/icons-react';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useInstance } from '../../hooks/UseInstance';
|
||||
|
|
@ -73,7 +85,9 @@ export default function PreviewDrawer({
|
|||
(event: MouseEvent) => {
|
||||
if (!modelType || !id) return;
|
||||
|
||||
onClose();
|
||||
if (!eventModified(event as any)) {
|
||||
onClose();
|
||||
}
|
||||
navigateToLink(getDetailUrl(modelType!, id!), navigate, event);
|
||||
},
|
||||
[modelType, id, navigate]
|
||||
|
|
@ -90,7 +104,14 @@ export default function PreviewDrawer({
|
|||
href={getDetailUrl(modelType!, id, true)}
|
||||
onClick={(e) => clickTitle(e)}
|
||||
>
|
||||
<StylishText size='lg'>{previewComponent.title}</StylishText>
|
||||
<Group gap='xs'>
|
||||
<Tooltip label={t`View Details`} position='left'>
|
||||
<ActionIcon variant='transparent' size='lg'>
|
||||
<IconArrowRight />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
<StylishText size='lg'>{previewComponent.title}</StylishText>
|
||||
</Group>
|
||||
</Anchor>
|
||||
) : (
|
||||
<StylishText size='lg'>{previewComponent.title}</StylishText>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,12 @@ import {
|
|||
import { t } from '@lingui/core/macro';
|
||||
import { Group, Stack, Text } from '@mantine/core';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useMemo } from 'react';
|
||||
import { useApi } from '../../../contexts/ApiContext';
|
||||
import { formatDate } from '../../../defaults/formatters';
|
||||
import { formatDate, formatPriceRange } from '../../../defaults/formatters';
|
||||
import { useInstance } from '../../../hooks/UseInstance';
|
||||
import { ApiImage } from '../../images/ApiImage';
|
||||
import { RenderPartCategory } from '../../render/Part';
|
||||
import { RenderRemoteInstance } from '../../render/Instance';
|
||||
import { RenderUser } from '../../render/User';
|
||||
import { AttributeGrid, type AttributeRow } from '../AttributeGrid';
|
||||
import type { PreviewType } from '../PreviewType';
|
||||
|
|
@ -20,13 +21,11 @@ import type { PreviewType } from '../PreviewType';
|
|||
function PartPreviewContent({ instance }: Readonly<{ instance: any }>) {
|
||||
const api = useApi();
|
||||
|
||||
// Fetch part requirements
|
||||
const { instance: requirements } = useInstance({
|
||||
endpoint: ApiEndpoints.part_requirements,
|
||||
pk: instance?.pk,
|
||||
hasPrimaryKey: true,
|
||||
disabled: !instance?.pk,
|
||||
params: {},
|
||||
defaultValue: {}
|
||||
});
|
||||
|
||||
|
|
@ -45,49 +44,45 @@ function PartPreviewContent({ instance }: Readonly<{ instance: any }>) {
|
|||
.then((res) => res.data?.results ?? [])
|
||||
});
|
||||
|
||||
const totalStock = requirements?.total_stock ?? instance?.total_in_stock ?? 0;
|
||||
const availableStock =
|
||||
requirements?.unallocated_stock ?? instance?.unallocated_stock ?? 0;
|
||||
const minStock = instance?.minimum_stock ?? 0;
|
||||
const ordering = requirements?.ordering ?? 0;
|
||||
const isPurchaseable = instance?.purchaseable ?? false;
|
||||
const units = instance?.units ? ` ${instance.units}` : '';
|
||||
|
||||
const category = instance?.category_detail;
|
||||
const stockItems: AttributeRow[] = useMemo(() => {
|
||||
const totalStock =
|
||||
requirements?.total_stock ?? instance?.total_in_stock ?? 0;
|
||||
const availableStock =
|
||||
requirements?.unallocated_stock ?? instance?.unallocated_stock ?? 0;
|
||||
const minStock = instance?.minimum_stock ?? 0;
|
||||
const ordering = requirements?.ordering ?? 0;
|
||||
const canBuild = requirements?.can_build ?? 0;
|
||||
const building = requirements?.building ?? 0;
|
||||
|
||||
const stockItems: AttributeRow[] = !instance?.virtual
|
||||
? [
|
||||
{
|
||||
label: t`In Stock`,
|
||||
value:
|
||||
formatDecimal(totalStock) +
|
||||
(instance?.units ? ` ${instance.units}` : '')
|
||||
},
|
||||
availableStock !== totalStock
|
||||
? {
|
||||
label: t`Available`,
|
||||
value:
|
||||
formatDecimal(availableStock) +
|
||||
(instance?.units ? ` ${instance.units}` : '')
|
||||
}
|
||||
: null,
|
||||
minStock > 0
|
||||
? {
|
||||
label: t`Minimum`,
|
||||
value:
|
||||
formatDecimal(minStock) +
|
||||
(instance?.units ? ` ${instance.units}` : '')
|
||||
}
|
||||
: null,
|
||||
isPurchaseable && ordering > 0
|
||||
? {
|
||||
label: t`On Order`,
|
||||
value:
|
||||
formatDecimal(ordering) +
|
||||
(instance?.units ? ` ${instance.units}` : '')
|
||||
}
|
||||
: null
|
||||
].filter((x): x is NonNullable<typeof x> => x !== null)
|
||||
: [];
|
||||
return !instance?.virtual
|
||||
? [
|
||||
{
|
||||
label: t`In Stock`,
|
||||
value: formatDecimal(totalStock) + units
|
||||
},
|
||||
availableStock !== totalStock
|
||||
? {
|
||||
label: t`Available`,
|
||||
value: formatDecimal(availableStock) + units
|
||||
}
|
||||
: null,
|
||||
minStock > 0
|
||||
? { label: t`Minimum`, value: formatDecimal(minStock) + units }
|
||||
: null,
|
||||
instance?.purchaseable && ordering > 0
|
||||
? { label: t`On Order`, value: formatDecimal(ordering) + units }
|
||||
: null,
|
||||
instance?.assembly && canBuild >= 0
|
||||
? { label: t`Can Build`, value: formatDecimal(canBuild) }
|
||||
: null,
|
||||
building > 0
|
||||
? { label: t`In Production`, value: formatDecimal(building) }
|
||||
: null
|
||||
].filter((x): x is NonNullable<typeof x> => x !== null)
|
||||
: [];
|
||||
}, [requirements, instance, units]);
|
||||
|
||||
const parameterItems: AttributeRow[] = parameters.map((param: any) => ({
|
||||
label: param.template_detail?.name,
|
||||
|
|
@ -96,28 +91,64 @@ function PartPreviewContent({ instance }: Readonly<{ instance: any }>) {
|
|||
(param.template_detail?.units ? ` ${param.template_detail.units}` : '')
|
||||
}));
|
||||
|
||||
const infoItems: AttributeRow[] = [
|
||||
{
|
||||
label: t`Category`,
|
||||
value: instance?.category_detail
|
||||
? RenderPartCategory({ instance: instance.category_detail, link: true })
|
||||
: null
|
||||
},
|
||||
{
|
||||
label: t`Creation Date`,
|
||||
value: instance?.creation_date ? formatDate(instance.creation_date) : null
|
||||
},
|
||||
{
|
||||
label: t`Created By`,
|
||||
value: instance?.creation_user_detail
|
||||
? RenderUser({ instance: instance.creation_user_detail })
|
||||
: null
|
||||
}
|
||||
];
|
||||
const infoItems: AttributeRow[] = useMemo(() => {
|
||||
const priceRange = formatPriceRange(
|
||||
instance?.pricing_min,
|
||||
instance?.pricing_max
|
||||
);
|
||||
|
||||
return [
|
||||
{
|
||||
label: t`Category`,
|
||||
value: instance?.category ? (
|
||||
<RenderRemoteInstance
|
||||
model={ModelType.partcategory}
|
||||
pk={instance.category}
|
||||
/>
|
||||
) : null
|
||||
},
|
||||
{
|
||||
label: t`Revision Of`,
|
||||
value: instance?.revision_of ? (
|
||||
<RenderRemoteInstance
|
||||
model={ModelType.part}
|
||||
pk={instance.revision_of}
|
||||
/>
|
||||
) : null
|
||||
},
|
||||
{
|
||||
label: t`Variant Of`,
|
||||
value: instance?.variant_of ? (
|
||||
<RenderRemoteInstance
|
||||
model={ModelType.part}
|
||||
pk={instance.variant_of}
|
||||
/>
|
||||
) : null
|
||||
},
|
||||
{
|
||||
label: t`Price Range`,
|
||||
value:
|
||||
instance?.pricing_min != null || instance?.pricing_max != null
|
||||
? priceRange
|
||||
: null
|
||||
},
|
||||
{
|
||||
label: t`Creation Date`,
|
||||
value: instance?.creation_date
|
||||
? formatDate(instance.creation_date)
|
||||
: null
|
||||
},
|
||||
{
|
||||
label: t`Created By`,
|
||||
value: instance?.creation_user_detail
|
||||
? RenderUser({ instance: instance.creation_user_detail })
|
||||
: null
|
||||
}
|
||||
];
|
||||
}, [instance]);
|
||||
|
||||
return (
|
||||
<Stack gap='md'>
|
||||
{/* Headline: image + name / description / IPN / category */}
|
||||
<Group align='flex-start' gap='md'>
|
||||
<ApiImage
|
||||
src={
|
||||
|
|
@ -149,12 +180,22 @@ function PartPreviewContent({ instance }: Readonly<{ instance: any }>) {
|
|||
</Text>
|
||||
</Group>
|
||||
)}
|
||||
{category && (
|
||||
{instance?.revision && (
|
||||
<Group gap='xs'>
|
||||
<Text size='xs' c='dimmed'>
|
||||
{t`Revision`}:
|
||||
</Text>
|
||||
<Text size='xs' fw={500}>
|
||||
{instance.revision}
|
||||
</Text>
|
||||
</Group>
|
||||
)}
|
||||
{instance?.category_name && (
|
||||
<Group gap='xs'>
|
||||
<Text size='xs' c='dimmed'>
|
||||
{t`Category`}:
|
||||
</Text>
|
||||
<Text size='xs'>{category.pathstring ?? category.name}</Text>
|
||||
<Text size='xs'>{instance?.category_name}</Text>
|
||||
</Group>
|
||||
)}
|
||||
</Stack>
|
||||
|
|
|
|||
Loading…
Reference in New Issue