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

index.jsx 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. import React, { useEffect, useState } from 'react';
  2. import { View, StyleSheet, TextInput, Text, ScrollView, Pressable } from 'react-native';
  3. import { Appbar, Menu, Avatar, useTheme, Button } from 'react-native-paper';
  4. import Icon from 'react-native-vector-icons/MaterialIcons';
  5. import dpuser from "@/assets/images/userdp.png";
  6. import { Link, router } from 'expo-router';
  7. import confirmationNotificationDummyData from "@/dummyData.json";
  8. const Home = () => {
  9. const { colors, fonts } = useTheme();
  10. const [menuVisible, setMenuVisible] = useState(false);
  11. const [searchInput, setSearchInput] = useState("")
  12. const [showRequest, setshowRequest] = useState(false)
  13. const [activeTab, setActiveTab] = useState('General');
  14. const [confirmationNotification, setConfirmationNotification] = useState([])
  15. useEffect(() => {
  16. setConfirmationNotification(confirmationNotificationDummyData)
  17. }, [])
  18. const renderNotification = () => {
  19. return (
  20. <Link href={{
  21. pathname: '/home/status',
  22. params: { id: '42', message: 'ReactNativeRocks' },
  23. }} asChild>
  24. <View style={{ marginBottom: 30, borderBottomWidth: 1, borderBottomColor: "rgba(57, 104, 104, 0.3)" }}>
  25. <View style={{ flexDirection: "row", marginBottom: 10 }}>
  26. <Avatar.Image size={60} source={dpuser}></Avatar.Image>
  27. <View style={{ flex: 1, justifyContent: "center", paddingStart: 15, position: "relative", justifyContent: "space-evenly" }}>
  28. <Text style={{ fontWeight: "700", position: "absolute", top: 5, right: 0, color: "rgba(0,0,0,0.3)" }}>7:55AM</Text>
  29. <Text style={{ fontWeight: "700" }}>Invest Pahang</Text>
  30. <Text style={{ fontWeight: "700" }}>ID No : Ariffudin@PSK</Text>
  31. </View>
  32. </View>
  33. <Text style={{ fontWeight: "700", marginBottom: 10 }}>Muhammad Ariffudin is working from home today</Text>
  34. </View>
  35. </Link>
  36. )
  37. }
  38. const renderNotificationAction = () => {
  39. return (
  40. <View style={{ marginBottom: 30, borderBottomWidth: 1, paddingBottom: 15, borderBottomColor: "rgba(57, 104, 104, 0.3)" }}>
  41. <Link href={{
  42. pathname: '/home/status',
  43. params: { id: '42', message: 'ReactNativeRocks' },
  44. }} asChild>
  45. <View style={{ flexDirection: "row", marginBottom: 10 }}>
  46. <Avatar.Image size={60} source={dpuser}></Avatar.Image>
  47. <View style={{ flex: 1, justifyContent: "center", paddingStart: 15, position: "relative", justifyContent: "space-evenly" }}>
  48. <Text style={{ fontWeight: "700", position: "absolute", top: 5, right: 0, color: "rgba(0,0,0,0.3)" }}>7:55AM</Text>
  49. <Text style={{ fontWeight: "700" }}>Invest Pahang</Text>
  50. <Text style={{ fontWeight: "700" }}>ID No : Ariffudin@PSK</Text>
  51. </View>
  52. </View>
  53. </Link>
  54. <Text style={{ fontWeight: "700", marginBottom: 10 }}>Muhammad Ariffudin is working from home today</Text>
  55. <View style={{ flexDirection: "row", justifyContent: "space-evenly", gap: 10 }}>
  56. <Button mode='outlined' style={{ paddingHorizontal: 35, borderColor: colors.primary }} onPress={() => { console.log("click") }}>Reject</Button>
  57. <Button mode='contained' style={{ paddingHorizontal: 35 }} onPress={() => { console.log("click") }}>Accept</Button>
  58. </View>
  59. </View>
  60. )
  61. }
  62. const renderNotificationResult = (result) => {
  63. return (
  64. <Link href={{
  65. pathname: '/home/status',
  66. params: { id: '42', message: 'ReactNativeRocks' },
  67. }} asChild>
  68. <View style={{ marginBottom: 30, borderBottomWidth: 1, paddingBottom: 15, borderBottomColor: "rgba(57, 104, 104, 0.3)" }}>
  69. <View style={{ flexDirection: "row", marginBottom: 10 }}>
  70. <Avatar.Image size={60} source={dpuser}></Avatar.Image>
  71. <View style={{ flex: 1, justifyContent: "center", paddingStart: 15, position: "relative", justifyContent: "space-evenly" }}>
  72. <Text style={{ fontWeight: "700", position: "absolute", top: 5, right: 0, color: "rgba(0,0,0,0.3)" }}>7:55AM</Text>
  73. <Text style={{ fontWeight: "700" }}>Invest Pahang</Text>
  74. <Text style={{ fontWeight: "700" }}>ID No : Ariffudin@PSK</Text>
  75. </View>
  76. </View>
  77. <Text style={{ fontWeight: "700", marginBottom: 10 }}>Muhammad Ariffudin is working from home today</Text>
  78. <View style={{ flexDirection: "row" }}>
  79. {(result) ?
  80. <Text style={[fonts.titleSmall, { color: colors.primary }]}><Icon name="done" size={20} style={{ verticalAlign: "middle", marginEnd: 10 }} />Request Accepted</Text> :
  81. <Text style={[fonts.titleSmall, { color: colors.error }]}><Icon name="close" size={20} style={{ verticalAlign: "middle", marginEnd: 10 }} />Request Decline</Text>
  82. }
  83. </View>
  84. </View>
  85. </Link>
  86. )
  87. }
  88. return (
  89. <View style={[styles.container, { backgroundColor: colors.background }]}>
  90. <Appbar.Header>
  91. <Avatar.Image size={50} source={dpuser}></Avatar.Image>
  92. <View style={styles.titleContainer}>
  93. <Appbar.Content title="General" titleStyle={[fonts.titleLarge, styles.title]} />
  94. </View>
  95. {/* Menu Component */}
  96. <Menu
  97. visible={menuVisible}
  98. onDismiss={() => setMenuVisible(false)}
  99. anchor={
  100. <Appbar.Action icon="dots-vertical" onPress={() => setMenuVisible(true)} />
  101. }
  102. >
  103. <Menu.Item onPress={() => console.log('Profile Clicked')} title="Profile" />
  104. <Menu.Item onPress={() => console.log('Settings Clicked')} title="Settings" />
  105. <Menu.Item onPress={() => console.log('Logout Clicked')} title="Logout" />
  106. </Menu>
  107. </Appbar.Header>
  108. <View style={styles.tabContainer}>
  109. <Text style={[styles.tabButton, fonts.titleMedium, activeTab === 'General' && styles.activeTab]} onPress={() => { setActiveTab('General') }}>General</Text>
  110. <Text style={[styles.tabButton, fonts.titleMedium, activeTab === 'Request' && styles.activeTab]} onPress={() => { setActiveTab('Request') }}>Request <Text style={styles.badge}>1</Text></Text>
  111. </View>
  112. <View style={styles.searchSection}>
  113. <TextInput
  114. style={styles.input}
  115. placeholder="Search"
  116. onChangeText={setSearchInput}
  117. value={searchInput}
  118. underlineColorAndroid="transparent"
  119. placeholderTextColor="#D9D9D9"
  120. />
  121. <Icon name="search" size={20} color="#888" style={styles.icon} />
  122. </View>
  123. {(activeTab == 'General') && <View style={{ flex: 1 }}>
  124. <ScrollView>
  125. <Text style={[fonts.titleMedium, { fontWeight: "bold", marginBottom: 15 }]}>Today</Text>
  126. {[1, 2].map(() => renderNotification())}
  127. <Text style={[fonts.titleMedium, { fontWeight: "bold", marginBottom: 15 }]}>Yesterday</Text>
  128. {[1, 2].map(() => renderNotification())}
  129. <Text style={[fonts.titleMedium, { fontWeight: "bold", marginBottom: 15 }]}>Older</Text>
  130. {[1, 2].map(() => renderNotification())}
  131. </ScrollView>
  132. </View>}
  133. {(activeTab == 'Request') && <View style={{ flex: 1 }}>
  134. <ScrollView>
  135. {confirmationNotification.map((confirmation) => {
  136. if (!confirmation) return
  137. if (confirmation.accepted == true) return renderNotificationResult(true)
  138. else if (confirmation.accepted == false) return renderNotificationResult(false)
  139. else return renderNotificationAction()
  140. })}
  141. </ScrollView>
  142. </View>}
  143. </View>
  144. );
  145. };
  146. const styles = StyleSheet.create({
  147. container: {
  148. flex: 1,
  149. padding: 20,
  150. width: '100%',
  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. activeTab: {
  164. borderBottomWidth: 2,
  165. borderBottomColor: "#396868",
  166. color: "#396868",
  167. fontWeight: "bold"
  168. },
  169. tabContainer: {
  170. flexDirection: "row",
  171. marginBottom: 20
  172. },
  173. tabButton: {
  174. fontWeight: "bold",
  175. paddingVertical: 15,
  176. width: "50%",
  177. textAlign: "center",
  178. active: {
  179. borderBottomWidth: 2,
  180. }
  181. },
  182. titleContainer: {
  183. flex: 1,
  184. alignItems: 'center',
  185. },
  186. title: {
  187. fontWeight: 'bold',
  188. },
  189. searchSection: {
  190. flexDirection: 'row',
  191. justifyContent: 'center',
  192. alignItems: 'center',
  193. marginBottom: 20
  194. },
  195. icon: {
  196. padding: 10,
  197. position: "absolute",
  198. right: 10,
  199. color: "#D9D9D9"
  200. },
  201. input: {
  202. height: 40,
  203. flex: 1,
  204. borderWidth: 1,
  205. paddingVertical: 10,
  206. paddingHorizontal: 20,
  207. borderRadius: 100,
  208. borderColor: "#C0CFD0"
  209. }
  210. });
  211. export default Home;