heartraite 1.0.191 → 1.0.193

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.
@@ -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) {
@@ -1,6 +1,7 @@
1
1
  export * from "./app-route.enum";
2
2
  export * from "./ca.enum";
3
3
  export * from "./cloudfunction.enum";
4
+ export * from "./consultation.enum";
4
5
  export * from "./country.enum";
5
6
  export * from "./evaluation.enum";
6
7
  export * from "./environment.enum";
@@ -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,46 @@
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
+ * One pending record per user at a time — the
11
+ * `/consultation/express-interest` endpoint upserts rather than
12
+ * appending so resubmits don't duplicate.
13
+ */
14
+ export type ConsultationInterest = {
15
+ id: string;
16
+ userId: string;
17
+ submittedAt: string;
18
+ status: ConsultationInterestStatus;
19
+ /**
20
+ * Set by the admin endpoint when the team reaches out by email.
21
+ * Stays `undefined` while the record is `PENDING`.
22
+ */
23
+ followUpSentAt?: string;
24
+ /**
25
+ * Internal team notes — never surfaced to the user. Used during
26
+ * the manual follow-up phase to track context ("emailed 2026-05-
27
+ * 14, awaiting reply", "user confirmed availability X/Y/Z", etc).
28
+ */
29
+ notes?: string;
30
+ };
31
+ /**
32
+ * The user-facing summary returned from
33
+ * `/consultation/my-interest`. Replaces the AsyncStorage flag in
34
+ * youand-app — the screen reads this on mount to decide whether
35
+ * to show the "Anmäl intresse" CTA or the post-submit "Tack — vi
36
+ * hör av oss" confirmation state.
37
+ *
38
+ * Carries just enough for the UI to render the two states; the
39
+ * full `ConsultationInterest` record (notes, internal status
40
+ * machinery) stays admin-only.
41
+ */
42
+ export type ConsultationInterestSummary = {
43
+ hasInterest: boolean;
44
+ submittedAt: string | null;
45
+ status: ConsultationInterestStatus | null;
46
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -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";
@@ -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,24 @@ export type SubmitFeedbackRequest = {
59
59
  context?: string;
60
60
  rating?: number;
61
61
  };
62
+ export type ExpressConsultationInterestRequest = undefined;
63
+ export type GetMyConsultationInterestRequest = undefined;
64
+ export type GetConsultationInterestsRequest = {
65
+ /**
66
+ * Optional status filter. Omit to fetch every record. Most
67
+ * common use is `PENDING` for the team's outreach worklist.
68
+ */
69
+ status?: ConsultationInterestStatus;
70
+ };
71
+ export type UpdateConsultationInterestRequest = {
72
+ id: string;
73
+ status: ConsultationInterestStatus;
74
+ /**
75
+ * Internal team-only notes. Trim before sending; empty / unset
76
+ * leaves the previous value in place.
77
+ */
78
+ notes?: string;
79
+ };
62
80
  export type HandleLastMessageSeenRequest = {
63
81
  conversationId: string;
64
82
  };
@@ -154,11 +172,13 @@ export type RegisterOnboardingRequest = {
154
172
  interestedIn: Gender[];
155
173
  gender: Gender;
156
174
  /** Client-resolved market (e.g. localeService.getMarketSync() in youand-app).
157
- * Required in the contract; the backend DTO accepts it as optional during
158
- * the rollout window so old in-the-wild app builds (which compile against
159
- * pre-1.0.191 types) still pass validation and fall back to the existing
160
- * users.market. Tighten DTO to required once adoption is high. */
161
- market: Market;
175
+ * Optional during the rollout youand-app doesn't yet populate it. Tighten
176
+ * to required once youand-app ships the change. The backend uses this to
177
+ * (a) keep users.market in sync if the device locale changed since signup
178
+ * and (b) recover the correct market for users self-healed by
179
+ * registerOnboarding. The backend MUST NOT update users.market when this
180
+ * field is absent (preserve the existing value). */
181
+ market?: Market;
162
182
  };
163
183
  export type GetUserRequest = undefined;
164
184
  export type UpdateUserRequest = {
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "heartraite",
3
- "version": "1.0.191",
3
+ "version": "1.0.193",
4
4
  "description": "Heartraite npm package for common functionality",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -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
+ }
@@ -15,6 +15,7 @@ export enum FirestoreCollection {
15
15
  PLS_ASSESSMENTS = "pls_assessments",
16
16
  PLS_SCORES = "pls_scores",
17
17
  PENDING_USERS = "pending_users",
18
+ CONSULTATION_INTERESTS = "consultation_interests",
18
19
  }
19
20
 
20
21
  export enum ConversationCollection {
package/src/enum/index.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from "./app-route.enum";
2
2
  export * from "./ca.enum";
3
3
  export * from "./cloudfunction.enum";
4
+ export * from "./consultation.enum";
4
5
  export * from "./country.enum";
5
6
  export * from "./evaluation.enum";
6
7
  export * from "./environment.enum";
@@ -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,48 @@
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
+ * One pending record per user at a time — the
12
+ * `/consultation/express-interest` endpoint upserts rather than
13
+ * appending so resubmits don't duplicate.
14
+ */
15
+ export type ConsultationInterest = {
16
+ id: string;
17
+ userId: string;
18
+ submittedAt: string;
19
+ status: ConsultationInterestStatus;
20
+ /**
21
+ * Set by the admin endpoint when the team reaches out by email.
22
+ * Stays `undefined` while the record is `PENDING`.
23
+ */
24
+ followUpSentAt?: string;
25
+ /**
26
+ * Internal team notes — never surfaced to the user. Used during
27
+ * the manual follow-up phase to track context ("emailed 2026-05-
28
+ * 14, awaiting reply", "user confirmed availability X/Y/Z", etc).
29
+ */
30
+ notes?: string;
31
+ };
32
+
33
+ /**
34
+ * The user-facing summary returned from
35
+ * `/consultation/my-interest`. Replaces the AsyncStorage flag in
36
+ * youand-app — the screen reads this on mount to decide whether
37
+ * to show the "Anmäl intresse" CTA or the post-submit "Tack — vi
38
+ * hör av oss" confirmation state.
39
+ *
40
+ * Carries just enough for the UI to render the two states; the
41
+ * full `ConsultationInterest` record (notes, internal status
42
+ * machinery) stays admin-only.
43
+ */
44
+ export type ConsultationInterestSummary = {
45
+ hasInterest: boolean;
46
+ submittedAt: string | null;
47
+ status: ConsultationInterestStatus | null;
48
+ };
@@ -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,35 @@ 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 AuthGuard'd from the user-facing side (express +
94
+ // my-interest) and AdminGuard'd from the team side (admin-interests
95
+ // + admin-update-interest). The express + my-interest payloads are
96
+ // intentionally empty / minimal — userId comes from the request's
97
+ // authed token, never the client.
98
+ export type ExpressConsultationInterestRequest = undefined;
99
+
100
+ export type GetMyConsultationInterestRequest = undefined;
101
+
102
+ export type GetConsultationInterestsRequest = {
103
+ /**
104
+ * Optional status filter. Omit to fetch every record. Most
105
+ * common use is `PENDING` for the team's outreach worklist.
106
+ */
107
+ status?: ConsultationInterestStatus;
108
+ };
109
+
110
+ export type UpdateConsultationInterestRequest = {
111
+ id: string;
112
+ status: ConsultationInterestStatus;
113
+ /**
114
+ * Internal team-only notes. Trim before sending; empty / unset
115
+ * leaves the previous value in place.
116
+ */
117
+ notes?: string;
118
+ };
119
+
90
120
  // message
91
121
  export type HandleLastMessageSeenRequest = {
92
122
  conversationId: string;
@@ -178,11 +208,13 @@ export type RegisterOnboardingRequest = {
178
208
  interestedIn: Gender[];
179
209
  gender: Gender;
180
210
  /** Client-resolved market (e.g. localeService.getMarketSync() in youand-app).
181
- * Required in the contract; the backend DTO accepts it as optional during
182
- * the rollout window so old in-the-wild app builds (which compile against
183
- * pre-1.0.191 types) still pass validation and fall back to the existing
184
- * users.market. Tighten DTO to required once adoption is high. */
185
- market: Market;
211
+ * Optional during the rollout youand-app doesn't yet populate it. Tighten
212
+ * to required once youand-app ships the change. The backend uses this to
213
+ * (a) keep users.market in sync if the device locale changed since signup
214
+ * and (b) recover the correct market for users self-healed by
215
+ * registerOnboarding. The backend MUST NOT update users.market when this
216
+ * field is absent (preserve the existing value). */
217
+ market?: Market;
186
218
  };
187
219
  export type GetUserRequest = undefined;
188
220
  export type UpdateUserRequest = {
@@ -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;