APPCHOBO
SYSTEM BOOTING...
v0.1.bit · firebase build · 富士 ed.
LV14
HP87/100
MP42/80
EXP2,840
1,240 G
앱초보의 모험
◀ 프롬프트 창고
#앱별 실전 패턴 · claude-code

[buildit] 별점·리뷰 시스템 (시공 완료 후)

빌드잇: 시공 완료 후 상호 평가 및 리뷰.

#buildit#rating#review
빌드잇: 시공 완료 후 상호 평가 및 리뷰. Firestore 스키마: ``` reviews/{reviewId} - fromUserId - toUserId - projectId - rating: 1~5 - text - photos: ["url1", "url2", ...] - createdAt - helpful: 0 ``` 구현: ```dart class ReviewService { static Future<void> submitReview({ required String fromUserId, required String toUserId, required String projectId, required double rating, required String reviewText, required List<String> photoUrls, }) async { final reviewDoc = await db.collection('reviews').add({ 'fromUserId': fromUserId, 'toUserId': toUserId, 'projectId': projectId, 'rating': rating, 'text': reviewText, 'photos': photoUrls, 'createdAt': DateTime.now(), 'helpful': 0, }); // 사용자의 평점 업데이트 await _updateUserRating(toUserId); } static Future<void> _updateUserRating(String userId) async { final snap = await db.collection('reviews') .where('toUserId', isEqualTo: userId) .get(); if (snap.docs.isEmpty) return; final avgRating = snap.docs .map((doc) => doc['rating'] as double) .reduce((a, b) => a + b) / snap.docs.length; await db.collection('users').doc(userId).update({ 'rating': avgRating, 'reviewCount': snap.size, }); } static Stream<List<Review>> getUserReviews(String userId) { return db.collection('reviews') .where('toUserId', isEqualTo: userId) .orderBy('createdAt', descending: true) .snapshots() .map((snap) => snap.docs.map((doc) => Review.fromDoc(doc)).toList()); } } ``` UI (리뷰 제출): ```dart class ReviewSubmitScreen extends StatefulWidget { final String toUserId; final String projectId; @override State<ReviewSubmitScreen> createState() => _ReviewSubmitScreenState(); } class _ReviewSubmitScreenState extends State<ReviewSubmitScreen> { double _rating = 5; late TextEditingController _reviewController; List<String> _photoUrls = []; @override void initState() { super.initState(); _reviewController = TextEditingController(); } @override Widget build(BuildContext context) { return Column( children: [ Text('평점'), RatingBar.builder( initialRating: _rating, minRating: 1, direction: Axis.horizontal, allowHalfRating: false, itemCount: 5, onRatingUpdate: (value) => setState(() => _rating = value), itemBuilder: (context, index) => Icon(Icons.star, color: Colors.amber), ), TextField( controller: _reviewController, decoration: InputDecoration(labelText: '리뷰'), maxLines: 5, ), ElevatedButton( onPressed: () async { await ReviewService.submitReview( fromUserId: currentUserId, toUserId: widget.toUserId, projectId: widget.projectId, rating: _rating, reviewText: _reviewController.text, photoUrls: _photoUrls, ); Navigator.pop(context); }, child: Text('리뷰 제출'), ), ], ); } } ``` 구현해줄까?
쓰는 법 — 위 칸에 본인 값을 채우면 아래 프롬프트에 바로 반영돼요. 복사 버튼을 누르면 채워진 그대로 클립보드에 담기니까, claude-code(또는 본인이 쓰는 AI)에 붙여넣기만 하면 됩니다. 변수가 없으면 그냥 복사해서 쓰세요.
▼ SPONSORED ▼
프롬프트 하단 광고