11import { useState } from 'react' ;
22import { useParams } from 'react-router-dom' ;
3- import { ReportViewer } from '@object-ui/plugin-report' ;
3+ import { ReportViewer , ReportBuilder } from '@object-ui/plugin-report' ;
44import { Empty , EmptyTitle , EmptyDescription , Button } from '@object-ui/components' ;
5- import { Code2 } from 'lucide-react' ;
5+ import { Code2 , PenLine , ChevronLeft } from 'lucide-react' ;
66import appConfig from '../../objectstack.shared' ;
77
8+ // Mock fields for the builder since we don't have a dynamic schema provider here yet
9+ const MOCK_FIELDS = [
10+ { name : 'month' , label : 'Month' , type : 'string' } ,
11+ { name : 'revenue' , label : 'Revenue' , type : 'number' } ,
12+ { name : 'count' , label : 'Count' , type : 'number' } ,
13+ { name : 'region' , label : 'Region' , type : 'string' } ,
14+ { name : 'product' , label : 'Product' , type : 'string' } ,
15+ { name : 'source' , label : 'Lead Source' , type : 'string' } ,
16+ { name : 'stage' , label : 'Stage' , type : 'string' } ,
17+ { name : 'amount' , label : 'Amount' , type : 'currency' } ,
18+ ] ;
19+
820export function ReportView ( ) {
921 const { reportName } = useParams < { reportName : string } > ( ) ;
1022 const [ showDebug , setShowDebug ] = useState ( false ) ;
23+ const [ isEditing , setIsEditing ] = useState ( false ) ;
1124
1225 // Find report definition in config
1326 // Note: we need to cast appConfig because reports might not be in the strict type yet
14- const report = ( appConfig as any ) . reports ?. find ( ( r : any ) => r . name === reportName ) ;
27+ const initialReport = ( appConfig as any ) . reports ?. find ( ( r : any ) => r . name === reportName ) ;
28+ const [ reportData , setReportData ] = useState ( initialReport ) ;
1529
16- if ( ! report ) {
30+ if ( ! initialReport ) {
1731 return (
1832 < div className = "h-full flex items-center justify-center p-8" >
1933 < Empty >
@@ -24,12 +38,43 @@ export function ReportView() {
2438 ) ;
2539 }
2640
41+ const handleSave = ( newReport : any ) => {
42+ console . log ( 'Saving report:' , newReport ) ;
43+ setReportData ( newReport ) ;
44+ setIsEditing ( false ) ;
45+ } ;
46+
47+ if ( isEditing ) {
48+ return (
49+ < div className = "flex flex-col h-full overflow-hidden bg-background" >
50+ < div className = "flex items-center p-4 border-b bg-muted/10 gap-2" >
51+ < Button variant = "ghost" size = "sm" onClick = { ( ) => setIsEditing ( false ) } >
52+ < ChevronLeft className = "h-4 w-4 mr-1" />
53+ Back to View
54+ </ Button >
55+ < div className = "font-medium" > Edit Report: { reportData . title } </ div >
56+ </ div >
57+ < div className = "flex-1 overflow-auto" >
58+ < ReportBuilder
59+ schema = { {
60+ title : 'Report Builder' ,
61+ report : reportData ,
62+ availableFields : MOCK_FIELDS ,
63+ onSave : handleSave ,
64+ onCancel : ( ) => setIsEditing ( false )
65+ } }
66+ />
67+ </ div >
68+ </ div >
69+ ) ;
70+ }
71+
2772 // Wrap the report definition in the ReportViewer schema
2873 // The ReportViewer expects a schema property which is of type ReportViewerSchema
2974 // That schema has a 'report' property which is the actual report definition (ReportSchema)
3075 const viewerSchema = {
3176 type : 'report-viewer' ,
32- report : report , // The report definition
77+ report : reportData , // The report definition
3378 showToolbar : true ,
3479 allowExport : true
3580 } ;
@@ -39,17 +84,23 @@ export function ReportView() {
3984 < div className = "flex justify-between items-center p-6 border-b shrink-0 bg-muted/10" >
4085 < div >
4186 { /* Header is handled by ReportViewer usually, but we can have a page header too */ }
42- < h1 className = "text-lg font-medium text-muted-foreground" > Report Viewer</ h1 >
87+ < h1 className = "text-lg font-medium text-muted-foreground" > { reportData . title || 'Report Viewer' } </ h1 >
88+ </ div >
89+ < div className = "flex items-center gap-2" >
90+ < Button variant = "outline" size = "sm" onClick = { ( ) => setIsEditing ( true ) } >
91+ < PenLine className = "h-4 w-4 mr-2" />
92+ Edit Report
93+ </ Button >
94+ < Button
95+ variant = { showDebug ? "secondary" : "ghost" }
96+ size = "sm"
97+ onClick = { ( ) => setShowDebug ( ! showDebug ) }
98+ className = "gap-2"
99+ >
100+ < Code2 className = "h-4 w-4" />
101+ { showDebug ? 'Hide JSON' : 'Show JSON' }
102+ </ Button >
43103 </ div >
44- < Button
45- variant = { showDebug ? "secondary" : "ghost" }
46- size = "sm"
47- onClick = { ( ) => setShowDebug ( ! showDebug ) }
48- className = "gap-2"
49- >
50- < Code2 className = "h-4 w-4" />
51- Metadata
52- </ Button >
53104 </ div >
54105
55106 < div className = "flex-1 overflow-hidden flex flex-row relative" >
@@ -70,7 +121,7 @@ export function ReportView() {
70121 < h4 className = "text-xs font-bold uppercase text-muted-foreground mb-2" > Report Configuration</ h4 >
71122 < div className = "relative rounded-md border bg-slate-950 text-slate-50 overflow-hidden" >
72123 < pre className = "text-xs p-3 overflow-auto max-h-[800px]" >
73- { JSON . stringify ( report , null , 2 ) }
124+ { JSON . stringify ( reportData , null , 2 ) }
74125 </ pre >
75126 </ div >
76127 </ div >
0 commit comments