- 화면마다 위젯/스타일만 담당하는 UI 파일과, 서버통신/상태/파생로직만 담당하는 ChangeNotifier 컨트롤러 파일로 1:1 분리 (lib/screens/ -> lib/ui/ + lib/function/) - UI는 ListenableBuilder로 컨트롤러를 구독해서 재렌더링, 버튼은 컨트롤러 메서드만 호출 - 다이얼로그/스낵바 등 위젯 코드는 전부 UI 파일에 남기고, 컨트롤러는 결과값(성공여부+메시지) 또는 콜백으로만 UI와 통신 (BuildContext/Widget 의존성 없음) - 디자인/레이아웃은 기존과 완전히 동일하게 유지 (순수 코드 재배치) - change_password_screen.dart, debug_pocket_main.dart(미사용 파일)는 깨지지 않게 import 경로만 갱신하고 리팩터링은 보류
103 lines
3.3 KiB
Dart
103 lines
3.3 KiB
Dart
// 🔐 (마스터 계정용) 학생 계정 및 기기 관리 화면의 기능(서버 통신/상태) 담당 컨트롤러.
|
|
import 'dart:convert';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:http/http.dart' as http;
|
|
import '../config.dart';
|
|
|
|
class StudentManagementController extends ChangeNotifier {
|
|
List<dynamic> _students = [];
|
|
bool _isLoading = true;
|
|
|
|
List<dynamic> get students => _students;
|
|
bool get isLoading => _isLoading;
|
|
|
|
Future<void> init() => fetchStudents();
|
|
|
|
/// 🌐 서버에서 전체 학생 목록 불러오기. 실패 시 에러 메시지를 반환한다(성공 시 null).
|
|
Future<String?> fetchStudents() async {
|
|
_isLoading = true;
|
|
notifyListeners();
|
|
try {
|
|
final response = await http.get(Uri.parse('$baseUrl/api/users'));
|
|
if (response.statusCode == 200) {
|
|
final data = jsonDecode(utf8.decode(response.bodyBytes));
|
|
_students = data['users'] ?? [];
|
|
_isLoading = false;
|
|
notifyListeners();
|
|
return null;
|
|
}
|
|
_isLoading = false;
|
|
notifyListeners();
|
|
return '데이터 불러오기 실패 (${response.statusCode})';
|
|
} catch (e) {
|
|
_isLoading = false;
|
|
notifyListeners();
|
|
return '데이터 불러오기 실패: $e';
|
|
}
|
|
}
|
|
|
|
/// 🌐 서버로 기기 초기화(리셋) 명령 보내기
|
|
Future<(bool success, String message)> resetDevice(
|
|
String studentId,
|
|
String studentName,
|
|
) async {
|
|
try {
|
|
final response = await http.post(
|
|
Uri.parse('$baseUrl/api/users/reset'),
|
|
headers: {"Content-Type": "application/json"},
|
|
body: jsonEncode({"studentId": studentId}),
|
|
);
|
|
if (response.statusCode == 200) {
|
|
await fetchStudents();
|
|
return (true, '✅ $studentName 학생 기기 초기화 완료!');
|
|
}
|
|
return (false, '❌ 초기화 통신 실패');
|
|
} catch (e) {
|
|
return (false, '❌ 초기화 통신 실패');
|
|
}
|
|
}
|
|
|
|
/// 🌐 서버로 계정 완전 삭제 명령 보내기
|
|
Future<(bool success, String message)> deleteUser(
|
|
String studentId,
|
|
String studentName,
|
|
) async {
|
|
try {
|
|
final response = await http.delete(
|
|
Uri.parse('$baseUrl/api/users/delete'),
|
|
headers: {"Content-Type": "application/json"},
|
|
body: jsonEncode({"studentId": studentId}),
|
|
);
|
|
if (response.statusCode == 200) {
|
|
await fetchStudents();
|
|
return (true, '💥 $studentName 학생의 계정이 영구 삭제되었습니다.');
|
|
}
|
|
return (false, '❌ 계정 삭제 통신 실패');
|
|
} catch (e) {
|
|
return (false, '❌ 계정 삭제 통신 실패');
|
|
}
|
|
}
|
|
|
|
/// 🌐 신규 학생 계정 생성
|
|
Future<(bool success, String message)> createUser(
|
|
String studentId,
|
|
String name,
|
|
) async {
|
|
try {
|
|
final response = await http.post(
|
|
Uri.parse('$baseUrl/api/users/create'),
|
|
headers: {"Content-Type": "application/json"},
|
|
body: jsonEncode({"studentId": studentId, "name": name}),
|
|
);
|
|
final res = jsonDecode(response.body);
|
|
if (res['status'] == 'success') {
|
|
await fetchStudents();
|
|
return (true, '✅ ${res['message']}');
|
|
}
|
|
return (false, '❌ ${res['message']}');
|
|
} catch (e) {
|
|
return (false, '❌ 학생 등록 실패 (통신 에러)');
|
|
}
|
|
}
|
|
}
|