feat: printing attributes in cards on dashboard

This commit is contained in:
2025-03-14 11:33:00 +04:00
parent ca80920af6
commit 3e66d6300b
7 changed files with 66 additions and 22 deletions

View File

@@ -7,6 +7,7 @@ export type AttributeSchema = {
label: string;
name: string;
isApplicableToGroup: boolean;
isShownOnDashboard: boolean;
isNullable: boolean;
defaultValue: (boolean | number | string | null);
typeId: number;

View File

@@ -6,6 +6,7 @@ export type BaseAttributeSchema = {
label: string;
name: string;
isApplicableToGroup: boolean;
isShownOnDashboard: boolean;
isNullable: boolean;
defaultValue: (boolean | number | string | null);
typeId: number;

View File

@@ -4,6 +4,7 @@
/* eslint-disable */
import type { BaseMarketplaceSchema } from './BaseMarketplaceSchema';
import type { BoardSchema } from './BoardSchema';
import type { CardAttributeSchema } from './CardAttributeSchema';
import type { CardBillRequestSchema } from './CardBillRequestSchema';
import type { CardGroupSchema } from './CardGroupSchema';
import type { CardTagSchema } from './CardTagSchema';
@@ -20,6 +21,7 @@ export type CardSummary = {
baseMarketplace?: (BaseMarketplaceSchema | null);
totalProducts: number;
tags: Array<CardTagSchema>;
attributes: Array<CardAttributeSchema>;
shipmentWarehouseId: (number | null);
shipmentWarehouseName: (string | null);
billRequest?: (CardBillRequestSchema | null);

View File

@@ -1,5 +1,5 @@
import { FC } from "react";
import { CardService, CardSummary } from "../../../../client";
import { CardAttributeSchema, CardService, CardSummary } from "../../../../client";
import styles from "./CardSummaryItem.module.css";
import { ActionIcon, Badge, CopyButton, Flex, Image, Popover, rem, Text, ThemeIcon, Tooltip } from "@mantine/core";
@@ -12,6 +12,7 @@ import useCardSummaryState from "./useCardSummaryState.tsx";
import isModuleInProject, { Modules } from "../../../../modules/utils/isModuleInProject.ts";
import { useProjectsContext } from "../../../../contexts/ProjectsContext.tsx";
import CardTags from "../CardTags/CardTags.tsx";
import { formatDate, formatDateTime } from "../../../../types/utils.ts";
type Props = {
cardSummary: CardSummary;
@@ -38,6 +39,40 @@ const CardSummaryItem: FC<Props> = ({ cardSummary, color }) => {
const isLockedInsideGroup = () => {
return cardSummary.group && !cardSummary.group.billRequest;
};
const attributeValues = () => {
return (
<Flex direction={"column"}>
{cardSummary.attributes
.filter(cardAttr => cardAttr.attribute.isShownOnDashboard && cardAttr.value !== null)
.map(cardAttr => (
<Text c={"gray.6"} size={"sm"}>
{cardAttr.attribute.label}: {getAttrValueValue(cardAttr)}
</Text>
))
}
</Flex>
);
};
const getAttrValueValue = (cardAttr: CardAttributeSchema) => {
const value = cardAttr.value;
if (value === null) return;
const type = cardAttr.attribute.type.type;
if (type === "datetime") {
return formatDateTime(value as string);
}
if (type === "date") {
return formatDate(value as string);
}
if (type === "bool") {
return value ? "да" : "нет";
}
return value;
};
return (
<div
onContextMenu={showContextMenu([
@@ -101,8 +136,9 @@ const CardSummaryItem: FC<Props> = ({ cardSummary, color }) => {
</Text>
</Flex>
)}
{attributeValues()}
{!cardSummary.group?.id && (
<CardTags cardId={cardSummary.id} tags={cardSummary.tags}/>
<CardTags cardId={cardSummary.id} tags={cardSummary.tags} />
)}
<Flex align={"center"} justify={"space-between"}>
<Flex align={"center"} gap={rem(5)}>

View File

@@ -47,6 +47,15 @@ const useAttributesTableColumns = () => {
<IconX />
),
},
{
header: "Вывод на дашборде",
accessorKey: "isShownOnDashboard",
Cell: ({ cell }) => cell.getValue() ? (
<IconCheck />
) : (
<IconX />
),
},
{
header: "Может быть пустым",
accessorKey: "isNullable",

View File

@@ -33,6 +33,7 @@ const AttributeModal = ({
name: "",
type: undefined,
isApplicableToGroup: false,
isShownOnDashboard: false,
isNullable: false,
defaultValue: null,
description: "",
@@ -143,6 +144,10 @@ const AttributeModal = ({
label={"Значение синхронизировано в группе"}
{...form.getInputProps("isApplicableToGroup", { type: "checkbox" })}
/>
<Checkbox
label={"Значение выводится на дашборде"}
{...form.getInputProps("isShownOnDashboard", { type: "checkbox" })}
/>
{isNullableInputShown && (
<Checkbox
label={"Может быть пустым"}

View File

@@ -41,26 +41,6 @@ const useAttributesTableColumns = ({ selectedAttributes }: Props) => {
accessorKey: "type.name",
size: 120,
},
// {
// header: " ",
// Cell: ({ row }) => {
// const description = row.original.description ? `Описание: ${row.original.description}` : "";
// const info = (
// <Box>
// <Text>Может быть пустым: {row.original.isNullable ? "да" : "нет"}</Text>
// <Text>{defaultValueToStr(row.original.defaultValue, row.original.type.type)}</Text>
// <Text>Синхронизировано в группе: {row.original.isApplicableToGroup ? "да" : "нет"}</Text>
// <Text>{description}</Text>
// </Box>
// );
// return (
// <Tooltip label={info} multiline w={rem(300)}>
// <IconInfoCircle />
// </Tooltip>
// );
// },
// size: 5,
// },
{
header: "Значение по умолчанию",
accessorKey: "defaultValue",
@@ -93,6 +73,16 @@ const useAttributesTableColumns = ({ selectedAttributes }: Props) => {
),
size: 120,
},
{
header: "Вывод на дашборде",
accessorKey: "isShownOnDashboard",
Cell: ({ cell }) => cell.getValue() ? (
<IconCheck />
) : (
<IconX />
),
size: 130,
},
{
header: "Может быть пустым",
accessorKey: "isNullable",