@@ -3,9 +3,9 @@ import { VscSettings } from "react-icons/vsc";
33import { IoHammerOutline } from "react-icons/io5" ;
44import SelectInput from "../components/input/SelectInput" ;
55import GreenButton from "../components/buttons/GreenButton" ;
6- import { FC , useCallback , useEffect , useState } from "react" ;
6+ import { FC , useCallback , useState } from "react" ;
77import LineInput from "../components/input/LineInput" ;
8- import { Line } from "../types/line " ;
8+ import { Card , Line , newCard } from "../types/card " ;
99import { generateLink } from "../utils/generate" ;
1010import { useFetchThemes } from "../hooks/useFetchThemes" ;
1111import NumberInput from "../components/input/NumberInput" ;
@@ -19,66 +19,43 @@ interface OptionsProps {
1919
2020const Options : FC < OptionsProps > = ( props ) => {
2121 const themes = useFetchThemes ( ) ;
22- const [ lineChars , setLineChars ] = useState ( [ "1" ] ) ;
23-
24- const [ title , setTitle ] = useState < string > ( "My Tech Stack" ) ;
25- const [ lineCount , setLineCount ] = useState < string > ( "1" ) ;
26- const [ theme , setTheme ] = useState < string > ( "github" ) ;
27- const [ align , setAlign ] = useState < string > ( "left" ) ;
28- const [ lines , setLines ] = useState < Line [ ] > ( [ ] ) ;
29- const [ showBorder , setShowBorder ] = useState ( true ) ;
30- const [ borderRadius , setBorderRadius ] = useState < string > ( "4.5" ) ;
31- const [ fontWeight , setFontWeight ] = useState < string > ( "semibold" ) ;
32- const [ fontSize , setFontSize ] = useState < string > ( "18" ) ;
33-
34- useEffect ( ( ) => {
35- // create an array with the numbers of lineCount to 1
36- const res : string [ ] = [ ] ;
37- for ( let i = 1 ; i <= Number ( lineCount ) ; i ++ ) {
38- res . push ( `${ i } ` ) ;
39- setLines ( ( prev ) => [
40- ...prev ,
41- {
42- badges : [ ] ,
43- lineNumber : `${ i } ` ,
44- } ,
45- ] ) ;
46- }
47- setLineChars ( res ) ;
48- } , [ lineCount , setLineCount , setLines ] ) ;
49-
50- const reset = ( ) => {
51- setTitle ( "My Tech Stack" ) ;
52- setLineCount ( "1" ) ;
53- setTheme ( "github" ) ;
54- setAlign ( "left" ) ;
55- setShowBorder ( true ) ;
56- setLines ( [ ] ) ;
57- setBorderRadius ( "4.5" ) ;
58- setFontSize ( "18" ) ;
59- setFontWeight ( "semibold" ) ;
60- } ;
22+ const [ card , setCard ] = useState < Card > ( newCard ( ) ) ;
6123
62- const updateLine = useCallback (
63- ( line : Line ) => {
64- setLines ( ( prev ) => {
65- const res : Line [ ] = [ ] ;
24+ const updateLineCount = useCallback (
25+ ( lineNumber : number ) => {
26+ // storing just the line numbers in an array
27+ const lineNums : number [ ] = card . lines . map ( ( x ) => Number ( x . lineNumber ) ) ;
6628
67- for ( const l of [ ...prev ] ) {
68- if ( l . lineNumber === line . lineNumber ) {
69- res . push ( line ) ;
70- continue ;
71- }
29+ // variable to store the result
30+ const updated : Line [ ] = [ ] ;
7231
73- res . push ( l ) ;
32+ for ( let i = 1 ; i <= lineNumber ; i ++ ) {
33+ // if the card.lines contain line with this lineNumber
34+ if ( lineNums . includes ( i ) ) {
35+ updated . push ( card . lines . filter ( ( x ) => x . lineNumber === `${ i } ` ) [ 0 ] ) ;
36+ continue ;
7437 }
7538
76- return res ;
77- } ) ;
39+ // else push a new one
40+ updated . push ( {
41+ badges : [ ] ,
42+ lineNumber : `${ i } ` ,
43+ } ) ;
44+ }
45+
46+ setCard ( { ...card , lines : updated } ) ;
7847 } ,
79- [ setLines ]
48+ [ card ]
8049 ) ;
8150
51+ const updateLine = ( line : Line ) => {
52+ const lines = [ ...card . lines ] ;
53+
54+ lines [ lines . findIndex ( ( l ) => l . lineNumber === line . lineNumber ) ] = line ;
55+
56+ setCard ( { ...card , lines : lines } ) ;
57+ } ;
58+
8259 const validateBorderRadius = ( val : string ) : string => {
8360 const num = parseInt ( val ) ;
8461
@@ -108,40 +85,44 @@ const Options: FC<OptionsProps> = (props) => {
10885 < Input
10986 label = "Title"
11087 placeholder = "My Tech Stack"
111- value = { title }
112- setValue = { ( val ) => setTitle ( val ) }
88+ value = { card . title }
89+ setValue = { ( v ) => setCard ( { ... card , title : v , lines : card . lines } ) }
11390 validate = { ( ) => "" }
11491 />
11592
11693 < div className = "flex items-center gap-4" >
11794 < SelectInput
11895 label = "Theme"
11996 options = { themes }
120- value = { theme }
121- setValue = { setTheme }
97+ value = { card . theme }
98+ setValue = { ( v ) => setCard ( { ... card , theme : v , lines : card . lines } ) }
12299 searchField = { true }
123100 />
124101
125102 < SelectInput
126103 label = "Badge Align"
127104 options = { [ "left" , "center" , "right" ] }
128- value = { align }
129- setValue = { ( val ) => setAlign ( val ) }
105+ value = { card . align }
106+ setValue = { ( v ) => setCard ( { ... card , align : v , lines : card . lines } ) }
130107 />
131108 </ div >
132109
133110 < div className = "flex items-start gap-4" >
134111 < SelectInput
135112 label = "Font Weight"
136113 options = { [ "thin" , "normal" , "semibold" , "bold" ] }
137- value = { fontWeight }
138- setValue = { ( val ) => setFontWeight ( val ) }
114+ value = { card . fontWeight }
115+ setValue = { ( v ) =>
116+ setCard ( { ...card , fontWeight : v , lines : card . lines } )
117+ }
139118 />
140119
141120 < NumberInput
142121 label = "Font Size"
143- value = { fontSize }
144- setValue = { ( val ) => setFontSize ( val ) }
122+ value = { card . fontSize }
123+ setValue = { ( v ) =>
124+ setCard ( { ...card , fontSize : v , lines : card . lines } )
125+ }
145126 minValue = { 15 }
146127 maxValue = { 30 }
147128 />
@@ -150,23 +131,27 @@ const Options: FC<OptionsProps> = (props) => {
150131 < Input
151132 label = "Border Radius"
152133 placeholder = "4.5"
153- value = { borderRadius }
154- setValue = { ( val ) => setBorderRadius ( val ) }
134+ value = { card . borderRadius }
135+ setValue = { ( v ) =>
136+ setCard ( { ...card , borderRadius : v , lines : card . lines } )
137+ }
155138 helperText = "A number between 0 and 50."
156139 validate = { ( val ) => validateBorderRadius ( val ) }
157140 />
158141
159142 < div className = "flex items-start gap-4" >
160143 < TrueFalseInput
161144 label = "Border"
162- setValue = { ( val ) => setShowBorder ( val ) }
163- value = { showBorder }
145+ value = { card . showBorder }
146+ setValue = { ( v ) =>
147+ setCard ( { ...card , showBorder : v , lines : card . lines } )
148+ }
164149 />
165150
166151 < NumberInput
167152 label = "Lines"
168- value = { lineCount }
169- setValue = { ( val ) => setLineCount ( val ) }
153+ value = { ` ${ card . lines . length } ` }
154+ setValue = { ( v ) => updateLineCount ( Number ( v ) ) }
170155 minValue = { 1 }
171156 maxValue = { 5 }
172157 />
@@ -176,36 +161,26 @@ const Options: FC<OptionsProps> = (props) => {
176161 < div className = "my-4 flex flex-col gap-4 px-4" >
177162 < div className = "w-full h-[.8px] bg-gh-border mx-auto" />
178163
179- { lineChars . map ( ( line ) => (
180- < LineInput line = { line } updateLine = { updateLine } key = { line } />
164+ { card . lines . map ( ( line ) => (
165+ < LineInput
166+ line = { line }
167+ updateLine = { updateLine }
168+ key = { line . lineNumber }
169+ />
181170 ) ) }
182171
183172 < div className = "w-full h-[.8px] bg-gh-border mx-auto" />
184173
185174 < div className = "flex items-stretch gap-3" >
186175 < GreenButton
187176 icon = { IoHammerOutline }
188- onClick = { ( ) => {
189- props . setLink (
190- generateLink (
191- title ,
192- lineCount ,
193- theme ,
194- align ,
195- lines ,
196- showBorder ,
197- borderRadius ,
198- fontWeight ,
199- fontSize
200- )
201- ) ;
202- } }
203- disabled = { validateBorderRadius ( borderRadius ) !== "" }
177+ onClick = { ( ) => props . setLink ( generateLink ( card ) ) }
178+ disabled = { validateBorderRadius ( card . borderRadius ) !== "" }
204179 text = "Generate"
205180 />
206181
207182 < SecondaryButton
208- onClick = { ( ) => reset ( ) }
183+ onClick = { ( ) => setCard ( newCard ( ) ) }
209184 text = "Reset"
210185 className = "text-red-500 font-semibold"
211186 />
0 commit comments