Skip to content

Commit 97a75dd

Browse files
feat(community): PEDAGO-2883 adding info modal
# Conflicts: # src/framework/modules/communities/screens/home/screen.tsx # Conflicts: # src/framework/modules/communities/screens/home/screen.tsx
1 parent 32dd725 commit 97a75dd

File tree

10 files changed

+218
-19
lines changed

10 files changed

+218
-19
lines changed

src/framework/modules/communities/components/community-card-large/component.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,11 @@ export const CommunityCardLarge = ({
5555
</View>
5656
</View>
5757
<View style={styles.infoSeparator} />
58-
<View style={styles.infoRoleContainer}>
58+
<View style={styles.infoInviterContainer}>
5959
<SingleAvatar userId={senderId} size="sm" />
60-
<SmallText style={styles.infoText}>{I18n.get('community-invitation-from-label', { name: senderName })}</SmallText>
60+
<SmallText style={styles.infoInviterText}>
61+
{I18n.get('community-invitation-from-label', { name: senderName })}
62+
</SmallText>
6163
</View>
6264
</View>
6365
</View>

src/framework/modules/communities/components/community-card-large/styles.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@ export const styles = StyleSheet.create({
2424
padding: UI_SIZES.spacing.medium,
2525
paddingTop: UI_SIZES.spacing.small,
2626
},
27+
infoInviterContainer: {
28+
alignItems: 'center',
29+
flexDirection: 'row',
30+
gap: UI_SIZES.spacing.minor,
31+
},
32+
infoInviterText: {
33+
color: theme.ui.text.inverse,
34+
flex: 1,
35+
},
2736
infoRoleContainer: {
2837
alignItems: 'center',
2938
flexDirection: 'row',
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import * as React from 'react';
2+
import { Platform, SafeAreaView, TouchableOpacity, View } from 'react-native';
3+
4+
import { styles } from './styles';
5+
import { CommunityInfoBottomSheetProps } from './types';
6+
7+
import { I18n } from '~/app/i18n';
8+
import theme from '~/app/theme';
9+
import { UI_SIZES } from '~/framework/components/constants';
10+
import BottomSheetModal, { BottomSheetModalMethods } from '~/framework/components/modals/bottom-sheet';
11+
import { Svg } from '~/framework/components/picture';
12+
import ScrollView from '~/framework/components/scrollView';
13+
import { BodyText, HeadingXSText } from '~/framework/components/text';
14+
import CommunityCardLarge from '~/framework/modules/communities/components/community-card-large';
15+
16+
const CommunityInfoBottomSheet = React.forwardRef<BottomSheetModalMethods, CommunityInfoBottomSheetProps>(({ data }, ref) => {
17+
const closeBottomSheet = React.useCallback(() => {
18+
(ref as React.RefObject<BottomSheetModalMethods>)?.current?.dismiss();
19+
}, [ref]);
20+
21+
const containerStyle = React.useMemo(
22+
() => [
23+
styles.container,
24+
{
25+
paddingBottom: UI_SIZES.spacing.medium,
26+
paddingTop:
27+
UI_SIZES.elements.navbarHeight + Platform.select({ default: UI_SIZES.spacing.small, ios: UI_SIZES.spacing.big }),
28+
},
29+
],
30+
[],
31+
);
32+
33+
return (
34+
<BottomSheetModal ref={ref} style={styles.bottomSheetPaddingBottom}>
35+
<ScrollView>
36+
<View style={styles.listHeader}>
37+
<TouchableOpacity onPress={closeBottomSheet} style={styles.closeButton}>
38+
<Svg
39+
name="ui-close"
40+
height={UI_SIZES.elements.icon.small}
41+
width={UI_SIZES.elements.icon.small}
42+
fill={theme.palette.grey.black}
43+
/>
44+
</TouchableOpacity>
45+
</View>
46+
<SafeAreaView style={containerStyle}>
47+
<CommunityCardLarge
48+
title={data?.title}
49+
image={data?.image}
50+
membersCount={data?.totalMembers}
51+
senderId={data?.senderId}
52+
senderName={data?.senderName}
53+
role={data?.role}
54+
/>
55+
<View style={styles.welcomeNote}>
56+
<View style={styles.welcomeNoteTitleContainer}>
57+
<Svg name="ui-notes" fill={styles.welcomeNoteTitle.color} />
58+
<HeadingXSText style={styles.welcomeNoteTitle}>{I18n.get('community-welcome-note')}</HeadingXSText>
59+
</View>
60+
<BodyText>{data?.welcomeNote}</BodyText>
61+
</View>
62+
</SafeAreaView>
63+
</ScrollView>
64+
</BottomSheetModal>
65+
);
66+
});
67+
68+
export default CommunityInfoBottomSheet;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import CommunityInfoBottomSheet from './component';
2+
3+
export default CommunityInfoBottomSheet;
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { StyleSheet } from 'react-native';
2+
3+
import theme from '~/app/theme';
4+
import { UI_SIZES } from '~/framework/components/constants';
5+
6+
export const styles = StyleSheet.create({
7+
bottomSheetPaddingBottom: {
8+
paddingBottom: UI_SIZES.spacing.big,
9+
},
10+
closeButton: {
11+
padding: UI_SIZES.spacing.minor,
12+
},
13+
container: {
14+
gap: UI_SIZES.spacing.medium,
15+
paddingHorizontal: UI_SIZES.spacing.big,
16+
},
17+
listHeader: {
18+
alignItems: 'center',
19+
flexDirection: 'row',
20+
paddingHorizontal: UI_SIZES.spacing.minor,
21+
},
22+
page: {
23+
flexShrink: 1,
24+
},
25+
welcomeNote: {
26+
backgroundColor: theme.palette.primary.pale,
27+
borderRadius: UI_SIZES.radius.mediumPlus,
28+
gap: UI_SIZES.spacing.minor,
29+
paddingHorizontal: UI_SIZES.spacing.medium,
30+
paddingVertical: UI_SIZES.spacing.small,
31+
},
32+
welcomeNoteTitle: {
33+
color: theme.palette.primary.regular,
34+
},
35+
welcomeNoteTitleContainer: {
36+
flexDirection: 'row',
37+
gap: UI_SIZES.spacing.minor,
38+
},
39+
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { MembershipRole } from '@edifice.io/community-client-rest-rn';
2+
3+
export interface CommunityInfoBottomSheetProps {
4+
data: {
5+
title?: string;
6+
image?: string;
7+
totalMembers?: number;
8+
senderId: string;
9+
senderName: string;
10+
role: MembershipRole;
11+
welcomeNote?: string;
12+
};
13+
}

src/framework/modules/communities/hooks/use-community-navbar/index.tsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react';
2-
import { Image, Platform, ScrollViewProps, StatusBar, View } from 'react-native';
2+
import { Image, Platform, ScrollViewProps, StatusBar, TouchableOpacity, View } from 'react-native';
33

44
import { HeaderBackButton } from '@react-navigation/elements';
55
import { ParamListBase } from '@react-navigation/native';
@@ -9,14 +9,16 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context';
99
import CommunityNavbar from './community-navbar';
1010
import { BANNER_BASE_HEIGHT } from './community-navbar/styles';
1111
import CommunityScrollViewStickyHeader, { BANNER_ACCELERATION } from './sticky-component';
12-
import styles from './styles';
12+
import styles, { NAVBAR_RIGHT_BUTTON_STYLE } from './styles';
1313
import { CommunityThumbnailNavbarScrollableProps } from './types';
1414

1515
import theme from '~/app/theme';
1616
import { UI_SIZES } from '~/framework/components/constants';
17+
import { Svg } from '~/framework/components/picture';
1718
import { HeadingXSText } from '~/framework/components/text';
1819
import { navBarOptions } from '~/framework/navigation/navBar';
1920

21+
export { NAVBAR_RIGHT_BUTTON_STYLE } from './styles';
2022
export type { CommunityThumbnailNavbarScrollableProps } from './types';
2123
export default function useCommunityScrollableThumbnail({
2224
contentContainerStyle: _contentContainerStyle,
@@ -125,7 +127,7 @@ export const communityNavBar = <NavigationParams extends ParamListBase, RouteNam
125127
<HeaderBackButton
126128
{...props}
127129
labelVisible={false}
128-
style={styles.navBarButton}
130+
style={styles.navBarLeftButton}
129131
onPress={navigation.goBack}
130132
backImage={Platform.select({
131133
default: undefined,
@@ -140,6 +142,16 @@ export const communityNavBar = <NavigationParams extends ParamListBase, RouteNam
140142
tintColor={theme.ui.text.regular.toString()}
141143
/>
142144
),
145+
headerRight: () => (
146+
<TouchableOpacity style={NAVBAR_RIGHT_BUTTON_STYLE}>
147+
<Svg
148+
name="ui-infoCircle"
149+
width={UI_SIZES.elements.icon.small}
150+
height={UI_SIZES.elements.icon.small}
151+
fill={theme.palette.grey.black}
152+
/>
153+
</TouchableOpacity>
154+
),
143155
headerShadowVisible: false,
144156
headerStyle: {
145157
backgroundColor: 'transparent',

src/framework/modules/communities/hooks/use-community-navbar/styles.ts

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,24 @@
1-
import { I18nManager, StyleSheet } from 'react-native';
1+
import { I18nManager, StyleSheet, ViewStyle } from 'react-native';
22

33
import theme from '~/app/theme';
44
import { getScaleWidth, UI_SIZES } from '~/framework/components/constants';
55

6+
const NAVBAR_BUTTON_STYLE: ViewStyle = {
7+
alignItems: 'center',
8+
backgroundColor: theme.ui.background.card,
9+
borderRadius: UI_SIZES.radius.medium,
10+
height: UI_SIZES.elements.icon.xlarge,
11+
justifyContent: 'center',
12+
position: 'absolute',
13+
width: UI_SIZES.elements.icon.xlarge,
14+
};
15+
const NAVBAR_ICON_OFFSET = -4; // compensate native placement of back icon. This value is not scaled by the UI.
16+
17+
export const NAVBAR_RIGHT_BUTTON_STYLE: ViewStyle = {
18+
...NAVBAR_BUTTON_STYLE,
19+
right: NAVBAR_ICON_OFFSET,
20+
};
21+
622
export default StyleSheet.create({
723
backButtonImage: {
824
// custom iOS back button to ensure that perfect match with the native one
@@ -13,15 +29,9 @@ export default StyleSheet.create({
1329
transform: [{ scaleX: I18nManager.getConstants().isRTL ? -1 : 1 }],
1430
width: 13, // value provided by react navigation
1531
},
16-
navBarButton: {
17-
alignItems: 'center',
18-
backgroundColor: theme.ui.background.card,
19-
borderRadius: UI_SIZES.radius.medium,
20-
height: UI_SIZES.elements.icon.xlarge,
21-
justifyContent: 'center',
22-
left: -4, // compensate native placement of back icon. This value is not scaled by the UI.
23-
position: 'absolute',
24-
width: UI_SIZES.elements.icon.xlarge,
32+
navBarLeftButton: {
33+
...NAVBAR_BUTTON_STYLE,
34+
left: NAVBAR_ICON_OFFSET,
2535
},
2636
titleHeaderInner: {
2737
alignItems: 'center',

src/framework/modules/communities/screens/home/screen.tsx

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,31 @@ import { sessionScreen } from '~/framework/components/screen';
2222
import ScrollView from '~/framework/components/scrollView';
2323
import { HeadingXSText, SmallBoldText, SmallText } from '~/framework/components/text';
2424
import { ContentLoader, ContentLoaderProps } from '~/framework/hooks/loader';
25+
import CommunityInfoBottomSheet from '~/framework/modules/communities/components/community-info-bottom-sheet';
2526
import CommunityWelcomeBottomSheetModal from '~/framework/modules/communities/components/community-welcome-bottomsheet';
2627
import {
2728
communityNavBar,
29+
NAVBAR_RIGHT_BUTTON_STYLE,
2830
default as useCommunityScrollableThumbnail,
2931
} from '~/framework/modules/communities/hooks/use-community-navbar';
3032
import moduleConfig from '~/framework/modules/communities/module-config';
3133
import { CommunitiesNavigationParams, communitiesRouteNames } from '~/framework/modules/communities/navigation';
3234
import { communitiesActions, communitiesSelectors } from '~/framework/modules/communities/store';
3335
import { accountApi } from '~/framework/util/transport';
3436

37+
const NavbarRightButton = ({ onPress }: { onPress: () => void }) => {
38+
return (
39+
<TouchableOpacity style={NAVBAR_RIGHT_BUTTON_STYLE} onPress={onPress}>
40+
<Svg
41+
name="ui-infoCircle"
42+
width={UI_SIZES.elements.icon.small}
43+
height={UI_SIZES.elements.icon.small}
44+
fill={theme.palette.grey.black}
45+
/>
46+
</TouchableOpacity>
47+
);
48+
};
49+
3550
export const computeNavBar = (
3651
props: NativeStackScreenProps<CommunitiesNavigationParams, typeof communitiesRouteNames.home>,
3752
): NativeStackNavigationOptions => communityNavBar(props);
@@ -46,6 +61,7 @@ export const CommunitiesHomeScreenLoaded = function ({
4661
},
4762
title,
4863
totalMembers,
64+
welcomeNote,
4965
}: Readonly<CommunitiesHomeScreen.AllPropsLoaded>) {
5066
const membersTile = (
5167
<TouchableOpacity
@@ -139,23 +155,47 @@ export const CommunitiesHomeScreenLoaded = function ({
139155
title,
140156
});
141157

142-
const bottomSheetModalRef = React.useRef<BottomSheetModalMethods>(null);
158+
const welcomeModalRef = React.useRef<BottomSheetModalMethods>(null);
143159
React.useEffect(() => {
144-
(showWelcome && invitationId !== undefined ? bottomSheetModalRef.current?.present : bottomSheetModalRef.current?.dismiss)?.();
160+
(showWelcome && invitationId !== undefined ? welcomeModalRef.current?.present : welcomeModalRef.current?.dismiss)?.();
145161
}, [showWelcome, invitationId]);
146162

147163
const invitation = useSelector(communitiesSelectors.getAllCommunities).find(
148164
item => item !== LOADING_ITEM_DATA && item.id === invitationId,
149165
) as InvitationResponseDto | undefined;
150166

167+
const { role, sentBy } = invitation || {};
168+
const { displayName: senderName, entId: senderId } = sentBy || {};
169+
const canShowInfoModal = role && senderId && senderName;
170+
171+
const infoModalRef = React.useRef<BottomSheetModalMethods>(null);
172+
173+
const openInfoModal = React.useCallback(() => {
174+
infoModalRef.current?.present();
175+
}, []);
176+
177+
React.useEffect(() => {
178+
navigation.setOptions({
179+
headerRight: () => <NavbarRightButton onPress={openInfoModal} />,
180+
});
181+
}, [navigation, openInfoModal]);
182+
151183
return (
152184
<>
153185
{statusBar}
154186
<ScrollView alwaysBounceVertical={false} refreshControl={refreshControl} {...scrollViewProps}>
155187
{scrollElements}
156188
{pageContent}
157189
</ScrollView>
158-
{invitation?.role && <CommunityWelcomeBottomSheetModal role={invitation?.role} title={title} ref={bottomSheetModalRef} />}
190+
{invitation?.role && <CommunityWelcomeBottomSheetModal role={invitation?.role} title={title} ref={welcomeModalRef} />}
191+
{canShowInfoModal ? (
192+
<CommunityInfoBottomSheet
193+
ref={infoModalRef}
194+
data={{ image, role, senderId, senderName, title, totalMembers, welcomeNote }}
195+
/>
196+
) : (
197+
<EmptyContentScreen />
198+
)}
159199
</>
160200
);
161201
};

src/framework/modules/communities/screens/home/types.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ export namespace CommunitiesHomeScreen {
1313
}
1414
export type NavigationProps = NativeStackScreenProps<CommunitiesNavigationParams, 'home'>;
1515
export type AllProps = CommunitiesHomeScreen.NavigationProps;
16-
export type RequiredData = Pick<CommunityResponseDto, 'title' | 'image'> & { totalMembers: number; membersId: string[] };
16+
export type RequiredData = Pick<CommunityResponseDto, 'title' | 'image' | 'welcomeNote'> & {
17+
totalMembers: number;
18+
membersId: string[];
19+
};
1720
export type AllPropsLoaded = CommunitiesHomeScreen.AllProps & RequiredData & Pick<ScrollViewProps, 'refreshControl'>;
1821
}

0 commit comments

Comments
 (0)