diff --git a/actions/skills/groupSkills.ts b/actions/skills/groupSkills.ts index bdee715e..329e5916 100644 --- a/actions/skills/groupSkills.ts +++ b/actions/skills/groupSkills.ts @@ -1,54 +1,126 @@ import Skill from "@/types/skills"; -const groupSkills = ( - groupedBy: string, - skills: Skill[] -): Record => { - let organizedSkills: Record = {}; +// Function to group skills by language +const groupByLanguage = (skills: Skill[]): Record => { + // Filter skills to include only those categorized as "Programming Languages" + const programmingLanguages = skills.filter( + (skill) => skill.category === "Programming Languages", + ); - const removeDuplicates = (skills: Skill[]): Skill[] => { - const skillSet = new Set(); - const uniqueSkills: Skill[] = []; - - skills.forEach((skill) => { - const serializedSkill = JSON.stringify(skill); - if (!skillSet.has(serializedSkill)) { - skillSet.add(serializedSkill); - uniqueSkills.push(skill); + // Reduce the filtered skills to group by language + return programmingLanguages.reduce( + (acc: Record, languageSkill) => { + // The language's name serves as the key, and its technical skills are the group elements + if (languageSkill.name) { + acc[languageSkill.name] = removeDuplicates([ + ...(languageSkill.technicalGeneralSkills || []), + ...(languageSkill.technicalHardSkills || []), + ...(languageSkill.technicalSoftSkills || []), + ]); } - }); + return acc; + }, + {}, + ); +}; - return uniqueSkills; - }; +// Function to group skills by category +const groupByCategory = (skills: Skill[]): Record => { + return skills.reduce((acc: Record, skill) => { + const category = skill.category || "Other"; + if (!acc[category]) { + acc[category] = []; + } + acc[category].push(skill); + return acc; + }, {}); +}; + +// Function to group skills by skill type +const groupBySkillType = (skills: Skill[]): Record => { + return skills.reduce((acc: Record, skill) => { + const skillType = skill.skillType || "Other"; + if (!acc[skillType]) { + acc[skillType] = []; + } + acc[skillType].push(skill); + return acc; + }, {}); +}; + +const removeDuplicates = (skills: Skill[]): Skill[] => { + const skillSet = new Set(); + const uniqueSkills: Skill[] = []; + + skills.forEach((skill) => { + const serializedSkill = JSON.stringify(skill); + if (!skillSet.has(serializedSkill)) { + skillSet.add(serializedSkill); + uniqueSkills.push(skill); + } + }); + + return uniqueSkills; +}; - if (groupedBy === "language") { - organizedSkills = skills.reduce((acc: Record, skill) => { - if (skill.technicalGeneralSkills) { - acc[skill.name] = removeDuplicates(skill.technicalGeneralSkills); +const recursiveFilter = ( + skills: Skill[], + excludedSkillTypes: ("hard" | "general" | "soft")[], +): Skill[] => { + return skills + .filter((skill) => !excludedSkillTypes.includes(skill.skillType)) + .map((skill) => { + const filteredSkill: Skill = { ...skill }; + + if (filteredSkill.technicalGeneralSkills) { + filteredSkill.technicalGeneralSkills = recursiveFilter( + filteredSkill.technicalGeneralSkills, + excludedSkillTypes, + ); } - return acc; - }, {}); - } else if (groupedBy === "category") { - organizedSkills = skills.reduce((acc: Record, skill) => { - const category = skill.category || "Other"; - if (!acc[category]) { - acc[category] = []; + if (filteredSkill.technicalHardSkills) { + filteredSkill.technicalHardSkills = recursiveFilter( + filteredSkill.technicalHardSkills, + excludedSkillTypes, + ); } - acc[category].push(skill); - return acc; - }, {}); - } else if (groupedBy === "skill-type") { - organizedSkills = skills.reduce((acc: Record, skill) => { - const skillType = skill.skillType || "Other"; - if (!acc[skillType]) { - acc[skillType] = []; + if (filteredSkill.technicalSoftSkills) { + filteredSkill.technicalSoftSkills = recursiveFilter( + filteredSkill.technicalSoftSkills, + excludedSkillTypes, + ); } - acc[skillType].push(skill); - return acc; - }, {}); - } else { - // groupedBy === "none" - organizedSkills["None"] = removeDuplicates(skills); + + return filteredSkill; + }); +}; + +const groupSkills = ( + groupedBy: string, + skills: Skill[], + excludedSkillTypes?: ("hard" | "general" | "soft")[], // array of skill types to be excluded +): Record => { + let organizedSkills: Record = {}; + + // Filter out the skills of excluded types recursively + const filteredSkills = excludedSkillTypes + ? recursiveFilter(skills, excludedSkillTypes) + : skills; + + switch (groupedBy) { + case "language": + organizedSkills = groupByLanguage(filteredSkills); + break; + case "category": + organizedSkills = groupByCategory(filteredSkills); + break; + case "skill-type": + organizedSkills = groupBySkillType(filteredSkills); + break; + default: + // groupedBy === "none" + organizedSkills["None"] = removeDuplicates(filteredSkills); + break; } // Remove duplicates for each category diff --git a/app/blogs/components/BlogList.tsx b/app/blogs/components/BlogList.tsx index 06568e83..6ac7c76b 100644 --- a/app/blogs/components/BlogList.tsx +++ b/app/blogs/components/BlogList.tsx @@ -72,10 +72,10 @@ export const BlogList: React.FC = ({ blogs }) => { "title", "subtitle", "category", - "technicalSkills.skill", + "technicalSkills.name", "technicalSkills.category", - "technicalSkills.skill.skill", - "softSkills.skill", + "technicalSkills.skill.name", + "softSkills.name", "softSkills.category", ], threshold: 0.3, diff --git a/app/credentials/components/CredentialsList.tsx b/app/credentials/components/CredentialsList.tsx index 4112ed38..42327f2f 100644 --- a/app/credentials/components/CredentialsList.tsx +++ b/app/credentials/components/CredentialsList.tsx @@ -85,10 +85,10 @@ const CredentialsList: React.FC = ({ "name", "issuer", "category", - "technicalSkills.skill", + "technicalSkills.name", "technicalSkills.category", - "technicalSkills.skill.skill", - "softSkills.skill", + "technicalSkills.skill.name", + "softSkills.name", "softSkills.category", ], // Only search these properties threshold: 0.3, // Lower threshold means more results diff --git a/app/projects/components/ProjectsList.tsx b/app/projects/components/ProjectsList.tsx index 88ac5733..3b821158 100644 --- a/app/projects/components/ProjectsList.tsx +++ b/app/projects/components/ProjectsList.tsx @@ -67,13 +67,13 @@ const ProjectsList: React.FC = ({ allProjects }) => { const searchOptions = { keys: [ "name", - "programmingLanguage.skill", - "technologySkills.skill", + "programmingLanguage.name", + "technologySkills.name", "technologySkills.category", - "technologySkills.skill.skill", - "softSkills.skill", + "technologySkills.skill.name", + "softSkills.name", "softSkills.category", - "extraTechnicalGeneralSkills.skill", + "extraTechnicalGeneralSkills.name", "extraTechnicalGeneralSkills.category", "tags", ], diff --git a/components/Modal/SkillsModal.tsx b/components/Modal/SkillsModal.tsx index 3e4500ac..6ea7158a 100644 --- a/components/Modal/SkillsModal.tsx +++ b/components/Modal/SkillsModal.tsx @@ -23,6 +23,7 @@ import Tag from "../Tags/Tag"; import HeadingThree from "../Text/HeadingThree"; import HeadingTwo from "../Text/HeadingTwo"; import { Button } from "../shadcn/ui/button"; +import groupSkills from "@/actions/skills/groupSkills"; /** * Displays a modal for the skills. @@ -49,48 +50,17 @@ const SkillsModal: React.FC = () => { (skill) => skill.isMainSkill, ); - const groupSkills = ( - skills: Skill[], - groupedBy: string, - ): Record => { - if (groupedBy === "none") { - return { None: skills }; - } - - return skills.reduce( - (acc, skill) => { - // Group by category - if (groupedBy === "category") { - const key = skill.category; - acc[key] = acc[key] || []; - acc[key].push(skill); - } - // Group by language - else if ( - groupedBy === "language" && - skill.category === "Programming Languages" - ) { - skill.technicalGeneralSkills?.forEach((subSkill) => { - if (subSkill.skillType === "hard" && subSkill.isMainSkill) { - const key = skill.name; // Grouping under the main programming language - acc[key] = acc[key] || []; - acc[key].push(subSkill); - } - }); - } - return acc; - }, - {} as Record, - ); - }; - const options: FilterOption[] = [ { slug: "category", entryName: "Category" }, { slug: "language", entryName: "Language" }, { slug: "none", entryName: "None" }, ]; - const groupedSkills = groupSkills(displayedSkills, groupedBy); + const groupedSkills = groupSkills(groupedBy, displayedSkills, [ + "general", + "soft", + ]); + return (