Files
house_hunter/lib/house/house_note_model.dart
2026-04-17 00:37:21 +08:00

191 lines
5.6 KiB
Dart

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,
);
}
}