@@ -10,12 +10,14 @@ import { useSkillImportExport } from "../hooks/useSkillImportExport";
1010import { SkillDetailPage } from "./SkillDetailPage" ;
1111import { SkillsDialogs } from "./SkillsDialogs" ;
1212import { SkillsEmptyState } from "./SkillsEmptyState" ;
13- import { SkillsListSections , type SkillsSection } from "./SkillsListSections" ;
14- import { SkillsToolbar , type SkillsFilter } from "./SkillsToolbar" ;
13+ import { SkillsListSections } from "./SkillsListSections" ;
14+ import { SkillsToolbar } from "./SkillsToolbar" ;
1515import { hydrateProjectNames } from "../lib/projectHydration" ;
1616import {
17- compareSkillsByName ,
17+ filterSkills ,
18+ groupSkills ,
1819 uniqueProjectFilters ,
20+ type SkillsFilter ,
1921} from "../lib/skillsHelpers" ;
2022import {
2123 deleteSkill ,
@@ -106,90 +108,24 @@ export function SkillsView({ onStartChatWithSkill }: SkillsViewProps) {
106108 ) ;
107109 } , [ categoryFilters ] ) ;
108110
109- const filteredSkills = useMemo ( ( ) => {
110- const searchTerm = search . trim ( ) . toLowerCase ( ) ;
111- return skills . filter ( ( skill ) => {
112- const matchesSearch =
113- searchTerm . length === 0 ||
114- skill . name . toLowerCase ( ) . includes ( searchTerm ) ||
115- skill . description . toLowerCase ( ) . includes ( searchTerm ) ||
116- skill . sourceLabel . toLowerCase ( ) . includes ( searchTerm ) ||
117- t ( `view.categories.options.${ skill . inferredCategory } ` )
118- . toLowerCase ( )
119- . includes ( searchTerm ) ;
120-
121- const matchesFilter =
122- activeFilter === "all"
123- ? true
124- : activeFilter === "global"
125- ? skill . sourceKind === "global"
126- : skill . projectLinks . some (
127- ( project ) => `project:${ project . id } ` === activeFilter ,
128- ) ;
129-
130- const matchesCategory =
131- selectedCategories . length === 0 ||
132- selectedCategories . includes ( skill . inferredCategory ) ;
133-
134- return matchesSearch && matchesFilter && matchesCategory ;
135- } ) ;
136- } , [ activeFilter , search , selectedCategories , skills , t ] ) ;
137-
138- const groupedSkills = useMemo < SkillsSection [ ] > ( ( ) => {
139- if ( activeFilter === "global" ) {
140- return [
141- {
142- id : "personal" ,
143- title : t ( "view.filtersGlobal" ) ,
144- skills : [ ...filteredSkills ] . sort ( compareSkillsByName ) ,
145- } ,
146- ] ;
147- }
148-
149- if ( activeFilter . startsWith ( "project:" ) ) {
150- const projectId = activeFilter . slice ( "project:" . length ) ;
151- const projectName =
152- projectFilters . find ( ( project ) => project . id === projectId ) ?. name ??
153- t ( "view.projects" ) ;
154-
155- return [
156- {
157- id : activeFilter ,
158- title : projectName ,
159- skills : [ ...filteredSkills ] . sort ( compareSkillsByName ) ,
160- } ,
161- ] ;
162- }
163-
164- const personalSkills = filteredSkills
165- . filter ( ( skill ) => skill . sourceKind === "global" )
166- . sort ( compareSkillsByName ) ;
167-
168- const projectSections = projectFilters
169- . map ( ( project ) => ( {
170- id : `project:${ project . id } ` ,
171- title : project . name ,
172- skills : filteredSkills
173- . filter ( ( skill ) =>
174- skill . projectLinks . some ( ( link ) => link . id === project . id ) ,
175- )
176- . sort ( compareSkillsByName ) ,
177- } ) )
178- . filter ( ( section ) => section . skills . length > 0 ) ;
111+ const filteredSkills = useMemo (
112+ ( ) =>
113+ filterSkills (
114+ skills ,
115+ { search, activeFilter, selectedCategories } ,
116+ ( category ) => t ( `view.categories.options.${ category } ` ) ,
117+ ) ,
118+ [ skills , search , activeFilter , selectedCategories , t ] ,
119+ ) ;
179120
180- return [
181- ...( personalSkills . length > 0
182- ? [
183- {
184- id : "personal" ,
185- title : t ( "view.filtersGlobal" ) ,
186- skills : personalSkills ,
187- } ,
188- ]
189- : [ ] ) ,
190- ...projectSections ,
191- ] ;
192- } , [ activeFilter , filteredSkills , projectFilters , t ] ) ;
121+ const groupedSkills = useMemo (
122+ ( ) =>
123+ groupSkills ( filteredSkills , activeFilter , projectFilters , {
124+ personalTitle : t ( "view.filtersGlobal" ) ,
125+ projectsFallback : t ( "view.projects" ) ,
126+ } ) ,
127+ [ filteredSkills , activeFilter , projectFilters , t ] ,
128+ ) ;
193129
194130 useEffect ( ( ) => {
195131 const nextIds = groupedSkills . map ( ( section ) => section . id ) ;
0 commit comments