better-auth-studio 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/package.json +8 -1
  2. package/frontend/index.html +0 -13
  3. package/frontend/package-lock.json +0 -4675
  4. package/frontend/package.json +0 -52
  5. package/frontend/pnpm-lock.yaml +0 -4020
  6. package/frontend/postcss.config.js +0 -6
  7. package/frontend/src/App.tsx +0 -36
  8. package/frontend/src/components/CommandPalette.tsx +0 -219
  9. package/frontend/src/components/Layout.tsx +0 -159
  10. package/frontend/src/components/ui/badge.tsx +0 -40
  11. package/frontend/src/components/ui/button.tsx +0 -53
  12. package/frontend/src/components/ui/card.tsx +0 -78
  13. package/frontend/src/components/ui/input.tsx +0 -20
  14. package/frontend/src/components/ui/label.tsx +0 -19
  15. package/frontend/src/components/ui/select.tsx +0 -71
  16. package/frontend/src/index.css +0 -130
  17. package/frontend/src/lib/utils.ts +0 -6
  18. package/frontend/src/main.tsx +0 -10
  19. package/frontend/src/pages/Dashboard.tsx +0 -231
  20. package/frontend/src/pages/OrganizationDetails.tsx +0 -1281
  21. package/frontend/src/pages/Organizations.tsx +0 -874
  22. package/frontend/src/pages/Sessions.tsx +0 -623
  23. package/frontend/src/pages/Settings.tsx +0 -1019
  24. package/frontend/src/pages/TeamDetails.tsx +0 -666
  25. package/frontend/src/pages/Users.tsx +0 -728
  26. package/frontend/tailwind.config.js +0 -75
  27. package/frontend/tsconfig.json +0 -31
  28. package/frontend/tsconfig.node.json +0 -10
  29. package/frontend/vite.config.ts +0 -31
  30. package/src/auth-adapter.ts +0 -473
  31. package/src/cli.ts +0 -51
  32. package/src/config.ts +0 -320
  33. package/src/data.ts +0 -351
  34. package/src/routes.ts +0 -1585
  35. package/src/studio.ts +0 -86
  36. package/test-project/README.md +0 -0
  37. package/test-project/better-auth.db +0 -0
  38. package/test-project/better-auth_migrations/2025-08-27T15-55-04.099Z.sql +0 -7
  39. package/test-project/better-auth_migrations/2025-09-04T02-33-19.422Z.sql +0 -7
  40. package/test-project/package.json +0 -29
  41. package/test-project/pnpm-lock.yaml +0 -1728
  42. package/test-project/src/auth.ts +0 -47
  43. package/test-project/src/index.ts +0 -40
  44. package/tsconfig.json +0 -21
@@ -1,623 +0,0 @@
1
- import { useState, useEffect } from 'react'
2
- import {
3
- Database,
4
- Search,
5
- Filter,
6
- Edit,
7
- Trash2,
8
- Plus,
9
- Eye,
10
- X,
11
- User
12
- } from 'lucide-react'
13
- import { Button } from '../components/ui/button'
14
- import { Input } from '../components/ui/input'
15
- import { Label } from '../components/ui/label'
16
- import { Select, SelectItem } from '../components/ui/select'
17
-
18
- interface Session {
19
- id: string
20
- userId: string
21
- expiresAt: string
22
- createdAt: string
23
- updatedAt: string
24
- }
25
-
26
- export default function Sessions() {
27
- const [sessions, setSessions] = useState<Session[]>([])
28
- const [loading, setLoading] = useState(true)
29
- const [searchTerm, setSearchTerm] = useState('')
30
- const [filter, setFilter] = useState('all')
31
- const [showCreateModal, setShowCreateModal] = useState(false)
32
- const [showEditModal, setShowEditModal] = useState(false)
33
- const [showDeleteModal, setShowDeleteModal] = useState(false)
34
- const [showViewModal, setShowViewModal] = useState(false)
35
- const [showSeedModal, setShowSeedModal] = useState(false)
36
- const [selectedSession, setSelectedSession] = useState<Session | null>(null)
37
- const [seedingLogs, setSeedingLogs] = useState<string[]>([])
38
-
39
- useEffect(() => {
40
- fetchSessions()
41
- }, [])
42
-
43
- const fetchSessions = async () => {
44
- try {
45
- const response = await fetch('/api/sessions')
46
- const data = await response.json()
47
- setSessions(data.sessions || [])
48
- } catch (error) {
49
- console.error('Failed to fetch sessions:', error)
50
- } finally {
51
- setLoading(false)
52
- }
53
- }
54
-
55
- const handleSeedSessions = async (count: number) => {
56
- setSeedingLogs([])
57
-
58
- try {
59
- const response = await fetch('/api/seed/sessions', {
60
- method: 'POST',
61
- headers: { 'Content-Type': 'application/json' },
62
- body: JSON.stringify({ count })
63
- })
64
-
65
- const result = await response.json()
66
-
67
- if (result.success) {
68
- setSeedingLogs(result.results.map((r: any) =>
69
- `✅ Created session: ${r.session.id}`
70
- ))
71
- // Refresh the sessions list to show updated count
72
- await fetchSessions()
73
- } else {
74
- setSeedingLogs([`❌ Error: ${result.error || 'Failed to seed sessions'}`])
75
- }
76
- } catch (error) {
77
- setSeedingLogs([`❌ Error: ${error}`])
78
- }
79
- }
80
-
81
- const handleSeedAccounts = async (count: number) => {
82
- setSeedingLogs([])
83
-
84
- try {
85
- const response = await fetch('/api/seed/accounts', {
86
- method: 'POST',
87
- headers: { 'Content-Type': 'application/json' },
88
- body: JSON.stringify({ count })
89
- })
90
-
91
- const result = await response.json()
92
-
93
- if (result.success) {
94
- setSeedingLogs(result.results.map((r: any) =>
95
- `✅ Created account: ${r.account.provider}`
96
- ))
97
- // Refresh the sessions list to show updated count
98
- await fetchSessions()
99
- } else {
100
- setSeedingLogs([`❌ Error: ${result.error || 'Failed to seed accounts'}`])
101
- }
102
- } catch (error) {
103
- setSeedingLogs([`❌ Error: ${error}`])
104
- }
105
- }
106
-
107
- const openViewModal = (session: Session) => {
108
- setSelectedSession(session)
109
- setShowViewModal(true)
110
- }
111
-
112
- const openEditModal = (session: Session) => {
113
- setSelectedSession(session)
114
- setShowEditModal(true)
115
- }
116
-
117
- const openDeleteModal = (session: Session) => {
118
- setSelectedSession(session)
119
- setShowDeleteModal(true)
120
- }
121
-
122
- const handleCreateSession = async (sessionData: any) => {
123
- // Implementation for creating session
124
- console.log('Creating session:', sessionData)
125
- setShowCreateModal(false)
126
- }
127
-
128
- const handleUpdateSession = async (sessionData: any) => {
129
- // Implementation for updating session
130
- console.log('Updating session:', sessionData)
131
- setShowEditModal(false)
132
- }
133
-
134
- const handleDeleteSession = async () => {
135
- // Implementation for deleting session
136
- console.log('Deleting session:', selectedSession?.id)
137
- setShowDeleteModal(false)
138
- }
139
-
140
- const filteredSessions = sessions.filter(session => {
141
- const matchesSearch = session.id.toLowerCase().includes(searchTerm.toLowerCase()) ||
142
- session.userId.toLowerCase().includes(searchTerm.toLowerCase())
143
- const matchesFilter = filter === 'all' ||
144
- (filter === 'active' && new Date(session.expiresAt) > new Date()) ||
145
- (filter === 'expired' && new Date(session.expiresAt) <= new Date())
146
- return matchesSearch && matchesFilter
147
- })
148
-
149
- if (loading) {
150
- return (
151
- <div className="flex items-center justify-center h-64">
152
- <div className="text-white">Loading sessions...</div>
153
- </div>
154
- )
155
- }
156
-
157
- return (
158
- <div className="space-y-6">
159
- {/* Header */}
160
- <div className="flex items-center justify-between">
161
- <div>
162
- <h1 className="text-2xl text-white font-light">Sessions ({sessions.length})</h1>
163
- <p className="text-gray-400 mt-1">Manage user sessions and accounts</p>
164
- </div>
165
- <div className="flex items-center space-x-3">
166
- <Button
167
- className="border border-dashed border-white/20 text-white hover:bg-white/10 rounded-none"
168
- onClick={() => setShowSeedModal(true)}
169
- >
170
- <Database className="w-4 h-4 mr-2" />
171
- Seed
172
- </Button>
173
- <Button
174
- className="bg-white hover:bg-white/90 text-black border border-white/20 rounded-none"
175
- onClick={() => setShowCreateModal(true)}
176
- >
177
- <Plus className="w-4 h-4 mr-2" />
178
- Add Session
179
- </Button>
180
- </div>
181
- </div>
182
-
183
- {/* Filters */}
184
- <div className="flex items-center space-x-4">
185
- <div className="flex-1 relative">
186
- <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
187
- <Input
188
- placeholder="Search sessions..."
189
- value={searchTerm}
190
- onChange={(e) => setSearchTerm(e.target.value)}
191
- className="pl-10 border border-dashed border-white/20 bg-black/30 text-white rounded-none"
192
- />
193
- </div>
194
-
195
- <div className="flex items-center space-x-2">
196
- <Filter className="w-4 h-4 text-gray-400" />
197
- <Select value={filter} onChange={(e) => setFilter(e.target.value)}>
198
- <SelectItem value="all">All</SelectItem>
199
- <SelectItem value="active">Active</SelectItem>
200
- <SelectItem value="expired">Expired</SelectItem>
201
- </Select>
202
- </div>
203
- </div>
204
-
205
- {/* Sessions Table */}
206
- <div className="bg-black/30 border border-dashed border-white/20 rounded-none">
207
- <div className="overflow-x-auto">
208
- <table className="w-full">
209
- <thead>
210
- <tr className="border-b border-dashed border-white/10">
211
- <th className="text-left py-4 px-4 text-white font-light">Session</th>
212
- <th className="text-left py-4 px-4 text-white font-light">User ID</th>
213
- <th className="text-left py-4 px-4 text-white font-light">Status</th>
214
- <th className="text-left py-4 px-4 text-white font-light">Expires</th>
215
- <th className="text-right py-4 px-4 text-white font-light">Actions</th>
216
- </tr>
217
- </thead>
218
- <tbody>
219
- {filteredSessions.map((session) => (
220
- <tr key={session.id} className="border-b border-dashed border-white/5 hover:bg-white/5">
221
- <td className="py-4 px-4">
222
- <div className="flex items-center space-x-3">
223
- <div className="w-10 h-10 rounded-none border border-dashed border-white/20 bg-white/10 flex items-center justify-center">
224
- <Database className="w-5 h-5 text-white" />
225
- </div>
226
- <div>
227
- <div className="text-white font-light">Session {session.id.slice(0, 8)}...</div>
228
- <div className="text-sm text-gray-400">ID: {session.id}</div>
229
- </div>
230
- </div>
231
- </td>
232
- <td className="py-4 px-4 text-white">{session.userId}</td>
233
- <td className="py-4 px-4">
234
- <div className="flex items-center space-x-2">
235
- {new Date(session.expiresAt) > new Date() ? (
236
- <div className="w-2 h-2 bg-green-400 rounded-full"></div>
237
- ) : (
238
- <div className="w-2 h-2 bg-red-400 rounded-full"></div>
239
- )}
240
- <span className="text-sm text-gray-400">
241
- {new Date(session.expiresAt) > new Date() ? 'Active' : 'Expired'}
242
- </span>
243
- </div>
244
- </td>
245
- <td className="py-4 px-4 text-sm text-gray-400">
246
- {new Date(session.expiresAt).toLocaleDateString()}
247
- </td>
248
- <td className="py-4 px-4 text-right">
249
- <div className="flex items-center justify-end space-x-2">
250
- <Button
251
- variant="ghost"
252
- size="sm"
253
- className="text-gray-400 hover:text-white rounded-none"
254
- onClick={() => openViewModal(session)}
255
- >
256
- <Eye className="w-4 h-4" />
257
- </Button>
258
- <Button
259
- variant="ghost"
260
- size="sm"
261
- className="text-gray-400 hover:text-white rounded-none"
262
- onClick={() => openEditModal(session)}
263
- >
264
- <Edit className="w-4 h-4" />
265
- </Button>
266
- <Button
267
- variant="ghost"
268
- size="sm"
269
- className="text-red-400 hover:text-red-300 rounded-none"
270
- onClick={() => openDeleteModal(session)}
271
- >
272
- <Trash2 className="w-4 h-4" />
273
- </Button>
274
- </div>
275
- </td>
276
- </tr>
277
- ))}
278
- </tbody>
279
- </table>
280
- </div>
281
- </div>
282
-
283
- {/* Seed Modal */}
284
- {showSeedModal && (
285
- <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
286
- <div className="bg-black/90 border border-dashed border-white/20 p-6 w-full max-w-lg rounded-none">
287
- <div className="flex items-center justify-between mb-6">
288
- <h3 className="text-lg text-white font-light">Seed Data</h3>
289
- <Button
290
- variant="ghost"
291
- size="sm"
292
- onClick={() => setShowSeedModal(false)}
293
- className="text-gray-400 hover:text-white rounded-none"
294
- >
295
- <X className="w-4 h-4" />
296
- </Button>
297
- </div>
298
- <div className="space-y-6">
299
- {/* Session Seeding */}
300
- <div className="space-y-4">
301
- <div className="flex items-center space-x-2">
302
- <Database className="w-5 h-5 text-white" />
303
- <h4 className="text-white font-light">Seed Sessions</h4>
304
- </div>
305
- <div className="flex items-center space-x-3">
306
- <div className="flex-1">
307
- <Label htmlFor="session-count" className="text-sm text-gray-400 font-light">Number of sessions</Label>
308
- <Input
309
- id="session-count"
310
- type="number"
311
- min="1"
312
- max="100"
313
- defaultValue="5"
314
- className="mt-1 border border-dashed border-white/20 bg-black/30 text-white rounded-none"
315
- />
316
- </div>
317
- <Button
318
- onClick={() => {
319
- const count = parseInt((document.getElementById('session-count') as HTMLInputElement)?.value || '5')
320
- handleSeedSessions(count)
321
- }}
322
- className="bg-white hover:bg-white/90 text-black border border-white/20 rounded-none mt-6"
323
- >
324
- Seed Sessions
325
- </Button>
326
- </div>
327
- </div>
328
-
329
- {/* Account Seeding */}
330
- <div className="space-y-4">
331
- <div className="flex items-center space-x-2">
332
- <User className="w-5 h-5 text-white" />
333
- <h4 className="text-white font-light">Seed Accounts</h4>
334
- </div>
335
- <div className="flex items-center space-x-3">
336
- <div className="flex-1">
337
- <Label htmlFor="account-count" className="text-sm text-gray-400 font-light">Number of accounts</Label>
338
- <Input
339
- id="account-count"
340
- type="number"
341
- min="1"
342
- max="100"
343
- defaultValue="5"
344
- className="mt-1 border border-dashed border-white/20 bg-black/30 text-white rounded-none"
345
- />
346
- </div>
347
- <Button
348
- onClick={() => {
349
- const count = parseInt((document.getElementById('account-count') as HTMLInputElement)?.value || '5')
350
- handleSeedAccounts(count)
351
- }}
352
- className="bg-white hover:bg-white/90 text-black border border-white/20 rounded-none mt-6"
353
- >
354
- Seed Accounts
355
- </Button>
356
- </div>
357
- </div>
358
-
359
- {/* Seeding Logs */}
360
- {seedingLogs.length > 0 && (
361
- <div className="mt-6">
362
- <div className="flex items-center flex-col mb-3">
363
- <h5 className="text-sm text-white font-light">Seeding Logs</h5>
364
- <br />
365
- <details className="group">
366
- <summary className="cursor-pointer text-sm text-gray-400 font-light hover:text-white">
367
- View Details ({seedingLogs.length} items)
368
- </summary>
369
- <div className="mt-3 p-4 bg-black/50 border border-dashed border-white/20 rounded-none">
370
- <div className="space-y-2 max-h-48 overflow-y-auto">
371
- {seedingLogs.map((log, index) => (
372
- <div key={index} className="text-xs font-mono text-gray-300 flex items-start space-x-2">
373
- <span className="text-green-400">✓</span>
374
- <span>{log}</span>
375
- </div>
376
- ))}
377
- </div>
378
- </div>
379
- </details>
380
- </div>
381
- </div>
382
- )}
383
- </div>
384
- <div className="flex justify-end mt-6 pt-6 border-t border-dashed border-white/10">
385
- <Button
386
- variant="outline"
387
- onClick={() => setShowSeedModal(false)}
388
- className="border border-dashed border-white/20 text-white hover:bg-white/10 rounded-none"
389
- >
390
- Close
391
- </Button>
392
- </div>
393
- </div>
394
- </div>
395
- )}
396
-
397
- {/* Create Session Modal */}
398
- {showCreateModal && (
399
- <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
400
- <div className="bg-black/90 border border-dashed border-white/20 p-6 w-full max-w-md rounded-none">
401
- <div className="flex items-center justify-between mb-4">
402
- <h3 className="text-lg text-white font-light">Create Session</h3>
403
- <Button
404
- variant="ghost"
405
- size="sm"
406
- onClick={() => setShowCreateModal(false)}
407
- className="text-gray-400 hover:text-white rounded-none"
408
- >
409
- <X className="w-4 h-4" />
410
- </Button>
411
- </div>
412
- <div className="space-y-4">
413
- <div>
414
- <Label htmlFor="create-user-id" className="text-sm text-gray-400 font-light">User ID</Label>
415
- <Input
416
- id="create-user-id"
417
- className="mt-1 border border-dashed border-white/20 bg-black/30 text-white rounded-none"
418
- />
419
- </div>
420
- <div>
421
- <Label htmlFor="create-expires" className="text-sm text-gray-400 font-light">Expires At</Label>
422
- <Input
423
- id="create-expires"
424
- type="datetime-local"
425
- className="mt-1 border border-dashed border-white/20 bg-black/30 text-white rounded-none"
426
- />
427
- </div>
428
- </div>
429
- <div className="flex justify-end space-x-3 mt-6">
430
- <Button
431
- variant="outline"
432
- onClick={() => setShowCreateModal(false)}
433
- className="border border-dashed border-white/20 text-white hover:bg-white/10 rounded-none"
434
- >
435
- Cancel
436
- </Button>
437
- <Button
438
- onClick={() => handleCreateSession({})}
439
- className="bg-white hover:bg-white/90 text-black border border-white/20 rounded-none"
440
- >
441
- Create
442
- </Button>
443
- </div>
444
- </div>
445
- </div>
446
- )}
447
-
448
- {/* Edit Session Modal */}
449
- {showEditModal && selectedSession && (
450
- <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
451
- <div className="bg-black/90 border border-dashed border-white/20 p-6 w-full max-w-md rounded-none">
452
- <div className="flex items-center justify-between mb-4">
453
- <h3 className="text-lg text-white font-light">Edit Session</h3>
454
- <Button
455
- variant="ghost"
456
- size="sm"
457
- onClick={() => setShowEditModal(false)}
458
- className="text-gray-400 hover:text-white rounded-none"
459
- >
460
- <X className="w-4 h-4" />
461
- </Button>
462
- </div>
463
- <div className="space-y-4">
464
- <div className="flex items-center space-x-3">
465
- <div className="w-16 h-16 rounded-none border border-dashed border-white/20 bg-white/10 flex items-center justify-center">
466
- <Database className="w-8 h-8 text-white" />
467
- </div>
468
- <div>
469
- <div className="text-white font-light">Session {selectedSession.id.slice(0, 8)}...</div>
470
- <div className="text-sm text-gray-400">{selectedSession.userId}</div>
471
- </div>
472
- </div>
473
- <div>
474
- <Label htmlFor="edit-user-id" className="text-sm text-gray-400 font-light">User ID</Label>
475
- <Input
476
- id="edit-user-id"
477
- defaultValue={selectedSession.userId}
478
- className="mt-1 border border-dashed border-white/20 bg-black/30 text-white rounded-none"
479
- />
480
- </div>
481
- <div>
482
- <Label htmlFor="edit-expires" className="text-sm text-gray-400 font-light">Expires At</Label>
483
- <Input
484
- id="edit-expires"
485
- type="datetime-local"
486
- defaultValue={new Date(selectedSession.expiresAt).toISOString().slice(0, 16)}
487
- className="mt-1 border border-dashed border-white/20 bg-black/30 text-white rounded-none"
488
- />
489
- </div>
490
- </div>
491
- <div className="flex justify-end space-x-3 mt-6">
492
- <Button
493
- variant="outline"
494
- onClick={() => setShowEditModal(false)}
495
- className="border border-dashed border-white/20 text-white hover:bg-white/10 rounded-none"
496
- >
497
- Cancel
498
- </Button>
499
- <Button
500
- onClick={() => handleUpdateSession({})}
501
- className="bg-white hover:bg-white/90 text-black border border-white/20 rounded-none"
502
- >
503
- Update
504
- </Button>
505
- </div>
506
- </div>
507
- </div>
508
- )}
509
-
510
- {/* Delete Session Modal */}
511
- {showDeleteModal && selectedSession && (
512
- <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
513
- <div className="bg-black/90 border border-dashed border-white/20 p-6 w-full max-w-md rounded-none">
514
- <div className="flex items-center justify-between mb-4">
515
- <h3 className="text-lg text-white font-light">Delete Session</h3>
516
- <Button
517
- variant="ghost"
518
- size="sm"
519
- onClick={() => setShowDeleteModal(false)}
520
- className="text-gray-400 hover:text-white rounded-none"
521
- >
522
- <X className="w-4 h-4" />
523
- </Button>
524
- </div>
525
- <div className="space-y-4">
526
- <div className="flex items-center space-x-3">
527
- <div className="w-16 h-16 rounded-none border border-dashed border-white/20 bg-white/10 flex items-center justify-center">
528
- <Database className="w-8 h-8 text-white" />
529
- </div>
530
- <div>
531
- <div className="text-white font-light">Session {selectedSession.id.slice(0, 8)}...</div>
532
- <div className="text-sm text-gray-400">{selectedSession.userId}</div>
533
- </div>
534
- </div>
535
- <p className="text-gray-400">Are you sure you want to delete this session? This action cannot be undone.</p>
536
- </div>
537
- <div className="flex justify-end space-x-3 mt-6">
538
- <Button
539
- variant="outline"
540
- onClick={() => setShowDeleteModal(false)}
541
- className="border border-dashed border-white/20 text-white hover:bg-white/10 rounded-none"
542
- >
543
- Cancel
544
- </Button>
545
- <Button
546
- onClick={handleDeleteSession}
547
- className="bg-red-600 hover:bg-red-700 text-white border border-red-600 rounded-none"
548
- >
549
- Delete
550
- </Button>
551
- </div>
552
- </div>
553
- </div>
554
- )}
555
-
556
- {/* View Session Modal */}
557
- {showViewModal && selectedSession && (
558
- <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
559
- <div className="bg-black/90 border border-dashed border-white/20 p-6 w-full max-w-md rounded-none">
560
- <div className="flex items-center justify-between mb-4">
561
- <h3 className="text-lg text-white font-light">Session Details</h3>
562
- <Button
563
- variant="ghost"
564
- size="sm"
565
- onClick={() => setShowViewModal(false)}
566
- className="text-gray-400 hover:text-white rounded-none"
567
- >
568
- <X className="w-4 h-4" />
569
- </Button>
570
- </div>
571
- <div className="space-y-4">
572
- <div className="flex items-center space-x-3">
573
- <div className="w-16 h-16 rounded-none border border-dashed border-white/20 bg-white/10 flex items-center justify-center">
574
- <Database className="w-8 h-8 text-white" />
575
- </div>
576
- <div>
577
- <div className="text-white font-light">Session {selectedSession.id.slice(0, 8)}...</div>
578
- <div className="text-sm text-gray-400">{selectedSession.userId}</div>
579
- </div>
580
- </div>
581
- <div className="space-y-2">
582
- <div className="flex justify-between">
583
- <span className="text-gray-400">ID:</span>
584
- <span className="text-white text-sm">{selectedSession.id}</span>
585
- </div>
586
- <div className="flex justify-between">
587
- <span className="text-gray-400">User ID:</span>
588
- <span className="text-white text-sm">{selectedSession.userId}</span>
589
- </div>
590
- <div className="flex justify-between">
591
- <span className="text-gray-400">Status:</span>
592
- <span className="text-white text-sm">
593
- {new Date(selectedSession.expiresAt) > new Date() ? 'Active' : 'Expired'}
594
- </span>
595
- </div>
596
- <div className="flex justify-between">
597
- <span className="text-gray-400">Expires:</span>
598
- <span className="text-white text-sm">{new Date(selectedSession.expiresAt).toLocaleString()}</span>
599
- </div>
600
- <div className="flex justify-between">
601
- <span className="text-gray-400">Created:</span>
602
- <span className="text-white text-sm">{new Date(selectedSession.createdAt).toLocaleString()}</span>
603
- </div>
604
- <div className="flex justify-between">
605
- <span className="text-gray-400">Updated:</span>
606
- <span className="text-white text-sm">{new Date(selectedSession.updatedAt).toLocaleString()}</span>
607
- </div>
608
- </div>
609
- </div>
610
- <div className="flex justify-end mt-6">
611
- <Button
612
- onClick={() => setShowViewModal(false)}
613
- className="bg-white hover:bg-white/90 text-black border border-white/20 rounded-none"
614
- >
615
- Close
616
- </Button>
617
- </div>
618
- </div>
619
- </div>
620
- )}
621
- </div>
622
- )
623
- }