sample project

This commit is contained in:
Phuoc Nguyen
2025-11-28 15:01:51 +07:00
parent ed6cc4cebc
commit 440b474504
11 changed files with 1071 additions and 343 deletions

View File

@@ -0,0 +1,89 @@
/// Domain Entity: Sample Project
///
/// Represents a sample/model house project with 360° view.
/// Based on API response from building_material.building_material.api.sample_project
library;
import 'package:equatable/equatable.dart';
/// Project File Entity
///
/// Represents an uploaded file attached to a sample project.
class SampleProjectFile extends Equatable {
/// Unique file identifier (API: name)
final String id;
/// Full URL to the file (API: file_url)
final String fileUrl;
const SampleProjectFile({
required this.id,
required this.fileUrl,
});
@override
List<Object?> get props => [id, fileUrl];
}
/// Sample Project Entity
///
/// Contains information about a model house/sample project.
/// API field mapping:
/// - name -> id
/// - project_name -> projectName
/// - notes -> description (HTML content)
/// - link -> viewUrl (360° viewer URL)
/// - thumbnail -> thumbnailUrl
/// - files_list -> filesList (detail only)
class SampleProject extends Equatable {
/// Unique project identifier (API: name)
final String id;
/// Project display name (API: project_name)
final String projectName;
/// Project description/notes - may contain HTML (API: notes)
final String? description;
/// URL to 360° view (API: link)
final String? viewUrl;
/// Thumbnail image URL (API: thumbnail)
final String? thumbnailUrl;
/// List of attached files/images (API: files_list) - available in detail
final List<SampleProjectFile> filesList;
const SampleProject({
required this.id,
required this.projectName,
this.description,
this.viewUrl,
this.thumbnailUrl,
this.filesList = const [],
});
/// Check if project has 360° view available
bool get has360View => viewUrl != null && viewUrl!.isNotEmpty;
/// Get plain text description (strips HTML tags)
String get plainDescription {
if (description == null) return '';
// Simple HTML tag removal
return description!
.replaceAll(RegExp(r'<[^>]*>'), '')
.replaceAll('&nbsp;', ' ')
.trim();
}
/// Get all image URLs for gallery (from filesList)
List<String> get imageUrls => filesList.map((f) => f.fileUrl).toList();
@override
List<Object?> get props => [id, projectName, description, viewUrl, thumbnailUrl, filesList];
@override
String toString() {
return 'SampleProject(id: $id, projectName: $projectName, has360View: $has360View, filesCount: ${filesList.length})';
}
}

View File

@@ -0,0 +1,26 @@
/// Sample Project Repository Interface
///
/// Defines contract for sample project data operations.
library;
import 'package:worker/features/showrooms/domain/entities/sample_project.dart';
/// Sample Project Repository
///
/// Repository interface for sample/model house project operations.
abstract class SampleProjectRepository {
/// Get list of sample/model house projects
///
/// Returns list of sample projects with 360° view links.
/// [limitStart] - Pagination offset
/// [limitPageLength] - Number of items per page (0 = all)
Future<List<SampleProject>> getSampleProjects({
int limitStart = 0,
int limitPageLength = 0,
});
/// Get detail of a sample/model house project by name
///
/// Returns full project detail with files_list for gallery.
Future<SampleProject> getSampleProjectDetail(String name);
}