diff --git a/.vscode/settings.json b/.vscode/settings.json index 8b856a5402ac28bfb17cb284c95305dee9578bda..f16ac62fceaba7b28197df203fe6d1c8eae4178c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,6 @@ { "editor.defaultFormatter": "esbenp.prettier-vscode", "[javascript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" + "editor.defaultFormatter": "vscode.typescript-language-features" } } diff --git a/assets/data/demo.ts b/assets/data/demo.ts new file mode 100644 index 0000000000000000000000000000000000000000..413973d9db7ac8bdcf3a6443cb2baccbcf87d95d --- /dev/null +++ b/assets/data/demo.ts @@ -0,0 +1,129 @@ +import { DataT } from "../../types"; +import IMAGE_01 from "../images/01.jpg"; +import IMAGE_02 from "../images/02.jpg"; +import IMAGE_03 from "../images/03.jpg"; +import IMAGE_04 from "../images/04.jpg"; +import IMAGE_05 from "../images/05.jpg"; +import IMAGE_06 from "../images/06.jpg"; +import IMAGE_07 from "../images/07.jpg"; +import IMAGE_08 from "../images/08.jpg"; +import IMAGE_09 from "../images/09.jpg"; +import IMAGE_10 from "../images/10.jpg"; + +const data: DataT[] = [ + { + id: 1, + name: "Leanne Graham", + isOnline: true, + match: "78", + description: + "Full-time Traveller. Globe Trotter. Occasional Photographer. Part time Singer/Dancer.", + message: + "I will go back to Gotham and I will fight men Iike this but I will not become an executioner.", + image: IMAGE_01, + }, + { + id: 2, + name: "Clementine Bauch", + match: "93", + description: + "Full-time Traveller. Globe Trotter. Occasional Photographer. Part time Singer/Dancer.", + isOnline: false, + message: "Someone like you. Someone who'll rattle the cages.", + image: IMAGE_02, + }, + { + id: 3, + name: "Ervin Howell", + match: "45", + description: + "Full-time Traveller. Globe Trotter. Occasional Photographer. Part time Singer/Dancer.", + isOnline: false, + message: + "Oh, hee-hee, aha. Ha, ooh, hee, ha-ha, ha-ha. And I thought my jokes were bad.", + image: IMAGE_03, + }, + { + id: 4, + name: "John Lebsack", + match: "88", + description: + "Full-time Traveller. Globe Trotter. Occasional Photographer. Part time Singer/Dancer.", + isOnline: true, + message: "Bats frighten me. It's time my enemies shared my dread.", + image: IMAGE_04, + }, + { + id: 5, + name: "James Dietrich", + match: "76", + description: + "Full-time Traveller. Globe Trotter. Occasional Photographer. Part time Singer/Dancer.", + isOnline: false, + message: "It's not who I am underneath but what I do that defines me.", + image: IMAGE_05, + }, + { + id: 6, + name: "Patricia Schulist", + match: "95", + description: + "Full-time Traveller. Globe Trotter. Occasional Photographer. Part time Singer/Dancer.", + isOnline: true, + message: + "You have nothing, nothing to threaten me with. Nothing to do with all your strength.", + image: IMAGE_06, + }, + { + id: 7, + name: "Chelsey Weissnat", + match: "67", + description: + "Full-time Traveller. Globe Trotter. Occasional Photographer. Part time Singer/Dancer.", + isOnline: true, + message: + "Never start with the head. The victim gets all fuzzy. He can't feel the next... See?", + image: IMAGE_07, + }, + { + id: 8, + name: "Nicky Runol", + match: "85", + description: + "Full-time Traveller. Globe Trotter. Occasional Photographer. Part time Singer/Dancer.", + age: "27", + location: "Irvine, CA", + info1: 'Straight, Single, 5"10', + info2: "Tea Totaller, Loves Photography & Travel", + info3: "Beaches, Mountain, Cafe, Movies", + info4: "Last seen: 23h ago", + isOnline: true, + message: + "And as for the television's so-called plan, Batman has no jurisdiction.", + image: IMAGE_08, + }, + { + id: 9, + name: "Glenna Reichert", + match: "74", + description: + "Full-time Traveller. Globe Trotter. Occasional Photographer. Part time Singer/Dancer.", + isOnline: true, + message: + "This is what happens when an unstoppable force meets an immovable object.", + image: IMAGE_09, + }, + { + id: 10, + name: "Kurtis DuBuque", + match: "98", + description: + "Full-time Traveller. Globe Trotter. Occasional Photographer. Part time Singer/Dancer.", + isOnline: false, + message: + "You want order in Gotham. Batman must take off his mask and turn himself in.", + image: IMAGE_10, + }, +]; + +export default data; diff --git a/assets/images/01.jpg b/assets/images/01.jpg new file mode 100644 index 0000000000000000000000000000000000000000..776bbba16fbc410a8a10d50c13669831dc32f3b8 Binary files /dev/null and b/assets/images/01.jpg differ diff --git a/assets/images/02.jpg b/assets/images/02.jpg new file mode 100644 index 0000000000000000000000000000000000000000..05360ed4a8228c106ecd31c03b572a2102a4cae8 Binary files /dev/null and b/assets/images/02.jpg differ diff --git a/assets/images/03.jpg b/assets/images/03.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8d6c1548ec9ce0baa84f7bae057f76a8c473858a Binary files /dev/null and b/assets/images/03.jpg differ diff --git a/assets/images/04.jpg b/assets/images/04.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a6d555cdd3f83ff9400bc163b9bc38c58f4c1890 Binary files /dev/null and b/assets/images/04.jpg differ diff --git a/assets/images/05.jpg b/assets/images/05.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4c0966757968e58d29fca375e693a90a0019002b Binary files /dev/null and b/assets/images/05.jpg differ diff --git a/assets/images/06.jpg b/assets/images/06.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b9851769a2df40cc3df33c155dd9913227083496 Binary files /dev/null and b/assets/images/06.jpg differ diff --git a/assets/images/07.jpg b/assets/images/07.jpg new file mode 100644 index 0000000000000000000000000000000000000000..56880c685526090fb59e07c2b6dabb13b0a6de2e Binary files /dev/null and b/assets/images/07.jpg differ diff --git a/assets/images/08.jpg b/assets/images/08.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9a5707d51495466139cc8daede3550176b185873 Binary files /dev/null and b/assets/images/08.jpg differ diff --git a/assets/images/09.jpg b/assets/images/09.jpg new file mode 100644 index 0000000000000000000000000000000000000000..139e4d67c62a31c615a1ea01b101d62e07807c61 Binary files /dev/null and b/assets/images/09.jpg differ diff --git a/assets/images/10.jpg b/assets/images/10.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ed1f7b3639991ac440a1c9751512074053a461f3 Binary files /dev/null and b/assets/images/10.jpg differ diff --git a/assets/images/bg.png b/assets/images/bg.png new file mode 100644 index 0000000000000000000000000000000000000000..8ce8aa2acdc1055d2132c9ae877abd1f9033151e Binary files /dev/null and b/assets/images/bg.png differ diff --git a/assets/images/folk.jpg b/assets/images/folk.jpg new file mode 100644 index 0000000000000000000000000000000000000000..54adf88b6601ecb94e3800264a3c09a698413758 Binary files /dev/null and b/assets/images/folk.jpg differ diff --git a/assets/styles/index.ts b/assets/styles/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..7dac881f90834eb4025a9698e896554e7937efb8 --- /dev/null +++ b/assets/styles/index.ts @@ -0,0 +1,424 @@ +import { StyleSheet, Dimensions } from "react-native"; + +export const PRIMARY_COLOR = "#7444C0"; +export const SECONDARY_COLOR = "#5636B8"; +export const WHITE = "#FFFFFF"; +export const GRAY = "#757E90"; +export const DARK_GRAY = "#363636"; +export const BLACK = "#000000"; + +export const ONLINE_STATUS = "#46A575"; +export const OFFLINE_STATUS = "#D04949"; + +export const STAR_ACTIONS = "#FFA200"; +export const LIKE_ACTIONS = "#B644B2"; +export const DISLIKE_ACTIONS = "#363636"; +export const FLASH_ACTIONS = "#5028D7"; + +export const DIMENSION_WIDTH = Dimensions.get("window").width; +export const DIMENSION_HEIGHT = Dimensions.get("window").height; + +export default StyleSheet.create({ + // COMPONENT - CARD ITEM + containerCardItem: { + backgroundColor: WHITE, + borderRadius: 8, + alignItems: "center", + margin: 10, + elevation: 1, + shadowOpacity: 0.05, + shadowRadius: 10, + shadowColor: BLACK, + shadowOffset: { height: 0, width: 0 }, + }, + matchesCardItem: { + marginTop: -35, + backgroundColor: PRIMARY_COLOR, + paddingVertical: 7, + paddingHorizontal: 20, + borderRadius: 20, + }, + matchesTextCardItem: { + color: WHITE, + }, + descriptionCardItem: { + color: GRAY, + textAlign: "center", + }, + status: { + paddingBottom: 10, + flexDirection: "row", + alignItems: "center", + }, + statusText: { + color: GRAY, + fontSize: 12, + }, + online: { + width: 6, + height: 6, + backgroundColor: ONLINE_STATUS, + borderRadius: 3, + marginRight: 4, + }, + offline: { + width: 6, + height: 6, + backgroundColor: OFFLINE_STATUS, + borderRadius: 3, + marginRight: 4, + }, + actionsCardItem: { + flexDirection: "row", + alignItems: "center", + paddingVertical: 30, + }, + button: { + width: 60, + height: 60, + borderRadius: 30, + backgroundColor: WHITE, + marginHorizontal: 7, + alignItems: "center", + justifyContent: "center", + elevation: 1, + shadowOpacity: 0.15, + shadowRadius: 20, + shadowColor: DARK_GRAY, + shadowOffset: { height: 10, width: 0 }, + }, + miniButton: { + width: 40, + height: 40, + borderRadius: 30, + backgroundColor: WHITE, + marginHorizontal: 7, + alignItems: "center", + justifyContent: "center", + elevation: 1, + shadowOpacity: 0.15, + shadowRadius: 20, + shadowColor: DARK_GRAY, + shadowOffset: { height: 10, width: 0 }, + }, + + // COMPONENT - CITY + city: { + backgroundColor: WHITE, + padding: 10, + borderRadius: 20, + width: 100, + elevation: 1, + shadowOpacity: 0.05, + shadowRadius: 10, + shadowColor: BLACK, + shadowOffset: { height: 0, width: 0 }, + }, + quickCenter: { + alignItems: "center", + justifyContent: "center", + textAlign: "center", + }, + + cityText: { + color: DARK_GRAY, + fontSize: 13, + textAlign: "center", + }, + + currentCity: { + justifyContent: "center", + flexDirection: "row", + alignItems: "center", + marginLeft: 10, + height: 50, + borderRadius: 25, + backgroundColor: PRIMARY_COLOR, + paddingHorizontal: 20, + }, + + // COMPONENT - FILTERS + filters: { + backgroundColor: WHITE, + padding: 10, + borderRadius: 20, + width: 90, + elevation: 1, + shadowOpacity: 0.05, + shadowRadius: 10, + shadowColor: BLACK, + shadowOffset: { height: 0, width: 0 }, + }, + filtersText: { + color: DARK_GRAY, + fontSize: 13, + textAlign: "center", + }, + + // COMPONENT - MESSAGE + containerMessage: { + flex: 1, + alignItems: "center", + justifyContent: "flex-start", + flexDirection: "row", + paddingHorizontal: 10, + width: DIMENSION_WIDTH - 100, + }, + avatar: { + borderRadius: 30, + width: 60, + height: 60, + marginRight: 20, + marginVertical: 15, + }, + message: { + color: GRAY, + fontSize: 12, + paddingTop: 5, + }, + + chatButton: { + position: "absolute", + bottom: 0, + right: 0, + backgroundColor: PRIMARY_COLOR, + height: 50, + width: 50, + borderRadius: 25, + alignItems: "center", + justifyContent: "center", + shadowColor: PRIMARY_COLOR, + shadowOffset: { + width: 0, + height: 2 + }, + shadowOpacity: 0.9, + shadowRadius: 8, + marginRight: 20, + marginBottom: 50, + zIndex: 1000 + }, + + // COMPONENT - PROFILE ITEM + containerProfileItem: { + backgroundColor: WHITE, + paddingHorizontal: 10, + paddingBottom: 25, + margin: 20, + borderRadius: 8, + marginTop: -65, + elevation: 1, + shadowOpacity: 0.05, + shadowRadius: 10, + shadowColor: BLACK, + shadowOffset: { height: 0, width: 0 }, + }, + matchesProfileItem: { + width: 135, + marginTop: -15, + backgroundColor: PRIMARY_COLOR, + paddingVertical: 7, + paddingHorizontal: 20, + borderRadius: 20, + alignSelf: "center", + }, + matchesTextProfileItem: { + color: WHITE, + textAlign: "center", + }, + name: { + paddingTop: 25, + paddingBottom: 5, + color: DARK_GRAY, + fontSize: 15, + textAlign: "center", + }, + descriptionProfileItem: { + color: GRAY, + textAlign: "center", + paddingBottom: 20, + fontSize: 13, + }, + info: { + paddingVertical: 8, + flexDirection: "row", + alignItems: "center", + }, + iconProfile: { + fontSize: 12, + color: DARK_GRAY, + paddingHorizontal: 10, + }, + infoContent: { + color: GRAY, + fontSize: 13, + }, + + // CONTAINER - GENERAL + bg: { + flex: 1, + resizeMode: "cover", + width: DIMENSION_WIDTH, + height: DIMENSION_HEIGHT, + }, + top: { + paddingTop: 50, + marginHorizontal: 10, + flexDirection: "row", + justifyContent: "space-between", + alignItems: "center", + }, + title: { paddingBottom: 10, fontSize: 22, color: DARK_GRAY }, + + // CONTAINER - HOME + containerHome: { + marginHorizontal: 10, + }, + + // CONTAINER - MATCHES + containerMatches: { + justifyContent: "space-between", + flex: 1, + paddingHorizontal: 10, + }, + + // CONTAINER - MESSAGES + containerMessages: { + justifyContent: "space-between", + flex: 1, + paddingHorizontal: 10, + }, + + // CONTAINER - PROFILE + containerProfile: { marginHorizontal: 0 }, + photo: { + width: DIMENSION_WIDTH, + height: 450, + }, + topIconLeft: { + paddingLeft: 20, + }, + topIconRight: { + paddingRight: 20, + }, + actionsProfile: { + justifyContent: "center", + flexDirection: "row", + alignItems: "center", + }, + textButton: { + fontSize: 15, + color: WHITE, + paddingLeft: 5, + }, + circledButton: { + width: 50, + height: 50, + borderRadius: 25, + backgroundColor: PRIMARY_COLOR, + justifyContent: "center", + alignItems: "center", + marginRight: 10, + }, + roundedButton: { + justifyContent: "center", + flexDirection: "row", + alignItems: "center", + marginLeft: 10, + height: 50, + borderRadius: 25, + backgroundColor: SECONDARY_COLOR, + paddingHorizontal: 20, + }, + + // MENU + tabButtonText: { + textTransform: "uppercase", + }, + iconMenu: { + alignItems: "center", + }, + + + //Search + searchBarContainer: { + margin: 15, + justifyContent: "flex-start", + alignItems: "center", + flexDirection: "row", + width: "90%", + + }, + searchBar__unclicked: { + padding: 10, + flexDirection: "row", + width: "95%", + backgroundColor: "#d9dbda", + borderRadius: 15, + alignItems: "center", + }, + searchBar__clicked: { + padding: 10, + flexDirection: "row", + width: "80%", + backgroundColor: "#d9dbda", + borderRadius: 15, + alignItems: "center", + justifyContent: "space-evenly", + }, + searchInput: { + fontSize: 20, + marginLeft: 10, + width: "90%", + }, + + //FlatList + flatListContainer: + { + marginTop:30, + padding:2, + }, + flatListItem: { + backgroundColor: 'orange', + padding: 20, + marginVertical: 8, + marginHorizontal: 16, + borderRadius: 8, + shadowColor: '#808080', + shadowOffset: { width: 3, height: 3 }, + shadowOpacity: 0.3, + shadowRadius: 8, + }, + + + containerHomePage: { + flex: 1, + flexDirection: "column", + justifyContent: "center", + alignItems: "center", + backgroundColor: "#fff", + position: "relative" + }, + + containerFlatList: { + flex: 1, + justifyContent: "center", + alignItems: "center", + backgroundColor: "#808080", + borderRadius: 8, + marginVertical: 20, + marginHorizontal: 16, + }, + + + catSitterCard: { + justifyContent: "center", + flexDirection: "row", + alignItems: "center", + marginLeft: 10, + height: 50, + backgroundColor: "#808080", + + }, + +}); diff --git a/components/CardItem.tsx b/components/CardItem.tsx new file mode 100644 index 0000000000000000000000000000000000000000..570e2c44a1458665b613cd39b6363503a80a252e --- /dev/null +++ b/components/CardItem.tsx @@ -0,0 +1,99 @@ +import React from "react"; +import { Text, View, Image, Dimensions, TouchableOpacity } from "react-native"; +import Icon from "./Icon"; +import { CardItemT } from "../types"; +import styles, { + DISLIKE_ACTIONS, + FLASH_ACTIONS, + LIKE_ACTIONS, + STAR_ACTIONS, + WHITE, +} from "../assets/styles"; + +const CardItem = ({ + description, + hasActions, + hasVariant, + image, + isOnline, + matches, + name, +}: CardItemT) => { + // Custom styling + const fullWidth = Dimensions.get("window").width; + + const imageStyle = [ + { + borderRadius: 8, + width: hasVariant ? fullWidth / 2 - 30 : fullWidth - 80, + height: hasVariant ? 170 : 350, + margin: hasVariant ? 0 : 20, + }, + ]; + + const nameStyle = [ + { + paddingTop: hasVariant ? 10 : 15, + paddingBottom: hasVariant ? 5 : 7, + color: "#363636", + fontSize: hasVariant ? 15 : 30, + }, + ]; + + return ( + <View style={styles.containerCardItem}> + {/* IMAGE */} + <Image source={image} style={imageStyle} /> + + {/* MATCHES */} + {matches && ( + <View style={styles.matchesCardItem}> + <Text style={styles.matchesTextCardItem}> + <Icon name="heart" color={WHITE} size={13} /> {matches}% Match! + </Text> + </View> + )} + + {/* NAME */} + <Text style={nameStyle}>{name}</Text> + + {/* DESCRIPTION */} + {description && ( + <Text style={styles.descriptionCardItem}>{description}</Text> + )} + + {/* STATUS */} + {!description && ( + <View style={styles.status}> + <View style={isOnline ? styles.online : styles.offline} /> + <Text style={styles.statusText}> + {isOnline ? "Online" : "Offline"} + </Text> + </View> + )} + + {/* ACTIONS */} + {hasActions && ( + <View style={styles.actionsCardItem}> + <TouchableOpacity style={styles.miniButton}> + <Icon name="star" color={STAR_ACTIONS} size={14} /> + </TouchableOpacity> + + <TouchableOpacity style={styles.button}> + <Icon name="heart" color={LIKE_ACTIONS} size={25} /> + </TouchableOpacity> + + <TouchableOpacity style={styles.button}> + <Icon name="close" color={DISLIKE_ACTIONS} size={25} /> + </TouchableOpacity> + + <TouchableOpacity style={styles.miniButton}> + <Icon name="flash" color={FLASH_ACTIONS} size={14} /> + </TouchableOpacity> + </View> + )} + </View> + ); +}; + +export default CardItem; diff --git a/components/City.tsx b/components/City.tsx new file mode 100644 index 0000000000000000000000000000000000000000..26f5e199121a47e47b892990b7f2ba8b834a1757 --- /dev/null +++ b/components/City.tsx @@ -0,0 +1,14 @@ +import React from "react"; +import { Text, TouchableOpacity } from "react-native"; +import Icon from "./Icon"; +import styles, { DARK_GRAY } from "../assets/styles"; + +const City = () => ( + <TouchableOpacity style={styles.city}> + <Text style={styles.cityText}> + <Icon name="location-sharp" size={13} color={DARK_GRAY} /> New York + </Text> + </TouchableOpacity> +); + +export default City; diff --git a/components/Filters.tsx b/components/Filters.tsx new file mode 100644 index 0000000000000000000000000000000000000000..bf9fdf68c398c950605264e99129303b41645c52 --- /dev/null +++ b/components/Filters.tsx @@ -0,0 +1,14 @@ +import React from "react"; +import { Text, TouchableOpacity } from "react-native"; +import Icon from "./Icon"; +import styles, { DARK_GRAY } from "../assets/styles"; + +const Filters = () => ( + <TouchableOpacity style={styles.filters}> + <Text style={styles.filtersText}> + <Icon name="filter" size={13} color={DARK_GRAY} /> Filters + </Text> + </TouchableOpacity> +); + +export default Filters; diff --git a/components/Icon.tsx b/components/Icon.tsx new file mode 100644 index 0000000000000000000000000000000000000000..5240a01e5d67c7cd0f9418fa4eebb53fdba9687e --- /dev/null +++ b/components/Icon.tsx @@ -0,0 +1,9 @@ +import React from "react"; +import { Ionicons } from "@expo/vector-icons"; +import { IconT } from "../types"; + +const Icon = ({ color, name, size, style }: IconT) => ( + <Ionicons name={name} size={size} color={color} style={style} /> +); + +export default Icon; diff --git a/components/Message.tsx b/components/Message.tsx new file mode 100644 index 0000000000000000000000000000000000000000..c2c2f6cf77a179285f9b747ad56ed7073f1ad9e2 --- /dev/null +++ b/components/Message.tsx @@ -0,0 +1,16 @@ +import React from "react"; +import { Text, View, Image } from "react-native"; +import { MessageT } from "../types"; +import styles from "../assets/styles"; + +const Message = ({ image, lastMessage, name }: MessageT) => ( + <View style={styles.containerMessage}> + <Image source={image} style={styles.avatar} /> + <View> + <Text>{name}</Text> + <Text style={styles.message}>{lastMessage}</Text> + </View> + </View> +); + +export default Message; diff --git a/components/ProfileItem.tsx b/components/ProfileItem.tsx new file mode 100644 index 0000000000000000000000000000000000000000..378cfefb1df2b73bc4bdd18dccd2a80aa29f50ff --- /dev/null +++ b/components/ProfileItem.tsx @@ -0,0 +1,60 @@ +import React from "react"; +import { Text, View } from "react-native"; +import Icon from "./Icon"; +import { ProfileItemT } from "../types"; +import styles, { DARK_GRAY, WHITE } from "../assets/styles"; + +const ProfileItem = ({ + age, + info1, + info2, + info3, + info4, + location, + matches, + name, +}: ProfileItemT) => ( + <View style={styles.containerProfileItem}> + <View style={styles.matchesProfileItem}> + <Text style={styles.matchesTextProfileItem}> + <Icon name="heart" size={13} color={WHITE} /> {matches}% Match! + </Text> + </View> + + <Text style={styles.name}>{name}</Text> + + <Text style={styles.descriptionProfileItem}> + {age} - {location} + </Text> + + <View style={styles.info}> + <Text style={styles.iconProfile}> + <Icon name="person" size={12} color={DARK_GRAY} /> + </Text> + <Text style={styles.infoContent}>{info1}</Text> + </View> + + <View style={styles.info}> + <Text style={styles.iconProfile}> + <Icon name="pizza" size={12} color={DARK_GRAY} /> + </Text> + <Text style={styles.infoContent}>{info2}</Text> + </View> + + <View style={styles.info}> + <Text style={styles.iconProfile}> + <Icon name="airplane" size={12} color={DARK_GRAY} /> + </Text> + <Text style={styles.infoContent}>{info3}</Text> + </View> + + <View style={styles.info}> + <Text style={styles.iconProfile}> + <Icon name="calendar" size={12} color={DARK_GRAY} /> + </Text> + <Text style={styles.infoContent}>{info4}</Text> + </View> + </View> +); + +export default ProfileItem; diff --git a/components/TabBarIcon.tsx b/components/TabBarIcon.tsx new file mode 100644 index 0000000000000000000000000000000000000000..343ac122e8928e6a50e4488bfb158e94173395aa --- /dev/null +++ b/components/TabBarIcon.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import { Text, View } from "react-native"; +import Icon from "./Icon"; +import styles, { DARK_GRAY, PRIMARY_COLOR } from "../assets/styles"; +import { TabBarIconT } from "../types"; + +const TabBarIcon = ({ focused, iconName, text }: TabBarIconT) => { + const iconFocused = focused ? PRIMARY_COLOR : DARK_GRAY; + + return ( + <View style={styles.iconMenu}> + <Icon name={iconName} size={16} color={iconFocused} /> + <Text style={[styles.tabButtonText, { color: iconFocused }]}>{text}</Text> + </View> + ); +}; + +export default TabBarIcon; diff --git a/components/index.ts b/components/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..8c342b920a550f0fd6ed0f04f3cd915e3de1f839 --- /dev/null +++ b/components/index.ts @@ -0,0 +1,6 @@ +export { default as CardItem } from "./CardItem"; +export { default as City } from "./City"; +export { default as Filters } from "./Filters"; +export { default as Icon } from "./Icon"; +export { default as Message } from "./Message"; +export { default as ProfileItem } from "./ProfileItem"; diff --git a/package-lock.json b/package-lock.json index 20b7a0cee79ef043f16dd11afb2d9ea44aa2d6c5..f46f96bdaa01f66e9ce44321032063201b6fdb69 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,6 +25,7 @@ "react-native-safe-area-context": "4.5.0", "react-native-screens": "~3.20.0", "react-native-web": "~0.18.10", + "typescript": "^4.9.4", "uuid": "^9.0.1" }, "devDependencies": { @@ -13129,6 +13130,18 @@ "node": ">= 0.6" } }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "node_modules/ua-parser-js": { "version": "1.0.35", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.35.tgz", diff --git a/package.json b/package.json index c23ad2fb3327f12aa881481e75f6c176cef3c238..13ff601f2977c88d0bafd80a943de9d219c153c2 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,8 @@ "react-native-safe-area-context": "4.5.0", "react-native-screens": "~3.20.0", "react-native-web": "~0.18.10", - "uuid": "^9.0.1" + "uuid": "^9.0.1", + "typescript": "^4.9.4" }, "devDependencies": { "@babel/core": "^7.12.9" diff --git a/screens/tabs/Catsitter.js b/screens/tabs/Catsitter.js index 4a07ba2fd6c6008a07914de6a926d6967f4317ed..f89a82cb60fc8df299238b816871d2bb15ca13bf 100644 --- a/screens/tabs/Catsitter.js +++ b/screens/tabs/Catsitter.js @@ -1,7 +1,8 @@ -import { StyleSheet, Text, View } from "react-native"; +import { StyleSheet, Text, View, FlatList } from "react-native"; import React, { useState, useLayoutEffect } from "react"; import { collection, query, onSnapshot, where, getDoc } from "firebase/firestore"; import { auth, database } from "../../config/firebase"; +import styles from "../../assets/styles"; const Catsitter = ({ route }) => { const { id } = route.params; @@ -20,14 +21,31 @@ const Catsitter = ({ route }) => { }, []); return ( - <View> - <Text> - Catsitter: {id} {JSON.stringify(catsitter)} - </Text> + + <View style={styles.containerFlatList}> + + <Text >Cat Sitter Name: {catsitter.name}</Text > + <Text >Cat Sitter Address: {catsitter.address}</Text > + <Text >Cat Sitter Available Time: {catsitter.availableTime}</Text > + <Text >Cat Sitter Postal Code:{catsitter.postalCode} </Text > + <Text >Cat Sitter Age: {catsitter.age}</Text > + <Text >Cat Sitter Price Per Night: {catsitter.price}</Text > + <Text >Cat Sitter Status: + {(() => { + switch (catsitter.isOpen) { + case true: return " Open"; + case "false": return " Closed"; + default: return " Closed"; + } + })()} + </Text > + <Text >Cat Sitter Information: {catsitter.description}</Text > + + + </View> ); }; export default Catsitter; -const styles = StyleSheet.create({}); diff --git a/screens/tabs/Home.js b/screens/tabs/Home.js index 4a650ec95e0cdbb717977f2da8f9587081ca31c4..644ae7a48dfefde34ce26974411cd6ab2209343c 100644 --- a/screens/tabs/Home.js +++ b/screens/tabs/Home.js @@ -1,12 +1,15 @@ import React, { useEffect, useState, useLayoutEffect } from "react"; -import { View, TouchableOpacity, Image, StyleSheet, Text, TextInput, FlatList } from "react-native"; +import { View, TouchableOpacity, Image, StyleSheet, Text, TextInput, FlatList, ImageBackground, Keyboard, Button, PRETT } from "react-native"; import { useNavigation } from "@react-navigation/native"; import { FontAwesome } from "@expo/vector-icons"; import colors from "../../colors"; import { collection, query, onSnapshot, orderBy } from "firebase/firestore"; import { Entypo } from "@expo/vector-icons"; import { database } from "../../config/firebase"; - +import { City, Filters, CardItem } from "../../components"; +import { Icon, Message } from '../../components' +import styles from "../../assets/styles"; +import { BLACK, DARK_GRAY, WHITE, PRIMARY_COLOR, GRAY, ONLINE_STATUS, OFFLINE_STATUS, DIMENSION_WIDTH, DIMENSION_HEIGHT, SECONDARY_COLOR } from '../../assets/styles' const catImageUrl = "https://i.guim.co.uk/img/media/26392d05302e02f7bf4eb143bb84c8097d09144b/446_167_3683_2210/master/3683.jpg?width=1200&height=1200&quality=85&auto=format&fit=crop&s=49ed3252c0b2ffb49cf8b508892e452d"; @@ -47,72 +50,53 @@ const Home = () => { }, []); return ( - <View style={styles.container}> - <TouchableOpacity onPress={() => navigation.navigate("Chat")} style={styles.chatButton}> - <Entypo name="chat" size={24} color={colors.lightGray} /> + <View source={require("../../assets/images/10.jpg")} style={styles.containerHomePage}> + <TouchableOpacity style={styles.roundedButton}> + <Icon name="logo-github" size={20} color={WHITE} /> + <Text style={styles.textButton}>Cat sitter near your home</Text> </TouchableOpacity> - <Text>Cat sitter near your home</Text> - <View style={{ display: "flex", flexDirection: "row" }}> - <Entypo name="chat" size={20} color={colors.lightGray} /> - <View> - <Text>Current Location</Text> - <Text>New York, USA</Text> - </View> + <View> + <Text style={styles.quickCenter}>Your Location</Text> + </View> + + <View style={styles.container}> + <TouchableOpacity style={styles.currentCity}> + <Icon name="navigate-outline" size={20} color={WHITE} /> + <Text style={styles.textButton}>New York, USA</Text> + </TouchableOpacity> + </View> + <View style={styles.searchBarContainer}> + <Icon name="search-outline" size={20} color={BLACK} /> + <TextInput style={styles.searchInput} placeholder="Search" autoCapitalize="none" autoFocus={true} value={keyword} onChangeText={(text) => setKeyword(text)} /> </View> - <TextInput style={styles.input} placeholder="Search" autoCapitalize="none" autoFocus={true} value={keyword} onChangeText={(text) => setKeyword(text)} /> - - <FlatList - data={catsitters} - keyExtractor={(item, index) => index.toString()} - renderItem={({ item }) => ( - <TouchableOpacity onPress={() => navigation.navigate("Catsitter", { id: item._id })}> - <Text>{JSON.stringify(item)}</Text> - </TouchableOpacity> - )} - /> + + <FlatList style={styles.flatListContainer} + data={catsitters} + keyExtractor={(item, index) => index.toString()} + renderItem={({ item }) => ( + <TouchableOpacity style={styles.catSitterCard} onPress={() => navigation.navigate("Catsitter", { id: item._id })}> + <Text >Cat Sitter Name: {JSON.stringify(item.content.name).replaceAll(/['"]+/g , "")}</Text > + </TouchableOpacity> + )} + /> + + + + + + + + + <TouchableOpacity onPress={() => navigation.navigate("Chat")} style={styles.chatButton}> + <Entypo name="chat" size={24} color={colors.lightGray} /> + </TouchableOpacity> </View> + + ); }; export default Home; -const styles = StyleSheet.create({ - container: { - flex: 1, - flexDirection: "column", - justifyContent: "center", - alignItems: "center", - backgroundColor: "#fff", - position: "relative" - }, - chatButton: { - position: "absolute", - bottom: 0, - right: 0, - backgroundColor: colors.primary, - height: 50, - width: 50, - borderRadius: 25, - alignItems: "center", - justifyContent: "center", - shadowColor: colors.primary, - shadowOffset: { - width: 0, - height: 2 - }, - shadowOpacity: 0.9, - shadowRadius: 8, - marginRight: 20, - marginBottom: 50, - zIndex: 1000 - }, - input: { - backgroundColor: "#F6F7FB", - height: 58, - marginBottom: 20, - fontSize: 16, - borderRadius: 10, - padding: 12 - } -}); + diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000000000000000000000000000000000000..0e6371f6f5c0b7cf001870252ab9f51e0fd14215 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,4 @@ +{ + "compilerOptions": {}, + "extends": "expo/tsconfig.base" +}