您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

index.jsx 6.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. import React, { useEffect, useState } from 'react';
  2. import { View, StyleSheet, TextInput, Text, ScrollView, FlatList, Pressable } from 'react-native';
  3. import BootstrapModal from '@/components/BootstrapModal';
  4. import { Appbar, Menu, Avatar, useTheme, Button } from 'react-native-paper';
  5. import Icon from 'react-native-vector-icons/MaterialIcons';
  6. import dpuser from "@/assets/images/userdp.png";
  7. /** Some Temp Bullshits */
  8. const dummyUserDataName = [
  9. {
  10. id: 1,
  11. name: "AzmanHadi@PSK",
  12. user_img: "https://t4.ftcdn.net/jpg/03/64/21/11/360_F_364211147_1qgLVxv1Tcq0Ohz3FawUfrtONzz8nq3e.jpg"
  13. },
  14. {
  15. id: 2,
  16. name: "NorMelati@PSK",
  17. user_img: "https://www.shutterstock.com/image-photo/head-shot-portrait-millennial-beautiful-260nw-1893951241.jpg"
  18. },
  19. {
  20. id: 3,
  21. name: "RazuanKhan@PSK",
  22. user_img: "https://plus.unsplash.com/premium_photo-1689568126014-06fea9d5d341?fm=jpg&q=60&w=3000&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MXx8cHJvZmlsZXxlbnwwfHwwfHx8MA%3D%3D"
  23. }
  24. ]
  25. const Notification = () => {
  26. const { colors, fonts } = useTheme();
  27. const [menuVisible, setMenuVisible] = useState(false);
  28. const [inputContent, setInputContent] = useState("");
  29. const [pickedUser, setPickedUser] = useState(null);
  30. const [userNameSearch, setUserNameSearch] = useState('');
  31. const [visible, setVisible] = useState(true);
  32. const [nameSuggestion, setNameSuggestion] = useState([])
  33. const preTextClick = (pretext) => {
  34. setInputContent(pretext)
  35. }
  36. const handleOnSearchUser = (e) => {
  37. const value = e.target.value;
  38. setUserNameSearch(value)
  39. }
  40. useEffect(() => {
  41. if (userNameSearch.length > 0) {
  42. let filteredData = dummyUserDataName.filter(
  43. ({ name }) => name.toLowerCase().includes(userNameSearch?.toLowerCase())
  44. )
  45. setNameSuggestion(filteredData);
  46. } else {
  47. setNameSuggestion([]);
  48. }
  49. }, [userNameSearch])
  50. const renderUser = ({ item }) => (
  51. <Pressable onPress={() => {
  52. setPickedUser(item);
  53. setNameSuggestion([]);
  54. setUserNameSearch("");
  55. }}>
  56. <View style={styles.nameItem} >
  57. <Avatar.Image size={25} source={item.user_img}></Avatar.Image>
  58. <Text style={styles.nameText}>{item.name}</Text>
  59. </View>
  60. </Pressable>
  61. );
  62. const renderUserBadge = (pickedUser) => {
  63. return (
  64. <View style={{ flexDirection: "row", backgroundColor: "#396868", padding: 5, borderRadius: 20, paddingRight: 10 }}>
  65. <Avatar.Image size={35} source={pickedUser?.user_img}></Avatar.Image>
  66. <Text style={{ marginTop: "auto", marginBottom: "auto", marginLeft: 10, fontWeight: "500", color: "#FFF", marginRight: 5 }}>{pickedUser?.name}</Text>
  67. <Pressable onPress={()=>{setPickedUser(null)}}>
  68. <Icon name="cancel" size={25} color={"#FFF"} style={{ marginTop: "auto", marginBottom: "auto" }} />
  69. </Pressable>
  70. </View>
  71. )
  72. }
  73. return (
  74. <View style={[styles.container, { backgroundColor: colors.background }]}>
  75. <BootstrapModal visible={visible} setVisible={setVisible} />
  76. <Appbar.Header>
  77. <Avatar.Image size={50} source={dpuser}></Avatar.Image>
  78. <View style={styles.titleContainer}>
  79. <Appbar.Content title="Send Notification" titleStyle={[fonts.titleLarge, styles.title]} />
  80. </View>
  81. {/* Menu Component */}
  82. <Menu
  83. visible={menuVisible}
  84. onDismiss={() => setMenuVisible(false)}
  85. anchor={
  86. <Appbar.Action icon="dots-vertical" onPress={() => setMenuVisible(true)} />
  87. }
  88. >
  89. <Menu.Item onPress={() => console.log('Profile Clicked')} title="Profile" />
  90. <Menu.Item onPress={() => console.log('Settings Clicked')} title="Settings" />
  91. <Menu.Item onPress={() => console.log('Logout Clicked')} title="Logout" />
  92. </Menu>
  93. </Appbar.Header>
  94. <View style={{ flex: 1, marginTop: 20 }}>
  95. <View style={{ flexDirection: "row", gap: 20, marginBottom: 20 }}>
  96. <Text style={[fonts.titleMedium, { fontWeight: "bold", marginTop: "auto", marginBottom: "auto" }]}>To :</Text>
  97. {pickedUser ? renderUserBadge(pickedUser) : <View style={{ flex: 1 }}>
  98. <TextInput
  99. value={userNameSearch}
  100. onChange={(e) => {
  101. handleOnSearchUser(e)
  102. }}
  103. style={styles.userSearchInput}
  104. />
  105. {(nameSuggestion.length > 0) && <View style={styles.nameListContainer}>
  106. <FlatList
  107. data={nameSuggestion}
  108. renderItem={renderUser}
  109. keyExtractor={(item) => `${item?.id}`}
  110. contentContainerStyle={styles.listContent}
  111. />
  112. </View>}
  113. </View>}
  114. </View>
  115. <TextInput
  116. style={styles.textArea}
  117. value={inputContent}
  118. onChangeText={setInputContent}
  119. multiline={true} // Enables multi-line input
  120. numberOfLines={8} // Sets an initial number of visible lines
  121. />
  122. <Text style={[fonts.titleLarge, { fontWeight: "bold", marginBottom: 20 }]}>Select Pretext</Text>
  123. <View style={{ flex: 1 }}>
  124. {[
  125. "Request to Work From Home",
  126. "Request for late Check In",
  127. "Request for early Check Out",
  128. "Notify for Annual Leave",
  129. "Notify for Emergency Leave"
  130. ].map(text => <Text onPress={() => { preTextClick(text) }} style={[fonts.titleMedium, { marginBottom: 20, fontWeight: "bold", color: colors.secondary }]} >{text}</Text>)}
  131. </View>
  132. </View>
  133. </View>
  134. );
  135. };
  136. const styles = StyleSheet.create({
  137. container: {
  138. flex: 1,
  139. padding: 20,
  140. width: '100%',
  141. },
  142. textArea: {
  143. height: 220,
  144. borderColor: "#ccc",
  145. borderWidth: 1,
  146. padding: 10,
  147. borderRadius: 8,
  148. textAlignVertical: "top", // Makes text start from the top-left
  149. backgroundColor: "#fff",
  150. marginBottom: 20
  151. },
  152. badge: {
  153. backgroundColor: "#BB5C3F",
  154. color: "#FFF",
  155. borderRadius: 100,
  156. paddingVertical: 4,
  157. paddingHorizontal: 6,
  158. fontSize: 10,
  159. fontWeight: "400",
  160. verticalAlign: "middle",
  161. marginStart: 5
  162. },
  163. userSearchInput: {
  164. flex: 1,
  165. paddingHorizontal: 20,
  166. borderBottomColor: "rgba(0,0,0,0.2)",
  167. borderBottomWidth: 1,
  168. marginEnd: 20
  169. },
  170. nameListContainer: {
  171. position: "absolute",
  172. top: 25,
  173. left: 0,
  174. backgroundColor: "#FFF",
  175. width: "100%",
  176. paddingHorizontal: 10,
  177. borderWidth: 2,
  178. borderColor: "#CFCFCF"
  179. },
  180. listContent: {
  181. paddingBottom: 10,
  182. },
  183. nameItem: {
  184. paddingVertical: 6,
  185. flex: 1,
  186. flexDirection: "row"
  187. },
  188. nameText: {
  189. marginLeft: 10,
  190. fontSize: 16,
  191. color: '#555',
  192. },
  193. titleContainer: {
  194. flex: 1,
  195. alignItems: 'center',
  196. },
  197. title: {
  198. fontWeight: 'bold',
  199. },
  200. icon: {
  201. padding: 10,
  202. position: "absolute",
  203. right: 10,
  204. color: "#D9D9D9"
  205. }
  206. });
  207. export default Notification;