Files
house_hunter/lib/house/house_note_api.dart
T
2026-04-17 23:34:02 +08:00

227 lines
7.3 KiB
Dart

import '../../services/generic_api_service.dart';
// import '../auth_manager.dart';
import 'house_note_model.dart';
import 'package:intl/intl.dart';
import 'package:uuid/uuid.dart';
import 'dart:io';
import 'package:http/http.dart' as http;
import 'dart:convert'; // 補上這行,json.decode 才能運作
class HouseNoteApiService {
final GenericApiService _apiService = GenericApiService();
// 獲取所有房屋列表
Future<List<House>> fetchHouses() async {
// 依據建立時間降冪排序
String queryFilter = "1^100^created_at^*^^^";
return await _apiService.fetchList<House>(
tableName: "hhp_houses",
pk: "id",
queryFilter: queryFilter,
fromJson: (json) => House.fromJson(json),
);
}
// 創建新物件 (UUID 在前端生成)
Future<List<House>> createHouse(House house) async {
final Map<String, dynamic> data = {
"id": house.id,
"title": house.title,
"address": house.address,
"latitude": house.latitude,
"longitude": house.longitude,
"total_price": house.totalPrice,
"total_ping": house.totalPing,
"property_type": house.propertyType,
"age": house.age,
"summary_notes": house.summaryNotes,
"created_at": DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.now()),
};
return await _apiService.fetchList<House>(
tableName: "hhp_houses",
pk: "id",
queryFilter: "", // 【關鍵修正】補上必填參數,傳入空字串即可
action: "C",
data: data,
fromJson: (json) => House.fromJson(json),
);
}
// 獲取預設檢查清單
Future<List<CheckItem>> fetchDefaultCheckItems() async {
return await _apiService.fetchList<CheckItem>(
tableName: "hhp_check_items",
pk: "id",
queryFilter: "1^200^sort_order^*^^^is_default^1",
fromJson: (json) => CheckItem.fromJson(json),
);
}
// 上傳照片檔案 (參考 expense_api)
Future<String?> uploadImage(File imageFile) async {
try {
final request = http.MultipartRequest(
'POST',
Uri.parse("${GenericApiService.BASE_IP}/upload/house_hunter/images")
);
// 取得本地檔案名稱
String picFileName = "${GenericApiService.BASE_IP}/upload/house_hunter/images/${imageFile.path.split('/').last}";
request.files.add(await http.MultipartFile.fromPath('file', imageFile.path));
final streamedResponse = await request.send();
final response = await http.Response.fromStream(streamedResponse);
if (response.statusCode == 200) {
// final data = json.decode(response.body);
// return data['fileName'];
return picFileName; // 這是回傳後端產生的檔名
}
} catch (e) {
print("圖片上傳異常: $e");
}
return null;
}
// 儲存照片關聯資訊
Future<bool> saveHousePhoto(String houseId, String fileName, String note) async {
final Map<String, dynamic> data = {
"id": const Uuid().v4(),
"house_id": houseId,
"file_path": fileName,
"description": note,
"created_at": DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.now()),
};
final result = await _apiService.fetchList<dynamic>(
tableName: "hhp_house_photos",
pk: "id",
queryFilter: "",
action: "C",
data: data,
fromJson: (json) => json,
);
return result.isNotEmpty;
}
// 獲取特定房屋的所有評估紀錄 (需 Join 項目名稱)
Future<List<HouseEvaluation>> fetchEvaluations(String houseId) async {
// 這裡假設後端會處理 Join hhp_check_items 取得名稱
String queryFilter = "1^100^id^*^^hhpm02^house_id^$houseId";
return await _apiService.fetchList<HouseEvaluation>(
tableName: "hhp_house_evaluations",
pk: "id",
queryFilter: queryFilter,
fromJson: (json) => HouseEvaluation.fromJson(json),
);
}
// 獲取特定房屋的所有照片
Future<List<HousePhoto>> fetchPhotos(String houseId) async {
String queryFilter = "1^100^created_at^*^^^house_id^$houseId";
return await _apiService.fetchList<HousePhoto>(
tableName: "hhp_house_photos",
pk: "id",
queryFilter: queryFilter,
fromJson: (json) => HousePhoto.fromJson(json),
);
}
// house_note_api.dart 新增方法
// 1. 獲取所有可用標籤庫 (hhp_tags)
Future<List<Tag>> fetchAllTags() async {
return await _apiService.fetchList<Tag>(
tableName: "hhp_tags",
pk: "id",
queryFilter: "1^100^id^*^^^",
fromJson: (json) => Tag.fromJson(json),
);
}
// 2. 獲取特定房屋已選取的標籤 ID 清單 (hhp_house_tags)
Future<List<String>> fetchHouseTagIds(String houseId) async {
final List<dynamic> result = await _apiService.fetchList<dynamic>(
tableName: "hhp_house_tags",
pk: "house_id", // 複合主鍵通常用其中一個,視 API 規範而定
queryFilter: "1^100^tag_id^*^^^house_id^$houseId",
fromJson: (json) => json,
);
return result.map((e) => e['tag_id'].toString()).toList();
}
// 3. 儲存/更新房屋標籤 (hhp_house_tags)
// 邏輯:通常是先刪除舊的再寫入新的,這裡簡化為寫入邏輯
Future<void> updateHouseTags(String houseId, List<String> selectedTagIds) async {
// A. 刪除該房屋舊有的所有標籤關聯 (假設 action 'D' 為刪除)
await _apiService.fetchList<dynamic>(
tableName: "hhp_house_tags",
pk: "house_id",
queryFilter: "house_id^$houseId",
action: "D",
fromJson: (json) => json,
);
// B. 逐一寫入新的標籤關聯
for (String tagId in selectedTagIds) {
await _apiService.fetchList<dynamic>(
tableName: "hhp_house_tags",
pk: "house_id",
queryFilter: "",
action: "C",
data: {
"house_id": houseId,
"tag_id": tagId,
},
fromJson: (json) => json,
);
}
}
// 1. 獲取所有檢查大類 (hhp_check_categories)
Future<List<CheckCategory>> fetchCategories() async {
return await _apiService.fetchList<CheckCategory>(
tableName: "hhp_check_categories",
pk: "id",
queryFilter: "1^100^sort_order^*^^^",
fromJson: (json) => CheckCategory.fromJson(json),
);
}
// 2. 儲存/更新評估紀錄
// 由於評估通常是多筆,我們這裡實作單筆提交,呼叫端可用迴圈或 Future.wait
Future<bool> saveSingleEvaluation(HouseEvaluation eval) async {
final Map<String, dynamic> data = {
"id": eval.id ?? const Uuid().v4(),
"house_id": eval.houseId,
"check_item_id": eval.checkItemId,
"score": eval.score,
"item_memo": eval.itemMemo ?? "",
"updated_at": DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.now()),
};
final result = await _apiService.fetchList<dynamic>(
tableName: "hhp_house_evaluations",
pk: "id",
queryFilter: "",
action: "C", // 使用 Create/Update
data: data,
fromJson: (json) => json,
);
return result.isNotEmpty;
}
// 獲取所有檢查項目 (包含非預設項目,用於表單與名稱對應)
Future<List<CheckItem>> fetchAllCheckItems() async {
return await _apiService.fetchList<CheckItem>(
tableName: "hhp_check_items",
pk: "id",
// 撈取所有項目,以 sort_order 排序
queryFilter: "1^200^sort_order^*^^^",
fromJson: (json) => CheckItem.fromJson(json),
);
}
}