// ๐Ÿ’ฌ ์ปค๋ฎค๋‹ˆํ‹ฐ ๊ฒŒ์‹œํŒ - ๊ฒŒ์‹œ๊ธ€ ์ƒ์„ธ(+๋Œ“๊ธ€) ํ™”๋ฉด์˜ ๊ธฐ๋Šฅ(์„œ๋ฒ„ ํ†ต์‹ /์ƒํƒœ) ๋‹ด๋‹น ์ปจํŠธ๋กค๋Ÿฌ. import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:http/http.dart' as http; import '../config.dart'; class BoardPostController extends ChangeNotifier { final int postId; final String studentId; BoardPostController({required this.postId, required this.studentId}); bool _isLoading = true; bool _isBusy = false; bool _postDeleted = false; Map? _post; List _comments = []; bool _disposed = false; bool get isLoading => _isLoading; bool get isBusy => _isBusy; bool get postDeleted => _postDeleted; Map? get post => _post; List get comments => _comments; void _safeNotify() { if (!_disposed) notifyListeners(); } @override void dispose() { _disposed = true; super.dispose(); } Future init() => fetchDetail(); Future fetchDetail() async { _isLoading = true; _safeNotify(); try { final response = await http.get( Uri.parse('$baseUrl/api/board/posts/$postId?studentId=$studentId'), ); final result = jsonDecode(utf8.decode(response.bodyBytes)); if (response.statusCode == 200 && result['status'] == 'success') { _post = Map.from(result['post']); _comments = result['comments'] ?? []; } else { _postDeleted = true; } } catch (_) { // ์กฐ์šฉํžˆ ๋ฌด์‹œ - ๋งˆ์ง€๋ง‰์œผ๋กœ ๋ฐ›์•„์˜จ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•œ๋‹ค. } finally { _isLoading = false; _safeNotify(); } } Future<(bool success, String message)> addComment(String content) async { if (content.trim().isEmpty) return (false, '๋Œ“๊ธ€ ๋‚ด์šฉ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.'); _isBusy = true; _safeNotify(); try { final response = await http.post( Uri.parse('$baseUrl/api/board/posts/$postId/comments'), headers: {"Content-Type": "application/json"}, body: jsonEncode({"studentId": studentId, "content": content.trim()}), ); final result = jsonDecode(utf8.decode(response.bodyBytes)); if (response.statusCode == 200 && result['status'] == 'success') { await fetchDetail(); return (true, '๋Œ“๊ธ€์ด ๋“ฑ๋ก๋˜์—ˆ์Šต๋‹ˆ๋‹ค.'); } return (false, '${result['message'] ?? '๋Œ“๊ธ€ ๋“ฑ๋ก ์‹คํŒจ'}'); } catch (e) { return (false, '๋„คํŠธ์›Œํฌ ์—๋Ÿฌ: $e'); } finally { _isBusy = false; _safeNotify(); } } Future<(bool success, String message)> deletePost() async { return _delete('$baseUrl/api/board/posts/$postId'); } Future<(bool success, String message)> deleteComment(int commentId) async { final (success, message) = await _delete( '$baseUrl/api/board/comments/$commentId', ); if (success) await fetchDetail(); return (success, message); } Future<(bool success, String message)> _delete(String url) async { _isBusy = true; _safeNotify(); try { final response = await http.delete( Uri.parse(url), headers: {"Content-Type": "application/json"}, body: jsonEncode({"studentId": studentId}), ); final result = jsonDecode(utf8.decode(response.bodyBytes)); if (response.statusCode == 200 && result['status'] == 'success') { return (true, '${result['message'] ?? '์‚ญ์ œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.'}'); } return (false, '${result['message'] ?? '์‚ญ์ œ ์‹คํŒจ'}'); } catch (e) { return (false, '๋„คํŠธ์›Œํฌ ์—๋Ÿฌ: $e'); } finally { _isBusy = false; _safeNotify(); } } Future<(bool success, String message)> report({ required String targetType, required int targetId, String? reason, }) async { try { final response = await http.post( Uri.parse('$baseUrl/api/board/reports'), headers: {"Content-Type": "application/json"}, body: jsonEncode({ "targetType": targetType, "targetId": targetId, "reporterStudentId": studentId, "reason": reason, }), ); final result = jsonDecode(utf8.decode(response.bodyBytes)); if (response.statusCode == 200 && result['status'] == 'success') { return (true, '${result['message'] ?? '์‹ ๊ณ ๊ฐ€ ์ ‘์ˆ˜๋˜์—ˆ์Šต๋‹ˆ๋‹ค.'}'); } return (false, '${result['message'] ?? '์‹ ๊ณ  ์ ‘์ˆ˜ ์‹คํŒจ'}'); } catch (e) { return (false, '๋„คํŠธ์›Œํฌ ์—๋Ÿฌ: $e'); } } }