feat: environment widgets layout redesign with always-visible widgets
- Desktop: 4-in-a-row layout (30/20/20/30 distribution) - Tablet: 2x2 grid layout - Mobile: Stacked vertically - All widgets show "No data available" state instead of being hidden - Sun position calculates from clock, defaults to 6am/6pm - Environment refresh changed from 5min to 1 hour 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.5
parent
fffc3d5baf
commit
d200cad8be
@@ -34,9 +34,9 @@ class _DashboardContentState extends ConsumerState<DashboardContent> {
|
||||
const Duration(seconds: 30),
|
||||
(_) => ref.invalidate(systemStatsProvider),
|
||||
);
|
||||
// Refresh environment data every 5 minutes
|
||||
// Refresh environment data every hour
|
||||
_environmentTimer = Timer.periodic(
|
||||
const Duration(minutes: 5),
|
||||
const Duration(hours: 1),
|
||||
(_) => ref.invalidate(environmentProvider),
|
||||
);
|
||||
}
|
||||
@@ -279,7 +279,12 @@ class _SystemStatsCard extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
/// Environment section displaying sun position, weather, forecast, and air quality.
|
||||
/// Environment section displaying sun position, weather, air quality, and forecast.
|
||||
///
|
||||
/// Layout:
|
||||
/// - Desktop (>900px): 4 widgets in a row - Sun(30%) | Weather(20%) | AirQuality(20%) | Forecast(30%)
|
||||
/// - Tablet (600-900px): 2x2 grid
|
||||
/// - Mobile (<600px): Stacked vertically
|
||||
class _EnvironmentSection extends StatelessWidget {
|
||||
const _EnvironmentSection({
|
||||
required this.envData,
|
||||
@@ -293,40 +298,73 @@ class _EnvironmentSection extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final isWide = constraints.maxWidth > 600;
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
// Sun Position Widget - prominent at top
|
||||
SunPositionWidget(sunTimes: envData.sunTimes),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
// Weather and Forecast side-by-side on wide screens
|
||||
if (isWide)
|
||||
if (constraints.maxWidth > 900) {
|
||||
// Desktop: 4 in a row (30/20/20/30) - wider widgets on outsides
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 30,
|
||||
child: SunPositionWidget(sunTimes: envData.sunTimes),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
flex: 20,
|
||||
child: WeatherWidget(apiData: envData.weather),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
flex: 20,
|
||||
child: AirQualityWidget(apiData: envData.airQuality),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
flex: 30,
|
||||
child: ForecastWidget(forecast: envData.forecast),
|
||||
),
|
||||
],
|
||||
);
|
||||
} else if (constraints.maxWidth > 600) {
|
||||
// Tablet: 2x2 grid
|
||||
return Column(
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: SunPositionWidget(sunTimes: envData.sunTimes),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(child: WeatherWidget(apiData: envData.weather)),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: AirQualityWidget(apiData: envData.airQuality),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(child: ForecastWidget(forecast: envData.forecast)),
|
||||
],
|
||||
)
|
||||
else
|
||||
Column(
|
||||
children: [
|
||||
WeatherWidget(apiData: envData.weather),
|
||||
const SizedBox(height: 12),
|
||||
ForecastWidget(forecast: envData.forecast),
|
||||
],
|
||||
),
|
||||
|
||||
// Air Quality - only show if data is available
|
||||
if (envData.airQuality != null) ...[
|
||||
],
|
||||
);
|
||||
} else {
|
||||
// Mobile: stacked vertically
|
||||
return Column(
|
||||
children: [
|
||||
SunPositionWidget(sunTimes: envData.sunTimes),
|
||||
const SizedBox(height: 12),
|
||||
WeatherWidget(apiData: envData.weather),
|
||||
const SizedBox(height: 12),
|
||||
AirQualityWidget(apiData: envData.airQuality),
|
||||
const SizedBox(height: 12),
|
||||
ForecastWidget(forecast: envData.forecast),
|
||||
],
|
||||
],
|
||||
);
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user