Sifa professional network frontend (Next.js, React, TailwindCSS) sifa.id/
at main 63 lines 1.9 kB view raw
1import type { ProfileSkill } from '@/lib/types'; 2 3export const CATEGORY_ORDER = [ 4 'technical', 5 'business', 6 'creative', 7 'interpersonal', 8 'industry', 9 'community', 10 'security', 11] as const; 12 13export type SkillCategory = (typeof CATEGORY_ORDER)[number]; 14 15export const CATEGORY_LABELS: Record<string, string> = { 16 technical: 'Technical', 17 business: 'Business', 18 creative: 'Creative', 19 interpersonal: 'Interpersonal', 20 industry: 'Industry', 21 community: 'Community', 22 security: 'Security', 23 other: 'Other', 24}; 25 26/** 27 * Groups skills by category in a defined display order. 28 * 29 * - Known categories appear in CATEGORY_ORDER 30 * - Skills with no category or unrecognised categories go to "other" 31 * - Within each group: sorted by endorsementCount desc, then alphabetical by skillName 32 * - Empty groups are omitted 33 */ 34export function groupSkillsByCategory(skills: ProfileSkill[]): [string, ProfileSkill[]][] { 35 const grouped = new Map<string, ProfileSkill[]>(); 36 37 for (const skill of skills) { 38 const normalised = skill.category?.toLowerCase().trim() ?? ''; 39 const key = (CATEGORY_ORDER as readonly string[]).includes(normalised) ? normalised : 'other'; 40 if (!grouped.has(key)) grouped.set(key, []); 41 grouped.get(key)!.push(skill); 42 } 43 44 // Sort within each group 45 for (const [, groupSkills] of grouped) { 46 groupSkills.sort((a, b) => { 47 const countDiff = (b.endorsementCount ?? 0) - (a.endorsementCount ?? 0); 48 if (countDiff !== 0) return countDiff; 49 return a.name.localeCompare(b.name); 50 }); 51 } 52 53 // Build ordered entries: known categories first, then "other" 54 const ordered: [string, ProfileSkill[]][] = []; 55 for (const cat of CATEGORY_ORDER) { 56 const group = grouped.get(cat); 57 if (group?.length) ordered.push([cat, group]); 58 } 59 const otherGroup = grouped.get('other'); 60 if (otherGroup?.length) ordered.push(['other', otherGroup]); 61 62 return ordered; 63}