Contacts Feature - Integration Status
This document tracks what is integrated between frontend and backend for the contacts feature.
Last updated: 2026-03-23
1. Multi-Value Email & Phone Numbers
Status: ✅ Fully integrated
Frontend sends and receives additionalEmails and additionalPhones arrays on all contact CRUD operations.
Implementation Details
Type:
type AdditionalEntry {
value: String!
label: String!
}
Label Options:
- Phone labels:
["Mobile", "Work", "Home", "Other"] - Email labels:
["Work", "Personal", "Other"]
Frontend Behavior:
- Entries are loaded from backend on page load
- Creating a contact sends
additionalEmails/additionalPhonesincreateContactmutation - Updating a contact sends the complete arrays (backend replaces, not merges)
- Removing an entry auto-saves immediately
- Pressing Enter on an entry auto-saves
- Pressing Escape dismisses editing without saving
- Delete icon is always visible (not hidden behind hover)
GraphQL Queries that include these fields:
GET_CONTACTS_BY_COMPANY(list view)GET_CONTACT_BY_ID(detail view)CREATE_CONTACT(return fields)UPDATE_CONTACT(return fields)
Files:
graphql/operations/contacts/queries.tsgraphql/operations/contacts/mutations.tsapp/company/connections/contacts/_components/CreateContactCard.tsxapp/company/connections/contacts/[id]/view/page.tsx
2. Company Name (Free Text)
Status: ✅ Fully integrated
The company field on contacts is a user-editable free text field, not auto-populated from the user's company.
Implementation Details
- Create:
companyNamesent increateContactmutation input - Update:
companyNamesent inupdateContactmutation input - Display: Loaded from
display.companyNameon the contact record - UI: Click-to-edit text input in both the hero section and the Organization panel
- Company is NOT resolved from
user.companiesoruserCompanyRole— it's whatever the contact creator typed
Backend requirement: The CreateContactInput and UpdateContactInput must accept a companyName: String field. This value should be stored in the contact's display JSON or as a dedicated column.
3. ContactNote.Author
Status: ✅ Integrated with fallback
The Author field is now queried directly on ContactNote in GET_CONTACT_BY_ID:
ContactNote {
id
contactId
authorId
title
content
createdAt
updatedAt
Author {
id
firstName
lastName
profileImageUrl
}
}
Frontend uses Author from the query when available, with a client-side fallback to userIdToName map via authorId if Author is null.
4. Contact Types System
Status: ✅ Fully integrated and working
5. Contact Notes System
Status: ✅ Fully integrated
- CRUD operations work via
createContactNote,updateContactNote,removeContactNote - Author info now comes from GraphQL
Authorfield with client-side fallback GET_CONTACT_NOTESstandalone query includesAuthor { id firstName lastName profileImageUrl }
6. External Sharing System
Status: ✅ Fully integrated and working
7. Merge Contacts System
Status: ✅ Fully integrated and working
8. CSV Bulk Import System
Status: ✅ Fully integrated
9. Collaboration & Partnership Status Fields
Status: ✅ Fully integrated and working
10. UX Behaviors
Auto-save on Enter
- Pressing Enter while editing any inline field dismisses the editor and auto-saves the contact
- Pressing Escape dismisses the editor without saving
- Removing an additional email/phone entry auto-saves immediately
Keyboard Support
- All inline edit fields (name, title, company, phone, location, types, responsible, additional entries) support Enter/Escape
EditableInfoItemcomponent hasonDismiss(Enter → save) andonCancel(Escape → dismiss) callbacksAdditionalEntryRowcomponent hasonSaveandonCancelcallbacks
Navigation
- Back button is an icon-only arrow on the left side next to "CONTACT PROFILE" label
- Prev/Next navigation with arrow keys (when not editing a field)
Remaining Backend Issues (Low Priority)
These have frontend workarounds in place:
-
Import
errors: null—importContactsreturnsnullinstead of[]for empty errors array. Frontend normalizes with?? []. -
Company Name Sorting —
COMPANY_NAMEsort uses a different field than what the frontend displays. Frontend applies client-side sort as workaround. -
Mutation Argument Naming — Some mutations use
createContactInput/updateContactInputinstead ofinput. Frontend maps to the correct names.
File Reference
| File | Purpose |
|---|---|
graphql/operations/contacts/queries.ts | All contact GraphQL queries |
graphql/operations/contacts/mutations.ts | All contact GraphQL mutations |
app/company/connections/contacts/page.tsx | Contacts list page |
app/company/connections/contacts/_components/CreateContactCard.tsx | Create contact form |
app/company/connections/contacts/[id]/view/page.tsx | View/edit contact detail page |
app/company/connections/contacts/_components/ShareContactDialog.tsx | External sharing dialog |
app/company/connections/contacts/_components/MergeContactsDialog.tsx | Merge contacts dialog |
app/company/connections/contacts/_components/ImportContactsDialog.tsx | CSV import dialog |
components/reusable/ProfileViewPrimitives.tsx | EditableInfoItem component (shared) |