@planningcenter/chat-react-native 3.2.0-rc.10 → 3.2.0-rc.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/components/display/action_button.d.ts +2 -1
- package/build/components/display/action_button.d.ts.map +1 -1
- package/build/components/display/action_button.js +2 -2
- package/build/components/display/action_button.js.map +1 -1
- package/build/hooks/groups/use_groups_conversation_create.d.ts +9 -0
- package/build/hooks/groups/use_groups_conversation_create.d.ts.map +1 -0
- package/build/hooks/groups/use_groups_conversation_create.js +36 -0
- package/build/hooks/groups/use_groups_conversation_create.js.map +1 -0
- package/build/screens/conversation_new/components/groups_form.d.ts.map +1 -1
- package/build/screens/conversation_new/components/groups_form.js +10 -37
- package/build/screens/conversation_new/components/groups_form.js.map +1 -1
- package/package.json +2 -2
- package/src/components/display/action_button.tsx +3 -1
- package/src/hooks/groups/use_groups_conversation_create.ts +50 -0
- package/src/screens/conversation_new/components/groups_form.tsx +14 -52
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
export declare const ActionButton: ({ visible, onPress, title, infoText, }: {
|
|
2
|
+
export declare const ActionButton: ({ visible, disabled, onPress, title, infoText, }: {
|
|
3
3
|
visible?: boolean;
|
|
4
|
+
disabled?: boolean;
|
|
4
5
|
onPress: () => void;
|
|
5
6
|
title: string;
|
|
6
7
|
infoText?: string;
|
|
@@ -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;AAQvC,eAAO,MAAM,YAAY,
|
|
1
|
+
{"version":3,"file":"action_button.d.ts","sourceRoot":"","sources":["../../../src/components/display/action_button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAA;AAQvC,eAAO,MAAM,YAAY,qDAMtB;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;CAClB,6BAuBA,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, onPress, title, infoText, }) => {
|
|
8
|
+
export const ActionButton = ({ visible = true, disabled = false, onPress, title, infoText, }) => {
|
|
9
9
|
const styles = useStyles();
|
|
10
10
|
const [show, setShow] = useState(visible);
|
|
11
11
|
useEffect(() => {
|
|
@@ -20,7 +20,7 @@ export const ActionButton = ({ visible = true, onPress, title, infoText, }) => {
|
|
|
20
20
|
{Boolean(infoText) && (<Text style={styles.infoText} variant="footnote">
|
|
21
21
|
{infoText}
|
|
22
22
|
</Text>)}
|
|
23
|
-
<Button variant="fill" size="lg" onPress={onPress} title={title}/>
|
|
23
|
+
<Button variant="fill" size="lg" onPress={onPress} title={title} disabled={disabled}/>
|
|
24
24
|
</Animated.View>);
|
|
25
25
|
};
|
|
26
26
|
const useStyles = () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action_button.js","sourceRoot":"","sources":["../../../src/components/display/action_button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAE7B,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,EAC3B,OAAO,GAAG,IAAI,EACd,OAAO,EACP,KAAK,EACL,QAAQ,
|
|
1
|
+
{"version":3,"file":"action_button.js","sourceRoot":"","sources":["../../../src/components/display/action_button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAE7B,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,EAC3B,OAAO,GAAG,IAAI,EACd,QAAQ,GAAG,KAAK,EAChB,OAAO,EACP,KAAK,EACL,QAAQ,GAOT,EAAE,EAAE;IACH,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAC1B,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAA;IAEzC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,IAAI,KAAK,OAAO;YAAE,OAAM;QAE5B,OAAO,CAAC,OAAO,CAAC,CAAA;QAChB,eAAe,CAAC,aAAa,CAAC,eAAe,CAAC,OAAO,CAAC,aAAa,CAAC,CAAA;IACtE,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAA;IAEnB,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAA;IAEzB,OAAO,CACL,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CACrC;MAAA,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CACpB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,UAAU,CAC9C;UAAA,CAAC,QAAQ,CACX;QAAA,EAAE,IAAI,CAAC,CACR,CACD;MAAA,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,EACtF;IAAA,EAAE,QAAQ,CAAC,IAAI,CAAC,CACjB,CAAA;AACH,CAAC,CAAA;AAED,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,MAAM,EAAE,MAAM,EAAE,GAAG,iBAAiB,EAAE,CAAA;IACtC,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAA;IAE7B,OAAO,UAAU,CAAC,MAAM,CAAC;QACvB,SAAS,EAAE;YACT,eAAe,EAAE,EAAE;YACnB,iBAAiB,EAAE,EAAE;YACrB,aAAa,EAAE,MAAM;YACrB,cAAc,EAAE,CAAC;YACjB,cAAc,EAAE,MAAM,CAAC,mBAAmB;YAC1C,GAAG,EAAE,EAAE;SACR;QACD,QAAQ,EAAE;YACR,SAAS,EAAE,QAAQ;SACpB;KACF,CAAC,CAAA;AACJ,CAAC,CAAA","sourcesContent":["import React, { useState } from 'react'\nimport { Animated, LayoutAnimation, StyleSheet } 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'\n\nexport const ActionButton = ({\n visible = true,\n disabled = false,\n onPress,\n title,\n infoText,\n}: {\n visible?: boolean\n disabled?: boolean\n onPress: () => void\n title: string\n infoText?: string\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 <Button variant=\"fill\" size=\"lg\" onPress={onPress} title={title} disabled={disabled} />\n </Animated.View>\n )\n}\n\nconst useStyles = () => {\n const { bottom } = useSafeAreaInsets()\n const { colors } = useTheme()\n\n return StyleSheet.create({\n container: {\n paddingVertical: 16,\n paddingHorizontal: 24,\n paddingBottom: bottom,\n borderTopWidth: 1,\n borderTopColor: colors.fillColorNeutral060,\n gap: 16,\n },\n infoText: {\n textAlign: 'center',\n },\n })\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ApiResource, ConversationResource } from '../../types';
|
|
2
|
+
interface Props {
|
|
3
|
+
groupId: number;
|
|
4
|
+
title?: string;
|
|
5
|
+
onSuccess: (conversationId: number) => void;
|
|
6
|
+
}
|
|
7
|
+
export declare function useGroupsConversationCreate({ groupId, title, onSuccess }: Props): import("@tanstack/react-query").UseMutationResult<ApiResource<ConversationResource>, Error, void, unknown>;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=use_groups_conversation_create.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use_groups_conversation_create.d.ts","sourceRoot":"","sources":["../../../src/hooks/groups/use_groups_conversation_create.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAkB,MAAM,aAAa,CAAA;AAG/E,UAAU,KAAK;IACb,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,IAAI,CAAA;CAC5C;AAED,wBAAgB,2BAA2B,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,KAAK,8GAmC/E"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { useMutation } from '@tanstack/react-query';
|
|
2
|
+
import { useApiClient } from '../use_api_client';
|
|
3
|
+
export function useGroupsConversationCreate({ groupId, title, onSuccess }) {
|
|
4
|
+
const apiClient = useApiClient();
|
|
5
|
+
return useMutation({
|
|
6
|
+
throwOnError: true,
|
|
7
|
+
onSuccess: result => {
|
|
8
|
+
onSuccess && onSuccess(result.data.id);
|
|
9
|
+
},
|
|
10
|
+
mutationFn: () => apiClient.groups
|
|
11
|
+
.post({
|
|
12
|
+
url: `/me/groups/${groupId}/chat_conversation_payload`,
|
|
13
|
+
data: {
|
|
14
|
+
data: {
|
|
15
|
+
type: '',
|
|
16
|
+
attributes: {
|
|
17
|
+
title,
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
})
|
|
22
|
+
.then(res => res.data.value)
|
|
23
|
+
.then(payload => apiClient.chat.post({
|
|
24
|
+
url: '/me/conversations',
|
|
25
|
+
data: {
|
|
26
|
+
data: {
|
|
27
|
+
type: 'Conversation',
|
|
28
|
+
attributes: {
|
|
29
|
+
payload,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
})),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=use_groups_conversation_create.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use_groups_conversation_create.js","sourceRoot":"","sources":["../../../src/hooks/groups/use_groups_conversation_create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAEnD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAQhD,MAAM,UAAU,2BAA2B,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAS;IAC9E,MAAM,SAAS,GAAG,YAAY,EAAE,CAAA;IAChC,OAAO,WAAW,CAAC;QACjB,YAAY,EAAE,IAAI;QAClB,SAAS,EAAE,MAAM,CAAC,EAAE;YAClB,SAAS,IAAI,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACxC,CAAC;QACD,UAAU,EAAE,GAAG,EAAE,CACf,SAAS,CAAC,MAAM;aACb,IAAI,CAAuC;YAC1C,GAAG,EAAE,cAAc,OAAO,4BAA4B;YACtD,IAAI,EAAE;gBACJ,IAAI,EAAE;oBACJ,IAAI,EAAE,EAAE;oBACR,UAAU,EAAE;wBACV,KAAK;qBACN;iBACF;aACF;SACF,CAAC;aACD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC;aAC3B,IAAI,CAAC,OAAO,CAAC,EAAE,CACd,SAAS,CAAC,IAAI,CAAC,IAAI,CAAoC;YACrD,GAAG,EAAE,mBAAmB;YACxB,IAAI,EAAE;gBACJ,IAAI,EAAE;oBACJ,IAAI,EAAE,cAAc;oBACpB,UAAU,EAAE;wBACV,OAAO;qBACR;iBACF;aACF;SACF,CAAC,CACH;KACN,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import { useMutation } from '@tanstack/react-query'\nimport { ApiResource, ConversationResource, ResourceObject } from '../../types'\nimport { useApiClient } from '../use_api_client'\n\ninterface Props {\n groupId: number\n title?: string\n onSuccess: (conversationId: number) => void\n}\n\nexport function useGroupsConversationCreate({ groupId, title, onSuccess }: Props) {\n const apiClient = useApiClient()\n return useMutation({\n throwOnError: true,\n onSuccess: result => {\n onSuccess && onSuccess(result.data.id)\n },\n mutationFn: () =>\n apiClient.groups\n .post<ApiResource<ChatConversationPayload>>({\n url: `/me/groups/${groupId}/chat_conversation_payload`,\n data: {\n data: {\n type: '',\n attributes: {\n title,\n },\n },\n },\n })\n .then(res => res.data.value)\n .then(payload =>\n apiClient.chat.post<ApiResource<ConversationResource>>({\n url: '/me/conversations',\n data: {\n data: {\n type: 'Conversation',\n attributes: {\n payload,\n },\n },\n },\n })\n ),\n })\n}\n\ninterface ChatConversationPayload extends ResourceObject {\n value: string\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"groups_form.d.ts","sourceRoot":"","sources":["../../../../src/screens/conversation_new/components/groups_form.tsx"],"names":[],"mappings":"AACA,OAAO,KAAgC,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"groups_form.d.ts","sourceRoot":"","sources":["../../../../src/screens/conversation_new/components/groups_form.tsx"],"names":[],"mappings":"AACA,OAAO,KAAgC,MAAM,OAAO,CAAA;AAapD,KAAK,eAAe,GAAG;IACrB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,eAAO,MAAM,UAAU,gBAAiB,eAAe,sBAwDtD,CAAA"}
|
|
@@ -4,17 +4,15 @@ import { Platform, StyleSheet, TextInput, View } from 'react-native';
|
|
|
4
4
|
import { Heading, Text } from '../../../components';
|
|
5
5
|
import { ActionButton } from '../../../components/display/action_button';
|
|
6
6
|
import { useSuspenseGet } from '../../../hooks';
|
|
7
|
-
import { useApiClient } from '../../../hooks/use_api_client';
|
|
8
|
-
import { useMutation } from '@tanstack/react-query';
|
|
9
7
|
import { Divider, FormList } from './form_list';
|
|
10
8
|
import { pluralize } from '../../../utils';
|
|
11
9
|
import { KeyboardView } from '../../../components/display/keyboard_view';
|
|
12
10
|
import { MemberErrorCard } from './member_error_card';
|
|
13
11
|
import { useGroupMembersForNewConversation } from '../../../hooks/groups/use_group_members_for_new_conversation';
|
|
12
|
+
import { useGroupsConversationCreate } from '../../../hooks/groups/use_groups_conversation_create';
|
|
14
13
|
export const GroupsForm = ({ groupId }) => {
|
|
15
14
|
const navigation = useNavigation();
|
|
16
15
|
const [title, setTitle] = useState();
|
|
17
|
-
const apiClient = useApiClient();
|
|
18
16
|
const { data: group } = useSuspenseGet({
|
|
19
17
|
url: `/me/groups/${groupId}`,
|
|
20
18
|
data: {
|
|
@@ -24,48 +22,23 @@ export const GroupsForm = ({ groupId }) => {
|
|
|
24
22
|
},
|
|
25
23
|
app: 'groups',
|
|
26
24
|
});
|
|
27
|
-
const
|
|
28
|
-
const { mutate: handleSave } = useMutation({
|
|
29
|
-
throwOnError: true,
|
|
30
|
-
onSuccess: result => {
|
|
31
|
-
handleRedirectToConversation({ conversation_id: result.data.id });
|
|
32
|
-
},
|
|
33
|
-
mutationFn: () => apiClient.groups
|
|
34
|
-
.post({
|
|
35
|
-
url: `/me/groups/${groupId}/chat_conversation_payload`,
|
|
36
|
-
data: {
|
|
37
|
-
data: {
|
|
38
|
-
type: '',
|
|
39
|
-
attributes: {
|
|
40
|
-
title,
|
|
41
|
-
},
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
|
-
})
|
|
45
|
-
.then(res => res.data.value)
|
|
46
|
-
.then(payload => apiClient.chat.post({
|
|
47
|
-
url: '/me/conversations',
|
|
48
|
-
data: {
|
|
49
|
-
data: {
|
|
50
|
-
type: 'Conversation',
|
|
51
|
-
attributes: {
|
|
52
|
-
payload,
|
|
53
|
-
},
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
})),
|
|
57
|
-
});
|
|
58
|
-
const handleRedirectToConversation = useCallback(({ conversation_id }) => {
|
|
25
|
+
const redirectToConversation = useCallback((conversationId) => {
|
|
59
26
|
// exit from the create stack
|
|
60
27
|
navigation.getParent()?.goBack();
|
|
61
28
|
// navigate to the conversation screen
|
|
62
29
|
navigation.dispatch(StackActions.push('Conversation', {
|
|
63
|
-
conversation_id,
|
|
30
|
+
conversation_id: conversationId,
|
|
64
31
|
}));
|
|
65
32
|
}, [navigation]);
|
|
33
|
+
const groupMemberships = useGroupMembersForNewConversation({ id: groupId });
|
|
34
|
+
const { mutate: handleSave } = useGroupsConversationCreate({
|
|
35
|
+
groupId,
|
|
36
|
+
title,
|
|
37
|
+
onSuccess: redirectToConversation,
|
|
38
|
+
});
|
|
66
39
|
return (<KeyboardView>
|
|
67
40
|
<FormList memberData={groupMemberships.data} FormContent={<FormContent group={group} title={title} setTitle={setTitle} isMemberError={groupMemberships.isError}/>}/>
|
|
68
|
-
<ActionButton title="Start Conversation" onPress={() => handleSave()} infoText="Conversation will be automatically updated if any members are added or removed from this group."/>
|
|
41
|
+
<ActionButton disabled={!title} title="Start Conversation" onPress={() => handleSave()} infoText="Conversation will be automatically updated if any members are added or removed from this group."/>
|
|
69
42
|
</KeyboardView>);
|
|
70
43
|
};
|
|
71
44
|
function FormContent({ group, title, setTitle, isMemberError }) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"groups_form.js","sourceRoot":"","sources":["../../../../src/screens/conversation_new/components/groups_form.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AACtE,OAAO,KAAK,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AACpD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AACpE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,2CAA2C,CAAA;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"groups_form.js","sourceRoot":"","sources":["../../../../src/screens/conversation_new/components/groups_form.tsx"],"names":[],"mappings":"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","sourcesContent":["import { StackActions, useNavigation } from '@react-navigation/native'\nimport React, { useCallback, useState } from 'react'\nimport { Platform, StyleSheet, TextInput, View } from 'react-native'\nimport { Heading, Text } from '../../../components'\nimport { ActionButton } from '../../../components/display/action_button'\nimport { useSuspenseGet } from '../../../hooks'\nimport { GroupsGroupResource } from '../../../types'\nimport { Divider, FormList } from './form_list'\nimport { pluralize } from '../../../utils'\nimport { KeyboardView } from '../../../components/display/keyboard_view'\nimport { MemberErrorCard } from './member_error_card'\nimport { useGroupMembersForNewConversation } from '../../../hooks/groups/use_group_members_for_new_conversation'\nimport { useGroupsConversationCreate } from '../../../hooks/groups/use_groups_conversation_create'\n\ntype GroupsFormProps = {\n groupId: number\n}\n\nexport const GroupsForm = ({ groupId }: GroupsFormProps) => {\n const navigation = useNavigation()\n const [title, setTitle] = useState<string>()\n const { data: group } = useSuspenseGet<GroupsGroupResource>({\n url: `/me/groups/${groupId}`,\n data: {\n fields: {\n Group: [],\n },\n },\n app: 'groups',\n })\n\n const redirectToConversation = useCallback(\n (conversationId: number) => {\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: conversationId,\n })\n )\n },\n [navigation]\n )\n\n const groupMemberships = useGroupMembersForNewConversation({ id: groupId })\n\n const { mutate: handleSave } = useGroupsConversationCreate({\n groupId,\n title,\n onSuccess: redirectToConversation,\n })\n\n return (\n <KeyboardView>\n <FormList\n memberData={groupMemberships.data}\n FormContent={\n <FormContent\n group={group}\n title={title}\n setTitle={setTitle}\n isMemberError={groupMemberships.isError}\n />\n }\n />\n <ActionButton\n disabled={!title}\n title=\"Start Conversation\"\n onPress={() => handleSave()}\n infoText=\"Conversation will be automatically updated if any members are added or removed from this group.\"\n />\n </KeyboardView>\n )\n}\n\ninterface FormContentProps {\n group: GroupsGroupResource\n title?: string\n setTitle: (title: string) => void\n isMemberError: boolean\n}\n\nfunction FormContent({ group, title, setTitle, isMemberError }: FormContentProps) {\n const styles = useStyles()\n const { name, membershipsCount } = group\n const memberHeader = pluralize(membershipsCount, 'member')\n\n return (\n <View style={styles.formContent}>\n <View style={styles.toSection}>\n <Heading variant=\"h3\">To:</Heading>\n <Text style={styles.groupName}>{name}</Text>\n </View>\n <Divider />\n <View style={styles.titleSection}>\n <Heading variant=\"h3\">Title</Heading>\n <TextInput\n placeholder=\"Topic of conversation (required)\"\n value={title}\n onChangeText={setTitle}\n style={styles.titleInput}\n autoFocus={true}\n />\n </View>\n <Divider />\n <View style={styles.memberSection}>\n <Heading variant=\"h3\">{memberHeader} selected</Heading>\n {isMemberError && (\n <MemberErrorCard description=\"There was an issue loading group members, please refresh and try again.\" />\n )}\n </View>\n </View>\n )\n}\n\nconst useStyles = () => {\n const sectionPadding = 16\n const inputPadding = 8\n\n return StyleSheet.create({\n formContent: {\n paddingVertical: sectionPadding,\n flex: 1,\n },\n toSection: {\n padding: sectionPadding,\n flexDirection: 'row',\n gap: 8,\n },\n groupName: {\n fontSize: 18,\n },\n titleSection: {\n padding: sectionPadding,\n paddingBottom: Platform.select({\n ios: sectionPadding,\n android: sectionPadding - inputPadding,\n }),\n gap: Platform.select({\n ios: 8,\n android: 0,\n }),\n },\n titleInput: {\n fontSize: 18,\n },\n memberSection: {\n padding: sectionPadding,\n paddingBottom: 0,\n },\n })\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@planningcenter/chat-react-native",
|
|
3
|
-
"version": "3.2.0-rc.
|
|
3
|
+
"version": "3.2.0-rc.11",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -54,5 +54,5 @@
|
|
|
54
54
|
"prettier": "^3.4.2",
|
|
55
55
|
"typescript": "<5.6.0"
|
|
56
56
|
},
|
|
57
|
-
"gitHead": "
|
|
57
|
+
"gitHead": "06b41192c7283b3fa64d28c068c936df2cf6b4ae"
|
|
58
58
|
}
|
|
@@ -8,11 +8,13 @@ import { Text } from './text'
|
|
|
8
8
|
|
|
9
9
|
export const ActionButton = ({
|
|
10
10
|
visible = true,
|
|
11
|
+
disabled = false,
|
|
11
12
|
onPress,
|
|
12
13
|
title,
|
|
13
14
|
infoText,
|
|
14
15
|
}: {
|
|
15
16
|
visible?: boolean
|
|
17
|
+
disabled?: boolean
|
|
16
18
|
onPress: () => void
|
|
17
19
|
title: string
|
|
18
20
|
infoText?: string
|
|
@@ -36,7 +38,7 @@ export const ActionButton = ({
|
|
|
36
38
|
{infoText}
|
|
37
39
|
</Text>
|
|
38
40
|
)}
|
|
39
|
-
<Button variant="fill" size="lg" onPress={onPress} title={title} />
|
|
41
|
+
<Button variant="fill" size="lg" onPress={onPress} title={title} disabled={disabled} />
|
|
40
42
|
</Animated.View>
|
|
41
43
|
)
|
|
42
44
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { useMutation } from '@tanstack/react-query'
|
|
2
|
+
import { ApiResource, ConversationResource, ResourceObject } from '../../types'
|
|
3
|
+
import { useApiClient } from '../use_api_client'
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
groupId: number
|
|
7
|
+
title?: string
|
|
8
|
+
onSuccess: (conversationId: number) => void
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function useGroupsConversationCreate({ groupId, title, onSuccess }: Props) {
|
|
12
|
+
const apiClient = useApiClient()
|
|
13
|
+
return useMutation({
|
|
14
|
+
throwOnError: true,
|
|
15
|
+
onSuccess: result => {
|
|
16
|
+
onSuccess && onSuccess(result.data.id)
|
|
17
|
+
},
|
|
18
|
+
mutationFn: () =>
|
|
19
|
+
apiClient.groups
|
|
20
|
+
.post<ApiResource<ChatConversationPayload>>({
|
|
21
|
+
url: `/me/groups/${groupId}/chat_conversation_payload`,
|
|
22
|
+
data: {
|
|
23
|
+
data: {
|
|
24
|
+
type: '',
|
|
25
|
+
attributes: {
|
|
26
|
+
title,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
})
|
|
31
|
+
.then(res => res.data.value)
|
|
32
|
+
.then(payload =>
|
|
33
|
+
apiClient.chat.post<ApiResource<ConversationResource>>({
|
|
34
|
+
url: '/me/conversations',
|
|
35
|
+
data: {
|
|
36
|
+
data: {
|
|
37
|
+
type: 'Conversation',
|
|
38
|
+
attributes: {
|
|
39
|
+
payload,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
})
|
|
44
|
+
),
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface ChatConversationPayload extends ResourceObject {
|
|
49
|
+
value: string
|
|
50
|
+
}
|
|
@@ -4,32 +4,21 @@ import { Platform, StyleSheet, TextInput, View } from 'react-native'
|
|
|
4
4
|
import { Heading, Text } from '../../../components'
|
|
5
5
|
import { ActionButton } from '../../../components/display/action_button'
|
|
6
6
|
import { useSuspenseGet } from '../../../hooks'
|
|
7
|
-
import {
|
|
8
|
-
import { useMutation } from '@tanstack/react-query'
|
|
9
|
-
import {
|
|
10
|
-
ApiResource,
|
|
11
|
-
ConversationResource,
|
|
12
|
-
GroupsGroupResource,
|
|
13
|
-
ResourceObject,
|
|
14
|
-
} from '../../../types'
|
|
7
|
+
import { GroupsGroupResource } from '../../../types'
|
|
15
8
|
import { Divider, FormList } from './form_list'
|
|
16
9
|
import { pluralize } from '../../../utils'
|
|
17
10
|
import { KeyboardView } from '../../../components/display/keyboard_view'
|
|
18
11
|
import { MemberErrorCard } from './member_error_card'
|
|
19
12
|
import { useGroupMembersForNewConversation } from '../../../hooks/groups/use_group_members_for_new_conversation'
|
|
13
|
+
import { useGroupsConversationCreate } from '../../../hooks/groups/use_groups_conversation_create'
|
|
20
14
|
|
|
21
15
|
type GroupsFormProps = {
|
|
22
16
|
groupId: number
|
|
23
17
|
}
|
|
24
18
|
|
|
25
|
-
interface ChatConversationPayload extends ResourceObject {
|
|
26
|
-
value: string
|
|
27
|
-
}
|
|
28
|
-
|
|
29
19
|
export const GroupsForm = ({ groupId }: GroupsFormProps) => {
|
|
30
20
|
const navigation = useNavigation()
|
|
31
21
|
const [title, setTitle] = useState<string>()
|
|
32
|
-
const apiClient = useApiClient()
|
|
33
22
|
const { data: group } = useSuspenseGet<GroupsGroupResource>({
|
|
34
23
|
url: `/me/groups/${groupId}`,
|
|
35
24
|
data: {
|
|
@@ -40,56 +29,28 @@ export const GroupsForm = ({ groupId }: GroupsFormProps) => {
|
|
|
40
29
|
app: 'groups',
|
|
41
30
|
})
|
|
42
31
|
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
const { mutate: handleSave } = useMutation({
|
|
46
|
-
throwOnError: true,
|
|
47
|
-
onSuccess: result => {
|
|
48
|
-
handleRedirectToConversation({ conversation_id: result.data.id })
|
|
49
|
-
},
|
|
50
|
-
mutationFn: () =>
|
|
51
|
-
apiClient.groups
|
|
52
|
-
.post<ApiResource<ChatConversationPayload>>({
|
|
53
|
-
url: `/me/groups/${groupId}/chat_conversation_payload`,
|
|
54
|
-
data: {
|
|
55
|
-
data: {
|
|
56
|
-
type: '',
|
|
57
|
-
attributes: {
|
|
58
|
-
title,
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
},
|
|
62
|
-
})
|
|
63
|
-
.then(res => res.data.value)
|
|
64
|
-
.then(payload =>
|
|
65
|
-
apiClient.chat.post<ApiResource<ConversationResource>>({
|
|
66
|
-
url: '/me/conversations',
|
|
67
|
-
data: {
|
|
68
|
-
data: {
|
|
69
|
-
type: 'Conversation',
|
|
70
|
-
attributes: {
|
|
71
|
-
payload,
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
})
|
|
76
|
-
),
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
const handleRedirectToConversation = useCallback(
|
|
80
|
-
({ conversation_id }: { conversation_id: number }) => {
|
|
32
|
+
const redirectToConversation = useCallback(
|
|
33
|
+
(conversationId: number) => {
|
|
81
34
|
// exit from the create stack
|
|
82
35
|
navigation.getParent()?.goBack()
|
|
83
36
|
// navigate to the conversation screen
|
|
84
37
|
navigation.dispatch(
|
|
85
38
|
StackActions.push('Conversation', {
|
|
86
|
-
conversation_id,
|
|
39
|
+
conversation_id: conversationId,
|
|
87
40
|
})
|
|
88
41
|
)
|
|
89
42
|
},
|
|
90
43
|
[navigation]
|
|
91
44
|
)
|
|
92
45
|
|
|
46
|
+
const groupMemberships = useGroupMembersForNewConversation({ id: groupId })
|
|
47
|
+
|
|
48
|
+
const { mutate: handleSave } = useGroupsConversationCreate({
|
|
49
|
+
groupId,
|
|
50
|
+
title,
|
|
51
|
+
onSuccess: redirectToConversation,
|
|
52
|
+
})
|
|
53
|
+
|
|
93
54
|
return (
|
|
94
55
|
<KeyboardView>
|
|
95
56
|
<FormList
|
|
@@ -104,6 +65,7 @@ export const GroupsForm = ({ groupId }: GroupsFormProps) => {
|
|
|
104
65
|
}
|
|
105
66
|
/>
|
|
106
67
|
<ActionButton
|
|
68
|
+
disabled={!title}
|
|
107
69
|
title="Start Conversation"
|
|
108
70
|
onPress={() => handleSave()}
|
|
109
71
|
infoText="Conversation will be automatically updated if any members are added or removed from this group."
|