Skip to content

Commit

Permalink
use server components for settings and members
Browse files Browse the repository at this point in the history
  • Loading branch information
IhsenBouallegue committed Oct 29, 2023
1 parent 449b0ce commit e02b25c
Show file tree
Hide file tree
Showing 13 changed files with 163 additions and 152 deletions.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import { ReactNode } from "react";

export default async function layout({
children,
}: { children: ReactNode | ReactNode[] }) {
params,
}: { children: ReactNode | ReactNode[]; params: { organizationId: string } }) {
const session = await auth();
const memberOrganizations = await db.query.organizations.findMany({
where: eq(organizations.admin, session?.user.id ?? ""),
Expand All @@ -20,13 +21,11 @@ export default async function layout({
<div className="hidden flex-col md:flex">
<div className="border-b">
<div className="flex h-16 items-center px-8">
<OrganizationSwitcher
memberOrganizations={memberOrganizations?.map((org) => ({
label: org.name,
value: org.id,
}))}
<OrganizationSwitcher memberOrganizations={memberOrganizations} />
<MainNav
className="mx-6"
selectedOrganization={params.organizationId}
/>
<MainNav className="mx-6" />
<div className="ml-auto flex items-center space-x-4">
<Search />
<UserNav />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
"use client";

import { Icons } from "@/components/icons";
import { useDashboardStore } from "@/lib/Store/dashboard";
import { User } from "@/lib/schema/auth";
import { UsersToOrganization } from "@/lib/schema/orgaizations";
import { API_URL } from "@/lib/useQueries";
import db from "@/lib/db";
import { organizations, usersToOrganizations } from "@/lib/schema/orgaizations";
import { Avatar, AvatarFallback, AvatarImage } from "@/ui/avatar";
import { Button } from "@/ui/button";
import {
Expand All @@ -15,27 +11,22 @@ import {
CardTitle,
} from "@/ui/card";
import { Popover, PopoverContent, PopoverTrigger } from "@/ui/popover";
import { useEffect, useState } from "react";
import { eq } from "drizzle-orm";
import RoleCommand from "./role-command";

export default function Members() {
const selectedOrganizationId = useDashboardStore(
(state) => state.selectedOrganizationId
);
const [members, setMembers] = useState<User[]>([]);

useEffect(() => {
fetch(
`${API_URL}/organization-members/?organizationId=${selectedOrganizationId}`
)
.then((res) => res.json())
.then(
({
organizationMembers,
}: { organizationMembers: (UsersToOrganization & { user: User })[] }) =>
setMembers(organizationMembers?.map((member) => member.user) ?? [])
);
}, [selectedOrganizationId]);
export default async function Members({
selectedOrganizationSlug,
}: { selectedOrganizationSlug: string }) {
const selectedOrgaization = await db.query.organizations.findFirst({
where: eq(organizations.slug, selectedOrganizationSlug),
});
if (!selectedOrgaization) return null;
const organizationMembers = await db.query.usersToOrganizations
.findMany({
where: eq(usersToOrganizations.organizationId, selectedOrgaization.id),
with: { user: true },
})
.then((res) => res.map((usersToOrganization) => usersToOrganization.user));

return (
<div className="space-y-6">
Expand All @@ -48,8 +39,8 @@ export default function Members() {
</CardHeader>
<CardContent className="grid gap-6">
<div className="flex items-center justify-between space-x-4">
{members.map((member) => (
<>
{organizationMembers.map((member) => (
<div key={member.id} className="w-full flex">
<div className="flex items-center space-x-4">
<Avatar>
<AvatarImage src={member.image ?? undefined} />
Expand All @@ -75,7 +66,7 @@ export default function Members() {
<RoleCommand />
</PopoverContent>
</Popover>
</>
</div>
))}
</div>
</CardContent>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Members from "./members";
import Settings from "./settings";

export default async function Page({
params,
}: { params: { organizationId: string } }) {
return (
<div className="max-w-screen-2xl m-auto space-y-12">
<h2 className="text-3xl font-bold">Organizations</h2>
<Members selectedOrganizationSlug={params.organizationId} />
<Settings selectedOrganizationSlug={params.organizationId} />
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import db from "@/lib/db";
import { organizations, usersToOrganizations } from "@/lib/schema/orgaizations";
import { Button } from "@/ui/button";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/ui/card";
import { and, eq } from "drizzle-orm";
import { redirect } from "next/navigation";
import { auth } from "../../../../../../auth";

export default function Settings({
selectedOrganizationSlug,
}: { selectedOrganizationSlug: string }) {
async function callAction() {
"use server";
const session = await auth();
if (!session) return;
await db
.delete(organizations)
.where(
and(
eq(organizations.slug, selectedOrganizationSlug),
eq(organizations.admin, session.user.id)
)
)
.then(
async () =>
await db
.delete(usersToOrganizations)
.where(
eq(usersToOrganizations.organizationId, selectedOrganizationSlug)
)
);
redirect("/dashboard");
}

return (
<Card>
<CardHeader>
<CardTitle className="text-2xl font-bold">Settings</CardTitle>
<CardDescription>Adjust your organization's settings.</CardDescription>
</CardHeader>
<CardContent className="grid gap-6">
{selectedOrganizationSlug ?? "no org"}
<form>
<Button variant="destructive" formAction={callAction}>
Delete
</Button>
</form>
</CardContent>
</Card>
);
}
File renamed without changes.
File renamed without changes.
14 changes: 14 additions & 0 deletions src/app/(dashboard)/dashboard/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import OrganizationSwitcher from "@/components/dashboard/organization-switcher";
import db from "@/lib/db";
import { organizations } from "@/lib/schema/orgaizations";
import { auth } from "auth";
import { eq } from "drizzle-orm";

export default async function Page() {
const session = await auth();

const memberOrganizations = await db.query.organizations.findMany({
where: eq(organizations.admin, session?.user.id ?? ""),
});
return <OrganizationSwitcher memberOrganizations={memberOrganizations} />;
}
12 changes: 0 additions & 12 deletions src/app/dashboard/organization/page.tsx

This file was deleted.

57 changes: 0 additions & 57 deletions src/app/dashboard/organization/settings.tsx

This file was deleted.

18 changes: 10 additions & 8 deletions src/components/dashboard/main-nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,29 @@ import { cn } from "@/lib/utils";
import { useSelectedLayoutSegment } from "next/navigation";

const segments = [
{ label: "Overview", value: null },
{ label: "Hubspaces", value: "hubspaces" },
{ label: "Organization", value: "organization" },
{ label: "Plan", value: "plan" },
{ label: "Billing", value: "billing" },
{ label: "Overview", value: "dashboard" },
{ label: "Hubspaces", value: "dashboard/hubspaces" },
{ label: "Organization", value: "dashboard/organization" },
{ label: "Plan", value: "dashboard/plan" },
{ label: "Billing", value: "dashboard/billing" },
];

export function MainNav({
className,
selectedOrganization,
...props
}: React.HTMLAttributes<HTMLElement>) {
}: React.HTMLAttributes<HTMLElement> & {
selectedOrganization: string;
}) {
const layoutSegment = useSelectedLayoutSegment();

return (
<nav
className={cn("flex items-center space-x-4 lg:space-x-6", className)}
{...props}
>
{segments.map((segment) => (
<Link
href={`/dashboard/${segment.value ?? ""}`}
href={`/${selectedOrganization}/${segment.value}`}
key={segment.value}
className={cn(
"text-sm font-medium transition-colors hover:text-primary",
Expand Down
Loading

1 comment on commit e02b25c

@vercel
Copy link

@vercel vercel bot commented on e02b25c Oct 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.