# @wisemen/wise-crm-web

Vue 3 CRM package: business, individual and deal overviews, detail views, dialogs and widgets.

## Extending the detail views

The business and individual detail views can be extended with content from the host app in two places.

### Custom tabs

Tabs next to the detail sidebar are routes, registered through `useWiseCrmRoutes`. At least one tab is required for businesses and individuals. The tab component reads the entity uuid from the route params (`businessUuid` / `individualUuid` / `dealUuid`).

```ts
useWiseCrmRoutes({
  businessTabRoutes: [
    {
      label: computed<string>(() => t('crm.business.tabs.information')),
      route: {
        name: 'crm-business-information',
        path: 'information',
        component: (): Component => import('./CrmBusinessInformationTabView.vue'),
      },
    },
  ],
  dealTabRoutes: [...],
  individualTabRoutes: [...],
})
```

### Custom sidebar sections

Accordion sections rendered at the end of the sidebar's Overview tab, after the built-in sections. They show in both the detail view and the quick-view dialog. Register them through the `business` / `individual` options of `useWiseCrmConfig().init()`:

```ts
import type { WiseCrmSidebarSection } from '@wisemen/wise-crm-web'

useWiseCrmConfig().init({
  // ...
  options: {
    business: {
      sidebarSections: [
        {
          icon: ShoppingCart01Icon,
          key: 'orders',
          label: computed<string>(() => t('crm.business.sidebar.orders')),
          component: defineAsyncComponent(() => import('./BusinessOrdersSidebarSection.vue')),
        },
      ],
    },
    individual: {
      sidebarSections: [...],
    },
    // ...
  },
})
```

| Field          | Description                                                                                                                       |
| -------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `key`          | Unique per entity; used as the accordion item value.                                                                              |
| `label`        | Section header, a `ComputedRef<string>` so it follows the locale.                                                                 |
| `icon`         | Section header icon.                                                                                                              |
| `component`    | Section body.                                                                                                                     |
| `useIsVisible` | Optional. Receives the component's props as a `ComputedRef` and returns a `ComputedRef<boolean>`; the section is hidden while it is `false`. |

The component receives only the entity uuid. It fetches its own data and renders its own loading and empty state. Sections are open by default.

```vue
<script setup lang="ts">
import type { WiseCrmBusinessUuid } from '@wisemen/wise-crm-web'

const props = defineProps<{
  businessUuid: WiseCrmBusinessUuid
}>()
</script>
```

Individual sections receive `individualUuid: WiseCrmIndividualUuid` instead. A component with the wrong props is a type error.

`useIsVisible` is called once in the sidebar's setup, so it can use composables such as queries. Use it to hide a section that has nothing to show for this entity, rather than rendering an empty body under its header:

```ts
{
  key: 'parent',
  // ...
  useIsVisible: (props) => useBusinessHasParent(computed(() => props.value.businessUuid)),
}
```

A section that becomes visible after the sidebar has mounted still opens by default.
