From fcf97c1054f377d9ad4bf780830f27d1b4e0c8ab Mon Sep 17 00:00:00 2001 From: Lorenzo Trujillo Date: Tue, 7 May 2024 09:56:36 -0600 Subject: [PATCH] =?UTF-8?q?Se=20cambio=20la=20estructura=20de=20la=20aplic?= =?UTF-8?q?aci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mobile/src/common/components/audio_player.tsx | 77 +++++++++++++++ .../common/components/caroussel/caroussel.tsx | 92 +++++++++++++++++ .../components/caroussel/caroussel_tile.tsx | 77 +++++++++++++++ .../common/components/custom_tile_button.tsx | 66 +++++++++++++ .../components/form/date_text_input.tsx | 42 ++++++++ .../src/common/components/form/text_input.tsx | 98 +++++++++++++++++++ .../common/components/full_page_loader.tsx | 9 ++ 7 files changed, 461 insertions(+) create mode 100644 mobile/src/common/components/audio_player.tsx create mode 100644 mobile/src/common/components/caroussel/caroussel.tsx create mode 100644 mobile/src/common/components/caroussel/caroussel_tile.tsx create mode 100644 mobile/src/common/components/custom_tile_button.tsx create mode 100644 mobile/src/common/components/form/date_text_input.tsx create mode 100644 mobile/src/common/components/form/text_input.tsx create mode 100644 mobile/src/common/components/full_page_loader.tsx diff --git a/mobile/src/common/components/audio_player.tsx b/mobile/src/common/components/audio_player.tsx new file mode 100644 index 00000000..ad8fe1a7 --- /dev/null +++ b/mobile/src/common/components/audio_player.tsx @@ -0,0 +1,77 @@ +import { TouchableOpacity, View, StyleSheet, Text } from "react-native"; +import { FontAwesome, Feather } from "@expo/vector-icons"; +import Slider from "@react-native-community/slider"; +import { millisecondsToHourFormat } from "../../utils/time"; +import { LIGTHT_THEME } from "../../constants/theme"; +import { useAudio } from "../../contexts/audio_context"; +import { useEffect } from "react"; + +const audio = require("./../../../assets/audio_prueba.mp3"); + +interface AudioPlayerProps { + audioUrl: string; + title: string; + description: string; +} + +export const AudioPlayer = () => { + const { loadAudio, position, togglePlay, isPlaying, duration, onValueChange } = + useAudio(); + + useEffect(() => { + loadAudio(audio); + }, []); + + return ( + + + + {millisecondsToHourFormat(position)} + + + + {millisecondsToHourFormat(duration)} + + + + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + height: 100, + width: "100%", + justifyContent: "center", + alignItems: "center", + backgroundColor: LIGTHT_THEME.color.primary, + gap: 10, + }, + sliderContainer: { + width: "100%", + display: "flex", + flexDirection: "row", + paddingHorizontal: 20, + }, + slider: { + flex: 1, + }, + hour_text: { + color: LIGTHT_THEME.color.white, + fontWeight: "bold", + }, +}); diff --git a/mobile/src/common/components/caroussel/caroussel.tsx b/mobile/src/common/components/caroussel/caroussel.tsx new file mode 100644 index 00000000..b78eee75 --- /dev/null +++ b/mobile/src/common/components/caroussel/caroussel.tsx @@ -0,0 +1,92 @@ +import { View, Animated, Text, Dimensions, Image, NativeSyntheticEvent, NativeScrollEvent } from "react-native"; +import { PlaceInfoEntity } from "../../../domain/entities/place_info_entity"; +import { useRef } from "react"; +import { StateDataSource } from "../../../domain/datasources/state_datasource"; +import { CarousselTile } from "./caroussel_tile"; +import { router } from "expo-router"; + +interface CarousselProps { + data: PlaceInfoEntity[]; + onPress?: (id: number) => void; + onIndexChange?: (index: number) => void; +} + +const ITEM_WIDTH = Dimensions.get("window").width * 0.7; +const BLANK_ITEM_WIDTH = Dimensions.get("window").width * 0.15; + +export const Caroussel = ({ data, onPress, onIndexChange }: CarousselProps) => { + const scrollX = useRef(new Animated.Value(0)).current; + const finalData = [ + { + id: -1, + name: "empty-left", + }, + ...data, + { + id: -2, + name: "empty-right", + }, + ]; + + scrollX.addListener(({ value }) => { + const index = Math.round(value / ITEM_WIDTH); + if (index < 0 || index >= data.length) { + return; + } + onIndexChange && onIndexChange(index); + }); + return ( + item.id.toString()} + horizontal + showsHorizontalScrollIndicator={false} + decelerationRate={0} + initialNumToRender={1} + + bounces={false} + snapToInterval={ITEM_WIDTH} + onScroll={Animated.event([{ nativeEvent: { contentOffset: { x: scrollX } } }], { + useNativeDriver: true, + })} + renderItem={({ item, index }) => { + if (item.id === -1 || item.id === -2) { + return ; + } + const inputRange = [ + (index - 2) * ITEM_WIDTH, + (index - 1) * ITEM_WIDTH, + index * ITEM_WIDTH, + ]; + + const translateY = scrollX.interpolate({ + inputRange, + outputRange: [100, 0, 100], + }); + + const opacity = scrollX.interpolate({ + inputRange, + outputRange: [0.6, 1, 0.6], + }); + const scale = scrollX.interpolate({ + inputRange, + outputRange: [0.8, 1, 0.8], + }); + return ( + { + if (item.id !== -1 && item.id !== -2) { + onPress && onPress(item.id); + } + } + } + /> + ); + }} + /> + ); +}; diff --git a/mobile/src/common/components/caroussel/caroussel_tile.tsx b/mobile/src/common/components/caroussel/caroussel_tile.tsx new file mode 100644 index 00000000..65a61985 --- /dev/null +++ b/mobile/src/common/components/caroussel/caroussel_tile.tsx @@ -0,0 +1,77 @@ +import { memo } from "react"; +import { + Animated, + Dimensions, + Image, + Pressable, + Text, + TouchableOpacity, +} from "react-native"; +import { PlaceInfoEntity } from "../../../domain/entities/place_info_entity"; +import { Link } from "expo-router"; + +interface CarousselTileProps { + onPress?: () => void; + item: PlaceInfoEntity; + translateY: Animated.AnimatedInterpolation; + scale: Animated.AnimatedInterpolation; + opacity: Animated.AnimatedInterpolation; +} + +const ITEM_WIDTH = Dimensions.get("window").width * 0.7; +const BLANK_ITEM_WIDTH = Dimensions.get("window").width * 0.15; +const ITEM_HEIGHT = Dimensions.get("window").height * 0.7; + +export const CarousselTile = memo( + ({ translateY, scale, opacity, item, onPress }: CarousselTileProps) => { + return ( + + + + + + {item.name} + + + + + ); + } +); diff --git a/mobile/src/common/components/custom_tile_button.tsx b/mobile/src/common/components/custom_tile_button.tsx new file mode 100644 index 00000000..93719b02 --- /dev/null +++ b/mobile/src/common/components/custom_tile_button.tsx @@ -0,0 +1,66 @@ +import { ReactNode } from "react"; +import { TouchableOpacity, View, Text, StyleSheet } from "react-native"; +import { MaterialIcons } from "@expo/vector-icons"; +import { LIGTHT_THEME } from "../../constants/theme"; + +interface CustomTileButtonProps { + leadingIcon?: ReactNode; + title: string; + subtitle?: string; + onPress?: () => void; +} + +export const CustomTileButton = ({ + title, + onPress, + leadingIcon, + subtitle +}: CustomTileButtonProps) => { + return ( + + + {leadingIcon} + + {title} + { + subtitle && {subtitle} + } + + + + + ); +}; + +const styles = StyleSheet.create({ + account_option: { + flexDirection: "row", + alignItems: "center", + justifyContent: "space-between", + height: 60, + paddingHorizontal: 10, + borderTopWidth: 2, + borderTopColor: "#ccc", + backgroundColor: LIGTHT_THEME.color.white, + borderRadius: 5, + width: "100%", + }, + titleContainer: { + height: "100%", + alignItems: "flex-start", + justifyContent: "space-between", + paddingVertical: 10, + maxWidth: "85%", + + }, + title: { + fontSize: 16, + fontWeight: "700", + }, + subtitle: { + fontSize: 14, + color: "#777", + fontWeight: "500", + textAlign: "left", + } +}); diff --git a/mobile/src/common/components/form/date_text_input.tsx b/mobile/src/common/components/form/date_text_input.tsx new file mode 100644 index 00000000..dae598e5 --- /dev/null +++ b/mobile/src/common/components/form/date_text_input.tsx @@ -0,0 +1,42 @@ +import { useEffect, useState } from "react"; +import { CustomTextInput } from "./text_input"; +import { TouchableOpacity, View } from "react-native"; +import DateTimePickerModal from "react-native-modal-datetime-picker"; + +interface DateInputProps { + label: string; + onChangeText: (text: string) => void; + value: string; + onBlur?: () => void; + errors?: string; +} + +export const DateTextInput = ({label, onChangeText, value, onBlur, errors}: DateInputProps) => { + const [isVisible, setIsVisible] = useState(false); + useEffect(() => { + console.log(isVisible); + }, [isVisible]); + return ( + setIsVisible(true)}> + {}} + onBlur={onBlur} + errors={errors} + editable={false} + /> + { + onChangeText(data.toDateString()); + setIsVisible(false); + }} + onCancel={() => { + setIsVisible(false); + }} + isVisible={isVisible} + /> + + ); +}; diff --git a/mobile/src/common/components/form/text_input.tsx b/mobile/src/common/components/form/text_input.tsx new file mode 100644 index 00000000..55e7e733 --- /dev/null +++ b/mobile/src/common/components/form/text_input.tsx @@ -0,0 +1,98 @@ +import { useEffect, useRef } from "react"; +import { TextInput, Text, StyleSheet, View, Animated, TouchableOpacity } from "react-native"; +import { LIGTHT_THEME } from "../../../constants/theme"; + +interface TextInputProps { + isPassword?: boolean; + label: string; + onChangeText: (text: string) => void; + value: string; + onBlur?: () => void; + errors?: string; + type?: any; + editable?: boolean; +} + +export const CustomTextInput = (props: TextInputProps) => { + const { isPassword, label, type, onBlur, errors, value, editable,...rest } = props; + const labelFocusAnimation = useRef(new Animated.Value(value.length > 0 ? 1 : 0)).current; + const inputRef = useRef(null); + + const handleFocus = () => { + Animated.timing(labelFocusAnimation, { + toValue: 1, + duration: 200, + useNativeDriver: false, + }).start(); + }; + + const handleBlur = () => { + if (!props.value || props.value === "") { + Animated.timing(labelFocusAnimation, { + toValue: 0, + duration: 200, + useNativeDriver: false, + }).start(); + } + onBlur && onBlur(); + }; + + return ( + + + + {label} + + + + { + errors ? {errors} : + } + + ); +}; + +const styles = StyleSheet.create({ + main_container: { + width: "100%", + }, + container: { + width: "100%", + borderWidth: 1, + borderRadius: 5, + borderColor: "black", + height: 40, + alignItems: "center", + justifyContent: "center", + }, + input: { + width: "100%", + height: "100%", + paddingHorizontal: 10, + }, + label: { + position: "absolute", + left: 10, + zIndex: 1, + backgroundColor: LIGTHT_THEME.color.white, + }, +}); diff --git a/mobile/src/common/components/full_page_loader.tsx b/mobile/src/common/components/full_page_loader.tsx new file mode 100644 index 00000000..85879208 --- /dev/null +++ b/mobile/src/common/components/full_page_loader.tsx @@ -0,0 +1,9 @@ +import { ActivityIndicator, View } from "react-native"; + +export const FullPageLoader = () => { + return ( + + + + ); +} \ No newline at end of file -- GitLab