Skip to main content

Contacts & Invites – End‑to‑End Specification

1. Terminology

TermMeaning
CustomerA fully‑registered Mind Your Now user (MYNCustomer)
ContactA verified relationship between two customers (Contact.verified = true)
ProspectRow in Prospect table – represents an out‑bound email invite that is not yet a verified contact
Customer  ──(0..N)── Prospect        // pending outbound invites
Customer ──(0..N)── Contact // verified connections

2. User‑Facing Flow

2.1 Inviting by Email

  1. Enter email → press Invite.
  2. UI shows spinner → then one of the outcomes below.
  3. Typeahead Suggestions: While typing an email, show live suggestions from MYN internal contacts, Google contacts, and Outlook/Office365 contacts.
OutcomeHTTP ResponseUI Behaviour
Email is new (not yet an MYN account)201 CREATED { prospectId }Add row under Pending Invites.
Email belongs to an existing MYN user not already contact200 OK { contactId }Instantly add to Your Contacts.
Email already a contact409 CONFLICT { code:"ALREADY_CONTACT" }Show toast: Already a contact.
Email previously invited (duplicate prospect)409 CONFLICT { code:"ALREADY_INVITED" }Show toast: Invitation already sent.
Any validation / format error400 BAD_REQUESTInline error under input.
Server failure500Toast: Could not send invite. Try later.

2.2 Accepting an Invite (Recipient Side)

StepActorAction
1Prospect clicks link in emailOpens Sign‑Up / Login page with inviteToken.
2Backend validates token → creates/links accountRemoves row from Prospect, creates Contact both directions, sets verified=true.
3Sender’s Pending Invites list auto‑refreshes (WS push).Moves person from Pending to Contacts.

2.2b Viewing & Managing Received Invites

OutcomeHTTP ResponseUI Behaviour
Invites received pending acceptance200 OK [PendingInviteResponse[id, inviterEmail]]Shown under Invites Received with Accept/Reject buttons.
Accept invitePOST /api/contacts/incoming/{id}/accept200 OK { code:"CONTACT_CREATED" }Moves the entry to Your Contacts.
Reject inviteDELETE /api/contacts/incoming/{id}204 NO_CONTENTRemoves the entry from Invites Received.

2.3 Cancelling a Pending Invite

  • Sender clicks Cancel on a prospect row.
  • DELETE /api/contacts/pending/{prospectId}.
  • Backend deletes prospect if customerWhoInvitedEmail matches caller.
  • UI instantly removes the row.

3. REST API Contract

VerbPathBody / ParamsSuccess (2xx)Error Codes
GET/api/contacts200 [ContactResponse]500
GET/api/contacts/pending200 [Prospect]500
POST/api/contacts{ "email": string }See Outcomes above400, 409, 500
DELETE/api/contacts/pending/{id}200404, 403, 500
GET/api/contacts/search?query=...200 [ContactResponse]500
GET/api/contacts/external/google?query=...200 [ExternalContactDto]401, 500
GET/api/contacts/external/microsoft?query=...200 [ExternalContactDto]401, 500
GET/api/contacts/incoming200 [PendingInviteResponse]500
POST/api/contacts/incoming/{id}/accept200 InviteResult400, 401, 500
DELETE/api/contacts/incoming/{id}204400, 401, 500
// ContactResponse (DTO)
{
id: number;
name: string; // username or email
email: string;
}

// Prospect (DTO)
{
id: number;
email: string;
}

4. UI Component Contract (Frontend)

ComponentSourceProps / State highlights
ContactsPagesrc/components/contacts/ContactsPage.tsxcontacts, pending, inviteContact(email)
TaskShareDialogUses searchContacts for suggestions

Error‑Handling Rules (Frontend)

if (status === 201) addToPending();
else if (status === 200) addToContacts();
else if (status === 409 && data.code==='ALREADY_CONTACT') toast('Already a contact');
else if (status === 409 && data.code==='ALREADY_INVITED') toast('Invite already sent');
else toast('Error sending invite');

5. Backend Service Rules

  1. Service: ContactService.inviteContact.
  2. Steps:
    1. findByEmail → if returns customer ⇒ create Contact (bidirectional) if not exists.
    2. Else check Prospect duplicate.
    3. If new prospect → save + send email.
  3. Throws:
    • CustomerAlreadyAContact → map to 409 ALREADY_CONTACT.
    • CustomerEmailAlreadyExists → map to 200/201 (see above logic).

6. Real‑Time Updates

  • WebSocket topic /contacts/{customerId} pushes events:
    • invite_sent, invite_cancelled, invite_accepted, contact_removed.
  • Front‑end subscribes via useContactsWS hook to update state without polling.

7. Future Enhancements

  1. Bulk Invites – CSV upload → multiple prospects.
  2. Invite linkhttps://mindyournow.com/invite/<token> for socials.
  3. Rate limiting – one invite/email/day to prevent spam.
  4. In‑app notification when an existing user becomes a contact (no email needed).

8. External Contacts Integration

Objective: Seamlessly import and invite external contacts from Google and Microsoft.

8.1 OAuth & Permissions

  • Google People API: https://www.googleapis.com/auth/contacts.readonly
  • Microsoft Graph API: Contacts.Read (and optionally Contacts.ReadWrite)

8.2 Backend Implementation

  • Extend OAuthController to request & store contact scopes for Google & Microsoft.
  • Implement ExternalContactsService with methods:
    • List<ContactDto> fetchGoogleContacts(MYNCustomer customer, String query)
    • List<ContactDto> fetchMicrosoftContacts(MYNCustomer customer, String query)
  • Expose new endpoints:
    • GET /api/contacts/external/google?query=...
    • GET /api/contacts/external/microsoft?query=...
  • Cache per‑user results & enforce rate limits.

8.3 Frontend Integration

  • In ContactsPage, add a typeahead search box that queries:
    1. Internal GET /api/contacts/search?query=
    2. External GET /api/contacts/external/{source}?query=
  • Merge & display suggestions with source icons (Google, Microsoft, MYN).
  • Debounce input (300ms) and support pagination/loading more.

8.4 UI/UX Considerations

  • Add an “Import from” dropdown to switch between sources.
  • Show contact avatars where available.
  • Allow multi‑select and bulk invite actions.

8.5 Security & Privacy

  • Encrypt external tokens at rest.
  • Provide a Settings > Integrations panel to view/revoke access.
  • Comply with Google & Microsoft data handling policies.

8.6 Milestones & Timeline

  1. Configure OAuth scopes & backend service hooks (1 week)
  2. Build external contacts service & endpoints (2 weeks)
  3. Integrate frontend typeahead & UI components (1 week)
  4. QA, privacy review & rollout (1 week)