Skip to content
Merged
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
1 change: 1 addition & 0 deletions apps/app/languine.lock
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ files:
onboarding.submit: 85a18a0474d135c1f4c6da6c383a2d81
onboarding.setup: 54efd9605180a9a74e6d1a53529f858e
onboarding.description: fcfd2a71d9095421e290f1b1229d1c6e
onboarding.switch: 7dd9e91261dd30c4cbbb77084b9af1bc
onboarding.trigger.title: c0a683b95c32208c79a08309225647ee
onboarding.trigger.creating: 5c1f94a8b72c6f33012732e6b8ba44e5
onboarding.trigger.completed: 435e0545f0bbfbbbe640e9e12e54c663
Expand Down
121 changes: 62 additions & 59 deletions apps/app/src/actions/change-organization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,71 +3,74 @@
import { authActionClient } from "./safe-action";
import { z } from "zod";
import { db } from "@bubba/db";
import { revalidatePath } from "next/cache";

export const changeOrganizationAction = authActionClient
.schema(
z.object({
organizationId: z.string(),
})
)
.metadata({
name: "change-organization",
track: {
event: "create-employee",
channel: "server",
},
})
.action(async ({ parsedInput, ctx }) => {
const { organizationId } = parsedInput;
const { user } = ctx;
.schema(
z.object({
organizationId: z.string(),
}),
)
.metadata({
name: "change-organization",
track: {
event: "create-employee",
channel: "server",
},
})
.action(async ({ parsedInput, ctx }) => {
const { organizationId } = parsedInput;
const { user } = ctx;

const organizationMember = await db.organizationMember.findFirst({
where: {
userId: user.id,
organizationId,
},
});
const organizationMember = await db.organizationMember.findFirst({
where: {
userId: user.id,
organizationId,
},
});

if (!organizationMember) {
return {
success: false,
error: "Unauthorized",
};
}
if (!organizationMember) {
return {
success: false,
error: "Unauthorized",
};
}

try {
const organization = await db.organization.findUnique({
where: {
id: organizationId,
},
});
try {
const organization = await db.organization.findUnique({
where: {
id: organizationId,
},
});

if (!organization) {
return {
success: false,
error: "Organization not found",
};
}
if (!organization) {
return {
success: false,
error: "Organization not found",
};
}

await db.user.update({
where: {
id: user.id,
},
data: {
organizationId: organization.id,
},
});
await db.user.update({
where: {
id: user.id,
},
data: {
organizationId: organization.id,
},
});

return {
success: true,
data: organization,
};
} catch (error) {
console.error("Error changing organization:", error);
revalidatePath(`/${organization.id}`, "layout");

return {
success: false,
error: "Failed to change organization",
};
}
});
return {
success: true,
data: organization,
};
} catch (error) {
console.error("Error changing organization:", error);

return {
success: false,
error: "Failed to change organization",
};
}
});
89 changes: 40 additions & 49 deletions apps/app/src/components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,53 +14,44 @@ import { auth } from "@/auth";
import { redirect } from "next/navigation";

export async function Header() {
const t = await getI18n();
const { organizations } = await getOrganizations();

const session = await auth();
const user = session?.user;
const currentOrganizationId = user?.organizationId;

if (!currentOrganizationId) {
redirect("/");
}

return (
<header className="-ml-4 -mr-4 md:m-0 z-10 px-4 md:px-0 md:border-b-[1px] flex justify-between pt-4 pb-2 md:pb-4 items-center todesktop:sticky todesktop:top-0 todesktop:bg-background todesktop:border-none sticky md:static top-0 backdrop-filter backdrop-blur-xl md:backdrop-filter md:backdrop-blur-none bg-opacity-70">
<MobileMenu organizationId={currentOrganizationId} />

<Suspense fallback={<Skeleton className="h-8 w-8 rounded-full" />}>
<OrganizationSwitcher
organizations={organizations}
organizationId={currentOrganizationId}
/>
</Suspense>

<div className="flex space-x-2 ml-auto">
<div className="hidden md:flex gap-2">
<FeedbackForm />
<Button
asChild
variant="outline"
className="rounded-full font-normal h-[32px] p-0 px-3 text-xs text-muted-foreground gap-2 items-center"
>
<Link
href="https://discord.gg/compai"
target="_blank"
className="flex gap-2"
>
<Icons.Discord className="h-4 w-4" />
{t("header.discord.button")}
</Link>
</Button>
</div>

<NotificationCenter />

<Suspense fallback={<Skeleton className="h-8 w-8 rounded-full" />}>
<UserMenu />
</Suspense>
</div>
</header>
);
const t = await getI18n();
const session = await auth();
const user = session?.user;
const currentOrganizationId = user?.organizationId;

if (!currentOrganizationId) {
redirect("/");
}

return (
<header className="-ml-4 -mr-4 md:m-0 z-10 px-4 md:px-0 md:border-b-[1px] flex justify-between pt-4 pb-2 md:pb-4 items-center todesktop:sticky todesktop:top-0 todesktop:bg-background todesktop:border-none sticky md:static top-0 backdrop-filter backdrop-blur-xl md:backdrop-filter md:backdrop-blur-none bg-opacity-70">
<MobileMenu organizationId={currentOrganizationId} />

<div className="flex space-x-2 ml-auto">
<div className="hidden md:flex gap-2">
<FeedbackForm />
<Button
asChild
variant="outline"
className="rounded-full font-normal h-[32px] p-0 px-3 text-xs text-muted-foreground gap-2 items-center"
>
<Link
href="https://discord.gg/compai"
target="_blank"
className="flex gap-2"
>
<Icons.Discord className="h-4 w-4" />
{t("header.discord.button")}
</Link>
</Button>
</div>

<NotificationCenter />

<Suspense fallback={<Skeleton className="h-8 w-8 rounded-full" />}>
<UserMenu />
</Suspense>
</div>
</header>
);
}
Loading