Imported from AncoraDev/guiders-frontend (
libs/chat/features/contacts/AGENTS.md). Install upstream withnpx skills add AncoraDev/guiders-frontend --skill contacts. Copyright stays with the author.
AGENTS.md - Chat: Contacts Feature
Parent Documentation: ../../AGENTS.md (Root)
Overview
The contacts feature manages the contact information for visitors/customers. Includes contact creation, editing, searching, and organization into contact groups.
Feature Structure
libs/chat/features/contacts/
├── src/
│ ├── lib/
│ │ ├── components/ # Contact list, detail, form
│ │ ├── services/ # Contact management logic
│ │ ├── state/ # Contact state management
│ │ └── routes/ # Feature routing
│ └── index.ts # Public API
└── project.json
Key Components & Services
- ContactsListComponent - Contacts directory/list view
- ContactDetailComponent - Contact profile with full information
- ContactFormComponent - Create/edit contact form
- ContactGroupsComponent - Manage contact groups/tags
- ContactsService - Contacts API and state management
- ContactSearchService - Search and filtering
Development Commands
# Serve console with contacts
npm run serve # Full console app
# Test contacts feature
nx test chat-contacts # All tests
nx test chat-contacts --testFile=contacts-list.component.spec.ts
nx test chat-contacts -- --grep "search"
# Lint and fix
nx lint chat-contacts
nx lint chat-contacts -- --fix
Common Tasks
Creating a New Contact
- Use
ContactFormComponentwith empty data - Service validates contact information
- On submit, POST to
/api/contacts - Update contacts list signal
- Navigate to contact detail view
Editing Contact Information
// Example: Update contact details
editContact(contactId: string, updates: Partial<Contact>): void {
this.contactsService.updateContact(contactId, updates).subscribe({
next: (updated) => {
this.currentContact.set(updated);
this.showSuccessMessage('Contact updated');
},
error: (err) => this.handleError(err),
});
}
Searching and Filtering Contacts
- Real-time search as user types
- Filter by contact group/tag
- Filter by contact status (active, inactive, blocked)
- Combine multiple filters
Adding Contact Tags/Groups
// Example: Add contact to group
addContactToGroup(contactId: string, groupId: string): void {
this.contactsService.addToGroup(contactId, groupId).subscribe({
next: () => this.refreshContactGroups(),
error: (err) => this.handleError(err),
});
}
Styling Contact Cards and Lists
@use '@guiders-frontend/shared/design-tokens' as tokens;
.guiders-contacts__card {
display: flex;
align-items: center;
padding: tokens.$spacing-md;
border: 1px solid tokens.$color-border-light;
border-radius: tokens.$border-radius-md;
&__avatar {
width: 40px;
height: 40px;
border-radius: 50%;
margin-right: tokens.$spacing-md;
background: tokens.$color-bg-secondary;
}
&__info {
flex: 1;
&-name {
font-weight: 600;
color: tokens.$color-text-primary;
}
&-email {
font-size: tokens.$font-size-sm;
color: tokens.$color-text-secondary;
}
}
&__tags {
display: flex;
gap: tokens.$spacing-xs;
flex-wrap: wrap;
}
}
Architecture Rules
Contacts (type: feature) can import from:
- ✅
@guiders-frontend/shared/ui/*(UI components) - ✅
@guiders-frontend/shared/util/*(utilities) - ✅
@guiders-frontend/chat/data-access/*(chat services) - ✅
@guiders-frontend/shared/types/*(types) - ✅
@guiders-frontend/chat/ui/*(chat-specific UI)
Contacts CANNOT import from:
- ❌
@guiders-frontend/admin/* - ❌
@guiders-frontend/analytics/*
Testing Guidelines
// Test contact creation
it('should create new contact', fakeAsync(() => {
const newContact: Contact = mockContact();
component.createContact(newContact);
tick();
expect(contactsService.createContact).toHaveBeenCalledWith(newContact);
expect(component.contacts()).toContain(newContact);
}));
// Test contact search
it('should filter contacts by search term', () => {
component.contactsList.set(mockContacts());
component.searchTerm.set('John');
const filtered = component.filteredContacts();
expect(filtered.every((c) => c.name.includes('John'))).toBe(true);
});
// Test adding contact to group
it('should add contact to group and emit event', () => {
spyOn(component.contactGroupAdded, 'emit');
const contact = mockContact();
component.addToGroup(contact, 'premium');
expect(component.contactGroupAdded.emit).toHaveBeenCalled();
});
// Test form validation
it('should validate email format', () => {
component.form.patchValue({ email: 'invalid-email' });
expect(component.form.valid).toBe(false);
expect(component.form.get('email')?.hasError('email')).toBe(true);
});
Key Files to Know
| File | Purpose |
|---|---|
src/lib/components/contacts-list/contacts-list.component.ts |
Contacts directory view |
src/lib/components/contact-detail/contact-detail.component.ts |
Contact profile |
src/lib/components/contact-form/contact-form.component.ts |
Create/edit form |
src/lib/components/contact-groups/contact-groups.component.ts |
Group management |
src/lib/services/contacts.service.ts |
Contacts API and state |
src/lib/services/contact-search.service.ts |
Search functionality |
src/index.ts |
Public API exports |
Performance Considerations
- Large Contact Lists: Virtual scrolling for 5000+ contacts
- Search Debouncing: Debounce search input to reduce API calls
- Caching: Cache contact list with 5-minute expiry
- Lazy Loading: Load contact groups on demand
- Change Detection:
ChangeDetectionStrategy.OnPushon all components
Form Validation Examples
// Advanced form validation for contact creation
private buildContactForm(): FormGroup {
return new FormGroup({
name: new FormControl('', [Validators.required, Validators.minLength(2)]),
email: new FormControl('', [Validators.required, Validators.email]),
phone: new FormControl('', [Validators.pattern(/^\+?[\d\s-()]{7,}$/)]),
company: new FormControl(''),
tags: new FormControl([]),
});
}
Debugging
Contacts Not Loading:
- Check network tab for API requests
- Verify ContactsService is properly initialized
- Check browser console for errors
Search Not Working:
- Verify search debounce timeout
- Check API supports search parameter
- Look for filter state issues
Form Validation Issues:
- Check FormControl validators
- Verify form group bindings in template
- Test individual validators in unit tests
Related Features
- Visitors (
libs/chat/features/visitors) - Visitor management - Inbox (
libs/chat/features/inbox) - Messaging with contacts - Escalations (
libs/chat/features/escalations) - Escalation tracking
Common Workflows
Creating Contact from Visitor
- Open visitor profile
- Click "Save as Contact"
- Pre-populate contact form with visitor data
- Allow editing before saving
- Auto-link contact to visitor
Bulk Contact Operations
- Select multiple contacts with checkboxes
- Apply bulk actions (add tag, change group, archive)
- Confirm action with dialog
- Show success/error notification
Contact Search and Discovery
- Use search bar with fuzzy search
- Filter by tags/groups
- Sort by name, email, last contacted
- View contact history
See Also
- Root AGENTS.md - General guidelines
- Visitors Feature - Visitor management
- Inbox Feature - Messaging
- Chat Data Access - API documentation
- Form Validation - Form patterns