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

[buildit] 의뢰자 ↔ 시공자 매칭

빌드잇: 건설 의뢰자(클라이언트)와 시공자 간 프로젝트 매칭.

#buildit#matching#project-management
빌드잇: 건설 의뢰자(클라이언트)와 시공자 간 프로젝트 매칭. Firestore 스키마: ``` users/{userId} - role: "client" | "contractor" - skills: ["electrical", "plumbing", ...] (시공자용) - serviceArea: ["Seoul", "Busan", ...] (시공자용) - rating: 4.5 - reviews: 42 projects/{projectId} - clientId - title - description - requiredSkills: ["electrical", "plumbing"] - location - budget: 5000000 - status: "open" | "matched" | "in_progress" | "completed" - contractorId: (선택사항) ``` 매칭 알고리즘: ```dart class MatchingService { static Future<List<Contractor>> findMatches(String projectId) async { final projectDoc = await db.collection('projects').doc(projectId).get(); final project = Project.fromDoc(projectDoc); // 1. 필요한 스킬 보유 확인 var query = db.collection('users') .where('role', isEqualTo: 'contractor'); final candidates = await query.get(); // 2. 클라이언트에서 추가 필터링 final matches = <Contractor>[]; for (final doc in candidates.docs) { final contractor = Contractor.fromDoc(doc); // 스킬 확인 final hasRequiredSkills = project.requiredSkills .every((skill) => contractor.skills.contains(skill)); if (!hasRequiredSkills) continue; // 지역 확인 if (!contractor.serviceArea.contains(project.location)) continue; // 예산 확인 (선택) if (contractor.minBudget != null && contractor.minBudget! > project.budget) continue; // 평점 필터 (선택) if (contractor.rating < 4.0) continue; matches.add(contractor); } // 평점으로 정렬 matches.sort((a, b) => b.rating.compareTo(a.rating)); return matches.take(10).toList(); // 상위 10명 } } ``` UI: ```dart class MatchedContractorsScreen extends StatefulWidget { final String projectId; @override State<MatchedContractorsScreen> createState() => _MatchedContractorsScreenState(); } class _MatchedContractorsScreenState extends State<MatchedContractorsScreen> { @override Widget build(BuildContext context) { return FutureBuilder<List<Contractor>>( future: MatchingService.findMatches(widget.projectId), builder: (context, snapshot) { if (snapshot.hasData) { return ListView.builder( itemCount: snapshot.data!.length, itemBuilder: (context, index) { final contractor = snapshot.data![index]; return ContractorCard( contractor: contractor, onTap: () { // 시공자 상세보기 또는 채팅 시작 }, ); }, ); } return LoadingWidget(); }, ); } } ``` 구현해줄까?
쓰는 법 — 위 칸에 본인 값을 채우면 아래 프롬프트에 바로 반영돼요. 복사 버튼을 누르면 채워진 그대로 클립보드에 담기니까, claude-code(또는 본인이 쓰는 AI)에 붙여넣기만 하면 됩니다. 변수가 없으면 그냥 복사해서 쓰세요.
▼ SPONSORED ▼
프롬프트 하단 광고