feat: refactor thought threads handling to improve structure and efficiency
This commit is contained in:
@@ -84,6 +84,24 @@ export const CreateApiKeySchema = z.object({
|
||||
name: z.string().min(1, "Key name cannot be empty."),
|
||||
});
|
||||
|
||||
export const ThoughtThreadSchema: z.ZodType<{
|
||||
id: string;
|
||||
authorUsername: string;
|
||||
content: string;
|
||||
visibility: "Public" | "FriendsOnly" | "Private";
|
||||
replyToId: string | null;
|
||||
createdAt: Date;
|
||||
replies: ThoughtThread[];
|
||||
}> = z.object({
|
||||
id: z.uuid(),
|
||||
authorUsername: z.string(),
|
||||
content: z.string(),
|
||||
visibility: z.enum(["Public", "FriendsOnly", "Private"]),
|
||||
replyToId: z.uuid().nullable(),
|
||||
createdAt: z.coerce.date(),
|
||||
replies: z.lazy(() => z.array(ThoughtThreadSchema)),
|
||||
});
|
||||
|
||||
export type User = z.infer<typeof UserSchema>;
|
||||
export type Me = z.infer<typeof MeSchema>;
|
||||
export type Thought = z.infer<typeof ThoughtSchema>;
|
||||
@@ -91,6 +109,7 @@ export type Register = z.infer<typeof RegisterSchema>;
|
||||
export type Login = z.infer<typeof LoginSchema>;
|
||||
export type ApiKey = z.infer<typeof ApiKeySchema>;
|
||||
export type ApiKeyResponse = z.infer<typeof ApiKeyResponseSchema>;
|
||||
export type ThoughtThread = z.infer<typeof ThoughtThreadSchema>;
|
||||
|
||||
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8000";
|
||||
|
||||
@@ -294,4 +313,7 @@ export const deleteApiKey = (keyId: string, token: string) =>
|
||||
{ method: "DELETE" },
|
||||
z.null(),
|
||||
token
|
||||
);
|
||||
);
|
||||
|
||||
export const getThoughtThread = (thoughtId: string, token: string | null) =>
|
||||
apiFetch(`/thoughts/${thoughtId}/thread`, {}, ThoughtThreadSchema, token);
|
@@ -1,35 +1,39 @@
|
||||
import { clsx, type ClassValue } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
import { Thought } from "./api";
|
||||
import { Thought, ThoughtThread as ThoughtThreadType } from "./api";
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
|
||||
export function buildThoughtThreads(allThoughts: Thought[]) {
|
||||
const repliesByParentId = new Map<string, Thought[]>();
|
||||
const topLevelThoughts: Thought[] = [];
|
||||
export function buildThoughtThreads(thoughts: Thought[]): ThoughtThreadType[] {
|
||||
const thoughtMap = new Map<string, Thought>();
|
||||
thoughts.forEach((t) => thoughtMap.set(t.id, t));
|
||||
|
||||
// 1. Group all thoughts into top-level posts or replies
|
||||
for (const thought of allThoughts) {
|
||||
const threads: ThoughtThreadType[] = [];
|
||||
const repliesMap: Record<string, Thought[]> = {};
|
||||
|
||||
thoughts.forEach((thought) => {
|
||||
if (thought.replyToId) {
|
||||
// It's a reply, group it with its parent
|
||||
const replies = repliesByParentId.get(thought.replyToId) || [];
|
||||
replies.push(thought);
|
||||
repliesByParentId.set(thought.replyToId, replies);
|
||||
} else {
|
||||
// It's a top-level thought
|
||||
topLevelThoughts.push(thought);
|
||||
if (!repliesMap[thought.replyToId]) {
|
||||
repliesMap[thought.replyToId] = [];
|
||||
}
|
||||
repliesMap[thought.replyToId].push(thought);
|
||||
}
|
||||
});
|
||||
|
||||
function buildThread(thought: Thought): ThoughtThreadType {
|
||||
return {
|
||||
...thought,
|
||||
replies: (repliesMap[thought.id] || []).map(buildThread),
|
||||
};
|
||||
}
|
||||
|
||||
// 2. Sort top-level thoughts by date, newest first
|
||||
topLevelThoughts.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
|
||||
thoughts.forEach((thought) => {
|
||||
if (!thought.replyToId) {
|
||||
threads.push(buildThread(thought));
|
||||
}
|
||||
});
|
||||
|
||||
// 3. Sort replies within each thread by date, oldest first for conversational flow
|
||||
for (const replies of repliesByParentId.values()) {
|
||||
replies.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
|
||||
}
|
||||
|
||||
return { topLevelThoughts, repliesByParentId };
|
||||
return threads;
|
||||
}
|
Reference in New Issue
Block a user