Skip to content

Commit a0e1f06

Browse files
authored
feat: 마음 기록 앨범 상세 페이지 구현 (#59)
* feat: 온도그래프 화면으로 전환 * feat: 온도그래프 화면으로 전환 * feat: 온도그래프 화면으로 전환 * feat: 온도그래프 화면으로 전환 * feat: 온도그래프 화면으로 전환 * feat: 온도그래프 화면 구현 * feat: 온도그래프 화면 구현 * feat: 온도그래프 화면 구현 * feat: 마이페이지 화면 구현 processing... * feat: 마이페이지 화면 구현 processing... * feat: 마이페이지 화면 구현 processing... * feat: 마이페이지 화면 구현 processing... * feat: 마이페이지 화면 구현 processing... * feat: 마이페이지 화면 구현 * feat: 마이페이지 화면 구현 * feat: 마이페이지 화면 구현 * feat: 마이페이지 화면 구현 * feat: 마이페이지 화면 구현 * feat: 마이페이지 화면 구현 * feat: 마음기록 앨범 상세 구현 processing * feat: 마음기록 앨범 상세 구현 processing * feat: 마음기록 앨범 상세 구현 processing
1 parent d764940 commit a0e1f06

File tree

4 files changed

+297
-9
lines changed

4 files changed

+297
-9
lines changed
1.01 MB
Loading

frontend/ongi/lib/screens/bottom_nav.dart

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ import 'package:ongi/screens/add_record_screen.dart';
44
import 'package:ongi/screens/home/home_screen.dart';
55
import 'package:ongi/screens/health/health_home_screen.dart';
66
import 'package:ongi/screens/family_tempbar_screen.dart';
7+
import 'package:ongi/screens/photo/photo_date_screen.dart';
8+
79
import 'package:ongi/screens/mypage/mypage_screen.dart';
810
import 'package:ongi/core/app_colors.dart';
9-
import 'dart:ui';
1011

1112
class BottomNavScreen extends StatefulWidget {
1213
const BottomNavScreen({super.key});
@@ -22,6 +23,7 @@ class _BottomNavScreenState extends State<BottomNavScreen> {
2223
const HomeScreen(),
2324
const HealthHomeScreen(),
2425
const FamilyTempbarScreen(),
26+
const PhotoDateScreen(),
2527
const ProfileScreen(),
2628
];
2729

@@ -91,9 +93,16 @@ class _BottomNavScreenState extends State<BottomNavScreen> {
9193
gradient: LinearGradient(
9294
begin: Alignment.topCenter,
9395
end: Alignment.bottomCenter,
94-
colors: [ AppColors.ongiBlue, AppColors.ongiOrange],
96+
colors: [ AppColors.ongiBlue, AppColors.ongiOrange ],
9597
),
9698
shape: BoxShape.circle,
99+
boxShadow: [
100+
BoxShadow(
101+
color: Colors.black12,
102+
blurRadius: 8,
103+
offset: Offset(0, 4),
104+
),
105+
],
97106
),
98107
child: const Icon(Icons.add, color: Colors.white, size: 36),
99108
),
@@ -138,17 +147,14 @@ class _BottomNavScreenState extends State<BottomNavScreen> {
138147
child: Column(
139148
mainAxisAlignment: MainAxisAlignment.center,
140149
children: [
141-
isSelected
142-
? Container(
143-
child: iconWidget,
144-
)
145-
: iconWidget,
150+
iconWidget,
146151
const SizedBox(height: 4),
147152
Text(
148153
text,
149154
style: TextStyle(
150155
fontSize: 12,
151-
color: isSelected ? AppColors.ongiOrange : Colors.grey[300],
156+
color:isSelected? AppColors.ongiOrange
157+
: Colors.grey[300],
152158
fontFamily: 'Pretendard',
153159
fontWeight: FontWeight.w600,
154160
),

frontend/ongi/lib/screens/photo/photo_date_screen.dart

Lines changed: 282 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:flutter/material.dart';
22
import 'package:ongi/core/app_light_background.dart';
33
import 'package:ongi/core/app_colors.dart';
4+
import 'dart:ui'; // Added for ImageFilter
45

56
class PhotoDateScreen extends StatefulWidget {
67
const PhotoDateScreen({super.key});
@@ -10,12 +11,292 @@ class PhotoDateScreen extends StatefulWidget {
1011
}
1112

1213
class _PhotoDateScreenState extends State<PhotoDateScreen> {
14+
int _currentPage = 1;
15+
final List<Map<String, String>> _photos = [
16+
{
17+
'main': 'assets/images/sample_family_photo.png',
18+
'sub': 'assets/images/sample_family_photo.png',
19+
'profile': 'assets/images/users/elderly_woman.png',
20+
'text': '엄마는 금정산 등산 덕에 활기가 너무 좋다~',
21+
'location': '부산광역시, 장전동',
22+
},
23+
{
24+
'main': 'assets/images/sample_family_photo.png',
25+
'sub': 'assets/images/sample_family_photo.png',
26+
'profile': 'assets/images/users/elderly_woman.png',
27+
'text': '오늘은 가족과 함께 산책 헤헤',
28+
'location': '서울특별시, 강남구',
29+
},
30+
{
31+
'main': 'assets/images/sample_family_photo.png',
32+
'sub': 'assets/images/sample_family_photo.png',
33+
'profile': 'assets/images/users/elderly_woman.png',
34+
'text': '즐거운 여행의 추억 :)',
35+
'location': '경기도, 수원시',
36+
},
37+
];
38+
1339
@override
1440
Widget build(BuildContext context) {
41+
final screenWidth = MediaQuery.of(context).size.width;
42+
final screenHeight = MediaQuery.of(context).size.height;
43+
final cardWidth = screenWidth;
44+
final cardHeight = screenHeight * 0.4;
45+
// 카드 크기 되돌림
1546
return Scaffold(
1647
backgroundColor: Colors.transparent,
1748
body: AppLightBackground(
18-
child: Padding(padding: const EdgeInsets.all(24)),
49+
child: Column(
50+
crossAxisAlignment: CrossAxisAlignment.start,
51+
children: [
52+
const SizedBox(height: 125),
53+
Expanded(
54+
child: Padding(
55+
padding: const EdgeInsets.symmetric(horizontal: 40),
56+
child: Column(
57+
crossAxisAlignment: CrossAxisAlignment.start,
58+
children: [
59+
// 타이틀
60+
const Text(
61+
'우리가족의',
62+
style: TextStyle(
63+
fontSize: 60,
64+
fontWeight: FontWeight.w200,
65+
height: 1.2,
66+
color: AppColors.ongiOrange,
67+
),
68+
),
69+
const Text(
70+
'마음 기록',
71+
style: TextStyle(
72+
fontSize: 60,
73+
fontWeight: FontWeight.w800,
74+
height: 1.2,
75+
color: AppColors.ongiOrange,
76+
),
77+
),
78+
const SizedBox(height: 32),
79+
// 사진 카드 PageView
80+
Center(
81+
child: SizedBox(
82+
width: cardWidth,
83+
height: cardHeight,
84+
child: PageView.builder(
85+
itemCount: _photos.length,
86+
controller: PageController(viewportFraction: 0.78, initialPage: _currentPage),
87+
onPageChanged: (idx) => setState(() => _currentPage = idx),
88+
itemBuilder: (context, idx) {
89+
final photo = _photos[idx];
90+
final isActive = idx == _currentPage;
91+
return AnimatedContainer(
92+
duration: const Duration(milliseconds: 200),
93+
margin: EdgeInsets.symmetric(
94+
horizontal: isActive ? 0 : 8,
95+
vertical: isActive ? 0 : 16,
96+
),
97+
width: cardWidth,
98+
height: cardHeight,
99+
child: Stack(
100+
clipBehavior: Clip.none,
101+
children: [
102+
ClipRRect(
103+
borderRadius: BorderRadius.circular(32),
104+
child: isActive
105+
? Image.asset(
106+
photo['main']!,
107+
width: cardWidth,
108+
height: cardHeight,
109+
fit: BoxFit.cover,
110+
)
111+
: ImageFiltered(
112+
imageFilter: ImageFilter.blur(sigmaX: 8, sigmaY: 8),
113+
child: Opacity(
114+
opacity: 0.7,
115+
child: Image.asset(
116+
photo['main']!,
117+
width: cardWidth,
118+
height: cardHeight,
119+
fit: BoxFit.cover,
120+
),
121+
),
122+
),
123+
),
124+
// 좌상단 서브(프로필) 사진
125+
Positioned(
126+
left: 16,
127+
top: 16,
128+
child: Container(
129+
width: 88,
130+
height: 100,
131+
decoration: BoxDecoration(
132+
border: Border.all(color: AppColors.ongiOrange, width: 3),
133+
borderRadius: BorderRadius.circular(15),
134+
),
135+
child: ClipRRect(
136+
borderRadius: BorderRadius.circular(15),
137+
child: Image.asset(
138+
photo['sub'] ?? photo['main']!,
139+
fit: BoxFit.cover,
140+
),
141+
),
142+
),
143+
),
144+
// 하단 오버레이
145+
Positioned(
146+
left: 0,
147+
right: 0,
148+
bottom: 0,
149+
child: Container(
150+
padding: const EdgeInsets.fromLTRB(20, 16, 20, 24),
151+
decoration: BoxDecoration(
152+
borderRadius: const BorderRadius.only(
153+
bottomLeft: Radius.circular(32),
154+
bottomRight: Radius.circular(32),
155+
),
156+
gradient: LinearGradient(
157+
begin: Alignment.topCenter,
158+
end: Alignment.bottomCenter,
159+
colors: [
160+
Colors.black.withOpacity(0.0),
161+
Colors.black.withOpacity(0.4),
162+
],
163+
),
164+
),
165+
child: Column(
166+
crossAxisAlignment: CrossAxisAlignment.start,
167+
mainAxisSize: MainAxisSize.min,
168+
children: [
169+
Row(
170+
children: [
171+
// 원형 프로필
172+
CircleAvatar(
173+
radius: 16,
174+
backgroundImage: AssetImage(photo['profile']!),
175+
),
176+
const SizedBox(width: 8),
177+
Expanded(
178+
child: Text(
179+
photo['text']!,
180+
style: const TextStyle(
181+
color: Colors.white,
182+
fontSize: 10,
183+
fontFamily: 'Pretendard',
184+
fontWeight: FontWeight.w500,
185+
shadows: [
186+
Shadow(
187+
color: Colors.black38,
188+
blurRadius: 4,
189+
offset: Offset(0, 2),
190+
),
191+
],
192+
),
193+
),
194+
),
195+
],
196+
),
197+
const SizedBox(height: 8),
198+
// 위치 버튼 스타일
199+
Align(
200+
alignment: Alignment.center,
201+
child: Container(
202+
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
203+
decoration: BoxDecoration(
204+
color: Colors.white,
205+
borderRadius: BorderRadius.circular(20),
206+
),
207+
child: Row(
208+
mainAxisSize: MainAxisSize.min,
209+
children: [
210+
Icon(Icons.place, color: AppColors.ongiOrange, size: 16),
211+
const SizedBox(width: 4),
212+
Text(
213+
photo['location']!,
214+
style: TextStyle(
215+
color: AppColors.ongiOrange,
216+
fontSize: 11,
217+
fontWeight: FontWeight.w500,
218+
fontFamily: 'Pretendard',
219+
),
220+
),
221+
],
222+
),
223+
),
224+
),
225+
],
226+
),
227+
),
228+
),
229+
],
230+
),
231+
);
232+
},
233+
),
234+
),
235+
),
236+
// 감정 태그 버튼
237+
Row(
238+
mainAxisAlignment: MainAxisAlignment.center,
239+
children: [
240+
_buildTagButton('뿌듯함', AppColors.ongiOrange),
241+
const SizedBox(width: 6),
242+
_buildTagButton('기운이 남', AppColors.ongiOrange),
243+
const SizedBox(width: 6),
244+
_buildTagButton('들뜸', AppColors.ongiOrange),
245+
],
246+
),
247+
const SizedBox(height: 16),
248+
// 페이지인디케이터
249+
Row(
250+
mainAxisAlignment: MainAxisAlignment.center,
251+
children: [
252+
for (int i = 0; i < _photos.length; i++) ...[
253+
_buildIndicator(i == _currentPage),
254+
if (i != _photos.length - 1) const SizedBox(width: 6),
255+
]
256+
],
257+
),
258+
],
259+
),
260+
),
261+
),
262+
],
263+
),
264+
),
265+
);
266+
}
267+
268+
Widget _buildTagButton(String text, Color color) {
269+
return OutlinedButton(
270+
onPressed: () {},
271+
style: OutlinedButton.styleFrom(
272+
side: BorderSide(color: color, width: 1.5),
273+
shape: RoundedRectangleBorder(
274+
borderRadius: BorderRadius.circular(20),
275+
),
276+
backgroundColor: AppColors.ongiOrange,
277+
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 15),
278+
minimumSize: Size.zero,
279+
visualDensity: VisualDensity.compact,
280+
),
281+
child: Text(
282+
text,
283+
style: TextStyle(
284+
color: Colors.white,
285+
fontWeight: FontWeight.w700,
286+
fontSize: 12,
287+
fontFamily: 'Pretendard',
288+
),
289+
),
290+
);
291+
}
292+
293+
Widget _buildIndicator(bool isActive) {
294+
return Container(
295+
width: isActive ? 15 : 10,
296+
height: isActive ? 15 : 10,
297+
decoration: BoxDecoration(
298+
color: isActive ? AppColors.ongiOrange : Colors.grey[300],
299+
borderRadius: BorderRadius.circular(8),
19300
),
20301
);
21302
}

frontend/ongi/pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ flutter:
5959
- assets/images/step_tracker_crown.svg
6060
- assets/images/step_tracker_light_background.svg
6161
- assets/images/step_tracker_rectangle.svg
62+
- assets/images/sample_family_photo.png
6263

6364
fonts:
6465
- family: Pretendard

0 commit comments

Comments
 (0)