Skip to content

Commit 17486fb

Browse files
committed
feat: update Next.js configuration and dependencies, add CommandSelect component
- Enabled typedRoutes in next.config.ts - Updated dependencies in package.json: better-auth (1.4.9), next (16.1.1), nuqs (2.8.6) - Introduced CommandSelect component for enhanced option selection with search functionality - Refactored GenerateAvatar component to export correctly - Updated various components to utilize the new CommandSelect and refactored imports for GenerateAvatar - Modified agent form to include agent selection using CommandSelect - Removed instructions field from meetingsInsertSchema
1 parent 9df2e4b commit 17486fb

14 files changed

Lines changed: 417 additions & 255 deletions

File tree

bun.lock

Lines changed: 169 additions & 209 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

next.config.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ import type { NextConfig } from "next";
22

33
const nextConfig: NextConfig = {
44
cacheComponents: true,
5+
typedRoutes: true,
56
compiler: {
67
removeConsole: process.env.NODE_ENV === "production",
78
},
8-
reactCompiler: true,
9-
output: "standalone",
109
experimental: {
11-
turbopackFileSystemCacheForDev: true,
10+
browserDebugInfoInTerminal: true,
1211
},
12+
reactCompiler: true,
13+
// output: "standalone",
1314
};
1415

1516
export default nextConfig;

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
"@trpc/server": "^11.8.1",
5252
"@trpc/tanstack-react-query": "^11.8.1",
5353
"babel-plugin-react-compiler": "^1.0.0",
54-
"better-auth": "^1.4.7",
54+
"better-auth": "^1.4.9",
5555
"class-variance-authority": "^0.7.1",
5656
"client-only": "^0.0.1",
5757
"clsx": "^2.1.1",
@@ -63,9 +63,9 @@
6363
"input-otp": "^1.4.2",
6464
"lucide-react": "^0.546.0",
6565
"nanoid": "^5.1.6",
66-
"next": "^16.1.0",
66+
"next": "^16.1.1",
6767
"next-themes": "^0.4.6",
68-
"nuqs": "^2.8.5",
68+
"nuqs": "^2.8.6",
6969
"react": "^19.2.3",
7070
"react-day-picker": "^9.13.0",
7171
"react-dom": "^19.2.3",

src/components/command-select.tsx

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { cn } from "@/lib/utils";
2+
import { ChevronsDownIcon } from "lucide-react";
3+
import { ReactNode, useState } from "react";
4+
import { Button } from "./ui/button";
5+
import {
6+
CommandEmpty,
7+
CommandInput,
8+
CommandItem,
9+
CommandList,
10+
CommandResponsiveDialog,
11+
} from "./ui/command";
12+
13+
interface Props {
14+
options: Array<{
15+
id: string;
16+
value: string;
17+
children: ReactNode;
18+
}>;
19+
onSelect: (value: string) => void;
20+
onSearch?: (query: string) => void;
21+
value: string;
22+
placeholder?: string;
23+
isSearchable?: boolean;
24+
className?: string;
25+
}
26+
27+
export const CommandSelect = ({
28+
options,
29+
onSelect,
30+
onSearch,
31+
value,
32+
placeholder = "Select an option...",
33+
isSearchable = false,
34+
className = "",
35+
}: Props) => {
36+
const [open, setOpen] = useState(false);
37+
const selectedOption = options.find((option) => option.value === value);
38+
39+
return (
40+
<>
41+
<Button
42+
onClick={() => setOpen(true)}
43+
type="button"
44+
variant="outline"
45+
className={cn(
46+
"h-9 justify-between font-normal px-2",
47+
!selectedOption && "text-muted-foreground",
48+
className
49+
)}
50+
>
51+
<div>{selectedOption ? selectedOption.children : placeholder}</div>
52+
<ChevronsDownIcon />
53+
</Button>
54+
<CommandResponsiveDialog open={open} onOpenChange={setOpen}>
55+
<CommandInput placeholder="Search..." />
56+
<CommandList>
57+
<CommandEmpty>
58+
<span className="text-muted-foreground text-sm">No options found.</span>
59+
</CommandEmpty>
60+
{options.map((option) => (
61+
<CommandItem
62+
key={option.id}
63+
onSelect={() => {
64+
onSelect(option.value);
65+
setOpen(false);
66+
}}
67+
>
68+
{option.children}
69+
</CommandItem>
70+
))}
71+
</CommandList>
72+
</CommandResponsiveDialog>
73+
</>
74+
);
75+
};

src/components/generate-avatar.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ interface GenerateAvatarProps {
1010
variant: "botttsNeutral" | "initials";
1111
}
1212

13-
const GenerateAvatar = ({ seed, className, variant }: GenerateAvatarProps) => {
13+
export const GenerateAvatar = ({ seed, className, variant }: GenerateAvatarProps) => {
1414
let avatar: ReturnType<typeof createAvatar>;
1515

1616
if (variant === "botttsNeutral") {
@@ -32,5 +32,3 @@ const GenerateAvatar = ({ seed, className, variant }: GenerateAvatarProps) => {
3232
</Avatar>
3333
);
3434
};
35-
36-
export default GenerateAvatar;

src/components/ui/command.tsx

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,13 @@ import {
1313
} from "@/components/ui/dialog";
1414
import { useIsMobile } from "@/hooks/use-mobile";
1515
import { cn } from "@/lib/utils";
16-
import { Drawer, DrawerContent, DrawerDescription, DrawerHeader, DrawerTitle } from "./drawer";
16+
import {
17+
Drawer,
18+
DrawerContent,
19+
DrawerDescription,
20+
DrawerHeader,
21+
DrawerTitle,
22+
} from "./drawer";
1723

1824
function Command({ className, ...props }: React.ComponentProps<typeof CommandPrimitive>) {
1925
return (
@@ -47,7 +53,10 @@ function CommandDialog({
4753
<DialogTitle>{title}</DialogTitle>
4854
<DialogDescription>{description}</DialogDescription>
4955
</DialogHeader>
50-
<DialogContent className={cn("overflow-hidden p-0", className)} showCloseButton={showCloseButton}>
56+
<DialogContent
57+
className={cn("overflow-hidden p-0", className)}
58+
showCloseButton={showCloseButton}
59+
>
5160
<Command className="[&_[cmdk-group-heading]]:text-muted-foreground **:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
5261
{children}
5362
</Command>
@@ -60,10 +69,12 @@ function CommandResponsiveDialog({
6069
title = "Command Palette",
6170
description = "Search for a command to run...",
6271
children,
72+
shouldFilter = true,
6373
...props
6474
}: React.ComponentProps<typeof Dialog> & {
6575
title?: string;
6676
description?: string;
77+
shouldFilter?: boolean;
6778
}) {
6879
const isMobile = useIsMobile();
6980

@@ -75,7 +86,10 @@ function CommandResponsiveDialog({
7586
<DrawerTitle>{title}</DrawerTitle>
7687
<DrawerDescription>{description}</DrawerDescription>
7788
</DrawerHeader>
78-
<Command className="[&_[cmdk-group-heading]]:text-muted-foreground **:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
89+
<Command
90+
shouldFilter={shouldFilter}
91+
className="[&_[cmdk-group-heading]]:text-muted-foreground **:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5"
92+
>
7993
{children}
8094
</Command>
8195
</DrawerContent>
@@ -90,17 +104,26 @@ function CommandResponsiveDialog({
90104
<DialogDescription>{description}</DialogDescription>
91105
</DialogHeader>
92106
<DialogContent className="overflow-hidden p-0">
93-
<Command className="[&_[cmdk-group-heading]]:text-muted-foreground **:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
107+
<Command
108+
shouldFilter={shouldFilter}
109+
className="[&_[cmdk-group-heading]]:text-muted-foreground **:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5"
110+
>
94111
{children}
95112
</Command>
96113
</DialogContent>
97114
</Dialog>
98115
);
99116
}
100117

101-
function CommandInput({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Input>) {
118+
function CommandInput({
119+
className,
120+
...props
121+
}: React.ComponentProps<typeof CommandPrimitive.Input>) {
102122
return (
103-
<div data-slot="command-input-wrapper" className="flex h-9 items-center gap-2 border-b px-3">
123+
<div
124+
data-slot="command-input-wrapper"
125+
className="flex h-9 items-center gap-2 border-b px-3"
126+
>
104127
<SearchIcon className="size-4 shrink-0 opacity-50" />
105128
<CommandPrimitive.Input
106129
data-slot="command-input"
@@ -114,23 +137,36 @@ function CommandInput({ className, ...props }: React.ComponentProps<typeof Comma
114137
);
115138
}
116139

117-
function CommandList({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.List>) {
140+
function CommandList({
141+
className,
142+
...props
143+
}: React.ComponentProps<typeof CommandPrimitive.List>) {
118144
return (
119145
<CommandPrimitive.List
120146
data-slot="command-list"
121-
className={cn("max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto", className)}
147+
className={cn(
148+
"max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto",
149+
className
150+
)}
122151
{...props}
123152
/>
124153
);
125154
}
126155

127156
function CommandEmpty({ ...props }: React.ComponentProps<typeof CommandPrimitive.Empty>) {
128157
return (
129-
<CommandPrimitive.Empty data-slot="command-empty" className="py-6 text-center text-sm" {...props} />
158+
<CommandPrimitive.Empty
159+
data-slot="command-empty"
160+
className="py-6 text-center text-sm"
161+
{...props}
162+
/>
130163
);
131164
}
132165

133-
function CommandGroup({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Group>) {
166+
function CommandGroup({
167+
className,
168+
...props
169+
}: React.ComponentProps<typeof CommandPrimitive.Group>) {
134170
return (
135171
<CommandPrimitive.Group
136172
data-slot="command-group"
@@ -156,7 +192,10 @@ function CommandSeparator({
156192
);
157193
}
158194

159-
function CommandItem({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Item>) {
195+
function CommandItem({
196+
className,
197+
...props
198+
}: React.ComponentProps<typeof CommandPrimitive.Item>) {
160199
return (
161200
<CommandPrimitive.Item
162201
data-slot="command-item"

src/modules/agents/ui/components/agent-form.tsx

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
1-
import GenerateAvatar from "@/components/generate-avatar";
1+
import { GenerateAvatar } from "@/components/generate-avatar";
22
import { Button } from "@/components/ui/button";
3-
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
3+
import {
4+
Form,
5+
FormControl,
6+
FormField,
7+
FormItem,
8+
FormLabel,
9+
FormMessage,
10+
} from "@/components/ui/form";
411
import { Input } from "@/components/ui/input";
512
import { Textarea } from "@/components/ui/textarea";
613
import { useTRPC } from "@/trpc/client";
@@ -44,7 +51,9 @@ export const AgentForm = ({ onSuccess, onCancel, initialValues }: AgentFormProps
4451
await queryClient.invalidateQueries(trpc.agents.getMany.queryOptions({}));
4552

4653
if (initialValues?.id) {
47-
await queryClient.invalidateQueries(trpc.agents.getOne.queryOptions({ id: initialValues.id }));
54+
await queryClient.invalidateQueries(
55+
trpc.agents.getOne.queryOptions({ id: initialValues.id })
56+
);
4857
}
4958

5059
onSuccess?.();
@@ -88,7 +97,11 @@ export const AgentForm = ({ onSuccess, onCancel, initialValues }: AgentFormProps
8897
return (
8998
<Form {...form}>
9099
<form className="space-y-4" onSubmit={form.handleSubmit(onSubmit)}>
91-
<GenerateAvatar seed={form.watch("name")} variant="botttsNeutral" className="border size-16" />
100+
<GenerateAvatar
101+
seed={form.watch("name")}
102+
variant="botttsNeutral"
103+
className="border size-16"
104+
/>
92105
<FormField
93106
name="name"
94107
control={form.control}

src/modules/agents/ui/components/columns.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use client";
22

3-
import GenerateAvatar from "@/components/generate-avatar";
3+
import { GenerateAvatar } from "@/components/generate-avatar";
44
import { Badge } from "@/components/ui/badge";
55
import { ColumnDef } from "@tanstack/react-table";
66
import { CornerDownRightIcon, VideoIcon } from "lucide-react";
@@ -42,10 +42,7 @@ export const columns: ColumnDef<AgentGetOne>[] = [
4242
accessorKey: "meetingCount",
4343
header: "Meetings",
4444
cell: ({ row }) => (
45-
<Badge
46-
variant="outline"
47-
className="flex items-center gap-x-2 [&>svg]:size-4"
48-
>
45+
<Badge variant="outline" className="flex items-center gap-x-2 [&>svg]:size-4">
4946
<VideoIcon className="text-blue-700" />
5047
{row.original.meetingCount}{" "}
5148
{row.original.meetingCount > 1 ? "meetings" : "meeting"}

src/modules/agents/ui/views/agent-id-view.tsx

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"use client";
22

33
import { ErrorState } from "@/components/error-state";
4-
import GenerateAvatar from "@/components/generate-avatar";
4+
import { GenerateAvatar } from "@/components/generate-avatar";
55
import { LoadingState } from "@/components/loading-state";
66
import { Badge } from "@/components/ui/badge";
77
import { useConfirm } from "@/hooks/use-confirm";
@@ -68,10 +68,17 @@ export const AgentIdView = ({ agentId }: Props) => {
6868
<div className="bg-white rounded-lg border">
6969
<div className="px-4 py-5 gap-y-5 flex flex-col col-span-5">
7070
<div className="flex items-center gap-x-3">
71-
<GenerateAvatar variant="botttsNeutral" seed={data.name} className="size-10" />
71+
<GenerateAvatar
72+
variant="botttsNeutral"
73+
seed={data.name}
74+
className="size-10"
75+
/>
7276
<h2 className="text-2xl font-medium">{data.name}</h2>
7377
</div>
74-
<Badge className="flex items-center gap-x-2 [&>svg]:size-4" variant={"outline"}>
78+
<Badge
79+
className="flex items-center gap-x-2 [&>svg]:size-4"
80+
variant={"outline"}
81+
>
7582
<VideoIcon className="text-blue-700" />
7683
{data.meetingCount}
7784
{data.meetingCount === 1 ? "Meeting" : "Meetings"}
@@ -88,7 +95,9 @@ export const AgentIdView = ({ agentId }: Props) => {
8895
};
8996

9097
export const AgentsIdViewLoading = () => {
91-
return <LoadingState title="Loading Agents" description="This may take a few seconds" />;
98+
return (
99+
<LoadingState title="Loading Agents" description="This may take a few seconds" />
100+
);
92101
};
93102

94103
export const AgentsIdViewError = () => {

0 commit comments

Comments
 (0)