Skip to content

Commit 296af64

Browse files
committed
2 parents ee9af38 + 383a0e7 commit 296af64

38 files changed

+776
-507
lines changed

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ Agents cannot:
180180
- ❌ Test API endpoints that require browser context
181181

182182
For runtime testing and verification, developers should:
183+
183184
1. Review the code changes
184185
2. Start the dev server manually (`pnpm dev`)
185186
3. Test the functionality in a browser

src/components/BlockWithFeedback.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ export function BlockWithFeedback({
8383
onMouseLeave={handleMouseLeave}
8484
data-feedback-wrapper="true"
8585
style={{
86-
anchorName: blockSelector ? `--feedback-${blockSelector.replace(/[^a-zA-Z0-9]/g, '-')}` : undefined,
86+
anchorName: blockSelector
87+
? `--feedback-${blockSelector.replace(/[^a-zA-Z0-9]/g, '-')}`
88+
: undefined,
8789
}}
8890
>
8991
{children}
@@ -111,11 +113,7 @@ export function BlockWithFeedback({
111113
{/* Note display - inline in document flow */}
112114
{note && blockSelector && (
113115
<div className="my-4">
114-
<DocFeedbackNote
115-
note={note}
116-
anchorName=""
117-
inline={true}
118-
/>
116+
<DocFeedbackNote note={note} anchorName="" inline={true} />
119117
</div>
120118
)}
121119
</>

src/components/DocFeedbackContext.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ interface DocFeedbackContextValue {
1010
toggleNote: (noteId: string) => void
1111

1212
// Actions
13-
onAddFeedback: (blockSelector: string, blockContentHash: string | undefined, type: 'note' | 'improvement') => void
13+
onAddFeedback: (
14+
blockSelector: string,
15+
blockContentHash: string | undefined,
16+
type: 'note' | 'improvement',
17+
) => void
1418
onEditNote: (note: DocFeedback) => void
1519
onShowNote: (noteId: string) => void
1620

@@ -20,7 +24,9 @@ interface DocFeedbackContextValue {
2024
libraryVersion: string
2125
}
2226

23-
const DocFeedbackContext = React.createContext<DocFeedbackContextValue | null>(null)
27+
const DocFeedbackContext = React.createContext<DocFeedbackContextValue | null>(
28+
null,
29+
)
2430

2531
export function useDocFeedback() {
2632
const context = React.useContext(DocFeedbackContext)

src/components/DocFeedbackFloatingButton.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,9 @@ export function DocFeedbackFloatingButton({
138138
</div>
139139
</div>
140140
</button>
141-
{!hasImprovement && <div className="h-px bg-gray-200 dark:bg-gray-700" />}
141+
{!hasImprovement && (
142+
<div className="h-px bg-gray-200 dark:bg-gray-700" />
143+
)}
142144
</>
143145
)}
144146
{!hasImprovement && (

src/components/DocFeedbackNote.tsx

Lines changed: 120 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
11
import * as React from 'react'
22
import { twMerge } from 'tailwind-merge'
3-
import { FaComment, FaLightbulb, FaTrash, FaChevronDown, FaChevronUp, FaSave, FaTimes } from 'react-icons/fa'
3+
import {
4+
FaComment,
5+
FaLightbulb,
6+
FaTrash,
7+
FaChevronDown,
8+
FaChevronUp,
9+
FaSave,
10+
FaTimes,
11+
} from 'react-icons/fa'
412
import { useMutation, useQueryClient } from '@tanstack/react-query'
5-
import { deleteDocFeedback, updateDocFeedback, updateDocFeedbackCollapsed } from '~/utils/docFeedback.functions'
13+
import {
14+
deleteDocFeedback,
15+
updateDocFeedback,
16+
updateDocFeedbackCollapsed,
17+
} from '~/utils/docFeedback.functions'
618
import { useToast } from '~/components/ToastProvider'
719
import type { DocFeedback } from '~/db/schema'
820

@@ -12,7 +24,11 @@ interface DocFeedbackNoteProps {
1224
inline?: boolean
1325
}
1426

15-
export function DocFeedbackNote({ note, anchorName, inline = false }: DocFeedbackNoteProps) {
27+
export function DocFeedbackNote({
28+
note,
29+
anchorName,
30+
inline = false,
31+
}: DocFeedbackNoteProps) {
1632
const queryClient = useQueryClient()
1733
const [isDeleting, setIsDeleting] = React.useState(false)
1834
const [deleteError, setDeleteError] = React.useState<string | null>(null)
@@ -57,7 +73,8 @@ export function DocFeedbackNote({ note, anchorName, inline = false }: DocFeedbac
5773

5874
// Extract first line for preview
5975
const firstLine = note.content.split('\n')[0]
60-
const preview = firstLine.length > 60 ? firstLine.substring(0, 60) + '...' : firstLine
76+
const preview =
77+
firstLine.length > 60 ? firstLine.substring(0, 60) + '...' : firstLine
6178

6279
const deleteMutation = useMutation({
6380
mutationFn: deleteDocFeedback,
@@ -66,33 +83,32 @@ export function DocFeedbackNote({ note, anchorName, inline = false }: DocFeedbac
6683
await queryClient.cancelQueries({ queryKey: ['docFeedback'] })
6784

6885
// Snapshot the previous value
69-
const previousData = queryClient.getQueriesData({ queryKey: ['docFeedback'] })
86+
const previousData = queryClient.getQueriesData({
87+
queryKey: ['docFeedback'],
88+
})
7089

7190
// Optimistically remove the note from all matching queries
72-
queryClient.setQueriesData(
73-
{ queryKey: ['docFeedback'] },
74-
(old: any) => {
75-
if (!old) return old
76-
77-
// Handle doc page structure (userFeedback)
78-
if ('userFeedback' in old && Array.isArray(old.userFeedback)) {
79-
return {
80-
...old,
81-
userFeedback: old.userFeedback.filter((f: any) => f.id !== note.id),
82-
}
91+
queryClient.setQueriesData({ queryKey: ['docFeedback'] }, (old: any) => {
92+
if (!old) return old
93+
94+
// Handle doc page structure (userFeedback)
95+
if ('userFeedback' in old && Array.isArray(old.userFeedback)) {
96+
return {
97+
...old,
98+
userFeedback: old.userFeedback.filter((f: any) => f.id !== note.id),
8399
}
100+
}
84101

85-
// Handle account/notes page structure (feedback)
86-
if ('feedback' in old && Array.isArray(old.feedback)) {
87-
return {
88-
...old,
89-
feedback: old.feedback.filter((f: any) => f.id !== note.id),
90-
}
102+
// Handle account/notes page structure (feedback)
103+
if ('feedback' in old && Array.isArray(old.feedback)) {
104+
return {
105+
...old,
106+
feedback: old.feedback.filter((f: any) => f.id !== note.id),
91107
}
92-
93-
return old
94108
}
95-
)
109+
110+
return old
111+
})
96112

97113
return { previousData }
98114
},
@@ -118,41 +134,48 @@ export function DocFeedbackNote({ note, anchorName, inline = false }: DocFeedbac
118134
await queryClient.cancelQueries({ queryKey: ['docFeedback'] })
119135

120136
// Snapshot the previous value
121-
const previousData = queryClient.getQueriesData({ queryKey: ['docFeedback'] })
137+
const previousData = queryClient.getQueriesData({
138+
queryKey: ['docFeedback'],
139+
})
122140

123141
// Optimistically update the note content
124-
queryClient.setQueriesData(
125-
{ queryKey: ['docFeedback'] },
126-
(old: any) => {
127-
if (!old) return old
128-
129-
// Handle doc page structure (userFeedback)
130-
if ('userFeedback' in old && Array.isArray(old.userFeedback)) {
131-
return {
132-
...old,
133-
userFeedback: old.userFeedback.map((f: any) =>
134-
f.id === note.id
135-
? { ...f, content: variables.data.content, updatedAt: new Date() }
136-
: f
137-
),
138-
}
142+
queryClient.setQueriesData({ queryKey: ['docFeedback'] }, (old: any) => {
143+
if (!old) return old
144+
145+
// Handle doc page structure (userFeedback)
146+
if ('userFeedback' in old && Array.isArray(old.userFeedback)) {
147+
return {
148+
...old,
149+
userFeedback: old.userFeedback.map((f: any) =>
150+
f.id === note.id
151+
? {
152+
...f,
153+
content: variables.data.content,
154+
updatedAt: new Date(),
155+
}
156+
: f,
157+
),
139158
}
159+
}
140160

141-
// Handle account/notes page structure (feedback)
142-
if ('feedback' in old && Array.isArray(old.feedback)) {
143-
return {
144-
...old,
145-
feedback: old.feedback.map((f: any) =>
146-
f.id === note.id
147-
? { ...f, content: variables.data.content, updatedAt: new Date() }
148-
: f
149-
),
150-
}
161+
// Handle account/notes page structure (feedback)
162+
if ('feedback' in old && Array.isArray(old.feedback)) {
163+
return {
164+
...old,
165+
feedback: old.feedback.map((f: any) =>
166+
f.id === note.id
167+
? {
168+
...f,
169+
content: variables.data.content,
170+
updatedAt: new Date(),
171+
}
172+
: f,
173+
),
151174
}
152-
153-
return old
154175
}
155-
)
176+
177+
return old
178+
})
156179

157180
return { previousData }
158181
},
@@ -182,41 +205,40 @@ export function DocFeedbackNote({ note, anchorName, inline = false }: DocFeedbac
182205
await queryClient.cancelQueries({ queryKey: ['docFeedback'] })
183206

184207
// Snapshot the previous value
185-
const previousData = queryClient.getQueriesData({ queryKey: ['docFeedback'] })
208+
const previousData = queryClient.getQueriesData({
209+
queryKey: ['docFeedback'],
210+
})
186211

187212
// Optimistically toggle collapsed state
188-
queryClient.setQueriesData(
189-
{ queryKey: ['docFeedback'] },
190-
(old: any) => {
191-
if (!old) return old
192-
193-
// Handle doc page structure (userFeedback)
194-
if ('userFeedback' in old && Array.isArray(old.userFeedback)) {
195-
return {
196-
...old,
197-
userFeedback: old.userFeedback.map((f: any) =>
198-
f.id === note.id
199-
? { ...f, isCollapsed: variables.data.isCollapsed }
200-
: f
201-
),
202-
}
213+
queryClient.setQueriesData({ queryKey: ['docFeedback'] }, (old: any) => {
214+
if (!old) return old
215+
216+
// Handle doc page structure (userFeedback)
217+
if ('userFeedback' in old && Array.isArray(old.userFeedback)) {
218+
return {
219+
...old,
220+
userFeedback: old.userFeedback.map((f: any) =>
221+
f.id === note.id
222+
? { ...f, isCollapsed: variables.data.isCollapsed }
223+
: f,
224+
),
203225
}
226+
}
204227

205-
// Handle account/notes page structure (feedback)
206-
if ('feedback' in old && Array.isArray(old.feedback)) {
207-
return {
208-
...old,
209-
feedback: old.feedback.map((f: any) =>
210-
f.id === note.id
211-
? { ...f, isCollapsed: variables.data.isCollapsed }
212-
: f
213-
),
214-
}
228+
// Handle account/notes page structure (feedback)
229+
if ('feedback' in old && Array.isArray(old.feedback)) {
230+
return {
231+
...old,
232+
feedback: old.feedback.map((f: any) =>
233+
f.id === note.id
234+
? { ...f, isCollapsed: variables.data.isCollapsed }
235+
: f,
236+
),
215237
}
216-
217-
return old
218238
}
219-
)
239+
240+
return old
241+
})
220242

221243
return { previousData }
222244
},
@@ -316,7 +338,8 @@ export function DocFeedbackNote({ note, anchorName, inline = false }: DocFeedbac
316338
<div
317339
className={twMerge(
318340
`flex flex-col gap-1 p-2 ${colors.header}`,
319-
note.isCollapsed && 'cursor-pointer hover:opacity-80 transition-opacity'
341+
note.isCollapsed &&
342+
'cursor-pointer hover:opacity-80 transition-opacity',
320343
)}
321344
onClick={note.isCollapsed ? handleToggle : undefined}
322345
>
@@ -364,9 +387,17 @@ export function DocFeedbackNote({ note, anchorName, inline = false }: DocFeedbac
364387
handleToggle()
365388
}}
366389
className={`p-1 ${colors.icon} ${colors.deleteHover} transition-colors`}
367-
title={note.isCollapsed ? `Expand ${isImprovement ? 'improvement' : 'note'}` : `Collapse ${isImprovement ? 'improvement' : 'note'}`}
390+
title={
391+
note.isCollapsed
392+
? `Expand ${isImprovement ? 'improvement' : 'note'}`
393+
: `Collapse ${isImprovement ? 'improvement' : 'note'}`
394+
}
368395
>
369-
{note.isCollapsed ? <FaChevronDown className="text-xs" /> : <FaChevronUp className="text-xs" />}
396+
{note.isCollapsed ? (
397+
<FaChevronDown className="text-xs" />
398+
) : (
399+
<FaChevronUp className="text-xs" />
400+
)}
370401
</button>
371402
</div>
372403
</div>
@@ -428,7 +459,9 @@ export function DocFeedbackNote({ note, anchorName, inline = false }: DocFeedbac
428459
)}
429460

430461
{/* Timestamp and Points */}
431-
<div className={`mt-2 flex items-center justify-between text-xs ${colors.timestamp}`}>
462+
<div
463+
className={`mt-2 flex items-center justify-between text-xs ${colors.timestamp}`}
464+
>
432465
<div>
433466
{new Date(note.createdAt).toLocaleDateString('en-US', {
434467
month: 'short',

src/components/FeedPage.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,10 @@ export function FeedPage({
300300
<div className="flex-1 space-y-2 sm:space-y-4 w-full max-w-7xl mx-auto flex flex-col lg:flex-row gap-2 min-h-0">
301301
<aside className="lg:w-64 flex-shrink-0 lg:self-start sticky top-[calc(var(--navbar-height)+1rem)] z-10">
302302
<FeedFilters
303-
libraries={libraries.filter((lib): lib is import('~/libraries/types').Library => 'tagline' in lib)}
303+
libraries={libraries.filter(
304+
(lib): lib is import('~/libraries/types').Library =>
305+
'tagline' in lib,
306+
)}
304307
partners={partners}
305308
selectedSources={effectiveFilters.sources}
306309
selectedLibraries={effectiveFilters.libraries}

src/components/FeedPageLayout.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,9 @@ function FeedPageLayoutFilters() {
212212
return (
213213
<aside className="lg:w-64 flex-shrink-0 lg:self-start">
214214
<FeedFilters
215-
libraries={libraries.filter((lib): lib is import('~/libraries/types').Library => 'tagline' in lib)}
215+
libraries={libraries.filter(
216+
(lib): lib is import('~/libraries/types').Library => 'tagline' in lib,
217+
)}
216218
partners={partners}
217219
selectedSources={filters.sources}
218220
selectedLibraries={filters.libraries}

src/components/FeedTicker.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ export function FeedTicker() {
101101
const libraryName = library?.name || libraryId || ''
102102

103103
// Get version from metadata
104-
const version = (entry.metadata as { version?: string } | null)?.version || ''
104+
const version =
105+
(entry.metadata as { version?: string } | null)?.version || ''
105106

106107
return (
107108
<Link

0 commit comments

Comments
 (0)