Skip to content

Commit 6db6211

Browse files
authored
feat: 마이페이지 화면 구현 완료 (#55)
* feat: 온도그래프 화면으로 전환 * feat: 온도그래프 화면으로 전환 * feat: 온도그래프 화면으로 전환 * feat: 온도그래프 화면으로 전환 * feat: 온도그래프 화면으로 전환 * feat: 온도그래프 화면 구현 * feat: 온도그래프 화면 구현 * feat: 온도그래프 화면 구현 * feat: 마이페이지 화면 구현 processing... * feat: 마이페이지 화면 구현 processing... * feat: 마이페이지 화면 구현 processing... * feat: 마이페이지 화면 구현 processing... * feat: 마이페이지 화면 구현 processing... * feat: 마이페이지 화면 구현 * feat: 마이페이지 화면 구현 * feat: 마이페이지 화면 구현 * feat: 마이페이지 화면 구현
1 parent ea0e29c commit 6db6211

File tree

6 files changed

+325
-104
lines changed

6 files changed

+325
-104
lines changed

frontend/ongi/lib/screens/bottom_nav.dart

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ import 'package:ongi/screens/home/home_screen.dart';
44
import 'package:ongi/screens/health/health_home_screen.dart';
55
import 'package:ongi/screens/family_tempbar_screen.dart';
66
import 'package:ongi/screens/photo_screen.dart';
7-
import 'package:ongi/screens/mypage_screen.dart';
7+
import 'package:ongi/screens/mypage/mypage_screen.dart';
88
import 'package:ongi/core/app_colors.dart';
9+
import 'dart:ui';
910

1011
class BottomNavScreen extends StatefulWidget {
1112
const BottomNavScreen({super.key});
@@ -84,16 +85,9 @@ class _BottomNavScreenState extends State<BottomNavScreen> {
8485
gradient: LinearGradient(
8586
begin: Alignment.topCenter,
8687
end: Alignment.bottomCenter,
87-
colors: [ AppColors.ongiBlue, AppColors.ongiOrange ],
88+
colors: [ AppColors.ongiBlue, AppColors.ongiOrange],
8889
),
8990
shape: BoxShape.circle,
90-
boxShadow: [
91-
BoxShadow(
92-
color: Colors.black12,
93-
blurRadius: 8,
94-
offset: Offset(0, 4),
95-
),
96-
],
9791
),
9892
child: const Icon(Icons.add, color: Colors.white, size: 36),
9993
),
@@ -138,14 +132,17 @@ class _BottomNavScreenState extends State<BottomNavScreen> {
138132
child: Column(
139133
mainAxisAlignment: MainAxisAlignment.center,
140134
children: [
141-
iconWidget,
135+
isSelected
136+
? Container(
137+
child: iconWidget,
138+
)
139+
: iconWidget,
142140
const SizedBox(height: 4),
143141
Text(
144142
text,
145143
style: TextStyle(
146144
fontSize: 12,
147-
color:isSelected? AppColors.ongiOrange
148-
: Colors.grey[300],
145+
color: isSelected ? AppColors.ongiOrange : Colors.grey[300],
149146
fontFamily: 'Pretendard',
150147
fontWeight: FontWeight.w600,
151148
),

frontend/ongi/lib/screens/home/home_screen.dart

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import 'package:ongi/screens/home/home_logo.dart';
55
import 'package:ongi/screens/home/home_ourfamily_text.dart';
66
import 'package:ongi/utils/prefs_manager.dart';
77
import 'package:ongi/screens/home/home_donutCapsule.dart';
8-
import 'package:ongi/core/app_light_background.dart';
98

109
class HomeScreen extends StatefulWidget {
1110
const HomeScreen({super.key});
@@ -43,24 +42,6 @@ class _HomeScreenState extends State<HomeScreen> {
4342
_currentView = 'home';
4443
});
4544
}
46-
Widget _buildBackButton() {
47-
return Positioned(
48-
top: MediaQuery.of(context).padding.top + 16,
49-
left: 20,
50-
child: GestureDetector(
51-
onTap: _goBackToHome,
52-
child: Container(
53-
width: 44,
54-
height: 44,
55-
child: Icon(
56-
Icons.arrow_back_ios,
57-
color: Colors.white,
58-
size: 30,
59-
),
60-
),
61-
),
62-
);
63-
}
6445
Widget _buildCurrentView(){
6546
switch(_currentView){
6647
case 'graph':
@@ -75,7 +56,6 @@ class _HomeScreenState extends State<HomeScreen> {
7556
HomeDegreeGraph(
7657
onBack: _goBackToHome,
7758
),
78-
_buildBackButton(),
7959
],
8060
);
8161
}
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:ongi/core/app_colors.dart';
3+
import 'package:ongi/utils/prefs_manager.dart';
4+
import 'package:flutter/services.dart';
5+
6+
class Myinfo extends StatelessWidget {
7+
const Myinfo({Key? key}) : super(key: key);
8+
9+
@override
10+
Widget build(BuildContext context) {
11+
final screenWidth = MediaQuery.of(context).size.width;
12+
final screenHeight = MediaQuery.of(context).size.height;
13+
return FutureBuilder<Map<String, String?>> (
14+
future: PrefsManager.getUserInfo(),
15+
builder: (context, snapshot) {
16+
if (snapshot.connectionState == ConnectionState.waiting) {
17+
return const Center(child: CircularProgressIndicator());
18+
}
19+
if (snapshot.hasError) {
20+
return Center(child: Text('에러: \\${snapshot.error}', style: TextStyle(color: Colors.red)));
21+
}
22+
final userInfo = snapshot.data ?? {};
23+
final name = userInfo['name'] ?? '사용자님';
24+
final familycode = userInfo['familycode'] ?? '33HYF6';
25+
final familyName = userInfo['familyName'] ?? '가족이름';
26+
final profileImage = userInfo['profileImage'] ?? 'assets/images/users/elderly_woman.png';
27+
final isParent = userInfo['isParent'] == 'true';
28+
final roleText = isParent ? '부모' : '자녀';
29+
30+
return Padding(
31+
padding: EdgeInsets.symmetric(
32+
horizontal: screenWidth * 0.05, // 32/375
33+
vertical: screenHeight * 0.02, // 16/812
34+
),
35+
child: Row(
36+
crossAxisAlignment: CrossAxisAlignment.start,
37+
children: [
38+
// 프로필 이미지
39+
ClipOval(
40+
child: Image.asset(
41+
profileImage,
42+
width: screenWidth * 0.3, // 112/375
43+
height: screenWidth * 0.4, // 160/375
44+
fit: BoxFit.contain,
45+
),
46+
),
47+
SizedBox(width: screenWidth * 0.0053),
48+
// 오른쪽 정보들
49+
Expanded(
50+
child: Column(
51+
crossAxisAlignment: CrossAxisAlignment.start,
52+
children: [
53+
Row(
54+
crossAxisAlignment: CrossAxisAlignment.center,
55+
children: [
56+
Text(
57+
'$name님',
58+
style: TextStyle(
59+
color: Colors.white,
60+
fontSize: screenWidth * 0.064, // 24/375
61+
fontWeight: FontWeight.w800,
62+
fontFamily: 'Pretendard',
63+
),
64+
),
65+
SizedBox(width: screenWidth * 0.015),
66+
Container(
67+
padding: EdgeInsets.symmetric(
68+
horizontal: screenWidth * 0.01,
69+
vertical: screenHeight * 0.001,
70+
),
71+
decoration: BoxDecoration(
72+
color: Colors.white,
73+
borderRadius: BorderRadius.circular(20),
74+
),
75+
child: Text(
76+
roleText,
77+
style: TextStyle(
78+
color: AppColors.ongiOrange,
79+
fontSize: screenWidth * 0.019,
80+
fontWeight: FontWeight.w600,
81+
fontFamily: 'Pretendard',
82+
),
83+
),
84+
),
85+
],
86+
),
87+
Padding(
88+
padding: EdgeInsets.only(left: screenWidth * 0.021), // 8/375
89+
child: Column(
90+
crossAxisAlignment: CrossAxisAlignment.start,
91+
children: [
92+
SizedBox(height: screenHeight * 0.005), // 4/812
93+
Row(
94+
children: [
95+
Text(
96+
familyName,
97+
style: TextStyle(
98+
color: Colors.white,
99+
fontSize: 15,
100+
fontWeight: FontWeight.w700,
101+
fontFamily: 'Pretendard',
102+
),
103+
),
104+
SizedBox(width: screenWidth * 0.011), // 4/375
105+
Text(
106+
familycode,
107+
style: TextStyle(
108+
color: Colors.white,
109+
fontSize: 10,
110+
fontWeight: FontWeight.w600,
111+
fontFamily: 'Pretendard',
112+
),
113+
),
114+
SizedBox(width: screenWidth * 0.021), // 8/375
115+
Builder(
116+
builder: (context) => OutlinedButton(
117+
onPressed: () async {
118+
await Clipboard.setData(ClipboardData(text: familycode));
119+
ScaffoldMessenger.of(context).showSnackBar(
120+
SnackBar(content: Text('가족코드가 복사되었습니다.')),
121+
);
122+
},
123+
style: OutlinedButton.styleFrom(
124+
side: const BorderSide(color: AppColors.ongiOrange, width: 1),
125+
shape: RoundedRectangleBorder(
126+
borderRadius: BorderRadius.circular(20),
127+
),
128+
minimumSize: Size.zero,
129+
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
130+
backgroundColor: Colors.white,
131+
padding: EdgeInsets.symmetric(
132+
horizontal: screenWidth * 0.01,
133+
vertical: screenHeight * 0.001,
134+
),
135+
),
136+
child: Text(
137+
'가족코드 공유',
138+
style: TextStyle(
139+
color: AppColors.ongiOrange,
140+
fontSize: screenWidth * 0.019,
141+
fontWeight: FontWeight.w600,
142+
fontFamily: 'Pretendard',
143+
),
144+
),
145+
),
146+
),
147+
],
148+
),
149+
SizedBox(height: screenHeight * 0.02), // 4/812
150+
OutlinedButton(
151+
onPressed: () {},
152+
style: OutlinedButton.styleFrom(
153+
side: const BorderSide(color: AppColors.ongiOrange, width: 1),
154+
shape: RoundedRectangleBorder(
155+
borderRadius: BorderRadius.circular(30),
156+
),
157+
backgroundColor: Colors.white,
158+
padding: EdgeInsets.symmetric(
159+
horizontal: screenWidth * 0.027, // 10/375
160+
vertical: screenHeight * 0.002, // 1/812
161+
),
162+
),
163+
child: const Text(
164+
'프로필 수정',
165+
style: TextStyle(
166+
color: AppColors.ongiOrange,
167+
fontWeight: FontWeight.w400,
168+
fontSize: 13,
169+
fontFamily: 'Pretendard',
170+
),
171+
),
172+
),
173+
],
174+
),
175+
),
176+
],
177+
),
178+
),
179+
],
180+
),
181+
);
182+
},
183+
);
184+
}
185+
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:ongi/utils/prefs_manager.dart';
3+
import 'package:ongi/screens/start_screen.dart';
4+
import 'package:ongi/core/app_colors.dart';
5+
import 'package:ongi/screens/mypage/mypage_myinfo.dart';
6+
7+
class ProfileScreen extends StatelessWidget {
8+
const ProfileScreen({Key? key}) : super(key: key);
9+
10+
Widget buildMenuList(BuildContext context) {
11+
final menuItems = [
12+
'개인정보 보호',
13+
'시스템 알림',
14+
'공지사항',
15+
'정보',
16+
'문의하기',
17+
'로그아웃',
18+
];
19+
20+
final double gap = MediaQuery.of(context).size.height * 0.02;
21+
final screenWidth = MediaQuery.of(context).size.width;
22+
return Container(
23+
margin: EdgeInsets.only(left: 0, right: screenWidth * 0.3),
24+
child: Column(
25+
crossAxisAlignment: CrossAxisAlignment.start,
26+
children: [
27+
for (final item in menuItems) ...[
28+
SizedBox(height: gap),
29+
item == '로그아웃'
30+
? GestureDetector(
31+
onTap: () async {
32+
await PrefsManager.logout();
33+
ScaffoldMessenger.of(context).showSnackBar(
34+
const SnackBar(content: Text('로그아웃되었습니다.')),
35+
);
36+
await Future.delayed(const Duration(milliseconds: 500));
37+
Navigator.of(context).pushAndRemoveUntil(
38+
MaterialPageRoute(builder: (context) => const StartScreen()),
39+
(route) => false,
40+
);
41+
},
42+
child: const Text(
43+
'로그아웃',
44+
style: TextStyle(
45+
fontSize: 24,
46+
color: Colors.black,
47+
),
48+
),
49+
)
50+
: Text(item, style: const TextStyle(fontSize: 24)),
51+
]
52+
],
53+
),
54+
);
55+
}
56+
57+
@override
58+
Widget build(BuildContext context) {
59+
return Scaffold(
60+
backgroundColor: AppColors.ongiOrange,
61+
appBar: AppBar(backgroundColor: AppColors.ongiOrange, elevation: 0),
62+
body: Stack(
63+
children: [
64+
Positioned(
65+
bottom: -MediaQuery.of(context).size.width * 0.6,
66+
left: 0,
67+
right: 0,
68+
height: MediaQuery.of(context).size.height * 0.75,
69+
child: OverflowBox(
70+
maxWidth: double.infinity,
71+
maxHeight: double.infinity,
72+
child: Center(
73+
child: Container(
74+
width: MediaQuery.of(context).size.width * 1.5,
75+
height: MediaQuery.of(context).size.height,
76+
decoration: BoxDecoration(
77+
color: AppColors.ongiLigntgrey,
78+
borderRadius: const BorderRadius.only(
79+
topLeft: Radius.circular(260),
80+
topRight: Radius.circular(260),
81+
),
82+
),
83+
),
84+
),
85+
),
86+
),
87+
// 기존 내용
88+
Center(
89+
child: Column(
90+
mainAxisAlignment: MainAxisAlignment.start,
91+
children: [
92+
const Text(
93+
'마이페이지',
94+
style: TextStyle(
95+
color: Colors.white,
96+
fontSize: 24,
97+
fontFamily: 'Pretendard',
98+
fontWeight: FontWeight.w600,
99+
),
100+
),
101+
const SizedBox(height: 8),
102+
const Padding(
103+
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 8),
104+
child: Myinfo(),
105+
),
106+
const SizedBox(height: 24),
107+
buildMenuList(context),
108+
],
109+
),
110+
),
111+
],
112+
),
113+
);
114+
}
115+
}
116+

0 commit comments

Comments
 (0)