79837217

Date: 2025-12-03 18:42:55
Score: 5.5
Natty:
Report link

muchachos no creo que vean esto pero tengo un problema el cual no se si estoy haciendo bien el componente

import React from 'react';
import { StyleSheet, View, TouchableOpacity, Image, Alert, Platform, PermissionsAndroid } from 'react-native';
import MapView, { Marker, Region, PROVIDER_GOOGLE } from 'react-native-maps';
import MapViewDirections from 'react-native-maps-directions';
import Config from 'react-native-config';
// import { fetchLatestPosition } from '../../api/traccar';
import Geolocation from '@react-native-community/geolocation';
// import AppLayout from './layout/AppLayout';
// import { useSafeAreaInsets } from 'react-native-safe-area-context';
import MarkerOrigin from '../../assets/markers/marker-origin.svg';
import MarkerDestination from '../../assets/markers/makerr-destination-own.svg';
import type { Coordinate } from '../FooterRoutes/routesData';
import MarkerMe from '../../assets/markers/waypoint.svg';
const CarSport = require('../../assets/icons/carro-deportivo.png');

type MarkerItem = {
  id: number;
  title: string;
  coordinate: Coordinate;
  type: 'origin' | 'destination' | 'waypoint';
  status?: 'red' | 'green' | 'conductor';
  nameRol?: string;
};

type Props = {
  markers?: MarkerItem[];
  initialRegion?: Region;
  renderTopBar?: React.ReactNode;
  bottomContent?: (args: {
    collapsed: boolean;
    toggle: () => void;
    onRouteSelect: (stops: Coordinate[]) => void;
    onModeChange: (isDetails: boolean) => void;
  }) => React.ReactNode;
  driver?: Coordinate;
  origin?: Coordinate;
  destination?: Coordinate;
  waypoints?: Coordinate[];
  driverIconColor?: string;
  driverDeviceId?: string | number;
};

const getMapsApiKey = (): string => {
  return (Config as any)?.GOOGLE_MAPS_API_KEY || (Config as any)?.Maps_API_KEY || '';
};

// Esta función simulará la obtención de la dirección real a partir de las coordenadas
const getAddressFromCoordinates = async (latitude: number, longitude: number): Promise<string> => {
  const apiKey = getMapsApiKey();
  if (!apiKey) {
    console.warn("GOOGLE_MAPS_API_KEY is missing. Cannot perform geocoding.");
    return `Lat: ${latitude.toFixed(5)}, Lon: ${longitude.toFixed(5)}`;
  }

  try {
    const response = await fetch(`https://maps.googleapis.com/maps/api/geocode/json?latlng=${latitude},${longitude}&key=${apiKey}`);
    const data = await response.json();

    if (data.status === 'OK' && data.results.length > 0) {
      return data.results[0].formatted_address;
    } else {
      return 'Dirección no encontrada';
    }
  } catch (error) {
    console.error("Geocoding failed:", error);
    return 'Error de servicio de geocodificación';
  }
};

// -----------------------------------------------------------------------------

export default function MapComponent({
  markers = [],
  initialRegion,
  renderTopBar,
  bottomContent,
  origin,
  destination,
  driver: _driver,
  waypoints,
  driverIconColor,
  driverDeviceId,
}: Props) {

  const uberLightMapStyle = [
    { elementType: 'geometry', stylers: [{ color: '#FAFAFA' }] },
    { featureType: 'water', elementType: 'geometry', stylers: [{ color: '#F7F8FA' }] },
    { featureType: 'landscape', elementType: 'geometry', stylers: [{ color: '#FAFAFA' }] },
    { featureType: 'landscape.man_made', elementType: 'geometry', stylers: [{ color: '#F9FAFB' }] },
    { featureType: 'landscape.natural', elementType: 'geometry', stylers: [{ color: '#FAFAFA' }] },
    { featureType: 'poi', stylers: [{ visibility: 'off' }] },
    { featureType: 'poi.park', stylers: [{ visibility: 'off' }] },
    { featureType: 'transit', stylers: [{ visibility: 'off' }] },
    { featureType: 'road', elementType: 'geometry', stylers: [{ color: '#FFFFFF' }] },
    { featureType: 'road.highway', elementType: 'geometry', stylers: [{ color: '#F7F7F7' }] },
    { featureType: 'road.arterial', elementType: 'geometry', stylers: [{ color: '#FFFFFF' }] },
    { featureType: 'road.local', elementType: 'geometry', stylers: [{ color: '#FFFFFF' }] },
    { featureType: 'road', elementType: 'geometry.stroke', stylers: [{ color: '#EEEEEE' }] },
    { featureType: 'road', elementType: 'labels.icon', stylers: [{ visibility: 'off' }] },
    { featureType: 'road', elementType: 'labels.text.stroke', stylers: [{ visibility: 'off' }] },
    { featureType: 'road', elementType: 'labels.text.fill', stylers: [{ color: '#BDBDBD' }] },
    { featureType: 'administrative', elementType: 'labels.text.fill', stylers: [{ color: '#B8B8B8' }] },
    { featureType: 'administrative', elementType: 'geometry', stylers: [{ visibility: 'off' }] },
  ];

  const mapRef = React.useRef<MapView>(null);
  const [activeRoute, setActiveRoute] = React.useState<{ origin?: Coordinate; destination?: Coordinate; driver?: Coordinate; waypoints?: Coordinate[]; }>({});
  const [routeStopMarkers, setRouteStopMarkers] = React.useState<MarkerItem[]>([]);
  const [routeCoords, setRouteCoords] = React.useState<Coordinate[]>([]);
  const [collapsed, setCollapsed] = React.useState(true);
  const [isFollowing, setIsFollowing] = React.useState(false);
  const waypointColors = [ '#10B981', '#EF4444'];
  const googleApiKey = getMapsApiKey();

  const fallback: Region = {
    latitude: -34.6037,
    longitude: -58.3816,
    latitudeDelta: 0.01,
    longitudeDelta: 0.01,
  };

  const [region] = React.useState<Region>(initialRegion ?? fallback);
  const [userLocation, setUserLocation] = React.useState<Coordinate | null>(null);
  const [showUserDot, setShowUserDot] = React.useState(true);
  const userLocationRef = React.useRef<Coordinate | null>(null);
  const [_driverLive, _setDriverLive] = React.useState<Coordinate | null>(null);
  const hasInitialCenterRef = React.useRef(false);
  const [directionsErrorNotified, setDirectionsErrorNotified] = React.useState(false);

  React.useEffect(() => {
    if (userLocation) {
      console.log('UserLocation', { latitude: userLocation.latitude, longitude: userLocation.longitude });
    }
  }, [userLocation]);

  const directionsData = React.useMemo(() => {
    const googleKey = googleApiKey || (Config as any).GOOGLE_MAPS_API_KEY;
    const o = activeRoute.origin ?? origin;
    const d = activeRoute.destination ?? destination;
    const w = activeRoute.waypoints ?? waypoints;
    return { googleKey, o, d, w };
  }, [googleApiKey, activeRoute, origin, destination, waypoints]);

  // Centra el mapa en la ruta
  const fitToRoute = React.useCallback(() => {
    const allPoints = [
      ...(activeRoute.origin ? [activeRoute.origin] : origin ? [origin] : []),
      ...(activeRoute.waypoints || waypoints || []),
      ...(activeRoute.destination ? [activeRoute.destination] : destination ? [destination] : []),
    ].filter(Boolean) as Coordinate[];

    if (allPoints.length < 1) return;

    if (allPoints.length === 1) {
      mapRef.current?.animateToRegion({
        latitude: allPoints[0].latitude,
        longitude: allPoints[0].longitude,
        latitudeDelta: 0.01,
        longitudeDelta: 0.01,
      }, 600);
      return;
    }

    mapRef.current?.fitToCoordinates(allPoints, {
      edgePadding: { top: 200, right: 200, bottom: 100, left: 110 },
      animated: true,
    });
  }, [activeRoute, origin, destination, waypoints]);

  React.useEffect(() => {}, [routeCoords, fitToRoute, isFollowing]);

  React.useEffect(() => {}, [_driver]);

  React.useEffect(() => {
    if (initialRegion && !userLocation) {
      console.log('MapComponent initialRegion', initialRegion);
      const { latitude, longitude, latitudeDelta, longitudeDelta } = initialRegion;
      mapRef.current?.animateToRegion({
        latitude,
        longitude,
        latitudeDelta,
        longitudeDelta,
      }, 600);
    }
  }, [initialRegion, userLocation]);

  // Solicitamos permisos de ubicación
  React.useEffect(() => {
    const init = async () => {
      if (Platform.OS === 'android') {
        const res = await PermissionsAndroid.requestMultiple([
          PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
          PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION,
        ]);
        console.log('MapComponent android permissions', res);
        const grantedFine = res[PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION] === PermissionsAndroid.RESULTS.GRANTED;
        const grantedCoarse = res[PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION] === PermissionsAndroid.RESULTS.GRANTED;
        if (!grantedFine && !grantedCoarse) return;
      } else {
        Geolocation.setRNConfiguration({ skipPermissionRequests: false, authorizationLevel: 'whenInUse' } as any);
        Geolocation.requestAuthorization();
      }

      Geolocation.getCurrentPosition(
        pos => {
          console.log('MapComponent getCurrentPosition', pos?.coords);
          const { latitude, longitude } = pos.coords;
          const coord = { latitude, longitude };
          setUserLocation(coord);
          userLocationRef.current = coord;
          setShowUserDot(false);
          if (!hasInitialCenterRef.current) {
            hasInitialCenterRef.current = true;
            mapRef.current?.animateToRegion({ latitude, longitude, latitudeDelta: 0.01, longitudeDelta: 0.01 }, 600);
          }
        },
        _err => { console.log('MapComponent getCurrentPosition error', _err); },
        { enableHighAccuracy: true, timeout: 20000, maximumAge: 0 }
      );
    };
    init();
  }, []);

  const isRouteActive = React.useMemo(() => {
    const o = activeRoute.origin ?? origin;
    const d = activeRoute.destination ?? destination;
    return !!(o && d);
  }, [activeRoute, origin, destination]);

  React.useEffect(() => {
    let watchId: any = null;
    let intervalId: any = null;
        // @ts-ignore
    const updateFromPosition = (pos: Geolocation.GeoPosition) => {
      const { latitude, longitude } = pos.coords as any;
      const coord = { latitude, longitude };
      setUserLocation(coord);
      userLocationRef.current = coord;
      setShowUserDot(false);
      if (!hasInitialCenterRef.current) {
        hasInitialCenterRef.current = true;
        mapRef.current?.animateToRegion({ latitude, longitude, latitudeDelta: 0.01, longitudeDelta: 0.01 }, 600);
      }
    };

    const startLowFrequency = () => {
      Geolocation.getCurrentPosition(
        p => updateFromPosition(p as any),
        e => console.log('MapComponent low-frequency error', e),
        { enableHighAccuracy: true, timeout: 20000, maximumAge: 0 }
      );
      intervalId = setInterval(() => {
        Geolocation.getCurrentPosition(
          p => updateFromPosition(p as any),
          e => console.log('MapComponent low-frequency interval error', e),
          { enableHighAccuracy: true, timeout: 20000, maximumAge: 0 }
        );
      }, 600000);
    };

    const startHighFrequency = () => {
      watchId = Geolocation.watchPosition(
        p => updateFromPosition(p as any),
        e => console.log('MapComponent high-frequency watch error', e),
        { enableHighAccuracy: true, distanceFilter: 0, interval: 3000 }
      );
    };

    if (isRouteActive) {
      startHighFrequency();
    } else {
      startLowFrequency();
    }

    return () => {
      if (watchId !== null) Geolocation.clearWatch(watchId);
      if (intervalId !== null) clearInterval(intervalId as any);
    };
  }, [isRouteActive]);

  React.useEffect(() => {}, [driverDeviceId]);

  React.useEffect(() => {
    if (directionsData.o && directionsData.d && !directionsData.googleKey && !directionsErrorNotified) {
      setDirectionsErrorNotified(true);
      Alert.alert('Ruta', 'falla en la implementacion para trazar direcciones');
    }
  }, [directionsData, directionsErrorNotified]);

  React.useEffect(() => {
    if (isFollowing) {
      const c = userLocation;
      if (c) {
        mapRef.current?.animateToRegion({
          latitude: c.latitude,
          longitude: c.longitude,
          latitudeDelta: 0.01,
          longitudeDelta: 0.01,
        }, 400);
      }
    }
  }, [isFollowing, userLocation]);

  // APLICACIÓN DE STOPS CON GEOCODING
  const applyRouteStops = React.useCallback(
    async (stops: Coordinate[]) => {
      const allStops = (stops || []).filter(Boolean);
      const routeStopsUniq = allStops.filter((s, idx, arr) => arr.findIndex(t => t.latitude === s.latitude && t.longitude === s.longitude) === idx);

      if (routeStopsUniq.length < 2) {
        setActiveRoute({});
        setRouteStopMarkers([]);
        setRouteCoords([]);
        return;
      }

      const geocodingPromises = routeStopsUniq.map(async (c) => {
        const address = await getAddressFromCoordinates(c.latitude, c.longitude);
        return { ...c, address };
      });

      const enrichedStops = await Promise.all(geocodingPromises);

      const primaryRouteStops = enrichedStops.filter(s => !s.status);
      const extraStops = enrichedStops.filter(s => !!s.status);

      if (primaryRouteStops.length < 2) {
        setActiveRoute({});
        setRouteStopMarkers([]);
        setRouteCoords([]);
        return;
      }

      const originStop = primaryRouteStops[0];
      const destinationStop = primaryRouteStops[primaryRouteStops.length - 1];
      const wp = primaryRouteStops.slice(1, primaryRouteStops.length - 1);

      setActiveRoute({ origin: originStop, destination: destinationStop, waypoints: wp });

      const nextMarkers: MarkerItem[] = [
        ...wp.map((c, i) => ({ id: 100 + i, title: c.name || c.address || `Punto ${i + 1}`, coordinate: c, type: 'waypoint' as const })),
        { id: 2, title: destinationStop.name || destinationStop.address || 'Destino', coordinate: destinationStop, type: 'destination' },
        ...extraStops.map((c, i) => ({ id: 200 + i, title: c.name || c.address || (c.status === 'red' ? 'Conductor' : 'Punto'), coordinate: c, type: 'waypoint' as const })),
      ];

      setRouteStopMarkers(nextMarkers);
    },
    [],
  );

  React.useEffect(() => {
    const o = activeRoute.origin ?? origin;
    const d = activeRoute.destination ?? destination;
    const w = activeRoute.waypoints ?? waypoints;
    if (!o || !d) {
      setRouteCoords([]);
      return;
    }
    setRouteCoords([o, ...(w ?? []), d]);
  }, [activeRoute, origin, destination, waypoints]);

  return (
    <View style={styles.container}>
      {renderTopBar ? <View style={styles.topOverlay}>{renderTopBar}</View> : null}

      <MapView
        ref={mapRef}
        style={styles.map}
        initialRegion={region}
        provider={PROVIDER_GOOGLE}
        mapType="standard"
        customMapStyle={uberLightMapStyle}
        showsUserLocation={showUserDot}
        showsMyLocationButton={false}
        onUserLocationChange={e => {
          const coord = (e && e.nativeEvent && e.nativeEvent.coordinate) || ({} as any);
          const { latitude, longitude } = coord;
          console.log('MapComponent onUserLocationChange', coord);
          if (typeof latitude === 'number' && typeof longitude === 'number') {
            const c = { latitude, longitude };
            setUserLocation(c);
            if (!hasInitialCenterRef.current) {
              hasInitialCenterRef.current = true;
              mapRef.current?.animateToRegion({
                latitude,
                longitude,
                latitudeDelta: 0.01,
                longitudeDelta: 0.01,
              }, 400);
            } else if (isFollowing) {
              mapRef.current?.animateToRegion({
                latitude,
                longitude,
                latitudeDelta: 0.01,
                longitudeDelta: 0.01,
              }, 400);
            }
          }
        }}
      >

        {markers.map(m => (
          <Marker key={m.id} coordinate={m.coordinate} title={m.title} />
        ))}

        {(_driver ?? userLocation) && (
          <Marker coordinate={(_driver ?? userLocation) as Coordinate} anchor={{ x: 0.5, y: 0.5 }} tracksViewChanges={false}>
            <Image source={CarSport} style={[styles.carMarker, driverIconColor ? { tintColor: driverIconColor } : null]} />
          </Marker>
        )}

        {routeStopMarkers.map((marker, idx) => (
          <Marker
            key={marker.id}
            coordinate={marker.coordinate}
            title={marker.title}
            anchor={{ x: 0.5, y: 0.5 }}
            tracksViewChanges={false}
          >
            {marker.type === 'origin' ? (
              <MarkerOrigin width={24} height={24} color="#2563EB" />
            ) : marker.type === 'destination' ? (
              <MarkerDestination width={30} height={50} fill="#2563EB" color="#2563EB" />
            ) : marker.nameRol === 'conductor' ? (
              <MarkerMe width={22} height={22} fill="#000" />
            ) : (
              <MarkerOrigin
                width={22}
                height={22}
                color={waypointColors[Math.max(0, (idx - 1) % waypointColors.length)]}
              />
            )}
          </Marker>
        ))}

        {(userLocation || directionsData.o) && directionsData.d && directionsData.googleKey ? (
          <MapViewDirections
            origin={userLocation ?? directionsData.o}
            destination={directionsData.d}
            waypoints={directionsData.w}
            apikey={directionsData.googleKey as string}
            strokeWidth={5}
            strokeColor="#707070"
            mode="DRIVING"
            onReady={() => {}}
            onError={_errorMessage => {
              Alert.alert('Ruta', 'No se pudo trazar la ruta con Google Directions');
            }}
          />
        ) : null}

      </MapView>

      <View style={styles.followButtonContainer}>
        <TouchableOpacity
          style={styles.followButton}
          onPress={async () => {
            const c = userLocation;
            if (c) {
              setIsFollowing(true);
              mapRef.current?.animateToRegion({
                latitude: c.latitude,
                longitude: c.longitude,
                latitudeDelta: 0.01,
                longitudeDelta: 0.01,
              }, 400);
              return;
            }

            Geolocation.getCurrentPosition(
              pos => {
                const { latitude, longitude } = pos.coords;
                const coord = { latitude, longitude };
                setUserLocation(coord);
                setIsFollowing(true);
                mapRef.current?.animateToRegion({ latitude, longitude, latitudeDelta: 0.01, longitudeDelta: 0.01 }, 400);
              },
              _err => {
                const id = Geolocation.watchPosition(
                  p => {
                    const { latitude, longitude } = p.coords;
                    const coord2 = { latitude, longitude };
                    setUserLocation(coord2);
                    setIsFollowing(true);
                    mapRef.current?.animateToRegion({ latitude, longitude, latitudeDelta: 0.01, longitudeDelta: 0.01 }, 400);
                    Geolocation.clearWatch(id);
                  },
                  () => {},
                  { enableHighAccuracy: true, distanceFilter: 0, interval: 2000 }
                );
              },
              { enableHighAccuracy: true, timeout: 20000, maximumAge: 0 }
            );
          }}
        >
          <Image
            source={{
              uri: 'https://img.icons8.com/?size=100&id=zydjAKYE3RWr&format=png&color=000000',
            }}
            style={styles.aimstyles}
          />
        </TouchableOpacity>

        {bottomContent?.({
          collapsed,
          toggle: () => setCollapsed(v => !v),
          onRouteSelect: applyRouteStops,
          onModeChange: (_v: boolean) => {},
        })}

      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1 },
  map: { flex: 1 },
  topOverlay: {
    position: 'absolute', top: 0, left: 0, right: 0, zIndex: 40
  },
  mapFallback: {
    position: 'absolute', top: 0, left: 0, right: 0, bottom: 0,
    alignItems: 'center', justifyContent: 'center'
  },
  mapFallbackText: {
    color: '#333', backgroundColor: '#FFFFFFEE',
    paddingHorizontal: 12, paddingVertical: 8, borderRadius: 8
  },

  followButtonContainer: {
    width: '100%',
    position: 'absolute',
    bottom: 0,
    paddingHorizontal: 7,
    flexDirection: 'column',
    justifyContent: 'center',
    zIndex: 50,
  },
  followButton: {
    alignSelf: 'flex-end',
    backgroundColor: '#fff',
    borderRadius: 30,
    padding: 8,
    elevation: 6,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.25,
    shadowRadius: 4,
    marginBottom: 8,
  },
  aimstyles: { width: 28, height: 28, tintColor: '#707070' },
  reportsButtonContainer: { position: 'absolute', zIndex: 30 },
  reportsButton: { backgroundColor: '#6D28D9', paddingVertical: 6, paddingHorizontal: 12, borderRadius: 8 },
  reportsButtonText: { color: '#fff', fontSize: 12, fontWeight: '600' },
  carMarker: { width: 64, height: 36, resizeMode: 'contain' },
});
Reasons:
  • Blacklisted phrase (2): tengo
  • Blacklisted phrase (2): estoy
  • RegEx Blacklisted phrase (2): encontrada
  • Long answer (-1):
  • Has code block (-0.5):
  • Low reputation (1):
Posted by: Matias Delgado