11'use client' ;
22
3- import { useState , useEffect } from 'react' ;
3+ import { useState , useEffect , useCallback } from 'react' ;
44import { TemplateService } from '@/lib/db/services/templateService' ;
55import { VariableService } from '@/lib/db/services/variableService' ;
66import { Template , Variable } from '@/types' ;
77import { TemplateEditor } from '@/components/template-editor' ;
88import { VariableForm } from '@/components/variable-form' ;
99import { Tabs , TabsContent , TabsList , TabsTrigger } from '@/components/ui/tabs' ;
10+ import { Input } from '@/components/ui/input' ;
11+ import { MultiSelect } from '@/components/ui/multi-select' ;
1012
1113export default function TemplateManagerPage ( ) {
1214 const [ variables , setVariables ] = useState < Variable [ ] > ( [ ] ) ;
1315 const [ templates , setTemplates ] = useState < Template [ ] > ( [ ] ) ;
1416 const [ selectedTemplate , setSelectedTemplate ] = useState < Template | null > ( null ) ;
1517 const [ loading , setLoading ] = useState ( true ) ;
18+ const [ searchQuery , setSearchQuery ] = useState ( '' ) ;
19+ const [ selectedCategories , setSelectedCategories ] = useState < string [ ] > ( [ ] ) ;
20+ const [ tags , setTags ] = useState ( '' ) ;
1621
1722 useEffect ( ( ) => {
18- loadData ( ) ;
23+ const init = async ( ) => {
24+ await TemplateService . initializeDefaultTemplates ( ) ;
25+ await VariableService . initializeDefaultVariables ( ) ;
26+ } ;
27+ init ( ) ;
1928 } , [ ] ) ;
2029
21- const loadData = async ( ) => {
30+ const loadData = useCallback ( async ( ) => {
2231 try {
2332 setLoading ( true ) ;
33+
34+ const templatesData = await TemplateService . getFilteredTemplates ( {
35+ searchQuery,
36+ categories : selectedCategories ,
37+ tags : tags . split ( ',' ) . map ( t => t . trim ( ) ) . filter ( t => t ) ,
38+ } ) ;
2439
25- // Initialize default data if needed
26- await TemplateService . initializeDefaultTemplates ( ) ;
27- await VariableService . initializeDefaultVariables ( ) ;
28-
29- // Load data
30- const [ templatesData , variablesData ] = await Promise . all ( [
31- TemplateService . getAllTemplates ( ) ,
32- VariableService . getAllVariables ( )
33- ] ) ;
40+ const variablesData = await VariableService . getAllVariables ( ) ;
3441
3542 setTemplates ( templatesData ) ;
3643 setVariables ( variablesData ) ;
3744
3845 if ( templatesData . length > 0 ) {
3946 setSelectedTemplate ( templatesData [ 0 ] ) ;
47+ } else {
48+ setSelectedTemplate ( null ) ;
4049 }
4150 } catch ( error ) {
4251 console . error ( 'Error loading data:' , error ) ;
4352 } finally {
4453 setLoading ( false ) ;
4554 }
46- } ;
55+ } , [ searchQuery , selectedCategories , tags ] ) ;
56+
57+ useEffect ( ( ) => {
58+ loadData ( ) ;
59+ } , [ loadData ] ) ;
4760 const handleCreateTemplate = async ( ) => {
4861 const newTemplate = await TemplateService . createTemplate ( {
4962 name : 'Untitled' ,
@@ -71,6 +84,21 @@ export default function TemplateManagerPage() {
7184 }
7285 } ;
7386
87+ const getHighlightedText = ( text : string , highlight : string ) => {
88+ const parts = text . split ( new RegExp ( `(${ highlight } )` , 'gi' ) ) ;
89+ return (
90+ < span >
91+ { parts . map ( ( part , i ) =>
92+ part . toLowerCase ( ) === highlight . toLowerCase ( ) ? (
93+ < strong key = { i } > { part } </ strong >
94+ ) : (
95+ part
96+ )
97+ ) }
98+ </ span >
99+ ) ;
100+ } ;
101+
74102 if ( loading ) {
75103 return (
76104 < div className = "min-h-screen bg-background flex items-center justify-center" >
@@ -91,9 +119,35 @@ export default function TemplateManagerPage() {
91119 Create and manage your professional templates with ease
92120 </ p >
93121 </ div >
94- < button onClick = { handleCreateTemplate } className = "btn btn-primary" >
95- + New Template
96- </ button >
122+ < div className = "flex justify-between items-center" >
123+ < div className = "flex gap-4" >
124+ < Input
125+ placeholder = "Search templates..."
126+ value = { searchQuery }
127+ onChange = { ( e ) => setSearchQuery ( e . target . value ) }
128+ className = "max-w-xs"
129+ />
130+ < MultiSelect
131+ options = { [
132+ { label : 'Email' , value : 'email' } ,
133+ { label : 'Blog' , value : 'blog' } ,
134+ { label : 'Social' , value : 'social' } ,
135+ ] }
136+ onValueChange = { setSelectedCategories }
137+ defaultValue = { selectedCategories }
138+ placeholder = "Filter by category"
139+ />
140+ < Input
141+ placeholder = "Filter by tags (comma-separated)"
142+ value = { tags }
143+ onChange = { ( e ) => setTags ( e . target . value ) }
144+ className = "max-w-xs"
145+ />
146+ </ div >
147+ < button onClick = { handleCreateTemplate } className = "btn btn-primary" >
148+ + New Template
149+ </ button >
150+ </ div >
97151
98152 < div className = "grid md:grid-cols-2 gap-8" >
99153 < VariableForm
@@ -111,7 +165,7 @@ export default function TemplateManagerPage() {
111165 value = { template . id }
112166 onClick = { ( ) => setSelectedTemplate ( template ) }
113167 >
114- { template . name }
168+ { getHighlightedText ( template . name , searchQuery ) }
115169 </ TabsTrigger >
116170 ) ) }
117171 </ TabsList >
0 commit comments