diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index 32b00e58..5e7cac58 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -82,7 +82,7 @@ function UserDashboardPageContent() { /> ); case 'myskill': - return ; + return setActiveComponent('skillVerify')} />; case 'listings': return setActiveComponent('myskill')} />; case 'matches': diff --git a/src/components/User/DashboardContent/MySkillsContent.tsx b/src/components/User/DashboardContent/MySkillsContent.tsx index 9185b6ce..08f08209 100644 --- a/src/components/User/DashboardContent/MySkillsContent.tsx +++ b/src/components/User/DashboardContent/MySkillsContent.tsx @@ -2,6 +2,7 @@ 'use client'; import React, { useState, useEffect, useMemo } from 'react'; +import { useRouter } from 'next/navigation'; import { getUserSkills, deleteUserSkill } from '@/services/skillService'; import { getSkillsUsedInMatches } from '@/services/trendingService'; import { UserSkill } from '@/types/userSkill'; @@ -9,10 +10,15 @@ import { useToast } from '@/lib/context/ToastContext'; import AddSkillForm from '@/components/Dashboard/skills/AddSkillForm'; import EditSkillForm from '@/components/Dashboard/skills/EditSkillForm'; import ConfirmationModal from '@/components/Dashboard/listings/ConfirmationModal'; -import { Info, AlertTriangle, Users, Calendar, Search, Filter, BarChart3, Award, Target, Activity, BookOpen, Settings, TrendingUp, Layers, Eye, Edit2, Trash2, Lock, ChevronDown } from 'lucide-react'; +import { Info, AlertTriangle, Users, Calendar, Search, Filter, BarChart3, Award, Target, Activity, BookOpen, Settings, TrendingUp, Layers, Eye, Edit2, Trash2, Lock, ChevronDown, BadgeCheck, AlertCircle, Clock, ExternalLink } from 'lucide-react'; -const SkillsPage = () => { +interface MySkillsContentProps { + onNavigateToSkillVerification?: () => void; +} + +const SkillsPage = ({ onNavigateToSkillVerification }: MySkillsContentProps = {}) => { const { showToast } = useToast(); + const router = useRouter(); // Fallback for standalone usage const [skills, setSkills] = useState([]); const [loading, setLoading] = useState(true); const [showAddForm, setShowAddForm] = useState(false); @@ -32,12 +38,14 @@ const SkillsPage = () => { const [selectedCategory, setSelectedCategory] = useState('all'); const [selectedProficiency, setSelectedProficiency] = useState('all'); const [selectedUsageStatus, setSelectedUsageStatus] = useState('all'); + const [selectedVerificationStatus, setSelectedVerificationStatus] = useState('all'); const [sortBy, setSortBy] = useState('name'); // Custom dropdown states for mobile const [showCategoryDropdown, setShowCategoryDropdown] = useState(false); const [showProficiencyDropdown, setShowProficiencyDropdown] = useState(false); const [showUsageDropdown, setShowUsageDropdown] = useState(false); + const [showVerificationDropdown, setShowVerificationDropdown] = useState(false); const [showSortDropdown, setShowSortDropdown] = useState(false); // Function to fetch user skills and used skill IDs @@ -165,6 +173,8 @@ const SkillsPage = () => { const usedInListings = skills.filter(s => isSkillUsedInListing(s.id)).length; const usedInMatches = skills.filter(s => isSkillUsedInMatches(s.id)).length; const categories = [...new Set(skills.map(s => s.categoryName))].length; + const verifiedSkills = skills.filter(s => s.isVerified).length; + const unverifiedSkills = skills.filter(s => !s.isVerified).length; return { total: totalSkills, @@ -173,7 +183,9 @@ const SkillsPage = () => { beginner: beginnerSkills, usedInListings, usedInMatches, - categories + categories, + verified: verifiedSkills, + unverified: unverifiedSkills }; }, [skills, usedSkillIds, matchUsedSkills]); @@ -211,6 +223,12 @@ const SkillsPage = () => { if (selectedUsageStatus === 'matches' && !usedInMatch) return false; } + // Verification status filter + if (selectedVerificationStatus !== 'all') { + if (selectedVerificationStatus === 'verified' && !skill.isVerified) return false; + if (selectedVerificationStatus === 'unverified' && skill.isVerified) return false; + } + return true; }); @@ -234,7 +252,7 @@ const SkillsPage = () => { }); return filtered; - }, [skills, searchTerm, selectedCategory, selectedProficiency, selectedUsageStatus, sortBy, usedSkillIds, matchUsedSkills]); + }, [skills, searchTerm, selectedCategory, selectedProficiency, selectedUsageStatus, selectedVerificationStatus, sortBy, usedSkillIds, matchUsedSkills]); // Group filtered skills by category const skillsByCategory = filteredAndSortedSkills.reduce((acc, skill) => { @@ -275,6 +293,17 @@ const SkillsPage = () => { setViewingSkill(skill); }; + // Navigate to skill verification page + const navigateToSkillVerification = () => { + if (onNavigateToSkillVerification) { + // Use dashboard navigation if available + onNavigateToSkillVerification(); + } else { + // Fallback to router navigation for standalone usage + router.push('/user/skillverification'); + } + }; + // Truncate text const truncateText = (text: string, maxLength: number) => { if (text.length <= maxLength) return text; @@ -310,6 +339,7 @@ const SkillsPage = () => { setShowCategoryDropdown(false); setShowProficiencyDropdown(false); setShowUsageDropdown(false); + setShowVerificationDropdown(false); setShowSortDropdown(false); }; @@ -409,9 +439,25 @@ const SkillsPage = () => {
{/* Title row with proficiency level always inline */}
-

- {skill.skillTitle} -

+
+

+ {skill.skillTitle} +

+ {skill.isVerified ? ( + + ) : ( +
+ + +
+ )} +
{ { value: 'matches', label: 'In Matches' } ]; + // Verification status options + const verificationOptions = [ + { value: 'all', label: 'All Verification' }, + { value: 'verified', label: 'Verified' }, + { value: 'unverified', label: 'Unverified' } + ]; + // Sort options const sortOptions = [ { value: 'name', label: 'Sort by Name' }, @@ -541,7 +594,7 @@ const SkillsPage = () => { {/* Overall Statistics */} {skills.length > 0 && ( -
+
@@ -596,6 +649,29 @@ const SkillsPage = () => {
In Listings
+
+
+ +
+
{skillStats.verified}
+
Verified
+
+ + +
@@ -609,7 +685,7 @@ const SkillsPage = () => { {/* Search and Filters */} {skills.length > 0 && (
-
+
{/* Search - Full width on mobile */}
@@ -681,19 +757,10 @@ const SkillsPage = () => {
-
+
+ +
+
{ isOpen={showUsageDropdown} setIsOpen={setShowUsageDropdown} /> + +
+ + {/* Mobile sort filter row */} +
{ setSelectedCategory('all'); setSelectedProficiency('all'); setSelectedUsageStatus('all'); + setSelectedVerificationStatus('all'); closeAllDropdowns(); }} className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700" @@ -838,7 +934,14 @@ const SkillsPage = () => {
-

{viewingSkill.skillTitle}

+
+

{viewingSkill.skillTitle}

+ {viewingSkill.isVerified ? ( + + ) : ( + + )} +
{ {viewingSkill.categoryName}
+ {/* Verification status */} +
+
+ {viewingSkill.isVerified ? ( + <> + + Skill Verified + + ) : ( + <> + + Verification Needed + + )} +
+ {!viewingSkill.isVerified && ( + + )} +
+ {/* Status indicators */} {(isSkillUsedInListing(viewingSkill.id) || isSkillUsedInMatches(viewingSkill.id)) && (
diff --git a/src/types/userSkill.ts b/src/types/userSkill.ts index 8bbe4ae3..ece27a2a 100644 --- a/src/types/userSkill.ts +++ b/src/types/userSkill.ts @@ -9,6 +9,7 @@ export interface UserSkill { skillTitle: string; proficiencyLevel: 'Beginner' | 'Intermediate' | 'Expert'; description: string; + isVerified: boolean; createdAt: string; updatedAt?: string; }