11import { useEffect , useMemo , useRef , useState } from "react" ;
22import type { ReactNode } from "react" ;
3- import { Activity , Globe , MessageSquareCode , PanelRightClose } from "lucide-react" ;
3+ import {
4+ Activity ,
5+ Globe ,
6+ MessageSquareCode ,
7+ MoreVertical ,
8+ PanelRightClose ,
9+ } from "lucide-react" ;
410import { useIntl } from "react-intl" ;
5-
611import type { PromptRead } from "@/generated/types" ;
712import { Badge } from "@/components/ui/badge" ;
813import { Button } from "@/components/ui/button" ;
914import { InlineTagAdd } from "@/components/ui/inline-tag-add" ;
15+ import {
16+ DropdownMenu ,
17+ DropdownMenuContent ,
18+ DropdownMenuItem ,
19+ DropdownMenuTrigger ,
20+ } from "@/components/ui/dropdown-menu" ;
1021import { cn } from "@/lib/utils" ;
1122import { getTagDisplay } from "@/components/gateways/utils" ;
1223import { formatDateTime } from "@/utils/format" ;
@@ -34,6 +45,8 @@ export interface PromptDetailsPanelProps {
3445 * a non-interactive "add" affordance.
3546 */
3647 onAddTag ?: ( promptId : string , tags : string [ ] ) => Promise < void > ;
48+ onEdit ?: ( prompt : NonNullable < PromptRead > ) => void ;
49+ onDelete ?: ( prompt : NonNullable < PromptRead > ) => void ;
3750}
3851
3952/**
@@ -53,6 +66,8 @@ export function PromptDetailsPanel({
5366 open,
5467 onClose,
5568 onAddTag,
69+ onEdit,
70+ onDelete,
5671} : PromptDetailsPanelProps ) {
5772 const intl = useIntl ( ) ;
5873 const closeButtonRef = useRef < HTMLButtonElement > ( null ) ;
@@ -126,25 +141,48 @@ export function PromptDetailsPanel({
126141 Prompt details: { title }
127142 </ h2 >
128143
129- < div className = "flex items-start justify-between gap-4" >
130- < div className = "flex min-w-0 items-start gap-3" >
131- < span className = "mt-0.5 flex size-7 shrink-0 items-center justify-center rounded-sm bg-emerald-300 text-neutral-950" >
132- < MessageSquareCode className = "size-4" />
144+ < div className = "flex min-w-0 items-start gap-3" >
145+ < span className = "mt-0.5 flex size-7 shrink-0 items-center justify-center rounded-sm bg-emerald-300 text-neutral-950" >
146+ < MessageSquareCode className = "size-4" />
147+ </ span >
148+ < div className = "flex min-w-0 items-center gap-2" >
149+ < span aria-hidden = "true" className = "truncate text-xl font-semibold text-foreground" >
150+ { title }
133151 </ span >
134- < div className = "min-w-0" >
135- < div className = "flex min-w-0 items-center gap-2" >
136- < span
137- aria-hidden = "true"
138- className = "truncate text-xl font-semibold text-foreground"
139- >
140- { title }
141- </ span >
142- </ div >
143- </ div >
152+ { selected && ( onEdit ?? onDelete ) && (
153+ < DropdownMenu >
154+ < DropdownMenuTrigger asChild >
155+ < Button
156+ type = "button"
157+ variant = "ghost"
158+ size = "sm"
159+ className = "h-8 w-8 shrink-0 p-0"
160+ aria-label = { intl . formatMessage (
161+ { id : "prompts.details.moreOptionsFor" } ,
162+ { name : selected . name } ,
163+ ) }
164+ aria-haspopup = "menu"
165+ >
166+ < MoreVertical className = "h-4 w-4" aria-hidden = "true" />
167+ </ Button >
168+ </ DropdownMenuTrigger >
169+ < DropdownMenuContent align = "start" >
170+ { onEdit && (
171+ < DropdownMenuItem onSelect = { ( ) => onEdit ( selected ) } >
172+ { intl . formatMessage ( { id : "prompts.details.action.edit" } ) }
173+ </ DropdownMenuItem >
174+ ) }
175+ { onDelete && (
176+ < DropdownMenuItem onSelect = { ( ) => onDelete ( selected ) } >
177+ { intl . formatMessage ( { id : "prompts.details.action.delete" } ) }
178+ </ DropdownMenuItem >
179+ ) }
180+ </ DropdownMenuContent >
181+ </ DropdownMenu >
182+ ) }
144183 </ div >
145184 </ div >
146185
147- { /* TODO(#5563): full local-prompt drawer variant (Try it / Definition tabs). */ }
148186 { selected && (
149187 < p className = "mt-7 max-w-4xl text-[15px] leading-6 text-muted-foreground" >
150188 { selected . gatewayId || selected . gatewaySlug
@@ -223,26 +261,35 @@ export function PromptDetailsPanel({
223261 { selected && (
224262 < >
225263 < div className = "border-b border-border p-4 pt-8" >
226- < h3 className = "mb-7 text-sm font-semibold text-foreground" > Prompt details</ h3 >
264+ < h3 className = "mb-7 text-sm font-semibold text-foreground" >
265+ { intl . formatMessage ( { id : "prompts.details.promptDetails" } ) }
266+ </ h3 >
227267
228268 < dl className = "space-y-4" >
229- < DetailRow label = "Status" >
269+ < DetailRow label = { intl . formatMessage ( { id : "prompts.details.label.status" } ) } >
230270 < span className = "flex items-center gap-2" >
231271 < Activity
232272 className = { `size-3.5 ${
233273 selected . enabled ? "text-emerald-400" : "text-gray-400"
234274 } `}
235275 />
236- { selected . enabled ? "Active" : "Inactive" }
276+ { selected . enabled
277+ ? intl . formatMessage ( { id : "prompts.details.status.active" } )
278+ : intl . formatMessage ( { id : "prompts.details.status.inactive" } ) }
237279 </ span >
238280 </ DetailRow >
239- < DetailRow label = "Visibility" >
281+ < DetailRow
282+ label = { intl . formatMessage ( { id : "prompts.details.label.visibility" } ) }
283+ >
240284 < span className = "flex items-center gap-2" >
241285 < Globe className = "size-3.5 text-muted-foreground" />
242- { selected . visibility
243- ? selected . visibility . charAt ( 0 ) . toUpperCase ( ) +
244- selected . visibility . slice ( 1 )
245- : "Not available" }
286+ { selected . visibility === "team"
287+ ? intl . formatMessage ( { id : "prompts.details.visibility.team" } )
288+ : selected . visibility === "public"
289+ ? intl . formatMessage ( { id : "prompts.details.visibility.public" } )
290+ : selected . visibility === "private"
291+ ? intl . formatMessage ( { id : "prompts.details.visibility.private" } )
292+ : intl . formatMessage ( { id : "prompts.details.notAvailable" } ) }
246293 </ span >
247294 </ DetailRow >
248295 { ( ( ) => {
@@ -278,10 +325,16 @@ export function PromptDetailsPanel({
278325 </ div >
279326
280327 < div className = "p-4" >
281- < h3 className = "mb-7 text-sm font-semibold text-foreground" > Activity</ h3 >
328+ < h3 className = "mb-7 text-sm font-semibold text-foreground" >
329+ { intl . formatMessage ( { id : "prompts.details.activity" } ) }
330+ </ h3 >
282331 < dl className = "space-y-4" >
283- < DetailRow label = "Created" > { formatDateTime ( selected . createdAt ) } </ DetailRow >
284- < DetailRow label = "Last modified" >
332+ < DetailRow label = { intl . formatMessage ( { id : "prompts.details.label.created" } ) } >
333+ { formatDateTime ( selected . createdAt ) }
334+ </ DetailRow >
335+ < DetailRow
336+ label = { intl . formatMessage ( { id : "prompts.details.label.lastModified" } ) }
337+ >
285338 { formatDateTime ( selected . updatedAt ) }
286339 </ DetailRow >
287340 </ dl >
0 commit comments