This commit is contained in:
Phuoc Nguyen
2025-11-27 14:59:48 +07:00
parent dc8e60f589
commit ba04576750
25 changed files with 931 additions and 721 deletions

View File

@@ -0,0 +1,73 @@
/// Project Status Model
///
/// Data model for project status from API responses with Hive caching.
library;
import 'package:hive_ce/hive.dart';
import 'package:worker/core/constants/storage_constants.dart';
import 'package:worker/features/projects/domain/entities/project_status.dart';
part 'project_status_model.g.dart';
/// Project Status Model - Type ID: 63
@HiveType(typeId: HiveTypeIds.projectStatusModel)
class ProjectStatusModel extends HiveObject {
@HiveField(0)
final String status;
@HiveField(1)
final String label;
@HiveField(2)
final String color;
@HiveField(3)
final int index;
ProjectStatusModel({
required this.status,
required this.label,
required this.color,
required this.index,
});
/// Create from JSON
factory ProjectStatusModel.fromJson(Map<String, dynamic> json) {
return ProjectStatusModel(
status: json['status'] as String,
label: json['label'] as String,
color: json['color'] as String,
index: json['index'] as int,
);
}
/// Convert to JSON
Map<String, dynamic> toJson() {
return {
'status': status,
'label': label,
'color': color,
'index': index,
};
}
/// Convert to entity
ProjectStatus toEntity() {
return ProjectStatus(
status: status,
label: label,
color: color,
index: index,
);
}
/// Create from entity
factory ProjectStatusModel.fromEntity(ProjectStatus entity) {
return ProjectStatusModel(
status: entity.status,
label: entity.label,
color: entity.color,
index: entity.index,
);
}
}

View File

@@ -0,0 +1,50 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'project_status_model.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class ProjectStatusModelAdapter extends TypeAdapter<ProjectStatusModel> {
@override
final typeId = 63;
@override
ProjectStatusModel read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return ProjectStatusModel(
status: fields[0] as String,
label: fields[1] as String,
color: fields[2] as String,
index: (fields[3] as num).toInt(),
);
}
@override
void write(BinaryWriter writer, ProjectStatusModel obj) {
writer
..writeByte(4)
..writeByte(0)
..write(obj.status)
..writeByte(1)
..write(obj.label)
..writeByte(2)
..write(obj.color)
..writeByte(3)
..write(obj.index);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is ProjectStatusModelAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

View File

@@ -1,129 +1,105 @@
import 'dart:convert';
/// Project Submission Model
///
/// Data model for project submission from API responses with Hive caching.
/// Based on API response from building_material.building_material.api.project.get_list
library;
import 'package:hive_ce/hive.dart';
import 'package:worker/core/constants/storage_constants.dart';
import 'package:worker/core/database/models/enums.dart';
import 'package:worker/features/projects/domain/entities/project_submission.dart';
part 'project_submission_model.g.dart';
/// Project Submission Model - Type ID: 14
@HiveType(typeId: HiveTypeIds.projectSubmissionModel)
class ProjectSubmissionModel extends HiveObject {
ProjectSubmissionModel({
required this.submissionId,
required this.userId,
required this.projectName,
required this.projectAddress,
required this.projectValue,
required this.projectType,
this.beforePhotos,
this.afterPhotos,
this.invoices,
required this.status,
this.reviewNotes,
this.rejectionReason,
this.pointsEarned,
required this.submittedAt,
this.reviewedAt,
this.reviewedBy,
});
/// Unique submission identifier (API: name)
@HiveField(0)
final String submissionId;
/// Project name/title (API: designed_area)
@HiveField(1)
final String userId;
final String designedArea;
/// Design area value in square meters (API: design_area)
@HiveField(2)
final String projectName;
final double designArea;
/// Submission/request date (API: request_date)
@HiveField(3)
final String projectAddress;
final DateTime requestDate;
/// Status label - Vietnamese (API: status)
@HiveField(4)
final double projectValue;
final String status;
/// Rejection reason if rejected (API: reason_for_rejection)
@HiveField(5)
final ProjectType projectType;
final String? reasonForRejection;
/// Status color indicator (API: status_color)
@HiveField(6)
final String? beforePhotos;
@HiveField(7)
final String? afterPhotos;
@HiveField(8)
final String? invoices;
@HiveField(9)
final SubmissionStatus status;
@HiveField(10)
final String? reviewNotes;
@HiveField(11)
final String? rejectionReason;
@HiveField(12)
final int? pointsEarned;
@HiveField(13)
final DateTime submittedAt;
@HiveField(14)
final DateTime? reviewedAt;
@HiveField(15)
final String? reviewedBy;
final String statusColor;
factory ProjectSubmissionModel.fromJson(
Map<String, dynamic> json,
) => ProjectSubmissionModel(
submissionId: json['submission_id'] as String,
userId: json['user_id'] as String,
projectName: json['project_name'] as String,
projectAddress: json['project_address'] as String,
projectValue: (json['project_value'] as num).toDouble(),
projectType: ProjectType.values.firstWhere(
(e) => e.name == json['project_type'],
),
beforePhotos: json['before_photos'] != null
? jsonEncode(json['before_photos'])
: null,
afterPhotos: json['after_photos'] != null
? jsonEncode(json['after_photos'])
: null,
invoices: json['invoices'] != null ? jsonEncode(json['invoices']) : null,
status: SubmissionStatus.values.firstWhere((e) => e.name == json['status']),
reviewNotes: json['review_notes'] as String?,
rejectionReason: json['rejection_reason'] as String?,
pointsEarned: json['points_earned'] as int?,
submittedAt: DateTime.parse(json['submitted_at']?.toString() ?? ''),
reviewedAt: json['reviewed_at'] != null
? DateTime.parse(json['reviewed_at']?.toString() ?? '')
: null,
reviewedBy: json['reviewed_by'] as String?,
);
ProjectSubmissionModel({
required this.submissionId,
required this.designedArea,
required this.designArea,
required this.requestDate,
required this.status,
this.reasonForRejection,
required this.statusColor,
});
Map<String, dynamic> toJson() => {
'submission_id': submissionId,
'user_id': userId,
'project_name': projectName,
'project_address': projectAddress,
'project_value': projectValue,
'project_type': projectType.name,
'before_photos': beforePhotos != null ? jsonDecode(beforePhotos!) : null,
'after_photos': afterPhotos != null ? jsonDecode(afterPhotos!) : null,
'invoices': invoices != null ? jsonDecode(invoices!) : null,
'status': status.name,
'review_notes': reviewNotes,
'rejection_reason': rejectionReason,
'points_earned': pointsEarned,
'submitted_at': submittedAt.toIso8601String(),
'reviewed_at': reviewedAt?.toIso8601String(),
'reviewed_by': reviewedBy,
};
List<String>? get beforePhotosList {
if (beforePhotos == null) return null;
try {
final decoded = jsonDecode(beforePhotos!) as List;
return decoded.map((e) => e.toString()).toList();
} catch (e) {
return null;
}
/// Create from JSON (API response)
factory ProjectSubmissionModel.fromJson(Map<String, dynamic> json) {
return ProjectSubmissionModel(
submissionId: json['name'] as String,
designedArea: json['designed_area'] as String,
designArea: (json['design_area'] as num).toDouble(),
requestDate: DateTime.parse(json['request_date'] as String),
status: json['status'] as String,
reasonForRejection: json['reason_for_rejection'] as String?,
statusColor: json['status_color'] as String,
);
}
List<String>? get afterPhotosList {
if (afterPhotos == null) return null;
try {
final decoded = jsonDecode(afterPhotos!) as List;
return decoded.map((e) => e.toString()).toList();
} catch (e) {
return null;
}
/// Convert to JSON
Map<String, dynamic> toJson() {
return {
'name': submissionId,
'designed_area': designedArea,
'design_area': designArea,
'request_date': requestDate.toIso8601String(),
'status': status,
'reason_for_rejection': reasonForRejection,
'status_color': statusColor,
};
}
/// Convert to entity
ProjectSubmission toEntity() {
return ProjectSubmission(
submissionId: submissionId,
designedArea: designedArea,
designArea: designArea,
requestDate: requestDate,
status: status,
reasonForRejection: reasonForRejection,
statusColor: statusColor,
);
}
/// Create from entity
factory ProjectSubmissionModel.fromEntity(ProjectSubmission entity) {
return ProjectSubmissionModel(
submissionId: entity.submissionId,
designedArea: entity.designedArea,
designArea: entity.designArea,
requestDate: entity.requestDate,
status: entity.status,
reasonForRejection: entity.reasonForRejection,
statusColor: entity.statusColor,
);
}
}

View File

@@ -19,60 +19,33 @@ class ProjectSubmissionModelAdapter
};
return ProjectSubmissionModel(
submissionId: fields[0] as String,
userId: fields[1] as String,
projectName: fields[2] as String,
projectAddress: fields[3] as String,
projectValue: (fields[4] as num).toDouble(),
projectType: fields[5] as ProjectType,
beforePhotos: fields[6] as String?,
afterPhotos: fields[7] as String?,
invoices: fields[8] as String?,
status: fields[9] as SubmissionStatus,
reviewNotes: fields[10] as String?,
rejectionReason: fields[11] as String?,
pointsEarned: (fields[12] as num?)?.toInt(),
submittedAt: fields[13] as DateTime,
reviewedAt: fields[14] as DateTime?,
reviewedBy: fields[15] as String?,
designedArea: fields[1] as String,
designArea: (fields[2] as num).toDouble(),
requestDate: fields[3] as DateTime,
status: fields[4] as String,
reasonForRejection: fields[5] as String?,
statusColor: fields[6] as String,
);
}
@override
void write(BinaryWriter writer, ProjectSubmissionModel obj) {
writer
..writeByte(16)
..writeByte(7)
..writeByte(0)
..write(obj.submissionId)
..writeByte(1)
..write(obj.userId)
..write(obj.designedArea)
..writeByte(2)
..write(obj.projectName)
..write(obj.designArea)
..writeByte(3)
..write(obj.projectAddress)
..write(obj.requestDate)
..writeByte(4)
..write(obj.projectValue)
..writeByte(5)
..write(obj.projectType)
..writeByte(6)
..write(obj.beforePhotos)
..writeByte(7)
..write(obj.afterPhotos)
..writeByte(8)
..write(obj.invoices)
..writeByte(9)
..write(obj.status)
..writeByte(10)
..write(obj.reviewNotes)
..writeByte(11)
..write(obj.rejectionReason)
..writeByte(12)
..write(obj.pointsEarned)
..writeByte(13)
..write(obj.submittedAt)
..writeByte(14)
..write(obj.reviewedAt)
..writeByte(15)
..write(obj.reviewedBy);
..writeByte(5)
..write(obj.reasonForRejection)
..writeByte(6)
..write(obj.statusColor);
}
@override