From 666e9f20f79c188d334333b641634266e335b63c Mon Sep 17 00:00:00 2001 From: AdithaBuwaneka Date: Tue, 22 Jul 2025 17:14:23 +0530 Subject: [PATCH 1/3] feat: add skill verification logic and integrate user skills fetching in MatchCard and MatchDetailsModal --- .../Dashboard/matches/MatchCard.tsx | 13 ++----- .../Dashboard/matches/MatchDetailsModal.tsx | 34 +++++++++++++++++-- .../User/DashboardContent/MatchesContent.tsx | 1 + src/services/skillServiceAdmin.ts | 27 +++++++++++++++ 4 files changed, 63 insertions(+), 12 deletions(-) create mode 100644 src/services/skillServiceAdmin.ts diff --git a/src/components/Dashboard/matches/MatchCard.tsx b/src/components/Dashboard/matches/MatchCard.tsx index 215fb42..557969e 100644 --- a/src/components/Dashboard/matches/MatchCard.tsx +++ b/src/components/Dashboard/matches/MatchCard.tsx @@ -5,15 +5,16 @@ import Image from 'next/image'; import { SkillMatch } from '@/types/skillMatch'; import { BadgeCheck, ArrowRightLeft, Eye, MessageCircle, Clock, CheckCircle, XCircle, Award, Calendar, AlertCircle } from 'lucide-react'; import { processAvatarUrl } from '@/utils/avatarUtils'; +import { getUserSkillsByUserId } from '@/services/skillServiceAdmin'; interface MatchCardProps { match: SkillMatch; onClick: () => void; + currentUserId?: string; // Needed to look up myDetails userId } -const MatchCard: React.FC = ({ match, onClick }) => { +const MatchCard: React.FC = ({ match, onClick, currentUserId }) => { const [otherUserKycStatus, setOtherUserKycStatus] = useState(null); - // Fetch KYC status for the other user useEffect(() => { async function fetchKycStatus() { @@ -255,14 +256,6 @@ const MatchCard: React.FC = ({ match, onClick }) => { : "🔄 Partial match! They can teach you what you're seeking."}

- - {/* Success indicators */} - {match.status === 'accepted' && ( -
- - Chat available -
- )} diff --git a/src/components/Dashboard/matches/MatchDetailsModal.tsx b/src/components/Dashboard/matches/MatchDetailsModal.tsx index 1b1bbf3..8dae1d2 100644 --- a/src/components/Dashboard/matches/MatchDetailsModal.tsx +++ b/src/components/Dashboard/matches/MatchDetailsModal.tsx @@ -10,6 +10,7 @@ import { fetchUserChatRooms } from '@/services/chatApiServices'; import { useAuth } from '@/lib/context/AuthContext'; import { BadgeCheck, ArrowRight, MessageCircle, Calendar, XCircle, CheckCircle, Clock, Award, BarChart3, Target, AlertCircle } from 'lucide-react'; import { processAvatarUrl } from '@/utils/avatarUtils'; +import { getUserSkillsByUserId } from '@/services/skillServiceAdmin'; interface MatchDetailsModalProps { match: SkillMatch; @@ -94,6 +95,31 @@ const MatchDetailsModal: React.FC = ({ match, currentUse const [openingChat, setOpeningChat] = useState(false); const [otherUserKycStatus, setOtherUserKycStatus] = useState(null); + // Skill verification state and effect (must be inside component) + const [mySkillVerified, setMySkillVerified] = useState(null); + const [otherSkillVerified, setOtherSkillVerified] = useState(null); + useEffect(() => { + async function fetchSkillVerification() { + // My skill: use currentUserId + if (currentUserId && match.myDetails && match.myDetails.offeringSkill) { + const res = await getUserSkillsByUserId(currentUserId); + if (res.success && res.data) { + const found = res.data.find((s: any) => s.skillTitle === match.myDetails.offeringSkill); + setMySkillVerified(found ? !!found.isVerified : false); + } + } + // Other user's skill + if (match.otherUser && match.otherUser.offeringSkill && match.otherUser.userId) { + const res = await getUserSkillsByUserId(match.otherUser.userId); + if (res.success && res.data) { + const found = res.data.find((s: any) => s.skillTitle === match.otherUser.offeringSkill); + setOtherSkillVerified(found ? !!found.isVerified : false); + } + } + } + fetchSkillVerification(); + }, [currentUserId, match.myDetails, match.otherUser]); + // Fetch KYC status for the other user useEffect(() => { async function fetchKycStatus() { @@ -371,8 +397,10 @@ const MatchDetailsModal: React.FC = ({ match, currentUse
Offering -

+

{match.myDetails.offeringSkill} + {mySkillVerified === true && } + {mySkillVerified === false && }

You'll teach this skill @@ -441,8 +469,10 @@ const MatchDetailsModal: React.FC = ({ match, currentUse

They Offer -

+

{match.otherUser.offeringSkill} + {otherSkillVerified === true && } + {otherSkillVerified === false && }

{match.otherUser.firstName} will teach you this diff --git a/src/components/User/DashboardContent/MatchesContent.tsx b/src/components/User/DashboardContent/MatchesContent.tsx index 3f87758..7e48f3a 100644 --- a/src/components/User/DashboardContent/MatchesContent.tsx +++ b/src/components/User/DashboardContent/MatchesContent.tsx @@ -527,6 +527,7 @@ const MatchesPage = () => { key={match.id} match={match} onClick={() => viewMatchDetails(match)} + currentUserId={currentUserId} /> ))}

diff --git a/src/services/skillServiceAdmin.ts b/src/services/skillServiceAdmin.ts new file mode 100644 index 0000000..fbf2139 --- /dev/null +++ b/src/services/skillServiceAdmin.ts @@ -0,0 +1,27 @@ +// Service to fetch another user's skills by userId (for admin or cross-user lookups) +import { ApiResponse, UserSkill } from '@/types/userSkill'; + +export const getUserSkillsByUserId = async (userId: string): Promise> => { + try { + const response = await fetch(`/api/userskillfetch?userId=${userId}`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }); + const apiResponse = await response.json(); + if (apiResponse.success && apiResponse.categories) { + // Flatten all skills from all categories + const allSkills = apiResponse.categories.flatMap((cat: any) => cat.skills.map((s: any) => ({ + ...s, + categoryId: cat.categoryId, + categoryName: cat.categoryName, + }))); + return { success: true, data: allSkills }; + } + return { success: false, message: apiResponse.message || 'Failed to fetch user skills' }; + } catch (error) { + console.error('Error fetching user skills by userId:', error); + return { success: false, message: 'Failed to fetch user skills' }; + } +}; From c41e5bcea1586928712a99d54611a61dd0051d52 Mon Sep 17 00:00:00 2001 From: AdithaBuwaneka Date: Tue, 22 Jul 2025 17:20:07 +0530 Subject: [PATCH 2/3] feat: center status display in MatchCard footer and remove quick action button --- .../Dashboard/matches/MatchCard.tsx | 31 +++++-------------- 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/src/components/Dashboard/matches/MatchCard.tsx b/src/components/Dashboard/matches/MatchCard.tsx index 557969e..0c278b7 100644 --- a/src/components/Dashboard/matches/MatchCard.tsx +++ b/src/components/Dashboard/matches/MatchCard.tsx @@ -259,32 +259,15 @@ const MatchCard: React.FC = ({ match, onClick, currentUserId })
- {/* Card Footer */} + {/* Card Footer - Centered status only */}
-
- {/* Quick action based on status */} -
-
- {match.status === 'pending' && '⏳ Awaiting your response'} - {match.status === 'accepted' && '🚀 Ready to collaborate'} - {match.status === 'completed' && '✅ Successfully completed'} - {match.status === 'rejected' && '❌ Match declined'} -
+
+
+ {match.status === 'pending' && '⏳ Awaiting your response'} + {match.status === 'accepted' && '🚀 Ready to collaborate'} + {match.status === 'completed' && '✅ Successfully completed'} + {match.status === 'rejected' && '❌ Match declined'}
- -
From bc147a6a2ff5ff1dd47f0e3842c6c012dddac728 Mon Sep 17 00:00:00 2001 From: AdithaBuwaneka Date: Tue, 22 Jul 2025 17:45:15 +0530 Subject: [PATCH 3/3] feat: add KYC status fetching for current user and display verification status in MatchDetailsModal --- .../Dashboard/matches/MatchDetailsModal.tsx | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/components/Dashboard/matches/MatchDetailsModal.tsx b/src/components/Dashboard/matches/MatchDetailsModal.tsx index 8dae1d2..77d76c5 100644 --- a/src/components/Dashboard/matches/MatchDetailsModal.tsx +++ b/src/components/Dashboard/matches/MatchDetailsModal.tsx @@ -98,6 +98,7 @@ const MatchDetailsModal: React.FC = ({ match, currentUse // Skill verification state and effect (must be inside component) const [mySkillVerified, setMySkillVerified] = useState(null); const [otherSkillVerified, setOtherSkillVerified] = useState(null); + const [myKycStatus, setMyKycStatus] = useState(null); useEffect(() => { async function fetchSkillVerification() { // My skill: use currentUserId @@ -120,21 +121,30 @@ const MatchDetailsModal: React.FC = ({ match, currentUse fetchSkillVerification(); }, [currentUserId, match.myDetails, match.otherUser]); - // Fetch KYC status for the other user + // Fetch KYC status for both users useEffect(() => { async function fetchKycStatus() { try { - const res = await fetch(`/api/kyc/status?userId=${match.otherUser.userId}`); - const data = await res.json(); - setOtherUserKycStatus(data.success ? data.status : null); + // Fetch other user's KYC status + const otherRes = await fetch(`/api/kyc/status?userId=${match.otherUser.userId}`); + const otherData = await otherRes.json(); + setOtherUserKycStatus(otherData.success ? otherData.status : null); + + // Fetch my KYC status + if (currentUserId) { + const myRes = await fetch(`/api/kyc/status?userId=${currentUserId}`); + const myData = await myRes.json(); + setMyKycStatus(myData.success ? myData.status : null); + } } catch (err) { setOtherUserKycStatus(null); + setMyKycStatus(null); } } if (match.otherUser.userId) { fetchKycStatus(); } - }, [match.otherUser.userId]); + }, [match.otherUser.userId, currentUserId]); // Format date const formatDate = (dateString: string) => { @@ -389,7 +399,14 @@ const MatchDetailsModal: React.FC = ({ match, currentUse />
-

Your Profile

+

+ Your Profile + {(myKycStatus === 'Accepted' || myKycStatus === 'Approved') ? ( + + ) : ( + + )} +

Skills Exchange