1
- import React from 'react' ;
1
+ import React , { useEffect , useState } from 'react' ;
2
2
import { NavLink , Route } from 'react-router-dom' ;
3
3
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' ;
4
4
import { Helmet } from 'react-helmet' ;
@@ -14,75 +14,110 @@ import JsonFormatter from './json/JsonFormatter';
14
14
import QRCodeReader from './qrcode/QrCodeReader' ;
15
15
import RegexTester from './regex/RegexTester' ;
16
16
17
+ const defaultRoutes = [
18
+ {
19
+ icon : < FontAwesomeIcon icon = "clock" /> ,
20
+ path : '/unix-converter' ,
21
+ name : 'Unix Time Converter' ,
22
+ Component : UnixTimestamp ,
23
+ } ,
24
+ {
25
+ icon : < FontAwesomeIcon icon = "registered" /> ,
26
+ path : '/regex-tester' ,
27
+ name : 'Regex Tester' ,
28
+ Component : RegexTester ,
29
+ } ,
30
+ {
31
+ icon : < FontAwesomeIcon icon = { [ 'fab' , 'markdown' ] } /> ,
32
+ path : '/markdown-to-html' ,
33
+ name : 'Markdown to HTML' ,
34
+ Component : MarkdownToHtml ,
35
+ } ,
36
+ {
37
+ icon : < FontAwesomeIcon icon = { [ 'fab' , 'html5' ] } /> ,
38
+ path : '/html-preview' ,
39
+ name : 'HTML Preview' ,
40
+ Component : HtmlPreview ,
41
+ } ,
42
+ {
43
+ icon : < FontAwesomeIcon icon = "qrcode" /> ,
44
+ path : '/qrcode-generator' ,
45
+ name : 'QRCode Generator' ,
46
+ Component : QrCodeGenerator ,
47
+ } ,
48
+ {
49
+ icon : < FontAwesomeIcon icon = "camera" /> ,
50
+ path : '/qrcode-reader' ,
51
+ name : 'QRCode Reader' ,
52
+ Component : QRCodeReader ,
53
+ } ,
54
+ {
55
+ icon : < FontAwesomeIcon icon = "code" /> ,
56
+ path : '/base64-encoder' ,
57
+ name : 'Base64 Encoder' ,
58
+ Component : Base64 ,
59
+ } ,
60
+ {
61
+ icon : < FontAwesomeIcon icon = "exchange-alt" /> ,
62
+ path : '/text-diff' ,
63
+ name : 'Text Diff' ,
64
+ Component : DiffText ,
65
+ } ,
66
+ {
67
+ icon : < FontAwesomeIcon icon = { [ 'fab' , 'js-square' ] } /> ,
68
+ path : '/json-formatter' ,
69
+ name : 'JSON Formatter' ,
70
+ Component : JsonFormatter ,
71
+ } ,
72
+ {
73
+ icon : < FontAwesomeIcon icon = "database" /> ,
74
+ path : '/sql-formatter' ,
75
+ name : 'SQL Formatter' ,
76
+ Component : SqlFormatter ,
77
+ } ,
78
+ ] ;
79
+
17
80
const Main = ( ) => {
18
- const routes = [
19
- {
20
- icon : < FontAwesomeIcon icon = "clock" /> ,
21
- path : '/unix-converter' ,
22
- name : 'Unix Time Converter' ,
23
- Component : UnixTimestamp ,
24
- } ,
25
- {
26
- icon : < FontAwesomeIcon icon = "registered" /> ,
27
- path : '/regex-tester' ,
28
- name : 'Regex Tester' ,
29
- Component : RegexTester ,
30
- } ,
31
- {
32
- icon : < FontAwesomeIcon icon = { [ 'fab' , 'markdown' ] } /> ,
33
- path : '/markdown-to-html' ,
34
- name : 'Markdown to HTML' ,
35
- Component : MarkdownToHtml ,
36
- } ,
37
- {
38
- icon : < FontAwesomeIcon icon = { [ 'fab' , 'html5' ] } /> ,
39
- path : '/html-preview' ,
40
- name : 'HTML Preview' ,
41
- Component : HtmlPreview ,
42
- } ,
43
- {
44
- icon : < FontAwesomeIcon icon = "qrcode" /> ,
45
- path : '/qrcode-generator' ,
46
- name : 'QRCode Generator' ,
47
- Component : QrCodeGenerator ,
48
- } ,
49
- {
50
- icon : < FontAwesomeIcon icon = "camera" /> ,
51
- path : '/qrcode-reader' ,
52
- name : 'QRCode Reader' ,
53
- Component : QRCodeReader ,
54
- } ,
55
- {
56
- icon : < FontAwesomeIcon icon = "code" /> ,
57
- path : '/base64-encoder' ,
58
- name : 'Base64 Encoder' ,
59
- Component : Base64 ,
60
- } ,
61
- {
62
- icon : < FontAwesomeIcon icon = "exchange-alt" /> ,
63
- path : '/text-diff' ,
64
- name : 'Text Diff' ,
65
- Component : DiffText ,
66
- } ,
67
- {
68
- icon : < FontAwesomeIcon icon = { [ 'fab' , 'js-square' ] } /> ,
69
- path : '/json-formatter' ,
70
- name : 'JSON Formatter' ,
71
- Component : JsonFormatter ,
72
- } ,
73
- {
74
- icon : < FontAwesomeIcon icon = "database" /> ,
75
- path : '/sql-formatter' ,
76
- name : 'SQL Formatter' ,
77
- Component : SqlFormatter ,
78
- } ,
79
- ] ;
81
+ const [ routes , setRoutes ] = useState ( defaultRoutes ) ;
82
+ const [ search , setSearch ] = useState ( '' ) ;
83
+
84
+ const handleSearch = ( e : { target : { value : string } } ) => {
85
+ setSearch ( e . target . value ) ;
86
+ } ;
87
+
88
+ useEffect ( ( ) => {
89
+ if ( search . trim ( ) ) {
90
+ setRoutes (
91
+ defaultRoutes . filter ( ( { name } ) => name . match ( new RegExp ( search , 'gi' ) ) )
92
+ ) ;
93
+ } else {
94
+ setRoutes ( defaultRoutes ) ;
95
+ }
96
+ } , [ search ] ) ;
80
97
81
98
return (
82
99
< div className = "absolute inset-0 flex flex-col overflow-hidden" >
83
100
< main className = "relative flex flex-1 min-h-0" >
84
101
{ /* Left sidebar */ }
85
102
< nav className = "flex flex-col w-1/4 overflow-x-hidden overflow-y-auto bg-gray-300" >
103
+ { /* Search */ }
104
+ < div className = "flex items-center px-3 mx-3 mt-6 space-x-1 text-gray-400 bg-gray-200 rounded-md focus-within:text-gray-600 focus-within:ring-2 focus-within:ring-blue-500" >
105
+ < FontAwesomeIcon icon = "search" />
106
+ < input
107
+ type = "text"
108
+ className = "w-full p-1 bg-gray-200 border-none rounded-r-md focus:ring-0"
109
+ value = { search }
110
+ onChange = { handleSearch }
111
+ placeholder = "Search..."
112
+ />
113
+ { search && (
114
+ < FontAwesomeIcon
115
+ icon = "times-circle"
116
+ onClick = { ( ) => setSearch ( '' ) }
117
+ />
118
+ ) }
119
+ </ div >
120
+
86
121
< div
87
122
className = "px-2 my-6"
88
123
role = "menu"
@@ -106,7 +141,7 @@ const Main = () => {
106
141
{ /* Main content */ }
107
142
< section className = "relative flex flex-col w-full bg-gray-200" >
108
143
< div className = "h-full px-6 my-6 overflow-x-hidden overflow-y-auto" >
109
- { routes . map ( ( { path, name, Component } ) => (
144
+ { defaultRoutes . map ( ( { path, name, Component } ) => (
110
145
< Route key = { path } exact path = { path } >
111
146
< Component />
112
147
< Helmet >
0 commit comments