1- import { useEffect } from 'react' ;
2- import { BrowserRouter , Routes , Route , Outlet , Link , useLocation } from 'react-router-dom' ;
1+ import { useEffect , useMemo } from 'react' ;
2+ import { BrowserRouter , Routes , Route , Outlet , Link , useLocation , useParams } from 'react-router-dom' ;
33import { SidebarProvider , SidebarInset , SidebarTrigger } from '@object-ui/components' ;
44import { SchemaRendererProvider , SchemaRenderer , useRenderer } from '@object-ui/react' ;
55import { registerFields } from '@object-ui/fields' ;
66import { registerLayout } from '@object-ui/layout' ;
7- import '@object-ui/plugin-dashboard' ; // Auto-register dashboard
7+ import '@object-ui/plugin-dashboard' ;
88import { registerPlaceholders } from '@object-ui/components' ;
99import { SidebarNav } from './components/SidebarNav' ;
1010
11- // 1. Register components from packages (The "Controls Repository")
11+ // Data & Schemas
12+ import { mockData , getContact , getOpportunity } from './data' ;
13+ import { dashboardSchema } from './schemas/dashboard' ;
14+ import { contactListSchema , contactDetailSchema } from './schemas/contacts' ;
15+ import { opportunityListSchema } from './schemas/opportunities' ;
16+
17+ // 1. Register components
1218registerFields ( ) ;
1319registerLayout ( ) ;
14- registerPlaceholders ( ) ; // Register missing components as placeholders
15-
16- // 2. Define Mock Data (In a real app, this comes from an API)
17- const mockData = {
18- user : { name : "Demo User" , role : "admin" } ,
19- stats : { revenue : 125000 , leads : 45 , deals : 12 } ,
20- contacts : [
21- { id : 1 , name : "Alice Johnson" , email : "alice@example.com" , status : "Active" } ,
22- { id : 2 , name : "Bob Smith" , email : "bob@tech.com" , status : "Lead" } ,
23- { id : 3 , name : "Charlie Brown" , email : "charlie@peanuts.com" , status : "Customer" }
24- ]
25- } ;
26-
27- // 3. Define Page Schemas (The "JSON Rendering")
20+ registerPlaceholders ( ) ;
2821
29- // Dashboard Page
30- const dashboardSchema = {
31- type : "dashboard" , // Changed from 'page' to 'dashboard'
32- props : { title : "Executive Dashboard" } ,
33- widgets : [
34- {
35- id : "w1" ,
36- component : {
37- type : "card" ,
38- props : { title : "Total Revenue" } ,
39- children : [ { type : "text" , props : { value : "$125,000" , className : "text-2xl font-bold" } } ]
40- }
41- } ,
42- {
43- id : "w2" ,
44- component : {
45- type : "card" ,
46- props : { title : "Active Leads" } ,
47- children : [ { type : "text" , props : { value : "45" , className : "text-2xl font-bold" } } ]
48- }
49- } ,
50- {
51- id : "w3" ,
52- component : {
53- type : "card" ,
54- props : { title : "Open Deals" } ,
55- children : [ { type : "text" , props : { value : "12" , className : "text-2xl font-bold" } } ]
56- }
57- } ,
58- {
59- id : "w4" ,
60- layout : { w : 3 , h : 2 } ,
61- title : "Recent Activity (Kanban Placeholder)" ,
62- component : {
63- type : "view:kanban" ,
64- props : {
65- columns : [ "Todo" , "In Progress" , "Done" ] ,
66- data : [ { id : 1 , title : "Task 1" , status : "Todo" } ]
67- }
68- }
69- }
70- ]
71- } ;
72-
73- // Contacts List Page
74- const contactsSchema = {
75- type : "page" ,
76- props : { title : "Contacts" } ,
77- children : [
78- {
79- type : "page-header" ,
80- props : {
81- title : "All Contacts" ,
82- description : "Manage your customer relationships"
83- } ,
84- children : [
85- {
86- type : "action:button" ,
87- props : { label : "Add Contact" , variant : "default" } ,
88- events : { onClick : [ { action : "navigate" , params : { url : "/contacts/new" } } ] }
89- }
90- ]
91- } ,
92- {
93- type : "card" ,
94- className : "mt-6" ,
95- children : [
96- {
97- type : "view:grid" ,
98- bind : "contacts" ,
99- props : {
100- columns : [
101- { key : "name" , label : "Name" } ,
102- { key : "email" , label : "Email" } ,
103- { key : "status" , label : "Status" }
104- ]
105- }
106- }
107- ]
108- } ,
109- {
110- type : "view:map" ,
111- props : {
112- lat : 34.05 ,
113- lng : - 118.25 ,
114- zoom : 10
115- } ,
116- className : "mt-4 h-64"
117- }
118- ]
119- } ;
120-
121- // Layout Shell Component
22+ // Generic Layout Shell
12223const Layout = ( ) => {
12324 return (
12425 < SidebarProvider >
12526 < div className = "flex min-h-screen w-full bg-gray-50 dark:bg-gray-900" >
12627 < SidebarNav />
12728 < SidebarInset >
128- < div className = "p-4" >
129- < SidebarTrigger className = "md:hidden" />
29+ < div className = "p-4 border-b bg-background flex items-center md:hidden" >
30+ < SidebarTrigger />
31+ < span className = "ml-2 font-semibold" > CRM Demo</ span >
13032 </ div >
131- < main className = "flex-1 overflow-y-auto p-4 md:p-8" >
33+ < main className = "flex-1 overflow-y-auto w-full p-4 md:p-8" >
13234 < Outlet />
13335 </ main >
13436 </ SidebarInset >
@@ -137,6 +39,22 @@ const Layout = () => {
13739 ) ;
13840} ;
13941
42+ // Generic Detail Page Loader
43+ const ContactDetailPage = ( ) => {
44+ const { id } = useParams ( ) ;
45+ const contact = getContact ( id || "" ) ;
46+
47+ if ( ! contact ) return < div > Contact not found</ div > ;
48+
49+ // In a real app, SchemaRendererProvider would be at the App root,
50+ // but here we nest it to inject specific record data into the context
51+ return (
52+ < SchemaRendererProvider dataSource = { contact } debug = { true } >
53+ < SchemaRenderer schema = { contactDetailSchema } />
54+ </ SchemaRendererProvider >
55+ ) ;
56+ }
57+
14058function App ( ) {
14159 return (
14260 < SchemaRendererProvider
@@ -147,8 +65,15 @@ function App() {
14765 < Routes >
14866 < Route path = "/" element = { < Layout /> } >
14967 < Route index element = { < SchemaRenderer schema = { dashboardSchema } /> } />
150- < Route path = "contacts" element = { < SchemaRenderer schema = { contactsSchema } /> } />
151- < Route path = "opportunities" element = { < div className = "p-4" > Opportunities Module (Coming Soon)</ div > } />
68+
69+ < Route path = "contacts" >
70+ < Route index element = { < SchemaRenderer schema = { contactListSchema } /> } />
71+ < Route path = ":id" element = { < ContactDetailPage /> } />
72+ </ Route >
73+
74+ < Route path = "opportunities" element = { < SchemaRenderer schema = { opportunityListSchema } /> } />
75+
76+ < Route path = "products" element = { < div className = "p-4" > Products Module (Coming Soon)</ div > } />
15277 < Route path = "settings" element = { < div className = "p-4" > Settings Module (Coming Soon)</ div > } />
15378 </ Route >
15479 </ Routes >
@@ -158,3 +83,4 @@ function App() {
15883}
15984
16085export default App ;
86+
0 commit comments