// ๐Ÿšฉ ์ปค๋ฎค๋‹ˆํ‹ฐ ๊ฒŒ์‹œํŒ - ์‹ ๊ณ  ๊ฒ€ํ† (์šด์˜์ž์šฉ) ํ™”๋ฉด (UI ์ „์šฉ). // ์„œ๋ฒ„ ํ†ต์‹ /์ƒํƒœ๋Š” lib/function/board_report_controller.dart๊ฐ€ ๋‹ด๋‹นํ•œ๋‹ค. import 'package:flutter/material.dart'; import '../function/board_report_controller.dart'; import '../theme/app_palette.dart'; import 'app_notice.dart'; import 'title_pill.dart'; class BoardReportScreen extends StatefulWidget { final String reviewerId; const BoardReportScreen({super.key, required this.reviewerId}); @override State createState() => _BoardReportScreenState(); } class _BoardReportScreenState extends State { late final BoardReportController _controller; @override void initState() { super.initState(); _controller = BoardReportController(reviewerId: widget.reviewerId); _controller.init(); } @override void dispose() { _controller.dispose(); super.dispose(); } Future _resolve(int reportId, String action) async { final (success, message) = await _controller.resolve(reportId, action); if (!mounted) return; AppNotice.show(context, message); } @override Widget build(BuildContext context) { return ListenableBuilder( listenable: _controller, builder: (context, _) { final reports = _controller.reports; 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()) : reports.isEmpty ? const Center( child: Text( '์ฒ˜๋ฆฌํ•  ์‹ ๊ณ ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.', style: TextStyle(color: Colors.grey), ), ) : RefreshIndicator( onRefresh: _controller.fetchPending, child: ListView.builder( padding: const EdgeInsets.all(16), itemCount: reports.length, itemBuilder: (context, index) { final report = reports[index]; final reportId = report['id'] as int; final alreadyDeleted = report['alreadyDeleted'] == true; return Container( margin: const EdgeInsets.only(bottom: 12), padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: AppPalette.paper, borderRadius: BorderRadius.circular(14), border: Border.all(color: AppPalette.sage), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Chip( label: Text( report['targetType'] == 'post' ? '๊ฒŒ์‹œ๊ธ€' : '๋Œ“๊ธ€', ), visualDensity: VisualDensity.compact, backgroundColor: AppPalette.mist, ), const SizedBox(width: 8), Text( '${report['createdAt'] ?? ''}', style: const TextStyle( color: Colors.grey, fontSize: 12, ), ), ], ), const SizedBox(height: 10), Text( '${report['targetContent'] ?? ''}', style: const TextStyle(fontSize: 14, height: 1.4), ), const SizedBox(height: 8), if (report['reason'] != null && '${report['reason']}'.isNotEmpty) Text( '์‹ ๊ณ  ์‚ฌ์œ : ${report['reason']}', style: const TextStyle( color: Colors.redAccent, fontSize: 12.5, ), ), Text( '์‹ ๊ณ ์ž ํ•™๋ฒˆ: ${report['reporterStudentId'] ?? ''}', style: const TextStyle( color: Colors.grey, fontSize: 12, ), ), const SizedBox(height: 12), if (alreadyDeleted) const Text( '์ด๋ฏธ ์‚ญ์ œ๋œ ํ•ญ๋ชฉ์ž…๋‹ˆ๋‹ค.', style: TextStyle(color: Colors.grey), ) else Row( children: [ Expanded( child: OutlinedButton( onPressed: _controller.isBusy ? null : () => _resolve(reportId, 'dismiss'), child: const Text('์œ ์ง€ (๋ฌธ์ œ ์—†์Œ)'), ), ), const SizedBox(width: 8), Expanded( child: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Colors.red[400], foregroundColor: Colors.white, ), onPressed: _controller.isBusy ? null : () => _resolve(reportId, 'delete'), child: const Text('์‚ญ์ œ'), ), ), ], ), ], ), ); }, ), ), ); }, ); } }