Skip to content
20 changes: 16 additions & 4 deletions frontend/ongi/lib/screens/health/add_pill_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -260,10 +260,22 @@ class _AddPillScreenState extends State<AddPillScreen> {
);

if (!mounted) return;
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => const PillUpdatePopup()),
);

// 즉시 홈으로 돌아가면서 성공 결과 전달
Navigator.pop(context, true);

// 성공 팝업을 약간 지연 후 표시 (홈 화면이 먼저 업데이트되도록)
Future.delayed(const Duration(milliseconds: 100), () {
if (!mounted) return;
showDialog(
context: context,
barrierDismissible: true,
builder: (BuildContext context) => Dialog(
backgroundColor: Colors.transparent,
child: const PillUpdatePopup(),
),
);
});
} catch (e) {
if (!mounted) return;
ScaffoldMessenger.of(
Expand Down
8 changes: 4 additions & 4 deletions frontend/ongi/lib/screens/health/exercise_record_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ class _ExerciseRecordScreenState extends State<ExerciseRecordScreen> {
_dateCarouselController.jumpToPage(targetPage);
}

// 새로운 날짜의 서버 데이터 조회
//새로운 날짜의 서버 데이터 조회
_loadExerciseFromServer(normalizedDate);

Future.delayed(const Duration(milliseconds: 100), () {
Expand Down Expand Up @@ -642,9 +642,9 @@ class _ExerciseRecordScreenState extends State<ExerciseRecordScreen> {
height: 1,
),
),
const Text(
'다 채우셨나요?',
style: TextStyle(
Text(
_isChild ? '다 채우셨을까요?' : '다 채우셨나요?',
style: const TextStyle(
fontSize: 40,
color: Colors.white,
fontWeight: FontWeight.w600,
Expand Down
99 changes: 55 additions & 44 deletions frontend/ongi/lib/screens/health/health_home_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ class _HealthHomeScreenState extends State<HealthHomeScreen> {
),
SizedBox(height: 3),
Text(
'입력되지 않았어요!',
'입력되지 \n않았어요!',
style: TextStyle(
fontSize: 38,
fontWeight: FontWeight.w600,
Expand Down Expand Up @@ -539,54 +539,65 @@ class _HealthHomeScreenState extends State<HealthHomeScreen> {
if (_isChild && !_isLoadingParents) {
// 자녀인 경우 드롭다운 표시
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(25),
boxShadow: [
BoxShadow(
color: Colors.black38,
blurRadius: 4,
offset: const Offset(0, 4),
),
],
),
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
child: DropdownButtonHideUnderline(
child: DropdownButton<String>(
value: _selectedParentId,
icon: const SizedBox.shrink(),
dropdownColor: Colors.white,
isDense: false,
itemHeight: 65,
borderRadius: BorderRadius.circular(20),
style: const TextStyle(
fontSize: 60,
fontWeight: FontWeight.w800,
color: AppColors.ongiOrange,
),
items: _parentMembers.map((parent) {
return DropdownMenuItem<String>(
value: parent['uuid'],
child: Text(
_formatNameForDisplay(parent['name']),
style: const TextStyle(
fontSize: 60,
fontWeight: FontWeight.w800,
color: AppColors.ongiOrange,
Flexible(
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(25),
boxShadow: [
BoxShadow(
color: Colors.black38,
blurRadius: 4,
offset: const Offset(0, 4),
),
],
),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
child: DropdownButtonHideUnderline(
child: DropdownButton<String>(
value: _selectedParentId,
icon: const SizedBox.shrink(),
dropdownColor: Colors.white,
isDense: false,
itemHeight: 80, // 높이 증가로 폰트 클리핑 방지
borderRadius: BorderRadius.circular(20),
isExpanded: false, // 내용에 맞는 너비
style: const TextStyle(
fontSize: 60,
fontWeight: FontWeight.w800,
color: AppColors.ongiOrange,
height: 1.1, // 줄 높이 조정으로 클리핑 방지
),
items: _parentMembers.map((parent) {
return DropdownMenuItem<String>(
value: parent['uuid'],
child: Container(
alignment: Alignment.centerLeft,
child: Text(
_formatNameForDisplay(parent['name']),
style: const TextStyle(
fontSize: 60,
fontWeight: FontWeight.w800,
color: AppColors.ongiOrange,
height: 1.1, // 줄 높이 조정
),
overflow: TextOverflow.ellipsis,
),
),
),
);
}).toList(),
onChanged: (String? newValue) {
if (newValue != null) {
_onParentSelected(newValue);
}
},
);
}).toList(),
onChanged: (String? newValue) {
if (newValue != null) {
_onParentSelected(newValue);
}
},
),
),
),
),
const SizedBox(width: 8), // 간격 추가
const Text(
'님의',
style: TextStyle(
Expand Down
111 changes: 90 additions & 21 deletions frontend/ongi/lib/screens/health/pill_history_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ class _PillHistoryScreenState extends State<PillHistoryScreen> {
// 자녀 사용자 관련 상태
bool _isChild = false;
String? _selectedParentId;

// 약 복용 상태 관련
int _todayPillCount = 0;

@override
void initState() {
Expand Down Expand Up @@ -83,16 +86,41 @@ class _PillHistoryScreenState extends State<PillHistoryScreen> {
taken.add('$pillId|$hhmm');
}
}
// 약 복용 카운트 계산
int totalIntakes = 0;
int takenIntakes = 0;

for (var pill in schedule) {
final List<dynamic> intakeTimes = pill['intakeTimes'] ?? [];
final Map<String, dynamic> dayIntakeStatus = pill['dayIntakeStatus'] ?? {};

totalIntakes += intakeTimes.length;

// dayIntakeStatus에서 실제 복용한 시간들을 확인
for (var intakeTime in intakeTimes) {
final timeKey = intakeTime.toString().substring(0, 5); // "08:00:00" -> "08:00"
if (dayIntakeStatus.containsKey(timeKey)) {
takenIntakes++;
}
}
}

// 남은 복용 횟수
int remainingIntakes = totalIntakes - takenIntakes;
if (remainingIntakes < 0) remainingIntakes = 0;

setState(() {
_todaySchedule = schedule;
_takenKeys
..clear()
..addAll(taken);
_todayPillCount = remainingIntakes;
_isLoading = false;
});
} catch (e) {
setState(() {
_todaySchedule = <Map<String, dynamic>>[];
_todayPillCount = 0;
_isLoading = false;
});
}
Expand Down Expand Up @@ -122,6 +150,54 @@ class _PillHistoryScreenState extends State<PillHistoryScreen> {
}
}

Widget _buildPillStatusText() {
if (_todayPillCount == 0) {
return const Column(
children: [
Text(
'오늘의 약을',
style: TextStyle(
fontSize: 25,
color: Colors.white,
fontWeight: FontWeight.w600,
height: 1,
),
),
Text(
'모두 섭취하셨어요!',
style: TextStyle(
fontSize: 40,
color: Colors.white,
fontWeight: FontWeight.w600,
),
),
],
);
} else {
return Column(
children: [
Text(
_isChild ? '오늘 ${_todayPillCount}개의 약을' : '오늘 복용해야 할 약,',
style: const TextStyle(
fontSize: 25,
color: Colors.white,
fontWeight: FontWeight.w600,
height: 1,
),
),
Text(
_isChild ? '섭취하지 않으셨어요!' : '다 섭취 하셨나요?',
style: const TextStyle(
fontSize: 40,
color: Colors.white,
fontWeight: FontWeight.w600,
),
),
],
);
}
}

Future<void> _addRecord({
required String pillId,
required String intakeTime,
Expand All @@ -131,6 +207,7 @@ class _PillHistoryScreenState extends State<PillHistoryScreen> {
// 즉시 UI 업데이트 (서버 응답 전)
setState(() {
_takenKeys.add(key);
if (_todayPillCount > 0) _todayPillCount--;
});

try {
Expand Down Expand Up @@ -159,6 +236,7 @@ class _PillHistoryScreenState extends State<PillHistoryScreen> {
// 서버 요청 실패 시 UI 상태 롤백
setState(() {
_takenKeys.remove(key);
_todayPillCount++;
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
Expand Down Expand Up @@ -186,6 +264,7 @@ class _PillHistoryScreenState extends State<PillHistoryScreen> {
// 즉시 UI 업데이트 (서버 응답 전)
setState(() {
_takenKeys.remove(key);
_todayPillCount++;
});

try {
Expand Down Expand Up @@ -214,6 +293,7 @@ class _PillHistoryScreenState extends State<PillHistoryScreen> {
// 서버 요청 실패 시 UI 상태 롤백
setState(() {
_takenKeys.add(key);
if (_todayPillCount > 0) _todayPillCount--;
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
Expand Down Expand Up @@ -264,23 +344,7 @@ class _PillHistoryScreenState extends State<PillHistoryScreen> {
maxHeight: double.infinity,
child: Column(
children: [
const Text(
'오늘 복용해야 할 약,',
style: TextStyle(
fontSize: 25,
color: Colors.white,
fontWeight: FontWeight.w600,
height: 1,
),
),
const Text(
'다 섭취 하셨나요?',
style: TextStyle(
fontSize: 40,
color: Colors.white,
fontWeight: FontWeight.w600,
),
),
_buildPillStatusText(),
Image.asset(
'assets/images/pill_history_title_logo.png',
width: circleSize * 0.26,
Expand Down Expand Up @@ -314,17 +378,22 @@ class _PillHistoryScreenState extends State<PillHistoryScreen> {
itemBuilder: (context, index) {
if (index == _todaySchedule.length) {
return GestureDetector(
onTap: () {
Navigator.push(
onTap: () async {
final result = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AddPillScreen(
targetParentId: _selectedParentId,
),
),
).then((_) {
);

// 약 추가 성공 시 즉시 새로고침
if (result == true) {
print('약 추가 성공 - 즉시 데이터 새로고침');
// 즉시 새로고침
_fetchTodaySchedule();
});
}
},
child: Container(
margin: const EdgeInsets.symmetric(
Expand Down
Loading
Loading