Commit fcf97c10 authored by Lorenzo Trujillo Rojas's avatar Lorenzo Trujillo Rojas
Browse files

Se cambio la estructura de la aplicación

parent ec99d3e9
Loading
Loading
Loading
Loading
+77 −0
Original line number Diff line number Diff line
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 (
    <View style={styles.container}>
      <View style={styles.sliderContainer}>
        <Text style={styles.hour_text}>
          {millisecondsToHourFormat(position)}
        </Text>
        <Slider
          thumbTintColor="gray"
          minimumTrackTintColor={LIGTHT_THEME.color.white}
          minimumValue={0}
          maximumValue={duration}
          value={position}
          onValueChange={onValueChange}
          style={styles.slider}
        />
        <Text style={styles.hour_text}>
          {millisecondsToHourFormat(duration)}
        </Text>
      </View>
      <TouchableOpacity onPress={togglePlay}>
        <Feather
          name={isPlaying ? "pause-circle" : "play-circle"}
          size={54}
          color={LIGTHT_THEME.color.white}
        />
      </TouchableOpacity>
    </View>
  );
};

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",
  },
});
+92 −0
Original line number Diff line number Diff line
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 (
    <Animated.FlatList
      data={finalData}
      keyExtractor={(item) => 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 <View style={{ width: BLANK_ITEM_WIDTH }} />;
        }
        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 (
          <CarousselTile
            opacity={opacity}
            scale={scale}
            translateY={translateY}
            item={item}
            onPress={() => {
              if (item.id !== -1 && item.id !== -2) {
                onPress && onPress(item.id);
              }
            }
            }
          />
        );
      }}
    />
  );
};
+77 −0
Original line number Diff line number Diff line
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<number>;
  scale: Animated.AnimatedInterpolation<number>;
  opacity: Animated.AnimatedInterpolation<number>;
}

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 (
      <Pressable onPress={onPress}>
        <Animated.View
          style={{
            width: ITEM_WIDTH,
            height: ITEM_HEIGHT,
            padding: 10,
            alignItems: "center",
            justifyContent: "center",
          }}
        >
          <Animated.View
            style={{
              transform: [{ translateY }, { scale }],
              opacity,
              height: "90%",
              width: "100%",
              overflow: "hidden",
              borderRadius: 20,
              alignItems: "center",
              justifyContent: "center",
              elevation: 10,
              borderWidth: 7,
              borderColor: "white",
            }}
          >
            <Animated.Image
              source={{ uri: item.imageUri }}
              style={{
                width: "100%",
                height: "100%",
              }}
            />
            <Text
              style={{
                position: "absolute",
                top: 10,
                color: "white",
                fontSize: 20,
                fontWeight: "bold",
                textAlign: "center",
              }}
            >
              {item.name}
            </Text>
          </Animated.View>
        </Animated.View>
      </Pressable>
    );
  }
);
+66 −0
Original line number Diff line number Diff line
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 (
    <TouchableOpacity onPress={onPress} style={styles.account_option}>
      <View style={{ flexDirection: "row", gap: 20, alignItems: "center" }}>
        {leadingIcon}
        <View style={styles.titleContainer} >
          <Text style={styles.title} numberOfLines={1} >{title}</Text>
          {
            subtitle && <Text style={styles.subtitle} numberOfLines={1} >{subtitle}</Text>
          }
        </View>
      </View>
      <MaterialIcons name="keyboard-arrow-right" size={30} color="black" />
    </TouchableOpacity>
  );
};

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",
  }
});
+42 −0
Original line number Diff line number Diff line
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 (
    <TouchableOpacity onPress={() => setIsVisible(true)}>
      <CustomTextInput
        label={label}
        value={value}
        onChangeText={() => {}}
        onBlur={onBlur}
        errors={errors}
        editable={false}
      />
      <DateTimePickerModal
        mode="date"
        onConfirm={(data) => {
          onChangeText(data.toDateString());
          setIsVisible(false);
        }}
        onCancel={() => {
          setIsVisible(false);
        }}
        isVisible={isVisible}
      />
    </TouchableOpacity>
  );
};
Loading