@@ -17,6 +17,8 @@ import androidx.compose.ui.Alignment
1717import androidx.compose.ui.Modifier
1818import androidx.compose.ui.draw.clip
1919import androidx.compose.ui.graphics.Color
20+ import androidx.compose.ui.graphics.Brush
21+ import kotlinx.coroutines.launch
2022import androidx.compose.ui.graphics.vector.ImageVector
2123import androidx.compose.ui.platform.LocalContext
2224import androidx.compose.ui.text.font.FontWeight
@@ -25,7 +27,12 @@ import androidx.compose.ui.unit.dp
2527import androidx.compose.ui.unit.sp
2628import androidx.core.content.ContextCompat
2729import com.example.ui.theme.*
28- import kotlinx.coroutines.launch
30+ import java.text.SimpleDateFormat
31+ import java.util.*
32+ import androidx.compose.ui.layout.ContentScale
33+ import androidx.compose.foundation.Image
34+ import androidx.compose.ui.res.painterResource
35+ import androidx.compose.foundation.shape.CircleShape
2936
3037@SuppressLint(" MissingPermission" )
3138@Composable
@@ -35,7 +42,8 @@ fun HomeScreen(
3542 onNavigateToMarket : () -> Unit = {},
3643 onNavigateToChat : () -> Unit = {},
3744 onNavigateToAutopilot : () -> Unit = {},
38- onNavigateToFinance : () -> Unit = {}
45+ onNavigateToFinance : () -> Unit = {},
46+ onNavigateToSavedReports : () -> Unit = {}
3947) {
4048 val context = LocalContext .current
4149 val scope = rememberCoroutineScope()
@@ -64,38 +72,71 @@ fun HomeScreen(
6472
6573 val tickerItems by PriceTickerService .tickerItems.collectAsState()
6674 val tickerLoading by PriceTickerService .isLoading.collectAsState()
75+ val now = remember { SimpleDateFormat (" d MMM yyyy | h:mm a" , Locale .getDefault()).format(Date ()) }
6776
6877 Box (modifier = modifier.fillMaxSize().background(Color (0xFF0D1208 ))) {
6978 Column (Modifier .fillMaxSize().verticalScroll(scrollState).padding(bottom = 100 .dp)) { // padding for nav bar
7079
71- // Top Weather Pill
72- Box (Modifier .fillMaxWidth().statusBarsPadding().padding(horizontal = 16 .dp, vertical = 12 .dp)) {
80+ // Hero Section
81+ Box (Modifier .fillMaxWidth().height(260 .dp)) {
82+ Image (
83+ painter = painterResource(id = R .drawable.farm_bg),
84+ contentDescription = " Farm background" ,
85+ contentScale = ContentScale .Crop ,
86+ modifier = Modifier .fillMaxSize()
87+ )
88+ // Gradient overlay
7389 Box (
74- Modifier .fillMaxWidth().clip(RoundedCornerShape (16 .dp)).background(Color (0xFF141A0A ))
75- .border(1 .dp, Color (0x30C8E837 ), RoundedCornerShape (16 .dp))
76- .clickable { if (! hasLocation) locLauncher.launch(Manifest .permission.ACCESS_FINE_LOCATION ) }
77- .padding(horizontal = 16 .dp, vertical = 12 .dp)
90+ Modifier .fillMaxSize().background(
91+ Brush .verticalGradient(listOf (Color (0x88000000 ), Color (0xFF0D1208 )))
92+ )
93+ )
94+ // Header row
95+ Row (
96+ Modifier .fillMaxWidth().statusBarsPadding().padding(16 .dp),
97+ Arrangement .SpaceBetween , Alignment .CenterVertically
7898 ) {
79- Row (Modifier .fillMaxWidth(), horizontalArrangement = Arrangement .SpaceBetween , verticalAlignment = Alignment .CenterVertically ) {
80- if (weatherLoading) {
81- Text (" Fetching live weather..." , color = NuKropTextMuted , fontSize = 12 .sp)
82- } else if (weather != null ) {
83- val w = weather!!
84- Row (verticalAlignment = Alignment .CenterVertically ) {
85- Text (w.emoji, fontSize = 20 .sp)
86- Spacer (Modifier .width(8 .dp))
87- Column {
88- Text (" ${w.temperature} C" , color = NuKropText , fontSize = 16 .sp, fontWeight = FontWeight .Bold )
89- Text (" Feels ${w.feelsLike} C" , color = NuKropTextMuted , fontSize = 10 .sp)
99+ Row (verticalAlignment = Alignment .CenterVertically , horizontalArrangement = Arrangement .spacedBy(10 .dp)) {
100+ Box (Modifier .size(44 .dp).clip(CircleShape )
101+ .background(Brush .linearGradient(listOf (NuKropGreen , NuKropAccent ))),
102+ Alignment .Center
103+ ) { Icon (Icons .Filled .Person , null , tint = NuKropDark , modifier = Modifier .size(24 .dp)) }
104+ Column {
105+ Text (" Good ${greeting()} , Farmer!" , fontSize = 14 .sp, fontWeight = FontWeight .Bold , color = Color .White )
106+ Text (now, fontSize = 10 .sp, color = Color .White .copy(alpha = 0.7f ), maxLines = 1 , overflow = TextOverflow .Ellipsis )
107+ }
108+ }
109+ }
110+
111+ // Weather Pill inside Hero
112+ Box (Modifier .align(Alignment .BottomCenter ).padding(16 .dp).fillMaxWidth()) {
113+ Box (
114+ Modifier .fillMaxWidth().clip(RoundedCornerShape (16 .dp)).background(Color (0x99000000 ))
115+ .border(1 .dp, Color (0x40C8E837 ), RoundedCornerShape (16 .dp))
116+ .clickable { if (! hasLocation) locLauncher.launch(Manifest .permission.ACCESS_FINE_LOCATION ) }
117+ .padding(horizontal = 16 .dp, vertical = 12 .dp)
118+ ) {
119+ Row (Modifier .fillMaxWidth(), horizontalArrangement = Arrangement .SpaceBetween , verticalAlignment = Alignment .CenterVertically ) {
120+ if (weatherLoading) {
121+ Text (" Fetching live weather..." , color = Color .White .copy(0.7f ), fontSize = 12 .sp)
122+ } else if (weather != null ) {
123+ val w = weather!!
124+ Row (verticalAlignment = Alignment .CenterVertically ) {
125+ Text (w.emoji, fontSize = 20 .sp)
126+ Spacer (Modifier .width(8 .dp))
127+ Column {
128+ Text (" ${w.temperature} C" , color = Color .White , fontSize = 16 .sp, fontWeight = FontWeight .Bold )
129+ Text (" Feels ${w.feelsLike} C" , color = Color .White .copy(0.7f ), fontSize = 10 .sp)
130+ }
90131 }
132+ Row (horizontalArrangement = Arrangement .spacedBy(12 .dp)) {
133+ WeatherDetail (Icons .Default .WaterDrop , " ${w.humidity} %" )
134+ WeatherDetail (Icons .Default .Air , " ${w.windSpeed} km/h" )
135+ WeatherDetail (Icons .Default .Water , " ${w.precipitation} mm" )
136+ }
137+ } else {
138+ Text (weatherError ? : " Weather unavailable" , color = NuKropWarning , fontSize = 12 .sp)
91139 }
92- Row (horizontalArrangement = Arrangement .spacedBy(12 .dp)) {
93- WeatherDetail (Icons .Default .WaterDrop , " ${w.humidity} %" )
94- WeatherDetail (Icons .Default .Air , " ${w.windSpeed} km/h" )
95- WeatherDetail (Icons .Default .Water , " ${w.precipitation} mm" )
96- }
97- } else {
98- Text (weatherError ? : " Weather unavailable" , color = NuKropWarning , fontSize = 12 .sp)
99140 }
100141 }
101142 }
@@ -149,7 +190,7 @@ fun HomeScreen(
149190 QuickActionTile (Modifier .weight(1f ), Icons .Filled .Navigation , " Field Navigator" , " GPS Route & Coverage" , Color (0xFFE57373 ), onNavigateToAutopilot)
150191 }
151192 Row (horizontalArrangement = Arrangement .spacedBy(10 .dp)) {
152- QuickActionTile (Modifier .weight(0.5f ), Icons .Filled .Download , " Saved Reports" , " View downloaded files" , Color (0xFF81C784 )) {}
193+ QuickActionTile (Modifier .weight(0.5f ), Icons .Filled .Download , " Saved Reports" , " View downloaded files" , Color (0xFF81C784 ), onNavigateToSavedReports)
153194 Spacer (Modifier .weight(0.5f ))
154195 }
155196 }
@@ -215,10 +256,14 @@ fun WeatherDetail(icon: ImageVector, text: String) {
215256 Row (verticalAlignment = Alignment .CenterVertically ) {
216257 Icon (icon, contentDescription = null , tint = NuKropAccent , modifier = Modifier .size(12 .dp))
217258 Spacer (Modifier .width(4 .dp))
218- Text (text, color = NuKropText , fontSize = 10 .sp, fontWeight = FontWeight .Bold )
259+ Text (text, color = Color . White , fontSize = 10 .sp, fontWeight = FontWeight .Bold )
219260 }
220261}
221262
263+ private fun greeting (): String = when (Calendar .getInstance().get(Calendar .HOUR_OF_DAY )) {
264+ in 0 .. 11 -> " Morning" ; in 12 .. 16 -> " Afternoon" ; else -> " Evening"
265+ }
266+
222267@SuppressLint(" MissingPermission" )
223268private fun fetchWeather (context : android.content.Context , onResult : (WeatherData ? , String? ) -> Unit ) {
224269 try {
0 commit comments