Viktoriia 4 hónapja
szülő
commit
812dce747c

+ 5 - 1
Route.tsx

@@ -99,6 +99,7 @@ import { NavigationProvider } from 'src/contexts/NavigationContext';
 import FullMapScreen from 'src/screens/InAppScreens/MessagesScreen/FullMapScreen';
 import EventScreen from 'src/screens/InAppScreens/TravelsScreen/EventScreen';
 import GroupChatScreen from 'src/screens/InAppScreens/MessagesScreen/GroupChatScreen';
+import GroupSettingScreen from 'src/screens/InAppScreens/MessagesScreen/GroupSettingsScreen';
 
 enableScreens();
 
@@ -420,7 +421,10 @@ const Route = () => {
             <ScreenStack.Screen name={NAVIGATION_PAGES.CHATS_LIST} component={MessagesScreen} />
             <ScreenStack.Screen name={NAVIGATION_PAGES.CHAT} component={ChatScreen} />
             <ScreenStack.Screen name={NAVIGATION_PAGES.GROUP_CHAT} component={GroupChatScreen} />
-
+            <ScreenStack.Screen
+              name={NAVIGATION_PAGES.GROUP_SETTINGS}
+              component={GroupSettingScreen}
+            />
             <ScreenStack.Screen name={NAVIGATION_PAGES.FULL_MAP_VIEW} component={FullMapScreen} />
             <ScreenStack.Screen
               name={NAVIGATION_PAGES.PUBLIC_PROFILE_VIEW}

+ 28 - 1
src/modules/api/chat/chat-api.ts

@@ -35,6 +35,29 @@ export interface PostGetChatsListReturn extends ResponseType {
   }[];
 }
 
+export interface PostGetGroupSettingsReturn extends ResponseType {
+  settings: {
+    members_can_add_new_members: 0 | 1;
+    members_can_edit_settings: 0 | 1;
+    members_can_send_messages: 0 | 1;
+    members_can_see_members: 0 | 1;
+    name: string;
+    description: string | null;
+    avatar: string | null;
+    avatar_full: string | null;
+  };
+}
+
+export interface PostGetGroupMembersReturn extends ResponseType {
+  settings: {
+    uid: number;
+    name: string;
+    avatar: string | null;
+    admin: 0 | 1;
+    added: string;
+  }[];
+}
+
 interface Attachement {
   id: number;
   filename: string;
@@ -359,5 +382,9 @@ export const chatApi = {
   setGroupAdmin: (token: string, uid: number, group_token: string, value: 0 | 1) =>
     request.postForm<ResponseType>(API.SET_GROUP_ADMIN, { token, uid, group_token, value }),
   removeFromGroup: (token: string, uid: number, group_token: string) =>
-    request.postForm<ResponseType>(API.REMOVE_FROM_GROUP, { token, uid, group_token })
+    request.postForm<ResponseType>(API.REMOVE_FROM_GROUP, { token, uid, group_token }),
+  getGroupSettings: (token: string, group_token: string) =>
+    request.postForm<PostGetGroupSettingsReturn>(API.GET_GROUP_SETTINGS, { token, group_token }),
+  getGroupMembers: (token: string, group_token: string) =>
+    request.postForm<PostGetGroupMembersReturn>(API.GET_GROUP_MEMBERS, { token, group_token })
 };

+ 5 - 1
src/modules/api/chat/chat-query-keys.tsx

@@ -41,5 +41,9 @@ export const chatQueryKeys = {
   addToGroup: () => ['addToGroup'] as const,
   addToGroupAsAdmin: () => ['addToGroupAsAdmin'] as const,
   setGroupAdmin: () => ['setGroupAdmin'] as const,
-  removeFromGroup: () => ['removeFromGroup'] as const
+  removeFromGroup: () => ['removeFromGroup'] as const,
+  getGroupSettings: (token: string, group_token: string) =>
+    ['getGroupSettings', token, group_token] as const,
+  getGroupMembers: (token: string, group_token: string) =>
+    ['getGroupMembers', token, group_token] as const
 };

+ 2 - 0
src/modules/api/chat/queries/index.ts

@@ -31,3 +31,5 @@ export * from './use-post-add-to-group';
 export * from './use-post-add-to-group-as-admin';
 export * from './use-post-set-group-admin';
 export * from './use-post-remove-from-group';
+export * from './use-post-get-group-settings';
+export * from './use-post-get-group-members';

+ 21 - 0
src/modules/api/chat/queries/use-post-get-group-members.tsx

@@ -0,0 +1,21 @@
+import { useQuery } from '@tanstack/react-query';
+
+import { chatQueryKeys } from '../chat-query-keys';
+import { chatApi, type PostGetGroupMembersReturn } from '../chat-api';
+
+import type { BaseAxiosError } from '../../../../types';
+
+export const usePostGetGroupMembersQuery = (
+  token: string,
+  group_token: string,
+  enabled: boolean
+) => {
+  return useQuery<PostGetGroupMembersReturn, BaseAxiosError>({
+    queryKey: chatQueryKeys.getGroupMembers(token, group_token),
+    queryFn: async () => {
+      const response = await chatApi.getGroupMembers(token, group_token);
+      return response.data;
+    },
+    enabled
+  });
+};

+ 21 - 0
src/modules/api/chat/queries/use-post-get-group-settings.tsx

@@ -0,0 +1,21 @@
+import { useQuery } from '@tanstack/react-query';
+
+import { chatQueryKeys } from '../chat-query-keys';
+import { chatApi, type PostGetGroupSettingsReturn } from '../chat-api';
+
+import type { BaseAxiosError } from '../../../../types';
+
+export const usePostGetGroupSettingsQuery = (
+  token: string,
+  group_token: string,
+  enabled: boolean
+) => {
+  return useQuery<PostGetGroupSettingsReturn, BaseAxiosError>({
+    queryKey: chatQueryKeys.getGroupSettings(token, group_token),
+    queryFn: async () => {
+      const response = await chatApi.getGroupSettings(token, group_token);
+      return response.data;
+    },
+    enabled
+  });
+};

+ 4 - 6
src/screens/InAppScreens/MessagesScreen/GroupChatScreen/index.tsx

@@ -1768,12 +1768,10 @@ const GroupChatScreen = ({ route }: { route: any }) => {
           textColor={userType !== 'normal' ? Colors.RED : Colors.DARK_BLUE}
           rightElement={
             <TouchableOpacity
-              // todo: change to settings
-              onPress={
-                () => {}
-                // navigation.navigate(
-                //   ...([NAVIGATION_PAGES.PUBLIC_PROFILE_VIEW, { userId: 57363 }] as never)
-                // )
+              onPress={() =>
+                navigation.navigate(
+                  ...([NAVIGATION_PAGES.GROUP_SETTINGS, { groupToken: group_token }] as never)
+                )
               }
               disabled={userType !== 'normal'}
             >

+ 295 - 0
src/screens/InAppScreens/MessagesScreen/GroupSettingsScreen/index.tsx

@@ -0,0 +1,295 @@
+import React, { FC, useCallback, useEffect, useState } from 'react';
+import { ScrollView, Text, TouchableOpacity, View, Image, StyleSheet } from 'react-native';
+import { NavigationProp, useFocusEffect } from '@react-navigation/native';
+import ImageView from 'react-native-image-viewing';
+import { storage, StoreType } from 'src/storage';
+import { PageWrapper, Header, Loading, Input, AvatarWithInitials } from 'src/components';
+import { usePostGetGroupMembersQuery, usePostGetGroupSettingsQuery } from '@api/chat';
+import { Colors } from 'src/theme';
+import { API_HOST } from 'src/constants';
+import GroupIcon from 'assets/icons/messages/group-chat.svg';
+import { getFontSize } from 'src/utils';
+import MegaphoneIcon from 'assets/icons/messages/megaphone.svg';
+import ExitIcon from 'assets/icons/messages/exit.svg';
+import TrashIcon from 'assets/icons/travels-screens/trash-solid.svg';
+import BanIcon from 'assets/icons/messages/ban.svg';
+import BellSlashIcon from 'assets/icons/messages/bell-slash.svg';
+import { useSafeAreaInsets } from 'react-native-safe-area-context';
+
+type Props = {
+  navigation: NavigationProp<any>;
+  route: any;
+};
+
+const GroupSettingScreen: FC<Props> = ({ navigation, route }) => {
+  const token = storage.get('token', StoreType.STRING) as string;
+  const groupToken = route.params.groupToken;
+  const insets = useSafeAreaInsets();
+  const [canSeeMembers, setCanSeeMembers] = useState(false);
+  const { data } = usePostGetGroupSettingsQuery(token, groupToken, true);
+  const { data: members } = usePostGetGroupMembersQuery(token, groupToken, canSeeMembers);
+
+  const [fullSizeImageVisible, setFullSizeImageVisible] = useState(false);
+
+  useEffect(() => {
+    if (data && data.settings) {
+      setCanSeeMembers(data.settings.members_can_see_members === 1);
+    }
+  }, [data]);
+
+  if (!data) return <Loading />;
+
+  return (
+    <PageWrapper>
+      <Header
+        label={data.settings.name}
+        rightElement={
+          data.settings.members_can_edit_settings === 1 ? (
+            <TouchableOpacity
+              style={{ width: 30, height: 30, backgroundColor: 'green' }}
+            ></TouchableOpacity>
+          ) : null
+        }
+      />
+      <ScrollView
+        showsVerticalScrollIndicator={false}
+        style={{ flex: 1 }}
+        contentContainerStyle={{
+          paddingBottom: insets.bottom,
+          justifyContent: 'space-between',
+          flex: 1
+        }}
+      >
+        <View style={{ gap: 16 }}>
+          <View style={styles.photoContainer}>
+            <TouchableOpacity
+              style={styles.photoContainer}
+              onPress={() => setFullSizeImageVisible(true)}
+              disabled={!data.settings.avatar}
+            >
+              {!data.settings.avatar ? (
+                <GroupIcon width={80} height={80} fill={Colors.LIGHT_GRAY} />
+              ) : (
+                <Image
+                  source={{ uri: API_HOST + data.settings.avatar }}
+                  style={{
+                    width: 80,
+                    height: 80,
+                    borderRadius: 40,
+                    borderWidth: 1,
+                    borderColor: Colors.FILL_LIGHT
+                  }}
+                />
+              )}
+            </TouchableOpacity>
+            <Text style={styles.bigText}>{data.settings.name}</Text>
+          </View>
+
+          {data.settings.description && (
+            <Input
+              editable={false}
+              value={data.settings.description}
+              header="Description"
+              multiline
+              height={58}
+            />
+          )}
+
+          {canSeeMembers && members ? (
+            <View style={{ gap: 8, marginBottom: 16 }}>
+              <View
+                style={{
+                  flexDirection: 'row',
+                  justifyContent: 'space-between',
+                  alignItems: 'center'
+                }}
+              >
+                <Text style={styles.title}>{members.settings.length} nomads</Text>
+                {data.settings.members_can_add_new_members === 1 ? (
+                  <TouchableOpacity
+                    style={{ width: 30, height: 30, backgroundColor: 'green' }}
+                  ></TouchableOpacity>
+                ) : null}
+              </View>
+
+              <View style={{ gap: 6 }}>
+                {(members.settings.length > 4
+                  ? members.settings.slice(0, 4)
+                  : members.settings
+                ).map((member, index) => (
+                  <TouchableOpacity key={index} style={styles.userItem} onPress={() => {}}>
+                    {member.avatar ? (
+                      <Image source={{ uri: API_HOST + member.avatar }} style={styles.avatar} />
+                    ) : (
+                      <AvatarWithInitials
+                        text={`${member.name?.split(' ')[0][0]}${member.name?.split(' ')[1][0]}`}
+                        flag={''}
+                        size={36}
+                        fontSize={16}
+                        borderColor={Colors.LIGHT_GRAY}
+                        borderWidth={1}
+                      />
+                    )}
+                    <View style={{ flex: 1 }}>
+                      <Text style={styles.userName}>{member.name}</Text>
+                    </View>
+                    <View style={{ justifyContent: 'center', alignItems: 'center' }}>
+                      {member.admin === 1 && (
+                        <Text
+                          style={{
+                            fontSize: getFontSize(10),
+                            fontWeight: '600',
+                            color: Colors.LIGHT_GRAY
+                          }}
+                        >
+                          Admin
+                        </Text>
+                      )}
+                    </View>
+                  </TouchableOpacity>
+                ))}
+              </View>
+            </View>
+          ) : null}
+        </View>
+
+        <View style={{ gap: 16 }}>
+          <View style={styles.optionsContainer}>
+            <TouchableOpacity
+              style={styles.option}
+              //  onPress={handleMute}
+            >
+              <Text style={styles.optionText}>{false ? 'Unmute' : 'Mute'}</Text>
+              <BellSlashIcon fill={Colors.DARK_BLUE} />
+            </TouchableOpacity>
+          </View>
+
+          <View style={[styles.optionsContainer, { paddingVertical: 0, gap: 0 }]}>
+            <TouchableOpacity
+              style={[styles.option, styles.dangerOption]}
+              // onPress={handleLeaveGroup}
+            >
+              <Text style={[styles.optionText, styles.dangerText]}>Leave group</Text>
+              <ExitIcon fill={Colors.RED} width={16} />
+            </TouchableOpacity>
+
+            <TouchableOpacity
+              style={[styles.option, styles.dangerOption]}
+              // onPress={handleReport}
+            >
+              <Text style={[styles.optionText, styles.dangerText]}>Report</Text>
+              <MegaphoneIcon fill={Colors.RED} />
+            </TouchableOpacity>
+
+            <TouchableOpacity
+              style={[styles.option, styles.dangerOption]}
+              // onPress={handleBlock}
+            >
+              <Text style={[styles.optionText, styles.dangerText]}>Block</Text>
+              <BanIcon fill={Colors.RED} />
+            </TouchableOpacity>
+
+            <TouchableOpacity
+              style={[styles.option, styles.dangerOption]}
+              // onPress={handleDelete}
+            >
+              <Text style={[styles.optionText, styles.dangerText]}>Delete chat</Text>
+              <TrashIcon fill={Colors.RED} width={18} height={18} />
+            </TouchableOpacity>
+          </View>
+        </View>
+      </ScrollView>
+
+      {/* <WarningModal
+        type={'confirm'}
+        isVisible={modalState.isWarningVisible}
+        message={`Are you sure you want to unfriend ${data.user_data.first_name} ${data.user_data.last_name}?`}
+        action={handleUpdateFriendStatus}
+        onClose={() => closeModal('isWarningVisible')}
+        title=""
+      /> */}
+      <ImageView
+        images={[{ uri: API_HOST + data.settings.avatar_full }]}
+        keyExtractor={(imageSrc, index) => index.toString()}
+        imageIndex={0}
+        visible={fullSizeImageVisible}
+        onRequestClose={() => setFullSizeImageVisible(false)}
+        swipeToCloseEnabled={false}
+        backgroundColor={Colors.DARK_BLUE}
+        doubleTapToZoomEnabled={true}
+      />
+    </PageWrapper>
+  );
+};
+
+const styles = StyleSheet.create({
+  photoContainer: {
+    alignItems: 'center',
+    gap: 8
+  },
+  groupPhoto: {
+    width: 80,
+    height: 80,
+    borderRadius: 40,
+    alignItems: 'center',
+    justifyContent: 'center'
+  },
+  bigText: {
+    color: Colors.DARK_BLUE,
+    fontSize: getFontSize(18),
+    fontFamily: 'montserrat-700'
+  },
+  userItem: {
+    flexDirection: 'row',
+    alignItems: 'center',
+    paddingVertical: 8,
+    paddingHorizontal: 12,
+    backgroundColor: Colors.FILL_LIGHT,
+    gap: 8,
+    borderRadius: 8
+  },
+  avatar: {
+    width: 36,
+    height: 36,
+    borderRadius: 18,
+    borderWidth: 1,
+    borderColor: Colors.LIGHT_GRAY
+  },
+  userName: {
+    color: Colors.DARK_BLUE,
+    fontSize: getFontSize(14),
+    fontFamily: 'montserrat-700'
+  },
+  title: {
+    color: Colors.DARK_BLUE,
+    fontSize: getFontSize(14),
+    fontFamily: 'redhat-700'
+  },
+  optionsContainer: {
+    paddingVertical: 10,
+    paddingHorizontal: 8,
+    gap: 16,
+    borderRadius: 8,
+    backgroundColor: Colors.FILL_LIGHT
+  },
+  option: {
+    flexDirection: 'row',
+    alignItems: 'center',
+    justifyContent: 'space-between'
+  },
+  optionText: {
+    fontSize: getFontSize(12),
+    fontWeight: '600',
+    color: Colors.DARK_BLUE
+  },
+  dangerOption: {
+    paddingVertical: 10,
+    borderBottomWidth: 1,
+    borderBlockColor: Colors.WHITE
+  },
+  dangerText: {
+    color: Colors.RED
+  }
+});
+
+export default GroupSettingScreen;

+ 0 - 0
src/screens/InAppScreens/MessagesScreen/GroupSettingsScreen/styles.tsx


+ 6 - 2
src/types/api.ts

@@ -175,7 +175,9 @@ export enum API_ENDPOINT {
   ADD_TO_GROUP = 'add-to-group',
   ADD_TO_GROUP_AS_ADMIN = 'add-to-group-as-admin',
   SET_GROUP_ADMIN = 'set-group-admin',
-  REMOVE_FROM_GROUP = 'remove-from-group'
+  REMOVE_FROM_GROUP = 'remove-from-group',
+  GET_GROUP_SETTINGS = 'get-group-settings',
+  GET_GROUP_MEMBERS = 'get-group-members'
 }
 
 export enum API {
@@ -325,7 +327,9 @@ export enum API {
   ADD_TO_GROUP = `${API_ROUTE.CHAT}/${API_ENDPOINT.ADD_TO_GROUP}`,
   ADD_TO_GROUP_AS_ADMIN = `${API_ROUTE.CHAT}/${API_ENDPOINT.ADD_TO_GROUP_AS_ADMIN}`,
   SET_GROUP_ADMIN = `${API_ROUTE.CHAT}/${API_ENDPOINT.SET_GROUP_ADMIN}`,
-  REMOVE_FROM_GROUP = `${API_ROUTE.CHAT}/${API_ENDPOINT.REMOVE_FROM_GROUP}`
+  REMOVE_FROM_GROUP = `${API_ROUTE.CHAT}/${API_ENDPOINT.REMOVE_FROM_GROUP}`,
+  GET_GROUP_SETTINGS = `${API_ROUTE.CHAT}/${API_ENDPOINT.GET_GROUP_SETTINGS}`,
+  GET_GROUP_MEMBERS = `${API_ROUTE.CHAT}/${API_ENDPOINT.GET_GROUP_MEMBERS}`
 }
 
 export type BaseAxiosError = AxiosError;

+ 1 - 0
src/types/navigation.ts

@@ -75,4 +75,5 @@ export enum NAVIGATION_PAGES {
   EVENTS = 'inAppEvents',
   EVENT = 'inAppEvent',
   FULL_MAP_VIEW = 'inAppFullMapView',
+  GROUP_SETTINGS = 'inAppGroupSettings',
 }