Skip to content
This repository was archived by the owner on Oct 14, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clients/web/app/(auth)/sign-in/SignInForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export default function SignInForm() {
};

return (
<Card className="min-w-80">
<Card className="max-w-80 w-full">
<CardHeader>
<h1 className="font-semibold text-xl">Sign in</h1>
</CardHeader>
Expand Down
8 changes: 6 additions & 2 deletions clients/web/app/(auth)/sign-in/actions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use server";

import { LOGIN_COOKIE_KEY } from "@/lib/constants";
import { EMAIL_COOKIE_KEY, LOGIN_COOKIE_KEY } from "@/lib/constants";
import { getApiClient } from "@/lib/sesameApiClient";
import { cookies } from "next/headers";

Expand All @@ -15,8 +15,12 @@ export async function login(email: string, password: string) {
});
if (ok && data.token) {
const cookiez = await cookies();
const expires = Date.now() + 259200000;
cookiez.set(LOGIN_COOKIE_KEY, data.token, {
expires: Date.now() + 259200000,
expires,
});
cookiez.set(EMAIL_COOKIE_KEY, email, {
expires,
});
return true;
}
Expand Down
22 changes: 21 additions & 1 deletion clients/web/app/(auth)/sign-in/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
import SignInForm from "@/app/(auth)/sign-in/SignInForm";
import Logo from "@/components/svg/Logo";

const drops = [0, 1, 2, 3];

export default function SignInPage() {
return <SignInForm />;
return (
<div className="h-dvh w-dvw md:grid md:grid-cols-2">
<div className="bg-foreground flex items-start justify-start p-8">
<div className="bg-primary brightness-95 aspect-square grid grid-cols-3 grid-rows-3 gap-2 rounded-lg p-4">
{drops.map((k) => (
<Logo key={k} className="block text-background rotate-12 w-5 h-5" />
))}
<Logo className="block text-primary brightness-125 -rotate-12 w-5 h-5" />
{drops.map((k) => (
<Logo key={drops.length + k} className="block text-background rotate-12 w-5 h-5" />
))}
</div>
</div>
<div className="bg-background flex items-center justify-center p-8 overflow-hidden">
<SignInForm />
</div>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ const ConversationList = ({
acc[group].push(conversation);
return acc;
},
{}
{},
);

const hasConversations = Object.keys(groupedConversations).length > 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export default function ConversationListItem({
{
"bg-secondary-foreground/[.05] font-medium": isActive,
"hover:bg-input": !isEditing,
}
},
)}
>
{isEditing ? (
Expand Down Expand Up @@ -150,7 +150,7 @@ export default function ConversationListItem({
<>
<PageTransitionLink
href={`/${workspaceId}/c/${conversation.conversation_id}`}
className="text-base flex-grow px-3 py-2 text-ellipsis text-nowrap overflow-hidden w-full"
className="text-base flex-grow px-3 py-2 text-ellipsis text-nowrap overflow-hidden w-full focus-visible:outline-primary focus-visible:outline-1"
onClick={onClick}
>
{title}
Expand All @@ -162,7 +162,7 @@ export default function ConversationListItem({
"shrink-0 text-foreground/50 group-hover:visible group-focus-within:visible aria-expanded:visible hover:bg-transparent hover:text-foreground",
{
invisible: !isActive,
}
},
)}
size="icon"
variant="ghost"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export default function DeleteConversationModal({
};

const conversation = conversations.find(
(c) => c.conversation_id === conversationId
(c) => c.conversation_id === conversationId,
);

return (
Expand Down
38 changes: 26 additions & 12 deletions clients/web/app/(authenticated)/[workspaceId]/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
"use client";

import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Button } from "@/components/ui/button";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import emitter from "@/lib/eventEmitter";
import { LLMModel } from "@/lib/llm";
import { Menu, Settings2 } from "lucide-react";
Expand All @@ -22,7 +29,7 @@ const Navbar: React.FC<NavbarProps> = ({ currentModelValue, models }) => {

const [selectedModel, setSelectedModel] = useState(currentModelValue);

const currentModel = models.find(m => m.model === selectedModel);
const currentModel = models.find((m) => m.model === selectedModel);

return (
<div className="bg-background flex items-center justify-between p-4 sticky top-0 z-10">
Expand All @@ -34,27 +41,34 @@ const Navbar: React.FC<NavbarProps> = ({ currentModelValue, models }) => {
<Menu className="w-6 h-6" />
</button>

<Select value={selectedModel} onValueChange={(v) => {
setSelectedModel(v);
emitter.emit("changeLlmModel", v);
}}>
<SelectTrigger className="font-semibold max-w-fit">
<Select
value={selectedModel}
onValueChange={(v) => {
setSelectedModel(v);
emitter.emit("changeLlmModel", v);
}}
>
<SelectTrigger className="text-base font-semibold max-w-fit rounded-full border-background shadow-none text-muted transition-all">
<SelectValue>{currentModel?.label}</SelectValue>
</SelectTrigger>
<SelectContent>
{models.map((m) => (
<SelectItem key={m.model} value={m.model}>{m.label}</SelectItem>
<SelectItem key={m.model} value={m.model}>
{m.label}
</SelectItem>
))}
</SelectContent>
</Select>

{/* Settings Icon */}
<button
className="p-2 rounded-md hover:bg-secondary focus:outline-none ms-auto"
<Button
variant="outline"
className="rounded-full ms-auto gap-1"
onClick={handleSettingsToggle}
>
<Settings2 className="w-6 h-6" />
</button>
<Settings2 size={16} />
Settings
</Button>
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const SearchResults = memo(
workspaceId={workspaceId}
/>
);
}
},
);
SearchResults.displayName = "SearchResults";

Expand Down
63 changes: 29 additions & 34 deletions clients/web/app/(authenticated)/[workspaceId]/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
"use client";

import UserMenu from "@/app/(authenticated)/[workspaceId]/UserMenu";
import PageTransitionLink from "@/components/PageTransitionLink";
import QueryClientProvider, {
queryClient,
} from "@/components/QueryClientProvider";
import SignOutButton from "@/components/SignOutButton";
import { Input } from "@/components/ui/input";
import { Separator } from "@/components/ui/separator";
import {
Expand All @@ -16,7 +16,7 @@ import {
import emitter from "@/lib/eventEmitter";
import { ConversationModel, WorkspaceModel } from "@/lib/sesameApi";
import { cn } from "@/lib/utils";
import { Edit, LoaderCircleIcon } from "lucide-react";
import { EditIcon, LoaderCircleIcon } from "lucide-react";
import { usePathname, useRouter } from "next/navigation";
import {
Suspense,
Expand All @@ -27,17 +27,19 @@ import {
} from "react";
import ConversationList from "./ConversationList";
import SearchResults from "./SearchResults";
import SidebarTitle from "./SidebarTitle";
import WorkspaceMenu from "./WorkspaceMenu";

interface SidebarProps {
conversations: ConversationModel[];
email?: string;
signOut?: boolean;
workspace?: WorkspaceModel | null;
workspaces?: WorkspaceModel[];
}

export default function Sidebar({
conversations,
email,
signOut = false,
workspace,
workspaces = [],
Expand Down Expand Up @@ -89,22 +91,18 @@ export default function Sidebar({
<PageTransitionLink
href={`/${workspace.workspace_id}`}
className={cn(
"flex items-center gap-3 px-3 py-2 rounded-lg transition-colors hover:bg-secondary-foreground/[.05]",
{
"bg-input": pathname === `/${workspace.workspace_id}`,
}
"flex items-center justify-center gap-3 px-3 py-2 rounded-full bg-transparent border border-input transition-colors text-base font-semibold hover:bg-secondary-foreground/[.05] focus-visible:bg-secondary-foreground/[.05] focus-visible:outline-primary",
)}
onClick={() => setIsOpen(false)}
>
<Edit size={21} />
New chat
<EditIcon size={24} />
New conversation
</PageTransitionLink>
)}
</div>

<Separator />

<Input
className="bg-background shadow-none border-none"
type="search"
placeholder="Search conversations…"
value={search}
Expand Down Expand Up @@ -134,9 +132,20 @@ export default function Sidebar({
) : null}
</QueryClientProvider>

{signOut && (
<SignOutButton className="sticky bottom-0 z-10 mt-auto">Sign out</SignOutButton>
)}
<div className="mt-auto sticky bottom-0 flex flex-col gap-4">
<WorkspaceMenu
className="bg-inherit mt-auto"
workspace={workspace}
workspaces={workspaces}
/>

{signOut && (
<>
<Separator />
<UserMenu email={email ?? "My account"} />
</>
)}
</div>
</>
);

Expand All @@ -146,32 +155,18 @@ export default function Sidebar({
<div className="lg:hidden">
<Sheet open={isOpen} onOpenChange={setIsOpen}>
<SheetContent side="left" className="overflow-y-auto">
<SheetTitle asChild>
<SidebarTitle
className="bg-background -top-4"
onSwitchWorkspace={() => {
setIsOpen(false);
}}
workspace={workspace}
workspaces={workspaces}
/>
</SheetTitle>
<SheetDescription></SheetDescription>
<div className="flex flex-col gap-6 p-4 min-h-full">{content}</div>
<SheetTitle className="sr-only">Navigation</SheetTitle>
<SheetDescription className="absolute"></SheetDescription>
<div className="flex flex-col gap-6 p-4 pt-12 min-h-full">
{content}
</div>
</SheetContent>
</Sheet>
</div>

{/* Desktop Sidebar */}
<div className="hidden lg:block lg:w-[var(--sidebar-width)] bg-secondary sticky top-0 overflow-y-auto h-dvh">
<div className="flex flex-col gap-6 p-4 min-h-full">
<SidebarTitle
className="bg-secondary"
workspace={workspace}
workspaces={workspaces}
/>
{content}
</div>
<div className="flex flex-col gap-6 p-4 pt-5 h-dvh">{content}</div>
</div>
</>
);
Expand Down
51 changes: 51 additions & 0 deletions clients/web/app/(authenticated)/[workspaceId]/UserMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"use client";

import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { EMAIL_COOKIE_KEY, LOGIN_COOKIE_KEY } from "@/lib/constants";
import { LogOutIcon } from "lucide-react";
import { useRouter } from "next/navigation";
import Gravatar from "react-gravatar";

interface UserMenuProps {
className?: string;
email?: string;
}

const UserMenu = ({ className, email = "My account" }: UserMenuProps) => {
const { push } = useRouter();

const handleSignout = () => {
document.cookie = `${LOGIN_COOKIE_KEY}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;
document.cookie = `${EMAIL_COOKIE_KEY}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;
push("/sign-in");
};

return (
<div className={className}>
<DropdownMenu>
<DropdownMenuTrigger className="group rounded-full flex gap-2 items-center w-full overflow-hidden hover:bg-secondary-foreground/[.05] focus-visible:bg-secondary-foreground/[.05] transition-colors">
<Gravatar email={email} size={32} className="rounded-full" />
<span className="flex-grow overflow-hidden text-ellipsis text-start">
{email}
</span>
</DropdownMenuTrigger>
<DropdownMenuContent align="start" className="w-64">
<DropdownMenuItem
onClick={handleSignout}
className="flex items-center justify-between gap-4 w-full"
>
Sign out
<LogOutIcon size={16} />
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
);
};

export default UserMenu;
Loading
Loading