// ๐Ÿ“ฑ ์Šค๋งˆํŠธ๊ธฐ๊ธฐ(ํŒจ๋“œ) ๋ฐ˜์ถœ ์‹ ์ฒญ ํ™”๋ฉด (UI ์ „์šฉ). ์‹œ์ž‘~์ข…๋ฃŒ ์‹œ๊ฐ๊ณผ ์‚ฌ์šฉ ๋ชฉ์ ์„ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค. // ์„œ๋ฒ„ ํ†ต์‹ /์ƒํƒœ๋Š” lib/function/device_checkout_controller.dart๊ฐ€ ๋‹ด๋‹นํ•œ๋‹ค. import 'package:flutter/material.dart'; import '../function/device_checkout_controller.dart'; import '../theme/app_palette.dart'; import 'app_notice.dart'; import 'title_pill.dart'; class DeviceCheckoutRequestScreen extends StatefulWidget { final String studentId; final String studentName; const DeviceCheckoutRequestScreen({ super.key, required this.studentId, required this.studentName, }); @override State createState() => _DeviceCheckoutRequestScreenState(); } class _DeviceCheckoutRequestScreenState extends State { final DeviceCheckoutController _controller = DeviceCheckoutController(); final TextEditingController _purposeController = TextEditingController(); TimeOfDay? _startTime; TimeOfDay? _endTime; @override void dispose() { _controller.dispose(); _purposeController.dispose(); super.dispose(); } String _formatTime(TimeOfDay time) => '${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}'; Future _pickStartTime() async { final picked = await showTimePicker( context: context, initialTime: _startTime ?? TimeOfDay.now(), helpText: '์‚ฌ์šฉ ์‹œ์ž‘ ์‹œ๊ฐ', ); if (picked != null) setState(() => _startTime = picked); } Future _pickEndTime() async { final picked = await showTimePicker( context: context, initialTime: _endTime ?? TimeOfDay.now(), helpText: '์‚ฌ์šฉ ์ข…๋ฃŒ ์‹œ๊ฐ', ); if (picked != null) setState(() => _endTime = picked); } Future _submit() async { final purpose = _purposeController.text.trim(); if (_startTime == null || _endTime == null || purpose.isEmpty) { AppNotice.show(context, '์‹œ์ž‘/์ข…๋ฃŒ ์‹œ๊ฐ๊ณผ ์‚ฌ์šฉ ๋ชฉ์ ์„ ๋ชจ๋‘ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.'); return; } final (success, message) = await _controller.submitRequest( studentId: widget.studentId, studentName: widget.studentName, purpose: purpose, startTime: _formatTime(_startTime!), endTime: _formatTime(_endTime!), ); if (!mounted) return; AppNotice.show(context, message); if (success) Navigator.pop(context); } @override Widget build(BuildContext context) { return ListenableBuilder( listenable: _controller, builder: (context, _) { return Scaffold( backgroundColor: AppPalette.mist, appBar: AppBar( backgroundColor: Colors.transparent, foregroundColor: AppPalette.ink, elevation: 0, centerTitle: true, title: const TitlePill( child: Text( '์Šค๋งˆํŠธ๊ธฐ๊ธฐ ๋ฐ˜์ถœ ์‹ ์ฒญ', style: TextStyle( fontWeight: FontWeight.bold, color: Colors.white, ), ), ), ), body: SingleChildScrollView( padding: const EdgeInsets.all(24.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'ํŒจ๋“œ๋Š” NFC ํƒœ๊ทธ๊ฐ€ ์•ˆ ๋˜๋‹ˆ, ์‚ฌ์šฉ ์‹œ๊ฐ„๊ณผ ๋ชฉ์ ์„ ์ ์–ด ์‹ ์ฒญํ•˜๋ฉด\n' '์„ ์ƒ๋‹˜์ด ํ™•์ธํ•˜๊ณ  ์Šน์ธํ•ด์ค๋‹ˆ๋‹ค. ์Šน์ธ๋˜๋ฉด ๋ฐ˜๋‚ฉ ๋ฐ”๊ตฌ๋‹ˆ์—์„œ ๊บผ๋‚ด ์“ฐ์„ธ์š”.', style: TextStyle( color: Colors.black54, fontSize: 13, height: 1.4, ), ), const SizedBox(height: 24), Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: AppPalette.paper, borderRadius: BorderRadius.circular(24), border: Border.all(color: AppPalette.sage), ), child: Column( children: [ Row( children: [ Expanded( child: OutlinedButton.icon( onPressed: _pickStartTime, icon: const Icon(Icons.play_arrow_rounded), label: Text( _startTime == null ? '์‹œ์ž‘ ์‹œ๊ฐ' : _formatTime(_startTime!), ), ), ), const SizedBox(width: 12), Expanded( child: OutlinedButton.icon( onPressed: _pickEndTime, icon: const Icon(Icons.stop_rounded), label: Text( _endTime == null ? '์ข…๋ฃŒ ์‹œ๊ฐ' : _formatTime(_endTime!), ), ), ), ], ), const SizedBox(height: 16), TextField( controller: _purposeController, maxLines: 3, decoration: const InputDecoration( labelText: '์‚ฌ์šฉ ๋ชฉ์ ', hintText: '์˜ˆ: ์ˆ˜ํ–‰ํ‰๊ฐ€ ์ž๋ฃŒ์กฐ์‚ฌ', alignLabelWithHint: true, border: OutlineInputBorder(), ), ), const SizedBox(height: 20), SizedBox( width: double.infinity, height: 50, child: ElevatedButton( onPressed: _controller.isSubmitting ? null : _submit, style: ElevatedButton.styleFrom( backgroundColor: AppPalette.ink, foregroundColor: AppPalette.paper, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: _controller.isSubmitting ? const CircularProgressIndicator( color: Colors.white, ) : const Text( '๋ฐ˜์ถœ ์‹ ์ฒญํ•˜๊ธฐ', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 15, ), ), ), ), ], ), ), ], ), ), ); }, ); } }