From 0a955502303c7d40506f2b61413309994bd85e39 Mon Sep 17 00:00:00 2001 From: yashwin-foxy Date: Fri, 22 Aug 2025 14:57:50 +0530 Subject: [PATCH] navigation isue resolved --- .../Dashboard/components/PredictionCard.tsx | 22 +++- .../Dashboard/components/PredictionsList.tsx | 117 +++++++++++------- app/modules/Dashboard/hooks/usePredictions.ts | 9 +- .../Dashboard/redux/predictionsSlice.ts | 7 ++ .../Dashboard/screens/DashboardScreen.tsx | 7 +- app/theme/shadows.ts | 2 +- 6 files changed, 108 insertions(+), 56 deletions(-) diff --git a/app/modules/Dashboard/components/PredictionCard.tsx b/app/modules/Dashboard/components/PredictionCard.tsx index a543a24..090499f 100644 --- a/app/modules/Dashboard/components/PredictionCard.tsx +++ b/app/modules/Dashboard/components/PredictionCard.tsx @@ -126,11 +126,14 @@ export const PredictionCard: React.FC = ({ {/* Header Section */} - + {prediction.patientdetails.Name || 'Unknown Patient'} - - {prediction.patientdetails.PatID} • {prediction.patientdetails.PatAge} • {prediction.patientdetails.PatSex} + + {prediction.patientdetails.PatID} + + + {prediction.patientdetails.PatAge} • {prediction.patientdetails.PatSex} @@ -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, diff --git a/app/modules/Dashboard/components/PredictionsList.tsx b/app/modules/Dashboard/components/PredictionsList.tsx index b85c493..2ac14f5 100644 --- a/app/modules/Dashboard/components/PredictionsList.tsx +++ b/app/modules/Dashboard/components/PredictionsList.tsx @@ -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 = ({ +export const PredictionsList: React.FC = React.memo(({ onPredictionPress, }) => { const { @@ -57,6 +63,14 @@ export const PredictionsList: React.FC = ({ 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 = ({ * * 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 = ({ // 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 ( @@ -184,46 +198,48 @@ export const PredictionsList: React.FC = ({ {currentPredictions.length} prediction{currentPredictions.length !== 1 ? 's' : ''} found {activeTab === 'with-feedback' && ( - {' • '}{currentPredictions.filter(p => p.feedbacks && p.feedbacks.length > 0).length} with feedback + {' • '}{feedbackCount} with feedback )} )} - {/* Horizontal Scrolling Predictions */} - ( - - handlePredictionPress(item)} - /> - - )} - keyExtractor={(item) => item.id.toString()} - contentContainerStyle={styles.listContainer} - showsHorizontalScrollIndicator={true} - showsVerticalScrollIndicator={false} - horizontal={true} - scrollEnabled={true} - refreshControl={ - - } - ListEmptyComponent={renderEmptyState} - /> + {/* Horizontal Scrolling Predictions */} + + ( + + handlePredictionPress(item)} + /> + + )} + keyExtractor={(item) => item.id.toString()} + contentContainerStyle={styles.listContainer} + showsHorizontalScrollIndicator={false} + showsVerticalScrollIndicator={false} + horizontal={true} + scrollEnabled={true} + refreshControl={ + + } + ListEmptyComponent={renderEmptyState} + /> + )} ); -}; +}); // ============================================================================ // 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 }, }); diff --git a/app/modules/Dashboard/hooks/usePredictions.ts b/app/modules/Dashboard/hooks/usePredictions.ts index 3d1b12d..514f83b 100644 --- a/app/modules/Dashboard/hooks/usePredictions.ts +++ b/app/modules/Dashboard/hooks/usePredictions.ts @@ -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]); diff --git a/app/modules/Dashboard/redux/predictionsSlice.ts b/app/modules/Dashboard/redux/predictionsSlice.ts index 44e0b94..d59e5a3 100644 --- a/app/modules/Dashboard/redux/predictionsSlice.ts +++ b/app/modules/Dashboard/redux/predictionsSlice.ts @@ -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; }; diff --git a/app/modules/Dashboard/screens/DashboardScreen.tsx b/app/modules/Dashboard/screens/DashboardScreen.tsx index daffe32..4fa15a7 100644 --- a/app/modules/Dashboard/screens/DashboardScreen.tsx +++ b/app/modules/Dashboard/screens/DashboardScreen.tsx @@ -638,9 +638,8 @@ export const DashboardScreen: React.FC = ({ // 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 = ({ console.log('Feedback submitted, refreshing dashboard...'); } } - }); + ); console.log('Navigation successful to FeedbackDetailScreen'); } catch (error) { diff --git a/app/theme/shadows.ts b/app/theme/shadows.ts index 53f3047..0b763ee 100644 --- a/app/theme/shadows.ts +++ b/app/theme/shadows.ts @@ -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,