Contacts & Invites – End‑to‑End Specification
1. Terminology
Term | Meaning |
---|---|
Customer | A fully‑registered Mind Your Now user (MYNCustomer ) |
Contact | A verified relationship between two customers (Contact.verified = true ) |
Prospect | Row 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
- Enter email → press Invite.
- UI shows spinner → then one of the outcomes below.
- Typeahead Suggestions: While typing an email, show live suggestions from MYN internal contacts, Google contacts, and Outlook/Office365 contacts.
Outcome | HTTP Response | UI 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 contact | 200 OK { contactId } | Instantly add to Your Contacts. |
Email already a contact | 409 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 error | 400 BAD_REQUEST | Inline error under input. |
Server failure | 500 | Toast: Could not send invite. Try later. |
2.2 Accepting an Invite (Recipient Side)
Step | Actor | Action |
---|---|---|
1 | Prospect clicks link in email | Opens Sign‑Up / Login page with inviteToken . |
2 | Backend validates token → creates/links account | Removes row from Prospect , creates Contact both directions, sets verified=true . |
3 | Sender’s Pending Invites list auto‑refreshes (WS push). | Moves person from Pending to Contacts. |
2.2b Viewing & Managing Received Invites
Outcome | HTTP Response | UI Behaviour |
---|---|---|
Invites received pending acceptance | 200 OK [PendingInviteResponse[id, inviterEmail]] | Shown under Invites Received with Accept/Reject buttons. |
Accept invite | POST /api/contacts/incoming/{id}/accept → 200 OK { code:"CONTACT_CREATED" } | Moves the entry to Your Contacts. |
Reject invite | DELETE /api/contacts/incoming/{id} → 204 NO_CONTENT | Removes 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
Verb | Path | Body / Params | Success (2xx) | Error Codes |
---|---|---|---|---|
GET | /api/contacts | – | 200 [ContactResponse] | 500 |
GET | /api/contacts/pending | – | 200 [Prospect] | 500 |
POST | /api/contacts | { "email": string } | See Outcomes above | 400 , 409 , 500 |
DELETE | /api/contacts/pending/{id} | – | 200 | 404 , 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/incoming | – | 200 [PendingInviteResponse] | 500 |
POST | /api/contacts/incoming/{id}/accept | – | 200 InviteResult | 400 , 401 , 500 |
DELETE | /api/contacts/incoming/{id} | – | 204 | 400 , 401 , 500 |
// ContactResponse (DTO)
{
id: number;
name: string; // username or email
email: string;
}
// Prospect (DTO)
{
id: number;
email: string;
}
4. UI Component Contract (Frontend)
Component | Source | Props / State highlights |
---|---|---|
ContactsPage | src/components/contacts/ContactsPage.tsx | contacts , pending , inviteContact(email) |
TaskShareDialog | Uses 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
- Service:
ContactService.inviteContact
. - Steps:
findByEmail
→ if returns customer ⇒ create Contact (bidirectional) if not exists.- Else check
Prospect
duplicate. - If new prospect → save + send email.
- Throws:
CustomerAlreadyAContact
→ map to409 ALREADY_CONTACT
.CustomerEmailAlreadyExists
→ map to200/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
- Bulk Invites – CSV upload → multiple prospects.
- Invite link –
https://mindyournow.com/invite/<token>
for socials. - Rate limiting – one invite/email/day to prevent spam.
- 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 optionallyContacts.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:- Internal
GET /api/contacts/search?query=
- External
GET /api/contacts/external/{source}?query=
- Internal
- 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
- Configure OAuth scopes & backend service hooks (1 week)
- Build external contacts service & endpoints (2 weeks)
- Integrate frontend typeahead & UI components (1 week)
- QA, privacy review & rollout (1 week)