88import PropTypes from 'prop-types' ;
99import { useCallback , useEffect , useState } from 'react' ;
1010import { fetchBugReport , fetchBugReports , updateBugReport } from '../lib/bug-report-api.js' ;
11+ import { buildClaudePrompts } from '../lib/bug-report-prompts.js' ;
1112
1213const STATUS_LABELS = {
1314 open : '未対応' ,
@@ -44,14 +45,15 @@ const hideBrokenImage = event => {
4445 event . currentTarget . style . display = 'none' ;
4546} ;
4647
47- const BugReportDetail = ( { reportId, onBack, onChanged} ) => {
48+ const BugReportDetail = ( { reportId, stage , onBack, onChanged} ) => {
4849 const [ detail , setDetail ] = useState ( null ) ;
4950 const [ error , setError ] = useState ( '' ) ;
5051 const [ nextStatus , setNextStatus ] = useState ( '' ) ;
5152 const [ reply , setReply ] = useState ( '' ) ;
5253 const [ confirming , setConfirming ] = useState ( false ) ;
5354 const [ busy , setBusy ] = useState ( false ) ;
5455 const [ savedAt , setSavedAt ] = useState ( null ) ;
56+ const [ copiedKey , setCopiedKey ] = useState ( null ) ;
5557
5658 useEffect ( ( ) => {
5759 fetchBugReport ( reportId )
@@ -93,6 +95,16 @@ const BugReportDetail = ({reportId, onBack, onChanged}) => {
9395 }
9496 } , [ detail , nextStatus , reply , reportId , onChanged ] ) ;
9597
98+ const handleCopyPrompt = useCallback ( async e => {
99+ const { key, prompt} = e . currentTarget . dataset ;
100+ try {
101+ await navigator . clipboard . writeText ( prompt ) ;
102+ setCopiedKey ( key ) ;
103+ } catch {
104+ setCopiedKey ( null ) ;
105+ }
106+ } , [ ] ) ;
107+
96108 if ( error && ! detail ) {
97109 return ( < p
98110 className = "admin-error"
@@ -220,17 +232,47 @@ const BugReportDetail = ({reportId, onBack, onChanged}) => {
220232 ) : null }
221233 </ div >
222234 </ div >
235+ < div
236+ className = "admin-respond"
237+ data-testid = "bug-admin-claude"
238+ >
239+ < h4 > { 'Claude に依頼(/bug-report スキル)' } </ h4 >
240+ < p className = "admin-meta" >
241+ { 'いまの状態に合わせたプロンプト案です。コピーして Claude Code に貼り付けてください。' }
242+ </ p >
243+ { buildClaudePrompts ( detail , stage ) . map ( suggestion => (
244+ < div
245+ className = "admin-prompt"
246+ key = { suggestion . key }
247+ >
248+ < div className = "admin-prompt-head" >
249+ < strong > { suggestion . title } </ strong >
250+ < button
251+ data-key = { suggestion . key }
252+ data-prompt = { suggestion . prompt }
253+ data-testid = { `bug-admin-copy-${ suggestion . key } ` }
254+ type = "button"
255+ onClick = { handleCopyPrompt }
256+ >
257+ { copiedKey === suggestion . key ? 'コピーしました ✓' : 'コピー' }
258+ </ button >
259+ </ div >
260+ < pre className = "admin-pre" > { suggestion . prompt } </ pre >
261+ </ div >
262+ ) ) }
263+ </ div >
223264 </ div >
224265 ) ;
225266} ;
226267
227268BugReportDetail . propTypes = {
228269 onBack : PropTypes . func . isRequired ,
229270 onChanged : PropTypes . func . isRequired ,
230- reportId : PropTypes . string . isRequired
271+ reportId : PropTypes . string . isRequired ,
272+ stage : PropTypes . string
231273} ;
232274
233- const BugReportsView = ( ) => {
275+ const BugReportsView = ( { stage } ) => {
234276 const [ status , setStatus ] = useState ( '' ) ;
235277 const [ reports , setReports ] = useState ( null ) ;
236278 const [ selectedId , setSelectedId ] = useState ( null ) ;
@@ -254,6 +296,7 @@ const BugReportsView = () => {
254296 return (
255297 < BugReportDetail
256298 reportId = { selectedId }
299+ stage = { stage }
257300 onBack = { handleBack }
258301 onChanged = { reload }
259302 />
@@ -323,4 +366,8 @@ const BugReportsView = () => {
323366 ) ;
324367} ;
325368
369+ BugReportsView . propTypes = {
370+ stage : PropTypes . string
371+ } ;
372+
326373export default BugReportsView ;
0 commit comments