@@ -17,6 +17,77 @@ type PromptTabProps = {
1717 onNewTemplate : ( ) => void
1818}
1919
20+ type PromptTemplateCardProps = {
21+ template : PromptTemplate
22+ selected ?: boolean
23+ onApply ?: ( template : PromptTemplate ) => void
24+ onEdit : ( template : PromptTemplate ) => void
25+ onDelete : ( templateId : number ) => void
26+ }
27+
28+ export function PromptTemplateCard ( { template, selected = false , onApply, onEdit, onDelete } : PromptTemplateCardProps ) {
29+ const cardClassName = `w-full rounded-xl border-2 p-4 text-left transition-all ${
30+ selected
31+ ? 'border-primary bg-primary/10 ring-2 ring-primary/30'
32+ : 'border-border bg-card hover:bg-accent/40'
33+ } `
34+
35+ const content = (
36+ < >
37+ < div className = "flex flex-wrap items-center gap-2" >
38+ < Badge className = "border-transparent bg-orange-500 text-[10px] uppercase tracking-wide text-white" >
39+ { template . category }
40+ </ Badge >
41+ < Badge className = "border-transparent bg-slate-600 text-[10px] uppercase tracking-wide text-white" >
42+ { template . cadenceHint }
43+ </ Badge >
44+ </ div >
45+ < div className = "mt-3" >
46+ < p className = "text-sm font-semibold" > { template . title } </ p >
47+ < p className = "mt-1 text-xs text-muted-foreground" > { template . description } </ p >
48+ </ div >
49+ < p className = "mt-3 line-clamp-3 text-xs text-muted-foreground" > { template . suggestedDescription } </ p >
50+ { selected && (
51+ < div className = "absolute right-2 top-2 flex h-5 w-5 items-center justify-center rounded-full bg-primary" >
52+ < Check className = "h-3 w-3 text-primary-foreground" />
53+ </ div >
54+ ) }
55+ </ >
56+ )
57+
58+ return (
59+ < div className = "group relative" >
60+ { onApply ? (
61+ < button type = "button" onClick = { ( ) => onApply ( template ) } className = { cardClassName } >
62+ { content }
63+ </ button >
64+ ) : (
65+ < div className = { cardClassName } > { content } </ div >
66+ ) }
67+ < div className = { `absolute top-2 flex gap-1 transition-opacity ${ selected || onApply ? 'right-10' : 'right-2' } ${ selected ? 'opacity-100' : 'opacity-0 group-hover:opacity-100' } ` } >
68+ < Button
69+ type = "button"
70+ variant = "ghost"
71+ size = "icon"
72+ className = "h-6 w-6"
73+ onClick = { ( e ) => { e . stopPropagation ( ) ; onEdit ( template ) } }
74+ >
75+ < Pencil className = "h-3 w-3" />
76+ </ Button >
77+ < Button
78+ type = "button"
79+ variant = "ghost"
80+ size = "icon"
81+ className = "h-6 w-6 text-destructive hover:text-destructive"
82+ onClick = { ( e ) => { e . stopPropagation ( ) ; onDelete ( template . id ) } }
83+ >
84+ < Trash2 className = "h-3 w-3" />
85+ </ Button >
86+ </ div >
87+ </ div >
88+ )
89+ }
90+
2091export function PromptTab ( {
2192 prompt,
2293 onPromptChange,
@@ -50,56 +121,14 @@ export function PromptTab({
50121 const isSelected = selectedPromptTemplateId === template . id
51122
52123 return (
53- < div key = { template . id } className = "relative group" >
54- < button
55- type = "button"
56- onClick = { ( ) => onApplyTemplate ( template ) }
57- className = { `w-full rounded-xl border-2 p-4 text-left transition-all ${
58- isSelected
59- ? 'border-primary bg-primary/10 ring-2 ring-primary/30'
60- : 'border-border bg-card hover:bg-accent/40'
61- } `}
62- >
63- < div className = "flex flex-wrap items-center gap-2" >
64- < Badge className = "text-[10px] uppercase tracking-wide border-transparent bg-orange-500 text-white" >
65- { template . category }
66- </ Badge >
67- < Badge className = "text-[10px] uppercase tracking-wide border-transparent bg-slate-600 text-white" >
68- { template . cadenceHint }
69- </ Badge >
70- </ div >
71- < div className = "mt-3" >
72- < p className = "text-sm font-semibold" > { template . title } </ p >
73- < p className = "mt-1 text-xs text-muted-foreground" > { template . description } </ p >
74- </ div >
75- < p className = "mt-3 text-xs text-muted-foreground line-clamp-3" > { template . suggestedDescription } </ p >
76- { isSelected && (
77- < div className = "absolute top-2 right-2 h-5 w-5 rounded-full bg-primary flex items-center justify-center" >
78- < Check className = "h-3 w-3 text-primary-foreground" />
79- </ div >
80- ) }
81- </ button >
82- < div className = { `absolute top-2 right-10 flex gap-1 transition-opacity ${ isSelected ? 'opacity-100' : 'opacity-0 group-hover:opacity-100' } ` } >
83- < Button
84- type = "button"
85- variant = "ghost"
86- size = "icon"
87- className = "h-6 w-6"
88- onClick = { ( e ) => { e . stopPropagation ( ) ; onEditTemplate ( template ) } }
89- >
90- < Pencil className = "h-3 w-3" />
91- </ Button >
92- < Button
93- type = "button"
94- variant = "ghost"
95- size = "icon"
96- className = "h-6 w-6 text-destructive hover:text-destructive"
97- onClick = { ( e ) => { e . stopPropagation ( ) ; onDeleteTemplate ( template . id ) } }
98- >
99- < Trash2 className = "h-3 w-3" />
100- </ Button >
101- </ div >
102- </ div >
124+ < PromptTemplateCard
125+ key = { template . id }
126+ template = { template }
127+ selected = { isSelected }
128+ onApply = { onApplyTemplate }
129+ onEdit = { onEditTemplate }
130+ onDelete = { onDeleteTemplate }
131+ />
103132 )
104133 } ) }
105134 </ div >
0 commit comments