Skip to content

Commit

Permalink
좋아요&싫어요 기능 구현 (#87)
Browse files Browse the repository at this point in the history
Co-authored-by: Jungwoo <108061510+jwson-automation@users.noreply.github.com>
  • Loading branch information
ottuck and jwson-automation authored Aug 31, 2024
1 parent 2da5e49 commit c5b12ef
Show file tree
Hide file tree
Showing 17 changed files with 449 additions and 196 deletions.
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

0 comments on commit c5b12ef

Please sign in to comment.