浏览代码

group creation settings

Viktoriia 4 月之前
父节点
当前提交
3082b9a139

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

@@ -353,5 +353,11 @@ export const chatApi = {
   leaveGroup: (token: string, group_token: string) =>
     request.postForm<ResponseType>(API.LEAVE_GROUP, { token, group_token }),
   addToGroup: (token: string, uid: number, group_token: string) =>
-    request.postForm<ResponseType>(API.ADD_TO_GROUP, { token, uid, group_token })
+    request.postForm<ResponseType>(API.ADD_TO_GROUP, { token, uid, group_token }),
+  addToGroupAsAdmin: (token: string, uid: number, group_token: string) =>
+    request.postForm<ResponseType>(API.ADD_TO_GROUP_AS_ADMIN, { token, uid, group_token }),
+  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 })
 };

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

@@ -38,5 +38,8 @@ export const chatQueryKeys = {
   setArchiveForGroup: () => ['setArchiveForGroup'] as const,
   setMuteForGroup: () => ['setMuteForGroup'] as const,
   leaveGroup: () => ['leaveGroup'] as const,
-  addToGroup: () => ['addToGroup'] as const
+  addToGroup: () => ['addToGroup'] as const,
+  addToGroupAsAdmin: () => ['addToGroupAsAdmin'] as const,
+  setGroupAdmin: () => ['setGroupAdmin'] as const,
+  removeFromGroup: () => ['removeFromGroup'] as const
 };

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

@@ -28,3 +28,6 @@ export * from './use-post-set-archive-for-group';
 export * from './use-post-set-mute-for-group';
 export * from './use-post-leave-group';
 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';

+ 22 - 0
src/modules/api/chat/queries/use-post-add-to-group-as-admin.tsx

@@ -0,0 +1,22 @@
+import { useMutation } from '@tanstack/react-query';
+
+import { chatQueryKeys } from '../chat-query-keys';
+import { chatApi } from '../chat-api';
+
+import type { BaseAxiosError } from '../../../../types';
+import { ResponseType } from '@api/response-type';
+
+export const usePostAddToGroupAsAdminMutation = () => {
+  return useMutation<
+    ResponseType,
+    BaseAxiosError,
+    { token: string; uid: number; group_token: string },
+    ResponseType
+  >({
+    mutationKey: chatQueryKeys.addToGroupAsAdmin(),
+    mutationFn: async (data) => {
+      const response = await chatApi.addToGroupAsAdmin(data.token, data.uid, data.group_token);
+      return response.data;
+    }
+  });
+};

+ 22 - 0
src/modules/api/chat/queries/use-post-remove-from-group.tsx

@@ -0,0 +1,22 @@
+import { useMutation } from '@tanstack/react-query';
+
+import { chatQueryKeys } from '../chat-query-keys';
+import { chatApi } from '../chat-api';
+
+import type { BaseAxiosError } from '../../../../types';
+import { ResponseType } from '@api/response-type';
+
+export const usePostRemoveFromGroupMutation = () => {
+  return useMutation<
+    ResponseType,
+    BaseAxiosError,
+    { token: string; uid: number; group_token: string },
+    ResponseType
+  >({
+    mutationKey: chatQueryKeys.removeFromGroup(),
+    mutationFn: async (data) => {
+      const response = await chatApi.removeFromGroup(data.token, data.uid, data.group_token);
+      return response.data;
+    }
+  });
+};

+ 27 - 0
src/modules/api/chat/queries/use-post-set-group-admin.tsx

@@ -0,0 +1,27 @@
+import { useMutation } from '@tanstack/react-query';
+
+import { chatQueryKeys } from '../chat-query-keys';
+import { chatApi } from '../chat-api';
+
+import type { BaseAxiosError } from '../../../../types';
+import { ResponseType } from '@api/response-type';
+
+export const usePostSetGroupAdminMutation = () => {
+  return useMutation<
+    ResponseType,
+    BaseAxiosError,
+    { token: string; uid: number; group_token: string; value: 0 | 1 },
+    ResponseType
+  >({
+    mutationKey: chatQueryKeys.setGroupAdmin(),
+    mutationFn: async (data) => {
+      const response = await chatApi.setGroupAdmin(
+        data.token,
+        data.uid,
+        data.group_token,
+        data.value
+      );
+      return response.data;
+    }
+  });
+};

+ 104 - 33
src/screens/InAppScreens/MessagesScreen/Components/RouteAddGroup.tsx

@@ -17,6 +17,7 @@ import { API_HOST } from 'src/constants';
 import { AvatarWithInitials } from 'src/components';
 import * as ImagePicker from 'expo-image-picker';
 import * as yup from 'yup';
+import Checkbox from 'expo-checkbox';
 
 import { FlashList } from '@shopify/flash-list';
 import { useSheetRouter } from 'react-native-actions-sheet';
@@ -51,7 +52,12 @@ const RouteAddGroup = () => {
     setGroupName,
     description,
     setDescription,
-    clearStore
+    canEdit,
+    canSend,
+    canAdd,
+    setCanEdit,
+    setCanSend,
+    setCanAdd
   } = useGroupChatStore();
   const [isSubmitting, setIsSubmitting] = useState(false);
 
@@ -109,7 +115,10 @@ const RouteAddGroup = () => {
           name: values.name,
           description: values.description,
           users: selectedUsers.map((user) => +user.user_id),
-          admins: []
+          admins: [],
+          members_can_edit_settings: canEdit ? 1 : 0,
+          members_can_send_messages: canSend ? 1 : 0,
+          members_can_add_new_members: canAdd ? 1 : 0
         };
 
         if (image && image.uri) {
@@ -246,38 +255,76 @@ const RouteAddGroup = () => {
                 formikError={props.touched.description && props.errors.description}
               />
 
-              {selectedUsers.length > 0 ? (
-                <View
-                  style={[
-                    styles.usersRow,
-                    props.errors.users ? { borderColor: Colors.RED, borderWidth: 1 } : {}
-                  ]}
-                >
-                  <FlashList
-                    viewabilityConfig={{
-                      waitForInteraction: true,
-                      itemVisiblePercentThreshold: 50,
-                      minimumViewTime: 1000
-                    }}
-                    scrollEnabled={false}
-                    data={selectedUsers}
-                    renderItem={renderUserItem}
-                    keyExtractor={(item) => item.user_id.toString()}
-                    estimatedItemSize={100}
-                    extraData={selectedUsers}
-                    showsVerticalScrollIndicator={false}
-                    contentContainerStyle={styles.selectedUsersList}
-                    numColumns={4}
-                  />
+              <View>
+                <Text style={styles.title}>Members can</Text>
+
+                <View style={styles.optionsContainer}>
+                  <TouchableOpacity style={styles.option} onPress={() => setCanEdit(!canEdit)}>
+                    <Text style={styles.optionText}>Edit group settings</Text>
+                    <Checkbox
+                      style={{ backgroundColor: Colors.WHITE, borderRadius: 4 }}
+                      color={Colors.DARK_BLUE}
+                      value={canEdit}
+                      onValueChange={setCanEdit}
+                    />
+                  </TouchableOpacity>
+
+                  <TouchableOpacity style={styles.option} onPress={() => setCanSend(!canSend)}>
+                    <Text style={styles.optionText}>Send messages</Text>
+                    <Checkbox
+                      style={{ backgroundColor: Colors.WHITE, borderRadius: 4 }}
+                      color={Colors.DARK_BLUE}
+                      value={canSend}
+                      onValueChange={setCanSend}
+                    />
+                  </TouchableOpacity>
+
+                  <TouchableOpacity style={styles.option} onPress={() => setCanAdd(!canAdd)}>
+                    <Text style={styles.optionText}>Add new members</Text>
+                    <Checkbox
+                      style={{ backgroundColor: Colors.WHITE, borderRadius: 4 }}
+                      color={Colors.DARK_BLUE}
+                      value={canAdd}
+                      onValueChange={setCanAdd}
+                    />
+                  </TouchableOpacity>
                 </View>
-              ) : null}
-              {props.errors.users && (
-                <Text
-                  style={[styles.textError, selectedUsers.length > 0 ? { marginTop: -32 } : {}]}
-                >
-                  select at least 2 members
-                </Text>
-              )}
+              </View>
+              <View>
+                <Text style={styles.title}>Members: {selectedUsers.length}</Text>
+                {selectedUsers.length > 0 ? (
+                  <View
+                    style={[
+                      styles.usersRow,
+                      props.errors.users ? { borderColor: Colors.RED, borderWidth: 1 } : {}
+                    ]}
+                  >
+                    <FlashList
+                      viewabilityConfig={{
+                        waitForInteraction: true,
+                        itemVisiblePercentThreshold: 50,
+                        minimumViewTime: 1000
+                      }}
+                      scrollEnabled={false}
+                      data={selectedUsers}
+                      renderItem={renderUserItem}
+                      keyExtractor={(item) => item.user_id.toString()}
+                      estimatedItemSize={100}
+                      extraData={selectedUsers}
+                      showsVerticalScrollIndicator={false}
+                      contentContainerStyle={styles.selectedUsersList}
+                      numColumns={4}
+                    />
+                  </View>
+                ) : null}
+                {props.errors.users && (
+                  <Text
+                    style={[styles.textError, selectedUsers.length > 0 ? { marginTop: -18 } : {}]}
+                  >
+                    select at least 2 members
+                  </Text>
+                )}
+              </View>
             </ScrollView>
           </View>
         );
@@ -405,6 +452,30 @@ const styles = StyleSheet.create({
     fontSize: getFontSize(12),
     fontFamily: 'redhat-600',
     marginTop: 5
+  },
+  optionsContainer: {
+    paddingHorizontal: 8,
+    borderRadius: 8,
+    backgroundColor: Colors.FILL_LIGHT
+  },
+  option: {
+    flexDirection: 'row',
+    alignItems: 'center',
+    justifyContent: 'space-between',
+    paddingVertical: 10,
+    borderBottomWidth: 1,
+    borderBlockColor: Colors.WHITE
+  },
+  optionText: {
+    fontSize: getFontSize(12),
+    fontWeight: '600',
+    color: Colors.DARK_BLUE
+  },
+  title: {
+    color: Colors.DARK_BLUE,
+    fontSize: getFontSize(14),
+    fontFamily: 'redhat-700',
+    marginBottom: 5
   }
 });
 

+ 20 - 16
src/screens/InAppScreens/MessagesScreen/GroupChatScreen/index.tsx

@@ -1710,22 +1710,26 @@ const GroupChatScreen = ({ route }: { route: any }) => {
     });
   };
 
-  const renderInputToolbar = (props: any) => (
-    <InputToolbar
-      {...props}
-      renderActions={() =>
-        userType === 'normal' ? (
-          <Actions
-            icon={() => <MaterialCommunityIcons name="plus" size={28} color={Colors.DARK_BLUE} />}
-            onPressActionButton={openAttachmentsModal}
-          />
-        ) : null
-      }
-      containerStyle={{
-        backgroundColor: Colors.FILL_LIGHT
-      }}
-    />
-  );
+  const renderInputToolbar = (props: any) => {
+    if (!chatData?.can_send_messages) return null;
+
+    return (
+      <InputToolbar
+        {...props}
+        renderActions={() =>
+          userType === 'normal' ? (
+            <Actions
+              icon={() => <MaterialCommunityIcons name="plus" size={28} color={Colors.DARK_BLUE} />}
+              onPressActionButton={openAttachmentsModal}
+            />
+          ) : null
+        }
+        containerStyle={{
+          backgroundColor: Colors.FILL_LIGHT
+        }}
+      />
+    );
+  };
 
   const renderScrollToBottom = () => {
     return (

+ 16 - 1
src/stores/groupChatStore.ts

@@ -14,11 +14,17 @@ interface GroupChatStore {
   image: ImagePickerAsset | null;
   groupName: string;
   description: string;
+  canEdit: boolean;
+  canSend: boolean;
+  canAdd: boolean;
   addUser: (user: User) => void;
   removeUser: (userId: string) => void;
   setImage: (image: ImagePickerAsset | null) => void;
   setGroupName: (name: string) => void;
   setDescription: (desc: string) => void;
+  setCanEdit: (canEdit: boolean) => void;
+  setCanSend: (canSend: boolean) => void;
+  setCanAdd: (canAdd: boolean) => void;
   clearStore: () => void;
 }
 
@@ -27,6 +33,9 @@ export const useGroupChatStore = create<GroupChatStore>((set) => ({
   image: null,
   groupName: '',
   description: '',
+  canEdit: true,
+  canSend: true,
+  canAdd: true,
   addUser: (user) => set((state) => ({ selectedUsers: [user, ...state.selectedUsers] })),
   removeUser: (userId) =>
     set((state) => ({
@@ -35,11 +44,17 @@ export const useGroupChatStore = create<GroupChatStore>((set) => ({
   setImage: (image) => set({ image }),
   setGroupName: (name) => set({ groupName: name }),
   setDescription: (desc) => set({ description: desc }),
+  setCanEdit: (canEdit) => set({ canEdit }),
+  setCanSend: (canSend) => set({ canSend }),
+  setCanAdd: (canAdd) => set({ canAdd }),
   clearStore: () =>
     set({
       selectedUsers: [],
       image: null,
       groupName: '',
-      description: ''
+      description: '',
+      canEdit: true,
+      canSend: true,
+      canAdd: true
     })
 }));

+ 8 - 2
src/types/api.ts

@@ -172,7 +172,10 @@ export enum API_ENDPOINT {
   SET_ARCHIVE_FOR_GROUP = 'set-archive-for-group',
   SET_MUTE_FOR_GROUP = 'set-mute-for-group',
   LEAVE_GROUP = 'leave-group',
-  ADD_TO_GROUP = 'add-to-group'
+  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'
 }
 
 export enum API {
@@ -319,7 +322,10 @@ export enum API {
   SET_ARCHIVE_FOR_GROUP = `${API_ROUTE.CHAT}/${API_ENDPOINT.SET_ARCHIVE_FOR_GROUP}`,
   SET_MUTE_FOR_GROUP = `${API_ROUTE.CHAT}/${API_ENDPOINT.SET_MUTE_FOR_GROUP}`,
   LEAVE_GROUP = `${API_ROUTE.CHAT}/${API_ENDPOINT.LEAVE_GROUP}`,
-  ADD_TO_GROUP = `${API_ROUTE.CHAT}/${API_ENDPOINT.ADD_TO_GROUP}`
+  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}`
 }
 
 export type BaseAxiosError = AxiosError;