Skip to content

Commit 1daacbf

Browse files
committed
feat: implement new components for metadata exploration and object data management, enhancing the app's functionality
1 parent 864c106 commit 1daacbf

7 files changed

Lines changed: 813 additions & 98 deletions

File tree

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/**
2+
* App Component
3+
*
4+
* Main application component that demonstrates complete CRUD operations
5+
* using ObjectStack Client with MSW for API mocking.
6+
*/
7+
8+
import { useState, useEffect } from 'react';
9+
import { ObjectStackClient } from '@objectstack/client';
10+
import type { Task } from './types';
11+
import { TaskForm } from './components/TaskForm';
12+
import { TaskList } from './components/TaskList';
13+
import { MetadataDemo } from './components/MetadataDemo';
14+
import './App.css';
15+
16+
export function App() {
17+
const [client, setClient] = useState<ObjectStackClient | null>(null);
18+
const [editingTask, setEditingTask] = useState<Task | null>(null);
19+
const [refreshTrigger, setRefreshTrigger] = useState(0);
20+
const [connected, setConnected] = useState(false);
21+
const [error, setError] = useState<string | null>(null);
22+
23+
useEffect(() => {
24+
initializeClient();
25+
}, []);
26+
27+
async function initializeClient() {
28+
try {
29+
// Initialize ObjectStack Client pointing to our mocked API
30+
// Note: We use an empty baseUrl because the Discovery Endpoint is at /api/v1
31+
// and the server routes (returned by connect) already include the /api/v1 prefix.
32+
const stackClient = new ObjectStackClient({
33+
baseUrl: ''
34+
});
35+
36+
// Connect to the server (will be intercepted by MSW)
37+
// Wait a bit to ensure MSW is fully ready and to simulate network delay
38+
await new Promise(resolve => setTimeout(resolve, 500));
39+
await stackClient.connect();
40+
41+
setClient(stackClient);
42+
setConnected(true);
43+
console.log('✅ ObjectStack Client connected (via MSW)');
44+
} catch (err) {
45+
setError(err instanceof Error ? err.message : 'Failed to initialize client');
46+
console.error('Failed to initialize client:', err);
47+
}
48+
}
49+
50+
function handleFormSuccess() {
51+
setEditingTask(null);
52+
// Trigger refresh of task list
53+
setRefreshTrigger(prev => prev + 1);
54+
}
55+
56+
function handleEditTask(task: Task) {
57+
setEditingTask(task);
58+
// Check if on mobile to scroll
59+
if (window.innerWidth < 1024) {
60+
window.scrollTo({ top: 0, behavior: 'smooth' });
61+
}
62+
}
63+
64+
function handleCancelEdit() {
65+
setEditingTask(null);
66+
}
67+
68+
if (error) {
69+
return (
70+
<div className="min-h-screen flex items-center justify-center p-6">
71+
<div className="max-w-md w-full p-8 border border-error-light bg-background rounded-lg shadow-sm text-center">
72+
<h1 className="text-xl font-bold text-error mb-2">Connection Error</h1>
73+
<p className="text-accents-5 mb-6">{error}</p>
74+
<button
75+
onClick={initializeClient}
76+
className="px-4 py-2 bg-foreground text-background rounded-md hover:bg-accents-7 transition-colors"
77+
>
78+
Retry
79+
</button>
80+
</div>
81+
</div>
82+
);
83+
}
84+
85+
if (!connected || !client) {
86+
return (
87+
<div className="min-h-screen flex flex-col items-center justify-center p-6 space-y-4">
88+
<div className="w-8 h-8 rounded-full border-4 border-accents-2 border-t-foreground animate-spin"></div>
89+
<div className="text-center">
90+
<h1 className="text-lg font-semibold mb-1">Connecting to ObjectStack...</h1>
91+
<p className="text-accents-5 text-sm">Initializing MSW and ObjectStack Client...</p>
92+
</div>
93+
</div>
94+
);
95+
}
96+
97+
return (
98+
<div className="max-w-6xl mx-auto px-6 py-12 min-h-screen font-sans">
99+
<header className="text-center mb-16">
100+
<h1 className="text-4xl font-extrabold tracking-tight mb-4 text-foreground">
101+
ObjectStack Action
102+
</h1>
103+
<p className="text-accents-5 text-lg mb-6">
104+
Complete CRUD operations using <code className="text-sm bg-accents-1 px-1.5 py-0.5 rounded font-mono text-accents-6">@objectstack/client</code> with Mock Service Worker
105+
</p>
106+
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-success-lighter border border-success-lighter text-success-dark text-sm font-medium">
107+
<span className="relative flex h-2 w-2">
108+
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-success opacity-75"></span>
109+
<span className="relative inline-flex rounded-full h-2 w-2 bg-success"></span>
110+
</span>
111+
MSW Active - All API calls are mocked
112+
</div>
113+
</header>
114+
115+
<main className="grid grid-cols-1 lg:grid-cols-12 gap-12 text-sm">
116+
<section className="lg:col-span-4 lg:sticky lg:top-6 lg:self-start">
117+
<TaskForm
118+
client={client}
119+
editingTask={editingTask}
120+
onSuccess={handleFormSuccess}
121+
onCancel={handleCancelEdit}
122+
/>
123+
</section>
124+
125+
<section className="lg:col-span-8">
126+
<TaskList
127+
client={client}
128+
onEdit={handleEditTask}
129+
refreshTrigger={refreshTrigger}
130+
/>
131+
</section>
132+
</main>
133+
134+
<div className="mt-8">
135+
<MetadataDemo />
136+
</div>
137+
138+
<footer className="mt-16 pt-8 border-t border-accents-2 text-center text-sm text-accents-4 space-y-2">
139+
<p>
140+
This example demonstrates MSW integration with React components.
141+
All API calls are intercepted and mocked in the browser.
142+
</p>
143+
<p className="font-mono text-xs text-accents-3">
144+
React + TypeScript + Vite + MSW + @objectstack/client
145+
</p>
146+
</footer>
147+
</div>
148+
);
149+
}

0 commit comments

Comments
 (0)