import '../core/utils/safe_convert.dart'; class NamedRecord { final int id; final String name; const NamedRecord({required this.id, required this.name}); factory NamedRecord.fromJson(Map json) { return NamedRecord( id: SafeConvert.toSafeInt(json['id']), name: SafeConvert.toSafeString(json['name']), ); } static NamedRecord? fromNullableJson(dynamic json) { final map = SafeConvert.toNullableMap(json); if (map == null) return null; return NamedRecord.fromJson(map); } Map toJson() => {'id': id, 'name': name}; @override String toString() => name; } class StudentBasic { final int id; final String name; const StudentBasic({required this.id, required this.name}); factory StudentBasic.fromJson(Map json) { return StudentBasic( id: SafeConvert.toSafeInt(json['id']), name: SafeConvert.toSafeString(json['name']), ); } static StudentBasic? fromNullableJson(dynamic json) { final map = SafeConvert.toNullableMap(json); if (map == null) return null; return StudentBasic.fromJson(map); } Map toJson() => {'id': id, 'name': name}; } class StudentProfile { final int id; final String studentId; final String admissionNumber; final String? registrationNumber; final String? rollNumber; final String fullName; final String? email; final String? mobile; final String? phone; final String? gender; final String? dateOfBirth; final String? bloodGroup; final String? emergencyContact; final String? emergencyPhone; final String? street; final String? street2; final String? city; final String? zip; final NamedRecord? state; final NamedRecord? country; final String? guardianName; final String? guardianRelation; final String? guardianPhone; final String? guardianEmail; final String status; final int profileCompletion; final bool hasPhoto; final NamedRecord? campus; final NamedRecord? department; final NamedRecord? program; final NamedRecord? level; final NamedRecord? academicYear; final NamedRecord? academicTerm; final NamedRecord? batch; final NamedRecord? semester; final NamedRecord? section; final List editableFields; final List protectedFields; const StudentProfile({ required this.id, required this.studentId, required this.admissionNumber, this.registrationNumber, this.rollNumber, required this.fullName, this.email, this.mobile, this.phone, this.gender, this.dateOfBirth, this.bloodGroup, this.emergencyContact, this.emergencyPhone, this.street, this.street2, this.city, this.zip, this.state, this.country, this.guardianName, this.guardianRelation, this.guardianPhone, this.guardianEmail, required this.status, this.profileCompletion = 0, this.hasPhoto = false, this.campus, this.department, this.program, this.level, this.academicYear, this.academicTerm, this.batch, this.semester, this.section, this.editableFields = const [], this.protectedFields = const [], }); factory StudentProfile.fromJson(Map json) { // If the data is nested under 'profile', unpack it final data = json.containsKey('profile') && json['profile'] is Map ? json['profile'] as Map : json; final guardianMap = SafeConvert.toNullableMap(data['guardian']); final editable = (data['editable_fields'] as List?) ?.map((e) => e.toString()) .toList() ?? const []; final protected = (data['protected_fields'] as List?) ?.map((e) => e.toString()) .toList() ?? const []; return StudentProfile( id: SafeConvert.toSafeInt(data['id']), studentId: SafeConvert.toSafeString(data['student_id']), admissionNumber: SafeConvert.toSafeString(data['admission_number']), registrationNumber: SafeConvert.toNullableString(data['registration_number']), rollNumber: SafeConvert.toNullableString(data['roll_number']), fullName: SafeConvert.toSafeString(data['full_name']), email: SafeConvert.toNullableString(data['email']), mobile: SafeConvert.toNullableString(data['mobile']), phone: SafeConvert.toNullableString(data['phone']), gender: SafeConvert.toNullableString(data['gender']), dateOfBirth: SafeConvert.toNullableString(data['date_of_birth']), bloodGroup: SafeConvert.toNullableString(data['blood_group']), emergencyContact: SafeConvert.toNullableString(data['emergency_contact']), emergencyPhone: SafeConvert.toNullableString(data['emergency_phone']), street: SafeConvert.toNullableString(data['street']), street2: SafeConvert.toNullableString(data['street2']), city: SafeConvert.toNullableString(data['city']), zip: SafeConvert.toNullableString(data['zip']), state: NamedRecord.fromNullableJson(data['state']), country: NamedRecord.fromNullableJson(data['country']), guardianName: guardianMap != null ? SafeConvert.toNullableString(guardianMap['name']) : null, guardianRelation: guardianMap != null ? SafeConvert.toNullableString(guardianMap['relation']) : null, guardianPhone: guardianMap != null ? SafeConvert.toNullableString(guardianMap['phone']) : null, guardianEmail: guardianMap != null ? SafeConvert.toNullableString(guardianMap['email']) : null, status: SafeConvert.toSafeString(data['status'], 'draft'), profileCompletion: SafeConvert.toSafeInt(data['profile_completion']), hasPhoto: SafeConvert.toSafeBool(data['has_photo']), campus: NamedRecord.fromNullableJson(data['campus']), department: NamedRecord.fromNullableJson(data['department']), program: NamedRecord.fromNullableJson(data['program']), level: NamedRecord.fromNullableJson(data['level']), academicYear: NamedRecord.fromNullableJson(data['academic_year']), academicTerm: NamedRecord.fromNullableJson(data['academic_term']), batch: NamedRecord.fromNullableJson(data['batch']), semester: NamedRecord.fromNullableJson(data['semester']), section: NamedRecord.fromNullableJson(data['section']), editableFields: editable, protectedFields: protected, ); } } class StudentDocument { final int id; final String name; final String category; final String categoryLabel; final String? fileName; final int fileSize; final String? mimeType; final String verificationStatus; // 'submitted', 'verified', 'rejected' final String uploadDate; final String? verificationDate; final String? rejectionReason; const StudentDocument({ required this.id, required this.name, required this.category, required this.categoryLabel, this.fileName, this.fileSize = 0, this.mimeType, required this.verificationStatus, required this.uploadDate, this.verificationDate, this.rejectionReason, }); bool get isVerified => verificationStatus == 'verified'; bool get isRejected => verificationStatus == 'rejected'; bool get isSubmitted => verificationStatus == 'submitted'; factory StudentDocument.fromJson(Map json) { return StudentDocument( id: SafeConvert.toSafeInt(json['id']), name: SafeConvert.toSafeString(json['name']), category: SafeConvert.toSafeString(json['category'], 'academic'), categoryLabel: SafeConvert.toSafeString(json['category_label'], json['category'] ?? 'Academic'), fileName: SafeConvert.toNullableString(json['file_name']), fileSize: SafeConvert.toSafeInt(json['file_size']), mimeType: SafeConvert.toNullableString(json['mime_type']), verificationStatus: SafeConvert.toSafeString(json['verification_status'], 'submitted'), uploadDate: SafeConvert.toSafeString(json['upload_date']), verificationDate: SafeConvert.toNullableString(json['verification_date']), rejectionReason: SafeConvert.toNullableString(json['rejection_reason']), ); } } class StudentCertificate { final int id; final String name; final String certificateType; final String certificateTypeLabel; final String state; // 'draft', 'requested', 'approved', 'issued', 'rejected' final String requestDate; final String? issueDate; final String? expiryDate; final String? fileName; final String? remarks; final String? rejectionReason; final bool hasFile; const StudentCertificate({ required this.id, required this.name, required this.certificateType, required this.certificateTypeLabel, required this.state, required this.requestDate, this.issueDate, this.expiryDate, this.fileName, this.remarks, this.rejectionReason, this.hasFile = false, }); bool get isIssued => state == 'issued'; bool get isApproved => state == 'approved'; bool get isRequested => state == 'requested'; bool get isRejected => state == 'rejected'; factory StudentCertificate.fromJson(Map json) { return StudentCertificate( id: SafeConvert.toSafeInt(json['id']), name: SafeConvert.toSafeString(json['name']), certificateType: SafeConvert.toSafeString(json['certificate_type']), certificateTypeLabel: SafeConvert.toSafeString( json['certificate_type_label'], json['certificate_type'] ?? 'Certificate', ), state: SafeConvert.toSafeString(json['state'], 'draft'), requestDate: SafeConvert.toSafeString(json['request_date']), issueDate: SafeConvert.toNullableString(json['issue_date']), expiryDate: SafeConvert.toNullableString(json['expiry_date']), fileName: SafeConvert.toNullableString(json['file_name']), remarks: SafeConvert.toNullableString(json['remarks']), rejectionReason: SafeConvert.toNullableString(json['rejection_reason']), hasFile: SafeConvert.toSafeBool(json['has_file']), ); } }