heartraite 1.0.192 → 1.0.194
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/enum/cloudfunction.enum.d.ts +4 -0
- package/dist/enum/cloudfunction.enum.js +4 -0
- package/dist/enum/consultation.enum.d.ts +27 -0
- package/dist/enum/consultation.enum.js +31 -0
- package/dist/enum/firestore.enum.d.ts +2 -1
- package/dist/enum/firestore.enum.js +1 -0
- package/dist/enum/index.d.ts +1 -0
- package/dist/enum/index.js +1 -0
- package/dist/types/cloud-function-types.d.ts +18 -2
- package/dist/types/consultation.types.d.ts +62 -0
- package/dist/types/consultation.types.js +2 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/request.types.d.ts +28 -1
- package/dist/types/response.types.d.ts +5 -0
- package/package.json +1 -1
- package/src/enum/cloudfunction.enum.ts +4 -0
- package/src/enum/consultation.enum.ts +27 -0
- package/src/enum/firestore.enum.ts +1 -0
- package/src/enum/index.ts +1 -0
- package/src/types/cloud-function-types.ts +26 -0
- package/src/types/consultation.types.ts +64 -0
- package/src/types/index.ts +1 -0
- package/src/types/request.types.ts +41 -0
- package/src/types/response.types.ts +16 -0
|
@@ -4,6 +4,10 @@ export declare enum CloudFunction {
|
|
|
4
4
|
AUTHENTICATE_BANKID = "bankid/authenticate",
|
|
5
5
|
COLLECT_BANKID = "bankid/collect",
|
|
6
6
|
SUBMIT_FEEDBACK = "feedback/submit-feedback",
|
|
7
|
+
EXPRESS_CONSULTATION_INTEREST = "consultation/express-interest",
|
|
8
|
+
GET_MY_CONSULTATION_INTEREST = "consultation/my-interest",
|
|
9
|
+
GET_CONSULTATION_INTERESTS = "consultation/admin-interests",
|
|
10
|
+
UPDATE_CONSULTATION_INTEREST = "consultation/admin-update-interest",
|
|
7
11
|
GET_CA = "ca/get-ca",
|
|
8
12
|
SUBMIT_ANSWER = "ca/submit-answer",
|
|
9
13
|
SEND_EVENT_FEEDBACK = "event/send-event-feedback",
|
|
@@ -8,6 +8,10 @@ var CloudFunction;
|
|
|
8
8
|
CloudFunction["AUTHENTICATE_BANKID"] = "bankid/authenticate";
|
|
9
9
|
CloudFunction["COLLECT_BANKID"] = "bankid/collect";
|
|
10
10
|
CloudFunction["SUBMIT_FEEDBACK"] = "feedback/submit-feedback";
|
|
11
|
+
CloudFunction["EXPRESS_CONSULTATION_INTEREST"] = "consultation/express-interest";
|
|
12
|
+
CloudFunction["GET_MY_CONSULTATION_INTEREST"] = "consultation/my-interest";
|
|
13
|
+
CloudFunction["GET_CONSULTATION_INTERESTS"] = "consultation/admin-interests";
|
|
14
|
+
CloudFunction["UPDATE_CONSULTATION_INTEREST"] = "consultation/admin-update-interest";
|
|
11
15
|
CloudFunction["GET_CA"] = "ca/get-ca";
|
|
12
16
|
CloudFunction["SUBMIT_ANSWER"] = "ca/submit-answer";
|
|
13
17
|
CloudFunction["SEND_EVENT_FEEDBACK"] = "event/send-event-feedback";
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State machine for a user's expression of interest in a 1:1
|
|
3
|
+
* consultation with a credentialed professional (psychologist,
|
|
4
|
+
* therapist, etc.). v1 ships the "interest list" MVP where the
|
|
5
|
+
* team manually follows up by email; v2 will add real booking +
|
|
6
|
+
* payment, at which point the later states get exercised.
|
|
7
|
+
*
|
|
8
|
+
* PENDING → user expressed interest, team hasn't reached
|
|
9
|
+
* out yet. Initial state on submit.
|
|
10
|
+
* FOLLOWED_UP → team emailed the user. v1 manual; v2 may be
|
|
11
|
+
* automated after a Stripe charge.
|
|
12
|
+
* BOOKED → consultation session scheduled (v2 only — v1
|
|
13
|
+
* tracks this only via team-internal notes).
|
|
14
|
+
* COMPLETED → session happened.
|
|
15
|
+
* DECLINED → user backed out / team declined the request.
|
|
16
|
+
*
|
|
17
|
+
* v1 only relies on the PENDING → FOLLOWED_UP transition driven
|
|
18
|
+
* by an admin action. Future states are reserved so the type
|
|
19
|
+
* shape doesn't change when the booking flow lands.
|
|
20
|
+
*/
|
|
21
|
+
export declare enum ConsultationInterestStatus {
|
|
22
|
+
PENDING = "PENDING",
|
|
23
|
+
FOLLOWED_UP = "FOLLOWED_UP",
|
|
24
|
+
BOOKED = "BOOKED",
|
|
25
|
+
COMPLETED = "COMPLETED",
|
|
26
|
+
DECLINED = "DECLINED"
|
|
27
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ConsultationInterestStatus = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* State machine for a user's expression of interest in a 1:1
|
|
6
|
+
* consultation with a credentialed professional (psychologist,
|
|
7
|
+
* therapist, etc.). v1 ships the "interest list" MVP where the
|
|
8
|
+
* team manually follows up by email; v2 will add real booking +
|
|
9
|
+
* payment, at which point the later states get exercised.
|
|
10
|
+
*
|
|
11
|
+
* PENDING → user expressed interest, team hasn't reached
|
|
12
|
+
* out yet. Initial state on submit.
|
|
13
|
+
* FOLLOWED_UP → team emailed the user. v1 manual; v2 may be
|
|
14
|
+
* automated after a Stripe charge.
|
|
15
|
+
* BOOKED → consultation session scheduled (v2 only — v1
|
|
16
|
+
* tracks this only via team-internal notes).
|
|
17
|
+
* COMPLETED → session happened.
|
|
18
|
+
* DECLINED → user backed out / team declined the request.
|
|
19
|
+
*
|
|
20
|
+
* v1 only relies on the PENDING → FOLLOWED_UP transition driven
|
|
21
|
+
* by an admin action. Future states are reserved so the type
|
|
22
|
+
* shape doesn't change when the booking flow lands.
|
|
23
|
+
*/
|
|
24
|
+
var ConsultationInterestStatus;
|
|
25
|
+
(function (ConsultationInterestStatus) {
|
|
26
|
+
ConsultationInterestStatus["PENDING"] = "PENDING";
|
|
27
|
+
ConsultationInterestStatus["FOLLOWED_UP"] = "FOLLOWED_UP";
|
|
28
|
+
ConsultationInterestStatus["BOOKED"] = "BOOKED";
|
|
29
|
+
ConsultationInterestStatus["COMPLETED"] = "COMPLETED";
|
|
30
|
+
ConsultationInterestStatus["DECLINED"] = "DECLINED";
|
|
31
|
+
})(ConsultationInterestStatus || (exports.ConsultationInterestStatus = ConsultationInterestStatus = {}));
|
|
@@ -14,7 +14,8 @@ export declare enum FirestoreCollection {
|
|
|
14
14
|
PLS_INPUTS = "pls_inputs",
|
|
15
15
|
PLS_ASSESSMENTS = "pls_assessments",
|
|
16
16
|
PLS_SCORES = "pls_scores",
|
|
17
|
-
PENDING_USERS = "pending_users"
|
|
17
|
+
PENDING_USERS = "pending_users",
|
|
18
|
+
CONSULTATION_INTERESTS = "consultation_interests"
|
|
18
19
|
}
|
|
19
20
|
export declare enum ConversationCollection {
|
|
20
21
|
MESSAGES = "messages"
|
|
@@ -19,6 +19,7 @@ var FirestoreCollection;
|
|
|
19
19
|
FirestoreCollection["PLS_ASSESSMENTS"] = "pls_assessments";
|
|
20
20
|
FirestoreCollection["PLS_SCORES"] = "pls_scores";
|
|
21
21
|
FirestoreCollection["PENDING_USERS"] = "pending_users";
|
|
22
|
+
FirestoreCollection["CONSULTATION_INTERESTS"] = "consultation_interests";
|
|
22
23
|
})(FirestoreCollection || (exports.FirestoreCollection = FirestoreCollection = {}));
|
|
23
24
|
var ConversationCollection;
|
|
24
25
|
(function (ConversationCollection) {
|
package/dist/enum/index.d.ts
CHANGED
package/dist/enum/index.js
CHANGED
|
@@ -17,6 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./app-route.enum"), exports);
|
|
18
18
|
__exportStar(require("./ca.enum"), exports);
|
|
19
19
|
__exportStar(require("./cloudfunction.enum"), exports);
|
|
20
|
+
__exportStar(require("./consultation.enum"), exports);
|
|
20
21
|
__exportStar(require("./country.enum"), exports);
|
|
21
22
|
__exportStar(require("./evaluation.enum"), exports);
|
|
22
23
|
__exportStar(require("./environment.enum"), exports);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CloudFunction } from "../enum";
|
|
2
|
-
import { AddImagesRequest, AuthenticateBankIDRequest, CollectBankIDRequest, CreateBillingPortalRequest, CreateCheckoutSessionRequest, CreateLikeRequest, CreatePLSInputRequest, CreatePLSSubmissionRequest, CreateReportRequest, DeleteUserRequest, GetCARequest, GetLikesRequest, GetMatchableUserRequest, GetMatchCheckRequest, GetMatchesRequest, GetAdvancedMatchRequest, GetMessagesRequest, GetPLSSubmissionRequest, GetProductsRequest, GetSelfAwarenessRequest, GetUserRequest, HandleLastMessageSeenRequest, HandleLikeSeenRequest, HandleMatchSeenRequest, RegisterOnboardingRequest, RegisterUserRequest, RemoveMatchRequest, SendMessageRequest, SubmitAnswerRequest, SubmitCategoryFeedbackRequest, SubmitPLSCategoryFeedbackRequest, SubmitPLSDemographicsRequest, UpdatePLSAnswerRequest, UpdateQuestionsRequest, UpdateUserRequest, SubmitFeedbackRequest, SyncAffiliateRequest, JoinEventRequest, GetEventRequest, GetEventMatchRequest, SendEventFeedbackRequest, GetEventParticipantsRequest } from "./request.types";
|
|
3
|
-
import { AddImagesResponse, AuthenticateBankIDResponse, CollectBankIDResponse, CreateBillingPortalResponse, CreateCheckoutSessionResponse, CreateLikeResponse, CreatePLSInputResponse, CreatePLSSubmissionResponse, CreateReportResponse, DeleteUserResponse, GetCAResponse, GetLikesResponse, GetMatchableUserResponse, GetMatchableUsersResponse, GetMatchCheckResponse, GetMatchesResponse, GetAdvancedMatchResponse, GetMessagesResponse, GetPLSSubmissionResponse, GetProductsResponse, GetSelfAwarenessReponse, GetUserResponse, HandleLastMessageSeenResponse, HandleLikeSeenResponse, HandleMatchSeenResponse, RegisterOnboardingResponse, RegisterUserResponse, RemoveMatchResponse, SendMessageResponse, SubmitAnswerResponse, SubmitCategoryFeedbackResponse, SubmitPLSCategoryFeedbackResponse, SubmitPLSDemographicsResponse, UpdatePLSAnswerResponse, UpdateQuestionsResponse, UpdateUserResponse, SubmitFeedbackResponse, SyncAffiliateResponse, GetUserEventsResponse, JoinEventResponse, GetEventResponse, GetEventMatchResponse, SendEventFeedbackResponse, GetEventParticipantsResponse } from "./response.types";
|
|
2
|
+
import { AddImagesRequest, AuthenticateBankIDRequest, CollectBankIDRequest, CreateBillingPortalRequest, CreateCheckoutSessionRequest, CreateLikeRequest, CreatePLSInputRequest, CreatePLSSubmissionRequest, CreateReportRequest, DeleteUserRequest, GetCARequest, GetLikesRequest, GetMatchableUserRequest, GetMatchCheckRequest, GetMatchesRequest, GetAdvancedMatchRequest, GetMessagesRequest, GetPLSSubmissionRequest, GetProductsRequest, GetSelfAwarenessRequest, GetUserRequest, HandleLastMessageSeenRequest, HandleLikeSeenRequest, HandleMatchSeenRequest, RegisterOnboardingRequest, RegisterUserRequest, RemoveMatchRequest, SendMessageRequest, SubmitAnswerRequest, SubmitCategoryFeedbackRequest, SubmitPLSCategoryFeedbackRequest, SubmitPLSDemographicsRequest, UpdatePLSAnswerRequest, UpdateQuestionsRequest, UpdateUserRequest, SubmitFeedbackRequest, ExpressConsultationInterestRequest, GetMyConsultationInterestRequest, GetConsultationInterestsRequest, UpdateConsultationInterestRequest, SyncAffiliateRequest, JoinEventRequest, GetEventRequest, GetEventMatchRequest, SendEventFeedbackRequest, GetEventParticipantsRequest } from "./request.types";
|
|
3
|
+
import { AddImagesResponse, AuthenticateBankIDResponse, CollectBankIDResponse, CreateBillingPortalResponse, CreateCheckoutSessionResponse, CreateLikeResponse, CreatePLSInputResponse, CreatePLSSubmissionResponse, CreateReportResponse, DeleteUserResponse, GetCAResponse, GetLikesResponse, GetMatchableUserResponse, GetMatchableUsersResponse, GetMatchCheckResponse, GetMatchesResponse, GetAdvancedMatchResponse, GetMessagesResponse, GetPLSSubmissionResponse, GetProductsResponse, GetSelfAwarenessReponse, GetUserResponse, HandleLastMessageSeenResponse, HandleLikeSeenResponse, HandleMatchSeenResponse, RegisterOnboardingResponse, RegisterUserResponse, RemoveMatchResponse, SendMessageResponse, SubmitAnswerResponse, SubmitCategoryFeedbackResponse, SubmitPLSCategoryFeedbackResponse, SubmitPLSDemographicsResponse, UpdatePLSAnswerResponse, UpdateQuestionsResponse, UpdateUserResponse, SubmitFeedbackResponse, ExpressConsultationInterestResponse, GetMyConsultationInterestResponse, GetConsultationInterestsResponse, UpdateConsultationInterestResponse, SyncAffiliateResponse, GetUserEventsResponse, JoinEventResponse, GetEventResponse, GetEventMatchResponse, SendEventFeedbackResponse, GetEventParticipantsResponse } from "./response.types";
|
|
4
4
|
/**
|
|
5
5
|
* @deprecated This function is deprecated.
|
|
6
6
|
* Use `CloudFunctionTypes` inside application code instead.
|
|
@@ -63,6 +63,22 @@ export type CloudFunctionTypes = {
|
|
|
63
63
|
payload: SubmitFeedbackRequest;
|
|
64
64
|
response: SubmitFeedbackResponse;
|
|
65
65
|
};
|
|
66
|
+
[CloudFunction.EXPRESS_CONSULTATION_INTEREST]: {
|
|
67
|
+
payload: ExpressConsultationInterestRequest;
|
|
68
|
+
response: ExpressConsultationInterestResponse;
|
|
69
|
+
};
|
|
70
|
+
[CloudFunction.GET_MY_CONSULTATION_INTEREST]: {
|
|
71
|
+
payload: GetMyConsultationInterestRequest;
|
|
72
|
+
response: GetMyConsultationInterestResponse;
|
|
73
|
+
};
|
|
74
|
+
[CloudFunction.GET_CONSULTATION_INTERESTS]: {
|
|
75
|
+
payload: GetConsultationInterestsRequest;
|
|
76
|
+
response: GetConsultationInterestsResponse;
|
|
77
|
+
};
|
|
78
|
+
[CloudFunction.UPDATE_CONSULTATION_INTEREST]: {
|
|
79
|
+
payload: UpdateConsultationInterestRequest;
|
|
80
|
+
response: UpdateConsultationInterestResponse;
|
|
81
|
+
};
|
|
66
82
|
[CloudFunction.CREATE_LIKE]: {
|
|
67
83
|
payload: CreateLikeRequest;
|
|
68
84
|
response: CreateLikeResponse;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { ConsultationInterestStatus } from "../enum";
|
|
2
|
+
/**
|
|
3
|
+
* A user's expression of interest in a 1:1 consultation with a
|
|
4
|
+
* credentialed professional. v1 surface is "Bohm-samtal" — a video
|
|
5
|
+
* session with Fredric Bohm, recorded as an interest-list entry the
|
|
6
|
+
* team manually follows up on. The domain name stays generic
|
|
7
|
+
* (`Consultation`) so subsequent professionals can land here
|
|
8
|
+
* without a schema rename.
|
|
9
|
+
*
|
|
10
|
+
* `expertId` scopes the record to a specific professional. v1 has
|
|
11
|
+
* exactly one value (`"bohm"`); future additions (other
|
|
12
|
+
* psychologists, therapists, sex therapists, financial planners,
|
|
13
|
+
* etc.) plug in without a schema migration. Idempotency at the
|
|
14
|
+
* backend is `(userId, expertId)` — a user can express interest in
|
|
15
|
+
* multiple experts independently, but only one pending record per
|
|
16
|
+
* (user, expert) pair at any time.
|
|
17
|
+
*
|
|
18
|
+
* The slug format (e.g. `"bohm"`) reads cleanly in logs / admin
|
|
19
|
+
* dashboards. Future v2 may move expert metadata (name, photo,
|
|
20
|
+
* pricing, credentials) into DatoCMS and key entries by their CMS
|
|
21
|
+
* slug — the runtime contract stays the same string.
|
|
22
|
+
*/
|
|
23
|
+
export type ConsultationInterest = {
|
|
24
|
+
id: string;
|
|
25
|
+
userId: string;
|
|
26
|
+
expertId: string;
|
|
27
|
+
submittedAt: string;
|
|
28
|
+
status: ConsultationInterestStatus;
|
|
29
|
+
/**
|
|
30
|
+
* Set by the admin endpoint when the team reaches out by email.
|
|
31
|
+
* Stays `undefined` while the record is `PENDING`.
|
|
32
|
+
*/
|
|
33
|
+
followUpSentAt?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Internal team notes — never surfaced to the user. Used during
|
|
36
|
+
* the manual follow-up phase to track context ("emailed 2026-05-
|
|
37
|
+
* 14, awaiting reply", "user confirmed availability X/Y/Z", etc).
|
|
38
|
+
*/
|
|
39
|
+
notes?: string;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* The user-facing summary returned from
|
|
43
|
+
* `/consultation/my-interest`. Replaces the AsyncStorage flag in
|
|
44
|
+
* youand-app — the screen reads this on mount to decide whether
|
|
45
|
+
* to show the "Anmäl intresse" CTA or the post-submit "Tack — vi
|
|
46
|
+
* hör av oss" confirmation state.
|
|
47
|
+
*
|
|
48
|
+
* Scoped to a single `expertId` (the one the client asked about) —
|
|
49
|
+
* a user with interest in multiple experts gets multiple summaries
|
|
50
|
+
* via multiple calls. v1 only ever asks about `"bohm"`, so the app
|
|
51
|
+
* still has a single CTA flow.
|
|
52
|
+
*
|
|
53
|
+
* Carries just enough for the UI to render the two states; the
|
|
54
|
+
* full `ConsultationInterest` record (notes, internal status
|
|
55
|
+
* machinery) stays admin-only.
|
|
56
|
+
*/
|
|
57
|
+
export type ConsultationInterestSummary = {
|
|
58
|
+
expertId: string;
|
|
59
|
+
hasInterest: boolean;
|
|
60
|
+
submittedAt: string | null;
|
|
61
|
+
status: ConsultationInterestStatus | null;
|
|
62
|
+
};
|
package/dist/types/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export * from "./am.types";
|
|
|
2
2
|
export * from "./assessment.types";
|
|
3
3
|
export * from "./ca.types";
|
|
4
4
|
export * from "./cloud-function-types";
|
|
5
|
+
export * from "./consultation.types";
|
|
5
6
|
export * from "./dq.types";
|
|
6
7
|
export * from "./error.types";
|
|
7
8
|
export * from "./event.types";
|
package/dist/types/index.js
CHANGED
|
@@ -18,6 +18,7 @@ __exportStar(require("./am.types"), exports);
|
|
|
18
18
|
__exportStar(require("./assessment.types"), exports);
|
|
19
19
|
__exportStar(require("./ca.types"), exports);
|
|
20
20
|
__exportStar(require("./cloud-function-types"), exports);
|
|
21
|
+
__exportStar(require("./consultation.types"), exports);
|
|
21
22
|
__exportStar(require("./dq.types"), exports);
|
|
22
23
|
__exportStar(require("./error.types"), exports);
|
|
23
24
|
__exportStar(require("./event.types"), exports);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DislikeReason, FeedbackAgreement, FeedbackType, Gender, LikeType, Market, ProviderType, ReportReason, Theme, UserDeletionReason } from "../enum";
|
|
1
|
+
import { ConsultationInterestStatus, DislikeReason, FeedbackAgreement, FeedbackType, Gender, LikeType, Market, ProviderType, ReportReason, Theme, UserDeletionReason } from "../enum";
|
|
2
2
|
import { DeepPartial } from "./helper.types";
|
|
3
3
|
import { Answer, Demographics } from "./submission.types";
|
|
4
4
|
import { DatingPreferences, UserConsents, UserDevice, UserNotifications, UserProfile, UserSettings } from "./user.types";
|
|
@@ -59,6 +59,33 @@ export type SubmitFeedbackRequest = {
|
|
|
59
59
|
context?: string;
|
|
60
60
|
rating?: number;
|
|
61
61
|
};
|
|
62
|
+
export type ExpressConsultationInterestRequest = {
|
|
63
|
+
expertId: string;
|
|
64
|
+
};
|
|
65
|
+
export type GetMyConsultationInterestRequest = {
|
|
66
|
+
expertId: string;
|
|
67
|
+
};
|
|
68
|
+
export type GetConsultationInterestsRequest = {
|
|
69
|
+
/**
|
|
70
|
+
* Optional status filter. Omit to fetch every record. Most
|
|
71
|
+
* common use is `PENDING` for the team's outreach worklist.
|
|
72
|
+
*/
|
|
73
|
+
status?: ConsultationInterestStatus;
|
|
74
|
+
/**
|
|
75
|
+
* Optional expert filter. Omit for the cross-expert worklist;
|
|
76
|
+
* pass to scope a single professional's outreach queue.
|
|
77
|
+
*/
|
|
78
|
+
expertId?: string;
|
|
79
|
+
};
|
|
80
|
+
export type UpdateConsultationInterestRequest = {
|
|
81
|
+
id: string;
|
|
82
|
+
status: ConsultationInterestStatus;
|
|
83
|
+
/**
|
|
84
|
+
* Internal team-only notes. Trim before sending; empty / unset
|
|
85
|
+
* leaves the previous value in place.
|
|
86
|
+
*/
|
|
87
|
+
notes?: string;
|
|
88
|
+
};
|
|
62
89
|
export type HandleLastMessageSeenRequest = {
|
|
63
90
|
conversationId: string;
|
|
64
91
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ConsultationInterest, ConsultationInterestSummary } from "./consultation.types";
|
|
1
2
|
import { Submission, CategoryEvaluation } from "./submission.types";
|
|
2
3
|
import { Event, FullParticipant, FullParticipantWithCS } from "./event.types";
|
|
3
4
|
import { UserMatch } from "./match.types";
|
|
@@ -46,6 +47,10 @@ export type GetEventParticipantsResponse = {
|
|
|
46
47
|
eventMatchIds: string[];
|
|
47
48
|
};
|
|
48
49
|
export type SubmitFeedbackResponse = undefined;
|
|
50
|
+
export type ExpressConsultationInterestResponse = ConsultationInterestSummary;
|
|
51
|
+
export type GetMyConsultationInterestResponse = ConsultationInterestSummary;
|
|
52
|
+
export type GetConsultationInterestsResponse = ConsultationInterest[];
|
|
53
|
+
export type UpdateConsultationInterestResponse = ConsultationInterest;
|
|
49
54
|
export type HandleLastMessageSeenResponse = undefined;
|
|
50
55
|
export type SendMessageResponse = Message;
|
|
51
56
|
export type GetMessagesResponse = Message[];
|
package/package.json
CHANGED
|
@@ -4,6 +4,10 @@ export enum CloudFunction {
|
|
|
4
4
|
AUTHENTICATE_BANKID = "bankid/authenticate",
|
|
5
5
|
COLLECT_BANKID = "bankid/collect",
|
|
6
6
|
SUBMIT_FEEDBACK = "feedback/submit-feedback",
|
|
7
|
+
EXPRESS_CONSULTATION_INTEREST = "consultation/express-interest",
|
|
8
|
+
GET_MY_CONSULTATION_INTEREST = "consultation/my-interest",
|
|
9
|
+
GET_CONSULTATION_INTERESTS = "consultation/admin-interests",
|
|
10
|
+
UPDATE_CONSULTATION_INTEREST = "consultation/admin-update-interest",
|
|
7
11
|
GET_CA = "ca/get-ca",
|
|
8
12
|
SUBMIT_ANSWER = "ca/submit-answer",
|
|
9
13
|
SEND_EVENT_FEEDBACK = "event/send-event-feedback",
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State machine for a user's expression of interest in a 1:1
|
|
3
|
+
* consultation with a credentialed professional (psychologist,
|
|
4
|
+
* therapist, etc.). v1 ships the "interest list" MVP where the
|
|
5
|
+
* team manually follows up by email; v2 will add real booking +
|
|
6
|
+
* payment, at which point the later states get exercised.
|
|
7
|
+
*
|
|
8
|
+
* PENDING → user expressed interest, team hasn't reached
|
|
9
|
+
* out yet. Initial state on submit.
|
|
10
|
+
* FOLLOWED_UP → team emailed the user. v1 manual; v2 may be
|
|
11
|
+
* automated after a Stripe charge.
|
|
12
|
+
* BOOKED → consultation session scheduled (v2 only — v1
|
|
13
|
+
* tracks this only via team-internal notes).
|
|
14
|
+
* COMPLETED → session happened.
|
|
15
|
+
* DECLINED → user backed out / team declined the request.
|
|
16
|
+
*
|
|
17
|
+
* v1 only relies on the PENDING → FOLLOWED_UP transition driven
|
|
18
|
+
* by an admin action. Future states are reserved so the type
|
|
19
|
+
* shape doesn't change when the booking flow lands.
|
|
20
|
+
*/
|
|
21
|
+
export enum ConsultationInterestStatus {
|
|
22
|
+
PENDING = "PENDING",
|
|
23
|
+
FOLLOWED_UP = "FOLLOWED_UP",
|
|
24
|
+
BOOKED = "BOOKED",
|
|
25
|
+
COMPLETED = "COMPLETED",
|
|
26
|
+
DECLINED = "DECLINED",
|
|
27
|
+
}
|
package/src/enum/index.ts
CHANGED
|
@@ -36,6 +36,10 @@ import {
|
|
|
36
36
|
UpdateQuestionsRequest,
|
|
37
37
|
UpdateUserRequest,
|
|
38
38
|
SubmitFeedbackRequest,
|
|
39
|
+
ExpressConsultationInterestRequest,
|
|
40
|
+
GetMyConsultationInterestRequest,
|
|
41
|
+
GetConsultationInterestsRequest,
|
|
42
|
+
UpdateConsultationInterestRequest,
|
|
39
43
|
SyncAffiliateRequest,
|
|
40
44
|
JoinEventRequest,
|
|
41
45
|
GetEventRequest,
|
|
@@ -81,6 +85,10 @@ import {
|
|
|
81
85
|
UpdateQuestionsResponse,
|
|
82
86
|
UpdateUserResponse,
|
|
83
87
|
SubmitFeedbackResponse,
|
|
88
|
+
ExpressConsultationInterestResponse,
|
|
89
|
+
GetMyConsultationInterestResponse,
|
|
90
|
+
GetConsultationInterestsResponse,
|
|
91
|
+
UpdateConsultationInterestResponse,
|
|
84
92
|
SyncAffiliateResponse,
|
|
85
93
|
GetUserEventsResponse,
|
|
86
94
|
JoinEventResponse,
|
|
@@ -163,6 +171,24 @@ export type CloudFunctionTypes = {
|
|
|
163
171
|
response: SubmitFeedbackResponse;
|
|
164
172
|
};
|
|
165
173
|
|
|
174
|
+
// consultation
|
|
175
|
+
[CloudFunction.EXPRESS_CONSULTATION_INTEREST]: {
|
|
176
|
+
payload: ExpressConsultationInterestRequest;
|
|
177
|
+
response: ExpressConsultationInterestResponse;
|
|
178
|
+
};
|
|
179
|
+
[CloudFunction.GET_MY_CONSULTATION_INTEREST]: {
|
|
180
|
+
payload: GetMyConsultationInterestRequest;
|
|
181
|
+
response: GetMyConsultationInterestResponse;
|
|
182
|
+
};
|
|
183
|
+
[CloudFunction.GET_CONSULTATION_INTERESTS]: {
|
|
184
|
+
payload: GetConsultationInterestsRequest;
|
|
185
|
+
response: GetConsultationInterestsResponse;
|
|
186
|
+
};
|
|
187
|
+
[CloudFunction.UPDATE_CONSULTATION_INTEREST]: {
|
|
188
|
+
payload: UpdateConsultationInterestRequest;
|
|
189
|
+
response: UpdateConsultationInterestResponse;
|
|
190
|
+
};
|
|
191
|
+
|
|
166
192
|
// like
|
|
167
193
|
[CloudFunction.CREATE_LIKE]: {
|
|
168
194
|
payload: CreateLikeRequest;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { ConsultationInterestStatus } from "../enum";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A user's expression of interest in a 1:1 consultation with a
|
|
5
|
+
* credentialed professional. v1 surface is "Bohm-samtal" — a video
|
|
6
|
+
* session with Fredric Bohm, recorded as an interest-list entry the
|
|
7
|
+
* team manually follows up on. The domain name stays generic
|
|
8
|
+
* (`Consultation`) so subsequent professionals can land here
|
|
9
|
+
* without a schema rename.
|
|
10
|
+
*
|
|
11
|
+
* `expertId` scopes the record to a specific professional. v1 has
|
|
12
|
+
* exactly one value (`"bohm"`); future additions (other
|
|
13
|
+
* psychologists, therapists, sex therapists, financial planners,
|
|
14
|
+
* etc.) plug in without a schema migration. Idempotency at the
|
|
15
|
+
* backend is `(userId, expertId)` — a user can express interest in
|
|
16
|
+
* multiple experts independently, but only one pending record per
|
|
17
|
+
* (user, expert) pair at any time.
|
|
18
|
+
*
|
|
19
|
+
* The slug format (e.g. `"bohm"`) reads cleanly in logs / admin
|
|
20
|
+
* dashboards. Future v2 may move expert metadata (name, photo,
|
|
21
|
+
* pricing, credentials) into DatoCMS and key entries by their CMS
|
|
22
|
+
* slug — the runtime contract stays the same string.
|
|
23
|
+
*/
|
|
24
|
+
export type ConsultationInterest = {
|
|
25
|
+
id: string;
|
|
26
|
+
userId: string;
|
|
27
|
+
expertId: string;
|
|
28
|
+
submittedAt: string;
|
|
29
|
+
status: ConsultationInterestStatus;
|
|
30
|
+
/**
|
|
31
|
+
* Set by the admin endpoint when the team reaches out by email.
|
|
32
|
+
* Stays `undefined` while the record is `PENDING`.
|
|
33
|
+
*/
|
|
34
|
+
followUpSentAt?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Internal team notes — never surfaced to the user. Used during
|
|
37
|
+
* the manual follow-up phase to track context ("emailed 2026-05-
|
|
38
|
+
* 14, awaiting reply", "user confirmed availability X/Y/Z", etc).
|
|
39
|
+
*/
|
|
40
|
+
notes?: string;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The user-facing summary returned from
|
|
45
|
+
* `/consultation/my-interest`. Replaces the AsyncStorage flag in
|
|
46
|
+
* youand-app — the screen reads this on mount to decide whether
|
|
47
|
+
* to show the "Anmäl intresse" CTA or the post-submit "Tack — vi
|
|
48
|
+
* hör av oss" confirmation state.
|
|
49
|
+
*
|
|
50
|
+
* Scoped to a single `expertId` (the one the client asked about) —
|
|
51
|
+
* a user with interest in multiple experts gets multiple summaries
|
|
52
|
+
* via multiple calls. v1 only ever asks about `"bohm"`, so the app
|
|
53
|
+
* still has a single CTA flow.
|
|
54
|
+
*
|
|
55
|
+
* Carries just enough for the UI to render the two states; the
|
|
56
|
+
* full `ConsultationInterest` record (notes, internal status
|
|
57
|
+
* machinery) stays admin-only.
|
|
58
|
+
*/
|
|
59
|
+
export type ConsultationInterestSummary = {
|
|
60
|
+
expertId: string;
|
|
61
|
+
hasInterest: boolean;
|
|
62
|
+
submittedAt: string | null;
|
|
63
|
+
status: ConsultationInterestStatus | null;
|
|
64
|
+
};
|
package/src/types/index.ts
CHANGED
|
@@ -2,6 +2,7 @@ export * from "./am.types";
|
|
|
2
2
|
export * from "./assessment.types";
|
|
3
3
|
export * from "./ca.types";
|
|
4
4
|
export * from "./cloud-function-types";
|
|
5
|
+
export * from "./consultation.types";
|
|
5
6
|
export * from "./dq.types";
|
|
6
7
|
export * from "./error.types";
|
|
7
8
|
export * from "./event.types";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ConsultationInterestStatus,
|
|
2
3
|
DislikeReason,
|
|
3
4
|
FeedbackAgreement,
|
|
4
5
|
FeedbackType,
|
|
@@ -87,6 +88,46 @@ export type SubmitFeedbackRequest = {
|
|
|
87
88
|
rating?: number;
|
|
88
89
|
};
|
|
89
90
|
|
|
91
|
+
// consultation — 1:1 video sessions with credentialed professionals
|
|
92
|
+
//
|
|
93
|
+
// v1 endpoints are CAGuard'd from the user-facing side (express +
|
|
94
|
+
// my-interest, gated on completed CA) and AdminGuard'd from the
|
|
95
|
+
// team side (admin-interests + admin-update-interest). userId
|
|
96
|
+
// always comes from the authed token, never the client. `expertId`
|
|
97
|
+
// scopes the request to a specific professional — v1 only sends
|
|
98
|
+
// `"bohm"` but the field is required so the schema is stable when
|
|
99
|
+
// future experts land.
|
|
100
|
+
export type ExpressConsultationInterestRequest = {
|
|
101
|
+
expertId: string;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export type GetMyConsultationInterestRequest = {
|
|
105
|
+
expertId: string;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export type GetConsultationInterestsRequest = {
|
|
109
|
+
/**
|
|
110
|
+
* Optional status filter. Omit to fetch every record. Most
|
|
111
|
+
* common use is `PENDING` for the team's outreach worklist.
|
|
112
|
+
*/
|
|
113
|
+
status?: ConsultationInterestStatus;
|
|
114
|
+
/**
|
|
115
|
+
* Optional expert filter. Omit for the cross-expert worklist;
|
|
116
|
+
* pass to scope a single professional's outreach queue.
|
|
117
|
+
*/
|
|
118
|
+
expertId?: string;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export type UpdateConsultationInterestRequest = {
|
|
122
|
+
id: string;
|
|
123
|
+
status: ConsultationInterestStatus;
|
|
124
|
+
/**
|
|
125
|
+
* Internal team-only notes. Trim before sending; empty / unset
|
|
126
|
+
* leaves the previous value in place.
|
|
127
|
+
*/
|
|
128
|
+
notes?: string;
|
|
129
|
+
};
|
|
130
|
+
|
|
90
131
|
// message
|
|
91
132
|
export type HandleLastMessageSeenRequest = {
|
|
92
133
|
conversationId: string;
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ConsultationInterest,
|
|
3
|
+
ConsultationInterestSummary,
|
|
4
|
+
} from "./consultation.types";
|
|
1
5
|
import { Submission, CategoryEvaluation } from "./submission.types";
|
|
2
6
|
import { Event, FullParticipant, FullParticipantWithCS } from "./event.types";
|
|
3
7
|
import { UserMatch } from "./match.types";
|
|
@@ -60,6 +64,18 @@ export type GetEventParticipantsResponse = {
|
|
|
60
64
|
// feedback
|
|
61
65
|
export type SubmitFeedbackResponse = undefined;
|
|
62
66
|
|
|
67
|
+
// consultation
|
|
68
|
+
//
|
|
69
|
+
// `Express` returns the freshly-recorded summary so the app can
|
|
70
|
+
// flip into the "Tack — vi hör av oss" state without a follow-up
|
|
71
|
+
// fetch. `GetMyConsultationInterest` returns the same summary;
|
|
72
|
+
// admin endpoints return the full record(s) with internal notes
|
|
73
|
+
// + audit fields.
|
|
74
|
+
export type ExpressConsultationInterestResponse = ConsultationInterestSummary;
|
|
75
|
+
export type GetMyConsultationInterestResponse = ConsultationInterestSummary;
|
|
76
|
+
export type GetConsultationInterestsResponse = ConsultationInterest[];
|
|
77
|
+
export type UpdateConsultationInterestResponse = ConsultationInterest;
|
|
78
|
+
|
|
63
79
|
// message
|
|
64
80
|
export type HandleLastMessageSeenResponse = undefined;
|
|
65
81
|
export type SendMessageResponse = Message;
|