@planningcenter/chat-react-native 3.13.1-rc.2 → 3.13.1-rc.3

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.
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { IconString } from './icon';
3
- export declare const ActionButton: ({ visible, disabled, onPress, title, infoText, buttonIconNameLeft, secondaryButton, }: {
3
+ export declare const ActionButton: ({ visible, disabled, onPress, title, infoText, buttonIconNameLeft, secondaryButton, loading, }: {
4
4
  visible?: boolean;
5
5
  disabled?: boolean;
6
6
  onPress: () => void;
@@ -8,5 +8,6 @@ export declare const ActionButton: ({ visible, disabled, onPress, title, infoTex
8
8
  infoText?: string;
9
9
  buttonIconNameLeft?: IconString;
10
10
  secondaryButton?: React.ReactNode;
11
+ loading?: boolean;
11
12
  }) => React.JSX.Element | null;
12
13
  //# sourceMappingURL=action_button.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"action_button.d.ts","sourceRoot":"","sources":["../../../src/components/display/action_button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAA;AAOvC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAEnC,eAAO,MAAM,YAAY,0FAQtB;IACD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,kBAAkB,CAAC,EAAE,UAAU,CAAA;IAC/B,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAClC,6BAkCA,CAAA"}
1
+ {"version":3,"file":"action_button.d.ts","sourceRoot":"","sources":["../../../src/components/display/action_button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAA;AAOvC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAEnC,eAAO,MAAM,YAAY,mGAStB;IACD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,kBAAkB,CAAC,EAAE,UAAU,CAAA;IAC/B,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACjC,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,6BAmCA,CAAA"}
@@ -5,7 +5,7 @@ import { useEffect } from 'react';
5
5
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
6
6
  import { useTheme } from '../../hooks';
7
7
  import { Text } from './text';
8
- export const ActionButton = ({ visible = true, disabled = false, onPress, title, infoText, buttonIconNameLeft, secondaryButton, }) => {
8
+ export const ActionButton = ({ visible = true, disabled = false, onPress, title, infoText, buttonIconNameLeft, secondaryButton, loading = false, }) => {
9
9
  const styles = useStyles();
10
10
  const [show, setShow] = useState(visible);
11
11
  useEffect(() => {
@@ -22,7 +22,7 @@ export const ActionButton = ({ visible = true, disabled = false, onPress, title,
22
22
  </Text>)}
23
23
  <View style={styles.buttonRow}>
24
24
  {secondaryButton}
25
- <Button variant="fill" size="lg" onPress={onPress} title={title} disabled={disabled} style={secondaryButton ? null : styles.fullWidthButton} iconNameLeft={buttonIconNameLeft}/>
25
+ <Button variant="fill" size="lg" onPress={onPress} title={title} disabled={disabled} style={secondaryButton ? null : styles.fullWidthButton} iconNameLeft={buttonIconNameLeft} loading={loading}/>
26
26
  </View>
27
27
  </Animated.View>);
28
28
  };
@@ -1 +1 @@
1
- {"version":3,"file":"action_button.js","sourceRoot":"","sources":["../../../src/components/display/action_button.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useState } from 'react'\nimport { Animated, LayoutAnimation, StyleSheet, useWindowDimensions, View } from 'react-native'\nimport { Button } from './button'\nimport { useEffect } from 'react'\nimport { useSafeAreaInsets } from 'react-native-safe-area-context'\nimport { useTheme } from '../../hooks'\nimport { Text } from './text'\nimport { IconString } from './icon'\n\nexport const ActionButton = ({\n visible = true,\n disabled = false,\n onPress,\n title,\n infoText,\n buttonIconNameLeft,\n secondaryButton,\n}: {\n visible?: boolean\n disabled?: boolean\n onPress: () => void\n title: string\n infoText?: string\n buttonIconNameLeft?: IconString\n secondaryButton?: React.ReactNode\n}) => {\n const styles = useStyles()\n const [show, setShow] = useState(visible)\n\n useEffect(() => {\n if (show === visible) return\n\n setShow(visible)\n LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)\n }, [show, visible])\n\n if (!visible) return null\n\n return (\n <Animated.View style={styles.container}>\n {Boolean(infoText) && (\n <Text style={styles.infoText} variant=\"footnote\">\n {infoText}\n </Text>\n )}\n <View style={styles.buttonRow}>\n {secondaryButton}\n <Button\n variant=\"fill\"\n size=\"lg\"\n onPress={onPress}\n title={title}\n disabled={disabled}\n style={secondaryButton ? null : styles.fullWidthButton}\n iconNameLeft={buttonIconNameLeft}\n />\n </View>\n </Animated.View>\n )\n}\n\nconst SCALE_THAT_BUTTONS_WRAP = 1.2\n\nconst useStyles = () => {\n const { fontScale } = useWindowDimensions()\n const { bottom } = useSafeAreaInsets()\n const { colors } = useTheme()\n const containerVerticalPadding = 16\n const isButtonsWrapping = fontScale >= SCALE_THAT_BUTTONS_WRAP\n\n return StyleSheet.create({\n container: {\n backgroundColor: colors.surfaceColor090,\n paddingHorizontal: 24,\n paddingTop: containerVerticalPadding,\n paddingBottom: bottom + containerVerticalPadding,\n borderTopWidth: 1,\n borderTopColor: colors.borderColorDefaultDim,\n gap: 16,\n },\n buttonRow: {\n flexDirection: 'row',\n justifyContent: isButtonsWrapping ? 'center' : 'space-between',\n alignItems: 'center',\n gap: 16,\n flexWrap: 'wrap-reverse',\n },\n fullWidthButton: {\n flexGrow: 1,\n },\n infoText: {\n textAlign: 'center',\n },\n })\n}\n"]}
1
+ {"version":3,"file":"action_button.js","sourceRoot":"","sources":["../../../src/components/display/action_button.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useState } from 'react'\nimport { Animated, LayoutAnimation, StyleSheet, useWindowDimensions, View } from 'react-native'\nimport { Button } from './button'\nimport { useEffect } from 'react'\nimport { useSafeAreaInsets } from 'react-native-safe-area-context'\nimport { useTheme } from '../../hooks'\nimport { Text } from './text'\nimport { IconString } from './icon'\n\nexport const ActionButton = ({\n visible = true,\n disabled = false,\n onPress,\n title,\n infoText,\n buttonIconNameLeft,\n secondaryButton,\n loading = false,\n}: {\n visible?: boolean\n disabled?: boolean\n onPress: () => void\n title: string\n infoText?: string\n buttonIconNameLeft?: IconString\n secondaryButton?: React.ReactNode\n loading?: boolean\n}) => {\n const styles = useStyles()\n const [show, setShow] = useState(visible)\n\n useEffect(() => {\n if (show === visible) return\n\n setShow(visible)\n LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)\n }, [show, visible])\n\n if (!visible) return null\n\n return (\n <Animated.View style={styles.container}>\n {Boolean(infoText) && (\n <Text style={styles.infoText} variant=\"footnote\">\n {infoText}\n </Text>\n )}\n <View style={styles.buttonRow}>\n {secondaryButton}\n <Button\n variant=\"fill\"\n size=\"lg\"\n onPress={onPress}\n title={title}\n disabled={disabled}\n style={secondaryButton ? null : styles.fullWidthButton}\n iconNameLeft={buttonIconNameLeft}\n loading={loading}\n />\n </View>\n </Animated.View>\n )\n}\n\nconst SCALE_THAT_BUTTONS_WRAP = 1.2\n\nconst useStyles = () => {\n const { fontScale } = useWindowDimensions()\n const { bottom } = useSafeAreaInsets()\n const { colors } = useTheme()\n const containerVerticalPadding = 16\n const isButtonsWrapping = fontScale >= SCALE_THAT_BUTTONS_WRAP\n\n return StyleSheet.create({\n container: {\n backgroundColor: colors.surfaceColor090,\n paddingHorizontal: 24,\n paddingTop: containerVerticalPadding,\n paddingBottom: bottom + containerVerticalPadding,\n borderTopWidth: 1,\n borderTopColor: colors.borderColorDefaultDim,\n gap: 16,\n },\n buttonRow: {\n flexDirection: 'row',\n justifyContent: isButtonsWrapping ? 'center' : 'space-between',\n alignItems: 'center',\n gap: 16,\n flexWrap: 'wrap-reverse',\n },\n fullWidthButton: {\n flexGrow: 1,\n },\n infoText: {\n textAlign: 'center',\n },\n })\n}\n"]}
@@ -1,11 +1,98 @@
1
- import { ConversationResource } from '../../types';
1
+ import { ApiCollection, ApiResource, ConversationResource, ServicesChatGroupIdentifiersResource, ServicesChatPayloadResource } from '../../types';
2
2
  import { ApiClient } from '../use_api_client';
3
3
  interface Props {
4
- teamIds: number[];
4
+ teamIds?: number[];
5
5
  planId?: number;
6
6
  onSuccess?: (conversation: ConversationResource) => void;
7
7
  }
8
- export declare function useFindOrCreateServicesConversation({ teamIds, planId, onSuccess }: Props): import("@tanstack/react-query").UseMutationResult<ConversationResource, Error, void, unknown>;
9
- export declare const findOrCreateServicesConversation: (apiClient: ApiClient, teamIds: number[], planId?: number) => Promise<ConversationResource>;
8
+ interface TeamAndPlanParams {
9
+ team_id?: string | null;
10
+ plan_id?: number;
11
+ }
12
+ export declare const useFindOrCreateServicesConversation: ({ teamIds, planId, onSuccess }: Props) => {
13
+ selectionHasConversation: boolean;
14
+ isLoadingConversationCheck: boolean;
15
+ data: undefined;
16
+ variables: undefined;
17
+ error: null;
18
+ isError: false;
19
+ isIdle: true;
20
+ isPending: false;
21
+ isSuccess: false;
22
+ status: "idle";
23
+ mutate: import("@tanstack/react-query").UseMutateFunction<ConversationResource, Error, void, unknown>;
24
+ reset: () => void;
25
+ context: unknown;
26
+ failureCount: number;
27
+ failureReason: Error | null;
28
+ isPaused: boolean;
29
+ submittedAt: number;
30
+ mutateAsync: import("@tanstack/react-query").UseMutateAsyncFunction<ConversationResource, Error, void, unknown>;
31
+ } | {
32
+ selectionHasConversation: boolean;
33
+ isLoadingConversationCheck: boolean;
34
+ data: undefined;
35
+ variables: void;
36
+ error: null;
37
+ isError: false;
38
+ isIdle: false;
39
+ isPending: true;
40
+ isSuccess: false;
41
+ status: "pending";
42
+ mutate: import("@tanstack/react-query").UseMutateFunction<ConversationResource, Error, void, unknown>;
43
+ reset: () => void;
44
+ context: unknown;
45
+ failureCount: number;
46
+ failureReason: Error | null;
47
+ isPaused: boolean;
48
+ submittedAt: number;
49
+ mutateAsync: import("@tanstack/react-query").UseMutateAsyncFunction<ConversationResource, Error, void, unknown>;
50
+ } | {
51
+ selectionHasConversation: boolean;
52
+ isLoadingConversationCheck: boolean;
53
+ data: undefined;
54
+ error: Error;
55
+ variables: void;
56
+ isError: true;
57
+ isIdle: false;
58
+ isPending: false;
59
+ isSuccess: false;
60
+ status: "error";
61
+ mutate: import("@tanstack/react-query").UseMutateFunction<ConversationResource, Error, void, unknown>;
62
+ reset: () => void;
63
+ context: unknown;
64
+ failureCount: number;
65
+ failureReason: Error | null;
66
+ isPaused: boolean;
67
+ submittedAt: number;
68
+ mutateAsync: import("@tanstack/react-query").UseMutateAsyncFunction<ConversationResource, Error, void, unknown>;
69
+ } | {
70
+ selectionHasConversation: boolean;
71
+ isLoadingConversationCheck: boolean;
72
+ data: ConversationResource;
73
+ error: null;
74
+ variables: void;
75
+ isError: false;
76
+ isIdle: false;
77
+ isPending: false;
78
+ isSuccess: true;
79
+ status: "success";
80
+ mutate: import("@tanstack/react-query").UseMutateFunction<ConversationResource, Error, void, unknown>;
81
+ reset: () => void;
82
+ context: unknown;
83
+ failureCount: number;
84
+ failureReason: Error | null;
85
+ isPaused: boolean;
86
+ submittedAt: number;
87
+ mutateAsync: import("@tanstack/react-query").UseMutateAsyncFunction<ConversationResource, Error, void, unknown>;
88
+ };
89
+ export declare const findOrCreateServicesConversation: (apiClient: ApiClient, teamAndPlanParams: TeamAndPlanParams) => Promise<ConversationResource>;
90
+ export declare const fetchServicesPayload: (apiClient: ApiClient, teamAndPlanParams: TeamAndPlanParams) => Promise<ApiResource<ServicesChatPayloadResource>>;
91
+ export declare const getGroupIdsFromServices: (apiClient: ApiClient, teamAndPlanParams: TeamAndPlanParams) => Promise<ApiResource<ServicesChatGroupIdentifiersResource>>;
92
+ export declare const findConversationWithExactTeams: (apiClient: ApiClient, groupIdentifiers: string[]) => Promise<ApiCollection<ConversationResource>>;
93
+ export declare const createConversation: (apiClient: ApiClient, payload: string) => Promise<ApiResource<ConversationResource>>;
94
+ export declare const findExactTeamConversation: (apiClient: ApiClient, groupIdentifiers: string[]) => Promise<ApiCollection<ConversationResource>>;
95
+ export declare const checkIfConversationWithGroupExists: (apiClient: ApiClient, teamAndPlanParams: TeamAndPlanParams) => Promise<boolean>;
96
+ export declare const buildTeamAndPlanParams: (teamIds?: number[], planId?: number) => import("lodash").Dictionary<string | number | undefined>;
10
97
  export {};
11
98
  //# sourceMappingURL=use_find_or_create_services_conversation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use_find_or_create_services_conversation.d.ts","sourceRoot":"","sources":["../../../src/hooks/services/use_find_or_create_services_conversation.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,oBAAoB,EAGrB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,SAAS,EAAgB,MAAM,mBAAmB,CAAA;AAG3D,UAAU,KAAK;IACb,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,CAAC,YAAY,EAAE,oBAAoB,KAAK,IAAI,CAAA;CACzD;AAED,wBAAgB,mCAAmC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,KAAK,iGASxF;AAED,eAAO,MAAM,gCAAgC,cAChC,SAAS,WACX,MAAM,EAAE,WACR,MAAM,kCAsBhB,CAAA"}
1
+ {"version":3,"file":"use_find_or_create_services_conversation.d.ts","sourceRoot":"","sources":["../../../src/hooks/services/use_find_or_create_services_conversation.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,aAAa,EACb,WAAW,EACX,oBAAoB,EACpB,oCAAoC,EACpC,2BAA2B,EAC5B,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,SAAS,EAAgB,MAAM,mBAAmB,CAAA;AAG3D,UAAU,KAAK;IACb,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,CAAC,YAAY,EAAE,oBAAoB,KAAK,IAAI,CAAA;CACzD;AAED,UAAU,iBAAiB;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,eAAO,MAAM,mCAAmC,mCAAoC,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BxF,CAAA;AAED,eAAO,MAAM,gCAAgC,cAChC,SAAS,qBACD,iBAAiB,kCAiBrC,CAAA;AAED,eAAO,MAAM,oBAAoB,cACpB,SAAS,qBACD,iBAAiB,KAU9B,OAAO,CAAC,WAAW,CAAC,2BAA2B,CAAC,CACvD,CAAA;AAED,eAAO,MAAM,uBAAuB,cACvB,SAAS,qBACD,iBAAiB,KAU9B,OAAO,CAAC,WAAW,CAAC,oCAAoC,CAAC,CAChE,CAAA;AAED,eAAO,MAAM,8BAA8B,cAC9B,SAAS,oBACF,MAAM,EAAE,KAWpB,OAAO,CAAC,aAAa,CAAC,oBAAoB,CAAC,CAClD,CAAA;AAED,eAAO,MAAM,kBAAkB,cAAe,SAAS,WAAW,MAAM,KAMhE,OAAO,CAAC,WAAW,CAAC,oBAAoB,CAAC,CAChD,CAAA;AAED,eAAO,MAAM,yBAAyB,cAAe,SAAS,oBAAoB,MAAM,EAAE,KAUlF,OAAO,CAAC,aAAa,CAAC,oBAAoB,CAAC,CAClD,CAAA;AAED,eAAO,MAAM,kCAAkC,cAClC,SAAS,qBACD,iBAAiB,qBAMrC,CAAA;AAED,eAAO,MAAM,sBAAsB,aAAa,MAAM,EAAE,WAAgB,MAAM,6DAQ7E,CAAA"}
@@ -1,21 +1,29 @@
1
- import { useMutation } from '@tanstack/react-query';
1
+ import { useMutation, useQuery } from '@tanstack/react-query';
2
+ import { useMemo } from 'react';
3
+ import { omitBy, isNil } from 'lodash';
2
4
  import { useApiClient } from '../use_api_client';
3
5
  import { throwResponseError } from '../../utils/response_error';
4
- export function useFindOrCreateServicesConversation({ teamIds, planId, onSuccess }) {
6
+ export const useFindOrCreateServicesConversation = ({ teamIds, planId, onSuccess }) => {
5
7
  const apiClient = useApiClient();
6
- return useMutation({
8
+ const teamAndPlanParams = useMemo(() => omitBy({
9
+ team_id: teamIds?.join(',') || null,
10
+ plan_id: planId,
11
+ }, isNil), [teamIds, planId]);
12
+ const { data: selectionHasConversation = false, isLoading: isLoadingConversationCheck } = useQuery({
13
+ queryKey: ['conversation-with-group-exists', teamAndPlanParams],
14
+ queryFn: () => checkIfConversationWithGroupExists(apiClient, teamAndPlanParams),
15
+ enabled: !!(teamIds?.length || planId),
16
+ });
17
+ const mutation = useMutation({
7
18
  throwOnError: true,
8
19
  onSuccess: result => {
9
20
  onSuccess && onSuccess(result);
10
21
  },
11
- mutationFn: async () => findOrCreateServicesConversation(apiClient, teamIds, planId),
22
+ mutationFn: async () => findOrCreateServicesConversation(apiClient, teamAndPlanParams),
12
23
  });
13
- }
14
- export const findOrCreateServicesConversation = async (apiClient, teamIds, planId) => {
15
- const teamAndPlanParams = {
16
- team_id: teamIds.join(','),
17
- ...(planId ? { plan_id: planId } : {}),
18
- };
24
+ return { ...mutation, selectionHasConversation, isLoadingConversationCheck };
25
+ };
26
+ export const findOrCreateServicesConversation = async (apiClient, teamAndPlanParams) => {
19
27
  const foundConversations = await getGroupIdsFromServices(apiClient, teamAndPlanParams)
20
28
  .then(res => res.data.groupIdentifiers)
21
29
  .then(groupIdentifiers => findConversationWithExactTeams(apiClient, groupIdentifiers))
@@ -30,7 +38,7 @@ export const findOrCreateServicesConversation = async (apiClient, teamIds, planI
30
38
  .then(res => res.data)
31
39
  .catch(throwResponseError);
32
40
  };
33
- function fetchServicesPayload(apiClient, teamAndPlanParams) {
41
+ export const fetchServicesPayload = (apiClient, teamAndPlanParams) => {
34
42
  return apiClient.services.get({
35
43
  url: `/chat`,
36
44
  data: {
@@ -40,8 +48,8 @@ function fetchServicesPayload(apiClient, teamAndPlanParams) {
40
48
  },
41
49
  },
42
50
  });
43
- }
44
- function getGroupIdsFromServices(apiClient, teamAndPlanParams) {
51
+ };
52
+ export const getGroupIdsFromServices = (apiClient, teamAndPlanParams) => {
45
53
  return apiClient.services.get({
46
54
  url: '/chat',
47
55
  data: {
@@ -51,8 +59,8 @@ function getGroupIdsFromServices(apiClient, teamAndPlanParams) {
51
59
  },
52
60
  },
53
61
  });
54
- }
55
- function findConversationWithExactTeams(apiClient, groupIdentifiers) {
62
+ };
63
+ export const findConversationWithExactTeams = (apiClient, groupIdentifiers) => {
56
64
  return apiClient.chat.get({
57
65
  url: '/me/conversations',
58
66
  data: {
@@ -63,13 +71,37 @@ function findConversationWithExactTeams(apiClient, groupIdentifiers) {
63
71
  gids: groupIdentifiers.join(','),
64
72
  },
65
73
  });
66
- }
67
- function createConversation(apiClient, payload) {
74
+ };
75
+ export const createConversation = (apiClient, payload) => {
68
76
  return apiClient.chat.post({
69
77
  url: '/me/conversations',
70
78
  data: {
71
79
  data: { type: 'Conversation', attributes: { payload } },
72
80
  },
73
81
  });
74
- }
82
+ };
83
+ export const findExactTeamConversation = (apiClient, groupIdentifiers) => {
84
+ return apiClient.chat.get({
85
+ url: '/me/conversations',
86
+ data: {
87
+ fields: {
88
+ Conversation: ['stream_channel', 'title'],
89
+ },
90
+ filter: 'with_exact_groups',
91
+ gids: groupIdentifiers.join(','),
92
+ },
93
+ });
94
+ };
95
+ export const checkIfConversationWithGroupExists = (apiClient, teamAndPlanParams) => {
96
+ return getGroupIdsFromServices(apiClient, teamAndPlanParams)
97
+ .then(res => res.data.groupIdentifiers)
98
+ .then(groupIdentifiers => findExactTeamConversation(apiClient, groupIdentifiers))
99
+ .then(response => response.data.length > 0);
100
+ };
101
+ export const buildTeamAndPlanParams = (teamIds = [], planId) => {
102
+ return omitBy({
103
+ team_id: teamIds.join(','),
104
+ plan_id: planId,
105
+ }, isNil);
106
+ };
75
107
  //# sourceMappingURL=use_find_or_create_services_conversation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use_find_or_create_services_conversation.js","sourceRoot":"","sources":["../../../src/hooks/services/use_find_or_create_services_conversation.ts"],"names":[],"mappings":"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","sourcesContent":["import { useMutation } from '@tanstack/react-query'\nimport {\n ApiCollection,\n ApiResource,\n ConversationResource,\n ServicesChatGroupIdentifiersResource,\n ServicesChatPayloadResource,\n} from '../../types'\nimport { ApiClient, useApiClient } from '../use_api_client'\nimport { throwResponseError } from '../../utils/response_error'\n\ninterface Props {\n teamIds: number[]\n planId?: number\n onSuccess?: (conversation: ConversationResource) => void\n}\n\nexport function useFindOrCreateServicesConversation({ teamIds, planId, onSuccess }: Props) {\n const apiClient = useApiClient()\n return useMutation({\n throwOnError: true,\n onSuccess: result => {\n onSuccess && onSuccess(result)\n },\n mutationFn: async () => findOrCreateServicesConversation(apiClient, teamIds, planId),\n })\n}\n\nexport const findOrCreateServicesConversation = async (\n apiClient: ApiClient,\n teamIds: number[],\n planId?: number\n) => {\n const teamAndPlanParams: TeamAndPlanParams = {\n team_id: teamIds.join(','),\n ...(planId ? { plan_id: planId } : {}),\n }\n\n const foundConversations = await getGroupIdsFromServices(apiClient, teamAndPlanParams)\n .then(res => res.data.groupIdentifiers)\n .then(groupIdentifiers => findConversationWithExactTeams(apiClient, groupIdentifiers))\n .catch(() => null)\n const foundConversation = foundConversations?.data[0]\n\n if (foundConversation?.id) {\n return foundConversation\n }\n\n return fetchServicesPayload(apiClient, teamAndPlanParams)\n .then(res => res.data.payload)\n .then(payload => createConversation(apiClient, payload))\n .then(res => res.data)\n .catch(throwResponseError)\n}\n\ninterface TeamAndPlanParams {\n plan_id?: number | undefined\n team_id: string\n}\n\nfunction fetchServicesPayload(apiClient: ApiClient, teamAndPlanParams: TeamAndPlanParams) {\n return apiClient.services.get({\n url: `/chat`,\n data: {\n ...teamAndPlanParams,\n fields: {\n Chat: ['payload'],\n },\n },\n }) as Promise<ApiResource<ServicesChatPayloadResource>>\n}\n\nfunction getGroupIdsFromServices(apiClient: ApiClient, teamAndPlanParams: TeamAndPlanParams) {\n return apiClient.services.get({\n url: '/chat',\n data: {\n ...teamAndPlanParams,\n fields: {\n Chat: ['group_identifiers'],\n },\n },\n }) as Promise<ApiResource<ServicesChatGroupIdentifiersResource>>\n}\n\nfunction findConversationWithExactTeams(apiClient: ApiClient, groupIdentifiers: string[]) {\n return apiClient.chat.get({\n url: '/me/conversations',\n data: {\n fields: {\n Conversation: ['stream_channel', 'title'],\n },\n filter: 'with_exact_groups',\n gids: groupIdentifiers.join(','),\n },\n }) as Promise<ApiCollection<ConversationResource>>\n}\n\nfunction createConversation(apiClient: ApiClient, payload: string) {\n return apiClient.chat.post({\n url: '/me/conversations',\n data: {\n data: { type: 'Conversation', attributes: { payload } },\n },\n }) as Promise<ApiResource<ConversationResource>>\n}\n"]}
1
+ {"version":3,"file":"use_find_or_create_services_conversation.js","sourceRoot":"","sources":["../../../src/hooks/services/use_find_or_create_services_conversation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAC/B,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAQtC,OAAO,EAAa,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAA;AAa/D,MAAM,CAAC,MAAM,mCAAmC,GAAG,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAS,EAAE,EAAE;IAC3F,MAAM,SAAS,GAAG,YAAY,EAAE,CAAA;IAEhC,MAAM,iBAAiB,GAAsB,OAAO,CAClD,GAAG,EAAE,CACH,MAAM,CACJ;QACE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI;QACnC,OAAO,EAAE,MAAM;KAChB,EACD,KAAK,CACN,EACH,CAAC,OAAO,EAAE,MAAM,CAAC,CAClB,CAAA;IAED,MAAM,EAAE,IAAI,EAAE,wBAAwB,GAAG,KAAK,EAAE,SAAS,EAAE,0BAA0B,EAAE,GACrF,QAAQ,CAAC;QACP,QAAQ,EAAE,CAAC,gCAAgC,EAAE,iBAAiB,CAAC;QAC/D,OAAO,EAAE,GAAG,EAAE,CAAC,kCAAkC,CAAC,SAAS,EAAE,iBAAiB,CAAC;QAC/E,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,MAAM,IAAI,MAAM,CAAC;KACvC,CAAC,CAAA;IAEJ,MAAM,QAAQ,GAAG,WAAW,CAAC;QAC3B,YAAY,EAAE,IAAI;QAClB,SAAS,EAAE,MAAM,CAAC,EAAE;YAClB,SAAS,IAAI,SAAS,CAAC,MAAM,CAAC,CAAA;QAChC,CAAC;QACD,UAAU,EAAE,KAAK,IAAI,EAAE,CAAC,gCAAgC,CAAC,SAAS,EAAE,iBAAiB,CAAC;KACvF,CAAC,CAAA;IAEF,OAAO,EAAE,GAAG,QAAQ,EAAE,wBAAwB,EAAE,0BAA0B,EAAE,CAAA;AAC9E,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,gCAAgC,GAAG,KAAK,EACnD,SAAoB,EACpB,iBAAoC,EACpC,EAAE;IACF,MAAM,kBAAkB,GAAG,MAAM,uBAAuB,CAAC,SAAS,EAAE,iBAAiB,CAAC;SACnF,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC;SACtC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC,8BAA8B,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;SACrF,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;IACpB,MAAM,iBAAiB,GAAG,kBAAkB,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;IAErD,IAAI,iBAAiB,EAAE,EAAE,EAAE,CAAC;QAC1B,OAAO,iBAAiB,CAAA;IAC1B,CAAC;IAED,OAAO,oBAAoB,CAAC,SAAS,EAAE,iBAAiB,CAAC;SACtD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC;SAC7B,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,kBAAkB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;SACvD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC;SACrB,KAAK,CAAC,kBAAkB,CAAC,CAAA;AAC9B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,SAAoB,EACpB,iBAAoC,EACpC,EAAE;IACF,OAAO,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC;QAC5B,GAAG,EAAE,OAAO;QACZ,IAAI,EAAE;YACJ,GAAG,iBAAiB;YACpB,MAAM,EAAE;gBACN,IAAI,EAAE,CAAC,SAAS,CAAC;aAClB;SACF;KACF,CAAsD,CAAA;AACzD,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,SAAoB,EACpB,iBAAoC,EACpC,EAAE;IACF,OAAO,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC;QAC5B,GAAG,EAAE,OAAO;QACZ,IAAI,EAAE;YACJ,GAAG,iBAAiB;YACpB,MAAM,EAAE;gBACN,IAAI,EAAE,CAAC,mBAAmB,CAAC;aAC5B;SACF;KACF,CAA+D,CAAA;AAClE,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAC5C,SAAoB,EACpB,gBAA0B,EAC1B,EAAE;IACF,OAAO,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC;QACxB,GAAG,EAAE,mBAAmB;QACxB,IAAI,EAAE;YACJ,MAAM,EAAE;gBACN,YAAY,EAAE,CAAC,gBAAgB,EAAE,OAAO,CAAC;aAC1C;YACD,MAAM,EAAE,mBAAmB;YAC3B,IAAI,EAAE,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC;SACjC;KACF,CAAiD,CAAA;AACpD,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,SAAoB,EAAE,OAAe,EAAE,EAAE;IAC1E,OAAO,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;QACzB,GAAG,EAAE,mBAAmB;QACxB,IAAI,EAAE;YACJ,IAAI,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,EAAE;SACxD;KACF,CAA+C,CAAA;AAClD,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,SAAoB,EAAE,gBAA0B,EAAE,EAAE;IAC5F,OAAO,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC;QACxB,GAAG,EAAE,mBAAmB;QACxB,IAAI,EAAE;YACJ,MAAM,EAAE;gBACN,YAAY,EAAE,CAAC,gBAAgB,EAAE,OAAO,CAAC;aAC1C;YACD,MAAM,EAAE,mBAAmB;YAC3B,IAAI,EAAE,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC;SACjC;KACF,CAAiD,CAAA;AACpD,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAChD,SAAoB,EACpB,iBAAoC,EACpC,EAAE;IACF,OAAO,uBAAuB,CAAC,SAAS,EAAE,iBAAiB,CAAC;SACzD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC;SACtC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC,yBAAyB,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;SAChF,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;AAC/C,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,UAAoB,EAAE,EAAE,MAAe,EAAE,EAAE;IAChF,OAAO,MAAM,CACX;QACE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC;QAC1B,OAAO,EAAE,MAAM;KAChB,EACD,KAAK,CACN,CAAA;AACH,CAAC,CAAA","sourcesContent":["import { useMutation, useQuery } from '@tanstack/react-query'\nimport { useMemo } from 'react'\nimport { omitBy, isNil } from 'lodash'\nimport {\n ApiCollection,\n ApiResource,\n ConversationResource,\n ServicesChatGroupIdentifiersResource,\n ServicesChatPayloadResource,\n} from '../../types'\nimport { ApiClient, useApiClient } from '../use_api_client'\nimport { throwResponseError } from '../../utils/response_error'\n\ninterface Props {\n teamIds?: number[]\n planId?: number\n onSuccess?: (conversation: ConversationResource) => void\n}\n\ninterface TeamAndPlanParams {\n team_id?: string | null\n plan_id?: number\n}\n\nexport const useFindOrCreateServicesConversation = ({ teamIds, planId, onSuccess }: Props) => {\n const apiClient = useApiClient()\n\n const teamAndPlanParams: TeamAndPlanParams = useMemo(\n () =>\n omitBy(\n {\n team_id: teamIds?.join(',') || null,\n plan_id: planId,\n },\n isNil\n ),\n [teamIds, planId]\n )\n\n const { data: selectionHasConversation = false, isLoading: isLoadingConversationCheck } =\n useQuery({\n queryKey: ['conversation-with-group-exists', teamAndPlanParams],\n queryFn: () => checkIfConversationWithGroupExists(apiClient, teamAndPlanParams),\n enabled: !!(teamIds?.length || planId),\n })\n\n const mutation = useMutation({\n throwOnError: true,\n onSuccess: result => {\n onSuccess && onSuccess(result)\n },\n mutationFn: async () => findOrCreateServicesConversation(apiClient, teamAndPlanParams),\n })\n\n return { ...mutation, selectionHasConversation, isLoadingConversationCheck }\n}\n\nexport const findOrCreateServicesConversation = async (\n apiClient: ApiClient,\n teamAndPlanParams: TeamAndPlanParams\n) => {\n const foundConversations = await getGroupIdsFromServices(apiClient, teamAndPlanParams)\n .then(res => res.data.groupIdentifiers)\n .then(groupIdentifiers => findConversationWithExactTeams(apiClient, groupIdentifiers))\n .catch(() => null)\n const foundConversation = foundConversations?.data[0]\n\n if (foundConversation?.id) {\n return foundConversation\n }\n\n return fetchServicesPayload(apiClient, teamAndPlanParams)\n .then(res => res.data.payload)\n .then(payload => createConversation(apiClient, payload))\n .then(res => res.data)\n .catch(throwResponseError)\n}\n\nexport const fetchServicesPayload = (\n apiClient: ApiClient,\n teamAndPlanParams: TeamAndPlanParams\n) => {\n return apiClient.services.get({\n url: `/chat`,\n data: {\n ...teamAndPlanParams,\n fields: {\n Chat: ['payload'],\n },\n },\n }) as Promise<ApiResource<ServicesChatPayloadResource>>\n}\n\nexport const getGroupIdsFromServices = (\n apiClient: ApiClient,\n teamAndPlanParams: TeamAndPlanParams\n) => {\n return apiClient.services.get({\n url: '/chat',\n data: {\n ...teamAndPlanParams,\n fields: {\n Chat: ['group_identifiers'],\n },\n },\n }) as Promise<ApiResource<ServicesChatGroupIdentifiersResource>>\n}\n\nexport const findConversationWithExactTeams = (\n apiClient: ApiClient,\n groupIdentifiers: string[]\n) => {\n return apiClient.chat.get({\n url: '/me/conversations',\n data: {\n fields: {\n Conversation: ['stream_channel', 'title'],\n },\n filter: 'with_exact_groups',\n gids: groupIdentifiers.join(','),\n },\n }) as Promise<ApiCollection<ConversationResource>>\n}\n\nexport const createConversation = (apiClient: ApiClient, payload: string) => {\n return apiClient.chat.post({\n url: '/me/conversations',\n data: {\n data: { type: 'Conversation', attributes: { payload } },\n },\n }) as Promise<ApiResource<ConversationResource>>\n}\n\nexport const findExactTeamConversation = (apiClient: ApiClient, groupIdentifiers: string[]) => {\n return apiClient.chat.get({\n url: '/me/conversations',\n data: {\n fields: {\n Conversation: ['stream_channel', 'title'],\n },\n filter: 'with_exact_groups',\n gids: groupIdentifiers.join(','),\n },\n }) as Promise<ApiCollection<ConversationResource>>\n}\n\nexport const checkIfConversationWithGroupExists = (\n apiClient: ApiClient,\n teamAndPlanParams: TeamAndPlanParams\n) => {\n return getGroupIdsFromServices(apiClient, teamAndPlanParams)\n .then(res => res.data.groupIdentifiers)\n .then(groupIdentifiers => findExactTeamConversation(apiClient, groupIdentifiers))\n .then(response => response.data.length > 0)\n}\n\nexport const buildTeamAndPlanParams = (teamIds: number[] = [], planId?: number) => {\n return omitBy(\n {\n team_id: teamIds.join(','),\n plan_id: planId,\n },\n isNil\n )\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"services_form.d.ts","sourceRoot":"","sources":["../../../../src/screens/conversation_new/components/services_form.tsx"],"names":[],"mappings":"AACA,OAAO,KAAoD,MAAM,OAAO,CAAA;AAaxE,OAAO,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAA;AAE5E,KAAK,iBAAiB,GAAG;IACvB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;IACzB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,cAAc,CAAC,EAAE,eAAe,CAAA;CACjC,CAAA;AAED,eAAO,MAAM,YAAY,uDAItB,iBAAiB,sBAqEnB,CAAA"}
1
+ {"version":3,"file":"services_form.d.ts","sourceRoot":"","sources":["../../../../src/screens/conversation_new/components/services_form.tsx"],"names":[],"mappings":"AACA,OAAO,KAAoD,MAAM,OAAO,CAAA;AAaxE,OAAO,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAA;AAE5E,KAAK,iBAAiB,GAAG;IACvB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;IACzB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,cAAc,CAAC,EAAE,eAAe,CAAA;CACjC,CAAA;AAED,eAAO,MAAM,YAAY,uDAItB,iBAAiB,sBA2EnB,CAAA"}
@@ -31,7 +31,7 @@ export const ServicesForm = ({ initialTeamIds, initialPlanId, teamFilterType, })
31
31
  });
32
32
  const adultMembers = useMemo(() => members.filter(member => !member.child), [members]);
33
33
  const navigation = useNavigation();
34
- const { mutate: createConversation, isPending } = useFindOrCreateServicesConversation({
34
+ const { mutate: createConversation, isPending, selectionHasConversation, isLoadingConversationCheck, } = useFindOrCreateServicesConversation({
35
35
  teamIds: selectedTeamIds,
36
36
  planId: filerByPlan ? selectedPlanId : undefined,
37
37
  onSuccess: (conversation) => {
@@ -45,7 +45,7 @@ export const ServicesForm = ({ initialTeamIds, initialPlanId, teamFilterType, })
45
45
  });
46
46
  return (<View style={styles.formContainer}>
47
47
  <FormList memberData={adultMembers} FormContent={<FormContent selectedTeamIds={selectedTeamIds} removeSelection={removeSelection} selectedPlanId={selectedPlanId} setSelectedPlanId={setSelectedPlanId} filterByPlan={filerByPlan} setFilterByPlan={setFilterByPlan} members={members} isMemberError={isMemberError} teamFilterType={teamFilterType}/>}/>
48
- <ActionButton disabled={!selectedTeamIds.length || isPending} title="Start Conversation" onPress={createConversation} infoText="Conversation will be automatically updated if any members are added or removed from included teams."/>
48
+ <ActionButton disabled={!selectedTeamIds.length || isPending || isLoadingConversationCheck} title={selectionHasConversation ? 'Open conversation' : 'Start conversation'} onPress={createConversation} infoText="Conversation will be automatically updated if any members are added or removed from included teams." loading={isLoadingConversationCheck}/>
49
49
  </View>);
50
50
  };
51
51
  function FormContent({ selectedTeamIds, removeSelection, selectedPlanId, setSelectedPlanId, filterByPlan, setFilterByPlan, members, isMemberError, teamFilterType, }) {
@@ -1 +1 @@
1
- {"version":3,"file":"services_form.js","sourceRoot":"","sources":["../../../../src/screens/conversation_new/components/services_form.tsx"],"names":[],"mappings":"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","sourcesContent":["import { StackActions, useNavigation } from '@react-navigation/native'\nimport React, { useCallback, useEffect, useMemo, useState } from 'react'\nimport { StyleSheet, View } from 'react-native'\nimport { Badge, Banner, ChildNotice, Heading, Switch, TextButton } from '../../../components'\nimport { ActionButton } from '../../../components/display/action_button'\nimport { Divider, FormList } from './form_list'\nimport { pluralize } from '../../../utils'\nimport { uniq } from 'lodash'\nimport { useTeamsILead } from '../../../hooks/services/use_teams_i_lead'\nimport { FilterByPlan } from './filter_by_plan'\nimport { useTeamMembersForNewConversation } from '../../../hooks/services/use_team_members_for_new_conversation'\nimport { useFindOrCreateServicesConversation } from '../../../hooks/services/use_find_or_create_services_conversation'\nimport { ConversationResource, MemberResource } from '../../../types'\nimport { tokens } from '../../../vendor/tapestry/tokens'\nimport { TeamFilterTypes } from '../../conversation_filter_recipients/types'\n\ntype ServicesFormProps = {\n initialTeamIds?: number[]\n initialPlanId?: number\n teamFilterType?: TeamFilterTypes\n}\n\nexport const ServicesForm = ({\n initialTeamIds,\n initialPlanId,\n teamFilterType,\n}: ServicesFormProps) => {\n const styles = useStyles()\n const [selectedPlanId, setSelectedPlanId] = useState<number | undefined>(initialPlanId)\n const initialState = useMemo(() => uniq(initialTeamIds) || [], [initialTeamIds]) // Uniq here because services can send duplicates in the teams_i_lead response.\n const [selectedTeamIds, setSelectedTeamIds] = useState<number[]>(initialState)\n\n // Sync with fresh props when they change (from navigation)\n useEffect(() => {\n setSelectedTeamIds(initialState)\n setSelectedPlanId(initialPlanId)\n }, [initialState, initialPlanId])\n\n const removeSelection = useCallback(\n (teamId: number) => {\n setSelectedTeamIds(selectedTeamIds.filter(id => id !== teamId))\n },\n [selectedTeamIds]\n )\n\n const [filerByPlan, setFilterByPlan] = useState(false)\n\n const { members, isError: isMemberError } = useTeamMembersForNewConversation({\n teamIds: selectedTeamIds,\n planId: selectedPlanId,\n })\n const adultMembers = useMemo(() => members.filter(member => !member.child), [members])\n\n const navigation = useNavigation()\n const { mutate: createConversation, isPending } = useFindOrCreateServicesConversation({\n teamIds: selectedTeamIds,\n planId: filerByPlan ? selectedPlanId : undefined,\n onSuccess: (conversation: ConversationResource) => {\n // exit from the create stack\n navigation.getParent()?.goBack()\n // navigate to the conversation screen\n navigation.dispatch(\n StackActions.push('Conversation', {\n conversation_id: conversation.id,\n })\n )\n },\n })\n\n return (\n <View style={styles.formContainer}>\n <FormList\n memberData={adultMembers}\n FormContent={\n <FormContent\n selectedTeamIds={selectedTeamIds}\n removeSelection={removeSelection}\n selectedPlanId={selectedPlanId}\n setSelectedPlanId={setSelectedPlanId}\n filterByPlan={filerByPlan}\n setFilterByPlan={setFilterByPlan}\n members={members}\n isMemberError={isMemberError}\n teamFilterType={teamFilterType}\n />\n }\n />\n <ActionButton\n disabled={!selectedTeamIds.length || isPending}\n title=\"Start Conversation\"\n onPress={createConversation}\n infoText=\"Conversation will be automatically updated if any members are added or removed from included teams.\"\n />\n </View>\n )\n}\n\ninterface FormContentProps {\n selectedTeamIds: number[]\n removeSelection: (teamId: number) => void\n selectedPlanId?: number\n setSelectedPlanId: (planId: number | undefined) => void\n filterByPlan: boolean\n setFilterByPlan: (value: boolean) => void\n members: MemberResource[]\n isMemberError: boolean\n teamFilterType?: TeamFilterTypes\n}\n\nfunction FormContent({\n selectedTeamIds,\n removeSelection,\n selectedPlanId,\n setSelectedPlanId,\n filterByPlan,\n setFilterByPlan,\n members,\n isMemberError,\n teamFilterType,\n}: FormContentProps) {\n const { teamsILead } = useTeamsILead()\n const selectedTeamsILead = useMemo(() => {\n return teamsILead.filter(team => selectedTeamIds.includes(team.value.teamId))\n }, [selectedTeamIds, teamsILead])\n const navigation = useNavigation()\n\n const styles = useStyles()\n const teamCountHeader = pluralize(selectedTeamIds.length, 'team')\n const memberCount = members.length\n const childMembers = useMemo(() => members.filter(member => member.child), [members])\n const hasChildren = childMembers.length > 0\n const multipleServiceTypes =\n uniq(selectedTeamsILead.map(team => team.value.serviceTypeId)).length > 1\n const firstTeamId = selectedTeamIds[0]\n const serviceTypeName =\n !multipleServiceTypes && selectedTeamsILead.length > 0\n ? selectedTeamsILead[0].serviceTypeName\n : undefined\n\n filterByPlan = filterByPlan && !!firstTeamId && !multipleServiceTypes\n\n return (\n <View style={styles.formContent}>\n <View style={styles.toSection}>\n <View style={styles.toSectionRow}>\n <Heading variant=\"h3\">To:</Heading>\n <TextButton\n accessibilityLabel=\"Select teams\"\n textStyle={styles.teamCountHeader}\n onPress={() =>\n navigation.navigate('New', {\n screen: 'ConversationFilterRecipients',\n params: {\n source_app_name: 'Services',\n team_ids: selectedTeamIds,\n team_filter_type: teamFilterType,\n },\n })\n }\n >\n {teamCountHeader}\n </TextButton>\n </View>\n <View style={styles.toSectionRow}>\n {selectedTeamsILead.map(team => (\n <View key={team.value.teamId} style={styles.badgeRow}>\n <Badge\n iconNameRight=\"general.x\"\n label={team.name}\n onPress={() => removeSelection(team.value.teamId)}\n />\n </View>\n ))}\n </View>\n </View>\n <Divider />\n <View style={styles.filterByPlanSection}>\n <View style={styles.filterByPlanSectionLead}>\n <Heading variant=\"h3\">Filter by plan</Heading>\n <Switch\n value={filterByPlan}\n onValueChange={value => {\n setFilterByPlan(value)\n if (!value) {\n setSelectedPlanId(undefined)\n }\n }}\n disabled={multipleServiceTypes}\n />\n </View>\n {multipleServiceTypes ? (\n <Banner\n appearance=\"neutral\"\n description=\"Plan filtering is not possible using teams from multiple service types. Try choosing teams above with only one service type.\"\n />\n ) : filterByPlan ? (\n <FilterByPlan\n teamIds={selectedTeamIds}\n selectedPlanId={selectedPlanId}\n serviceTypeName={serviceTypeName}\n onPlanSelect={setSelectedPlanId}\n />\n ) : null}\n </View>\n <Divider />\n <View style={styles.memberSection}>\n <Heading variant=\"h3\">{pluralize(memberCount, 'member')} selected</Heading>\n {hasChildren && (\n <ChildNotice childMembers={childMembers} showMembers={true} style={styles.banner} />\n )}\n {isMemberError && (\n <Banner\n appearance=\"error\"\n description=\"There was an issue loading team members, please refresh and try again.\"\n style={styles.banner}\n />\n )}\n </View>\n </View>\n )\n}\n\nconst useStyles = () => {\n const sectionPadding = 16\n\n return StyleSheet.create({\n formContainer: {\n flex: 1,\n },\n formContent: {\n paddingBottom: sectionPadding,\n flex: 1,\n },\n toSection: {\n padding: sectionPadding,\n gap: 8,\n },\n toSectionRow: {\n flexDirection: 'row',\n gap: 8,\n alignItems: 'baseline',\n flexWrap: 'wrap',\n },\n badgeRow: {\n flexDirection: 'row',\n },\n groupName: {\n fontSize: 18,\n },\n filterByPlanSection: {\n padding: sectionPadding,\n gap: 12,\n },\n filterByPlanSectionLead: {\n flexDirection: 'row',\n gap: 8,\n justifyContent: 'space-between',\n alignItems: 'center',\n },\n filterByPlanSectionRow: {\n flexDirection: 'row',\n gap: 8,\n },\n titleInput: {\n fontSize: 18,\n },\n memberSection: {\n padding: sectionPadding,\n paddingBottom: 0,\n },\n banner: {\n marginTop: 16,\n },\n teamCountHeader: {\n fontSize: tokens.fontSizeLg,\n },\n })\n}\n"]}
1
+ {"version":3,"file":"services_form.js","sourceRoot":"","sources":["../../../../src/screens/conversation_new/components/services_form.tsx"],"names":[],"mappings":"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","sourcesContent":["import { StackActions, useNavigation } from '@react-navigation/native'\nimport React, { useCallback, useEffect, useMemo, useState } from 'react'\nimport { StyleSheet, View } from 'react-native'\nimport { Badge, Banner, ChildNotice, Heading, Switch, TextButton } from '../../../components'\nimport { ActionButton } from '../../../components/display/action_button'\nimport { Divider, FormList } from './form_list'\nimport { pluralize } from '../../../utils'\nimport { uniq } from 'lodash'\nimport { useTeamsILead } from '../../../hooks/services/use_teams_i_lead'\nimport { FilterByPlan } from './filter_by_plan'\nimport { useTeamMembersForNewConversation } from '../../../hooks/services/use_team_members_for_new_conversation'\nimport { useFindOrCreateServicesConversation } from '../../../hooks/services/use_find_or_create_services_conversation'\nimport { ConversationResource, MemberResource } from '../../../types'\nimport { tokens } from '../../../vendor/tapestry/tokens'\nimport { TeamFilterTypes } from '../../conversation_filter_recipients/types'\n\ntype ServicesFormProps = {\n initialTeamIds?: number[]\n initialPlanId?: number\n teamFilterType?: TeamFilterTypes\n}\n\nexport const ServicesForm = ({\n initialTeamIds,\n initialPlanId,\n teamFilterType,\n}: ServicesFormProps) => {\n const styles = useStyles()\n const [selectedPlanId, setSelectedPlanId] = useState<number | undefined>(initialPlanId)\n const initialState = useMemo(() => uniq(initialTeamIds) || [], [initialTeamIds]) // Uniq here because services can send duplicates in the teams_i_lead response.\n const [selectedTeamIds, setSelectedTeamIds] = useState<number[]>(initialState)\n\n // Sync with fresh props when they change (from navigation)\n useEffect(() => {\n setSelectedTeamIds(initialState)\n setSelectedPlanId(initialPlanId)\n }, [initialState, initialPlanId])\n\n const removeSelection = useCallback(\n (teamId: number) => {\n setSelectedTeamIds(selectedTeamIds.filter(id => id !== teamId))\n },\n [selectedTeamIds]\n )\n\n const [filerByPlan, setFilterByPlan] = useState(false)\n\n const { members, isError: isMemberError } = useTeamMembersForNewConversation({\n teamIds: selectedTeamIds,\n planId: selectedPlanId,\n })\n const adultMembers = useMemo(() => members.filter(member => !member.child), [members])\n\n const navigation = useNavigation()\n const {\n mutate: createConversation,\n isPending,\n selectionHasConversation,\n isLoadingConversationCheck,\n } = useFindOrCreateServicesConversation({\n teamIds: selectedTeamIds,\n planId: filerByPlan ? selectedPlanId : undefined,\n onSuccess: (conversation: ConversationResource) => {\n // exit from the create stack\n navigation.getParent()?.goBack()\n // navigate to the conversation screen\n navigation.dispatch(\n StackActions.push('Conversation', {\n conversation_id: conversation.id,\n })\n )\n },\n })\n\n return (\n <View style={styles.formContainer}>\n <FormList\n memberData={adultMembers}\n FormContent={\n <FormContent\n selectedTeamIds={selectedTeamIds}\n removeSelection={removeSelection}\n selectedPlanId={selectedPlanId}\n setSelectedPlanId={setSelectedPlanId}\n filterByPlan={filerByPlan}\n setFilterByPlan={setFilterByPlan}\n members={members}\n isMemberError={isMemberError}\n teamFilterType={teamFilterType}\n />\n }\n />\n <ActionButton\n disabled={!selectedTeamIds.length || isPending || isLoadingConversationCheck}\n title={selectionHasConversation ? 'Open conversation' : 'Start conversation'}\n onPress={createConversation}\n infoText=\"Conversation will be automatically updated if any members are added or removed from included teams.\"\n loading={isLoadingConversationCheck}\n />\n </View>\n )\n}\n\ninterface FormContentProps {\n selectedTeamIds: number[]\n removeSelection: (teamId: number) => void\n selectedPlanId?: number\n setSelectedPlanId: (planId: number | undefined) => void\n filterByPlan: boolean\n setFilterByPlan: (value: boolean) => void\n members: MemberResource[]\n isMemberError: boolean\n teamFilterType?: TeamFilterTypes\n}\n\nfunction FormContent({\n selectedTeamIds,\n removeSelection,\n selectedPlanId,\n setSelectedPlanId,\n filterByPlan,\n setFilterByPlan,\n members,\n isMemberError,\n teamFilterType,\n}: FormContentProps) {\n const { teamsILead } = useTeamsILead()\n const selectedTeamsILead = useMemo(() => {\n return teamsILead.filter(team => selectedTeamIds.includes(team.value.teamId))\n }, [selectedTeamIds, teamsILead])\n const navigation = useNavigation()\n\n const styles = useStyles()\n const teamCountHeader = pluralize(selectedTeamIds.length, 'team')\n const memberCount = members.length\n const childMembers = useMemo(() => members.filter(member => member.child), [members])\n const hasChildren = childMembers.length > 0\n const multipleServiceTypes =\n uniq(selectedTeamsILead.map(team => team.value.serviceTypeId)).length > 1\n const firstTeamId = selectedTeamIds[0]\n const serviceTypeName =\n !multipleServiceTypes && selectedTeamsILead.length > 0\n ? selectedTeamsILead[0].serviceTypeName\n : undefined\n\n filterByPlan = filterByPlan && !!firstTeamId && !multipleServiceTypes\n\n return (\n <View style={styles.formContent}>\n <View style={styles.toSection}>\n <View style={styles.toSectionRow}>\n <Heading variant=\"h3\">To:</Heading>\n <TextButton\n accessibilityLabel=\"Select teams\"\n textStyle={styles.teamCountHeader}\n onPress={() =>\n navigation.navigate('New', {\n screen: 'ConversationFilterRecipients',\n params: {\n source_app_name: 'Services',\n team_ids: selectedTeamIds,\n team_filter_type: teamFilterType,\n },\n })\n }\n >\n {teamCountHeader}\n </TextButton>\n </View>\n <View style={styles.toSectionRow}>\n {selectedTeamsILead.map(team => (\n <View key={team.value.teamId} style={styles.badgeRow}>\n <Badge\n iconNameRight=\"general.x\"\n label={team.name}\n onPress={() => removeSelection(team.value.teamId)}\n />\n </View>\n ))}\n </View>\n </View>\n <Divider />\n <View style={styles.filterByPlanSection}>\n <View style={styles.filterByPlanSectionLead}>\n <Heading variant=\"h3\">Filter by plan</Heading>\n <Switch\n value={filterByPlan}\n onValueChange={value => {\n setFilterByPlan(value)\n if (!value) {\n setSelectedPlanId(undefined)\n }\n }}\n disabled={multipleServiceTypes}\n />\n </View>\n {multipleServiceTypes ? (\n <Banner\n appearance=\"neutral\"\n description=\"Plan filtering is not possible using teams from multiple service types. Try choosing teams above with only one service type.\"\n />\n ) : filterByPlan ? (\n <FilterByPlan\n teamIds={selectedTeamIds}\n selectedPlanId={selectedPlanId}\n serviceTypeName={serviceTypeName}\n onPlanSelect={setSelectedPlanId}\n />\n ) : null}\n </View>\n <Divider />\n <View style={styles.memberSection}>\n <Heading variant=\"h3\">{pluralize(memberCount, 'member')} selected</Heading>\n {hasChildren && (\n <ChildNotice childMembers={childMembers} showMembers={true} style={styles.banner} />\n )}\n {isMemberError && (\n <Banner\n appearance=\"error\"\n description=\"There was an issue loading team members, please refresh and try again.\"\n style={styles.banner}\n />\n )}\n </View>\n </View>\n )\n}\n\nconst useStyles = () => {\n const sectionPadding = 16\n\n return StyleSheet.create({\n formContainer: {\n flex: 1,\n },\n formContent: {\n paddingBottom: sectionPadding,\n flex: 1,\n },\n toSection: {\n padding: sectionPadding,\n gap: 8,\n },\n toSectionRow: {\n flexDirection: 'row',\n gap: 8,\n alignItems: 'baseline',\n flexWrap: 'wrap',\n },\n badgeRow: {\n flexDirection: 'row',\n },\n groupName: {\n fontSize: 18,\n },\n filterByPlanSection: {\n padding: sectionPadding,\n gap: 12,\n },\n filterByPlanSectionLead: {\n flexDirection: 'row',\n gap: 8,\n justifyContent: 'space-between',\n alignItems: 'center',\n },\n filterByPlanSectionRow: {\n flexDirection: 'row',\n gap: 8,\n },\n titleInput: {\n fontSize: 18,\n },\n memberSection: {\n padding: sectionPadding,\n paddingBottom: 0,\n },\n banner: {\n marginTop: 16,\n },\n teamCountHeader: {\n fontSize: tokens.fontSizeLg,\n },\n })\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"team_conversation_screen.d.ts","sourceRoot":"","sources":["../../src/screens/team_conversation_screen.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAgB,iBAAiB,EAAiB,MAAM,0BAA0B,CAAA;AAOzF,MAAM,MAAM,0BAA0B,GAAG;IACvC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,2BAA2B,GAAG,iBAAiB,CAAC,0BAA0B,CAAC,CAAA;AAEvF,eAAO,MAAM,sBAAsB,cAAe,2BAA2B,gCA+B5E,CAAA"}
1
+ {"version":3,"file":"team_conversation_screen.d.ts","sourceRoot":"","sources":["../../src/screens/team_conversation_screen.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAgB,iBAAiB,EAAiB,MAAM,0BAA0B,CAAA;AAUzF,MAAM,MAAM,0BAA0B,GAAG;IACvC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,2BAA2B,GAAG,iBAAiB,CAAC,0BAA0B,CAAC,CAAA;AAEvF,eAAO,MAAM,sBAAsB,cAAe,2BAA2B,gCA0B5E,CAAA"}
@@ -2,15 +2,16 @@ import { StackActions, useNavigation } from '@react-navigation/native';
2
2
  import { useQuery, useQueryClient } from '@tanstack/react-query';
3
3
  import { useEffect } from 'react';
4
4
  import { useApiClient } from '../hooks';
5
- import { findOrCreateServicesConversation } from '../hooks/services/use_find_or_create_services_conversation';
5
+ import { buildTeamAndPlanParams, findOrCreateServicesConversation, } from '../hooks/services/use_find_or_create_services_conversation';
6
6
  import { DefaultLoading } from '../components/page/loading';
7
7
  export const TeamConversationScreen = ({ route }) => {
8
8
  const apiClient = useApiClient();
9
9
  const queryClient = useQueryClient();
10
10
  const navigation = useNavigation();
11
+ const teamAndPlanParams = buildTeamAndPlanParams(route.params.team_ids, route.params.plan_id);
11
12
  const { data: conversation } = useQuery({
12
13
  queryKey: ['team-conversation', route.params.team_ids, route.params.plan_id],
13
- queryFn: () => findOrCreateServicesConversation(apiClient, route.params.team_ids || [], route.params.plan_id),
14
+ queryFn: () => findOrCreateServicesConversation(apiClient, teamAndPlanParams),
14
15
  });
15
16
  useEffect(() => {
16
17
  if (!conversation?.id)
@@ -1 +1 @@
1
- {"version":3,"file":"team_conversation_screen.js","sourceRoot":"","sources":["../../src/screens/team_conversation_screen.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAqB,aAAa,EAAE,MAAM,0BAA0B,CAAA;AACzF,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AACvC,OAAO,EAAE,gCAAgC,EAAE,MAAM,4DAA4D,CAAA;AAC7G,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAS3D,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,EAAE,KAAK,EAA+B,EAAE,EAAE;IAC/E,MAAM,SAAS,GAAG,YAAY,EAAE,CAAA;IAChC,MAAM,WAAW,GAAG,cAAc,EAAE,CAAA;IACpC,MAAM,UAAU,GAAG,aAAa,EAAE,CAAA;IAElC,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,QAAQ,CAAC;QACtC,QAAQ,EAAE,CAAC,mBAAmB,EAAE,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC;QAC5E,OAAO,EAAE,GAAG,EAAE,CACZ,gCAAgC,CAC9B,SAAS,EACT,KAAK,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,EAC3B,KAAK,CAAC,MAAM,CAAC,OAAO,CACrB;KACJ,CAAC,CAAA;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,YAAY,EAAE,EAAE;YAAE,OAAM;QAE7B,UAAU,CAAC,QAAQ,CACjB,YAAY,CAAC,OAAO,CAAC,cAAc,EAAE;YACnC,eAAe,EAAE,YAAY,CAAC,EAAE;YAChC,KAAK,EAAE,YAAY,CAAC,KAAK;SAC1B,CAAC,CACH,CAAA;QAED,OAAO,GAAG,EAAE;YACV,WAAW,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAA;QAChE,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,YAAY,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC,CAAA;IAEpE,OAAO,CAAC,cAAc,CAAC,AAAD,EAAG,CAAA;AAC3B,CAAC,CAAA","sourcesContent":["import { StackActions, StaticScreenProps, useNavigation } from '@react-navigation/native'\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport { useEffect } from 'react'\nimport { useApiClient } from '../hooks'\nimport { findOrCreateServicesConversation } from '../hooks/services/use_find_or_create_services_conversation'\nimport { DefaultLoading } from '../components/page/loading'\n\nexport type TeamConversationRouteProps = {\n plan_id?: number\n team_ids?: number[]\n}\n\nexport type TeamConversationScreenProps = StaticScreenProps<TeamConversationRouteProps>\n\nexport const TeamConversationScreen = ({ route }: TeamConversationScreenProps) => {\n const apiClient = useApiClient()\n const queryClient = useQueryClient()\n const navigation = useNavigation()\n\n const { data: conversation } = useQuery({\n queryKey: ['team-conversation', route.params.team_ids, route.params.plan_id],\n queryFn: () =>\n findOrCreateServicesConversation(\n apiClient,\n route.params.team_ids || [],\n route.params.plan_id\n ),\n })\n\n useEffect(() => {\n if (!conversation?.id) return\n\n navigation.dispatch(\n StackActions.replace('Conversation', {\n conversation_id: conversation.id,\n title: conversation.title,\n })\n )\n\n return () => {\n queryClient.removeQueries({ queryKey: ['team-conversation'] })\n }\n }, [conversation?.id, conversation?.title, navigation, queryClient])\n\n return <DefaultLoading />\n}\n"]}
1
+ {"version":3,"file":"team_conversation_screen.js","sourceRoot":"","sources":["../../src/screens/team_conversation_screen.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAqB,aAAa,EAAE,MAAM,0BAA0B,CAAA;AACzF,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AACvC,OAAO,EACL,sBAAsB,EACtB,gCAAgC,GACjC,MAAM,4DAA4D,CAAA;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAS3D,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,EAAE,KAAK,EAA+B,EAAE,EAAE;IAC/E,MAAM,SAAS,GAAG,YAAY,EAAE,CAAA;IAChC,MAAM,WAAW,GAAG,cAAc,EAAE,CAAA;IACpC,MAAM,UAAU,GAAG,aAAa,EAAE,CAAA;IAClC,MAAM,iBAAiB,GAAG,sBAAsB,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IAC7F,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,QAAQ,CAAC;QACtC,QAAQ,EAAE,CAAC,mBAAmB,EAAE,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC;QAC5E,OAAO,EAAE,GAAG,EAAE,CAAC,gCAAgC,CAAC,SAAS,EAAE,iBAAiB,CAAC;KAC9E,CAAC,CAAA;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,YAAY,EAAE,EAAE;YAAE,OAAM;QAE7B,UAAU,CAAC,QAAQ,CACjB,YAAY,CAAC,OAAO,CAAC,cAAc,EAAE;YACnC,eAAe,EAAE,YAAY,CAAC,EAAE;YAChC,KAAK,EAAE,YAAY,CAAC,KAAK;SAC1B,CAAC,CACH,CAAA;QAED,OAAO,GAAG,EAAE;YACV,WAAW,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAA;QAChE,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,YAAY,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC,CAAA;IAEpE,OAAO,CAAC,cAAc,CAAC,AAAD,EAAG,CAAA;AAC3B,CAAC,CAAA","sourcesContent":["import { StackActions, StaticScreenProps, useNavigation } from '@react-navigation/native'\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport { useEffect } from 'react'\nimport { useApiClient } from '../hooks'\nimport {\n buildTeamAndPlanParams,\n findOrCreateServicesConversation,\n} from '../hooks/services/use_find_or_create_services_conversation'\nimport { DefaultLoading } from '../components/page/loading'\n\nexport type TeamConversationRouteProps = {\n plan_id?: number\n team_ids?: number[]\n}\n\nexport type TeamConversationScreenProps = StaticScreenProps<TeamConversationRouteProps>\n\nexport const TeamConversationScreen = ({ route }: TeamConversationScreenProps) => {\n const apiClient = useApiClient()\n const queryClient = useQueryClient()\n const navigation = useNavigation()\n const teamAndPlanParams = buildTeamAndPlanParams(route.params.team_ids, route.params.plan_id)\n const { data: conversation } = useQuery({\n queryKey: ['team-conversation', route.params.team_ids, route.params.plan_id],\n queryFn: () => findOrCreateServicesConversation(apiClient, teamAndPlanParams),\n })\n\n useEffect(() => {\n if (!conversation?.id) return\n\n navigation.dispatch(\n StackActions.replace('Conversation', {\n conversation_id: conversation.id,\n title: conversation.title,\n })\n )\n\n return () => {\n queryClient.removeQueries({ queryKey: ['team-conversation'] })\n }\n }, [conversation?.id, conversation?.title, navigation, queryClient])\n\n return <DefaultLoading />\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@planningcenter/chat-react-native",
3
- "version": "3.13.1-rc.2",
3
+ "version": "3.13.1-rc.3",
4
4
  "description": "",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -55,5 +55,5 @@
55
55
  "react-native-url-polyfill": "^2.0.0",
56
56
  "typescript": "<5.6.0"
57
57
  },
58
- "gitHead": "f316ed927e252abb4a4dc20531c8dbcf85f21e87"
58
+ "gitHead": "e54253cbb9e39bd4c88b92a650353fc3e7039f6f"
59
59
  }
@@ -15,6 +15,7 @@ export const ActionButton = ({
15
15
  infoText,
16
16
  buttonIconNameLeft,
17
17
  secondaryButton,
18
+ loading = false,
18
19
  }: {
19
20
  visible?: boolean
20
21
  disabled?: boolean
@@ -23,6 +24,7 @@ export const ActionButton = ({
23
24
  infoText?: string
24
25
  buttonIconNameLeft?: IconString
25
26
  secondaryButton?: React.ReactNode
27
+ loading?: boolean
26
28
  }) => {
27
29
  const styles = useStyles()
28
30
  const [show, setShow] = useState(visible)
@@ -53,6 +55,7 @@ export const ActionButton = ({
53
55
  disabled={disabled}
54
56
  style={secondaryButton ? null : styles.fullWidthButton}
55
57
  iconNameLeft={buttonIconNameLeft}
58
+ loading={loading}
56
59
  />
57
60
  </View>
58
61
  </Animated.View>
@@ -1,4 +1,6 @@
1
- import { useMutation } from '@tanstack/react-query'
1
+ import { useMutation, useQuery } from '@tanstack/react-query'
2
+ import { useMemo } from 'react'
3
+ import { omitBy, isNil } from 'lodash'
2
4
  import {
3
5
  ApiCollection,
4
6
  ApiResource,
@@ -10,32 +12,53 @@ import { ApiClient, useApiClient } from '../use_api_client'
10
12
  import { throwResponseError } from '../../utils/response_error'
11
13
 
12
14
  interface Props {
13
- teamIds: number[]
15
+ teamIds?: number[]
14
16
  planId?: number
15
17
  onSuccess?: (conversation: ConversationResource) => void
16
18
  }
17
19
 
18
- export function useFindOrCreateServicesConversation({ teamIds, planId, onSuccess }: Props) {
20
+ interface TeamAndPlanParams {
21
+ team_id?: string | null
22
+ plan_id?: number
23
+ }
24
+
25
+ export const useFindOrCreateServicesConversation = ({ teamIds, planId, onSuccess }: Props) => {
19
26
  const apiClient = useApiClient()
20
- return useMutation({
27
+
28
+ const teamAndPlanParams: TeamAndPlanParams = useMemo(
29
+ () =>
30
+ omitBy(
31
+ {
32
+ team_id: teamIds?.join(',') || null,
33
+ plan_id: planId,
34
+ },
35
+ isNil
36
+ ),
37
+ [teamIds, planId]
38
+ )
39
+
40
+ const { data: selectionHasConversation = false, isLoading: isLoadingConversationCheck } =
41
+ useQuery({
42
+ queryKey: ['conversation-with-group-exists', teamAndPlanParams],
43
+ queryFn: () => checkIfConversationWithGroupExists(apiClient, teamAndPlanParams),
44
+ enabled: !!(teamIds?.length || planId),
45
+ })
46
+
47
+ const mutation = useMutation({
21
48
  throwOnError: true,
22
49
  onSuccess: result => {
23
50
  onSuccess && onSuccess(result)
24
51
  },
25
- mutationFn: async () => findOrCreateServicesConversation(apiClient, teamIds, planId),
52
+ mutationFn: async () => findOrCreateServicesConversation(apiClient, teamAndPlanParams),
26
53
  })
54
+
55
+ return { ...mutation, selectionHasConversation, isLoadingConversationCheck }
27
56
  }
28
57
 
29
58
  export const findOrCreateServicesConversation = async (
30
59
  apiClient: ApiClient,
31
- teamIds: number[],
32
- planId?: number
60
+ teamAndPlanParams: TeamAndPlanParams
33
61
  ) => {
34
- const teamAndPlanParams: TeamAndPlanParams = {
35
- team_id: teamIds.join(','),
36
- ...(planId ? { plan_id: planId } : {}),
37
- }
38
-
39
62
  const foundConversations = await getGroupIdsFromServices(apiClient, teamAndPlanParams)
40
63
  .then(res => res.data.groupIdentifiers)
41
64
  .then(groupIdentifiers => findConversationWithExactTeams(apiClient, groupIdentifiers))
@@ -53,12 +76,10 @@ export const findOrCreateServicesConversation = async (
53
76
  .catch(throwResponseError)
54
77
  }
55
78
 
56
- interface TeamAndPlanParams {
57
- plan_id?: number | undefined
58
- team_id: string
59
- }
60
-
61
- function fetchServicesPayload(apiClient: ApiClient, teamAndPlanParams: TeamAndPlanParams) {
79
+ export const fetchServicesPayload = (
80
+ apiClient: ApiClient,
81
+ teamAndPlanParams: TeamAndPlanParams
82
+ ) => {
62
83
  return apiClient.services.get({
63
84
  url: `/chat`,
64
85
  data: {
@@ -70,7 +91,10 @@ function fetchServicesPayload(apiClient: ApiClient, teamAndPlanParams: TeamAndPl
70
91
  }) as Promise<ApiResource<ServicesChatPayloadResource>>
71
92
  }
72
93
 
73
- function getGroupIdsFromServices(apiClient: ApiClient, teamAndPlanParams: TeamAndPlanParams) {
94
+ export const getGroupIdsFromServices = (
95
+ apiClient: ApiClient,
96
+ teamAndPlanParams: TeamAndPlanParams
97
+ ) => {
74
98
  return apiClient.services.get({
75
99
  url: '/chat',
76
100
  data: {
@@ -82,7 +106,10 @@ function getGroupIdsFromServices(apiClient: ApiClient, teamAndPlanParams: TeamAn
82
106
  }) as Promise<ApiResource<ServicesChatGroupIdentifiersResource>>
83
107
  }
84
108
 
85
- function findConversationWithExactTeams(apiClient: ApiClient, groupIdentifiers: string[]) {
109
+ export const findConversationWithExactTeams = (
110
+ apiClient: ApiClient,
111
+ groupIdentifiers: string[]
112
+ ) => {
86
113
  return apiClient.chat.get({
87
114
  url: '/me/conversations',
88
115
  data: {
@@ -95,7 +122,7 @@ function findConversationWithExactTeams(apiClient: ApiClient, groupIdentifiers:
95
122
  }) as Promise<ApiCollection<ConversationResource>>
96
123
  }
97
124
 
98
- function createConversation(apiClient: ApiClient, payload: string) {
125
+ export const createConversation = (apiClient: ApiClient, payload: string) => {
99
126
  return apiClient.chat.post({
100
127
  url: '/me/conversations',
101
128
  data: {
@@ -103,3 +130,36 @@ function createConversation(apiClient: ApiClient, payload: string) {
103
130
  },
104
131
  }) as Promise<ApiResource<ConversationResource>>
105
132
  }
133
+
134
+ export const findExactTeamConversation = (apiClient: ApiClient, groupIdentifiers: string[]) => {
135
+ return apiClient.chat.get({
136
+ url: '/me/conversations',
137
+ data: {
138
+ fields: {
139
+ Conversation: ['stream_channel', 'title'],
140
+ },
141
+ filter: 'with_exact_groups',
142
+ gids: groupIdentifiers.join(','),
143
+ },
144
+ }) as Promise<ApiCollection<ConversationResource>>
145
+ }
146
+
147
+ export const checkIfConversationWithGroupExists = (
148
+ apiClient: ApiClient,
149
+ teamAndPlanParams: TeamAndPlanParams
150
+ ) => {
151
+ return getGroupIdsFromServices(apiClient, teamAndPlanParams)
152
+ .then(res => res.data.groupIdentifiers)
153
+ .then(groupIdentifiers => findExactTeamConversation(apiClient, groupIdentifiers))
154
+ .then(response => response.data.length > 0)
155
+ }
156
+
157
+ export const buildTeamAndPlanParams = (teamIds: number[] = [], planId?: number) => {
158
+ return omitBy(
159
+ {
160
+ team_id: teamIds.join(','),
161
+ plan_id: planId,
162
+ },
163
+ isNil
164
+ )
165
+ }
@@ -52,7 +52,12 @@ export const ServicesForm = ({
52
52
  const adultMembers = useMemo(() => members.filter(member => !member.child), [members])
53
53
 
54
54
  const navigation = useNavigation()
55
- const { mutate: createConversation, isPending } = useFindOrCreateServicesConversation({
55
+ const {
56
+ mutate: createConversation,
57
+ isPending,
58
+ selectionHasConversation,
59
+ isLoadingConversationCheck,
60
+ } = useFindOrCreateServicesConversation({
56
61
  teamIds: selectedTeamIds,
57
62
  planId: filerByPlan ? selectedPlanId : undefined,
58
63
  onSuccess: (conversation: ConversationResource) => {
@@ -86,10 +91,11 @@ export const ServicesForm = ({
86
91
  }
87
92
  />
88
93
  <ActionButton
89
- disabled={!selectedTeamIds.length || isPending}
90
- title="Start Conversation"
94
+ disabled={!selectedTeamIds.length || isPending || isLoadingConversationCheck}
95
+ title={selectionHasConversation ? 'Open conversation' : 'Start conversation'}
91
96
  onPress={createConversation}
92
97
  infoText="Conversation will be automatically updated if any members are added or removed from included teams."
98
+ loading={isLoadingConversationCheck}
93
99
  />
94
100
  </View>
95
101
  )
@@ -2,7 +2,10 @@ import { StackActions, StaticScreenProps, useNavigation } from '@react-navigatio
2
2
  import { useQuery, useQueryClient } from '@tanstack/react-query'
3
3
  import { useEffect } from 'react'
4
4
  import { useApiClient } from '../hooks'
5
- import { findOrCreateServicesConversation } from '../hooks/services/use_find_or_create_services_conversation'
5
+ import {
6
+ buildTeamAndPlanParams,
7
+ findOrCreateServicesConversation,
8
+ } from '../hooks/services/use_find_or_create_services_conversation'
6
9
  import { DefaultLoading } from '../components/page/loading'
7
10
 
8
11
  export type TeamConversationRouteProps = {
@@ -16,15 +19,10 @@ export const TeamConversationScreen = ({ route }: TeamConversationScreenProps) =
16
19
  const apiClient = useApiClient()
17
20
  const queryClient = useQueryClient()
18
21
  const navigation = useNavigation()
19
-
22
+ const teamAndPlanParams = buildTeamAndPlanParams(route.params.team_ids, route.params.plan_id)
20
23
  const { data: conversation } = useQuery({
21
24
  queryKey: ['team-conversation', route.params.team_ids, route.params.plan_id],
22
- queryFn: () =>
23
- findOrCreateServicesConversation(
24
- apiClient,
25
- route.params.team_ids || [],
26
- route.params.plan_id
27
- ),
25
+ queryFn: () => findOrCreateServicesConversation(apiClient, teamAndPlanParams),
28
26
  })
29
27
 
30
28
  useEffect(() => {