@planningcenter/chat-react-native 3.2.0-rc.8 → 3.2.0-rc.9

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.
Files changed (25) hide show
  1. package/build/components/display/person.d.ts +3 -1
  2. package/build/components/display/person.d.ts.map +1 -1
  3. package/build/components/display/person.js +2 -2
  4. package/build/components/display/person.js.map +1 -1
  5. package/build/screens/conversation_new/components/form_list.d.ts +12 -0
  6. package/build/screens/conversation_new/components/form_list.d.ts.map +1 -0
  7. package/build/screens/conversation_new/components/form_list.js +42 -0
  8. package/build/screens/conversation_new/components/form_list.js.map +1 -0
  9. package/build/screens/conversation_new/components/groups_form.d.ts.map +1 -1
  10. package/build/screens/conversation_new/components/groups_form.js +56 -49
  11. package/build/screens/conversation_new/components/groups_form.js.map +1 -1
  12. package/build/screens/conversation_new/components/member_error_card.d.ts +5 -0
  13. package/build/screens/conversation_new/components/member_error_card.d.ts.map +1 -0
  14. package/build/screens/conversation_new/components/member_error_card.js +17 -0
  15. package/build/screens/conversation_new/components/member_error_card.js.map +1 -0
  16. package/build/screens/conversation_new/utils/fake_member_data.d.ts +3 -0
  17. package/build/screens/conversation_new/utils/fake_member_data.d.ts.map +1 -0
  18. package/build/screens/conversation_new/utils/fake_member_data.js +129 -0
  19. package/build/screens/conversation_new/utils/fake_member_data.js.map +1 -0
  20. package/package.json +2 -2
  21. package/src/components/display/person.tsx +4 -3
  22. package/src/screens/conversation_new/components/form_list.tsx +67 -0
  23. package/src/screens/conversation_new/components/groups_form.tsx +84 -52
  24. package/src/screens/conversation_new/components/member_error_card.tsx +20 -0
  25. package/src/screens/conversation_new/utils/fake_member_data.ts +130 -0
@@ -1,8 +1,10 @@
1
1
  import React from 'react';
2
+ import { type ViewStyle } from 'react-native';
2
3
  import { MemberResource } from '../../types';
3
4
  interface PersonProps {
4
5
  person: MemberResource;
6
+ style?: ViewStyle;
5
7
  }
6
- export declare function Person({ person }: PersonProps): React.JSX.Element;
8
+ export declare function Person({ person, style }: PersonProps): React.JSX.Element;
7
9
  export {};
8
10
  //# sourceMappingURL=person.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"person.d.ts","sourceRoot":"","sources":["../../../src/components/display/person.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAU5C,UAAU,WAAW;IACnB,MAAM,EAAE,cAAc,CAAA;CACvB;AAED,wBAAgB,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,WAAW,qBAc7C"}
1
+ {"version":3,"file":"person.d.ts","sourceRoot":"","sources":["../../../src/components/display/person.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,cAAc,CAAA;AAE/D,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAU5C,UAAU,WAAW;IACnB,MAAM,EAAE,cAAc,CAAA;IACtB,KAAK,CAAC,EAAE,SAAS,CAAA;CAClB;AAED,wBAAgB,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,WAAW,qBAcpD"}
@@ -5,9 +5,9 @@ import { Avatar } from './avatar';
5
5
  import { Text } from './text';
6
6
  import { Badge } from './badge';
7
7
  import { space } from '../../utils';
8
- export function Person({ person }) {
8
+ export function Person({ person, style }) {
9
9
  const styles = useStyles();
10
- return (<View style={styles.wrapper}>
10
+ return (<View style={[styles.wrapper, style]}>
11
11
  <Avatar sourceUri={person.avatar}/>
12
12
  <View style={styles.content}>
13
13
  <Text style={styles.name}>{person.name}</Text>
@@ -1 +1 @@
1
- {"version":3,"file":"person.js","sourceRoot":"","sources":["../../../src/components/display/person.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAA;AAE7D,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAUnC,MAAM,UAAU,MAAM,CAAC,EAAE,MAAM,EAAe;IAC5C,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAE1B,OAAO,CACL,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAC1B;MAAA,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EACjC;MAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAC1B;QAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,CAC7C;QAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CACzB;UAAA,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAG,CAAC,CAClF;QAAA,EAAE,IAAI,CACR;MAAA,EAAE,IAAI,CACR;IAAA,EAAE,IAAI,CAAC,CACR,CAAA;AACH,CAAC;AAED,oCAAoC;AACpC,oCAAoC;AACpC,oCAAoC;AAEpC,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,OAAO,UAAU,CAAC,MAAM,CAAC;QACvB,OAAO,EAAE;YACP,aAAa,EAAE,KAAK;YACpB,UAAU,EAAE,QAAQ;YACpB,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;SACd;QACD,OAAO,EAAE;YACP,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC;SACjB;QACD,IAAI,EAAE;YACJ,UAAU,EAAE,wBAAwB;SACrC;QACD,MAAM,EAAE;YACN,aAAa,EAAE,KAAK;YACpB,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC;SAChB;KACF,CAAC,CAAA;AACJ,CAAC,CAAA","sourcesContent":["import React from 'react'\nimport { StyleSheet, View } from 'react-native'\nimport { platformFontWeightMedium } from '../../utils/styles'\nimport { MemberResource } from '../../types'\nimport { Avatar } from './avatar'\nimport { Text } from './text'\nimport { Badge } from './badge'\nimport { space } from '../../utils'\n\n// =================================\n// ====== Components ===============\n// =================================\n\ninterface PersonProps {\n person: MemberResource\n}\n\nexport function Person({ person }: PersonProps) {\n const styles = useStyles()\n\n return (\n <View style={styles.wrapper}>\n <Avatar sourceUri={person.avatar} />\n <View style={styles.content}>\n <Text style={styles.name}>{person.name}</Text>\n <View style={styles.badges}>\n {person.badges?.map((badge, index) => <Badge key={index} label={badge.title} />)}\n </View>\n </View>\n </View>\n )\n}\n\n// =================================\n// ====== Styles ===================\n// =================================\n\nconst useStyles = () => {\n return StyleSheet.create({\n wrapper: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: space(1),\n },\n content: {\n gap: space(0.25),\n },\n name: {\n fontWeight: platformFontWeightMedium,\n },\n badges: {\n flexDirection: 'row',\n gap: space(0.5),\n },\n })\n}\n"]}
1
+ {"version":3,"file":"person.js","sourceRoot":"","sources":["../../../src/components/display/person.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,UAAU,EAAE,IAAI,EAAkB,MAAM,cAAc,CAAA;AAC/D,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAA;AAE7D,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAWnC,MAAM,UAAU,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,EAAe;IACnD,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAE1B,OAAO,CACL,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CACnC;MAAA,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EACjC;MAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAC1B;QAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,CAC7C;QAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CACzB;UAAA,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAG,CAAC,CAClF;QAAA,EAAE,IAAI,CACR;MAAA,EAAE,IAAI,CACR;IAAA,EAAE,IAAI,CAAC,CACR,CAAA;AACH,CAAC;AAED,oCAAoC;AACpC,oCAAoC;AACpC,oCAAoC;AAEpC,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,OAAO,UAAU,CAAC,MAAM,CAAC;QACvB,OAAO,EAAE;YACP,aAAa,EAAE,KAAK;YACpB,UAAU,EAAE,QAAQ;YACpB,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;SACd;QACD,OAAO,EAAE;YACP,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC;SACjB;QACD,IAAI,EAAE;YACJ,UAAU,EAAE,wBAAwB;SACrC;QACD,MAAM,EAAE;YACN,aAAa,EAAE,KAAK;YACpB,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC;SAChB;KACF,CAAC,CAAA;AACJ,CAAC,CAAA","sourcesContent":["import React from 'react'\nimport { StyleSheet, View, type ViewStyle } from 'react-native'\nimport { platformFontWeightMedium } from '../../utils/styles'\nimport { MemberResource } from '../../types'\nimport { Avatar } from './avatar'\nimport { Text } from './text'\nimport { Badge } from './badge'\nimport { space } from '../../utils'\n\n// =================================\n// ====== Components ===============\n// =================================\n\ninterface PersonProps {\n person: MemberResource\n style?: ViewStyle\n}\n\nexport function Person({ person, style }: PersonProps) {\n const styles = useStyles()\n\n return (\n <View style={[styles.wrapper, style]}>\n <Avatar sourceUri={person.avatar} />\n <View style={styles.content}>\n <Text style={styles.name}>{person.name}</Text>\n <View style={styles.badges}>\n {person.badges?.map((badge, index) => <Badge key={index} label={badge.title} />)}\n </View>\n </View>\n </View>\n )\n}\n\n// =================================\n// ====== Styles ===================\n// =================================\n\nconst useStyles = () => {\n return StyleSheet.create({\n wrapper: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: space(1),\n },\n content: {\n gap: space(0.25),\n },\n name: {\n fontWeight: platformFontWeightMedium,\n },\n badges: {\n flexDirection: 'row',\n gap: space(0.5),\n },\n })\n}\n"]}
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { type FlashListProps } from '@shopify/flash-list';
3
+ import { MemberResource } from '../../../types';
4
+ interface FormListProps {
5
+ memberData: MemberResource[];
6
+ FormContent?: FlashListProps<MemberResource>['ListHeaderComponent'];
7
+ listEmptyText?: string;
8
+ }
9
+ export declare const FormList: ({ memberData, FormContent, listEmptyText }: FormListProps) => React.JSX.Element;
10
+ export declare const Divider: () => React.JSX.Element;
11
+ export {};
12
+ //# sourceMappingURL=form_list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form_list.d.ts","sourceRoot":"","sources":["../../../../src/screens/conversation_new/components/form_list.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAI/C,UAAU,aAAa;IACrB,UAAU,EAAE,cAAc,EAAE,CAAA;IAC5B,WAAW,CAAC,EAAE,cAAc,CAAC,cAAc,CAAC,CAAC,qBAAqB,CAAC,CAAA;IACnE,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,eAAO,MAAM,QAAQ,+CAAgD,aAAa,sBAajF,CAAA;AAYD,eAAO,MAAM,OAAO,yBAInB,CAAA"}
@@ -0,0 +1,42 @@
1
+ import React from 'react';
2
+ import { StyleSheet, View } from 'react-native';
3
+ import { FlashList } from '@shopify/flash-list';
4
+ import { Person, Text } from '../../../components/display';
5
+ import { useTheme } from '../../../hooks';
6
+ export const FormList = ({ memberData, FormContent, listEmptyText }) => {
7
+ const styles = useStyles();
8
+ return (<FlashList data={memberData} ListHeaderComponent={FormContent} renderItem={({ item }) => <Person person={item} style={styles.person}/>} keyExtractor={item => item.id.toString()} estimatedItemSize={45} ListEmptyComponent={<ListEmptyText text={listEmptyText || 'No members found'}/>}/>);
9
+ };
10
+ const ListEmptyText = ({ text }) => {
11
+ const styles = useStyles();
12
+ return (<View style={styles.emptyTextContainer}>
13
+ <Text style={styles.emptyText}>{text}</Text>
14
+ </View>);
15
+ };
16
+ export const Divider = () => {
17
+ const styles = useStyles();
18
+ return <View style={styles.divider}/>;
19
+ };
20
+ const useStyles = () => {
21
+ const { colors } = useTheme();
22
+ return StyleSheet.create({
23
+ person: {
24
+ paddingHorizontal: 16,
25
+ paddingBottom: 12,
26
+ },
27
+ emptyTextContainer: {
28
+ alignItems: 'center',
29
+ justifyContent: 'center',
30
+ padding: 32,
31
+ },
32
+ emptyText: {
33
+ textAlign: 'center',
34
+ color: colors.textColorDefaultSecondary,
35
+ },
36
+ divider: {
37
+ borderBottomWidth: 1,
38
+ borderBottomColor: colors.fillColorNeutral050Base,
39
+ },
40
+ });
41
+ };
42
+ //# sourceMappingURL=form_list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form_list.js","sourceRoot":"","sources":["../../../../src/screens/conversation_new/components/form_list.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,SAAS,EAAuB,MAAM,qBAAqB,CAAA;AAEpE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,6BAA6B,CAAA;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAQzC,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAiB,EAAE,EAAE;IACpF,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAE1B,OAAO,CACL,CAAC,SAAS,CACR,IAAI,CAAC,CAAC,UAAU,CAAC,CACjB,mBAAmB,CAAC,CAAC,WAAW,CAAC,CACjC,UAAU,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAG,CAAC,CACzE,YAAY,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,CACzC,iBAAiB,CAAC,CAAC,EAAE,CAAC,CACtB,kBAAkB,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,aAAa,IAAI,kBAAkB,CAAC,EAAG,CAAC,EACjF,CACH,CAAA;AACH,CAAC,CAAA;AAED,MAAM,aAAa,GAAG,CAAC,EAAE,IAAI,EAAoB,EAAE,EAAE;IACnD,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAE1B,OAAO,CACL,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC,CACrC;MAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,CAC7C;IAAA,EAAE,IAAI,CAAC,CACR,CAAA;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,GAAG,EAAE;IAC1B,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAE1B,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAG,CAAA;AACxC,CAAC,CAAA;AAED,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAA;IAE7B,OAAO,UAAU,CAAC,MAAM,CAAC;QACvB,MAAM,EAAE;YACN,iBAAiB,EAAE,EAAE;YACrB,aAAa,EAAE,EAAE;SAClB;QACD,kBAAkB,EAAE;YAClB,UAAU,EAAE,QAAQ;YACpB,cAAc,EAAE,QAAQ;YACxB,OAAO,EAAE,EAAE;SACZ;QACD,SAAS,EAAE;YACT,SAAS,EAAE,QAAQ;YACnB,KAAK,EAAE,MAAM,CAAC,yBAAyB;SACxC;QACD,OAAO,EAAE;YACP,iBAAiB,EAAE,CAAC;YACpB,iBAAiB,EAAE,MAAM,CAAC,uBAAuB;SAClD;KACF,CAAC,CAAA;AACJ,CAAC,CAAA","sourcesContent":["import React from 'react'\nimport { StyleSheet, View } from 'react-native'\nimport { FlashList, type FlashListProps } from '@shopify/flash-list'\nimport { MemberResource } from '../../../types'\nimport { Person, Text } from '../../../components/display'\nimport { useTheme } from '../../../hooks'\n\ninterface FormListProps {\n memberData: MemberResource[]\n FormContent?: FlashListProps<MemberResource>['ListHeaderComponent']\n listEmptyText?: string\n}\n\nexport const FormList = ({ memberData, FormContent, listEmptyText }: FormListProps) => {\n const styles = useStyles()\n\n return (\n <FlashList\n data={memberData}\n ListHeaderComponent={FormContent}\n renderItem={({ item }) => <Person person={item} style={styles.person} />}\n keyExtractor={item => item.id.toString()}\n estimatedItemSize={45}\n ListEmptyComponent={<ListEmptyText text={listEmptyText || 'No members found'} />}\n />\n )\n}\n\nconst ListEmptyText = ({ text }: { text: string }) => {\n const styles = useStyles()\n\n return (\n <View style={styles.emptyTextContainer}>\n <Text style={styles.emptyText}>{text}</Text>\n </View>\n )\n}\n\nexport const Divider = () => {\n const styles = useStyles()\n\n return <View style={styles.divider} />\n}\n\nconst useStyles = () => {\n const { colors } = useTheme()\n\n return StyleSheet.create({\n person: {\n paddingHorizontal: 16,\n paddingBottom: 12,\n },\n emptyTextContainer: {\n alignItems: 'center',\n justifyContent: 'center',\n padding: 32,\n },\n emptyText: {\n textAlign: 'center',\n color: colors.textColorDefaultSecondary,\n },\n divider: {\n borderBottomWidth: 1,\n borderBottomColor: colors.fillColorNeutral050Base,\n },\n })\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;AAepD,KAAK,eAAe,GAAG;IACrB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAMD,eAAO,MAAM,UAAU,gBAAiB,eAAe,sBAqFtD,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;AAmBpD,KAAK,eAAe,GAAG;IACrB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAMD,eAAO,MAAM,UAAU,gBAAiB,eAAe,sBAgFtD,CAAA"}
@@ -1,14 +1,17 @@
1
1
  import { StackActions, useNavigation } from '@react-navigation/native';
2
2
  import React, { useCallback, useState } from 'react';
3
- import { StyleSheet, TextInput, View } from 'react-native';
4
- import { useSafeAreaInsets } from 'react-native-safe-area-context';
5
- import { Text } from '../../../components';
3
+ import { Platform, StyleSheet, TextInput, View } from 'react-native';
4
+ import { Heading, Text } from '../../../components';
6
5
  import { ActionButton } from '../../../components/display/action_button';
7
- import { useSuspenseGet, useTheme } from '../../../hooks';
6
+ import { useSuspenseGet } from '../../../hooks';
8
7
  import { useApiClient } from '../../../hooks/use_api_client';
9
8
  import { useMutation } from '@tanstack/react-query';
9
+ import { FAKE_MEMBER_DATA } from '../utils/fake_member_data';
10
+ import { Divider, FormList } from './form_list';
11
+ import { pluralize } from '../../../utils';
12
+ import { KeyboardView } from '../../../components/display/keyboard_view';
13
+ import { MemberErrorCard } from './member_error_card';
10
14
  export const GroupsForm = ({ groupId }) => {
11
- const styles = useStyles();
12
15
  const navigation = useNavigation();
13
16
  const [title, setTitle] = useState();
14
17
  const apiClient = useApiClient();
@@ -21,6 +24,7 @@ export const GroupsForm = ({ groupId }) => {
21
24
  },
22
25
  app: 'groups',
23
26
  });
27
+ const isMemberError = false; // TODO: Replace with error from a future useGroupsMember hook
24
28
  const { mutate: handleSave } = useMutation({
25
29
  throwOnError: true,
26
30
  onSuccess: result => {
@@ -59,63 +63,66 @@ export const GroupsForm = ({ groupId }) => {
59
63
  conversation_id,
60
64
  }));
61
65
  }, [navigation]);
62
- return (<View style={styles.container}>
63
- <View style={styles.section}>
64
- <View style={styles.to}>
65
- <Text>To:</Text>
66
- <View>
67
- <Text>{group.name}</Text>
68
- <Text>{group.membershipsCount} members</Text>
69
- </View>
70
- </View>
71
- <View style={styles.titleContainer}>
72
- <Text style={styles.titleLabel}>Title</Text>
73
- <TextInput placeholder="Topic of conversation (required)" value={title} onChangeText={setTitle} style={styles.titleInput}/>
74
- </View>
75
- </View>
66
+ return (<KeyboardView>
67
+ <FormList memberData={FAKE_MEMBER_DATA} // TODO: Replace with actual group members
68
+ FormContent={<FormContent group={group} title={title} setTitle={setTitle} isMemberError={isMemberError}/>}/>
76
69
  <ActionButton title="Start Conversation" onPress={() => handleSave()}/>
77
- </View>);
70
+ </KeyboardView>);
78
71
  };
72
+ function FormContent({ group, title, setTitle, isMemberError }) {
73
+ const styles = useStyles();
74
+ const { name, membershipsCount } = group;
75
+ const memberHeader = pluralize(membershipsCount, 'member');
76
+ return (<View style={styles.formContent}>
77
+ <View style={styles.toSection}>
78
+ <Heading variant="h3">To:</Heading>
79
+ <Text style={styles.groupName}>{name}</Text>
80
+ </View>
81
+ <Divider />
82
+ <View style={styles.titleSection}>
83
+ <Heading variant="h3">Title</Heading>
84
+ <TextInput placeholder="Topic of conversation (required)" value={title} onChangeText={setTitle} style={styles.titleInput} autoFocus={true}/>
85
+ </View>
86
+ <Divider />
87
+ <View style={styles.memberSection}>
88
+ <Heading variant="h3">{memberHeader} selected</Heading>
89
+ {isMemberError && (<MemberErrorCard description="There was an issue loading group members, please refresh and try again."/>)}
90
+ </View>
91
+ </View>);
92
+ }
79
93
  const useStyles = () => {
80
- const { bottom } = useSafeAreaInsets();
81
- const theme = useTheme();
94
+ const sectionPadding = 16;
95
+ const inputPadding = 8;
82
96
  return StyleSheet.create({
83
- container: {
84
- flex: 1,
85
- gap: 8,
86
- },
87
- section: {
88
- padding: 16,
97
+ formContent: {
98
+ paddingVertical: sectionPadding,
89
99
  flex: 1,
90
100
  },
91
- sectionHeader: {
101
+ toSection: {
102
+ padding: sectionPadding,
92
103
  flexDirection: 'row',
93
- justifyContent: 'space-between',
104
+ gap: 8,
94
105
  },
95
- selectTeamsButton: {},
96
- routeDebug: {
97
- alignContent: 'center',
98
- padding: 16,
99
- paddingBottom: bottom,
100
- borderTopWidth: 1,
101
- borderTopColor: theme.colors.fillColorNeutral050Base,
106
+ groupName: {
107
+ fontSize: 18,
102
108
  },
103
- titleContainer: {
104
- paddingVertical: 12,
105
- borderBottomWidth: 1,
106
- borderBottomColor: theme.colors.fillColorNeutral050Base,
107
- gap: 8,
109
+ titleSection: {
110
+ padding: sectionPadding,
111
+ paddingBottom: Platform.select({
112
+ ios: sectionPadding,
113
+ android: sectionPadding - inputPadding,
114
+ }),
115
+ gap: Platform.select({
116
+ ios: 8,
117
+ android: 0,
118
+ }),
108
119
  },
109
120
  titleInput: {
110
121
  fontSize: 18,
111
122
  },
112
- titleLabel: {},
113
- to: {
114
- flexDirection: 'row',
115
- gap: 8,
116
- paddingVertical: 12,
117
- borderBottomWidth: 1,
118
- borderBottomColor: theme.colors.fillColorNeutral050Base,
123
+ memberSection: {
124
+ padding: sectionPadding,
125
+ paddingBottom: 0,
119
126
  },
120
127
  });
121
128
  };
@@ -1 +1 @@
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 { StyleSheet, TextInput, View } from 'react-native'\nimport { useSafeAreaInsets } from 'react-native-safe-area-context'\nimport { Text } from '../../../components'\nimport { ActionButton } from '../../../components/display/action_button'\nimport { useSuspenseGet, useTheme } from '../../../hooks'\nimport { useApiClient } from '../../../hooks/use_api_client'\nimport { useMutation } from '@tanstack/react-query'\nimport {\n ApiResource,\n ConversationResource,\n GroupsGroupResource,\n ResourceObject,\n} from '../../../types'\n\ntype GroupsFormProps = {\n groupId?: string\n}\n\ninterface ChatConversationPayload extends ResourceObject {\n value: string\n}\n\nexport const GroupsForm = ({ groupId }: GroupsFormProps) => {\n const styles = useStyles()\n const navigation = useNavigation()\n const [title, setTitle] = useState<string>()\n const apiClient = useApiClient()\n const { data: group } = useSuspenseGet<GroupsGroupResource>({\n url: `/me/groups/${groupId}`,\n data: {\n fields: {\n Group: [],\n },\n },\n app: 'groups',\n })\n const { mutate: handleSave } = useMutation({\n throwOnError: true,\n onSuccess: result => {\n handleRedirectToConversation({ conversation_id: 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 const handleRedirectToConversation = useCallback(\n ({ conversation_id }: { conversation_id: 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,\n })\n )\n },\n [navigation]\n )\n\n return (\n <View style={styles.container}>\n <View style={styles.section}>\n <View style={styles.to}>\n <Text>To:</Text>\n <View>\n <Text>{group.name}</Text>\n <Text>{group.membershipsCount} members</Text>\n </View>\n </View>\n <View style={styles.titleContainer}>\n <Text style={styles.titleLabel}>Title</Text>\n <TextInput\n placeholder=\"Topic of conversation (required)\"\n value={title}\n onChangeText={setTitle}\n style={styles.titleInput}\n />\n </View>\n </View>\n <ActionButton title=\"Start Conversation\" onPress={() => handleSave()} />\n </View>\n )\n}\n\nconst useStyles = () => {\n const { bottom } = useSafeAreaInsets()\n const theme = useTheme()\n\n return StyleSheet.create({\n container: {\n flex: 1,\n gap: 8,\n },\n section: {\n padding: 16,\n flex: 1,\n },\n sectionHeader: {\n flexDirection: 'row',\n justifyContent: 'space-between',\n },\n selectTeamsButton: {},\n routeDebug: {\n alignContent: 'center',\n padding: 16,\n paddingBottom: bottom,\n borderTopWidth: 1,\n borderTopColor: theme.colors.fillColorNeutral050Base,\n },\n titleContainer: {\n paddingVertical: 12,\n borderBottomWidth: 1,\n borderBottomColor: theme.colors.fillColorNeutral050Base,\n gap: 8,\n },\n titleInput: {\n fontSize: 18,\n },\n titleLabel: {},\n to: {\n flexDirection: 'row',\n gap: 8,\n paddingVertical: 12,\n borderBottomWidth: 1,\n borderBottomColor: theme.colors.fillColorNeutral050Base,\n },\n })\n}\n"]}
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 { useApiClient } from '../../../hooks/use_api_client'\nimport { useMutation } from '@tanstack/react-query'\nimport {\n ApiResource,\n ConversationResource,\n GroupsGroupResource,\n ResourceObject,\n} from '../../../types'\nimport { FAKE_MEMBER_DATA } from '../utils/fake_member_data'\nimport { Divider, FormList } from './form_list'\nimport { pluralize } from '../../../utils'\nimport { KeyboardView } from '../../../components/display/keyboard_view'\nimport { MemberErrorCard } from './member_error_card'\n\ntype GroupsFormProps = {\n groupId?: string\n}\n\ninterface ChatConversationPayload extends ResourceObject {\n value: string\n}\n\nexport const GroupsForm = ({ groupId }: GroupsFormProps) => {\n const navigation = useNavigation()\n const [title, setTitle] = useState<string>()\n const apiClient = useApiClient()\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 isMemberError = false // TODO: Replace with error from a future useGroupsMember hook\n\n const { mutate: handleSave } = useMutation({\n throwOnError: true,\n onSuccess: result => {\n handleRedirectToConversation({ conversation_id: 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 const handleRedirectToConversation = useCallback(\n ({ conversation_id }: { conversation_id: 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,\n })\n )\n },\n [navigation]\n )\n\n return (\n <KeyboardView>\n <FormList\n memberData={FAKE_MEMBER_DATA} // TODO: Replace with actual group members\n FormContent={\n <FormContent\n group={group}\n title={title}\n setTitle={setTitle}\n isMemberError={isMemberError}\n />\n }\n />\n <ActionButton title=\"Start Conversation\" onPress={() => handleSave()} />\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"]}
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ export declare const MemberErrorCard: ({ description }: {
3
+ description: string;
4
+ }) => React.JSX.Element;
5
+ //# sourceMappingURL=member_error_card.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"member_error_card.d.ts","sourceRoot":"","sources":["../../../../src/screens/conversation_new/components/member_error_card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAIzB,eAAO,MAAM,eAAe,oBAAqB;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,sBAOvE,CAAA"}
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { View, StyleSheet } from 'react-native';
3
+ import { Banner } from '../../../components';
4
+ export const MemberErrorCard = ({ description }) => {
5
+ const styles = useStyles();
6
+ return (<View style={styles.memberErrorBanner}>
7
+ <Banner appearance="error" description={description}/>
8
+ </View>);
9
+ };
10
+ const useStyles = () => {
11
+ return StyleSheet.create({
12
+ memberErrorBanner: {
13
+ paddingTop: 16,
14
+ },
15
+ });
16
+ };
17
+ //# sourceMappingURL=member_error_card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"member_error_card.js","sourceRoot":"","sources":["../../../../src/screens/conversation_new/components/member_error_card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAE5C,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,EAAE,WAAW,EAA2B,EAAE,EAAE;IAC1E,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAC1B,OAAO,CACL,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,CACpC;MAAA,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,EACtD;IAAA,EAAE,IAAI,CAAC,CACR,CAAA;AACH,CAAC,CAAA;AAED,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,OAAO,UAAU,CAAC,MAAM,CAAC;QACvB,iBAAiB,EAAE;YACjB,UAAU,EAAE,EAAE;SACf;KACF,CAAC,CAAA;AACJ,CAAC,CAAA","sourcesContent":["import React from 'react'\nimport { View, StyleSheet } from 'react-native'\nimport { Banner } from '../../../components'\n\nexport const MemberErrorCard = ({ description }: { description: string }) => {\n const styles = useStyles()\n return (\n <View style={styles.memberErrorBanner}>\n <Banner appearance=\"error\" description={description} />\n </View>\n )\n}\n\nconst useStyles = () => {\n return StyleSheet.create({\n memberErrorBanner: {\n paddingTop: 16,\n },\n })\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import { MemberResource } from '../../../types';
2
+ export declare const FAKE_MEMBER_DATA: MemberResource[];
3
+ //# sourceMappingURL=fake_member_data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fake_member_data.d.ts","sourceRoot":"","sources":["../../../../src/screens/conversation_new/utils/fake_member_data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAE/C,eAAO,MAAM,gBAAgB,EAAE,cAAc,EA+H5C,CAAA"}
@@ -0,0 +1,129 @@
1
+ export const FAKE_MEMBER_DATA = [
2
+ {
3
+ type: 'Member',
4
+ id: 1,
5
+ name: 'John Doe',
6
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/JD.png',
7
+ badges: [{ title: 'Leader' }, { title: 'Conversation owner' }],
8
+ child: false,
9
+ role: 'unknown',
10
+ },
11
+ {
12
+ type: 'Member',
13
+ id: 2,
14
+ name: 'Jane Smith',
15
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/JS.png',
16
+ badges: [{ title: 'Leader' }],
17
+ child: false,
18
+ role: 'unknown',
19
+ },
20
+ {
21
+ type: 'Member',
22
+ id: 3,
23
+ name: 'Bob Wilson',
24
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/BW.png',
25
+ badges: [],
26
+ child: false,
27
+ role: 'unknown',
28
+ },
29
+ {
30
+ type: 'Member',
31
+ id: 4,
32
+ name: 'Sarah Johnson',
33
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/SJ.png',
34
+ badges: [{ title: 'Leader' }],
35
+ child: false,
36
+ role: 'unknown',
37
+ },
38
+ {
39
+ type: 'Member',
40
+ id: 5,
41
+ name: 'Mike Brown',
42
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/MB.png',
43
+ badges: [],
44
+ child: false,
45
+ role: 'unknown',
46
+ },
47
+ {
48
+ type: 'Member',
49
+ id: 6,
50
+ name: 'Emily Davis',
51
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/ED.png',
52
+ badges: [{ title: 'Leader' }],
53
+ child: false,
54
+ role: 'unknown',
55
+ },
56
+ {
57
+ type: 'Member',
58
+ id: 7,
59
+ name: 'James Miller',
60
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/JM.png',
61
+ badges: [],
62
+ child: false,
63
+ role: 'unknown',
64
+ },
65
+ {
66
+ type: 'Member',
67
+ id: 8,
68
+ name: 'Lisa Anderson',
69
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/LA.png',
70
+ badges: [],
71
+ child: false,
72
+ role: 'unknown',
73
+ },
74
+ {
75
+ type: 'Member',
76
+ id: 9,
77
+ name: 'David Taylor',
78
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/DT.png',
79
+ badges: [{ title: 'Leader' }],
80
+ child: false,
81
+ role: 'unknown',
82
+ },
83
+ {
84
+ type: 'Member',
85
+ id: 10,
86
+ name: 'Rachel White',
87
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/RW.png',
88
+ badges: [],
89
+ child: false,
90
+ role: 'unknown',
91
+ },
92
+ {
93
+ type: 'Member',
94
+ id: 11,
95
+ name: 'Kevin Martin',
96
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/KM.png',
97
+ badges: [{ title: 'Leader' }],
98
+ child: false,
99
+ role: 'unknown',
100
+ },
101
+ {
102
+ type: 'Member',
103
+ id: 12,
104
+ name: 'Michelle Lee',
105
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/ML.png',
106
+ badges: [],
107
+ child: false,
108
+ role: 'unknown',
109
+ },
110
+ {
111
+ type: 'Member',
112
+ id: 13,
113
+ name: 'Daniel Clark',
114
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/DC.png',
115
+ badges: [],
116
+ child: false,
117
+ role: 'unknown',
118
+ },
119
+ {
120
+ type: 'Member',
121
+ id: 14,
122
+ name: 'Amanda Moore',
123
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/AM.png',
124
+ badges: [{ title: 'Leader' }],
125
+ child: false,
126
+ role: 'unknown',
127
+ },
128
+ ];
129
+ //# sourceMappingURL=fake_member_data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fake_member_data.js","sourceRoot":"","sources":["../../../../src/screens/conversation_new/utils/fake_member_data.ts"],"names":[],"mappings":"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","sourcesContent":["import { MemberResource } from '../../../types'\n\nexport const FAKE_MEMBER_DATA: MemberResource[] = [\n {\n type: 'Member',\n id: 1,\n name: 'John Doe',\n avatar: 'https://avatars.planningcenteronline.com/uploads/initials/JD.png',\n badges: [{ title: 'Leader' }, { title: 'Conversation owner' }],\n child: false,\n role: 'unknown',\n },\n {\n type: 'Member',\n id: 2,\n name: 'Jane Smith',\n avatar: 'https://avatars.planningcenteronline.com/uploads/initials/JS.png',\n badges: [{ title: 'Leader' }],\n child: false,\n role: 'unknown',\n },\n {\n type: 'Member',\n id: 3,\n name: 'Bob Wilson',\n avatar: 'https://avatars.planningcenteronline.com/uploads/initials/BW.png',\n badges: [],\n child: false,\n role: 'unknown',\n },\n {\n type: 'Member',\n id: 4,\n name: 'Sarah Johnson',\n avatar: 'https://avatars.planningcenteronline.com/uploads/initials/SJ.png',\n badges: [{ title: 'Leader' }],\n child: false,\n role: 'unknown',\n },\n {\n type: 'Member',\n id: 5,\n name: 'Mike Brown',\n avatar: 'https://avatars.planningcenteronline.com/uploads/initials/MB.png',\n badges: [],\n child: false,\n role: 'unknown',\n },\n {\n type: 'Member',\n id: 6,\n name: 'Emily Davis',\n avatar: 'https://avatars.planningcenteronline.com/uploads/initials/ED.png',\n badges: [{ title: 'Leader' }],\n child: false,\n role: 'unknown',\n },\n {\n type: 'Member',\n id: 7,\n name: 'James Miller',\n avatar: 'https://avatars.planningcenteronline.com/uploads/initials/JM.png',\n badges: [],\n child: false,\n role: 'unknown',\n },\n {\n type: 'Member',\n id: 8,\n name: 'Lisa Anderson',\n avatar: 'https://avatars.planningcenteronline.com/uploads/initials/LA.png',\n badges: [],\n child: false,\n role: 'unknown',\n },\n {\n type: 'Member',\n id: 9,\n name: 'David Taylor',\n avatar: 'https://avatars.planningcenteronline.com/uploads/initials/DT.png',\n badges: [{ title: 'Leader' }],\n child: false,\n role: 'unknown',\n },\n {\n type: 'Member',\n id: 10,\n name: 'Rachel White',\n avatar: 'https://avatars.planningcenteronline.com/uploads/initials/RW.png',\n badges: [],\n child: false,\n role: 'unknown',\n },\n {\n type: 'Member',\n id: 11,\n name: 'Kevin Martin',\n avatar: 'https://avatars.planningcenteronline.com/uploads/initials/KM.png',\n badges: [{ title: 'Leader' }],\n child: false,\n role: 'unknown',\n },\n {\n type: 'Member',\n id: 12,\n name: 'Michelle Lee',\n avatar: 'https://avatars.planningcenteronline.com/uploads/initials/ML.png',\n badges: [],\n child: false,\n role: 'unknown',\n },\n {\n type: 'Member',\n id: 13,\n name: 'Daniel Clark',\n avatar: 'https://avatars.planningcenteronline.com/uploads/initials/DC.png',\n badges: [],\n child: false,\n role: 'unknown',\n },\n {\n type: 'Member',\n id: 14,\n name: 'Amanda Moore',\n avatar: 'https://avatars.planningcenteronline.com/uploads/initials/AM.png',\n badges: [{ title: 'Leader' }],\n child: false,\n role: 'unknown',\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.8",
3
+ "version": "3.2.0-rc.9",
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": "f01a38da67def56c62c319ecae44e2faeb6ab529"
57
+ "gitHead": "5c7aa0ac63ac807b4e9a16a4924828eb73aee990"
58
58
  }
@@ -1,5 +1,5 @@
1
1
  import React from 'react'
2
- import { StyleSheet, View } from 'react-native'
2
+ import { StyleSheet, View, type ViewStyle } from 'react-native'
3
3
  import { platformFontWeightMedium } from '../../utils/styles'
4
4
  import { MemberResource } from '../../types'
5
5
  import { Avatar } from './avatar'
@@ -13,13 +13,14 @@ import { space } from '../../utils'
13
13
 
14
14
  interface PersonProps {
15
15
  person: MemberResource
16
+ style?: ViewStyle
16
17
  }
17
18
 
18
- export function Person({ person }: PersonProps) {
19
+ export function Person({ person, style }: PersonProps) {
19
20
  const styles = useStyles()
20
21
 
21
22
  return (
22
- <View style={styles.wrapper}>
23
+ <View style={[styles.wrapper, style]}>
23
24
  <Avatar sourceUri={person.avatar} />
24
25
  <View style={styles.content}>
25
26
  <Text style={styles.name}>{person.name}</Text>
@@ -0,0 +1,67 @@
1
+ import React from 'react'
2
+ import { StyleSheet, View } from 'react-native'
3
+ import { FlashList, type FlashListProps } from '@shopify/flash-list'
4
+ import { MemberResource } from '../../../types'
5
+ import { Person, Text } from '../../../components/display'
6
+ import { useTheme } from '../../../hooks'
7
+
8
+ interface FormListProps {
9
+ memberData: MemberResource[]
10
+ FormContent?: FlashListProps<MemberResource>['ListHeaderComponent']
11
+ listEmptyText?: string
12
+ }
13
+
14
+ export const FormList = ({ memberData, FormContent, listEmptyText }: FormListProps) => {
15
+ const styles = useStyles()
16
+
17
+ return (
18
+ <FlashList
19
+ data={memberData}
20
+ ListHeaderComponent={FormContent}
21
+ renderItem={({ item }) => <Person person={item} style={styles.person} />}
22
+ keyExtractor={item => item.id.toString()}
23
+ estimatedItemSize={45}
24
+ ListEmptyComponent={<ListEmptyText text={listEmptyText || 'No members found'} />}
25
+ />
26
+ )
27
+ }
28
+
29
+ const ListEmptyText = ({ text }: { text: string }) => {
30
+ const styles = useStyles()
31
+
32
+ return (
33
+ <View style={styles.emptyTextContainer}>
34
+ <Text style={styles.emptyText}>{text}</Text>
35
+ </View>
36
+ )
37
+ }
38
+
39
+ export const Divider = () => {
40
+ const styles = useStyles()
41
+
42
+ return <View style={styles.divider} />
43
+ }
44
+
45
+ const useStyles = () => {
46
+ const { colors } = useTheme()
47
+
48
+ return StyleSheet.create({
49
+ person: {
50
+ paddingHorizontal: 16,
51
+ paddingBottom: 12,
52
+ },
53
+ emptyTextContainer: {
54
+ alignItems: 'center',
55
+ justifyContent: 'center',
56
+ padding: 32,
57
+ },
58
+ emptyText: {
59
+ textAlign: 'center',
60
+ color: colors.textColorDefaultSecondary,
61
+ },
62
+ divider: {
63
+ borderBottomWidth: 1,
64
+ borderBottomColor: colors.fillColorNeutral050Base,
65
+ },
66
+ })
67
+ }
@@ -1,10 +1,9 @@
1
1
  import { StackActions, useNavigation } from '@react-navigation/native'
2
2
  import React, { useCallback, useState } from 'react'
3
- import { StyleSheet, TextInput, View } from 'react-native'
4
- import { useSafeAreaInsets } from 'react-native-safe-area-context'
5
- import { Text } from '../../../components'
3
+ import { Platform, StyleSheet, TextInput, View } from 'react-native'
4
+ import { Heading, Text } from '../../../components'
6
5
  import { ActionButton } from '../../../components/display/action_button'
7
- import { useSuspenseGet, useTheme } from '../../../hooks'
6
+ import { useSuspenseGet } from '../../../hooks'
8
7
  import { useApiClient } from '../../../hooks/use_api_client'
9
8
  import { useMutation } from '@tanstack/react-query'
10
9
  import {
@@ -13,6 +12,11 @@ import {
13
12
  GroupsGroupResource,
14
13
  ResourceObject,
15
14
  } from '../../../types'
15
+ import { FAKE_MEMBER_DATA } from '../utils/fake_member_data'
16
+ import { Divider, FormList } from './form_list'
17
+ import { pluralize } from '../../../utils'
18
+ import { KeyboardView } from '../../../components/display/keyboard_view'
19
+ import { MemberErrorCard } from './member_error_card'
16
20
 
17
21
  type GroupsFormProps = {
18
22
  groupId?: string
@@ -23,7 +27,6 @@ interface ChatConversationPayload extends ResourceObject {
23
27
  }
24
28
 
25
29
  export const GroupsForm = ({ groupId }: GroupsFormProps) => {
26
- const styles = useStyles()
27
30
  const navigation = useNavigation()
28
31
  const [title, setTitle] = useState<string>()
29
32
  const apiClient = useApiClient()
@@ -36,6 +39,9 @@ export const GroupsForm = ({ groupId }: GroupsFormProps) => {
36
39
  },
37
40
  app: 'groups',
38
41
  })
42
+
43
+ const isMemberError = false // TODO: Replace with error from a future useGroupsMember hook
44
+
39
45
  const { mutate: handleSave } = useMutation({
40
46
  throwOnError: true,
41
47
  onSuccess: result => {
@@ -85,71 +91,97 @@ export const GroupsForm = ({ groupId }: GroupsFormProps) => {
85
91
  )
86
92
 
87
93
  return (
88
- <View style={styles.container}>
89
- <View style={styles.section}>
90
- <View style={styles.to}>
91
- <Text>To:</Text>
92
- <View>
93
- <Text>{group.name}</Text>
94
- <Text>{group.membershipsCount} members</Text>
95
- </View>
96
- </View>
97
- <View style={styles.titleContainer}>
98
- <Text style={styles.titleLabel}>Title</Text>
99
- <TextInput
100
- placeholder="Topic of conversation (required)"
101
- value={title}
102
- onChangeText={setTitle}
103
- style={styles.titleInput}
94
+ <KeyboardView>
95
+ <FormList
96
+ memberData={FAKE_MEMBER_DATA} // TODO: Replace with actual group members
97
+ FormContent={
98
+ <FormContent
99
+ group={group}
100
+ title={title}
101
+ setTitle={setTitle}
102
+ isMemberError={isMemberError}
104
103
  />
105
- </View>
106
- </View>
104
+ }
105
+ />
107
106
  <ActionButton title="Start Conversation" onPress={() => handleSave()} />
107
+ </KeyboardView>
108
+ )
109
+ }
110
+
111
+ interface FormContentProps {
112
+ group: GroupsGroupResource
113
+ title?: string
114
+ setTitle: (title: string) => void
115
+ isMemberError: boolean
116
+ }
117
+
118
+ function FormContent({ group, title, setTitle, isMemberError }: FormContentProps) {
119
+ const styles = useStyles()
120
+ const { name, membershipsCount } = group
121
+ const memberHeader = pluralize(membershipsCount, 'member')
122
+
123
+ return (
124
+ <View style={styles.formContent}>
125
+ <View style={styles.toSection}>
126
+ <Heading variant="h3">To:</Heading>
127
+ <Text style={styles.groupName}>{name}</Text>
128
+ </View>
129
+ <Divider />
130
+ <View style={styles.titleSection}>
131
+ <Heading variant="h3">Title</Heading>
132
+ <TextInput
133
+ placeholder="Topic of conversation (required)"
134
+ value={title}
135
+ onChangeText={setTitle}
136
+ style={styles.titleInput}
137
+ autoFocus={true}
138
+ />
139
+ </View>
140
+ <Divider />
141
+ <View style={styles.memberSection}>
142
+ <Heading variant="h3">{memberHeader} selected</Heading>
143
+ {isMemberError && (
144
+ <MemberErrorCard description="There was an issue loading group members, please refresh and try again." />
145
+ )}
146
+ </View>
108
147
  </View>
109
148
  )
110
149
  }
111
150
 
112
151
  const useStyles = () => {
113
- const { bottom } = useSafeAreaInsets()
114
- const theme = useTheme()
152
+ const sectionPadding = 16
153
+ const inputPadding = 8
115
154
 
116
155
  return StyleSheet.create({
117
- container: {
118
- flex: 1,
119
- gap: 8,
120
- },
121
- section: {
122
- padding: 16,
156
+ formContent: {
157
+ paddingVertical: sectionPadding,
123
158
  flex: 1,
124
159
  },
125
- sectionHeader: {
160
+ toSection: {
161
+ padding: sectionPadding,
126
162
  flexDirection: 'row',
127
- justifyContent: 'space-between',
163
+ gap: 8,
128
164
  },
129
- selectTeamsButton: {},
130
- routeDebug: {
131
- alignContent: 'center',
132
- padding: 16,
133
- paddingBottom: bottom,
134
- borderTopWidth: 1,
135
- borderTopColor: theme.colors.fillColorNeutral050Base,
165
+ groupName: {
166
+ fontSize: 18,
136
167
  },
137
- titleContainer: {
138
- paddingVertical: 12,
139
- borderBottomWidth: 1,
140
- borderBottomColor: theme.colors.fillColorNeutral050Base,
141
- gap: 8,
168
+ titleSection: {
169
+ padding: sectionPadding,
170
+ paddingBottom: Platform.select({
171
+ ios: sectionPadding,
172
+ android: sectionPadding - inputPadding,
173
+ }),
174
+ gap: Platform.select({
175
+ ios: 8,
176
+ android: 0,
177
+ }),
142
178
  },
143
179
  titleInput: {
144
180
  fontSize: 18,
145
181
  },
146
- titleLabel: {},
147
- to: {
148
- flexDirection: 'row',
149
- gap: 8,
150
- paddingVertical: 12,
151
- borderBottomWidth: 1,
152
- borderBottomColor: theme.colors.fillColorNeutral050Base,
182
+ memberSection: {
183
+ padding: sectionPadding,
184
+ paddingBottom: 0,
153
185
  },
154
186
  })
155
187
  }
@@ -0,0 +1,20 @@
1
+ import React from 'react'
2
+ import { View, StyleSheet } from 'react-native'
3
+ import { Banner } from '../../../components'
4
+
5
+ export const MemberErrorCard = ({ description }: { description: string }) => {
6
+ const styles = useStyles()
7
+ return (
8
+ <View style={styles.memberErrorBanner}>
9
+ <Banner appearance="error" description={description} />
10
+ </View>
11
+ )
12
+ }
13
+
14
+ const useStyles = () => {
15
+ return StyleSheet.create({
16
+ memberErrorBanner: {
17
+ paddingTop: 16,
18
+ },
19
+ })
20
+ }
@@ -0,0 +1,130 @@
1
+ import { MemberResource } from '../../../types'
2
+
3
+ export const FAKE_MEMBER_DATA: MemberResource[] = [
4
+ {
5
+ type: 'Member',
6
+ id: 1,
7
+ name: 'John Doe',
8
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/JD.png',
9
+ badges: [{ title: 'Leader' }, { title: 'Conversation owner' }],
10
+ child: false,
11
+ role: 'unknown',
12
+ },
13
+ {
14
+ type: 'Member',
15
+ id: 2,
16
+ name: 'Jane Smith',
17
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/JS.png',
18
+ badges: [{ title: 'Leader' }],
19
+ child: false,
20
+ role: 'unknown',
21
+ },
22
+ {
23
+ type: 'Member',
24
+ id: 3,
25
+ name: 'Bob Wilson',
26
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/BW.png',
27
+ badges: [],
28
+ child: false,
29
+ role: 'unknown',
30
+ },
31
+ {
32
+ type: 'Member',
33
+ id: 4,
34
+ name: 'Sarah Johnson',
35
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/SJ.png',
36
+ badges: [{ title: 'Leader' }],
37
+ child: false,
38
+ role: 'unknown',
39
+ },
40
+ {
41
+ type: 'Member',
42
+ id: 5,
43
+ name: 'Mike Brown',
44
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/MB.png',
45
+ badges: [],
46
+ child: false,
47
+ role: 'unknown',
48
+ },
49
+ {
50
+ type: 'Member',
51
+ id: 6,
52
+ name: 'Emily Davis',
53
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/ED.png',
54
+ badges: [{ title: 'Leader' }],
55
+ child: false,
56
+ role: 'unknown',
57
+ },
58
+ {
59
+ type: 'Member',
60
+ id: 7,
61
+ name: 'James Miller',
62
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/JM.png',
63
+ badges: [],
64
+ child: false,
65
+ role: 'unknown',
66
+ },
67
+ {
68
+ type: 'Member',
69
+ id: 8,
70
+ name: 'Lisa Anderson',
71
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/LA.png',
72
+ badges: [],
73
+ child: false,
74
+ role: 'unknown',
75
+ },
76
+ {
77
+ type: 'Member',
78
+ id: 9,
79
+ name: 'David Taylor',
80
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/DT.png',
81
+ badges: [{ title: 'Leader' }],
82
+ child: false,
83
+ role: 'unknown',
84
+ },
85
+ {
86
+ type: 'Member',
87
+ id: 10,
88
+ name: 'Rachel White',
89
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/RW.png',
90
+ badges: [],
91
+ child: false,
92
+ role: 'unknown',
93
+ },
94
+ {
95
+ type: 'Member',
96
+ id: 11,
97
+ name: 'Kevin Martin',
98
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/KM.png',
99
+ badges: [{ title: 'Leader' }],
100
+ child: false,
101
+ role: 'unknown',
102
+ },
103
+ {
104
+ type: 'Member',
105
+ id: 12,
106
+ name: 'Michelle Lee',
107
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/ML.png',
108
+ badges: [],
109
+ child: false,
110
+ role: 'unknown',
111
+ },
112
+ {
113
+ type: 'Member',
114
+ id: 13,
115
+ name: 'Daniel Clark',
116
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/DC.png',
117
+ badges: [],
118
+ child: false,
119
+ role: 'unknown',
120
+ },
121
+ {
122
+ type: 'Member',
123
+ id: 14,
124
+ name: 'Amanda Moore',
125
+ avatar: 'https://avatars.planningcenteronline.com/uploads/initials/AM.png',
126
+ badges: [{ title: 'Leader' }],
127
+ child: false,
128
+ role: 'unknown',
129
+ },
130
+ ]