295 lines
9.8 KiB
Dart

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<String, dynamic> 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<String, dynamic> 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<String, dynamic> 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<String, dynamic> 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<String> editableFields;
final List<String> 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<String, dynamic> json) {
// If the data is nested under 'profile', unpack it
final data = json.containsKey('profile') && json['profile'] is Map<String, dynamic>
? json['profile'] as Map<String, dynamic>
: json;
final guardianMap = SafeConvert.toNullableMap(data['guardian']);
final editable = (data['editable_fields'] as List<dynamic>?)
?.map((e) => e.toString())
.toList() ??
const [];
final protected = (data['protected_fields'] as List<dynamic>?)
?.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<String, dynamic> 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<String, dynamic> 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']),
);
}
}