sync: phase 1 backend + frontend from server

This commit is contained in:
2026-06-30 09:26:03 -04:00
parent d4cdd89544
commit 30e159cbdb
31 changed files with 4758 additions and 114 deletions
+63
View File
@@ -0,0 +1,63 @@
import { useEffect, useState } from "react";
import { useConversationStore } from "../stores/conversation.ts";
import { useAuthStore } from "../stores/auth.ts";
import { NewConversationModal } from "./NewConversationModal.tsx";
function otherMemberName(conv: { members: { id: string; username: string }[] }, currentUserId: string) {
const other = conv.members.find((m) => m.id !== currentUserId);
return other?.username || "unknown";
}
export function ConversationList() {
const conversations = useConversationStore((s) => s.conversations);
const activeId = useConversationStore((s) => s.activeConversationId);
const fetchConversations = useConversationStore((s) => s.fetchConversations);
const setActive = useConversationStore((s) => s.setActiveConversation);
const currentUser = useAuthStore((s) => s.user);
const [showNew, setShowNew] = useState(false);
useEffect(() => {
fetchConversations();
}, [fetchConversations]);
return (
<div className="h-full w-56 bg-gb-bg-s border-r border-gb-bg-t flex flex-col">
<div className="terminal-border border-t-0 border-x-0 px-3 py-2 text-gb-fg truncate flex items-center justify-between">
<span>[DIRECT MESSAGES]</span>
<button
onClick={() => setShowNew(true)}
className="terminal-button text-xs"
title="New conversation"
>
[+]
</button>
</div>
<div className="flex-1 overflow-y-auto p-2 font-mono text-sm">
{conversations.length === 0 && (
<p className="text-gb-fg-f">[no conversations]</p>
)}
{conversations.map((conv) => {
const name =
conv.type === "group_dm"
? conv.name || conv.members.map((m) => m.username).join(", ")
: otherMemberName(conv, currentUser?.id || "");
return (
<button
key={conv.id}
onClick={() => setActive(conv.id)}
className={`w-full text-left px-2 py-1 rounded-sm flex items-center gap-2 ${
conv.id === activeId
? "terminal-active"
: "hover:bg-gb-bg-t text-gb-fg-s"
}`}
>
<span className="text-gb-fg-f">@</span>
<span className="truncate">{name}</span>
</button>
);
})}
</div>
{showNew && <NewConversationModal onClose={() => setShowNew(false)} />}
</div>
);
}