Context
The frontend session list has duplication and lacks management actions. This issue covers the UI work to support delete, rename, deduplication, and eventually pagination.
Depends on backend issue: uncleJim21/pullthatupjamie-backend#69
All frontend work is in src/components/UnifiedSidePanel.tsx unless noted.
2.1 Extract SessionCard component (dedup)
The session card list is rendered identically in two places:
- Bottom layout: inside the
isBottomLayout branch (sessions else-block)
- Side layout: inside the
isSessionsMode branch at the end of the component
Extract into a shared component (can be a local component in the same file or a separate SessionCard.tsx):
interface SessionCardProps {
session: ResearchSession;
isActive: boolean;
activeSessionItemCount?: number;
onOpen: (sessionId: string, title: string) => void;
onCopyLink: (sessionId: string) => void;
onDelete: (sessionId: string, title: string) => void;
onRename: (sessionId: string, newTitle: string) => void;
copiedSessionId: string | null;
}
Both layout branches should render <SessionCard ... /> instead of duplicating the card markup.
2.2 Add delete action per session card
- Add a subtle trash icon button (similar to the existing copy button) on each session card
- On click, show the existing
DeleteConfirmationModal (from src/components/DeleteConfirmationModal.tsx)
- On confirm, call
deleteResearchSession(sessionId) and remove from local sessions state
- If the deleted session is the
activeSessionId, the parent should be notified (add an onDeleteSession callback prop)
- Prevent deleting while a delete is in-flight (use
isDeleting state)
The DeleteConfirmationModal already supports:
isDeleting loading state with spinner
- Custom button text
itemType for contextual messaging
2.3 Add inline rename
- Clicking the session title text switches it to an
<input> (controlled)
- Pre-filled with current
displayTitle
- Save on Enter or blur, cancel on Escape
- Calls
updateResearchSessionTitle(sessionId, newTitle)
- Optimistically update the local sessions state
- Follow the inline-edit pattern from
src/components/MentionPinManagement.tsx (lines 254-294)
- Add a small pencil/edit icon on hover to hint at editability
2.4 Wire up service functions
Add to src/services/researchSessionService.ts:
export async function deleteResearchSession(sessionId: string): Promise<{ success: boolean }> {
const clientId = getOrCreateClientId();
const url = `${API_URL}/api/research-sessions/${sessionId}?clientId=${encodeURIComponent(clientId)}`;
const response = await fetch(url, {
method: 'DELETE',
headers: getAuthHeaders(),
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(errorData.message || `HTTP error! status: ${response.status}`);
}
return response.json();
}
export async function updateResearchSessionTitle(
sessionId: string,
title: string
): Promise<ResearchSessionResponse> {
const clientId = getOrCreateClientId();
const response = await fetch(`${API_URL}/api/research-sessions/${sessionId}?clientId=${encodeURIComponent(clientId)}`, {
method: 'PATCH',
headers: getAuthHeaders(),
body: JSON.stringify({ title }),
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(errorData.message || `HTTP error! status: ${response.status}`);
}
return response.json();
}
2.5 Pagination / infinite scroll (Phase 2)
Once the backend supports pagination (1.3):
- Update
fetchAllResearchSessions() to accept page and limit params
- Implement infinite scroll or "Load more" button in the sessions list
- Show a loading spinner at the bottom when fetching the next page
- Track
hasMore based on pagination.total vs loaded count
This can be a follow-up PR after the backend pagination is deployed.
Acceptance Criteria
Files likely touched
src/components/UnifiedSidePanel.tsx
src/services/researchSessionService.ts
src/components/DeleteConfirmationModal.tsx (may need minor props)
- New:
src/components/SessionCard.tsx (optional extraction)
Context
The frontend session list has duplication and lacks management actions. This issue covers the UI work to support delete, rename, deduplication, and eventually pagination.
Depends on backend issue: uncleJim21/pullthatupjamie-backend#69
All frontend work is in
src/components/UnifiedSidePanel.tsxunless noted.2.1 Extract SessionCard component (dedup)
The session card list is rendered identically in two places:
isBottomLayoutbranch (sessions else-block)isSessionsModebranch at the end of the componentExtract into a shared component (can be a local component in the same file or a separate
SessionCard.tsx):Both layout branches should render
<SessionCard ... />instead of duplicating the card markup.2.2 Add delete action per session card
DeleteConfirmationModal(fromsrc/components/DeleteConfirmationModal.tsx)deleteResearchSession(sessionId)and remove from local sessions stateactiveSessionId, the parent should be notified (add anonDeleteSessioncallback prop)isDeletingstate)The
DeleteConfirmationModalalready supports:isDeletingloading state with spinneritemTypefor contextual messaging2.3 Add inline rename
<input>(controlled)displayTitleupdateResearchSessionTitle(sessionId, newTitle)src/components/MentionPinManagement.tsx(lines 254-294)2.4 Wire up service functions
Add to
src/services/researchSessionService.ts:2.5 Pagination / infinite scroll (Phase 2)
Once the backend supports pagination (1.3):
fetchAllResearchSessions()to acceptpageandlimitparamshasMorebased onpagination.totalvs loaded countThis can be a follow-up PR after the backend pagination is deployed.
Acceptance Criteria
Files likely touched
src/components/UnifiedSidePanel.tsxsrc/services/researchSessionService.tssrc/components/DeleteConfirmationModal.tsx(may need minor props)src/components/SessionCard.tsx(optional extraction)