navigation isue resolved

This commit is contained in:
yashwin-foxy 2025-08-22 14:57:50 +05:30
parent 41de1bbb25
commit 0a95550230
6 changed files with 108 additions and 56 deletions

View File

@ -126,11 +126,14 @@ export const PredictionCard: React.FC<PredictionCardProps> = ({
{/* Header Section */}
<View style={styles.header}>
<View style={styles.patientInfo}>
<Text style={styles.patientName}>
<Text style={styles.patientName} numberOfLines={1}>
{prediction.patientdetails.Name || 'Unknown Patient'}
</Text>
<Text style={styles.patientDetails}>
{prediction.patientdetails.PatID} {prediction.patientdetails.PatAge} {prediction.patientdetails.PatSex}
<Text style={styles.patientDetails} numberOfLines={1} ellipsizeMode="head">
{prediction.patientdetails.PatID}
</Text>
<Text style={styles.patientDetailsSecondary}>
{prediction.patientdetails.PatAge} {prediction.patientdetails.PatSex}
</Text>
</View>
@ -255,7 +258,12 @@ const styles = StyleSheet.create({
borderRadius: theme.borderRadius.large,
padding: theme.spacing.md,
marginBottom: theme.spacing.md,
...theme.shadows.primary,
// Custom shadow properties to ensure visibility
shadowColor: '#000000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,
elevation: 3,
},
header: {
@ -278,6 +286,12 @@ const styles = StyleSheet.create({
},
patientDetails: {
fontSize: theme.typography.fontSize.bodySmall,
fontFamily: theme.typography.fontFamily.medium,
color: theme.colors.textPrimary,
marginBottom: theme.spacing.xs,
},
patientDetailsSecondary: {
fontSize: theme.typography.fontSize.bodySmall,
fontFamily: theme.typography.fontFamily.regular,
color: theme.colors.textSecondary,

View File

@ -5,7 +5,7 @@
* Copyright (c) Spurrin Innovations. All rights reserved.
*/
import React from 'react';
import React, { useMemo, useCallback } from 'react';
import {
View,
Text,
@ -44,8 +44,14 @@ interface PredictionsListProps {
* - Loading states
* - Error handling
* - Empty states
*
* Performance Optimizations:
* - Both datasets (with/without feedback) are pre-loaded upfront
* - Tab switching is instant - no filtering needed
* - React.memo prevents unnecessary re-renders
* - useCallback optimizes event handlers
*/
export const PredictionsList: React.FC<PredictionsListProps> = ({
export const PredictionsList: React.FC<PredictionsListProps> = React.memo(({
onPredictionPress,
}) => {
const {
@ -57,6 +63,14 @@ export const PredictionsList: React.FC<PredictionsListProps> = ({
refreshPredictions,
} = usePredictions();
// Performance optimization: Memoize feedback count calculation
const feedbackCount = useMemo(() => {
if (activeTab === 'with-feedback') {
return currentPredictions.filter(p => p.feedbacks?.length > 0).length;
}
return 0;
}, [activeTab, currentPredictions]);
// ============================================================================
// UTILITY FUNCTIONS
// ============================================================================
@ -66,18 +80,18 @@ export const PredictionsList: React.FC<PredictionsListProps> = ({
*
* Purpose: Switch between radiologist feedback status tabs
*/
const handleTabSwitch = (tab: 'with-feedback' | 'without-feedback') => {
const handleTabSwitch = useCallback((tab: 'with-feedback' | 'without-feedback') => {
switchTab(tab);
};
}, [switchTab]);
/**
* Handle Prediction Press
*
* Purpose: Handle when a prediction card is pressed
*/
const handlePredictionPress = (prediction: PredictionData) => {
const handlePredictionPress = useCallback((prediction: PredictionData) => {
onPredictionPress(prediction);
};
}, [onPredictionPress]);
/**
* Render Tab Button
@ -150,15 +164,15 @@ export const PredictionsList: React.FC<PredictionsListProps> = ({
// RENDER
// ============================================================================
// Debug logging to see current state
console.log('🔍 PredictionsList render debug:');
console.log('Active tab:', activeTab);
console.log('Current predictions count:', currentPredictions.length);
console.log('Current predictions sample:', currentPredictions.slice(0, 2).map(p => ({
id: p.id,
has_feedback: p.has_provided_feedback,
feedbacks_count: p.feedbacks?.length || 0
})));
// Performance optimization: Only log when needed (development mode)
// Note: Tab switching is now instant due to pre-loaded datasets
if (__DEV__ && currentPredictions.length > 0) {
console.log('🔍 PredictionsList render debug:', {
activeTab,
count: currentPredictions.length,
performance: 'Instant tab switching - datasets pre-loaded'
});
}
return (
<View style={styles.container}>
@ -184,46 +198,48 @@ export const PredictionsList: React.FC<PredictionsListProps> = ({
{currentPredictions.length} prediction{currentPredictions.length !== 1 ? 's' : ''} found
{activeTab === 'with-feedback' && (
<Text style={styles.feedbackCount}>
{' • '}{currentPredictions.filter(p => p.feedbacks && p.feedbacks.length > 0).length} with feedback
{' • '}{feedbackCount} with feedback
</Text>
)}
</Text>
</View>
)}
{/* Horizontal Scrolling Predictions */}
<FlatList
data={currentPredictions}
renderItem={({ item }) => (
<View style={styles.predictionCardWrapper}>
<PredictionCard
prediction={item}
onPress={() => handlePredictionPress(item)}
/>
</View>
)}
keyExtractor={(item) => item.id.toString()}
contentContainerStyle={styles.listContainer}
showsHorizontalScrollIndicator={true}
showsVerticalScrollIndicator={false}
horizontal={true}
scrollEnabled={true}
refreshControl={
<RefreshControl
refreshing={currentLoadingState}
onRefresh={refreshPredictions}
colors={[theme.colors.primary]}
tintColor={theme.colors.primary}
/>
}
ListEmptyComponent={renderEmptyState}
/>
{/* Horizontal Scrolling Predictions */}
<View style={styles.listWrapper}>
<FlatList
data={currentPredictions}
renderItem={({ item }) => (
<View style={styles.predictionCardWrapper}>
<PredictionCard
prediction={item}
onPress={() => handlePredictionPress(item)}
/>
</View>
)}
keyExtractor={(item) => item.id.toString()}
contentContainerStyle={styles.listContainer}
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
horizontal={true}
scrollEnabled={true}
refreshControl={
<RefreshControl
refreshing={currentLoadingState}
onRefresh={refreshPredictions}
colors={[theme.colors.primary]}
tintColor={theme.colors.primary}
/>
}
ListEmptyComponent={renderEmptyState}
/>
</View>
</>
)}
</View>
</View>
);
};
});
// ============================================================================
// STYLES
@ -271,10 +287,19 @@ const styles = StyleSheet.create({
contentContainer: {
flex: 1,
minHeight: 0,
},
listWrapper: {
// flex: 1,
minHeight: 0, // Prevent flex overflow
marginBottom: theme.spacing.md, // Add bottom margin for shadow visibility
},
listContainer: {
padding: theme.spacing.md,
padding: 2,
paddingBottom: theme.spacing.xxl, // Increased bottom padding for shadow visibility
alignItems: 'flex-start',
},
@ -366,7 +391,9 @@ const styles = StyleSheet.create({
predictionCardWrapper: {
marginRight: theme.spacing.md,
marginBottom: theme.spacing.md, // Add bottom margin for shadow visibility
width: 280, // Uniform width for all cards
// Height will be determined by content naturally
},
});

View File

@ -53,12 +53,14 @@ export const usePredictions = () => {
const activeTab = useAppSelector(selectActiveTab);
const searchQuery = useAppSelector(selectSearchQuery);
// Performance optimization: Load both datasets upfront
const predictionsWithFeedback = useAppSelector(selectPredictionsWithFeedback);
const predictionsWithoutFeedback = useAppSelector(selectPredictionsWithoutFeedback);
const isLoading = useAppSelector(selectIsLoading);
const error = useAppSelector(selectError);
// Performance optimization: Direct dataset selection - no filtering needed
const currentPredictions = useAppSelector(selectCurrentPredictions);
const currentLoadingState = useAppSelector(selectCurrentLoadingState);
const currentError = useAppSelector(selectCurrentError);
@ -74,6 +76,7 @@ export const usePredictions = () => {
* Switch Active Tab
*
* Purpose: Change between feedback tabs
* Performance: Instant switching - no filtering needed as both datasets are pre-loaded
*/
const switchTab = useCallback((tab: PredictionTabType) => {
dispatch(setActiveTab(tab));
@ -132,12 +135,14 @@ export const usePredictions = () => {
/**
* Auto-fetch data when component mounts or token changes
* Performance optimization: Load both datasets upfront to eliminate tab switching delays
*/
useEffect(() => {
if (!authToken) return;
// Only fetch if we don't have any predictions yet
if (predictionsWithFeedback.length === 0 && predictionsWithoutFeedback.length === 0) {
// Performance optimization: Always fetch if either dataset is empty
// This ensures both datasets are loaded upfront for instant tab switching
if (predictionsWithFeedback.length === 0 || predictionsWithoutFeedback.length === 0) {
dispatch(fetchAllPredictions(authToken));
}
}, [authToken, predictionsWithFeedback.length, predictionsWithoutFeedback.length, dispatch]);

View File

@ -218,9 +218,16 @@ export const selectError = (state: { predictions: PredictionsState }) => state.p
export const selectCurrentPredictions = (state: { predictions: PredictionsState }) => {
const { activeTab, predictionsWithFeedback, predictionsWithoutFeedback } = state.predictions;
// Performance optimization: Direct dataset selection instead of filtering
return activeTab === 'with-feedback' ? predictionsWithFeedback : predictionsWithoutFeedback;
};
// Performance optimization: Pre-computed selectors for instant tab switching
export const selectPredictionsForTab = (state: { predictions: PredictionsState }, tab: PredictionTabType) => {
const { predictionsWithFeedback, predictionsWithoutFeedback } = state.predictions;
return tab === 'with-feedback' ? predictionsWithFeedback : predictionsWithoutFeedback;
};
export const selectCurrentLoadingState = (state: { predictions: PredictionsState }) => {
return state.predictions.isLoading;
};

View File

@ -638,9 +638,8 @@ export const DashboardScreen: React.FC<DashboardScreenProps> = ({
// Navigate to FeedbackDetailScreen with required parameters
navigation.navigate('Patients', {
screen: 'FeedbackDetail',
params: {
navigation.navigate('FeedbackDetail',
{
patientId: prediction.patid,
patientName: prediction.patientdetails.Name || 'Unknown Patient',
seriesNumber: prediction.prediction.processing_info.filename || 'Unknown Series',
@ -685,7 +684,7 @@ export const DashboardScreen: React.FC<DashboardScreenProps> = ({
console.log('Feedback submitted, refreshing dashboard...');
}
}
});
);
console.log('Navigation successful to FeedbackDetailScreen');
} catch (error) {

View File

@ -38,7 +38,7 @@ export const shadows = {
},
primary: {
shadowColor: colors.primary,
shadowOffset: { width: 0, height: 4 },
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.3,
shadowRadius: 8,
elevation: 6,