// ๐Ÿ“ ์„ ์ƒ๋‹˜ ์œ„์น˜ ๋“ฑ๋ก ํ™”๋ฉด(๊ต์‚ฌ์šฉ) (UI ์ „์šฉ). ๋ณธ์ธ ์œ„์น˜๋ฅผ ๋ฐ”๊พธ๊ณ , ๋ฐ›์€ ํ˜ธ์ถœ์„ ํ™•์ธํ•œ๋‹ค. // ์„œ๋ฒ„ ํ†ต์‹ /์ƒํƒœ๋Š” lib/function/teacher_location_controller.dart๊ฐ€ ๋‹ด๋‹นํ•œ๋‹ค. import 'package:flutter/material.dart'; import '../data/teacher_call_schedule.dart'; import '../function/teacher_location_controller.dart'; import '../theme/app_palette.dart'; import 'app_notice.dart'; import 'title_pill.dart'; class TeacherLocationScreen extends StatefulWidget { final String teacherId; const TeacherLocationScreen({super.key, required this.teacherId}); @override State createState() => _TeacherLocationScreenState(); } class _TeacherLocationScreenState extends State { late final TeacherLocationController _controller; @override void initState() { super.initState(); _controller = TeacherLocationController(teacherId: widget.teacherId); _controller.init(); } @override void dispose() { _controller.dispose(); super.dispose(); } Future _selectLocation(String location) async { final (success, message) = await _controller.updateLocation(location); if (!mounted) return; AppNotice.show( context, message, icon: success ? Icons.check_circle_rounded : Icons.error_outline_rounded, ); } @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('๋‚ด ์œ„์น˜ ์•Œ๋ฆฌ๊ธฐ'), ), body: _controller.isLoading ? const Center(child: CircularProgressIndicator()) : RefreshIndicator( onRefresh: _controller.fetchReceivedCalls, child: ListView( padding: const EdgeInsets.all(16), children: [ Container( padding: const EdgeInsets.all(14), decoration: BoxDecoration( color: const Color(0xFFEFF6FF), borderRadius: BorderRadius.circular(14), ), child: Row( children: [ const Text( 'ํ˜„์žฌ ์œ„์น˜', style: TextStyle(fontWeight: FontWeight.bold), ), const Spacer(), Text( '${kLocationIcons[_controller.currentLocation] ?? '๐Ÿ“'} ${_controller.currentLocation}', style: const TextStyle( fontWeight: FontWeight.bold, color: AppPalette.ink, ), ), ], ), ), const SizedBox(height: 20), const Text( '์œ„์น˜ ์„ ํƒ', style: TextStyle(fontWeight: FontWeight.bold), ), const SizedBox(height: 8), GridView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, childAspectRatio: 1.3, crossAxisSpacing: 10, mainAxisSpacing: 10, ), itemCount: kLocationOptions.length, itemBuilder: (context, index) { final loc = kLocationOptions[index]; final isSelected = _controller.currentLocation == loc; return GestureDetector( onTap: _controller.isSaving ? null : () => _selectLocation(loc), child: Container( decoration: BoxDecoration( color: isSelected ? AppPalette.ink : AppPalette.paper, borderRadius: BorderRadius.circular(12), border: Border.all( color: isSelected ? AppPalette.ink : AppPalette.sage, ), ), child: Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( kLocationIcons[loc] ?? '๐Ÿ“', style: const TextStyle(fontSize: 20), ), const SizedBox(height: 4), Text( loc, style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, color: isSelected ? Colors.white : AppPalette.ink, ), ), ], ), ), ), ); }, ), const SizedBox(height: 24), const Text( '๋‚˜๋ฅผ ์ฐพ์€ ํ•™์ƒ ๊ธฐ๋ก', style: TextStyle(fontWeight: FontWeight.bold), ), const SizedBox(height: 8), _buildReceivedCalls(), ], ), ), ); }, ); } Widget _buildReceivedCalls() { if (_controller.receivedCalls.isEmpty) { return const Padding( padding: EdgeInsets.symmetric(vertical: 12), child: Text('์•„์ง ํ˜ธ์ถœ ๊ธฐ๋ก์ด ์—†์–ด์š”.', style: TextStyle(color: Colors.grey)), ); } return Column( children: [ for (final c in _controller.receivedCalls) Container( margin: const EdgeInsets.only(bottom: 8), padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10), decoration: BoxDecoration( color: AppPalette.paper, borderRadius: BorderRadius.circular(12), ), child: Row( children: [ Expanded( child: Text('${c['studentName']} ํ•™์ƒ ยท ${c['purpose']}'), ), Text( '${c['createdAt'] ?? ''}', style: const TextStyle(color: Colors.grey, fontSize: 11), ), ], ), ), ], ); } }