Skip to content

Commit b1cbb63

Browse files
authored
Merge pull request #223 from objectstack-ai/copilot/implement-objectui-component
2 parents 72ee527 + 0cd9178 commit b1cbb63

File tree

22 files changed

+1463
-11
lines changed

22 files changed

+1463
-11
lines changed

examples/crm-app/src/App.tsx

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ import { registerPlaceholders } from '@object-ui/components';
88
import { SidebarNav } from './components/SidebarNav';
99

1010
// Data & Schemas
11-
import { mockData, getContact } from './data';
11+
import { mockData, getContact, getOpportunity } from './data';
1212
import { dashboardSchema } from './schemas/dashboard';
1313
import { contactListSchema, contactDetailSchema } from './schemas/contacts';
1414
import { opportunityListSchema } from './schemas/opportunities';
15+
import { opportunityDetailSchema } from './schemas/opportunity-detail';
1516

1617
// 1. Register components
1718
registerFields();
@@ -54,6 +55,19 @@ const ContactDetailPage = () => {
5455
);
5556
}
5657

58+
const OpportunityDetailPage = () => {
59+
const { id } = useParams();
60+
const opportunity = getOpportunity(id || "");
61+
62+
if (!opportunity) return <div>Opportunity not found</div>;
63+
64+
return (
65+
<SchemaRendererProvider dataSource={opportunity} debug={true}>
66+
<SchemaRenderer schema={opportunityDetailSchema} />
67+
</SchemaRendererProvider>
68+
);
69+
}
70+
5771
function App() {
5872
return (
5973
<SchemaRendererProvider
@@ -70,7 +84,10 @@ function App() {
7084
<Route path=":id" element={<ContactDetailPage />} />
7185
</Route>
7286

73-
<Route path="opportunities" element={<SchemaRenderer schema={opportunityListSchema} />} />
87+
<Route path="opportunities">
88+
<Route index element={<SchemaRenderer schema={opportunityListSchema} />} />
89+
<Route path=":id" element={<OpportunityDetailPage />} />
90+
</Route>
7491

7592
<Route path="products" element={<div className="p-4">Products Module (Coming Soon)</div>} />
7693
<Route path="settings" element={<div className="p-4">Settings Module (Coming Soon)</div>} />

examples/crm-app/src/data.ts

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,36 @@ export const mockData = {
88
{ id: "3", name: "Charlie Brown", email: "charlie@peanuts.com", phone: "555-0103", title: "Manager", company: "Good Grief LLC", status: "Customer" }
99
],
1010
opportunities: [
11-
{ id: "101", name: "TechCorp Enterprise License", amount: 50000, stage: "Proposal", closeDate: "2024-06-30", accountId: "1" },
12-
{ id: "102", name: "Software Inc Pilot", amount: 5000, stage: "Closed Won", closeDate: "2024-01-15", accountId: "2" },
13-
{ id: "103", name: "Good Grief Consultant", amount: 12000, stage: "Negotiation", closeDate: "2024-05-20", accountId: "3" }
11+
{
12+
id: "101",
13+
name: "TechCorp Enterprise License",
14+
amount: 50000,
15+
stage: "Proposal",
16+
closeDate: "2024-06-30",
17+
accountId: "1",
18+
contactIds: ["c1", "c2"],
19+
description: "Enterprise software license for 500 users. Includes premium support and training."
20+
},
21+
{
22+
id: "102",
23+
name: "Software Inc Pilot",
24+
amount: 5000,
25+
stage: "Closed Won",
26+
closeDate: "2024-01-15",
27+
accountId: "2",
28+
contactIds: ["c2"],
29+
description: "Pilot program for 50 users."
30+
},
31+
{
32+
id: "103",
33+
name: "Good Grief Consultant",
34+
amount: 12000,
35+
stage: "Negotiation",
36+
closeDate: "2024-05-20",
37+
accountId: "3",
38+
contactIds: ["c3"],
39+
description: "Consulting services for Q2 implementation."
40+
}
1441
]
1542
};
1643

examples/crm-app/src/schemas/opportunities.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ export const opportunityListSchema: PageSchema = {
2626
card: {
2727
title: "name",
2828
subtitle: "amount",
29-
footer: "closeDate"
29+
footer: "closeDate",
30+
onClick: { action: "navigate", params: { url: "/opportunities/${id}" } }
3031
}
3132
}
3233
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import { PageSchema } from "@object-ui/types";
2+
3+
/**
4+
* Opportunity Detail Schema
5+
* Demonstrates the new field widgets: CurrencyField, LookupField, and action execution
6+
*/
7+
export const opportunityDetailSchema: PageSchema = {
8+
type: "page",
9+
props: { title: "Opportunity Details" },
10+
children: [
11+
{
12+
type: "page:header",
13+
props: {
14+
title: "${data.name}",
15+
description: "Deal Amount: ${data.amount}"
16+
},
17+
children: [
18+
{
19+
type: "action:button",
20+
props: { label: "Edit", variant: "outline" }
21+
},
22+
{
23+
type: "action:button",
24+
props: {
25+
label: "Mark as Won",
26+
variant: "default",
27+
confirmText: "Are you sure you want to mark this as won?",
28+
successMessage: "Opportunity marked as won!",
29+
api: "/api/opportunities/${data.id}/win",
30+
reload: true
31+
}
32+
}
33+
]
34+
},
35+
{
36+
type: "page:card",
37+
className: "mt-6",
38+
props: { title: "Deal Information" },
39+
children: [
40+
{
41+
type: "view:simple",
42+
props: { columns: 2 },
43+
children: [
44+
{
45+
type: "field:text",
46+
bind: "name",
47+
props: { label: "Opportunity Name" }
48+
},
49+
{
50+
type: "field:select",
51+
bind: "stage",
52+
props: {
53+
label: "Stage",
54+
options: [
55+
{ value: "Prospecting", label: "Prospecting" },
56+
{ value: "Proposal", label: "Proposal" },
57+
{ value: "Negotiation", label: "Negotiation" },
58+
{ value: "Closed Won", label: "Closed Won" },
59+
{ value: "Closed Lost", label: "Closed Lost" }
60+
]
61+
}
62+
},
63+
{
64+
type: "field:currency",
65+
bind: "amount",
66+
props: {
67+
label: "Amount",
68+
currency: "USD",
69+
precision: 2
70+
}
71+
},
72+
{
73+
type: "field:date",
74+
bind: "closeDate",
75+
props: { label: "Close Date" }
76+
},
77+
{
78+
type: "field:lookup",
79+
bind: "accountId",
80+
props: {
81+
label: "Account",
82+
options: [
83+
{ value: "1", label: "Acme Corp" },
84+
{ value: "2", label: "TechStart Inc" },
85+
{ value: "3", label: "Global Solutions" }
86+
],
87+
display_field: "label"
88+
}
89+
},
90+
{
91+
type: "field:lookup",
92+
bind: "contactIds",
93+
props: {
94+
label: "Contacts",
95+
multiple: true,
96+
options: [
97+
{ value: "c1", label: "John Doe" },
98+
{ value: "c2", label: "Jane Smith" },
99+
{ value: "c3", label: "Bob Johnson" }
100+
]
101+
}
102+
}
103+
]
104+
}
105+
]
106+
},
107+
{
108+
type: "page:card",
109+
className: "mt-6",
110+
props: { title: "Description" },
111+
children: [
112+
{
113+
type: "field:textarea",
114+
bind: "description",
115+
props: {
116+
label: "Notes",
117+
rows: 6,
118+
placeholder: "Enter opportunity notes..."
119+
}
120+
}
121+
]
122+
}
123+
]
124+
};

0 commit comments

Comments
 (0)