JIT
debugging typeerror in alarms screen component
import React, {useState, useEffect} from 'react'; import { TouchableOpacity, Text, View, FlatList, Alert, ActivityIndicator, ScrollView, RefreshControl, } from 'react-native'; import {useUser} from '../context/UserContext'; import ApiManager from '../services/ApiManager'; import ZoneScreenStyle from '../styles/ZoneScreenStyle'; const AlarmsScreen = ({navigation}) => { const [items, setItems] = useState([]); const [isFetching, setIsFetching] = useState(false); const [currentPage, setCurrentPage] = useState(1); const [hasMoreData, setHasMoreData] = useState(true); const {userDetails} = useUser(); useEffect(() => { if (userDetails?.profileDetails.customer_id) { getDeviceDetails(); } else { setItems([]); } }, [userDetails?.profileDetails.customer_id]); useEffect(() => { if (hasMoreData && !isFetching) { getDeviceDetails(); } }, [currentPage]); const getDeviceDetails = async (isManualRefresh = false) => { if (!userDetails?.profileDetails.customer_id) { console.log('User details not available yet or missing customer_id.'); setIsFetching(false); return; } console.log(`Fetching list... Manual Refresh: ${isManualRefresh}`); setIsFetching(true); let alarm_api_body = ''; apiBody = userDetails.profileDetails.customer_id !== null ? { customer_id: userDetails.profileDetails.customer_id, society_id: userDetails.profileDetails.society_id, } : { society_id: userDetails.profileDetails.society_id, member_id: userDetails.profileDetails.member_id, }; try { const listResponse = await ApiManager.getAlarmsDetails(alarm_api_body,currentPage); console.log('alarms received listResponse:', listResponse.Data); if (listResponse) { setItems(listResponse.Data.zonesList); } else { console.error( 'API did not return expected data structure:', listResponse, ); setItems([]); if (isManualRefresh) { Alert.alert( 'Error', 'Failed to fetch items. Invalid data format received.', ); } } } catch (error) { console.error('Fetch List Error in AlarmsScreen:', error); if (isManualRefresh) { Alert.alert( 'Fetch Failed', error.message || 'An unexpected error occurred while fetching items.', ); } setItems([]); } finally { setIsFetching(false); } }; const handleRefresh = () => { getDeviceDetails(true); }; const handleEndReached = () => { if (hasMoreData && !isFetching) { setCurrentPage(prevPage => prevPage + 1); getDeviceDetails(true); } }; const renderItem = ({item}) => ( <TouchableOpacity style={ZoneScreenStyle.zoneListView} onPress={() => {}}> <Text style={ZoneScreenStyle.itemTypeText}>{item.zone_name}</Text> </TouchableOpacity> ); const renderContent = () => { if (isFetching && items.length == 0) { return ( <View style={ZoneScreenStyle.centeredMessageContainer}> <ActivityIndicator size="large" color="#007bff" /> <Text style={ZoneScreenStyle.messageText}>Loading items...</Text> </View> ); } if (!isFetching && items.length === 0) { return ( <ScrollView refreshControl={ <RefreshControl onRefresh={() => { handleRefresh(); }} /> } contentContainerStyle={ZoneScreenStyle.centeredMessageContainer}> <Text style={ZoneScreenStyle.messageText}>No items found</Text> </ScrollView> ); } return ( <FlatList data={items} renderItem={renderItem} keyExtractor={item => item.id} contentContainerStyle={ZoneScreenStyle.listContentContainer} onRefresh={handleRefresh} refreshing={isFetching} onEndReached={() => { if (totalPages > 1 || currentPage != totalPages) { handleEndReached(); } }} /> ); }; return <View style={ZoneScreenStyle.safeArea}>{renderContent()}</View>; }; export default AlarmsScreen; got error TypeError: Cannot read property 'length' of undefined at if (isFetching && items.length == 0) {
Updated files
v1
import React, {useState, useEffect} from 'react'; import { TouchableOpacity, Text, View, FlatList, Alert, ActivityIndicator, Image, Dimensions, } from 'react-native'; import {useUser} from '../context/UserContext'; import ApiManager from '../services/ApiManager'; import ZoneScreenStyle from '../styles/ZoneScreenStyle'; import {COLORS} from '../styles/colors'; import {VLCPlayer} from 'react-native-vlc-media-player'; import {HOME, PLAY} from '../assets'; import Orientation from 'react-native-orientation-locker'; const CCTVScreen = ({navigation}) => { const [items, setItems] = useState([]); const [isFetching, setIsFetching] = useState(false); const [error, setError] = useState(false); const [onPlaying, setPlaying] = useState(true); const [playingIndex, setPlayingIndex] = useState(null); const [isFullScreen, setIsFullScreen] = useState(false); const [playing, setIsPlaying] = useState(false); const [videoUrl, setVideoUrl] = useState(''); const {userDetails} = useUser(); useEffect(() => { if (userDetails?.profileDetails.customer_id) { getCCTVDetails(); } else { setItems([]); } }, [userDetails?.profileDetails.customer_id]); // Re-run only if customer_id changes const getCCTVDetails = async (isManualRefresh = false) => { if (!userDetails?.profileDetails.customer_id) { console.log('User details not available yet or missing customer_id.'); setIsFetching(false); return; } console.log(`Fetching list... Manual Refresh: ${isManualRefresh}`); setIsFetching(true); const customer_id = userDetails.profileDetails.customer_id; try { const listResponse = await ApiManager.getcctvDetails(customer_id); console.log('zone received listResponse:', listResponse); if (listResponse) { setItems(listResponse.Data.camerasList); } else { console.error( 'API did not return expected data structure:', listResponse, ); setItems([]); if (isManualRefresh) { Alert.alert( 'Error', 'Failed to fetch items. Invalid data format received.', ); } } } catch (error) { console.error('Fetch List Error in CommunityScreen:', error); if (isManualRefresh) { Alert.alert( 'Fetch Failed', error.message || 'An unexpected error occurred while fetching items.', ); } setItems([]); } finally { setIsFetching(false); } }; const handleRefresh = () => { fetchList(true); }; const renderItem = ({item, index}) => { const isPlaying = playingIndex === index; console.log('item', item); return ( <TouchableOpacity activeOpacity={1} onPress={() => { setIsPlaying(!playing); if (!playing) { setTimeout(() => { setIsPlaying(false); }, 3000); } }} style={{ backgroundColor: COLORS.background_color, borderColor: COLORS.background_color, flex: 1, marginVertical: !isFullScreen ? 8 : '', marginHorizontal: !isFullScreen ? 10 : '', borderWidth: 1, borderRadius: 6, }}> {item.rtsp_stream_url != null && ( <View style={{ borderTopLeftRadius: 6, borderTopRightRadius: 6, backgroundColor: COLORS.black_color, borderColor: COLORS.background_color, }}> {!error ? ( <View> <VLCPlayer source={{ initType: 2, hwDecoderEnabled: 1, hwDecoderForced: 1, uri: item.rtsp_stream_url, // uri: 'rtsp://admin:advaint101@192.168.1.90:554/ISAPI/Streaming/Channels/101', }} autoplay={false} autoAspectRatio={true} resizeMode="cover" videoAspectRatio={'16:9'} isLive={true} autoReloadLive={true} style={{ width: '100%', height: isFullScreen ? Dimensions.get('window').height / 1.97 : 200, }} paused={!isPlaying} onError={() => setError(true)} /> <View style={{ position: 'absolute', top: '50%', left: '50%', zIndex: 10, transform: [{translateX: -25}, {translateY: -25}], }}> {isPlaying == false && ( <TouchableOpacity onPress={() => { if (playingIndex === index) { setPlayingIndex(null); setPlaying(false); } else { setPlayingIndex(index); setPlaying(true); } }}> <View style={{ width: 50, height: 50, backgroundColor: COLORS.white_color, borderRadius: 25, justifyContent: 'center', alignItems: 'center', }}> <Image source={PLAY} style={{height: 20, width: 20}} /> </View> </TouchableOpacity> )} {isPlaying && playing && ( <TouchableOpacity onPress={() => { setPlayingIndex(null); setPlaying(false); }}> <View style={{ width: 50, height: 50, backgroundColor: COLORS.white_color, borderRadius: 25, justifyContent: 'center', alignItems: 'center', }}> <Image source={HOME} style={{height: 20, width: 20}} /> </View> </TouchableOpacity> )} </View> </View> ) : ( <Text style={{paddingVertical: '25%'}}> cctv video unavailable </Text> )} </View> )} {!isFullScreen && ( <View style={{ flexDirection: 'row', justifyContent: 'space-between', padding: 10, }}> <Text>{item.name}</Text> <TouchableOpacity onPress={() => { setVideoUrl(item.rtsp_stream_url); handleFullScreenonPress(); }}> <Image style={{height: 20, width: 20}} source={HOME} /> </TouchableOpacity> </View> )} {isFullScreen && ( <TouchableOpacity style={{position: 'absolute', top: 10, right: 10}} onPress={handleFullScreenonPress}> <Image style={{height: 20, width: 20}} source={HOME} /> </TouchableOpacity> )} </TouchableOpacity> ); }; const renderContent = () => { if (isFetching && items.length == 0) { return ( <View style={ZoneScreenStyle.centeredMessageContainer}> <ActivityIndicator size="large" color="#007bff" /> <Text style={ZoneScreenStyle.messageText}>Loading items...</Text> </View> ); } if (!isFetching && items.length === 0) { return ( <View style={ZoneScreenStyle.centeredMessageContainer}> <Text style={ZoneScreenStyle.messageText}> No community items found. Tap 'Add' to create one. </Text> </View> ); } return ( <FlatList data={items} renderItem={renderItem} keyExtractor={item => item.id} contentContainerStyle={ZoneScreenStyle.listContentContainer} onRefresh={handleRefresh} refreshing={isFetching} /> ); }; const handleFullScreenonPress = () => { if (isFullScreen == false) { setIsFullScreen(true); Orientation.lockToLandscape(); } else { setIsFullScreen(false); Orientation.lockToPortrait(); } }; return ( <View style={ZoneScreenStyle.safeArea}> {renderContent()} {isFullScreen && ( <TouchableOpacity activeOpacity={1} onPress={() => { setIsPlaying(!playing); if (!playing) { setTimeout(() => { setIsPlaying(false); }, 3000); } }} style={{bottom: 5}}> <VLCPlayer source={{ initType: 2, hwDecoderEnabled: 1, hwDecoderForced: 1, uri: videoUrl, }} autoplay={true} autoAspectRatio={true} resizeMode="cover" videoAspectRatio={'16:8'} isLive={true} autoReloadLive={true} style={{ width: '100%', height: '100%', marginTop: 5, }} paused={!playingIndex} onError={() => setError(true)} /> {onPlaying == false && ( <TouchableOpacity style={{ width: 50, height: 50, backgroundColor: COLORS.white_color, borderRadius: 25, justifyContent: 'center', alignItems: 'center', position: 'absolute', alignSelf: 'center', top: '45%', }} onPress={() => { setPlaying(true); setPlayingIndex(true); }}> <Image source={PLAY} style={{height: 20, width: 20}} /> </TouchableOpacity> )} {onPlaying && playing && ( <TouchableOpacity style={{ width: 50, height: 50, backgroundColor: COLORS.white_color, borderRadius: 25, justifyContent: 'center', alignItems: 'center', position: 'absolute', alignSelf: 'center', top: '45%', }} onPress={() => { setPlayingIndex(null); setPlaying(false); }}> <Image source={HOME} style={{height: 20, width: 20}} /> </TouchableOpacity> )} <TouchableOpacity style={{position: 'absolute', bottom: 10, right: 10}} onPress={() => { handleFullScreenonPress(); setPlayingIndex(null); setPlaying(false); }}> <Image style={{height: 20, width: 20}} source={HOME} /> </TouchableOpacity> </TouchableOpacity> )} </View> ); }; export default CCTVScreen; i want to add top tab bar here in this screen one tab with title live videos and other with past videos make changes and provide updated src folder
<jitProject id="cctv-screen-with-top-tab-bar" title="CCTVScreen with Top Tab Bar"> <jitFile type="file" filePath="src/screens/CCTVScreen.js"> import React, {useState, useEffect, useCallback} from 'react'; import { TouchableOpacity, Text, View, FlatList, Alert, ActivityIndicator, Image, Dimensions, StyleSheet, } from 'react-native'; import {useUser} from '../context/UserContext'; import ApiManager from '../services/ApiManager'; import ZoneScreenStyle from '../styles/ZoneScreenStyle'; import {COLORS} from '../styles/colors'; import {VLCPlayer} from 'react-native-vlc-media-player'; import {HOME, PLAY} from '../assets'; import Orientation from 'react-native-orientation-locker'; import {TabView, SceneMap, TabBar} from 'react-native-tab-view';

const initialLayout = {width: Dimensions.get('window').width};

const LiveVideosRoute = () => { const [items, setItems] = useState([]); const [isFetching, setIsFetching] = useState(false); const [error, setError] = useState(false); const [playingIndex, setPlayingIndex] = useState(null); const [isFullScreen, setIsFullScreen] = useState(false); const [videoUrl, setVideoUrl] = useState(''); const [playing, setIsPlaying] = useState(false); const {userDetails} = useUser();

useEffect(() => { if (userDetails?.profileDetails.customer_id) { getCCTVDetails(); } else { setItems([]); } }, [userDetails?.profileDetails.customer_id]);

const getCCTVDetails = async (isManualRefresh = false) => { if (!userDetails?.profileDetails.customer_id) { console.log('User details not available yet or missing customer_id.'); setIsFetching(false); return; }

console.log(`Fetching list... Manual Refresh: ${isManualRefresh}`);
setIsFetching(true);

const customer_id = userDetails.profileDetails.customer_id;

try {
  const listResponse = await ApiManager.getcctvDetails(customer_id);
  console.log('zone received listResponse:', listResponse);

  if (listResponse) {
    setItems(listResponse.Data.camerasList);
  } else {
    console.error(
      'API did not return expected data structure:',
      listResponse,
    );
    setItems([]);
    if (isManualRefresh) {
      Alert.alert(
        'Error',
        'Failed to fetch items. Invalid data format received.',
      );
    }
  }
} catch (error) {
  console.error('Fetch List Error in CommunityScreen:', error);
  if (isManualRefresh) {
    Alert.alert(
      'Fetch Failed',
      error.message || 'An unexpected error occurred while fetching items.',
    );
  }
  setItems([]);
} finally {
  setIsFetching(false);
}

};

const handleRefresh = () => { getCCTVDetails(true); };

const renderItem = ({item, index}) => { const isPlaying = playingIndex === index;

return (
  <TouchableOpacity
    activeOpacity={1}
    onPress={() => {
      setIsPlaying(!playing);
      if (!playing) {
        setTimeout(() => {
          setIsPlaying(false);
        }, 3000);
      }
    }}
    style={styles.listItemContainer}>
    {item.rtsp_stream_url != null && (
      <View style={styles.videoContainer}>
        {!error ? (
          <View>
            <VLCPlayer
              source={{
                initType: 2,
                hwDecoderEnabled: 1,
                hwDecoderForced: 1,
                uri: item.rtsp_stream_url,
              }}
              autoplay={false}
              autoAspectRatio={true}
              resizeMode="cover"
              videoAspectRatio={'16:9'}
              isLive={true}
              autoReloadLive={true}
              style={styles.videoPlayer}
              paused={!isPlaying}
              onError={() => setError(true)}
            />
            <View style={styles.playButtonContainer}>
              {isPlaying == false && (
                <TouchableOpacity
                  onPress={() => {
                    if (playingIndex === index) {
                      setPlayingIndex(null);
                      setPlaying(false);
                    } else {
                      setPlayingIndex(index);
                      setPlaying(true);
                    }
                  }}>
                  <View style={styles.playButton}>
                    <Image source={PLAY} style={styles.playIcon} />
                  </View>
                </TouchableOpacity>
              )}

              {isPlaying && playing && (
                <TouchableOpacity
                  onPress={() => {
                    setPlayingIndex(null);
                    setPlaying(false);
                  }}>
                  <View style={styles.playButton}>
                    <Image source={HOME} style={styles.playIcon} />
                  </View>
                </TouchableOpacity>
              )}
            </View>
          </View>
        ) : (
          <Text style={styles.videoUnavailableText}>
            cctv video unavailable
          </Text>
        )}
      </View>
    )}

    {!isFullScreen && (
      <View style={styles.videoDetailsContainer}>
        <Text style={styles.cameraName}>{item.name}</Text>
        <TouchableOpacity
          onPress={() => {
            setVideoUrl(item.rtsp_stream_url);
            handleFullScreenonPress();
          }}>
          <Image style={styles.fullScreenIcon} source={HOME} />
        </TouchableOpacity>
      </View>
    )}
    {isFullScreen && (
      <TouchableOpacity
        style={styles.fullScreenExitButton}
        onPress={handleFullScreenonPress}>
        <Image style={styles.fullScreenIcon} source={HOME} />
      </TouchableOpacity>
    )}
  </TouchableOpacity>
);

};

const renderContent = () => { if (isFetching && items.length == 0) { return ( <View style={ZoneScreenStyle.centeredMessageContainer}> <ActivityIndicator size="large" color="#007bff" /> <Text style={ZoneScreenStyle.messageText}>Loading items...</Text> </View> ); }

if (!isFetching && items.length === 0) {
  return (
    <View style={ZoneScreenStyle.centeredMessageContainer}>
      <Text style={ZoneScreenStyle.messageText}>No live videos found.</Text>
    </View>
  );
}

return (
  <FlatList
    data={items}
    renderItem={renderItem}
    keyExtractor={item => item.id}
    contentContainerStyle={ZoneScreenStyle.listContentContainer}
    onRefresh={handleRefresh}
    refreshing={isFetching}
  />
);

};

const handleFullScreenonPress = () => { if (isFullScreen == false) { setIsFullScreen(true); Orientation.lockToLandscape(); } else { setIsFullScreen(false); Orientation.lockToPortrait(); } };

return <View style={{flex: 1}}>{renderContent()}</View>; };

const PastVideosRoute = () => ( <View style={[ZoneScreenStyle.centeredMessageContainer, {backgroundColor: COLORS.white_color}]}> <Text style={ZoneScreenStyle.messageText}>Past Videos Content</Text> </View> );

const renderScene = SceneMap({ live: LiveVideosRoute, past: PastVideosRoute, });

const CCTVScreen = ({navigation}) => { const [index, setIndex] = useState(0); const [routes] = useState([ {key: 'live', title: 'Live Videos'}, {key: 'past', title: 'Past Videos'}, ]);

const renderTabBar = props => ( <TabBar {...props} indicatorStyle={{backgroundColor: COLORS.primary_color}} style={{backgroundColor: COLORS.white_color}} renderLabel={({route, focused, color}) => ( <Text style={{color: focused ? COLORS.primary_color : COLORS.grey_color, margin: 8, fontWeight: 'bold'}}> {route.title} </Text> )} /> );

return ( <TabView navigationState={{index, routes}} renderScene={renderScene} onIndexChange={setIndex} initialLayout={initialLayout} renderTabBar={renderTabBar} /> ); };

const styles = StyleSheet.create({ listItemContainer: { backgroundColor: COLORS.background_color, borderColor: COLORS.background_color, flex: 1, marginVertical: 8, marginHorizontal: 10, borderWidth: 1, borderRadius: 6, }, videoContainer: { borderTopLeftRadius: 6, borderTopRightRadius: 6, backgroundColor: COLORS.black_color, borderColor: COLORS.background_color, }, videoPlayer: { width: '100%', height: 200, }, playButtonContainer: { position: 'absolute', top: '50%', left: '50%', zIndex: 10, transform: [{translateX: -25}, {translateY: -25}], }, playButton: { width: 50, height: 50, backgroundColor: COLORS.white_color, borderRadius: 25, justifyContent: 'center', alignItems: 'center', }, playIcon: { height: 20, width: 20, }, videoUnavailableText: { paddingVertical: '25%', textAlign: 'center', color: COLORS.white_color }, videoDetailsContainer: { flexDirection: 'row', justifyContent: 'space-between', padding: 10, }, cameraName: { color: COLORS.text_color }, fullScreenIcon: { height: 20, width: 20, }, fullScreenExitButton: { position: 'absolute', top: 10, right: 10, }, });

export default CCTVScreen; _