Skip to content
12 changes: 12 additions & 0 deletions astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,18 @@ async function config() {
collapsed: true,
items: [
{ label: 'Overview', link: '/dropins-b2b/' },
{
label: 'Company Management',
collapsed: true,
items: [
{ label: 'Overview', link: '/dropins-b2b/company/' },
{ label: 'Installation', link: '/dropins-b2b/company/installation/' },
{ label: 'Initialization', link: '/dropins-b2b/company/initialization/' },
{ label: 'Functions', link: '/dropins-b2b/company/functions/' },
{ label: 'Events', link: '/dropins-b2b/company/events/' },
{ label: 'Dictionary', link: '/dropins-b2b/company/dictionary/' },
],
},
{
label: 'B2B Containers',
collapsed: true,
Expand Down
282 changes: 282 additions & 0 deletions src/content/docs/dropins-b2b/company/dictionary.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
---
title: Company dictionary
description: Learn how to customize the default dictionary for the Company drop-in component.
sidebar:
label: Dictionary
order: 7
---

import CodeInclude from '@components/CodeInclude.astro';
import CodeImport from '@components/CodeImport.astro';

The Company drop-in component includes a comprehensive dictionary for internationalization and text customization. The default dictionary contains all labels, messages, validation text, and user interface strings used throughout the company management interface. You can customize these values or add support for additional languages.

## Default keys and values

The dictionary file for the Company drop-in is located at:
`@dropins/storefront-company-management/i18n/en_US.json`

```json
{
"Company": {
"shared": {
"fields": {
"companyName": "Company Name",
"email": "Email",
"legalName": "Legal Name",
"vatTaxId": "VAT/Tax ID",
"resellerId": "Reseller ID",
"legalAddress": "Legal Address",
"streetAddress": "Street Address",
"city": "City",
"country": "Country",
"stateProvince": "State/Province",
"zipPostalCode": "ZIP/Postal Code",
"phoneNumber": "Phone Number",
"status": "Status",
"region": "Region",
"postalCode": "Postal Code",
"jobTitle": "Job Title",
"workPhoneNumber": "Work Phone Number",
"userRole": "User Role"
},
"buttons": {
"edit": "Edit",
"cancel": "Cancel",
"save": "Save Changes",
"saving": "Saving...",
"close": "Close",
"confirm": "Confirm"
},
"validation": {
"required": "This field is required",
"invalidEmail": "Please enter a valid email address",
"companyNameRequired": "Company name is required",
"emailRequired": "Email is required",
"emailNotAvailable": "This email is already used by another company",
"phoneInvalid": "Please enter a valid phone number",
"postalCodeInvalid": "Please enter a valid postal code",
"companyNameLengthError": "Company name must not exceed 40 characters",
"legalNameLengthError": "Legal name must not exceed 80 characters",
"vatTaxIdLengthError": "VAT/Tax ID must not exceed 40 characters",
"resellerIdLengthError": "Reseller ID must not exceed 40 characters"
},
"messages": {
"loading": "Loading...",
"noData": "No data available",
"error": "An error occurred",
"success": "Operation completed successfully"
},
"ariaLabels": {
"editButton": "Edit company profile",
"cancelButton": "Cancel editing",
"saveButton": "Save company profile changes",
"closeButton": "Close dialog"
}
},
"CompanyProfile": {
"containerTitle": "Company Profile",
"editCompanyProfile": {
"containerTitle": "Edit Company Profile",
"companySuccess": "Company profile updated successfully",
"companyError": "Failed to update company profile",
"buttonSecondary": "Cancel",
"buttonPrimary": "Save Changes"
},
"companyProfileCard": {
"noDataMessage": "Company profile not available. Please contact your administrator.",
"contacts": "Contacts",
"companyAdministrator": "Company Administrator",
"salesRepresentative": "Sales Representative",
"paymentInformation": "Payment Information",
"availablePaymentMethods": "Available Payment Methods",
"shippingInformation": "Shipping Information",
"availableShippingMethods": "Available Shipping Methods",
"noPaymentMethods": "This company has no payment methods. Please contact store administrator.",
"noShippingMethods": "This company has no shipping methods. Please contact store administrator.",
"companyDetails": "Company Details",
"addressInformation": "Address Information"
},
"messages": {
"loadError": "Failed to load company profile",
"updateError": "Failed to update company profile",
"loadingProfile": "Loading company profile...",
"savingProfile": "Saving company profile..."
}
},
"FormText": {
"requiredFieldError": "This is a required field.",
"numericError": "Only numeric values are allowed.",
"alphaNumWithSpacesError": "Only alphanumeric characters and spaces are allowed.",
"alphaNumericError": "Only alphanumeric characters are allowed.",
"alphaError": "Only alphabetic characters are allowed.",
"emailError": "Please enter a valid email address.",
"phoneError": "Please enter a valid phone number.",
"postalCodeError": "Please enter a valid postal code.",
"lengthTextError": "Text length must be between {min} and {max} characters.",
"companyNameLengthError": "Company name must be between {min} and {max} characters."
}
}
}
```

## Dictionary structure

The dictionary is organized into logical sections:

### Shared section

Contains common elements used across multiple components:
- **fields**: Labels for form fields and data display
- **buttons**: Text for interactive elements
- **validation**: Error messages for form validation
- **messages**: General status and informational messages
- **ariaLabels**: Accessibility labels for screen readers

### CompanyProfile section

Contains text specific to the CompanyProfile container:
- **containerTitle**: Main container heading
- **editCompanyProfile**: Edit form specific text
- **companyProfileCard**: Profile card display text
- **messages**: Component-specific status messages

### FormText section

Contains validation messages and form-related text:
- Field validation error messages
- Input format requirements
- Length validation messages with placeholder support

## Customizing the dictionary

### Method 1: Initialize with custom dictionary

```js
import { initialize } from '@dropins/storefront-company-management/api';

await initialize({
langDefinitions: {
en_US: {
'Company.shared.fields.companyName': 'Business Name',
'Company.shared.fields.email': 'Business Email',
'Company.CompanyProfile.containerTitle': 'Business Profile',
'Company.shared.buttons.edit': 'Modify',
'Company.shared.buttons.save': 'Update Changes'
}
}
});
```

### Method 2: Override specific keys

```js
// Override individual dictionary keys
const customDictionary = {
'Company.shared.fields.companyName': 'Organization Name',
'Company.shared.fields.legalName': 'Legal Business Name',
'Company.CompanyProfile.companyProfileCard.contacts': 'Contact Information',
'Company.shared.validation.required': 'This field cannot be empty'
};

await initialize({
langDefinitions: {
en_US: customDictionary
}
});
```

## Adding new languages

### Spanish (es_ES) example

```js
const spanishDictionary = {
'Company.shared.fields.companyName': 'Nombre de la Empresa',
'Company.shared.fields.email': 'Correo Electrónico',
'Company.shared.fields.legalName': 'Nombre Legal',
'Company.shared.fields.vatTaxId': 'NIF/CIF',
'Company.shared.fields.legalAddress': 'Dirección Legal',
'Company.shared.fields.city': 'Ciudad',
'Company.shared.fields.country': 'País',
'Company.shared.fields.postalCode': 'Código Postal',
'Company.shared.buttons.edit': 'Editar',
'Company.shared.buttons.cancel': 'Cancelar',
'Company.shared.buttons.save': 'Guardar Cambios',
'Company.shared.validation.required': 'Este campo es obligatorio',
'Company.shared.validation.invalidEmail': 'Ingrese una dirección de correo válida',
'Company.CompanyProfile.containerTitle': 'Perfil de la Empresa'
};

await initialize({
langDefinitions: {
es_ES: spanishDictionary
}
});
```

### French (fr_FR) example

```js
const frenchDictionary = {
'Company.shared.fields.companyName': 'Nom de l\'Entreprise',
'Company.shared.fields.email': 'Adresse E-mail',
'Company.shared.fields.legalName': 'Raison Sociale',
'Company.shared.fields.vatTaxId': 'Numéro de TVA',
'Company.shared.fields.legalAddress': 'Adresse Légale',
'Company.shared.fields.city': 'Ville',
'Company.shared.fields.country': 'Pays',
'Company.shared.fields.postalCode': 'Code Postal',
'Company.shared.buttons.edit': 'Modifier',
'Company.shared.buttons.cancel': 'Annuler',
'Company.shared.buttons.save': 'Enregistrer',
'Company.shared.validation.required': 'Ce champ est obligatoire',
'Company.CompanyProfile.containerTitle': 'Profil de l\'Entreprise'
};

await initialize({
langDefinitions: {
fr_FR: frenchDictionary
}
});
```

## Dynamic text with placeholders

Some dictionary entries support placeholders for dynamic content:

```js
// Dictionary entry with placeholders
'Company.FormText.lengthTextError': 'Text length must be between {min} and {max} characters.'

// Usage in validation
const errorMessage = getText('Company.FormText.lengthTextError', { min: 1, max: 40 });
// Result: "Text length must be between 1 and 40 characters."
```

## Best practices

### Naming conventions
- Use descriptive, hierarchical keys
- Group related text under common prefixes
- Use camelCase for key names
- Include context in key names (e.g., `companyProfileCard.noDataMessage`)

### Translation guidelines
- Keep text concise and clear
- Consider character length differences between languages
- Maintain consistent terminology across the interface
- Test with longer text to ensure UI layout remains intact

### Accessibility considerations
- Provide clear, descriptive aria labels
- Use plain language for error messages
- Ensure button text clearly describes the action
- Include context for screen reader users

:::note
```js
import dictionary from '@dropins/storefront-company-management/i18n/en_US.json?raw';
```
:::

87 changes: 87 additions & 0 deletions src/content/docs/dropins-b2b/company/events.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
---
title: Company Management Data & Events
description: Learn about the events used by the Company Management and the data available within the events.
sidebar:
label: Events
order: 5
---

import { Aside } from '@astrojs/starlight/components';
import TableWrapper from '@components/TableWrapper.astro';

The **Company Management** drop-in uses the [Event Bus](/sdk/reference/events/) to emit and listen to events for communication between drop-ins and external integrations. For common events shared across multiple drop-ins (such as `locale`, `error`, `authenticated`, etc.), see the Common Events Reference.

## Events reference

{/* EVENTS_TABLE_START */}
<TableWrapper nowrap={[0, 1]}>

| Event | Direction | Description |
|-------|-----------|-------------|
| [company/updated](#companyupdated-emits) | Emits | Emitted when the component state is updated |
| [companyContext/changed](#companycontextchanged-listens) | Listens | Fired by Company Context (`companyContext`) when a change occurs |

</TableWrapper>
{/* EVENTS_TABLE_END */}

## Event details

The following sections provide detailed information about each event, including its direction, data payload structure, and usage examples.

### `company/updated` (emits)

Emitted when the component state is updated

#### Data payload

```typescript
{ company?: any; message?: string; error?: any }
```

| Property | Type | Description |
|----------|------|-------------|
| `company` | `any` (optional) | See type definition in source code |
| `message` | `string` (optional) | See type definition in source code |
| `error` | `any` (optional) | See type definition in source code |

#### Usage

Listen to this event in your storefront:

```javascript
import { events } from '@dropins/tools/event-bus.js';

const companyUpdatedListener = events.on('company/updated', (data) => {
console.log('company/updated event received:', data);
// Add your custom logic here
});

// Later, when you want to stop listening
companyUpdatedListener.off();
```

### `companyContext/changed` (listens)

Fired by Company Context (`companyContext`) when a change occurs

#### Data payload

```typescript
string | null | undefined
```

#### Usage

Listen to this event in your storefront:

```javascript
import { events } from '@dropins/tools/event-bus.js';

const companyContextChangedListener = events.on('companyContext/changed', (data) => {
console.log('companyContext/changed event received:', data);
// Add your custom logic here
});

// Later, when you want to stop listening
companyContextChangedListener.off();
```
Loading