Skip to content

Commit

Permalink
added channels, members in schema and in workspace sidebar, added sid…
Browse files Browse the repository at this point in the history
…ebar-item
  • Loading branch information
Diivvuu committed Oct 7, 2024
1 parent c9eb207 commit 108394d
Show file tree
Hide file tree
Showing 13 changed files with 241 additions and 2 deletions.
Binary file modified bun.lockb
Binary file not shown.
2 changes: 2 additions & 0 deletions convex/_generated/api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type {
FunctionReference,
} from "convex/server";
import type * as auth from "../auth.js";
import type * as channels from "../channels.js";
import type * as http from "../http.js";
import type * as members from "../members.js";
import type * as users from "../users.js";
Expand All @@ -31,6 +32,7 @@ import type * as workspaces from "../workspaces.js";
*/
declare const fullApi: ApiFromModules<{
auth: typeof auth;
channels: typeof channels;
http: typeof http;
members: typeof members;
users: typeof users;
Expand Down
31 changes: 31 additions & 0 deletions convex/channels.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { getAuthUserId } from "@convex-dev/auth/server";
import { query } from "./_generated/server";
import { v } from "convex/values";

export const get = query({
args: {
workspaceId: v.id("workspaces"),
},
handler: async (ctx, args) => {
const userId = await getAuthUserId(ctx);
if (!userId) return [];

const member = await ctx.db
.query("members")
.withIndex("by_workspace_id_user_id", (q) =>
q.eq("workspaceId", args.workspaceId).eq("userId", userId)
)
.unique();

if (!member) return [];

const channels = await ctx.db
.query("channels")
.withIndex("by_workspace_id", (q) =>
q.eq("workspaceId", args.workspaceId)
)
.collect();

return channels;
},
});
46 changes: 45 additions & 1 deletion convex/members.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,50 @@
import { v } from "convex/values";
import { query } from "./_generated/server";
import { query, QueryCtx } from "./_generated/server";
import { getAuthUserId } from "@convex-dev/auth/server";
import { Id } from "./_generated/dataModel";

const populateUser = (ctx: QueryCtx, id: Id<"users">) => {
return ctx.db.get(id);
};

export const get = query({
args: { workspaceId: v.id("workspaces") },
handler: async (ctx, args) => {
const userId = await getAuthUserId(ctx);

if (!userId) return [];

const member = await ctx.db
.query("members")
.withIndex("by_workspace_id_user_id", (q) =>
q.eq("workspaceId", args.workspaceId).eq("userId", userId)
)
.unique();

if (!member) return [];

const data = await ctx.db
.query("members")
.withIndex("by_workspace_id", (q) =>
q.eq("workspaceId", args.workspaceId)
)
.collect();

const members = [];

for (const member of data) {
const user = await populateUser(ctx, member.userId);

if (user) {
members.push({
...member,
user,
});
}
}
return members;
},
});

export const current = query({
args: { workspaceId: v.id("workspaces") },
Expand Down
4 changes: 4 additions & 0 deletions convex/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ const schema = defineSchema({
.index("by_user_id", ["userId"])
.index("by_workspace_id", ["workspaceId"])
.index("by_workspace_id_user_id", ["workspaceId", "userId"]),
channels: defineTable({
name: v.string(),
workspaceId: v.id("workspaces"),
}).index("by_workspace_id", ["workspaceId"]),
});

export default schema;
4 changes: 4 additions & 0 deletions convex/workspaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ export const create = mutation({
role: "admin",
});

await ctx.db.insert("channels", {
name: "general",
workspaceId,
});
return workspaceId;
},
});
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"react-dom": "^18",
"react-icons": "^5.3.0",
"react-resizable-panels": "^2.1.4",
"react-use": "^17.5.1",
"shadcn": "^2.1.0",
"shadcn-ui": "^0.9.0",
"sonner": "^1.5.0",
Expand Down
52 changes: 52 additions & 0 deletions src/app/workspace/[workspaceId]/sidebar-item.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import Link from "next/link";
import { cva, type VariantProps } from "class-variance-authority";
import { useWorkspaceId } from "@/hooks/use-workspace-id";

import { Button } from "@/components/ui/button";
import { LucideIcon } from "lucide-react";
import { IconType } from "react-icons/lib";
import { cn } from "@/lib/utils";

const SidebarItemVariants = cva(
"flex items-center gap-1.5 justify-start font-normal h-7 px-[18px] text-sm overflow-hidden",
{
variants: {
variant: {
default: "text-[#f9edffcc]",
active: "text-[#481349] bg-white/90",
},
},
defaultVariants: {
variant: "default",
},
}
);

interface SidebarItemProps {
label: string;
id: string;
icon: LucideIcon | IconType;
variant?: VariantProps<typeof SidebarItemVariants>["variant"];
}

export const SidebarItem = ({
label,
id,
icon: Icon,
variant,
}: SidebarItemProps) => {
const workspaceId = useWorkspaceId();
return (
<Button
variant="transparent"
size="sm"
asChild
className={cn(SidebarItemVariants({ variant }))}
>
<Link href={`/workspace/${workspaceId}/channel/${id}`}>
<Icon className="size-3.5 mr-1 shrink-0" />
<span className="text-sm truncate">{label}</span>
</Link>
</Button>
);
};
56 changes: 56 additions & 0 deletions src/app/workspace/[workspaceId]/workspace-section.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { Hint } from "@/components/hint";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import { PlusIcon } from "lucide-react";
import { FaCaretDown } from "react-icons/fa";
import { useToggle } from "react-use";
interface WorkspaceSectionProps {
children: React.ReactNode;
label: string;
hint: string;
onNew?: () => void;
}

export const WorkspaceSection = ({
children,
label,
hint,
onNew,
}: WorkspaceSectionProps) => {
const [on, toggle] = useToggle(true);
return (
<div className="flex flex-col mt-3 px-2">
<div className="flex items-center px-3.5 group">
<Button
variant="transparent"
className="p-0.5 text-sm text-[#f9edffcc] shrink-0 size-6"
onClick={toggle}
>
<FaCaretDown
className={cn("size-4 transition-transform", on && "-rotate-90")}
/>
</Button>
<Button
variant="transparent"
size="sm"
className="group px-1.5 text-[#f9edffcc] h-[28px] justify-start items-center overflow-hidden"
>
<span className="truncate">{label}</span>
</Button>
{onNew && (
<Hint label={hint} side="top" align="center">
<Button
onClick={onNew}
variant="transparent"
size="iconSm"
className="opacity-0 group-hover:opacity-100 transition-opacity ml-auto p-0.5 text-sm text-[#f9edffcc] size-6 shrink-0"
>
<PlusIcon className="size-5" />
</Button>
</Hint>
)}
</div>
{on && children}
</div>
);
};
30 changes: 29 additions & 1 deletion src/app/workspace/[workspaceId]/workspace-sidebar.jsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
import { useCurrentMember } from "@/features/members/api/use-current-member";
import { useGetWorkspace } from "@/features/workspaces/api/use-get-workspace";
import { useWorkspaceId } from "@/hooks/use-workspace-id";
import { AlertTriangle, Loader } from "lucide-react";

import {
AlertTriangle,
HashIcon,
Loader,
MessageSquareText,
SendHorizonal,
} from "lucide-react";

import { WorkspaceHeader } from "./workspace-header";
import { SidebarItem } from "./sidebar-item";
import { useGetChannels } from "@/features/channels/api/use-get-channels";
import { WorkspaceSection } from "./workspace-section";

const WorkspaceSidebar = () => {
const workspaceId = useWorkspaceId();
Expand All @@ -12,6 +23,9 @@ const WorkspaceSidebar = () => {
const { data: workspace, isLoading: workspaceLoading } = useGetWorkspace({
id: workspaceId,
});
const { data: channels, isLoading: channelsLoading } = useGetChannels({
workspaceId,
});
if (workspaceLoading || memberLoading) {
return (
<div className="flex flex-col bg-[#5E2C5F] h-full items-center justify-center">
Expand All @@ -33,6 +47,20 @@ const WorkspaceSidebar = () => {
workspace={workspace}
isAdmin={member.role === "admin"}
/>
<div className="flex flex-col px-2 mt-3">
<SidebarItem label="Threads" icon={MessageSquareText} id="threads" />
<SidebarItem label="Drafts & Sent" icon={SendHorizonal} id="drafts" />
</div>
<WorkspaceSection label="Channels" hint="New Channel" onNew={() => {}}>
{channels?.map((item) => (
<SidebarItem
key={item._id}
icon={HashIcon}
label={item.name}
id={item._id}
/>
))}
</WorkspaceSection>
</div>
);
};
Expand Down
1 change: 1 addition & 0 deletions src/features/auth/components/sign-in-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export const SignInCard = ({ setState }: SignInCardProps) => {
};

const handleProviderSignIn = (value: "github" | "google") => {
console.log("clivked");
setPending(true);
signIn(value).finally(() => {
setPending(false);
Expand Down
15 changes: 15 additions & 0 deletions src/features/channels/api/use-get-channels.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { useQuery } from "convex/react";
import { api } from "../../../../convex/_generated/api";
import { Id } from "../../../../convex/_generated/dataModel";
import workSpaceId from "@/app/workspace/[workspaceId]/page";

interface UseGetChannelsProps {
workspaceId: Id<"workspaces">;
}

export const useGetChannels = ({ workspaceId }: UseGetChannelsProps) => {
const data = useQuery(api.channels.get, { workspaceId });
const isLoading = data === undefined;

return { data, isLoading };
};
1 change: 1 addition & 0 deletions src/features/channels/api/use-get-members.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// interface UseGetMemberProps = {}

0 comments on commit 108394d

Please sign in to comment.