Skip to content

Commit c43c197

Browse files
authored
UI developments (#495)
* Added granularity parameter * Trackerball UI update * 'unsafe_html' was removed in Dart '3.7.0' Remove the reference to 'unsafe_html'. * Added min and max values to tank card * Removed continuous dynamic sizing dependent on card width * Formatting
1 parent e16b270 commit c43c197

11 files changed

Lines changed: 273 additions & 137 deletions

File tree

extras/log_file_client/lib/components/graph_view.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ class _GraphViewState extends State<GraphView> {
100100
format: 'series.name : point.y',
101101
),
102102
activationMode: ActivationMode.singleTap,
103+
lineColor: Colors.grey.shade600,
104+
lineWidth: 1.5,
105+
lineDashArray: [2, 2],
103106
);
104107

105108
return Expanded(
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import 'package:flutter/material.dart';
2+
3+
class PageHeader extends StatelessWidget {
4+
const PageHeader({required this.text, super.key});
5+
final String text;
6+
7+
@override
8+
Widget build(BuildContext context) {
9+
final screenWidth = MediaQuery.of(context).size.width;
10+
11+
return Container(
12+
margin: EdgeInsets.only(
13+
top: 40,
14+
left: 135,
15+
right: 135,
16+
),
17+
padding: EdgeInsets.only(bottom: 16),
18+
width: screenWidth,
19+
decoration: BoxDecoration(
20+
border: Border(
21+
bottom: BorderSide(
22+
color: const Color(0xFFE6E6E6),
23+
width: 1.5,
24+
),
25+
),
26+
),
27+
child: Text(
28+
text,
29+
style: TextStyle(
30+
fontSize: 60,
31+
letterSpacing: -2,
32+
color: const Color(0xFF0C2D48),
33+
),
34+
),
35+
);
36+
}
37+
}

extras/log_file_client/lib/components/tank_card.dart

Lines changed: 102 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ import 'package:log_file_client/components/tank_thumbnail.dart';
44
import 'package:log_file_client/utils/http_client.dart';
55
import 'package:skeletonizer/skeletonizer.dart';
66

7+
enum TankInfoType { pH, temp }
8+
9+
enum TankInfoMode { current, range }
10+
711
class TankCard extends StatelessWidget {
812
const TankCard({
913
required this.log,
@@ -29,25 +33,26 @@ class TankCard extends StatelessWidget {
2933
onTap: onTap,
3034
child: LayoutBuilder(
3135
builder: (BuildContext context, BoxConstraints constraints) {
32-
// Decide sizes of internal components based on card width
3336
final double cardWidth = constraints.maxWidth * 0.93;
34-
final double titleFontSize = cardWidth * 0.05;
35-
final double descriptionFontSize = cardWidth * 0.04;
37+
final double titleFontSize = 20;
38+
final double tankInfoFontSize = 16;
39+
final double tankInfoHeaderFontSize = 14;
3640

3741
// ignore: discarded_futures
3842
final Future<TankSnapshot> tankSnapshot = getTankSnapshot();
3943

4044
return Container(
41-
margin: EdgeInsets.all(cardWidth * 0.075),
45+
margin: EdgeInsets.all(30),
4246
decoration: _cardBackground(),
4347
child: Column(
48+
mainAxisAlignment: MainAxisAlignment.spaceBetween,
4449
children: [
4550
_graphThumbnailBuilder(tankSnapshot, cardWidth),
4651
_tankName(titleFontSize),
4752
_tankInfoBuilder(
4853
tankSnapshot,
49-
cardWidth,
50-
descriptionFontSize,
54+
tankInfoFontSize,
55+
tankInfoHeaderFontSize,
5156
),
5257
],
5358
),
@@ -91,21 +96,12 @@ class TankCard extends StatelessWidget {
9196
);
9297
}
9398

94-
Container _graphThumbnail(
99+
Widget _graphThumbnail(
95100
double cardWidth,
96101
AsyncSnapshot<TankSnapshot>? snapshot,
97102
) {
98-
return Container(
99-
width: cardWidth,
103+
return SizedBox(
100104
height: cardWidth * 0.6,
101-
margin: EdgeInsets.only(
102-
bottom: cardWidth * 0.05,
103-
),
104-
decoration: BoxDecoration(
105-
borderRadius: BorderRadius.vertical(
106-
top: Radius.circular(20),
107-
),
108-
),
109105
child: ClipRRect(
110106
borderRadius: BorderRadius.vertical(
111107
top: Radius.circular(20),
@@ -139,26 +135,33 @@ class TankCard extends StatelessWidget {
139135

140136
Widget _tankInfoBuilder(
141137
Future<TankSnapshot> tankSnapshot,
142-
double cardWidth,
143-
double descriptionFontSize,
138+
double tankInfoFontSize,
139+
double tankInfoHeaderFontSize,
144140
) {
145141
return FutureBuilder(
146142
future: tankSnapshot,
147143
builder: (context, snapshot) {
148144
if (snapshot.connectionState == ConnectionState.waiting) {
149-
return _skeletonLoaderInfo(cardWidth, descriptionFontSize);
145+
return _skeletonLoaderInfo(
146+
tankInfoFontSize,
147+
tankInfoHeaderFontSize,
148+
);
150149
} else if (snapshot.hasError) {
151150
return Center(child: Text('Error: ${snapshot.error}'));
152151
} else {
153-
return _tankInfo(cardWidth, descriptionFontSize, snapshot);
152+
return _tankInfo(
153+
tankInfoFontSize,
154+
tankInfoHeaderFontSize,
155+
snapshot,
156+
);
154157
}
155158
},
156159
);
157160
}
158161

159162
Skeletonizer _skeletonLoaderInfo(
160-
double cardWidth,
161-
double descriptionFontSize,
163+
double tankInfoFontSize,
164+
double tankInfoHeaderFontSize,
162165
) {
163166
return Skeletonizer(
164167
textBoneBorderRadius: TextBoneBorderRadius(BorderRadius.circular(4)),
@@ -167,47 +170,107 @@ class TankCard extends StatelessWidget {
167170
highlightColor: Colors.grey[100]!,
168171
duration: Duration(seconds: 2),
169172
),
170-
child: _tankInfo(cardWidth, descriptionFontSize, null),
173+
child: _tankInfo(tankInfoFontSize, tankInfoHeaderFontSize, null),
171174
);
172175
}
173176

174177
Widget _tankInfo(
175-
double cardWidth,
176-
double descriptionFontSize,
178+
double tankInfoFontSize,
179+
double tankInfoHeaderFontSize,
177180
AsyncSnapshot<TankSnapshot>? snapshot,
178181
) {
179182
return Padding(
180-
padding: EdgeInsets.only(top: cardWidth * 0.06),
183+
padding: const EdgeInsets.only(bottom: 15),
181184
child: Row(
182185
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
183186
children: [
184-
_tankInfoLine('ph', descriptionFontSize, snapshot),
185-
_tankInfoLine('temp', descriptionFontSize, snapshot),
187+
_tankInfoBlock(
188+
TankInfoMode.current,
189+
tankInfoFontSize,
190+
tankInfoHeaderFontSize,
191+
snapshot,
192+
),
193+
_tankInfoBlock(
194+
TankInfoMode.range,
195+
tankInfoFontSize,
196+
tankInfoHeaderFontSize,
197+
snapshot,
198+
),
186199
],
187200
),
188201
);
189202
}
190203

191-
Row _tankInfoLine(
192-
String type,
193-
double descriptionFontSize,
204+
Widget _tankInfoBlock(
205+
TankInfoMode mode,
206+
double tankInfoFontSize,
207+
double tankInfoHeaderFontSize,
194208
AsyncSnapshot<TankSnapshot>? snapshot,
195209
) {
210+
return Column(
211+
children: [
212+
_tankInfoHeader(mode, tankInfoHeaderFontSize),
213+
_tankInfoLine(TankInfoType.pH, mode, tankInfoFontSize, snapshot),
214+
_tankInfoLine(TankInfoType.temp, mode, tankInfoFontSize, snapshot),
215+
],
216+
);
217+
}
218+
219+
Widget _tankInfoHeader(TankInfoMode mode, double tankInfoHeaderFontSize) {
220+
return Text(
221+
mode == TankInfoMode.current ? 'Current' : '12hr Range',
222+
style: TextStyle(
223+
fontSize: tankInfoHeaderFontSize,
224+
fontWeight: FontWeight.normal,
225+
color: Colors.grey.shade500,
226+
),
227+
);
228+
}
229+
230+
Widget _tankInfoLine(
231+
TankInfoType type,
232+
TankInfoMode mode,
233+
double tankInfoFontSize,
234+
AsyncSnapshot<TankSnapshot>? snapshot,
235+
) {
236+
final IconData iconType =
237+
type == TankInfoType.pH ? Icons.water_drop : Icons.thermostat;
238+
final Color iconColor =
239+
type == TankInfoType.pH ? Colors.green : Colors.blue;
240+
241+
String textData = 'mock';
242+
if (mode == TankInfoMode.current) {
243+
if (type == TankInfoType.pH) {
244+
textData = 'pH ${snapshot?.data!.pH ?? 'mock'}';
245+
} else {
246+
textData = '${snapshot?.data!.temperature ?? 'mock'}°C';
247+
}
248+
} else if (mode == TankInfoMode.range) {
249+
if (type == TankInfoType.pH) {
250+
final min = snapshot?.data!.minPH ?? 'm.k';
251+
final max = snapshot?.data!.maxPH ?? 'm.k';
252+
textData = 'pH $min - $max';
253+
} else {
254+
final min = snapshot?.data!.minTemp ?? 'mk';
255+
final max = snapshot?.data!.maxTemp ?? 'mk';
256+
textData = '$min - $max°C';
257+
}
258+
}
259+
196260
return Row(
197261
children: [
198262
Skeleton.keep(
199263
child: Icon(
200-
type == 'ph' ? Icons.water_drop : Icons.thermostat,
201-
color: type == 'ph' ? Colors.green : Colors.blue,
202-
size: descriptionFontSize,
264+
iconType,
265+
color: iconColor,
266+
size: tankInfoFontSize,
203267
),
204268
),
269+
SizedBox(width: 5),
205270
Text(
206-
type == 'ph'
207-
? 'pH ${snapshot?.data!.pH ?? 'mock'}'
208-
: '${snapshot?.data!.temperature ?? 'mock'}°C',
271+
textData,
209272
style: TextStyle(
210-
fontSize: descriptionFontSize,
273+
fontSize: tankInfoFontSize,
211274
color: const Color(0xFF6D6D6D),
212275
),
213276
),

extras/log_file_client/lib/components/tank_thumbnail.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class TankThumbnail extends StatelessWidget {
2525
primaryXAxis: DateTimeAxis(
2626
intervalType: DateTimeIntervalType.hours,
2727
interval: 6,
28+
labelStyle: TextStyle(color: Colors.grey.shade700),
2829
// isVisible: !(axis == 'pHAxis'),
2930
),
3031
primaryYAxis: NumericAxis(
@@ -39,6 +40,7 @@ class TankThumbnail extends StatelessWidget {
3940
? snapshot.pHSetpoint! + 0.5
4041
: snapshot.temperatureSetpoint! + 0.5,
4142
anchorRangeToVisiblePoints: false,
43+
labelStyle: TextStyle(color: Colors.grey.shade700),
4244
),
4345
series: series,
4446
),

extras/log_file_client/lib/pages/home_page.dart

Lines changed: 12 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'dart:async';
22

33
import 'package:flutter/material.dart';
4+
import 'package:log_file_client/components/page_header.dart';
45
import 'package:log_file_client/components/project_card.dart';
56
import 'package:log_file_client/pages/project_page.dart';
67
import 'package:log_file_client/utils/http_client.dart';
@@ -71,8 +72,8 @@ class _HomePageState extends State<HomePage> {
7172
body: Center(
7273
child: Column(
7374
children: [
74-
_pageHeader(screenWidth),
75-
_projectCards(gridCrossAxis, screenWidth),
75+
PageHeader(text: 'Projects'),
76+
_projectCards(gridCrossAxis),
7677
],
7778
),
7879
),
@@ -102,37 +103,9 @@ class _HomePageState extends State<HomePage> {
102103
// );
103104
// }
104105

105-
Container _pageHeader(double screenWidth) {
106-
return Container(
107-
margin: EdgeInsets.only(
108-
top: screenWidth * 0.025,
109-
left: screenWidth * 0.0875,
110-
right: screenWidth * 0.0875,
111-
),
112-
padding: EdgeInsets.only(bottom: screenWidth * 0.01),
113-
width: screenWidth,
114-
decoration: BoxDecoration(
115-
border: Border(
116-
bottom: BorderSide(
117-
color: const Color(0xFFE6E6E6),
118-
width: 1.5,
119-
),
120-
),
121-
),
122-
child: Text(
123-
'Projects',
124-
style: TextStyle(
125-
fontSize: screenWidth * 0.04,
126-
letterSpacing: -2,
127-
color: const Color(0xFF0C2D48),
128-
),
129-
),
130-
);
131-
}
132-
133-
Widget _projectCards(int gridCrossAxis, double screenWidth) {
106+
Widget _projectCards(int gridCrossAxis) {
134107
return _isLoading
135-
? _skeletonLoader(gridCrossAxis, screenWidth)
108+
? _skeletonLoader(gridCrossAxis)
136109
: Expanded(
137110
child: GridView.builder(
138111
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
@@ -146,15 +119,15 @@ class _HomePageState extends State<HomePage> {
146119
);
147120
},
148121
padding: EdgeInsets.only(
149-
left: screenWidth * 0.067,
150-
right: screenWidth * 0.067,
151-
top: screenWidth * 0.011,
122+
left: 100,
123+
right: 100,
124+
top: 16,
152125
),
153126
),
154127
);
155128
}
156129

157-
Widget _skeletonLoader(int gridCrossAxis, double screenWidth) {
130+
Widget _skeletonLoader(int gridCrossAxis) {
158131
return Expanded(
159132
child: Skeletonizer(
160133
effect: ShimmerEffect(
@@ -174,9 +147,9 @@ class _HomePageState extends State<HomePage> {
174147
);
175148
},
176149
padding: EdgeInsets.only(
177-
left: screenWidth * 0.067,
178-
right: screenWidth * 0.067,
179-
top: screenWidth * 0.011,
150+
left: 100,
151+
right: 100,
152+
top: 16,
180153
),
181154
),
182155
),

0 commit comments

Comments
 (0)