add
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
/// Represents a request for design consultation service.
|
||||
library;
|
||||
|
||||
import 'project_submission.dart';
|
||||
import 'package:worker/features/projects/domain/entities/project_type.dart';
|
||||
|
||||
/// Design status enum
|
||||
enum DesignStatus {
|
||||
|
||||
33
lib/features/projects/domain/entities/project_status.dart
Normal file
33
lib/features/projects/domain/entities/project_status.dart
Normal file
@@ -0,0 +1,33 @@
|
||||
/// Project Status Entity
|
||||
///
|
||||
/// Represents a project status option from the API.
|
||||
library;
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
/// Project Status Entity
|
||||
///
|
||||
/// Similar to OrderStatus - represents status options for project submissions.
|
||||
class ProjectStatus extends Equatable {
|
||||
/// Status value (e.g., "Pending approval", "Approved", "Rejected", "Cancelled")
|
||||
final String status;
|
||||
|
||||
/// Vietnamese label (e.g., "Chờ phê duyệt", "Đã được phê duyệt", "Từ chối", "HỦY BỎ")
|
||||
final String label;
|
||||
|
||||
/// Color indicator (e.g., "Warning", "Success", "Danger")
|
||||
final String color;
|
||||
|
||||
/// Display order index
|
||||
final int index;
|
||||
|
||||
const ProjectStatus({
|
||||
required this.status,
|
||||
required this.label,
|
||||
required this.color,
|
||||
required this.index,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [status, label, color, index];
|
||||
}
|
||||
@@ -1,242 +1,100 @@
|
||||
/// Domain Entity: Project Submission
|
||||
///
|
||||
/// Represents a completed project submitted for loyalty points.
|
||||
/// Based on API response from building_material.building_material.api.project.get_list
|
||||
library;
|
||||
|
||||
/// Project type enum
|
||||
enum ProjectType {
|
||||
/// Residential project
|
||||
residential,
|
||||
|
||||
/// Commercial project
|
||||
commercial,
|
||||
|
||||
/// Industrial project
|
||||
industrial,
|
||||
|
||||
/// Public infrastructure
|
||||
infrastructure,
|
||||
|
||||
/// Other type
|
||||
other;
|
||||
|
||||
/// Get display name for project type
|
||||
String get displayName {
|
||||
switch (this) {
|
||||
case ProjectType.residential:
|
||||
return 'Residential';
|
||||
case ProjectType.commercial:
|
||||
return 'Commercial';
|
||||
case ProjectType.industrial:
|
||||
return 'Industrial';
|
||||
case ProjectType.infrastructure:
|
||||
return 'Infrastructure';
|
||||
case ProjectType.other:
|
||||
return 'Other';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Submission status enum
|
||||
enum SubmissionStatus {
|
||||
/// Submitted, pending review
|
||||
pending,
|
||||
|
||||
/// Under review
|
||||
reviewing,
|
||||
|
||||
/// Approved, points awarded
|
||||
approved,
|
||||
|
||||
/// Rejected
|
||||
rejected;
|
||||
|
||||
/// Get display name for status
|
||||
String get displayName {
|
||||
switch (this) {
|
||||
case SubmissionStatus.pending:
|
||||
return 'Pending';
|
||||
case SubmissionStatus.reviewing:
|
||||
return 'Reviewing';
|
||||
case SubmissionStatus.approved:
|
||||
return 'Approved';
|
||||
case SubmissionStatus.rejected:
|
||||
return 'Rejected';
|
||||
}
|
||||
}
|
||||
}
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
/// Project Submission Entity
|
||||
///
|
||||
/// Contains information about a completed project:
|
||||
/// - Project details
|
||||
/// - Before/after photos
|
||||
/// - Invoice documentation
|
||||
/// - Review status
|
||||
/// - Points earned
|
||||
class ProjectSubmission {
|
||||
/// Unique submission identifier
|
||||
/// Contains information about a completed project submission.
|
||||
/// Mapped from API response:
|
||||
/// - name -> submissionId
|
||||
/// - designed_area -> designedArea (project name/title)
|
||||
/// - design_area -> designArea (area value in m²)
|
||||
/// - request_date -> requestDate
|
||||
/// - status -> status (Vietnamese label)
|
||||
/// - reason_for_rejection -> reasonForRejection
|
||||
/// - status_color -> statusColor
|
||||
class ProjectSubmission extends Equatable {
|
||||
/// Unique submission identifier (API: name)
|
||||
final String submissionId;
|
||||
|
||||
/// User ID who submitted
|
||||
final String userId;
|
||||
/// Project name/title (API: designed_area)
|
||||
final String designedArea;
|
||||
|
||||
/// Project name
|
||||
final String projectName;
|
||||
/// Design area value in square meters (API: design_area)
|
||||
final double designArea;
|
||||
|
||||
/// Project address/location
|
||||
final String? projectAddress;
|
||||
/// Submission/request date (API: request_date)
|
||||
final DateTime requestDate;
|
||||
|
||||
/// Project value/cost
|
||||
final double projectValue;
|
||||
/// Status label - Vietnamese (API: status)
|
||||
/// e.g., "Chờ phê duyệt", "Đã được phê duyệt", "Từ chối", "HỦY BỎ"
|
||||
final String status;
|
||||
|
||||
/// Project type
|
||||
final ProjectType projectType;
|
||||
/// Rejection reason if rejected (API: reason_for_rejection)
|
||||
final String? reasonForRejection;
|
||||
|
||||
/// Before photos URLs
|
||||
final List<String> beforePhotos;
|
||||
|
||||
/// After photos URLs
|
||||
final List<String> afterPhotos;
|
||||
|
||||
/// Invoice/receipt URLs
|
||||
final List<String> invoices;
|
||||
|
||||
/// Submission status
|
||||
final SubmissionStatus status;
|
||||
|
||||
/// Review notes from admin
|
||||
final String? reviewNotes;
|
||||
|
||||
/// Rejection reason (if rejected)
|
||||
final String? rejectionReason;
|
||||
|
||||
/// Points earned (if approved)
|
||||
final int? pointsEarned;
|
||||
|
||||
/// Submission timestamp
|
||||
final DateTime submittedAt;
|
||||
|
||||
/// Review timestamp
|
||||
final DateTime? reviewedAt;
|
||||
|
||||
/// ID of admin who reviewed
|
||||
final String? reviewedBy;
|
||||
/// Status color indicator (API: status_color)
|
||||
/// Values: "Warning", "Success", "Danger"
|
||||
final String statusColor;
|
||||
|
||||
const ProjectSubmission({
|
||||
required this.submissionId,
|
||||
required this.userId,
|
||||
required this.projectName,
|
||||
this.projectAddress,
|
||||
required this.projectValue,
|
||||
required this.projectType,
|
||||
required this.beforePhotos,
|
||||
required this.afterPhotos,
|
||||
required this.invoices,
|
||||
required this.designedArea,
|
||||
required this.designArea,
|
||||
required this.requestDate,
|
||||
required this.status,
|
||||
this.reviewNotes,
|
||||
this.rejectionReason,
|
||||
this.pointsEarned,
|
||||
required this.submittedAt,
|
||||
this.reviewedAt,
|
||||
this.reviewedBy,
|
||||
this.reasonForRejection,
|
||||
required this.statusColor,
|
||||
});
|
||||
|
||||
/// Check if submission is pending
|
||||
bool get isPending => status == SubmissionStatus.pending;
|
||||
|
||||
/// Check if submission is under review
|
||||
bool get isReviewing => status == SubmissionStatus.reviewing;
|
||||
/// Check if submission is pending approval
|
||||
bool get isPending => statusColor == 'Warning';
|
||||
|
||||
/// Check if submission is approved
|
||||
bool get isApproved => status == SubmissionStatus.approved;
|
||||
bool get isApproved => statusColor == 'Success';
|
||||
|
||||
/// Check if submission is rejected
|
||||
bool get isRejected => status == SubmissionStatus.rejected;
|
||||
|
||||
/// Check if submission has been reviewed
|
||||
bool get isReviewed =>
|
||||
status == SubmissionStatus.approved ||
|
||||
status == SubmissionStatus.rejected;
|
||||
|
||||
/// Check if submission has before photos
|
||||
bool get hasBeforePhotos => beforePhotos.isNotEmpty;
|
||||
|
||||
/// Check if submission has after photos
|
||||
bool get hasAfterPhotos => afterPhotos.isNotEmpty;
|
||||
|
||||
/// Check if submission has invoices
|
||||
bool get hasInvoices => invoices.isNotEmpty;
|
||||
|
||||
/// Get total number of photos
|
||||
int get totalPhotos => beforePhotos.length + afterPhotos.length;
|
||||
|
||||
/// Get review duration
|
||||
Duration? get reviewDuration {
|
||||
if (reviewedAt == null) return null;
|
||||
return reviewedAt!.difference(submittedAt);
|
||||
}
|
||||
/// Check if submission is rejected or cancelled
|
||||
bool get isRejected => statusColor == 'Danger';
|
||||
|
||||
/// Copy with method for immutability
|
||||
ProjectSubmission copyWith({
|
||||
String? submissionId,
|
||||
String? userId,
|
||||
String? projectName,
|
||||
String? projectAddress,
|
||||
double? projectValue,
|
||||
ProjectType? projectType,
|
||||
List<String>? beforePhotos,
|
||||
List<String>? afterPhotos,
|
||||
List<String>? invoices,
|
||||
SubmissionStatus? status,
|
||||
String? reviewNotes,
|
||||
String? rejectionReason,
|
||||
int? pointsEarned,
|
||||
DateTime? submittedAt,
|
||||
DateTime? reviewedAt,
|
||||
String? reviewedBy,
|
||||
String? designedArea,
|
||||
double? designArea,
|
||||
DateTime? requestDate,
|
||||
String? status,
|
||||
String? reasonForRejection,
|
||||
String? statusColor,
|
||||
}) {
|
||||
return ProjectSubmission(
|
||||
submissionId: submissionId ?? this.submissionId,
|
||||
userId: userId ?? this.userId,
|
||||
projectName: projectName ?? this.projectName,
|
||||
projectAddress: projectAddress ?? this.projectAddress,
|
||||
projectValue: projectValue ?? this.projectValue,
|
||||
projectType: projectType ?? this.projectType,
|
||||
beforePhotos: beforePhotos ?? this.beforePhotos,
|
||||
afterPhotos: afterPhotos ?? this.afterPhotos,
|
||||
invoices: invoices ?? this.invoices,
|
||||
designedArea: designedArea ?? this.designedArea,
|
||||
designArea: designArea ?? this.designArea,
|
||||
requestDate: requestDate ?? this.requestDate,
|
||||
status: status ?? this.status,
|
||||
reviewNotes: reviewNotes ?? this.reviewNotes,
|
||||
rejectionReason: rejectionReason ?? this.rejectionReason,
|
||||
pointsEarned: pointsEarned ?? this.pointsEarned,
|
||||
submittedAt: submittedAt ?? this.submittedAt,
|
||||
reviewedAt: reviewedAt ?? this.reviewedAt,
|
||||
reviewedBy: reviewedBy ?? this.reviewedBy,
|
||||
reasonForRejection: reasonForRejection ?? this.reasonForRejection,
|
||||
statusColor: statusColor ?? this.statusColor,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other is ProjectSubmission &&
|
||||
other.submissionId == submissionId &&
|
||||
other.userId == userId &&
|
||||
other.projectName == projectName &&
|
||||
other.projectValue == projectValue &&
|
||||
other.status == status;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return Object.hash(submissionId, userId, projectName, projectValue, status);
|
||||
}
|
||||
List<Object?> get props => [
|
||||
submissionId,
|
||||
designedArea,
|
||||
designArea,
|
||||
requestDate,
|
||||
status,
|
||||
reasonForRejection,
|
||||
statusColor,
|
||||
];
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ProjectSubmission(submissionId: $submissionId, projectName: $projectName, '
|
||||
'projectValue: $projectValue, projectType: $projectType, status: $status, '
|
||||
'pointsEarned: $pointsEarned)';
|
||||
return 'ProjectSubmission(submissionId: $submissionId, designedArea: $designedArea, '
|
||||
'designArea: $designArea, status: $status, statusColor: $statusColor)';
|
||||
}
|
||||
}
|
||||
|
||||
38
lib/features/projects/domain/entities/project_type.dart
Normal file
38
lib/features/projects/domain/entities/project_type.dart
Normal file
@@ -0,0 +1,38 @@
|
||||
/// Project Type Enum
|
||||
///
|
||||
/// Represents the type of construction project.
|
||||
library;
|
||||
|
||||
/// Project type enum
|
||||
enum ProjectType {
|
||||
/// Residential project
|
||||
residential,
|
||||
|
||||
/// Commercial project
|
||||
commercial,
|
||||
|
||||
/// Industrial project
|
||||
industrial,
|
||||
|
||||
/// Public infrastructure
|
||||
infrastructure,
|
||||
|
||||
/// Other type
|
||||
other;
|
||||
|
||||
/// Get display name for project type
|
||||
String get displayName {
|
||||
switch (this) {
|
||||
case ProjectType.residential:
|
||||
return 'Residential';
|
||||
case ProjectType.commercial:
|
||||
return 'Commercial';
|
||||
case ProjectType.industrial:
|
||||
return 'Industrial';
|
||||
case ProjectType.infrastructure:
|
||||
return 'Infrastructure';
|
||||
case ProjectType.other:
|
||||
return 'Other';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,24 +3,26 @@
|
||||
/// Repository interface for project submissions operations.
|
||||
library;
|
||||
|
||||
import 'package:worker/features/projects/domain/entities/project_status.dart';
|
||||
import 'package:worker/features/projects/domain/entities/project_submission.dart';
|
||||
|
||||
/// Submissions Repository
|
||||
///
|
||||
/// Defines contract for project submissions data operations.
|
||||
abstract class SubmissionsRepository {
|
||||
/// Get list of available project statuses
|
||||
///
|
||||
/// Uses cache-first pattern:
|
||||
/// - Returns cached data if available
|
||||
/// - Fetches from API and updates cache
|
||||
/// - [forceRefresh] bypasses cache and fetches fresh data
|
||||
Future<List<ProjectStatus>> getProjectStatusList({
|
||||
bool forceRefresh = false,
|
||||
});
|
||||
|
||||
/// Get all project submissions for the current user
|
||||
Future<List<ProjectSubmission>> getSubmissions();
|
||||
|
||||
/// Get a single submission by ID
|
||||
Future<ProjectSubmission> getSubmissionById(String submissionId);
|
||||
|
||||
/// Create a new project submission
|
||||
Future<ProjectSubmission> createSubmission(ProjectSubmission submission);
|
||||
|
||||
/// Update an existing submission
|
||||
Future<ProjectSubmission> updateSubmission(ProjectSubmission submission);
|
||||
|
||||
/// Delete a submission
|
||||
Future<void> deleteSubmission(String submissionId);
|
||||
Future<List<ProjectSubmission>> getSubmissions({
|
||||
int limitStart = 0,
|
||||
int limitPageLength = 0,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
/// Get Submissions Use Case
|
||||
///
|
||||
/// Retrieves all project submissions for the current user.
|
||||
library;
|
||||
|
||||
import 'package:worker/features/projects/domain/entities/project_submission.dart';
|
||||
import 'package:worker/features/projects/domain/repositories/submissions_repository.dart';
|
||||
|
||||
/// Get Submissions Use Case
|
||||
///
|
||||
/// Business logic for retrieving project submissions.
|
||||
class GetSubmissions {
|
||||
|
||||
const GetSubmissions(this._repository);
|
||||
final SubmissionsRepository _repository;
|
||||
|
||||
/// Execute the use case
|
||||
///
|
||||
/// Returns list of all project submissions for the current user.
|
||||
Future<List<ProjectSubmission>> call() async {
|
||||
return await _repository.getSubmissions();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user