rup-project/app/lib/services/firestore_service.dart

151 lines
5.1 KiB
Dart

import 'dart:io';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:uuid/uuid.dart';
import '../models/pet_model.dart';
import '../utils/log_manager.dart';
class FirestoreService {
final FirebaseFirestore _db = FirebaseFirestore.instance;
final FirebaseStorage _storage = FirebaseStorage.instance;
final FirebaseAuth _auth = FirebaseAuth.instance;
// 반려동물 등록
Future<void> registerPet(Pet pet, File? imageFile) async {
try {
String? imageUrl;
// 1. 이미지 업로드 (이미지가 있는 경우)
if (imageFile != null) {
final String fileName =
'${pet.id}_${DateTime.now().millisecondsSinceEpoch}.jpg';
final Reference storageRef = _storage
.ref()
.child('pet_images')
.child(fileName);
LogManager().addLog(
'[Storage] Starting upload to ${storageRef.fullPath}',
);
LogManager().addLog('[Storage] Bucket: ${_storage.bucket}');
final TaskSnapshot snapshot = await storageRef.putFile(imageFile);
if (snapshot.state == TaskState.success) {
LogManager().addLog(
'[Storage] Upload success. Validating metadata...',
);
// 잠시 대기 (consistency 이슈 방지)
await Future.delayed(const Duration(milliseconds: 500));
imageUrl = await storageRef.getDownloadURL();
LogManager().addLog('[Storage] Download URL retrieved: $imageUrl');
} else {
throw Exception('이미지 업로드 실패 (상태: ${snapshot.state})');
}
}
// 2. Pet 객체에 이미지 URL 업데이트 (새로운 객체 생성)
Pet petWithImage = Pet(
id: pet.id,
ownerId: pet.ownerId,
name: pet.name,
species: pet.species,
breed: pet.breed,
gender: pet.gender,
isNeutered: pet.isNeutered,
birthDate: pet.birthDate,
isDateUnknown: pet.isDateUnknown,
registrationNumber: pet.registrationNumber,
profileImageUrl: imageUrl, // 이미지 URL 설정
weight: pet.weight, // 체중 추가
diseases: pet.diseases,
pastDiseases: pet.pastDiseases,
healthConcerns: pet.healthConcerns,
createdAt: pet.createdAt,
);
// 3. Firestore에 저장
await _db.collection('pets').doc(pet.id).set(petWithImage.toMap());
LogManager().addLog('[Firestore] Pet registered successfully: ${pet.id}');
} catch (e) {
LogManager().addLog('[Firestore] Error registering pet: $e');
throw Exception('반려동물 등록 실패: $e');
}
}
// 반려동물 정보 수정
Future<void> updatePet(Pet pet, File? newImageFile) async {
try {
String? imageUrl = pet.profileImageUrl;
// 1. 새 이미지가 있다면 업로드 및 기존 이미지 삭제(선택사항)
if (newImageFile != null) {
// 기존 이미지가 있다면 삭제할 수도 있겠지만, 여기선 덮어쓰거나 새로 올림
// 간단히 새로 올리고 URL 교체
final String fileName =
'${pet.id}_${DateTime.now().millisecondsSinceEpoch}.jpg';
final Reference storageRef = _storage
.ref()
.child('pet_images')
.child(fileName);
LogManager().addLog('[Storage] Uploading new image...');
await storageRef.putFile(newImageFile);
imageUrl = await storageRef.getDownloadURL();
}
// 2. Pet 객체 업데이트
Pet updatedPet = Pet(
id: pet.id, // ID 유지
ownerId: pet.ownerId, // Owner ID 유지
name: pet.name,
species: pet.species,
breed: pet.breed,
gender: pet.gender,
isNeutered: pet.isNeutered,
birthDate: pet.birthDate,
isDateUnknown: pet.isDateUnknown,
registrationNumber: pet.registrationNumber,
profileImageUrl: imageUrl,
weight: pet.weight,
diseases: pet.diseases,
pastDiseases: pet.pastDiseases,
healthConcerns: pet.healthConcerns,
createdAt: pet.createdAt, // 생성일 유지
);
// 3. Firestore 업데이트
await _db.collection('pets').doc(pet.id).set(updatedPet.toMap());
LogManager().addLog('[Firestore] Pet updated successfully: ${pet.id}');
} catch (e) {
LogManager().addLog('[Firestore] Error updating pet: $e');
throw Exception('반려동물 수정 실패: $e');
}
}
// 현재 로그인한 사용자의 ID 가져오기
String? getCurrentUserId() {
return _auth.currentUser?.uid;
}
// 반려동물 리스트 스트림 가져오기
Stream<List<Pet>> getPets(String userId) {
return _db
.collection('pets')
.where('ownerId', isEqualTo: userId)
.orderBy('createdAt', descending: true) // 최신 등록순
.snapshots()
.map((snapshot) {
return snapshot.docs.map((doc) => Pet.fromMap(doc.data())).toList();
});
}
// 새 Pet ID 생성
String generatePetId() {
return const Uuid().v4();
}
}