@@ -6,15 +6,13 @@ import {
66 ScrollView ,
77 RefreshControl ,
88 TouchableOpacity ,
9- StatusBar ,
10- Platform ,
119 Switch ,
1210 ActivityIndicator ,
1311} from 'react-native' ;
1412import { useRouter } from 'expo-router' ;
1513import { MaterialIcons } from '@expo/vector-icons' ;
1614import { useTheme } from '@/theme' ;
17- import { Card , CardHeader , CollapsibleCard , InfoRow , SignalBar , SignalMeter , DataPieChart , SpeedGauge , ThemedAlertHelper , WebViewLogin , BandSelectionModal , getSelectedBandsDisplay } from '@/components' ;
15+ import { Card , CardHeader , CollapsibleCard , InfoRow , SignalBar , SignalMeter , SpeedGauge , ThemedAlertHelper , WebViewLogin , BandSelectionModal , getSelectedBandsDisplay , UsageCard , SignalCard } from '@/components' ;
1816import { useAuthStore } from '@/stores/auth.store' ;
1917import { useModemStore } from '@/stores/modem.store' ;
2018import { ModemService } from '@/services/modem.service' ;
@@ -30,6 +28,29 @@ import {
3028} from '@/utils/helpers' ;
3129import { useTranslation } from '@/i18n' ;
3230
31+ // Helper to determine signal quality based on thresholds
32+ const getSignalQuality = (
33+ value : number ,
34+ thresholds : { excellent : number ; good : number ; fair : number ; poor : number } ,
35+ reverseScale : boolean
36+ ) : 'excellent' | 'good' | 'fair' | 'poor' | 'unknown' => {
37+ if ( isNaN ( value ) ) return 'unknown' ;
38+
39+ if ( reverseScale ) {
40+ // Higher value is better (e.g., RSSI: -60 is better than -90)
41+ if ( value >= thresholds . excellent ) return 'excellent' ;
42+ if ( value >= thresholds . good ) return 'good' ;
43+ if ( value >= thresholds . fair ) return 'fair' ;
44+ return 'poor' ;
45+ } else {
46+ // Higher value is better in normal scale (e.g., SINR: 20 is better than 5)
47+ if ( value >= thresholds . excellent ) return 'excellent' ;
48+ if ( value >= thresholds . good ) return 'good' ;
49+ if ( value >= thresholds . fair ) return 'fair' ;
50+ return 'poor' ;
51+ }
52+ } ;
53+
3354export default function HomeScreen ( ) {
3455 const router = useRouter ( ) ;
3556 const { colors, typography, spacing } = useTheme ( ) ;
@@ -506,58 +527,40 @@ export default function HomeScreen() {
506527 { /* Signal Strength Card */ }
507528 { signalInfo && ( signalInfo . rssi || signalInfo . rsrp ) ? (
508529 < CollapsibleCard title = { t ( 'home.signalInfo' ) } >
509- { signalInfo . rssi && (
510- < SignalMeter
511- label = "RSSI"
512- value = { signalInfo . rssi }
513- unit = "dBm"
514- min = { - 110 }
515- max = { - 50 }
516- thresholds = { { excellent : - 65 , good : - 75 , fair : - 85 , poor : - 95 } }
517- reverseScale = { true }
518- />
519- ) }
520- { signalInfo . rsrp && (
521- < SignalMeter
522- label = "RSRP"
523- value = { signalInfo . rsrp }
524- unit = "dBm"
525- min = { - 140 }
526- max = { - 70 }
527- thresholds = { { excellent : - 80 , good : - 90 , fair : - 100 , poor : - 110 } }
528- reverseScale = { true }
529- />
530- ) }
531- { signalInfo . rsrq && (
532- < SignalMeter
533- label = "RSRQ"
534- value = { signalInfo . rsrq }
535- unit = "dB"
536- min = { - 20 }
537- max = { - 3 }
538- thresholds = { { excellent : - 5 , good : - 9 , fair : - 12 , poor : - 15 } }
539- reverseScale = { true }
540- />
541- ) }
542- { signalInfo . sinr && (
543- < SignalMeter
544- label = "SINR"
545- value = { signalInfo . sinr }
546- unit = "dB"
547- min = { - 5 }
548- max = { 30 }
549- thresholds = { { excellent : 20 , good : 13 , fair : 6 , poor : 0 } }
550- reverseScale = { false }
551- />
552- ) }
553-
554- { /* Additional Info */ }
555- { ( signalInfo . band || signalInfo . cellId ) && (
556- < View style = { { marginTop : spacing . sm , paddingTop : spacing . sm , borderTopWidth : 1 , borderTopColor : colors . border } } >
557- { signalInfo . band && < InfoRow label = { t ( 'home.band' ) } value = { signalInfo . band } /> }
558- { signalInfo . cellId && < InfoRow label = { t ( 'home.cellId' ) } value = { signalInfo . cellId } /> }
559- </ View >
560- ) }
530+ < SignalCard
531+ title = { t ( 'home.signalStrength' ) }
532+ badge = { getSignalStrength ( signalInfo . rssi ) }
533+ color = "blue"
534+ icon = "signal-cellular-alt"
535+ metrics = { [
536+ ...( signalInfo . rssi ? [ {
537+ label : 'RSSI' ,
538+ value : signalInfo . rssi ,
539+ unit : 'dBm' ,
540+ quality : getSignalQuality ( parseFloat ( signalInfo . rssi ) , { excellent : - 65 , good : - 75 , fair : - 85 , poor : - 95 } , true ) ,
541+ } ] : [ ] ) ,
542+ ...( signalInfo . rsrp ? [ {
543+ label : 'RSRP' ,
544+ value : signalInfo . rsrp ,
545+ unit : 'dBm' ,
546+ quality : getSignalQuality ( parseFloat ( signalInfo . rsrp ) , { excellent : - 80 , good : - 90 , fair : - 100 , poor : - 110 } , true ) ,
547+ } ] : [ ] ) ,
548+ ...( signalInfo . rsrq ? [ {
549+ label : 'RSRQ' ,
550+ value : signalInfo . rsrq ,
551+ unit : 'dB' ,
552+ quality : getSignalQuality ( parseFloat ( signalInfo . rsrq ) , { excellent : - 5 , good : - 9 , fair : - 12 , poor : - 15 } , true ) ,
553+ } ] : [ ] ) ,
554+ ...( signalInfo . sinr ? [ {
555+ label : 'SINR' ,
556+ value : signalInfo . sinr ,
557+ unit : 'dB' ,
558+ quality : getSignalQuality ( parseFloat ( signalInfo . sinr ) , { excellent : 20 , good : 13 , fair : 6 , poor : 0 } , false ) ,
559+ } ] : [ ] ) ,
560+ ] }
561+ band = { signalInfo . band ? getLteBandInfo ( signalInfo . band ) : undefined }
562+ cellId = { signalInfo . cellId }
563+ />
561564 </ CollapsibleCard >
562565 ) : (
563566 < CollapsibleCard title = { t ( 'home.signalInfo' ) } >
@@ -580,43 +583,35 @@ export default function HomeScreen() {
580583 { /* Divider */ }
581584 < View style = { { height : 1 , backgroundColor : colors . border , marginVertical : spacing . md } } />
582585
583- { /* Data Usage Grid - 2 columns */ }
584- < View style = { styles . dataUsageGrid } >
585- { /* Current Session */ }
586- < View style = { styles . dataUsageItem } >
587- < DataPieChart
588- title = { t ( 'home.currentSession' ) }
589- subtitle = { formatDuration ( trafficStats . currentConnectTime ) }
590- download = { trafficStats . currentDownload }
591- upload = { trafficStats . currentUpload }
592- formatValue = { formatBytes }
593- compact
594- />
595- </ View >
586+ { /* Current Session Card */ }
587+ < UsageCard
588+ title = { t ( 'home.currentSession' ) }
589+ badge = { formatDuration ( trafficStats . currentConnectTime ) }
590+ download = { trafficStats . currentDownload }
591+ upload = { trafficStats . currentUpload }
592+ color = "cyan"
593+ icon = "schedule"
594+ />
596595
597- { /* Monthly */ }
598- < View style = { styles . dataUsageItem } >
599- < DataPieChart
600- title = { t ( 'home.monthlyUsage' ) }
601- subtitle = { new Date ( ) . toLocaleDateString ( undefined , { month : 'long' , year : 'numeric' } ) }
602- download = { trafficStats . monthDownload }
603- upload = { trafficStats . monthUpload }
604- formatValue = { formatBytes }
605- compact
606- />
607- </ View >
608- </ View >
596+ { /* Monthly Usage Card */ }
597+ < UsageCard
598+ title = { t ( 'home.monthlyUsage' ) }
599+ badge = { new Date ( ) . toLocaleDateString ( undefined , { month : 'short' } ) . toUpperCase ( ) }
600+ download = { trafficStats . monthDownload }
601+ upload = { trafficStats . monthUpload }
602+ color = "emerald"
603+ icon = "calendar-today"
604+ />
609605
610- { /* Total Usage - centered below */ }
611- < View style = { styles . totalUsageContainer } >
612- < DataPieChart
613- title = { t ( 'home.trafficStats' ) }
614- subtitle = { formatDuration ( trafficStats . totalConnectTime ) }
615- download = { trafficStats . totalDownload }
616- upload = { trafficStats . totalUpload }
617- formatValue = { formatBytes }
618- />
619- </ View >
606+ { /* Total Traffic Card */ }
607+ < UsageCard
608+ title = { t ( 'home.totalUsage' ) }
609+ badge = { formatDuration ( trafficStats . totalConnectTime ) }
610+ download = { trafficStats . totalDownload }
611+ upload = { trafficStats . totalUpload }
612+ color = "amber"
613+ icon = "storage"
614+ />
620615 </ CollapsibleCard >
621616 ) }
622617
0 commit comments