11import { useState , useEffect } from 'react' ;
22import { ObjectStackClient } from '@objectstack/client' ;
3+ import { Card , CardContent , CardHeader , CardTitle , CardFooter } from "@/components/ui/card" ;
4+ import { Button } from "@/components/ui/button" ;
5+ import { ArrowLeft , ArrowRight , Edit , Trash2 , Plus } from 'lucide-react' ;
36
47interface ObjectDataTableProps {
58 client : ObjectStackClient ;
@@ -42,7 +45,7 @@ export function ObjectDataTable({ client, objectApiName, onEdit }: ObjectDataTab
4245 if ( ! client ) return ;
4346 setLoading ( true ) ;
4447 try {
45- const result = await client . data . find ( objectApiName , {
48+ const result : any = await client . data . find ( objectApiName , {
4649 filters : {
4750 top : pageSize ,
4851 skip : ( page - 1 ) * pageSize ,
@@ -95,18 +98,9 @@ export function ObjectDataTable({ client, objectApiName, onEdit }: ObjectDataTab
9598 }
9699 }
97100
98- // Helper to allow debugging and simple formatting
99- function formatRecords ( recs : any [ ] , cols : any [ ] ) {
100- if ( ! recs || recs . length === 0 ) return [ ] ;
101- // Optional: Ensure fields that match columns exist or default to ''
102- return recs ;
103- }
104-
105- if ( ! def ) return < div className = "p-4 text-accents-5" > Loading metadata for { objectApiName } ...</ div > ;
101+ if ( ! def ) return < div className = "p-4 text-muted-foreground animate-pulse" > Loading metadata for { objectApiName } ...</ div > ;
106102
107103 // Determine columns from fields
108- // fields is usually a map or array depending on the internal structure.
109- // Based on previous logs: objects: [{ fields: { ... } }]
110104 const fields = def . fields || { } ;
111105 const columns = Object . keys ( fields ) . map ( key => {
112106 const f = fields [ key ] ;
@@ -115,78 +109,107 @@ export function ObjectDataTable({ client, objectApiName, onEdit }: ObjectDataTab
115109 label : f . label || key ,
116110 type : f . type || 'text'
117111 } ;
118- } ) . filter ( c => ! [ 'formatted_summary' ] . includes ( c . name ) ) ; // hide system fields if any
112+ } ) . filter ( c => ! [ 'formatted_summary' ] . includes ( c . name ) ) ;
119113
120114 return (
121- < div className = "bg-background rounded-lg border border-accents-2 overflow-hidden shadow-sm" >
122- < div className = "p-4 border-b border-accents-2 flex justify-between items-center bg-gray-50" >
123- < h3 className = "font-bold text-lg" > { def . label } ({ def . name } )</ h3 >
124- < span className = "text-sm text-accents-5" >
125- Records: { total > 0 ? total : records . length }
126- </ span >
127- </ div >
115+ < Card className = "flex flex-col h-full border-border/60 shadow-sm" >
116+ < CardHeader className = "flex flex-row items-center justify-between p-4 border-b space-y-0 bg-muted/20" >
117+ < div className = "space-y-1" >
118+ < CardTitle className = "text-xl font-semibold tracking-tight" >
119+ { def . label }
120+ </ CardTitle >
121+ < p className = "text-sm text-muted-foreground" >
122+ { def . name } • { total > 0 ? total : records . length } records
123+ </ p >
124+ </ div >
125+ < Button onClick = { ( ) => onEdit ( { } ) } size = "sm" className = "gap-1" >
126+ < Plus className = "h-4 w-4" />
127+ New
128+ </ Button >
129+ </ CardHeader >
128130
129- < div className = "overflow-x -auto" >
130- < table className = "w-full text-sm text-left" >
131- < thead className = "bg-gray-100 text-accents-6 uppercase font-medium " >
132- < tr >
131+ < CardContent className = "flex-1 p-0 overflow -auto" >
132+ < table className = "w-full caption-bottom text-sm text-left" >
133+ < thead className = "[&_tr]:border-b " >
134+ < tr className = "border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted" >
133135 { columns . map ( col => (
134- < th key = { col . name } className = "px-4 py-3 whitespace-nowrap" > { col . label } </ th >
136+ < th key = { col . name } className = "h-10 px-4 align-middle font-medium text-muted-foreground" >
137+ { col . label }
138+ </ th >
135139 ) ) }
136- < th className = "px-4 py-3 text-right" > Actions</ th >
140+ < th className = "h-10 px-4 align-middle font-medium text-muted-foreground text-right" > Actions</ th >
137141 </ tr >
138142 </ thead >
139- < tbody className = "divide-y divide-accents-2 " >
143+ < tbody className = "[&_tr:last-child]:border-0 " >
140144 { loading && records . length === 0 ? (
141- < tr > < td colSpan = { columns . length + 1 } className = "p-4 text-center" > Loading...</ td > </ tr >
142- ) : formatRecords ( records , columns ) . map ( record => (
143- < tr key = { record . id || record . _id } className = "hover:bg-gray- 50 transition-colors " >
145+ < tr > < td colSpan = { columns . length + 1 } className = "p-4 text-center text-muted-foreground " > Loading...</ td > </ tr >
146+ ) : records . map ( record => (
147+ < tr key = { record . id || record . _id } className = "border-b transition-colors hover:bg-muted/ 50 data-[state=selected]:bg-muted " >
144148 { columns . map ( col => (
145- < td key = { col . name } className = "px -4 py-3 whitespace-nowrap " >
149+ < td key = { col . name } className = "p -4 align-middle " >
146150 { String ( record [ col . name ] !== undefined ? record [ col . name ] : '' ) }
147151 </ td >
148152 ) ) }
149- < td className = "px-4 py-3 text-right space-x-2" >
150- < button
151- onClick = { ( ) => onEdit ( record ) }
152- className = "text-primary hover:text-primary-dark font-medium"
153- >
154- Edit
155- </ button >
156- < button
157- onClick = { ( ) => handleDelete ( record . id || record . _id ) }
158- className = "text-error hover:text-red-700 font-medium"
159- >
160- Delete
161- </ button >
153+ < td className = "p-4 align-middle text-right" >
154+ < div className = "flex justify-end gap-2" >
155+ < Button
156+ variant = "ghost"
157+ size = "sm"
158+ className = "h-8 w-8 p-0"
159+ onClick = { ( ) => onEdit ( record ) }
160+ >
161+ < Edit className = "h-4 w-4 text-muted-foreground" />
162+ < span className = "sr-only" > Edit</ span >
163+ </ Button >
164+ < Button
165+ variant = "ghost"
166+ size = "sm"
167+ className = "h-8 w-8 p-0"
168+ onClick = { ( ) => handleDelete ( record . id || record . _id ) }
169+ >
170+ < Trash2 className = "h-4 w-4 text-destructive" />
171+ < span className = "sr-only" > Delete</ span >
172+ </ Button >
173+ </ div >
162174 </ td >
163175 </ tr >
164176 ) ) }
165177 { ! loading && records . length === 0 && (
166- < tr > < td colSpan = { columns . length + 1 } className = "p-8 text-center text-accents-5" > No records found</ td > </ tr >
178+ < tr >
179+ < td colSpan = { columns . length + 1 } className = "p-8 text-center text-muted-foreground" >
180+ No records found
181+ </ td >
182+ </ tr >
167183 ) }
168184 </ tbody >
169185 </ table >
170- </ div >
186+ </ CardContent >
171187
172- { /* Pagination Controls */ }
173- < div className = "p-3 border-t border-accents-2 flex justify-end items-center gap-2 bg-gray-50" >
174- < button
188+ < CardFooter className = "p-2 border-t bg-muted/20 flex justify-end items-center gap-2" >
189+ < Button
190+ variant = "outline"
191+ size = "sm"
175192 disabled = { page === 1 }
176193 onClick = { ( ) => setPage ( p => Math . max ( 1 , p - 1 ) ) }
177- className = "px-3 py-1 border border-accents-3 rounded text-sm disabled:opacity-50 bg-white "
194+ className = "h-8 gap-1 "
178195 >
196+ < ArrowLeft className = "h-3.5 w-3.5" />
179197 Previous
180- </ button >
181- < span className = "text-sm font-medium px-2" > Page { page } </ span >
182- < button
183- disabled = { records . length < pageSize } // Simple check
198+ </ Button >
199+ < div className = "text-sm font-medium text-muted-foreground min-w-[3rem] text-center" >
200+ Page { page }
201+ </ div >
202+ < Button
203+ variant = "outline"
204+ size = "sm"
205+ disabled = { records . length < pageSize }
184206 onClick = { ( ) => setPage ( p => p + 1 ) }
185- className = "px-3 py-1 border border-accents-3 rounded text-sm disabled:opacity-50 bg-white "
207+ className = "h-8 gap-1 "
186208 >
187209 Next
188- </ button >
189- </ div >
190- </ div >
210+ < ArrowRight className = "h-3.5 w-3.5" />
211+ </ Button >
212+ </ CardFooter >
213+ </ Card >
191214 ) ;
192215}
0 commit comments