mirror of
https://github.com/makeplane/plane.git
synced 2026-07-12 13:29:56 +02:00
feat: added UI for customer properties CRUD (#2443)
This commit is contained in:
@@ -912,6 +912,31 @@
|
||||
},
|
||||
"customers": {
|
||||
"label": "{count, plural, one {Customer} other {Customers}}",
|
||||
"properties": {
|
||||
"default": {
|
||||
"title": "Default Properties",
|
||||
"customer_name": "Customer Name",
|
||||
"description": "Description",
|
||||
"email": "Email",
|
||||
"website_url": "Website URL",
|
||||
"employees": "Employees",
|
||||
"domain": "Domain",
|
||||
"stage": "Stage",
|
||||
"contract_status": "Contract Status",
|
||||
"revenue": "Revenue"
|
||||
},
|
||||
"custom": {
|
||||
"title": "Custom Properties",
|
||||
"info": "Customize your customer properties here. Choose from different property types to aggregate your customers data."
|
||||
},
|
||||
"empty_state": {
|
||||
"title": "Add custom properties",
|
||||
"description": "New properties you add for the customer will show here"
|
||||
},
|
||||
"add": {
|
||||
"primary_button": "Add new property"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"unauthorized": "You are not authorized to access this page.",
|
||||
"description": "Track and manage customer relationships in your workflow.",
|
||||
|
||||
@@ -919,6 +919,31 @@
|
||||
},
|
||||
"customers": {
|
||||
"label": "{count, plural, one {Cliente} other {Clientes}}",
|
||||
"properties": {
|
||||
"default": {
|
||||
"title": "Propiedades predeterminadas",
|
||||
"customer_name": "Nombre del cliente",
|
||||
"description": "Descripción",
|
||||
"email": "Correo electrónico",
|
||||
"website_url": "URL del sitio web",
|
||||
"employees": "Empleados",
|
||||
"domain": "Dominio",
|
||||
"stage": "Etapa",
|
||||
"contract_status": "Estado del contrato",
|
||||
"revenue": "Ingresos"
|
||||
},
|
||||
"custom": {
|
||||
"title": "Propiedades personalizadas",
|
||||
"info": "Personaliza las propiedades de tus clientes aquí. Elige entre diferentes tipos de propiedades para agregar los datos de tus clientes."
|
||||
},
|
||||
"empty_state": {
|
||||
"title": "Agregar propiedades personalizadas",
|
||||
"description": "Las nuevas propiedades que agregues para el cliente se mostrarán aquí"
|
||||
},
|
||||
"add": {
|
||||
"primary_button": "Agregar nueva propiedad"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"unauthorized": "No está autorizado para acceder a esta página.",
|
||||
"description": "Realice seguimiento y gestione las relaciones con los clientes en su flujo de trabajo.",
|
||||
|
||||
@@ -919,6 +919,31 @@
|
||||
},
|
||||
"customers": {
|
||||
"label": "{count, plural, one {Client} other {Clients}}",
|
||||
"properties": {
|
||||
"default": {
|
||||
"title": "Propriétés par défaut",
|
||||
"customer_name": "Nom du client",
|
||||
"description": "Description",
|
||||
"email": "Email",
|
||||
"website_url": "URL du site web",
|
||||
"employees": "Employés",
|
||||
"domain": "Domaine",
|
||||
"stage": "Étape",
|
||||
"contract_status": "Statut du contrat",
|
||||
"revenue": "Revenus"
|
||||
},
|
||||
"custom": {
|
||||
"title": "Propriétés personnalisées",
|
||||
"info": "Personnalisez vos propriétés client ici. Choisissez parmi différents types de propriétés pour agréger les données de vos clients."
|
||||
},
|
||||
"empty_state": {
|
||||
"title": "Ajouter des propriétés personnalisées",
|
||||
"description": "Les nouvelles propriétés que vous ajoutez pour le client apparaîtront ici"
|
||||
},
|
||||
"add": {
|
||||
"primary_button": "Ajouter une nouvelle propriété"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"unauthorized": "Vous n'êtes pas autorisé à accéder à cette page.",
|
||||
"description": "Suivez et gérez les relations clients dans votre flux de travail.",
|
||||
|
||||
@@ -919,6 +919,31 @@
|
||||
},
|
||||
"customers": {
|
||||
"label": "{count, plural, one {顧客} other {顧客}}",
|
||||
"properties": {
|
||||
"default": {
|
||||
"title": "デフォルトプロパティ",
|
||||
"customer_name": "顧客名",
|
||||
"description": "説明",
|
||||
"email": "メール",
|
||||
"website_url": "ウェブサイトURL",
|
||||
"employees": "従業員数",
|
||||
"domain": "ドメイン",
|
||||
"stage": "ステージ",
|
||||
"contract_status": "契約状況",
|
||||
"revenue": "収益"
|
||||
},
|
||||
"custom": {
|
||||
"title": "カスタムプロパティ",
|
||||
"info": "ここで顧客プロパティをカスタマイズできます。異なるプロパティタイプから選択して、顧客データを集計します。"
|
||||
},
|
||||
"empty_state": {
|
||||
"title": "カスタムプロパティを追加",
|
||||
"description": "顧客に追加した新しいプロパティがここに表示されます"
|
||||
},
|
||||
"add": {
|
||||
"primary_button": "新しいプロパティを追加"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"unauthorized": "このページにアクセスする権限がありません。",
|
||||
"description": "ワークフローで顧客関係を追跡および管理します。",
|
||||
|
||||
@@ -919,6 +919,31 @@
|
||||
},
|
||||
"customers": {
|
||||
"label": "{count, plural, one {客户} other {客户}}",
|
||||
"properties": {
|
||||
"default": {
|
||||
"title": "默认属性",
|
||||
"customer_name": "客户名称",
|
||||
"description": "描述",
|
||||
"email": "电子邮件",
|
||||
"website_url": "网站链接",
|
||||
"employees": "员工数",
|
||||
"domain": "域名",
|
||||
"stage": "阶段",
|
||||
"contract_status": "合同状态",
|
||||
"revenue": "收入"
|
||||
},
|
||||
"custom": {
|
||||
"title": "自定义属性",
|
||||
"info": "在此处自定义您的客户属性。从不同的属性类型中选择以汇总您的客户数据。"
|
||||
},
|
||||
"empty_state": {
|
||||
"title": "添加自定义属性",
|
||||
"description": "您为客户添加的新属性将显示在此处"
|
||||
},
|
||||
"add": {
|
||||
"primary_button": "添加新属性"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"unauthorized": "您无权访问此页面。",
|
||||
"description": "在工作流程中跟踪和管理客户关系。",
|
||||
|
||||
14
packages/ui/src/icons/buildings-icon.tsx
Normal file
14
packages/ui/src/icons/buildings-icon.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import * as React from "react";
|
||||
|
||||
import { ISvgIcons } from "./type";
|
||||
|
||||
export const BuildingsIcon: React.FC<ISvgIcons> = ({ className = "text-current", ...rest }) => (
|
||||
<svg width="21" height="20" viewBox="0 0 21 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M1.5 0.25C1.30109 0.25 1.11032 0.329018 0.96967 0.46967C0.829018 0.610322 0.75 0.801088 0.75 1C0.75 1.19891 0.829018 1.38968 0.96967 1.53033C1.11032 1.67098 1.30109 1.75 1.5 1.75V18.25H0.75C0.551088 18.25 0.360322 18.329 0.21967 18.4697C0.0790177 18.6103 0 18.8011 0 19C0 19.1989 0.0790177 19.3897 0.21967 19.5303C0.360322 19.671 0.551088 19.75 0.75 19.75H13.5V1.75C13.6989 1.75 13.8897 1.67098 14.0303 1.53033C14.171 1.38968 14.25 1.19891 14.25 1C14.25 0.801088 14.171 0.610322 14.0303 0.46967C13.8897 0.329018 13.6989 0.25 13.5 0.25H1.5ZM5.25 17.5V15.25C5.25 15.0511 5.32902 14.8603 5.46967 14.7197C5.61032 14.579 5.80109 14.5 6 14.5H9C9.19891 14.5 9.38968 14.579 9.53033 14.7197C9.67098 14.8603 9.75 15.0511 9.75 15.25V17.5C9.75 17.6989 9.67098 17.8897 9.53033 18.0303C9.38968 18.171 9.19891 18.25 9 18.25H6C5.80109 18.25 5.61032 18.171 5.46967 18.0303C5.32902 17.8897 5.25 17.6989 5.25 17.5ZM4.5 4.75C4.5 4.55109 4.57902 4.36032 4.71967 4.21967C4.86032 4.07902 5.05109 4 5.25 4H6C6.19891 4 6.38968 4.07902 6.53033 4.21967C6.67098 4.36032 6.75 4.55109 6.75 4.75C6.75 4.94891 6.67098 5.13968 6.53033 5.28033C6.38968 5.42098 6.19891 5.5 6 5.5H5.25C5.05109 5.5 4.86032 5.42098 4.71967 5.28033C4.57902 5.13968 4.5 4.94891 4.5 4.75ZM5.25 7C5.05109 7 4.86032 7.07902 4.71967 7.21967C4.57902 7.36032 4.5 7.55109 4.5 7.75C4.5 7.94891 4.57902 8.13968 4.71967 8.28033C4.86032 8.42098 5.05109 8.5 5.25 8.5H6C6.19891 8.5 6.38968 8.42098 6.53033 8.28033C6.67098 8.13968 6.75 7.94891 6.75 7.75C6.75 7.55109 6.67098 7.36032 6.53033 7.21967C6.38968 7.07902 6.19891 7 6 7H5.25ZM4.5 10.75C4.5 10.5511 4.57902 10.3603 4.71967 10.2197C4.86032 10.079 5.05109 10 5.25 10H6C6.19891 10 6.38968 10.079 6.53033 10.2197C6.67098 10.3603 6.75 10.5511 6.75 10.75C6.75 10.9489 6.67098 11.1397 6.53033 11.2803C6.38968 11.421 6.19891 11.5 6 11.5H5.25C5.05109 11.5 4.86032 11.421 4.71967 11.2803C4.57902 11.1397 4.5 10.9489 4.5 10.75ZM9 4C8.80109 4 8.61032 4.07902 8.46967 4.21967C8.32902 4.36032 8.25 4.55109 8.25 4.75C8.25 4.94891 8.32902 5.13968 8.46967 5.28033C8.61032 5.42098 8.80109 5.5 9 5.5H9.75C9.94891 5.5 10.1397 5.42098 10.2803 5.28033C10.421 5.13968 10.5 4.94891 10.5 4.75C10.5 4.55109 10.421 4.36032 10.2803 4.21967C10.1397 4.07902 9.94891 4 9.75 4H9ZM8.25 7.75C8.25 7.55109 8.32902 7.36032 8.46967 7.21967C8.61032 7.07902 8.80109 7 9 7H9.75C9.94891 7 10.1397 7.07902 10.2803 7.21967C10.421 7.36032 10.5 7.55109 10.5 7.75C10.5 7.94891 10.421 8.13968 10.2803 8.28033C10.1397 8.42098 9.94891 8.5 9.75 8.5H9C8.80109 8.5 8.61032 8.42098 8.46967 8.28033C8.32902 8.13968 8.25 7.94891 8.25 7.75ZM9 10C8.80109 10 8.61032 10.079 8.46967 10.2197C8.32902 10.3603 8.25 10.5511 8.25 10.75C8.25 10.9489 8.32902 11.1397 8.46967 11.2803C8.61032 11.421 8.80109 11.5 9 11.5H9.75C9.94891 11.5 10.1397 11.421 10.2803 11.2803C10.421 11.1397 10.5 10.9489 10.5 10.75C10.5 10.5511 10.421 10.3603 10.2803 10.2197C10.1397 10.079 9.94891 10 9.75 10H9ZM15 4.75V19.75H20.25C20.4489 19.75 20.6397 19.671 20.7803 19.5303C20.921 19.3897 21 19.1989 21 19C21 18.8011 20.921 18.6103 20.7803 18.4697C20.6397 18.329 20.4489 18.25 20.25 18.25H19.5V6.25C19.6989 6.25 19.8897 6.17098 20.0303 6.03033C20.171 5.88968 20.25 5.69891 20.25 5.5C20.25 5.30109 20.171 5.11032 20.0303 4.96967C19.8897 4.82902 19.6989 4.75 19.5 4.75H15ZM16.5 9.25C16.5 9.05109 16.579 8.86032 16.7197 8.71967C16.8603 8.57902 17.0511 8.5 17.25 8.5H17.258C17.4569 8.5 17.6477 8.57902 17.7883 8.71967C17.929 8.86032 18.008 9.05109 18.008 9.25V9.258C18.008 9.45691 17.929 9.64768 17.7883 9.78833C17.6477 9.92898 17.4569 10.008 17.258 10.008H17.25C17.0511 10.008 16.8603 9.92898 16.7197 9.78833C16.579 9.64768 16.5 9.45691 16.5 9.258V9.25ZM17.25 11.5C17.0511 11.5 16.8603 11.579 16.7197 11.7197C16.579 11.8603 16.5 12.0511 16.5 12.25V12.258C16.5 12.672 16.836 13.008 17.25 13.008H17.258C17.4569 13.008 17.6477 12.929 17.7883 12.7883C17.929 12.6477 18.008 12.4569 18.008 12.258V12.25C18.008 12.0511 17.929 11.8603 17.7883 11.7197C17.6477 11.579 17.4569 11.5 17.258 11.5H17.25ZM16.5 15.25C16.5 15.0511 16.579 14.8603 16.7197 14.7197C16.8603 14.579 17.0511 14.5 17.25 14.5H17.258C17.4569 14.5 17.6477 14.579 17.7883 14.7197C17.929 14.8603 18.008 15.0511 18.008 15.25V15.258C18.008 15.4569 17.929 15.6477 17.7883 15.7883C17.6477 15.929 17.4569 16.008 17.258 16.008H17.25C17.0511 16.008 16.8603 15.929 16.7197 15.7883C16.579 15.6477 16.5 15.4569 16.5 15.258V15.25Z"
|
||||
fill="#9AA4BC"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
@@ -63,3 +63,4 @@ export * from "./multiple-sticky";
|
||||
export * from "./sticky-note-icon";
|
||||
export * from "./bar-icon";
|
||||
export * from "./tree-map-icon";
|
||||
export * from "./buildings-icon";
|
||||
|
||||
@@ -91,8 +91,8 @@ const CustomerSettingsPage = observer(() => {
|
||||
<>
|
||||
<PageHead title={pageTitle} />
|
||||
<WithFeatureFlagHOC flag="CUSTOMERS" fallback={<CustomerUpgrade />} workspaceSlug={workspaceSlug?.toString()}>
|
||||
<div className="px-4 py-6 flex items-center justify-between gap-2 border-b border-custom-border-100">
|
||||
<div className="pb-3 tracking-tight">
|
||||
<div className="flex items-center justify-between gap-2 border-b border-custom-border-200 pb-3">
|
||||
<div className="tracking-tight">
|
||||
<h3 className="text-xl font-medium">{t("customers.label", { count: 2 })}</h3>
|
||||
<span className="text-custom-sidebar-text-400 text-sm font-medium">
|
||||
{t("customers.settings.description")}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from "./root";
|
||||
export * from "./disabled";
|
||||
export * from "./loader";
|
||||
export * from "./properties";
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
import React, { FC, useRef, useState } from "react";
|
||||
import { v4 } from "uuid";
|
||||
import { ChevronRight, Plus } from "lucide-react";
|
||||
import { EIssuePropertyType } from "@plane/constants";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { TCreationListModes, TIssueProperty } from "@plane/types";
|
||||
import { Button, Collapsible } from "@plane/ui";
|
||||
import { cn } from "@/helpers/common.helper";
|
||||
import { CustomerPropertiesEmptyState } from "./empty-state";
|
||||
import { IssuePropertyList } from "@/plane-web/components/issue-types";
|
||||
|
||||
export type TCustomerPropertyCreateList = Partial<TIssueProperty<EIssuePropertyType>> & {
|
||||
key: string;
|
||||
};
|
||||
|
||||
export const defaultCustomProperty: Partial<TIssueProperty<EIssuePropertyType>> = {
|
||||
id: undefined,
|
||||
display_name: "",
|
||||
property_type: undefined,
|
||||
relation_type: undefined,
|
||||
is_multi: false,
|
||||
is_active: false,
|
||||
is_required: false,
|
||||
};
|
||||
|
||||
export const CustomerCustomPropertiesRoot: FC = () => {
|
||||
// states
|
||||
const [isOpen, setIsOpen] = useState(true);
|
||||
const [customerPropertyCreateList, setCustomerPropertyCreateList] = useState<TCustomerPropertyCreateList[]>([]);
|
||||
// hooks
|
||||
const { t } = useTranslation();
|
||||
|
||||
// derived
|
||||
const isAnyPropertiesAvailable = customerPropertyCreateList.length > 0;
|
||||
|
||||
// refs
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const lastElementRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// handlers
|
||||
const handleCustomerPropertiesCreate = (mode: TCreationListModes, value: TCustomerPropertyCreateList) => {
|
||||
switch (mode) {
|
||||
case "add":
|
||||
setCustomerPropertyCreateList((prevValue) => {
|
||||
prevValue = prevValue ? [...prevValue] : [];
|
||||
return [...prevValue, value];
|
||||
});
|
||||
break;
|
||||
case "remove":
|
||||
if (value) {
|
||||
setCustomerPropertyCreateList((prevValue) => {
|
||||
prevValue = prevValue ? [...prevValue] : [];
|
||||
return prevValue.filter((item) => item.key !== value.key);
|
||||
});
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div className="group/issue-type bg-custom-background-90/60 rounded-md px-4">
|
||||
<Collapsible
|
||||
isOpen={isOpen}
|
||||
onToggle={() => setIsOpen(!isOpen)}
|
||||
title={
|
||||
<div className="flex w-full gap-2 cursor-pointer items-center">
|
||||
<div className="flex-shrink-0">
|
||||
<ChevronRight
|
||||
className={cn("flex-shrink-0 size-4 transition-all text-custom-text-300", {
|
||||
"rotate-90": isOpen,
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<h3 className="text-base font-medium">{t("customers.properties.custom.title")}</h3>
|
||||
<p className="text-sm text-custom-text-300">{t("customers.properties.custom.info")}</p>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
buttonClassName={cn("flex w-full py-3 gap-2 items-center justify-between")}
|
||||
>
|
||||
<div className="pb-4">
|
||||
{isAnyPropertiesAvailable ? (
|
||||
<>
|
||||
<IssuePropertyList
|
||||
issueTypeId=""
|
||||
issuePropertyCreateList={customerPropertyCreateList}
|
||||
handleIssuePropertyCreateList={handleCustomerPropertiesCreate}
|
||||
containerRef={containerRef}
|
||||
lastElementRef={lastElementRef}
|
||||
/>
|
||||
<div className={cn("flex items-center py-2", !isAnyPropertiesAvailable && "justify-center")}>
|
||||
<Button
|
||||
variant="accent-primary"
|
||||
size="sm"
|
||||
className="rounded-md"
|
||||
onClick={() => {
|
||||
handleCustomerPropertiesCreate("add", {
|
||||
key: v4(),
|
||||
...defaultCustomProperty,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Plus className="h-3.5 w-3.5" />
|
||||
{t("customers.properties.add.primary_button")}
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<CustomerPropertiesEmptyState handleCustomerPropertiesCreate={handleCustomerPropertiesCreate} />
|
||||
)}
|
||||
</div>
|
||||
</Collapsible>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,86 @@
|
||||
import React, { useState } from "react";
|
||||
import { AlignLeft, ChevronRight, Hash, CircleChevronDown } from "lucide-react";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { Collapsible } from "@plane/ui";
|
||||
import { cn } from "@/helpers/common.helper";
|
||||
|
||||
const DEFAULT_PROPERTIES_LIST = [
|
||||
{
|
||||
i18n_title: "customers.properties.default.customer_name",
|
||||
icon: AlignLeft,
|
||||
},
|
||||
{
|
||||
i18n_title: "customers.properties.default.description",
|
||||
icon: AlignLeft,
|
||||
},
|
||||
{
|
||||
i18n_title: "customers.properties.default.email",
|
||||
icon: AlignLeft,
|
||||
},
|
||||
{
|
||||
i18n_title: "customers.properties.default.website_url",
|
||||
icon: AlignLeft,
|
||||
},
|
||||
{
|
||||
i18n_title: "customers.properties.default.employees",
|
||||
icon: Hash,
|
||||
},
|
||||
{
|
||||
i18n_title: "customers.properties.default.domain",
|
||||
icon: AlignLeft,
|
||||
},
|
||||
{
|
||||
i18n_title: "customers.properties.default.stage",
|
||||
icon: CircleChevronDown,
|
||||
},
|
||||
{
|
||||
i18n_title: "customers.properties.default.contract_status",
|
||||
icon: CircleChevronDown,
|
||||
},
|
||||
{
|
||||
i18n_title: "customers.properties.default.revenue",
|
||||
icon: Hash,
|
||||
},
|
||||
];
|
||||
|
||||
export const CustomerDefaultProperties = () => {
|
||||
// states
|
||||
const [isOpen, setIsOpen] = useState(true);
|
||||
// hooks
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<div className="group/issue-type bg-custom-background-90/60 rounded-md px-4">
|
||||
<Collapsible
|
||||
isOpen={isOpen}
|
||||
onToggle={() => setIsOpen(!isOpen)}
|
||||
title={
|
||||
<div className="flex w-full gap-2 cursor-pointer items-center">
|
||||
<div className="flex-shrink-0">
|
||||
<ChevronRight
|
||||
className={cn("flex-shrink-0 size-4 transition-all text-custom-text-300", {
|
||||
"rotate-90": isOpen,
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<h3 className="text-base font-medium">{t("customers.properties.default.title")}</h3>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
buttonClassName={cn("flex w-full py-3 gap-2 items-center justify-between")}
|
||||
>
|
||||
<div className="flex flex-wrap gap-2 pb-4">
|
||||
{DEFAULT_PROPERTIES_LIST.map((property) => (
|
||||
<div
|
||||
key={property.i18n_title}
|
||||
className="flex items-center gap-2 bg-custom-primary-0 border border-custom-border-200 rounded-md p-2 cursor-default"
|
||||
>
|
||||
<property.icon className="size-4" />
|
||||
<p className="text-sm text-custom-text-300">{t(property.i18n_title)}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</Collapsible>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
import React, { FC } from "react";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { BuildingsIcon, Button } from "@plane/ui";
|
||||
import { Plus } from "lucide-react";
|
||||
import { TCreationListModes } from "@plane/types";
|
||||
import { TIssuePropertyCreateList } from "@/plane-web/components/issue-types";
|
||||
import { defaultCustomProperty } from "@/plane-web/components/customers/settings";
|
||||
import { v4 } from "uuid";
|
||||
|
||||
type TCustomerPropertiesEmptyStateProps = {
|
||||
handleCustomerPropertiesCreate: (mode: TCreationListModes, value: TIssuePropertyCreateList) => void;
|
||||
};
|
||||
|
||||
export const CustomerPropertiesEmptyState: FC<TCustomerPropertiesEmptyStateProps> = (props) => {
|
||||
const { handleCustomerPropertiesCreate } = props;
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<div className="w-full p-8 relative flex justify-center items-center bg-custom-primary-0 rounded-lg border border-custom-border-100">
|
||||
<div className="flex flex-col items-center space-y-1">
|
||||
<div className="flex-shrink-0 grid place-items-center rounded-lg bg-custom-background-90 p-3">
|
||||
<BuildingsIcon className="h-14 w-14 text-custom-text-400" strokeWidth="1.5" />
|
||||
</div>
|
||||
<div className="text-custom-text-100 font-medium text-base">{t("customers.properties.empty_state.title")}</div>
|
||||
<div className="text-sm text-custom-text-400 pb-4">{t("customers.properties.empty_state.description")}</div>
|
||||
<Button
|
||||
variant="accent-primary"
|
||||
size="sm"
|
||||
className="rounded-md"
|
||||
onClick={() => {
|
||||
handleCustomerPropertiesCreate("add", { key: v4(), ...defaultCustomProperty });
|
||||
}}
|
||||
>
|
||||
<Plus className="h-3.5 w-3.5" />
|
||||
{t("customers.properties.add.primary_button")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
export * from "./root";
|
||||
export * from "./default-properties";
|
||||
export * from "./custom-properties";
|
||||
16
web/ee/components/customers/settings/properties/root.tsx
Normal file
16
web/ee/components/customers/settings/properties/root.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import React, { FC } from "react";
|
||||
import { CustomerDefaultProperties, CustomerCustomPropertiesRoot } from "@/plane-web/components/customers/settings";
|
||||
type TCustomPropertiesRootProps = {
|
||||
workspaceSlug: string;
|
||||
};
|
||||
|
||||
export const CustomerPropertiesRoot: FC<TCustomPropertiesRootProps> = (props) => {
|
||||
const { workspaceSlug } = props;
|
||||
|
||||
return (
|
||||
<>
|
||||
<CustomerDefaultProperties />
|
||||
<CustomerCustomPropertiesRoot />
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -1,5 +1,9 @@
|
||||
import { FC } from "react";
|
||||
import { CustomerSettingsDisabled, CustomerPropertiesLoader } from "@/plane-web/components/customers/settings";
|
||||
import {
|
||||
CustomerSettingsDisabled,
|
||||
CustomerPropertiesLoader,
|
||||
CustomerPropertiesRoot,
|
||||
} from "@/plane-web/components/customers/settings";
|
||||
import { useWorkspaceFeatures } from "@/plane-web/hooks/store";
|
||||
type TCustomerSettingsRoot = {
|
||||
workspaceSlug: string;
|
||||
@@ -9,16 +13,16 @@ type TCustomerSettingsRoot = {
|
||||
};
|
||||
|
||||
export const CustomerSettingsRoot: FC<TCustomerSettingsRoot> = (props) => {
|
||||
const { toggleCustomersFeature, isCustomersFeatureEnabled } = props;
|
||||
const { toggleCustomersFeature, isCustomersFeatureEnabled, workspaceSlug } = props;
|
||||
|
||||
const { loader } = useWorkspaceFeatures();
|
||||
return (
|
||||
<div className="space-y-3 space-x">
|
||||
<div className="space-y-3 space-x pt-3">
|
||||
{isCustomersFeatureEnabled ? (
|
||||
loader ? (
|
||||
<CustomerPropertiesLoader />
|
||||
) : (
|
||||
<></>
|
||||
<CustomerPropertiesRoot workspaceSlug={workspaceSlug} />
|
||||
)
|
||||
) : (
|
||||
<CustomerSettingsDisabled toggleCustomersFeature={toggleCustomersFeature} />
|
||||
|
||||
Reference in New Issue
Block a user