From b674fc980db300a5ee1180f8aeced3a5204d531e Mon Sep 17 00:00:00 2001 From: Oliver Date: Fri, 1 Mar 2024 01:37:35 +0000 Subject: [PATCH] Implement CompanyDetails page --- src/frontend/src/functions/icons.tsx | 11 ++- .../src/pages/company/CompanyDetail.tsx | 94 ++++++++++++++++++- src/frontend/src/tables/Details.tsx | 19 +++- 3 files changed, 120 insertions(+), 4 deletions(-) diff --git a/src/frontend/src/functions/icons.tsx b/src/frontend/src/functions/icons.tsx index 712a9fa850..d702110dac 100644 --- a/src/frontend/src/functions/icons.tsx +++ b/src/frontend/src/functions/icons.tsx @@ -5,6 +5,7 @@ import { IconBox, IconBuilding, IconBuildingFactory2, + IconBuildingStore, IconCalendar, IconCalendarStats, IconCheck, @@ -22,6 +23,7 @@ import { IconLink, IconList, IconListTree, + IconMail, IconMapPin, IconMapPinHeart, IconNotes, @@ -30,6 +32,7 @@ import { IconPackageImport, IconPackages, IconPaperclip, + IconPhone, IconPhoto, IconProgressCheck, IconQuestionMark, @@ -49,6 +52,7 @@ import { IconUserStar, IconUsersGroup, IconVersions, + IconWorld, IconWorldCode, IconX } from '@tabler/icons-react'; @@ -87,6 +91,7 @@ const icons: { [key: string]: (props: TablerIconsProps) => React.JSX.Element } = used_in: IconStack2, manufacturers: IconBuildingFactory2, suppliers: IconBuilding, + customers: IconBuildingStore, purchase_orders: IconShoppingCart, sales_orders: IconTruckDelivery, scheduling: IconCalendarStats, @@ -121,6 +126,7 @@ const icons: { [key: string]: (props: TablerIconsProps) => React.JSX.Element } = link: IconLink, responsible: IconUserStar, pricing: IconCurrencyDollar, + currency: IconCurrencyDollar, stocktake: IconClipboardList, user: IconUser, group: IconUsersGroup, @@ -128,7 +134,10 @@ const icons: { [key: string]: (props: TablerIconsProps) => React.JSX.Element } = copy: IconCopy, quantity: IconNumbers, progress: IconProgressCheck, - reference: IconHash + reference: IconHash, + website: IconWorld, + email: IconMail, + phone: IconPhone }; /** diff --git a/src/frontend/src/pages/company/CompanyDetail.tsx b/src/frontend/src/pages/company/CompanyDetail.tsx index 6728cb1caf..d4f9e81c28 100644 --- a/src/frontend/src/pages/company/CompanyDetail.tsx +++ b/src/frontend/src/pages/company/CompanyDetail.tsx @@ -1,5 +1,5 @@ import { t } from '@lingui/macro'; -import { LoadingOverlay, Skeleton, Stack } from '@mantine/core'; +import { Grid, LoadingOverlay, Skeleton, Stack } from '@mantine/core'; import { IconBuildingFactory2, IconBuildingWarehouse, @@ -18,6 +18,8 @@ import { import { useMemo } from 'react'; import { useParams } from 'react-router-dom'; +import { DetailsImage } from '../../components/details/DetailsImage'; +import { ItemDetailsGrid } from '../../components/details/ItemDetails'; import { ActionDropdown, DeleteItemAction, @@ -35,6 +37,7 @@ import { useEditApiFormModal } from '../../hooks/UseForm'; import { useInstance } from '../../hooks/UseInstance'; import { apiUrl } from '../../states/ApiState'; import { useUserState } from '../../states/UserState'; +import { DetailsField, DetailsTable } from '../../tables/Details'; import { AddressTable } from '../../tables/company/AddressTable'; import { ContactTable } from '../../tables/company/ContactTable'; import { AttachmentTable } from '../../tables/general/AttachmentTable'; @@ -69,12 +72,99 @@ export default function CompanyDetail(props: CompanyDetailProps) { refetchOnMount: true }); + const detailsPanel = useMemo(() => { + if (instanceQuery.isFetching) { + return ; + } + + let tl: DetailsField[] = [ + { + type: 'text', + name: 'description', + label: t`Description` + }, + { + type: 'link', + name: 'website', + label: t`Website`, + external: true, + copy: true, + hidden: !company.website + }, + { + type: 'text', + name: 'phone', + label: t`Phone Number`, + copy: true, + hidden: !company.phone + }, + { + type: 'text', + name: 'email', + label: t`Email Address`, + copy: true, + hidden: !company.email + } + ]; + + let tr: DetailsField[] = [ + { + type: 'string', + name: 'currency', + label: t`Default Currency` + }, + { + type: 'boolean', + name: 'is_supplier', + label: t`Supplier`, + icon: 'suppliers' + }, + { + type: 'boolean', + name: 'is_manufacturer', + label: t`Manufacturer`, + icon: 'manufacturers' + }, + { + type: 'boolean', + name: 'is_customer', + label: t`Customer`, + icon: 'customers' + } + ]; + + return ( + + + + + + + + + + + + ); + }, [company, instanceQuery]); + const companyPanels: PanelType[] = useMemo(() => { return [ { name: 'details', label: t`Details`, - icon: + icon: , + content: detailsPanel }, { name: 'manufactured-parts', diff --git a/src/frontend/src/tables/Details.tsx b/src/frontend/src/tables/Details.tsx index 58932c979f..80ae1316c5 100644 --- a/src/frontend/src/tables/Details.tsx +++ b/src/frontend/src/tables/Details.tsx @@ -16,6 +16,7 @@ import { Suspense, useMemo } from 'react'; import { api } from '../App'; import { ProgressBar } from '../components/items/ProgressBar'; +import { YesNoButton } from '../components/items/YesNoButton'; import { getModelInfo } from '../components/render/ModelType'; import { StatusRenderer } from '../components/render/StatusRenderer'; import { ApiEndpoints } from '../enums/ApiEndpoints'; @@ -45,7 +46,13 @@ export type DetailsField = badge?: BadgeType; copy?: boolean; value_formatter?: () => ValueFormatterReturn; - } & (StringDetailField | LinkDetailField | ProgressBarfield | StatusField); + } & ( + | StringDetailField + | BooleanField + | LinkDetailField + | ProgressBarfield + | StatusField + ); type BadgeType = 'owner' | 'user' | 'group'; type ValueFormatterReturn = string | number | null; @@ -55,6 +62,10 @@ type StringDetailField = { unit?: boolean; }; +type BooleanField = { + type: 'boolean'; +}; + type LinkDetailField = { type: 'link'; } & (InternalLinkField | ExternalLinkField); @@ -288,6 +299,10 @@ function TableStringValue(props: FieldProps) { ); } +function BooleanValue(props: FieldProps) { + return ; +} + function TableAnchorValue(props: FieldProps) { if (props.field_data.external) { return ( @@ -404,6 +419,8 @@ export function DetailsTableField({ case 'text': case 'string': return TableStringValue; + case 'boolean': + return BooleanValue; case 'link': return TableAnchorValue; case 'progressbar':