First Commit
This commit is contained in:
@@ -0,0 +1,190 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
class House {
|
||||
final String id;
|
||||
final String title;
|
||||
final String? address;
|
||||
final double? latitude;
|
||||
final double? longitude;
|
||||
final double? totalPrice;
|
||||
final double? totalPing;
|
||||
final double? age;
|
||||
final String? propertyType;
|
||||
final String? summaryNotes;
|
||||
final double? overallRating;
|
||||
final bool isFavorite;
|
||||
final DateTime? createdAt;
|
||||
|
||||
House({
|
||||
required this.id,
|
||||
required this.title,
|
||||
this.address,
|
||||
this.latitude,
|
||||
this.longitude,
|
||||
this.totalPrice,
|
||||
this.totalPing,
|
||||
this.age,
|
||||
this.propertyType,
|
||||
this.summaryNotes,
|
||||
this.overallRating,
|
||||
this.isFavorite = false,
|
||||
this.createdAt,
|
||||
});
|
||||
|
||||
factory House.fromJson(Map<String, dynamic> json) {
|
||||
return House(
|
||||
id: json['id'] as String? ?? const Uuid().v4(),
|
||||
title: json['title'] as String? ?? '未命名物件',
|
||||
address: json['address'] as String?,
|
||||
latitude: double.tryParse(json['latitude']?.toString() ?? ''),
|
||||
longitude: double.tryParse(json['longitude']?.toString() ?? ''),
|
||||
totalPrice: double.tryParse(json['total_price']?.toString() ?? ''),
|
||||
totalPing: double.tryParse(json['total_ping']?.toString() ?? ''),
|
||||
age: double.tryParse(json['age']?.toString() ?? ''),
|
||||
propertyType: json['property_type'] as String?,
|
||||
summaryNotes: json['summary_notes'] as String?,
|
||||
overallRating: double.tryParse(json['overall_rating']?.toString() ?? '0'),
|
||||
isFavorite: json['is_favorite'] == 1 || json['is_favorite'] == true,
|
||||
createdAt: json['created_at'] != null ? DateTime.tryParse(json['created_at']) : null,
|
||||
);
|
||||
}
|
||||
|
||||
// UI Helper: 評分顏色
|
||||
Color get ratingColor {
|
||||
if ((overallRating ?? 0) >= 4) return Colors.green;
|
||||
if ((overallRating ?? 0) >= 3) return Colors.orange;
|
||||
return Colors.red;
|
||||
}
|
||||
|
||||
// 格式化顯示價格與坪數
|
||||
String get priceTag => totalPrice != null ? '${totalPrice} 萬' : '價格未定';
|
||||
String get infoSummary => '${propertyType ?? "未知"} | ${age ?? "?"}年 | ${totalPing ?? "?"}坪';
|
||||
}
|
||||
|
||||
// 檢查項目定義 (Template)
|
||||
class CheckItem {
|
||||
final String id;
|
||||
final String categoryId;
|
||||
final String name;
|
||||
final bool isDefault;
|
||||
|
||||
CheckItem({required this.id, required this.categoryId, required this.name, this.isDefault = true});
|
||||
|
||||
factory CheckItem.fromJson(Map<String, dynamic> json) {
|
||||
return CheckItem(
|
||||
id: json['id'] as String,
|
||||
categoryId: json['category_id'] as String,
|
||||
name: json['name'] as String,
|
||||
isDefault: json['is_default'] == 1,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 新增照片模型
|
||||
class HousePhoto {
|
||||
final String id;
|
||||
final String houseId;
|
||||
final String? evaluationId; // 關聯特定評估項目
|
||||
final String filePath;
|
||||
final String? description;
|
||||
|
||||
HousePhoto({required this.id, required this.houseId, this.evaluationId, required this.filePath, this.description});
|
||||
|
||||
factory HousePhoto.fromJson(Map<String, dynamic> json) {
|
||||
return HousePhoto(
|
||||
id: json['id'] as String,
|
||||
houseId: json['house_id'] as String,
|
||||
evaluationId: json['evaluation_id'] as String?,
|
||||
filePath: json['file_path'] as String,
|
||||
description: json['description'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
// 取得完整圖片網址
|
||||
// String get fullUrl => "https://api.gex.com.tw/uploads/$filePath";
|
||||
String get fullUrl {
|
||||
if (filePath.startsWith('http')) {
|
||||
return filePath;
|
||||
}
|
||||
return "https://api.gex.com.tw/uploads/$filePath";
|
||||
}
|
||||
}
|
||||
|
||||
// 新增評估紀錄模型
|
||||
class HouseEvaluation {
|
||||
String? id; // 【修改】允許為 null (新建立的評估還沒有 ID)
|
||||
String houseId; // 移除 final
|
||||
String checkItemId; // 移除 final
|
||||
String itemName; // 移除 final,讓前端可以賦值
|
||||
int score; // 【修改】移除 final,讓表單可以更新分數
|
||||
String? itemMemo; // 【修改】移除 final,讓表單可以更新備註
|
||||
|
||||
HouseEvaluation({
|
||||
this.id, // 【修改】移除 required
|
||||
required this.houseId,
|
||||
required this.checkItemId,
|
||||
required this.itemName, // 給予預設值,解決報錯
|
||||
this.score = 0,
|
||||
this.itemMemo,
|
||||
});
|
||||
|
||||
factory HouseEvaluation.fromJson(Map<String, dynamic> json) {
|
||||
return HouseEvaluation(
|
||||
id: json['id'] as String?,
|
||||
houseId: json['house_id'] as String? ?? '',
|
||||
checkItemId: json['check_item_id'] as String? ?? '',
|
||||
itemName: json['itemName'] as String? ?? '',
|
||||
score: int.tryParse(json['score']?.toString() ?? '0') ?? 0,
|
||||
itemMemo: json['item_memo'] as String?,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Tag
|
||||
class Tag {
|
||||
final String id;
|
||||
final String name;
|
||||
final String colorHex;
|
||||
bool isSelected; // UI 用:判斷是否被選取
|
||||
|
||||
Tag({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.colorHex,
|
||||
this.isSelected = false,
|
||||
});
|
||||
|
||||
factory Tag.fromJson(Map<String, dynamic> json) {
|
||||
return Tag(
|
||||
id: json['id'] as String,
|
||||
name: json['name'] as String,
|
||||
colorHex: json['color_hex'] as String? ?? '#CCCCCC',
|
||||
);
|
||||
}
|
||||
|
||||
// 輔助:轉換 Hex String 為 Color 物件
|
||||
Color get color {
|
||||
final hexCode = colorHex.replaceAll('#', '');
|
||||
return Color(int.parse('FF$hexCode', radix: 16));
|
||||
}
|
||||
}
|
||||
|
||||
// 檢查項目大類模型
|
||||
class CheckCategory {
|
||||
final String id;
|
||||
final String name;
|
||||
final int sortOrder;
|
||||
|
||||
CheckCategory({required this.id, required this.name, required this.sortOrder});
|
||||
|
||||
factory CheckCategory.fromJson(Map<String, dynamic> json) {
|
||||
return CheckCategory(
|
||||
id: json['id'] as String,
|
||||
name: json['name'] as String,
|
||||
sortOrder: int.tryParse(json['sort_order']?.toString() ?? '0') ?? 0,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user