From 04892d5e65cdc2a45b4fb010e29732c52f81ebb5 Mon Sep 17 00:00:00 2001 From: sihoo Date: Wed, 9 Sep 2026 08:31:10 +0900 Subject: [PATCH] =?UTF-8?q?=EC=8A=A4=EB=A7=88=ED=8A=B8=EA=B8=B0=EA=B8=B0?= =?UTF-8?q?=20=EB=B0=98=EC=B6=9C=20=EB=8C=80=EC=9E=A5:=201=EC=8B=9C?= =?UTF-8?q?=EA=B0=84=2059=EB=B6=84=20=EC=9D=B4=EC=83=81=20=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=EC=9D=80=20=EB=AA=A9=EB=A1=9D=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EB=B9=A8=EA=B0=84=20=ED=85=8C=EB=91=90=EB=A6=AC=EB=A1=9C=20?= =?UTF-8?q?=ED=91=9C=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 기존엔 "많은 시간요청 학생" 팝업에서만 2시간 기준으로 걸러냈는데, 메인 목록 카드 자체에도 (대기중/승인/거절 등 상태 무관하게) 빨간 테두리를 씌워서 바로 눈에 띄게 함. 기준을 2시간 → 1시간 59분(119분)으로 낮춰서 두 기능이 같은 기준을 쓰도록 통일. Co-Authored-By: Claude Sonnet 5 --- .../device_checkout_ledger_controller.dart | 33 +++++++++++++------ lib/ui/device_checkout_ledger_page.dart | 23 ++++++++++--- 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/lib/function/device_checkout_ledger_controller.dart b/lib/function/device_checkout_ledger_controller.dart index c942bfa..9ba4d34 100644 --- a/lib/function/device_checkout_ledger_controller.dart +++ b/lib/function/device_checkout_ledger_controller.dart @@ -16,25 +16,38 @@ class DeviceCheckoutLedgerController extends ChangeNotifier { bool get isLoading => _isLoading; bool get isWorking => _isWorking; - /// ⏰ 요청 시간이 얼마나 되는지(시간 단위). 형식이 이상하면 null. - double? durationHours(dynamic request) { + // 🚨 [장시간 요청 기준] 1시간 59분(119분) 이상이면 "많은 시간요청"으로 본다. + static const int longRequestMinutes = 119; + + int? _durationMinutes(dynamic request) { try { final start = DateTime.parse(request['requestedStart']); final end = DateTime.parse(request['requestedEnd']); final minutes = end.difference(start).inMinutes; - return minutes > 0 ? minutes / 60.0 : null; + return minutes > 0 ? minutes : null; } catch (_) { return null; } } - /// 🚨 [장시간 요청 감지] 2시간 넘게 신청한, 아직 대기 중인 요청 목록. - /// 학생이 시간을 비정상적으로 길게 적어냈을 수 있으니 전체 승인 전에 따로 훑어볼 수 있게 한다. - List get longPendingRequests => _requests.where((r) { - if (r['status'] != 'PENDING') return false; - final hours = durationHours(r); - return hours != null && hours >= 2; - }).toList(); + /// ⏰ 요청 시간이 얼마나 되는지(시간 단위). 형식이 이상하면 null. + double? durationHours(dynamic request) { + final minutes = _durationMinutes(request); + return minutes == null ? null : minutes / 60.0; + } + + /// 🚨 [장시간 요청 감지] 1시간 59분 넘게 신청했는지. 상태(대기/승인 등)와 무관하게 판단한다 - + /// 목록 카드에 빨간 테두리를 씌우는 데 쓴다. + bool isLongRequest(dynamic request) { + final minutes = _durationMinutes(request); + return minutes != null && minutes >= longRequestMinutes; + } + + /// 학생이 시간을 비정상적으로 길게 적어냈을 수 있으니, 아직 대기 중인 장시간 요청만 + /// 따로 모아서 전체 승인 전에 훑어볼 수 있게 한다. + List get longPendingRequests => _requests + .where((r) => r['status'] == 'PENDING' && isLongRequest(r)) + .toList(); void _safeNotify() { if (!_disposed) notifyListeners(); diff --git a/lib/ui/device_checkout_ledger_page.dart b/lib/ui/device_checkout_ledger_page.dart index 3090715..bcce350 100644 --- a/lib/ui/device_checkout_ledger_page.dart +++ b/lib/ui/device_checkout_ledger_page.dart @@ -89,7 +89,7 @@ class _DeviceCheckoutLedgerPageState extends State { ); } - // 🚨 [많은 시간요청 학생] 2시간 넘게 신청한 대기 중인 요청만 따로 모아 보여준다. + // 🚨 [많은 시간요청 학생] 1시간 59분 넘게 신청한 대기 중인 요청만 따로 모아 보여준다. // 학생이 시간을 비정상적으로 길게 적어냈을 수 있으니, 전체 승인 전에 훑어보는 용도. void _showLongRequestsDialog() { showDialog( @@ -113,7 +113,7 @@ class _DeviceCheckoutLedgerPageState extends State { return const Padding( padding: EdgeInsets.symmetric(vertical: 16), child: Text( - '2시간 넘게 신청한 대기 중인 요청이 없습니다.', + '1시간 59분 넘게 신청한 대기 중인 요청이 없습니다.', style: TextStyle(color: Colors.grey), ), ); @@ -320,6 +320,10 @@ class _DeviceCheckoutLedgerPageState extends State { final String status = r['status']; final info = _statusInfo(status); final bool isPending = status == 'PENDING'; + // 🚨 1시간 59분 넘게 신청했으면 상태와 무관하게 빨간 테두리로 눈에 띄게. + final bool isLong = _controller.isLongRequest( + r, + ); return Card( elevation: 0, @@ -327,9 +331,18 @@ class _DeviceCheckoutLedgerPageState extends State { margin: const EdgeInsets.only(bottom: 10), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), - side: isPending - ? BorderSide(color: Colors.orange[300]!) - : BorderSide(color: AppPalette.sage), + side: isLong + ? BorderSide( + color: Colors.red[400]!, + width: 2, + ) + : (isPending + ? BorderSide( + color: Colors.orange[300]!, + ) + : BorderSide( + color: AppPalette.sage, + )), ), child: Padding( padding: const EdgeInsets.all(16),