Compare commits
4 commits
feat/story
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 410cd7c123 | |||
|
|
c9d4122b3a | ||
|
|
22781365e6 | ||
|
|
a3303a605b |
3 changed files with 71 additions and 21 deletions
44
__tests__/components/idea-timeline-merge.test.ts
Normal file
44
__tests__/components/idea-timeline-merge.test.ts
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
import { describe, it, expect } from 'vitest'
|
||||
import { mergeTimelineItems } from '@/components/ideas/idea-timeline'
|
||||
|
||||
describe('mergeTimelineItems', () => {
|
||||
it('sorteert reverse-chronologisch: nieuwste entry staat eerst', () => {
|
||||
const logs = [
|
||||
{ id: 'l1', type: 'NOTE', content: 'oud', metadata: null, created_at: '2024-01-01T10:00:00.000Z' },
|
||||
]
|
||||
const questions = [
|
||||
{
|
||||
id: 'q1',
|
||||
question: 'Vraag?',
|
||||
options: null,
|
||||
status: 'open' as const,
|
||||
answer: null,
|
||||
created_at: '2024-01-03T12:00:00.000Z',
|
||||
expires_at: '2024-01-10T12:00:00.000Z',
|
||||
},
|
||||
]
|
||||
const userQuestions = [
|
||||
{
|
||||
id: 'uq1',
|
||||
question: 'Mijn vraag',
|
||||
answer: null,
|
||||
status: 'pending' as const,
|
||||
created_at: '2024-01-02T08:00:00.000Z',
|
||||
},
|
||||
]
|
||||
|
||||
const result = mergeTimelineItems(logs, questions, userQuestions)
|
||||
|
||||
expect(result).toHaveLength(3)
|
||||
expect(result[0].created_at).toBe('2024-01-03T12:00:00.000Z')
|
||||
expect(result[0].kind).toBe('question')
|
||||
expect(result[1].created_at).toBe('2024-01-02T08:00:00.000Z')
|
||||
expect(result[1].kind).toBe('user_question')
|
||||
expect(result[2].created_at).toBe('2024-01-01T10:00:00.000Z')
|
||||
expect(result[2].kind).toBe('log')
|
||||
})
|
||||
|
||||
it('geeft lege lijst terug bij geen input', () => {
|
||||
expect(mergeTimelineItems([], [], [])).toEqual([])
|
||||
})
|
||||
})
|
||||
|
|
@ -89,7 +89,7 @@ export default async function IdeaDetailPage({ params, searchParams }: PageProps
|
|||
|
||||
const userQuestionsRaw = await prisma.userQuestion.findMany({
|
||||
where: { idea_id: id },
|
||||
orderBy: { created_at: 'asc' },
|
||||
orderBy: { created_at: 'desc' },
|
||||
take: 100,
|
||||
select: { id: true, question: true, answer: true, status: true, created_at: true },
|
||||
})
|
||||
|
|
|
|||
|
|
@ -99,6 +99,23 @@ const USER_QUESTION_STATUS_LABEL: Record<TimelineUserQuestion['status'], string>
|
|||
answered: 'Beantwoord',
|
||||
}
|
||||
|
||||
export type TimelineEntry =
|
||||
| { kind: 'log'; created_at: string; data: TimelineLog }
|
||||
| { kind: 'question'; created_at: string; data: TimelineQuestion }
|
||||
| { kind: 'user_question'; created_at: string; data: TimelineUserQuestion }
|
||||
|
||||
export function mergeTimelineItems(
|
||||
logs: TimelineLog[],
|
||||
questions: TimelineQuestion[],
|
||||
userQuestions: TimelineUserQuestion[],
|
||||
): TimelineEntry[] {
|
||||
return [
|
||||
...logs.map((l) => ({ kind: 'log' as const, created_at: l.created_at, data: l })),
|
||||
...questions.map((q) => ({ kind: 'question' as const, created_at: q.created_at, data: q })),
|
||||
...userQuestions.map((uq) => ({ kind: 'user_question' as const, created_at: uq.created_at, data: uq })),
|
||||
].sort((a, b) => (a.created_at < b.created_at ? 1 : -1))
|
||||
}
|
||||
|
||||
export function IdeaTimeline({
|
||||
logs,
|
||||
questions,
|
||||
|
|
@ -107,28 +124,18 @@ export function IdeaTimeline({
|
|||
ideaId,
|
||||
isDemo = false,
|
||||
}: Props) {
|
||||
const merged = [
|
||||
...logs.map((l) => ({
|
||||
kind: 'log' as const,
|
||||
created_at: l.created_at,
|
||||
data: l,
|
||||
})),
|
||||
...questions.map((q) => ({
|
||||
kind: 'question' as const,
|
||||
created_at: q.created_at,
|
||||
data: q,
|
||||
})),
|
||||
...userQuestions.map((uq) => ({
|
||||
kind: 'user_question' as const,
|
||||
created_at: uq.created_at,
|
||||
data: uq,
|
||||
})),
|
||||
].sort((a, b) => (a.created_at < b.created_at ? 1 : -1))
|
||||
const merged = mergeTimelineItems(logs, questions, userQuestions)
|
||||
|
||||
const showChatInput = planMd !== null
|
||||
|
||||
return (
|
||||
<div className="space-y-4" {...debugProps('idea-timeline', 'IdeaTimeline', 'components/ideas/idea-timeline.tsx')}>
|
||||
<div {...debugProps('idea-timeline', 'IdeaTimeline', 'components/ideas/idea-timeline.tsx')}>
|
||||
{showChatInput && (
|
||||
<div className="sticky top-0 z-10 bg-background border-b border-border pb-3 mb-4" data-debug-id="idea-timeline__chat-input">
|
||||
<UserChatInput ideaId={ideaId} isDemo={isDemo} />
|
||||
</div>
|
||||
)}
|
||||
<div className="space-y-4">
|
||||
{merged.length === 0 ? (
|
||||
<p className="text-sm text-muted-foreground py-8 text-center italic">
|
||||
Nog geen activiteit op dit idee.
|
||||
|
|
@ -252,8 +259,7 @@ export function IdeaTimeline({
|
|||
})}
|
||||
</ol>
|
||||
)}
|
||||
|
||||
{showChatInput && <UserChatInput ideaId={ideaId} isDemo={isDemo} />}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue