Skip to content

Commit c0b8b2b

Browse files
authored
feat: 홈화면 온도 그래프 구현 (Neibce/OnGi#51)
* feat: 온도그래프 화면으로 전환 * feat: 온도그래프 화면으로 전환 * feat: 온도그래프 화면으로 전환 * feat: 온도그래프 화면으로 전환 * feat: 온도그래프 화면으로 전환 * feat: 온도그래프 화면 구현 * feat: 온도그래프 화면 구현
1 parent c727ed5 commit c0b8b2b

File tree

6 files changed

+483
-115
lines changed

6 files changed

+483
-115
lines changed

frontend/ongi/lib/main.dart

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,17 @@ void main() async {
1313
WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
1414
FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
1515

16-
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
17-
FirebaseMessaging messaging = FirebaseMessaging.instance;
18-
messaging.requestPermission(
19-
alert: true,
20-
announcement: false,
21-
badge: true,
22-
carPlay: false,
23-
criticalAlert: false,
24-
provisional: false,
25-
sound: true,
26-
);
16+
// await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
17+
// FirebaseMessaging messaging = FirebaseMessaging.instance;
18+
// messaging.requestPermission(
19+
// alert: true,
20+
// announcement: false,
21+
// badge: true,
22+
// carPlay: false,
23+
// criticalAlert: false,
24+
// provisional: false,
25+
// sound: true,
26+
// );
2727

2828
runApp(const OngiApp());
2929
}
Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:fl_chart/fl_chart.dart';
3+
import 'package:ongi/core/app_colors.dart';
4+
import 'package:ongi/core/app_light_background.dart';
5+
import 'package:ongi/screens/home/home_ourfamily_text_withoutUser.dart';
6+
7+
final List<String> dates = ['6/11', '6/12', '6/13', '6/14', '6/15'];
8+
final List<double> temps = [36.2, 35.8, 37.2, 38.0, 38.6];
9+
final List<FlSpot> spots = List.generate(
10+
temps.length,
11+
(i) => FlSpot(i.toDouble(), temps[i]),
12+
);
13+
14+
class HomeDegreeGraph extends StatefulWidget {
15+
final VoidCallback? onBack;
16+
const HomeDegreeGraph({super.key, this.onBack});
17+
18+
@override
19+
State<HomeDegreeGraph> createState() => _HomeDegreeGraph();
20+
}
21+
22+
class _HomeDegreeGraph extends State<HomeDegreeGraph> {
23+
bool showHistory = false;
24+
25+
final List<Map<String, String>> history = [
26+
{"name": "양금명님", "change": "+0.3°C", "date": "25.06.15 22:07"},
27+
{"name": "양은명님", "change": "+0.1°C", "date": "25.06.14 20:55"},
28+
{"name": "양관식님", "change": "+0.2°C", "date": "25.06.14 17:14"},
29+
{"name": "양관식님", "change": "+0.2°C", "date": "25.06.13 17:14"},
30+
{"name": "양관식님", "change": "+0.2°C", "date": "25.06.13 17:14"},
31+
{"name": "양관식님", "change": "+0.1°C", "date": "25.06.13 17:14"},
32+
{"name": "오애순님", "change": "+0.2°C", "date": "25.06.13 15:09"},
33+
{"name": "오애순님", "change": "+0.2°C", "date": "25.06.13 15:08"},
34+
{"name": "오애순님", "change": "+0.2°C", "date": "25.06.13 15:08"},
35+
{"name": "오애순님", "change": "+0.1°C", "date": "25.06.13 15:07"},
36+
{"name": "양금명님", "change": "+0.1°C", "date": "25.06.13 12:28"},
37+
];
38+
39+
@override
40+
Widget build(BuildContext context) {
41+
return Scaffold(
42+
backgroundColor: AppColors.ongiLigntgrey,
43+
body: AppLightBackground(
44+
child: SafeArea(
45+
child: Column(
46+
crossAxisAlignment: CrossAxisAlignment.start,
47+
children: [
48+
// 뒤로가기
49+
GestureDetector(
50+
onTap: widget.onBack ?? () => Navigator.of(context).pop(),
51+
child: Padding(
52+
padding: EdgeInsets.only(
53+
left: 32,
54+
top: MediaQuery.of(context).size.height * 0.08,
55+
),
56+
child: Icon(Icons.arrow_back_ios, color: Colors.black, size: 28),
57+
),
58+
),
59+
// 타이틀
60+
const HomeOngiTextWithoutUser(),
61+
// 카드
62+
Padding(
63+
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
64+
child: Container(
65+
decoration: BoxDecoration(
66+
color: Colors.white,
67+
borderRadius: BorderRadius.circular(24),
68+
),
69+
padding: const EdgeInsets.all(20),
70+
child: showHistory
71+
? _buildHistoryList()
72+
: _buildGraphCard(),
73+
),
74+
),
75+
],
76+
),
77+
),
78+
),
79+
);
80+
}
81+
82+
Widget _buildGraphCard() {
83+
String latestName = '';
84+
String latestChange = '';
85+
if (history.isNotEmpty) {
86+
latestName = history[0]['name'] ?? '';
87+
latestChange = history[0]['change'] ?? '';
88+
}
89+
return Column(
90+
mainAxisSize: MainAxisSize.min,
91+
children: [
92+
SizedBox(
93+
height: 270,
94+
child: LineChart(
95+
LineChartData(
96+
minY: 35.2,
97+
maxY: 40.5,
98+
minX: 0,
99+
maxX: (dates.length - 1).toDouble(),
100+
gridData: FlGridData(
101+
show: true,
102+
drawVerticalLine: false,
103+
horizontalInterval: 0.5,
104+
getDrawingHorizontalLine: (value) => FlLine(
105+
color: Colors.grey[300],
106+
strokeWidth: 1,
107+
),
108+
),
109+
titlesData: FlTitlesData(
110+
leftTitles: AxisTitles(
111+
sideTitles: SideTitles(
112+
showTitles: true,
113+
interval: 0.5,
114+
getTitlesWidget: (value, meta) {
115+
if (value == 35.2 || value == 40.5) return const SizedBox.shrink();
116+
return Text(
117+
value.toStringAsFixed(1),
118+
style: const TextStyle(
119+
color: Colors.grey,
120+
fontSize: 13,
121+
fontFamily: 'Pretendard',
122+
),
123+
);
124+
},
125+
reservedSize: 36,
126+
),
127+
),
128+
bottomTitles: AxisTitles(
129+
sideTitles: SideTitles(
130+
showTitles: true,
131+
getTitlesWidget: (value, meta) {
132+
if (value % 1 != 0) return const SizedBox.shrink();
133+
int idx = value.toInt();
134+
if (idx < 0 || idx >= dates.length) return const SizedBox.shrink();
135+
return Padding(
136+
padding: const EdgeInsets.only(top: 8),
137+
child: Text(
138+
dates[idx],
139+
style: const TextStyle(
140+
color: Colors.grey,
141+
fontSize: 13,
142+
fontFamily: 'Pretendard',
143+
),
144+
),
145+
);
146+
},
147+
interval: 1,
148+
),
149+
),
150+
rightTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)),
151+
topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)),
152+
),
153+
borderData: FlBorderData(
154+
show: false,
155+
),
156+
lineBarsData: [
157+
LineChartBarData(
158+
spots: spots,
159+
isCurved: false,
160+
color: Colors.orange,
161+
barWidth: 2.5,
162+
isStrokeCapRound: true,
163+
dotData: FlDotData(
164+
show: true,
165+
getDotPainter: (spot, percent, bar, index) => FlDotCirclePainter(
166+
radius: 3,
167+
color: Colors.white,
168+
strokeWidth: 2.5,
169+
strokeColor: Colors.orange,
170+
),
171+
),
172+
),
173+
],
174+
),
175+
),
176+
),
177+
const SizedBox(height: 12),
178+
Text(
179+
latestName.isNotEmpty && latestChange.isNotEmpty
180+
? '최근 $latestName 님이 $latestChange 상승 시켰어요!'
181+
: '최근 온도 변화 데이터가 없습니다.',
182+
style: const TextStyle(
183+
fontSize: 15,
184+
color: Colors.grey,
185+
fontFamily: 'Pretendard',
186+
),
187+
),
188+
IconButton(
189+
icon: const Icon(Icons.keyboard_arrow_down, color: Colors.grey),
190+
onPressed: () => setState(() => showHistory = true),
191+
),
192+
],
193+
);
194+
}
195+
196+
Widget _buildHistoryList() {
197+
return Column(
198+
mainAxisSize: MainAxisSize.min,
199+
children: [
200+
IconButton(
201+
icon: const Icon(Icons.keyboard_arrow_up, color: Colors.grey),
202+
onPressed: () => setState(() => showHistory = false),
203+
),
204+
SizedBox(
205+
height: 290,
206+
child: ListView.builder(
207+
itemCount: history.length,
208+
itemBuilder: (context, idx) {
209+
final item = history[idx];
210+
return Row(
211+
crossAxisAlignment: CrossAxisAlignment.start,
212+
children: [
213+
// 왼쪽 선과 원
214+
Column(
215+
children: [
216+
Container(
217+
width: 9,
218+
height: 9,
219+
decoration: BoxDecoration(
220+
shape: BoxShape.circle,
221+
border: Border.all(color: Colors.orange, width: 2),
222+
color: Colors.white,
223+
),
224+
),
225+
if (idx != history.length - 1)
226+
Container(
227+
width: 2,
228+
height: 24,
229+
color: Colors.orange,
230+
),
231+
],
232+
),
233+
const SizedBox(width: 8),
234+
Expanded(
235+
child: Text(
236+
"${item['name']}이 ${item['change']} 상승 시켰어요!",
237+
style: const TextStyle(
238+
color: Colors.grey,
239+
fontSize: 15,
240+
fontFamily: 'Pretendard',
241+
),
242+
),
243+
),
244+
Text(
245+
item['date'] ?? '',
246+
style: const TextStyle(
247+
color: Colors.grey,
248+
fontSize: 12,
249+
fontFamily: 'Pretendard',
250+
),
251+
),
252+
],
253+
);
254+
},
255+
),
256+
),
257+
],
258+
);
259+
}
260+
}

0 commit comments

Comments
 (0)