11import { Button } from "@/components/ui/button" ;
22import { Input } from "@/components/ui/input" ;
33import {
4- Select ,
5- SelectContent ,
6- SelectItem ,
7- SelectTrigger ,
8- SelectValue ,
4+ Select ,
5+ SelectContent ,
6+ SelectItem ,
7+ SelectTrigger ,
8+ SelectValue ,
99} from "@/components/ui/select" ;
1010import { AlertColors } from "@/config/siteConfig" ;
1111import { cn } from "@/lib/utils" ;
@@ -15,116 +15,136 @@ import { ScriptSchema, type Script } from "../_schemas/schemas";
1515import { memo , useCallback , useRef } from "react" ;
1616
1717type NoteProps = {
18- script : Script ;
19- setScript : ( script : Script ) => void ;
20- setIsValid : ( isValid : boolean ) => void ;
21- setZodErrors : ( zodErrors : z . ZodError | null ) => void ;
18+ script : Script ;
19+ setScript : ( script : Script ) => void ;
20+ setIsValid : ( isValid : boolean ) => void ;
21+ setZodErrors : ( zodErrors : z . ZodError | null ) => void ;
2222} ;
2323
2424function Note ( {
25- script,
26- setScript,
27- setIsValid,
28- setZodErrors,
25+ script,
26+ setScript,
27+ setIsValid,
28+ setZodErrors,
2929} : NoteProps ) {
30- const inputRefs = useRef < ( HTMLInputElement | null ) [ ] > ( [ ] ) ;
30+ const inputRefs = useRef < ( HTMLInputElement | null ) [ ] > ( [ ] ) ;
3131
32- const addNote = useCallback ( ( ) => {
33- setScript ( {
34- ...script ,
35- notes : [ ...script . notes , { text : "" , type : "" } ] ,
36- } ) ;
37- } , [ script , setScript ] ) ;
32+ const addNote = useCallback ( ( ) => {
33+ setScript ( {
34+ ...script ,
35+ notes : [ ...script . notes , { text : "" , type : "" } ] ,
36+ } ) ;
37+ } , [ script , setScript ] ) ;
3838
39- const updateNote = useCallback ( (
40- index : number ,
41- key : keyof Script [ "notes" ] [ number ] ,
42- value : string ,
43- ) => {
44- const updated : Script = {
45- ...script ,
46- notes : script . notes . map ( ( note , i ) =>
47- i === index ? { ...note , [ key ] : value } : note ,
48- ) ,
49- } ;
50- const result = ScriptSchema . safeParse ( updated ) ;
51- setIsValid ( result . success ) ;
52- setZodErrors ( result . success ? null : result . error ) ;
53- setScript ( updated ) ;
54- // Restore focus after state update
55- if ( key === "text" ) {
56- setTimeout ( ( ) => {
57- inputRefs . current [ index ] ?. focus ( ) ;
58- } , 0 ) ;
59- }
60- } , [ script , setScript , setIsValid , setZodErrors ] ) ;
39+ const updateNote = useCallback ( (
40+ index : number ,
41+ key : keyof Script [ "notes" ] [ number ] ,
42+ value : string ,
43+ ) => {
44+ const updated : Script = {
45+ ...script ,
46+ notes : script . notes . map ( ( note , i ) =>
47+ i === index ? { ...note , [ key ] : value } : note ,
48+ ) ,
49+ } ;
50+ const result = ScriptSchema . safeParse ( updated ) ;
51+ setIsValid ( result . success ) ;
52+ setZodErrors ( result . success ? null : result . error ) ;
53+ setScript ( updated ) ;
54+ // Restore focus after state update
55+ if ( key === "text" ) {
56+ setTimeout ( ( ) => {
57+ inputRefs . current [ index ] ?. focus ( ) ;
58+ } , 0 ) ;
59+ }
60+ } , [ script , setScript , setIsValid , setZodErrors ] ) ;
6161
62- const removeNote = useCallback ( ( index : number ) => {
63- setScript ( {
64- ...script ,
65- notes : script . notes . filter ( ( _ , i ) => i !== index ) ,
66- } ) ;
67- } , [ script , setScript ] ) ;
62+ const removeNote = useCallback ( ( index : number ) => {
63+ setScript ( {
64+ ...script ,
65+ notes : script . notes . filter ( ( _ , i ) => i !== index ) ,
66+ } ) ;
67+ } , [ script , setScript ] ) ;
6868
69- const NoteItem = memo (
70- ( { note, index } : { note : Script [ "notes" ] [ number ] ; index : number } ) => (
71- < div className = "space-y-2 border p-4 rounded" >
72- < Input
73- placeholder = "Note Text"
74- value = { note . text }
75- onChange = { ( e ) => updateNote ( index , "text" , e . target . value ) }
76- ref = { ( el ) => {
77- inputRefs . current [ index ] = el ;
78- } }
79- />
80- < Select
81- value = { note . type }
82- onValueChange = { ( value ) => updateNote ( index , "type" , value ) }
83- >
84- < SelectTrigger className = "flex-1" >
85- < SelectValue placeholder = "Type" />
86- </ SelectTrigger >
87- < SelectContent >
88- { Object . keys ( AlertColors ) . map ( ( type ) => (
89- < SelectItem key = { type } value = { type } >
90- < span className = "flex items-center gap-2" >
91- { type . charAt ( 0 ) . toUpperCase ( ) + type . slice ( 1 ) } { " " }
92- < div
93- className = { cn (
94- "size-4 rounded-full border" ,
95- AlertColors [ type as keyof typeof AlertColors ] ,
96- ) }
97- />
98- </ span >
99- </ SelectItem >
69+ return (
70+ < >
71+ < h3 className = "text-xl font-semibold" > Notes</ h3 >
72+ { script . notes . map ( ( note , index ) => (
73+ < NoteItem key = { index } note = { note } index = { index } updateNote = { updateNote } removeNote = { removeNote } />
10074 ) ) }
101- </ SelectContent >
102- </ Select >
103- < Button
104- size = "sm"
105- variant = "destructive"
106- type = "button"
107- onClick = { ( ) => removeNote ( index ) }
108- >
109- < Trash2 className = "mr-2 h-4 w-4" /> Remove Note
110- </ Button >
111- </ div >
112- ) ,
113- ) ;
75+ < Button type = "button" size = "sm" onClick = { addNote } >
76+ < PlusCircle className = "mr-2 h-4 w-4" /> Add Note
77+ </ Button >
78+ </ >
79+ ) ;
80+ }
11481
115- NoteItem . displayName = 'NoteItem' ;
82+ const NoteItem = memo (
83+ ( {
84+ note,
85+ index,
86+ updateNote,
87+ removeNote,
88+ } : {
89+ note : Script [ "notes" ] [ number ] ;
90+ index : number ;
91+ updateNote : ( index : number , key : keyof Script [ "notes" ] [ number ] , value : string ) => void ;
92+ removeNote : ( index : number ) => void ;
93+ } ) => {
94+ const inputRef = useRef < HTMLInputElement | null > ( null ) ;
95+
96+ const handleTextChange = useCallback ( ( e : React . ChangeEvent < HTMLInputElement > ) => {
97+ updateNote ( index , "text" , e . target . value ) ;
98+ setTimeout ( ( ) => {
99+ inputRef . current ?. focus ( ) ;
100+ } , 0 ) ;
101+ } , [ index , updateNote ] ) ;
102+
103+ return (
104+ < div className = "space-y-2 border p-4 rounded" >
105+ < Input
106+ placeholder = "Note Text"
107+ value = { note . text }
108+ onChange = { handleTextChange }
109+ ref = { inputRef }
110+ />
111+ < Select
112+ value = { note . type }
113+ onValueChange = { ( value ) => updateNote ( index , "type" , value ) }
114+ >
115+ < SelectTrigger className = "flex-1" >
116+ < SelectValue placeholder = "Type" />
117+ </ SelectTrigger >
118+ < SelectContent >
119+ { Object . keys ( AlertColors ) . map ( ( type ) => (
120+ < SelectItem key = { type } value = { type } >
121+ < span className = "flex items-center gap-2" >
122+ { type . charAt ( 0 ) . toUpperCase ( ) + type . slice ( 1 ) } { " " }
123+ < div
124+ className = { cn (
125+ "size-4 rounded-full border" ,
126+ AlertColors [ type as keyof typeof AlertColors ] ,
127+ ) }
128+ />
129+ </ span >
130+ </ SelectItem >
131+ ) ) }
132+ </ SelectContent >
133+ </ Select >
134+ < Button
135+ size = "sm"
136+ variant = "destructive"
137+ type = "button"
138+ onClick = { ( ) => removeNote ( index ) }
139+ >
140+ < Trash2 className = "mr-2 h-4 w-4" /> Remove Note
141+ </ Button >
142+ </ div >
143+ ) ;
144+ }
145+ ) ;
146+
147+ NoteItem . displayName = 'NoteItem' ;
116148
117- return (
118- < >
119- < h3 className = "text-xl font-semibold" > Notes</ h3 >
120- { script . notes . map ( ( note , index ) => (
121- < NoteItem key = { index } note = { note } index = { index } />
122- ) ) }
123- < Button type = "button" size = "sm" onClick = { addNote } >
124- < PlusCircle className = "mr-2 h-4 w-4" /> Add Note
125- </ Button >
126- </ >
127- ) ;
128- }
129149
130- export default memo ( Note ) ;
150+ export default memo ( Note ) ;
0 commit comments