120 lines
4.4 KiB
TypeScript
120 lines
4.4 KiB
TypeScript
'use client';
|
||
|
||
import { useEffect, useState } from 'react';
|
||
import { db, auth } from '@/lib/firebase/config';
|
||
import { collection, query, where, orderBy, limit, getDocs } from 'firebase/firestore';
|
||
|
||
export default function TestSessionsPage() {
|
||
const [sessions, setSessions] = useState<any[]>([]);
|
||
const [loading, setLoading] = useState(true);
|
||
const [error, setError] = useState<string | null>(null);
|
||
|
||
useEffect(() => {
|
||
const unsubscribe = auth.onAuthStateChanged(async (user) => {
|
||
if (!user) {
|
||
setError('Not authenticated');
|
||
setLoading(false);
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const sessionsRef = collection(db, 'sessions');
|
||
const q = query(
|
||
sessionsRef,
|
||
where('userId', '==', user.uid),
|
||
orderBy('createdAt', 'desc'),
|
||
limit(20)
|
||
);
|
||
const snapshot = await getDocs(q);
|
||
|
||
const sessionData = snapshot.docs.map(doc => ({
|
||
id: doc.id,
|
||
...doc.data()
|
||
}));
|
||
|
||
setSessions(sessionData);
|
||
} catch (err: any) {
|
||
console.error('Error fetching sessions:', err);
|
||
setError(err.message);
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
});
|
||
|
||
return () => unsubscribe();
|
||
}, []);
|
||
|
||
return (
|
||
<div className="p-8">
|
||
<h1 className="text-2xl font-bold mb-4">Recent Sessions</h1>
|
||
|
||
{loading && <p>Loading...</p>}
|
||
{error && <p className="text-red-500">Error: {error}</p>}
|
||
|
||
{!loading && sessions.length === 0 && (
|
||
<p className="text-gray-500">No sessions found yet. Make sure you're coding in Cursor with the extension enabled!</p>
|
||
)}
|
||
|
||
{sessions.length > 0 && (
|
||
<div className="space-y-4">
|
||
{sessions.map((session) => (
|
||
<div key={session.id} className="p-4 border rounded-lg bg-card">
|
||
<div className="grid grid-cols-2 gap-2 text-sm">
|
||
<div><strong>Session ID:</strong> {session.id}</div>
|
||
<div><strong>User ID:</strong> {session.userId?.substring(0, 20)}...</div>
|
||
|
||
<div className="col-span-2 mt-2">
|
||
<strong>🗂️ Workspace:</strong>
|
||
<div className="font-mono text-xs bg-muted p-2 rounded mt-1">
|
||
{session.workspacePath || 'N/A'}
|
||
</div>
|
||
{session.workspaceName && (
|
||
<div className="text-muted-foreground mt-1">
|
||
Project: <span className="font-medium">{session.workspaceName}</span>
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
<div><strong>Created:</strong> {session.createdAt?.toDate?.()?.toLocaleString() || 'N/A'}</div>
|
||
<div><strong>Duration:</strong> {session.duration ? `${session.duration}s` : 'N/A'}</div>
|
||
|
||
<div><strong>Model:</strong> {session.model || 'unknown'}</div>
|
||
<div><strong>Cost:</strong> ${session.cost?.toFixed(4) || '0.0000'}</div>
|
||
|
||
<div><strong>Tokens Used:</strong> {session.tokensUsed || 0}</div>
|
||
<div><strong>Files Modified:</strong> {session.filesModified?.length || 0}</div>
|
||
</div>
|
||
|
||
{session.filesModified && session.filesModified.length > 0 && (
|
||
<details className="mt-3">
|
||
<summary className="cursor-pointer text-primary hover:underline text-sm">
|
||
View Modified Files ({session.filesModified.length})
|
||
</summary>
|
||
<div className="mt-2 p-2 bg-muted rounded text-xs space-y-1">
|
||
{session.filesModified.map((file: string, idx: number) => (
|
||
<div key={idx} className="font-mono">{file}</div>
|
||
))}
|
||
</div>
|
||
</details>
|
||
)}
|
||
|
||
{session.conversationSummary && (
|
||
<details className="mt-3">
|
||
<summary className="cursor-pointer text-primary hover:underline text-sm">
|
||
View Conversation Summary
|
||
</summary>
|
||
<div className="mt-2 p-3 bg-muted rounded text-sm">
|
||
{session.conversationSummary}
|
||
</div>
|
||
</details>
|
||
)}
|
||
</div>
|
||
))}
|
||
</div>
|
||
)}
|
||
</div>
|
||
);
|
||
}
|
||
|
||
|