Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

좋아요&싫어요 기능 구현 #87

Merged
merged 17 commits into from
Aug 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/core/TopScreen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class TopScreen extends ConsumerWidget {
selectedIconTheme: const IconThemeData(color: Colors.black),
selectedItemColor: Colors.black,
unselectedIconTheme: const IconThemeData(color: Colors.grey),
backgroundColor: Colors.blueGrey[100],
backgroundColor: Colors.white,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.podcasts),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';

// 친구목록 이미지 URL을 제공하는 Provider
final friendsListImageProvider =
FutureProvider.family<String, String>((ref, imageName) async {
FutureProvider.family<String, String>((ref, imageName) async {
final storageRef = FirebaseStorage.instance.ref('profileimage/$imageName');
final downloadUrl = await storageRef.getDownloadURL();
return downloadUrl;
});
});
7 changes: 2 additions & 5 deletions lib/feature/friendsList/provider/FriendsListProvider.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../../../model/FriendModel.dart';
import '../../../utils/AppStrings.dart';
import '../../../utils/Talker.dart';
import '../../userreport/provider/UserReportBottomSheetWidget.dart';

// 친구목록을 제공하는 Provider
Expand All @@ -21,7 +19,8 @@ final friendsListProvider = StreamProvider<List<FriendModel>>((ref) {
.asyncMap((snapshot) async {
final friendModels = await Future.wait(snapshot.docs.map((doc) async {
final userID = doc['userID'] as String;
final userDoc = await firestore.collection('users_test').doc(userID).get();
final userDoc =
await firestore.collection('users_test').doc(userID).get();

if (userDoc.exists) {
return FriendModel.fromJson(userDoc.data()!);
Expand Down Expand Up @@ -57,8 +56,6 @@ final deleteFriendProvider =
};
});



// ui 팝업 메뉴 선택시 처리하는 함수
void handleMenuSelection(
BuildContext context, WidgetRef ref, int value, FriendModel friend) async {
Expand Down
4 changes: 3 additions & 1 deletion lib/feature/match/MatchScreen.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import '../../utils/AppStrings.dart';
import 'widget/MatchProfileListWidget.dart';
import 'widget/MatchFilterWidget.dart';

Expand All @@ -23,8 +24,9 @@ class MatchScreen extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text(
'Petting',
AppStrings.appbar_Text_Logo,
style: GoogleFonts.lobster(
textStyle: const TextStyle(
fontSize: 24,
Expand Down
1 change: 0 additions & 1 deletion lib/feature/match/provider/MatchProvider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,6 @@ class MatchScreenNotifier extends StateNotifier<List<PetProfileModel>> {
Future<void> _addFriend(String userId, String friendId) async {
final firestore = FirebaseFirestore.instance;
final userDoc = firestore.collection('users_test').doc(userId);

try {
await userDoc.collection('friends').doc(friendId).set({
'userID': friendId,
Expand Down
10 changes: 7 additions & 3 deletions lib/feature/post/PostScreen.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// 게시물 화면!
//
import 'package:blueberry_flutter_template/feature/mbti/MBTIScreen.dart';
import 'package:blueberry_flutter_template/feature/post/widget/PostListViewWidget.dart';
import 'package:blueberry_flutter_template/feature/profile/ProfileDetailScreen.dart';
Expand All @@ -8,6 +7,7 @@ import 'package:blueberry_flutter_template/feature/setting/SettingScreen.dart';
import 'package:blueberry_flutter_template/utils/AppStrings.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart';

import '../../core/widget/CustomFab.dart';
import '../chat/ChatRoomScreen.dart';
Expand Down Expand Up @@ -38,8 +38,12 @@ class PostScreen extends StatelessWidget {

AppBar _buildAppBar(BuildContext context) {
return AppBar(
centerTitle: false,
title: const Text(AppStrings.appbar_Text_Logo),
centerTitle: true,
title: Text(AppStrings.appbar_Text_Logo,
style: GoogleFonts.lobster(
fontSize: 24,
fontWeight: FontWeight.bold,
)),
actions: [
IconButton(
icon: const Icon(Icons.message),
Expand Down
46 changes: 21 additions & 25 deletions lib/feature/post/PostingScreen.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import 'package:blueberry_flutter_template/utils/Talker.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

import '../../model/PostModel.dart';

class PostingScreen extends StatefulWidget {
static const name = 'CreatePostPage';
Expand Down Expand Up @@ -63,27 +59,27 @@ class _PostingScreenState extends State<PostingScreen> {
},
),
const SizedBox(height: 20),
Center(
child: ElevatedButton(
onPressed: () {
if (_formKey.currentState?.validate() ?? false) {
_formKey.currentState?.save();
final String uploadTime =
DateFormat('yyyy-MM-dd HH:mm:ss')
.format(DateTime.now());
final post = PostModel(
title: title!,
content: content!,
imageUrl: imageUrl!,
uploadTime: uploadTime,
);
// 포스트 생성 후 처리
talker.info('포스트 생성: ${post.toJson()}');
}
},
child: const Text('포스트 생성'),
),
),
// Center(
// child: ElevatedButton(
// onPressed: () {
// if (_formKey.currentState?.validate() ?? false) {
// _formKey.currentState?.save();
// final String uploadTime =
// DateFormat('yyyy-MM-dd HH:mm:ss')
// .format(DateTime.now());
// final post = PostModel(
// title: title!,
// content: content!,
// imageUrl: imageUrl!,
// uploadTime: uploadTime,
// );
// // 포스트 생성 후 처리
// talker.info('포스트 생성: ${post.toJson()}');
// }
// },
// child: const Text('포스트 생성'),
// ),
// ),
],
),
),
Expand Down
73 changes: 73 additions & 0 deletions lib/feature/post/provider/DisLikeProvider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

final dislikeProvider =
StateNotifierProvider<DislikeNotifier, Map<String, bool>>((ref) {
return DislikeNotifier();
});

class DislikeNotifier extends StateNotifier<Map<String, bool>> {
DislikeNotifier() : super({});

// 싫어요 상태를 가져오기
Future<void> fetchDislikeStatus(String postID, String userID) async {
final dislikeDoc = await FirebaseFirestore.instance
.collection('posts')
.doc(postID)
.collection('dislikes')
.doc(userID)
.get();

if (dislikeDoc.exists) {
state = {
...state,
postID: true,
};
} else {
state = {
...state,
postID: false,
};
}
}

// 싫어요 토글 기능
Future<void> toggleDislike(String postID, String userID) async {
final postRef = FirebaseFirestore.instance.collection('posts').doc(postID);
final dislikeRef = postRef.collection('dislikes').doc(userID);

final dislikeDoc = await dislikeRef.get();
final isDisliked = dislikeDoc.exists;

if (isDisliked) {
// 이미 싫어요 상태라면 싫어요 취소
await dislikeRef.delete();
state = {
...state,
postID: false,
};
} else {
// 싫어요 추가
await dislikeRef.set({
'createdAt': Timestamp.now(),
'postID': postID,
'userID': userID,
});
state = {
...state,
postID: true,
};
}

// 싫어요 카운트 업데이트
await _updateDislikesCount(postRef, isDisliked ? -1 : 1);
}

// 싫어요 카운트 업데이트 기능
Future<void> _updateDislikesCount(
DocumentReference postRef, int dislikeChange) async {
await postRef.update({
'dislikesCount': FieldValue.increment(dislikeChange),
});
}
}
73 changes: 73 additions & 0 deletions lib/feature/post/provider/LikeProvider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

final likeProvider =
StateNotifierProvider<LikeNotifier, Map<String, bool>>((ref) {
return LikeNotifier();
});

class LikeNotifier extends StateNotifier<Map<String, bool>> {
LikeNotifier() : super({});

// 좋아요 상태를 가져오기
Future<void> fetchLikeStatus(String postID, String userID) async {
final likeDoc = await FirebaseFirestore.instance
.collection('posts')
.doc(postID)
.collection('likes')
.doc(userID)
.get();

if (likeDoc.exists) {
state = {
...state,
'postID': true,
};
} else {
state = {
...state,
'postID': false,
};
}
}

// 좋아요 토글 기능
Future<void> toggleLike(String postID, String userID) async {
final postRef = FirebaseFirestore.instance.collection('posts').doc(postID);
final likeRef = postRef.collection('likes').doc(userID);

final likeDoc = await likeRef.get();
final isLiked = likeDoc.exists;

if (isLiked) {
// 이미 좋아요 상태라면 좋아요 취소
await likeRef.delete();
state = {
...state,
postID: false,
};
} else {
// 좋아요 추가
await likeRef.set({
'createdAt': Timestamp.now(),
'postID': postID,
'userID': userID,
});
state = {
...state,
postID: true,
};
}

// 좋아요 카운트 업데이트
await _updateLikesCount(postRef, isLiked ? -1 : 1);
}

// 좋아요 카운트 업데이트 기능
Future<void> _updateLikesCount(
DocumentReference postRef, int likeChange) async {
await postRef.update({
'likesCount': FieldValue.increment(likeChange),
});
}
}
19 changes: 17 additions & 2 deletions lib/feature/post/provider/PostProvider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,24 @@ import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:blueberry_flutter_template/model/PostModel.dart';

final postListInfoProvider = StreamProvider<List<PostModel>>((ref) {
final postProvider = StreamProvider<List<PostModel>>((ref) {
final firestore = FirebaseFirestore.instance;

return firestore.collection('posts').snapshots().map((snapshot) {
return snapshot.docs.map((doc) => PostModel.fromJson(doc.data())).toList();
return snapshot.docs.map((doc) {
final data = doc.data();

// Firestore Timestamp 를 String으로 변환
final createdAt =
(data['createdAt'] as Timestamp).toDate().toIso8601String();

// 변환된 String 형의 createdAt 를 PostModel에 전달(freezed로 생성된 fromJson은 String을 DateTime으로 변환)
final post = PostModel.fromJson({
...data,
'createdAt': createdAt,
});

return post;
}).toList();
});
});
28 changes: 28 additions & 0 deletions lib/feature/post/provider/UserInfoProvider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:blueberry_flutter_template/model/PostUserInfoModel.dart';

final postUserInfoProvider =
FutureProvider.family<PostUserInfoModel, String>((ref, userID) async {
final firestore = FirebaseFirestore.instance;

final userDoc = await firestore.collection('users_test').doc(userID).get();

if (userDoc.exists) {
final data = userDoc.data()!;
final userName = data['name'] as String;
final imageName = data['imageName'] as String;

final storageRef =
FirebaseStorage.instance.ref().child('profileimage/$imageName');
final profileImageUrl = await storageRef.getDownloadURL();

return PostUserInfoModel(
name: userName,
profileImageUrl: profileImageUrl,
);
} else {
throw Exception('User data not found for userID: $userID');
}
});
Loading
Loading