mirror of
https://github.com/Portabase/portabase.git
synced 2026-07-14 11:16:13 +02:00
Working on some bugs.
This commit is contained in:
+3
-3
@@ -9,9 +9,9 @@ import { toast } from "sonner";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { TooltipProvider } from "@/components/ui/tooltip";
|
||||
import Link from "next/link";
|
||||
import { PasswordInput } from "@/components/wrappers/auth/PaswordInput/password-input";
|
||||
import { LoginSchema, LoginType } from "@/components/wrappers/auth/login/loginForm/login-form.schema";
|
||||
import { SocialAuthButton, SocialProviderType } from "@/components/wrappers/auth/login/buttonAuth/SocialAuthButton";
|
||||
import { PasswordInput } from "@/components/wrappers/auth/password-input/password-input";
|
||||
import { LoginSchema, LoginType } from "@/components/wrappers/auth/login/login-form/login-form.schema";
|
||||
import { SocialAuthButton, SocialProviderType } from "@/components/wrappers/auth/login/button-auth/social-auth-button";
|
||||
import { signIn } from "@/lib/auth/auth-client";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { Icon } from "@iconify/react";
|
||||
@@ -12,7 +12,7 @@ import { Form } from "@/components/ui/form";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { TooltipProvider, TooltipTrigger, Tooltip, TooltipContent } from "@/components/ui/tooltip";
|
||||
import { RegisterSchema, RegisterType } from "@/components/wrappers/auth/register/register-form/register-form.schema";
|
||||
import { PasswordInput } from "@/components/wrappers/auth/PaswordInput/password-input";
|
||||
import { PasswordInput } from "@/components/wrappers/auth/password-input/password-input";
|
||||
import {signUp} from "@/lib/auth/auth-client";
|
||||
|
||||
export type registerFormProps = {
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
"use server";
|
||||
import { userAction } from "@/safe-actions";
|
||||
import { z } from "zod";
|
||||
import { EmailFormSchema } from "@/components/wrappers/dashboard/admin/AdminEmailTab/EmailForm/email-form.schema";
|
||||
import { EmailFormSchema } from "@/components/wrappers/dashboard/admin/admin-email-tab/email-form/email-form.schema";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { db } from "@/db";
|
||||
import * as drizzleDb from "@/db";
|
||||
+3
-3
@@ -8,9 +8,9 @@ import { Button } from "@/components/ui/button";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { TooltipProvider } from "@/components/ui/tooltip";
|
||||
|
||||
import { EmailFormSchema, EmailFormType } from "@/components/wrappers/dashboard/admin/AdminEmailTab/EmailForm/email-form.schema";
|
||||
import { PasswordInput } from "@/components/wrappers/auth/PaswordInput/password-input";
|
||||
import { updateEmailSettingsAction } from "@/components/wrappers/dashboard/admin/AdminEmailTab/EmailForm/email-form.action";
|
||||
import { EmailFormSchema, EmailFormType } from "@/components/wrappers/dashboard/admin/admin-email-tab/email-form/email-form.schema";
|
||||
import { PasswordInput } from "@/components/wrappers/auth/password-input/password-input";
|
||||
import { updateEmailSettingsAction } from "@/components/wrappers/dashboard/admin/admin-email-tab/email-form/email-form.action";
|
||||
import { toast } from "sonner";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { EmailForm } from "@/components/wrappers/dashboard/admin/AdminEmailTab/EmailForm/EmailForm";
|
||||
import { EmailForm } from "@/components/wrappers/dashboard/admin/admin-email-tab/email-form/email-form";
|
||||
import { Send } from "lucide-react";
|
||||
import { ButtonWithLoading } from "@/components/wrappers/common/button/button-with-loading";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
+2
-2
@@ -2,14 +2,14 @@ import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||
import { Info, ShieldCheck } from "lucide-react";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { StorageS3Form } from "@/components/wrappers/dashboard/admin/AdminStorageTab/StorageS3Form/StorageS3Form";
|
||||
import { StorageS3Form } from "@/components/wrappers/dashboard/admin/admin-storage-tab/storage-s3/storage-s3-form";
|
||||
import { useState } from "react";
|
||||
import { ButtonWithLoading } from "@/components/wrappers/common/button/button-with-loading";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { checkConnexionToS3 } from "@/features/upload/public/upload.action";
|
||||
import { toast } from "sonner";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { updateStorageSettingsAction } from "@/components/wrappers/dashboard/admin/AdminStorageTab/StorageS3Form/s3-form.action";
|
||||
import { updateStorageSettingsAction } from "@/components/wrappers/dashboard/admin/admin-storage-tab/storage-s3/s3-form.action";
|
||||
import {Setting} from "@/db/schema/00_setting";
|
||||
|
||||
export type SettingsStorageTabProps = {
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
import { userAction } from "@/safe-actions";
|
||||
import { z } from "zod";
|
||||
import { db } from "@/db";
|
||||
import { S3FormSchema, StorageSwitchSchema } from "@/components/wrappers/dashboard/admin/AdminStorageTab/StorageS3Form/s3-form.schema";
|
||||
import { S3FormSchema, StorageSwitchSchema } from "@/components/wrappers/dashboard/admin/admin-storage-tab/storage-s3/s3-form.schema";
|
||||
import { eq } from "drizzle-orm";
|
||||
import * as drizzleDb from "@/db";
|
||||
|
||||
+2
-2
@@ -8,10 +8,10 @@ import { Button } from "@/components/ui/button";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { TooltipProvider } from "@/components/ui/tooltip";
|
||||
|
||||
import { S3FormSchema, S3FormType } from "@/components/wrappers/dashboard/admin/AdminStorageTab/StorageS3Form/s3-form.schema";
|
||||
import { S3FormSchema, S3FormType } from "@/components/wrappers/dashboard/admin/admin-storage-tab/storage-s3/s3-form.schema";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { toast } from "sonner";
|
||||
import { updateS3SettingsAction } from "@/components/wrappers/dashboard/admin/AdminStorageTab/StorageS3Form/s3-form.action";
|
||||
import { updateS3SettingsAction } from "@/components/wrappers/dashboard/admin/admin-storage-tab/storage-s3/s3-form.action";
|
||||
|
||||
export type S3FormProps = {
|
||||
defaultValues?: S3FormType;
|
||||
@@ -1,8 +1,8 @@
|
||||
"use client";
|
||||
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { SettingsEmailTab } from "@/components/wrappers/dashboard/admin/AdminEmailTab/SettingsEmailTab";
|
||||
import { SettingsStorageTab } from "@/components/wrappers/dashboard/admin/AdminStorageTab/SettingsStorageTab";
|
||||
import { SettingsEmailTab } from "@/components/wrappers/dashboard/admin/admin-email-tab/settings-email-tab";
|
||||
import { SettingsStorageTab } from "@/components/wrappers/dashboard/admin/admin-storage-tab/settings-storage-tab";
|
||||
import { AdminUsersTable } from "@/components/wrappers/dashboard/admin/admin-user-table";
|
||||
import { User } from "@/db/schema/01_user";
|
||||
import { Setting } from "@/db/schema/00_setting";
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
"use client"
|
||||
import {ColumnDef} from "@tanstack/react-table";
|
||||
import {Badge} from "@/components/ui/badge";
|
||||
import {updateUserAction} from "@/components/wrappers/dashboard/profile/UserForm/user-form.action";
|
||||
import {updateUserAction} from "@/components/wrappers/dashboard/profile/user-form/user-form.action";
|
||||
import {useMutation} from "@tanstack/react-query";
|
||||
import {toast} from "sonner";
|
||||
import {useRouter} from "next/navigation";
|
||||
import {useState} from "react";
|
||||
import {Trash2} from "lucide-react";
|
||||
import {deleteUserAction} from "@/components/wrappers/dashboard/profile/ButtonDeleteAccount/delete-account.action";
|
||||
import {deleteUserAction} from "@/components/wrappers/dashboard/profile/button-delete-account/delete-account.action";
|
||||
import {ButtonWithLoading} from "@/components/wrappers/common/button/button-with-loading";
|
||||
import {User} from "@/db/schema/01_user";
|
||||
import {useSession} from "@/lib/auth/auth-client";
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
import {generateEdgeKey} from "@/utils/edge_key";
|
||||
import {getServerUrl} from "@/utils/get-server-url";
|
||||
import {PasswordInput} from "@/components/wrappers/auth/PaswordInput/password-input";
|
||||
import {PasswordInput} from "@/components/wrappers/auth/password-input/password-input";
|
||||
import {useState} from "react";
|
||||
import {CopyButton} from "@/components/wrappers/common/button/copy-button";
|
||||
import {Agent} from "@/db/schema/07_agent";
|
||||
+1
-1
@@ -16,7 +16,7 @@ export const AgentCard = (props: agentCardProps) => {
|
||||
return (
|
||||
<Link href={`/dashboard/agents/${agent.id}`} className="block transition-all duration-200 hover:scale-[1.01] hover:shadow-md">
|
||||
<Card className="flex flex-row justify-between">
|
||||
<div>
|
||||
<div className="flex-1 text-left">
|
||||
<CardHeader className="text-2xl font-bold">{agent.name}</CardHeader>
|
||||
<CardContent>Last contact: {formatDateLastContact(agent.lastContact)}</CardContent>
|
||||
</div>
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
"use server";
|
||||
import {ActionError, userAction} from "@/safe-actions";
|
||||
import {AgentSchema} from "@/components/wrappers/dashboard/agent/AgentForm/agent-form.schema";
|
||||
import {AgentSchema} from "@/components/wrappers/dashboard/agent/agent-form/agent-form.schema";
|
||||
import {z} from "zod";
|
||||
import {eq, and, ne, count} from "drizzle-orm";
|
||||
import {db} from "@/db";
|
||||
+2
-2
@@ -16,9 +16,9 @@ import {Button} from "@/components/ui/button";
|
||||
import {useRouter} from "next/navigation";
|
||||
import {useMutation} from "@tanstack/react-query";
|
||||
import {TooltipProvider} from "@/components/ui/tooltip";
|
||||
import {AgentSchema, AgentType} from "@/components/wrappers/dashboard/agent/AgentForm/agent-form.schema";
|
||||
import {AgentSchema, AgentType} from "@/components/wrappers/dashboard/agent/agent-form/agent-form.schema";
|
||||
import {toast} from "sonner";
|
||||
import {createAgentAction, updateAgentAction} from "@/components/wrappers/dashboard/agent/AgentForm/agent-form.action";
|
||||
import {createAgentAction, updateAgentAction} from "@/components/wrappers/dashboard/agent/agent-form/agent-form.action";
|
||||
|
||||
export type agentFormProps = {
|
||||
defaultValues?: AgentType;
|
||||
+1
-1
@@ -7,7 +7,7 @@ import { generateEdgeKey } from "@/utils/edge_key";
|
||||
import { PropsWithChildren } from "react";
|
||||
import { CopyButton } from "@/components/wrappers/common/button/copy-button";
|
||||
import { getServerUrl } from "@/utils/get-server-url";
|
||||
import { CodeSnippet } from "@/components/wrappers/code-snippet/CodeSnippet";
|
||||
import { CodeSnippet } from "@/components/wrappers/code-snippet/code-snippet";
|
||||
import {Agent} from "@/db/schema/07_agent";
|
||||
|
||||
export type agentRegistrationDialogProps = PropsWithChildren<{
|
||||
@@ -0,0 +1,42 @@
|
||||
"use client";
|
||||
|
||||
import { Trash2 } from "lucide-react";
|
||||
import { ButtonWithConfirm } from "@/components/wrappers/common/button/button-with-confirm";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { toast } from "sonner";
|
||||
import {deleteAgentAction} from "@/components/wrappers/dashboard/agent/button-delete-agent/delete-agent.action";
|
||||
|
||||
export type ButtonDeleteAgentProps = {
|
||||
text?: string;
|
||||
agentId: string;
|
||||
};
|
||||
|
||||
export const ButtonDeleteAgent = (props: ButtonDeleteAgentProps) => {
|
||||
const router = useRouter();
|
||||
|
||||
const mutation = useMutation({
|
||||
mutationFn: () => deleteAgentAction(props.agentId),
|
||||
onSuccess: async (result: any) => {
|
||||
if (result.data?.success) {
|
||||
toast.success(result.data.actionSuccess.message);
|
||||
router.push("/dashboard/agents");
|
||||
} else {
|
||||
toast.error(result.data.actionError.message || "Unknown error occurred.");
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<ButtonWithConfirm
|
||||
text={props.text ? props.text : ""}
|
||||
onClick={() => {
|
||||
mutation.mutate();
|
||||
}}
|
||||
variant={"destructive"}
|
||||
isPending={mutation.isPending}
|
||||
className="gap-2"
|
||||
icon={<Trash2 />}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,53 @@
|
||||
"use server";
|
||||
|
||||
import {userAction} from "@/safe-actions";
|
||||
import {z} from "zod";
|
||||
import {v4 as uuidv4} from "uuid";
|
||||
import {ServerActionResult} from "@/types/action-type";
|
||||
import {eq} from "drizzle-orm";
|
||||
import {db} from "@/db";
|
||||
import * as drizzleDb from "@/db";
|
||||
import {Agent} from "@/db/schema/07_agent";
|
||||
|
||||
export const deleteAgentAction = userAction.schema(z.string()).action(async ({parsedInput}): Promise<ServerActionResult<Agent>> => {
|
||||
try {
|
||||
|
||||
// const deletedAgent: Agent[] = await db.delete(drizzleDb.schemas.agent).where(eq(drizzleDb.schemas.agent.id, parsedInput)).returning();
|
||||
|
||||
const uuid = uuidv4();
|
||||
|
||||
const updatedAgent = await db
|
||||
.update(drizzleDb.schemas.agent)
|
||||
.set({
|
||||
isArchived: true,
|
||||
slug: uuid,
|
||||
})
|
||||
.where(eq(drizzleDb.schemas.agent.id, parsedInput))
|
||||
.returning();
|
||||
|
||||
|
||||
if (!updatedAgent[0]) {
|
||||
throw new Error("Agent not found or update failed");
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
success: true,
|
||||
value: updatedAgent[0],
|
||||
actionSuccess: {
|
||||
message: "Agent has been successfully deleted.",
|
||||
messageParams: {projectId: parsedInput},
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
actionError: {
|
||||
message: "Failed to delete agent.",
|
||||
status: 500,
|
||||
cause: error instanceof Error ? error.message : "Unknown error",
|
||||
messageParams: {projectId: parsedInput},
|
||||
},
|
||||
};
|
||||
}
|
||||
});
|
||||
+1
-1
@@ -1,8 +1,8 @@
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||
import { SidebarMenuButton } from "@/components/ui/sidebar";
|
||||
import { ChevronUp } from "lucide-react";
|
||||
import { LoggedInDropdown } from "@/components/wrappers/dashboard/loggedInDropdown/LoggedInDropdown";
|
||||
import { currentUser } from "@/lib/auth/current-user";
|
||||
import {LoggedInDropdown} from "@/components/wrappers/dashboard/common/logged-in/logged-in-dropdown";
|
||||
|
||||
export const LoggedInButton = async () => {
|
||||
const user = await currentUser();
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
import {SidebarLogo} from "@/components/wrappers/dashboard/common/sidebar/logo-sidebar";
|
||||
import {SidebarMenuCustomMain} from "@/components/wrappers/dashboard/common/sidebar/menu-sidebar-main";
|
||||
import {SideBarFooterCredit} from "@/components/wrappers/dashboard/common/sidebar/side-bar-footer-credit";
|
||||
import {LoggedInButton} from "@/components/wrappers/dashboard/loggedInButton/LoggedInButton";
|
||||
import {OrganizationCombobox} from "@/components/wrappers/dashboard/organization/organization-combobox";
|
||||
import {LoggedInButton} from "@/components/wrappers/dashboard/common/logged-in/logged-in-button";
|
||||
|
||||
export function AppSidebar() {
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ export const SidebarMenuCustomMain = () => {
|
||||
const member = authClient.useActiveMember();
|
||||
|
||||
|
||||
|
||||
if (isPending) return null;
|
||||
|
||||
if (error || !session) {
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@
|
||||
import { Clock9 } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
|
||||
import { CronInput } from "@/components/wrappers/dashboard/database/CronButton/CronInput";
|
||||
import { CronInput } from "@/components/wrappers/dashboard/database/cron-button/cron-input";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
@@ -10,7 +10,7 @@ import { useState } from "react";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { toast } from "sonner";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { updateDatabaseBackupPolicyAction } from "@/components/wrappers/dashboard/database/CronButton/cron.action";
|
||||
import { updateDatabaseBackupPolicyAction } from "@/components/wrappers/dashboard/database/cron-button/cron.action";
|
||||
import {Database} from "@/db/schema/06_database";
|
||||
|
||||
export type CronButtonProps = {
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { AdvancedCronSelect } from "./AdvancedCronSelect";
|
||||
import { updateDatabaseBackupPolicyAction } from "@/components/wrappers/dashboard/database/CronButton/cron.action";
|
||||
import { AdvancedCronSelect } from "./advanced-cron-select";
|
||||
import { updateDatabaseBackupPolicyAction } from "@/components/wrappers/dashboard/database/cron-button/cron.action";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
+2
-2
@@ -8,8 +8,8 @@ import { Button } from "@/components/ui/button";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { TooltipProvider } from "@/components/ui/tooltip";
|
||||
import { DatabaseSchema, DatabaseType } from "@/components/wrappers/dashboard/database/DatabaseForm/form-database.schema";
|
||||
import { updateDatabaseAction } from "@/components/wrappers/dashboard/database/DatabaseForm/form-database.action";
|
||||
import { DatabaseSchema, DatabaseType } from "@/components/wrappers/dashboard/database/database-form/form-database.schema";
|
||||
import { updateDatabaseAction } from "@/components/wrappers/dashboard/database/database-form/form-database.action";
|
||||
import { toast } from "sonner";
|
||||
|
||||
export type DatabaseFormProps = {
|
||||
+1
-1
@@ -4,7 +4,7 @@ import { z } from "zod";
|
||||
import { userAction } from "@/safe-actions";
|
||||
import { db } from "@/db";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { DatabaseSchema } from "@/components/wrappers/dashboard/database/DatabaseForm/form-database.schema";
|
||||
import { DatabaseSchema } from "@/components/wrappers/dashboard/database/database-form/form-database.schema";
|
||||
import * as drizzleDb from "@/db";
|
||||
|
||||
export const updateDatabaseAction = userAction
|
||||
@@ -4,6 +4,8 @@ import {ComboBox} from "@/components/wrappers/common/combobox";
|
||||
import {useSidebar} from "@/components/ui/sidebar";
|
||||
import {useRouter} from "next/navigation";
|
||||
import {authClient} from "@/lib/auth/auth-client";
|
||||
import {auth} from "@/lib/auth/auth";
|
||||
|
||||
|
||||
export function OrganizationCombobox() {
|
||||
const router = useRouter();
|
||||
@@ -24,11 +26,15 @@ export function OrganizationCombobox() {
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
|
||||
const onValueChange = async (slug: string) => {
|
||||
|
||||
await authClient.organization.setActive({
|
||||
organizationSlug: slug,
|
||||
});
|
||||
router.refresh();
|
||||
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ export const OrganizationFormSchema = z.object({
|
||||
.regex(/^[a-zA-Z0-9_-]*$/, 'Slug can only contain letters, numbers, underscores, and hyphens')
|
||||
.min(5, 'Slug must be at least 5 characters long')
|
||||
.max(20, 'Slug must be at most 20 characters long'),
|
||||
members: z.array(z.string()),
|
||||
users: z.array(z.string()),
|
||||
|
||||
});
|
||||
|
||||
+65
-36
@@ -1,19 +1,38 @@
|
||||
"use client";
|
||||
|
||||
import { Card, CardContent, CardHeader } from "@/components/ui/card";
|
||||
import { FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, useZodForm } from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Form } from "@/components/ui/form";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { MultiSelect } from "@/components/wrappers/common/multiselect/multi-select";
|
||||
import { OrganizationFormSchema, OrganizationFormType } from "@/components/wrappers/dashboard/organization/OrganizationForm/organization-form.schema";
|
||||
import {Card, CardContent, CardHeader} from "@/components/ui/card";
|
||||
import {
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
useZodForm
|
||||
} from "@/components/ui/form";
|
||||
import {Input} from "@/components/ui/input";
|
||||
import {Form} from "@/components/ui/form";
|
||||
import {Button} from "@/components/ui/button";
|
||||
import {useMutation} from "@tanstack/react-query";
|
||||
import {useRouter} from "next/navigation";
|
||||
import {MultiSelect} from "@/components/wrappers/common/multiselect/multi-select";
|
||||
import {
|
||||
OrganizationFormSchema,
|
||||
OrganizationFormType
|
||||
} from "@/components/wrappers/dashboard/organization/organization-form/organization-form.schema";
|
||||
import {MemberWithUser, OrganizationWithMembers} from "@/db/schema/02_organization";
|
||||
import {
|
||||
deleteOrganizationAction,
|
||||
updateOrganizationAction
|
||||
} from "@/components/wrappers/dashboard/organization/organization.action";
|
||||
import {toast} from "sonner";
|
||||
import {User as BetterAuthUser} from "better-auth";
|
||||
import {User} from "@/db/schema/01_user";
|
||||
|
||||
export type organizationFormProps = {
|
||||
defaultValues?: OrganizationWithMembers;
|
||||
members: MemberWithUser[];
|
||||
users: User[];
|
||||
currentUser: BetterAuthUser;
|
||||
};
|
||||
|
||||
export const OrganizationForm = (props: organizationFormProps) => {
|
||||
@@ -21,17 +40,20 @@ export const OrganizationForm = (props: organizationFormProps) => {
|
||||
const router = useRouter();
|
||||
const isCreate = !Boolean(props.defaultValues);
|
||||
|
||||
const formatUsersList = (members: MemberWithUser[]) => {
|
||||
const formatUsersList = (users: User[]) => {
|
||||
|
||||
return members.map((member) => ({
|
||||
value: member.user.id,
|
||||
label: `${member.user.name} | ${member.user.email}`,
|
||||
}));
|
||||
return users
|
||||
.filter((user) => user.id !== props.currentUser.id)
|
||||
.map((user) => ({
|
||||
value: user.id,
|
||||
label: `${user.name} | ${user.email}`,
|
||||
}));
|
||||
};
|
||||
|
||||
const formatDefaultUsers = (members: MemberWithUser[]): string[] => {
|
||||
console.log("ici",members);
|
||||
return members.map((member) => member.userId);
|
||||
return members
|
||||
.filter((member) => member.userId !== props.currentUser.id)
|
||||
.map((member) => member.userId);
|
||||
};
|
||||
|
||||
const formattedDefaultValues = {
|
||||
@@ -46,21 +68,28 @@ export const OrganizationForm = (props: organizationFormProps) => {
|
||||
});
|
||||
|
||||
const mutation = useMutation({
|
||||
mutationFn: async (values: OrganizationFormType) => {
|
||||
console.log(values);
|
||||
// const organization = await updateOrganizationAction({ data: values, organizationId: props.defaultValues.id });
|
||||
// console.log(organization);
|
||||
// if (organization.data.success) {
|
||||
// // toast.success(organization.data.actionSuccess.message);
|
||||
// // router.push(`/dashboard/${organization.data.value.slug}/settings`);
|
||||
// // router.refresh();
|
||||
// } else {
|
||||
// // toast.success(organization.data.actionError.message);
|
||||
// }
|
||||
mutationFn: (values: OrganizationFormType) => updateOrganizationAction({
|
||||
data: values,
|
||||
organizationId: props.defaultValues?.id ?? ""
|
||||
}),
|
||||
onSuccess: async (result) => {
|
||||
if (result?.data?.success) {
|
||||
toast.success(result.data.actionSuccess?.message || "Organization updated successfully.");
|
||||
router.push("/dashboard/settings");
|
||||
} else {
|
||||
// @ts-ignore
|
||||
const errorMsg = result?.data?.actionError?.message || result?.data?.actionError?.messageParams?.message || "Failed to update the organization.";
|
||||
toast.error(errorMsg);
|
||||
}
|
||||
},
|
||||
onError: (error: any) => {
|
||||
console.error("Mutation network error:", error);
|
||||
toast.error(error?.message || "A network error occurred.");
|
||||
},
|
||||
|
||||
|
||||
});
|
||||
|
||||
console.log(formatUsersList(props.members))
|
||||
|
||||
return (
|
||||
<Card>
|
||||
@@ -77,13 +106,13 @@ export const OrganizationForm = (props: organizationFormProps) => {
|
||||
control={form.control}
|
||||
name="name"
|
||||
defaultValue=""
|
||||
render={({ field }) => (
|
||||
render={({field}) => (
|
||||
<FormItem>
|
||||
<FormLabel>Name</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="Organization 1" {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
<FormMessage/>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
@@ -91,7 +120,7 @@ export const OrganizationForm = (props: organizationFormProps) => {
|
||||
control={form.control}
|
||||
name="slug"
|
||||
defaultValue=""
|
||||
render={({ field }) => (
|
||||
render={({field}) => (
|
||||
<FormItem>
|
||||
<FormLabel>Slug</FormLabel>
|
||||
<FormControl>
|
||||
@@ -104,19 +133,19 @@ export const OrganizationForm = (props: organizationFormProps) => {
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
<FormMessage/>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="users"
|
||||
render={({ field }) => (
|
||||
render={({field}) => (
|
||||
<FormItem>
|
||||
<FormLabel>Users</FormLabel>
|
||||
<FormControl>
|
||||
<MultiSelect
|
||||
options={formatUsersList(props.members)}
|
||||
options={formatUsersList(props.users)}
|
||||
onValueChange={field.onChange}
|
||||
defaultValue={field.value ?? []}
|
||||
placeholder="Select users"
|
||||
@@ -126,7 +155,7 @@ export const OrganizationForm = (props: organizationFormProps) => {
|
||||
/>
|
||||
</FormControl>
|
||||
<FormDescription>Select users you want to add to this organization</FormDescription>
|
||||
<FormMessage />
|
||||
<FormMessage/>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
@@ -4,14 +4,14 @@ import { userAction } from "@/safe-actions";
|
||||
import { OrganizationSchema } from "@/components/wrappers/dashboard/organization/organization.schema";
|
||||
import { ServerActionResult } from "@/types/action-type";
|
||||
import { z } from "zod";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { OrganizationFormSchema } from "@/components/wrappers/dashboard/organization/OrganizationForm/organization-form.schema";
|
||||
import { OrganizationFormSchema } from "@/components/wrappers/dashboard/organization/organization-form/organization-form.schema";
|
||||
import { db } from "@/db";
|
||||
import { eq } from "drizzle-orm";
|
||||
import {checkSlugOrganization, createOrganization, deleteOrganization} from "@/lib/auth/auth";
|
||||
import {and, eq, inArray} from "drizzle-orm";
|
||||
import {auth, checkSlugOrganization, createOrganization, deleteOrganization} from "@/lib/auth/auth";
|
||||
import {slugify} from "@/utils/slugify";
|
||||
import {Organization} from "@/db/schema/02_organization";
|
||||
import * as drizzleDb from "@/db";
|
||||
import {headers} from "next/headers";
|
||||
|
||||
export const createOrganizationAction = userAction.schema(OrganizationSchema).action(async ({ parsedInput }): Promise<ServerActionResult<Organization>> => {
|
||||
try {
|
||||
@@ -72,53 +72,117 @@ export const updateOrganizationAction = userAction
|
||||
organizationId: z.string(),
|
||||
})
|
||||
)
|
||||
.action(async ({ parsedInput }): Promise<ServerActionResult<Organization>> => {
|
||||
.action(async ({ parsedInput, ctx }): Promise<ServerActionResult<Organization>> => {
|
||||
try {
|
||||
const newUserList = parsedInput.data.users;
|
||||
console.log(parsedInput);
|
||||
const organization = await db.query.organization.findFirst({
|
||||
where: eq(drizzleDb.schemas.organization.id, parsedInput.organizationId),
|
||||
with: {
|
||||
members: true,
|
||||
}
|
||||
});
|
||||
|
||||
const organization = await db.select().from(drizzleDb.schemas.organization).where(eq(drizzleDb.schemas.organization.id, parsedInput.organizationId)).execute();
|
||||
|
||||
if (organization.length === 0) {
|
||||
throw new Error("Organization not found.");
|
||||
if (!organization) {
|
||||
return {
|
||||
success: false,
|
||||
actionError: {
|
||||
message: "Organization not found.",
|
||||
status: 404,
|
||||
cause: "not_found",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const existingItemIds = organization[0].users.map((user) => user.userId);
|
||||
const existingItemIds = organization.members
|
||||
.filter((member) => member.userId !== ctx.user.id)
|
||||
.map((member) => member.userId);
|
||||
const usersToAdd = newUserList.filter((id) => !existingItemIds.includes(id));
|
||||
const usersToRemove = existingItemIds.filter((id) => !newUserList.includes(id));
|
||||
|
||||
if (usersToAdd.length > 0) {
|
||||
await db
|
||||
.insert(drizzleDb.schemas.organization)
|
||||
.values(
|
||||
usersToAdd.map((userId) => ({
|
||||
userId,
|
||||
organizationId: organization[0].id,
|
||||
for (const userToAdd of usersToAdd) {
|
||||
await auth.api.addMember({
|
||||
body: {
|
||||
userId: userToAdd,
|
||||
role: "member",
|
||||
}))
|
||||
)
|
||||
.execute();
|
||||
organizationId: organization.id,
|
||||
},
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// await db
|
||||
// .insert(drizzleDb.schemas.member)
|
||||
// .values(
|
||||
// usersToAdd.map((userId) => ({
|
||||
// userId,
|
||||
// organizationId: organization.id,
|
||||
// role: "member",
|
||||
// }))
|
||||
// )
|
||||
// .execute();
|
||||
}
|
||||
|
||||
if (usersToRemove.length > 0) {
|
||||
await db.delete().from(userOrganization).where(inArray(userOrganization.userId, usersToRemove)).execute();
|
||||
await db.delete(drizzleDb.schemas.member).where(inArray(drizzleDb.schemas.member.userId, usersToRemove)).execute();
|
||||
// TODO : Do not delete, go permission error with better auth
|
||||
// for (const userToRemove of usersToRemove) {
|
||||
//
|
||||
// const memberToRemove = await db.query.member.findFirst({
|
||||
// where: and(eq(drizzleDb.schemas.member.userId, userToRemove), eq(drizzleDb.schemas.member.organizationId, organization.id)),
|
||||
// with: {
|
||||
// user: true
|
||||
// }
|
||||
// })
|
||||
// console.log(memberToRemove)
|
||||
//
|
||||
// if (memberToRemove) {
|
||||
// console.log("ici")
|
||||
// await auth.api.removeMember({
|
||||
// body: {
|
||||
// memberIdOrEmail: memberToRemove.user.email,
|
||||
// organizationId: organization.id,
|
||||
// },
|
||||
// headers: await headers()
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
||||
// const updatedOrganization = await auth.api.updateOrganization({
|
||||
// body: {
|
||||
// data: {
|
||||
// name: parsedInput.data.name,
|
||||
// slug: parsedInput.data.slug,
|
||||
// },
|
||||
// organizationId: organization.id,
|
||||
// },
|
||||
// headers: await headers(),
|
||||
// });
|
||||
|
||||
|
||||
const updatedOrganization = await db
|
||||
.update(organization)
|
||||
.update(drizzleDb.schemas.organization)
|
||||
.set({
|
||||
name: parsedInput.data.name,
|
||||
slug: parsedInput.data.slug,
|
||||
})
|
||||
.where(eq(organization.id, parsedInput.organizationId))
|
||||
.where(eq(drizzleDb.schemas.organization.id, parsedInput.organizationId))
|
||||
.returning()
|
||||
.execute();
|
||||
|
||||
return {
|
||||
success: true,
|
||||
value: updatedOrganization[0],
|
||||
value: updatedOrganization as unknown as Organization,
|
||||
actionSuccess: {
|
||||
message: "Organization has been successfully updated.",
|
||||
messageParams: { organizationId: updatedOrganization[0].id },
|
||||
messageParams: { organizationId: organization.id},
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
@@ -128,7 +192,7 @@ export const updateOrganizationAction = userAction
|
||||
actionError: {
|
||||
message: "Failed to update organization.",
|
||||
status: 500,
|
||||
cause: error.message ?? "Unknown error",
|
||||
cause: "server_error",
|
||||
messageParams: { message: "Error updating the organization" },
|
||||
},
|
||||
};
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ import { UploadIcon } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
import { uploadImageAction } from "@/features/upload/public/upload.action";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { updateImageUserAction } from "@/components/wrappers/dashboard/profile/Avatar/avatar.action";
|
||||
import { updateImageUserAction } from "@/components/wrappers/dashboard/profile/avatar/avatar.action";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { User } from "@/db/schema/01_user";
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
"use server";
|
||||
import { userAction } from "@/safe-actions";
|
||||
import { z } from "zod";
|
||||
import { UserSchema } from "@/components/wrappers/dashboard/profile/UserForm/user-form.schema";
|
||||
import { UserSchema } from "@/components/wrappers/dashboard/profile/user-form/user-form.schema";
|
||||
import { db } from "@/db";
|
||||
import { eq } from "drizzle-orm";
|
||||
import * as drizzleDb from "@/db";
|
||||
+2
-2
@@ -8,9 +8,9 @@ import { Button } from "@/components/ui/button";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { TooltipProvider } from "@/components/ui/tooltip";
|
||||
import { UserSchema, UserType } from "@/components/wrappers/dashboard/profile/UserForm/user-form.schema";
|
||||
import { UserSchema, UserType } from "@/components/wrappers/dashboard/profile/user-form/user-form.schema";
|
||||
import { toast } from "sonner";
|
||||
import { updateUserAction } from "@/components/wrappers/dashboard/profile/UserForm/user-form.action";
|
||||
import { updateUserAction } from "@/components/wrappers/dashboard/profile/user-form/user-form.action";
|
||||
|
||||
export type userFormProps = {
|
||||
defaultValues?: UserType;
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
import { Trash2 } from "lucide-react";
|
||||
import { ButtonWithConfirm } from "@/components/wrappers/common/button/button-with-confirm";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { deleteProjectAction } from "@/components/wrappers/dashboard/projects/ButtonDeleteProject/delete-project.action";
|
||||
import { deleteProjectAction } from "@/components/wrappers/dashboard/projects/button-delete-project/delete-project.action";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { toast } from "sonner";
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
"use server";
|
||||
|
||||
import { userAction } from "@/safe-actions";
|
||||
import { ProjectSchema } from "@/components/wrappers/dashboard/projects/ProjectsForm/ProjectForm.schema";
|
||||
import { ProjectSchema } from "@/components/wrappers/dashboard/projects/project-form/project-form.schema";
|
||||
import { z } from "zod";
|
||||
import { ServerActionResult } from "@/types/action-type";
|
||||
import { db } from "@/db";
|
||||
+2
-2
@@ -6,8 +6,8 @@ import { Input } from "@/components/ui/input";
|
||||
import { Form } from "@/components/ui/form";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { ProjectSchema, ProjectType } from "@/components/wrappers/dashboard/projects/ProjectsForm/ProjectForm.schema";
|
||||
import { createProjectAction, updateProjectAction } from "@/components/wrappers/dashboard/projects/ProjectsForm/project-form.action";
|
||||
import { ProjectSchema, ProjectType } from "@/components/wrappers/dashboard/projects/project-form/project-form.schema";
|
||||
import { createProjectAction, updateProjectAction } from "@/components/wrappers/dashboard/projects/project-form/project-form.action";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { MultiSelect } from "@/components/wrappers/common/multiselect/multi-select";
|
||||
import { toast } from "sonner";
|
||||
@@ -5,7 +5,7 @@ import {MemberWithUser} from "@/db/schema/02_organization";
|
||||
import {useState} from "react";
|
||||
import {useSession} from "@/lib/auth/auth-client";
|
||||
import {useMutation} from "@tanstack/react-query";
|
||||
import {updateUserAction} from "@/components/wrappers/dashboard/profile/UserForm/user-form.action";
|
||||
import {updateUserAction} from "@/components/wrappers/dashboard/profile/user-form/user-form.action";
|
||||
import {toast} from "sonner";
|
||||
import {Badge} from "@/components/ui/badge";
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
"use client";
|
||||
import { useSidebar } from "@/components/ui/sidebar";
|
||||
import { env } from "@/env.mjs";
|
||||
|
||||
export type SideBarFooterCreditProps = {};
|
||||
|
||||
export const SideBarFooterCredit = (props: SideBarFooterCreditProps) => {
|
||||
const { state } = useSidebar();
|
||||
|
||||
return (
|
||||
<>
|
||||
{state === "expanded" && (
|
||||
<div className="text-center">
|
||||
<h1 className="text-[10px]">Portabase Community Edition v{env.NEXT_PUBLIC_PROJECT_VERSION}</h1>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -1,15 +0,0 @@
|
||||
"use client"
|
||||
import {useSidebar} from "@/components/ui/sidebar";
|
||||
|
||||
export type SideBarLogoProps = {}
|
||||
|
||||
export const SideBarLogo = (props: SideBarLogoProps) => {
|
||||
const { state, isMobile } = useSidebar();
|
||||
return (
|
||||
<div className="flex justify-center items-center ">
|
||||
<h1 className="font-bold text-xl">
|
||||
{state === 'collapsed' && !isMobile ? "P" : "Portabase"}
|
||||
</h1>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { JSX, useEffect, useState } from "react";
|
||||
import Link from "next/link";
|
||||
import {
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu as SM,
|
||||
SidebarMenuAction,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
} from "@/components/ui/sidebar";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { buttonVariants } from "@/components/ui/button";
|
||||
import { ChevronDown, MoreHorizontal } from "lucide-react";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
|
||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
||||
|
||||
export type SidebarMenuProps = {
|
||||
baseUrl: string;
|
||||
items: SidebarItem[];
|
||||
};
|
||||
|
||||
type SidebarItemContent = {
|
||||
title: string;
|
||||
url: string;
|
||||
icon: JSX.Element;
|
||||
dropdown?: {
|
||||
title: string;
|
||||
url: string;
|
||||
}[];
|
||||
};
|
||||
|
||||
type SidebarListItem = {
|
||||
type: "list";
|
||||
content: SidebarItemContent;
|
||||
};
|
||||
|
||||
type SidebarCollapseItem = {
|
||||
type: "collapse";
|
||||
title: string;
|
||||
content: SidebarItemContent[];
|
||||
};
|
||||
|
||||
export type SidebarItem = SidebarListItem | SidebarCollapseItem;
|
||||
|
||||
export const SidebarMenu = (props: SidebarMenuProps) => {
|
||||
const pathname = usePathname();
|
||||
|
||||
useEffect(() => {
|
||||
const currentUrl = pathname;
|
||||
|
||||
const currentItem = props.items.find((item) => {
|
||||
if (item.type === "list") {
|
||||
return `${props.baseUrl}/${item.content.url}` === currentUrl;
|
||||
} else if (item.type === "collapse") {
|
||||
return item.content.some((content) => `${props.baseUrl}/${content.url}` === currentUrl);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (currentItem) {
|
||||
if (currentItem.type === "list") {
|
||||
setActiveItem(currentItem.content.title);
|
||||
} else if (currentItem.type === "collapse") {
|
||||
setActiveItem(currentItem.title!);
|
||||
}
|
||||
} else {
|
||||
setActiveItem("");
|
||||
}
|
||||
}, [pathname]);
|
||||
|
||||
const [activeItem, setActiveItem] = useState("");
|
||||
const handleItemClick = (title: string) => {
|
||||
setActiveItem(title);
|
||||
};
|
||||
|
||||
return (
|
||||
<SM>
|
||||
{props.items.map((item, index) =>
|
||||
item.type === "collapse" ? (
|
||||
<Collapsible defaultOpen key={index} className={`group/collapsible`}>
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel asChild>
|
||||
<CollapsibleTrigger>
|
||||
{item.title ?? "Please define a title"}
|
||||
<ChevronDown className="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-180" />
|
||||
</CollapsibleTrigger>
|
||||
</SidebarGroupLabel>
|
||||
<CollapsibleContent>
|
||||
<SidebarGroupContent>
|
||||
{item.content.map((content) => (
|
||||
<SidebarMenuItem key={content.title}>
|
||||
<SidebarMenuButton asChild>
|
||||
<Link
|
||||
className={cn(
|
||||
buttonVariants({
|
||||
size: "lg",
|
||||
variant: activeItem === content.title ? "secondary" : "ghost",
|
||||
}),
|
||||
"justify-start p-0"
|
||||
)}
|
||||
href={`${props.baseUrl}/${content.url}`}
|
||||
onClick={() => handleItemClick(content.title)}
|
||||
>
|
||||
{content.icon}
|
||||
<span>{content.title}</span>
|
||||
</Link>
|
||||
</SidebarMenuButton>
|
||||
|
||||
{content.dropdown && (
|
||||
<SidebarMenuAction>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<SidebarMenuAction>
|
||||
<MoreHorizontal />
|
||||
</SidebarMenuAction>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent side="right" align="start">
|
||||
{content.dropdown.map((dropdown) => (
|
||||
<Link href={`${props.baseUrl}/${dropdown.url}`} className="justify-start p-0">
|
||||
<DropdownMenuItem>
|
||||
<span>{dropdown.title ?? "Please define a title"}</span>
|
||||
</DropdownMenuItem>
|
||||
</Link>
|
||||
))}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</SidebarMenuAction>
|
||||
)}
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
</SidebarGroupContent>
|
||||
</CollapsibleContent>
|
||||
</SidebarGroup>
|
||||
</Collapsible>
|
||||
) : (
|
||||
<SidebarMenuItem key={index}>
|
||||
<SidebarMenuButton asChild>
|
||||
<Link
|
||||
className={cn(
|
||||
buttonVariants({
|
||||
size: "lg",
|
||||
variant: activeItem === item.content.title ? "secondary" : "ghost",
|
||||
}),
|
||||
"justify-start p-0"
|
||||
)}
|
||||
href={`${props.baseUrl}/${item.content.url}`}
|
||||
onClick={() => handleItemClick(item.content.title)}
|
||||
>
|
||||
{item.content.icon}
|
||||
<span>{item.content.title}</span>
|
||||
</Link>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
)
|
||||
)}
|
||||
</SM>
|
||||
);
|
||||
};
|
||||
@@ -1,54 +0,0 @@
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarFooter,
|
||||
SidebarHeader,
|
||||
SidebarMenu as SM,
|
||||
SidebarMenuItem,
|
||||
} from "@/components/ui/sidebar";
|
||||
import {OrganizationCombobox} from "@/components/wrappers/dashboard/organization/organization-combobox";
|
||||
import {SideBarLogo} from "@/components/wrappers/dashboard/sideBar/SideBarLogo/SideBarLogo";
|
||||
import {SideBarFooterCredit} from "@/components/wrappers/dashboard/sideBar/SideBarFooterCredit/SideBarFooterCredit";
|
||||
import {LoggedInButton} from "@/components/wrappers/dashboard/loggedInButton/LoggedInButton";
|
||||
import {SidebarContentA} from "./sidebar-content";
|
||||
import {getActiveMember, getOrganization} from "@/lib/auth/auth";
|
||||
import {notFound} from "next/navigation";
|
||||
|
||||
export async function AppSidebar() {
|
||||
const member = await getActiveMember();
|
||||
|
||||
console.log("member", member);
|
||||
|
||||
if (!member) {
|
||||
return notFound();
|
||||
}
|
||||
|
||||
// const organization = await getOrganization({organizationId: member.organizationId});
|
||||
|
||||
// console.log("organization", organization);
|
||||
|
||||
|
||||
return (
|
||||
<Sidebar collapsible="icon">
|
||||
<SidebarHeader>
|
||||
<SideBarLogo/>
|
||||
<SM>
|
||||
<SidebarMenuItem>
|
||||
<OrganizationCombobox/>
|
||||
</SidebarMenuItem>
|
||||
</SM>
|
||||
</SidebarHeader>
|
||||
<SidebarContent>
|
||||
<SidebarContentA/>
|
||||
</SidebarContent>
|
||||
<SidebarFooter>
|
||||
<SM>
|
||||
<SidebarMenuItem>
|
||||
<LoggedInButton/>
|
||||
</SidebarMenuItem>
|
||||
</SM>
|
||||
<SideBarFooterCredit/>
|
||||
</SidebarFooter>
|
||||
</Sidebar>
|
||||
);
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
"use client";
|
||||
import { SidebarGroup, SidebarGroupLabel, SidebarGroupContent, SidebarContent } from "@/components/ui/sidebar";
|
||||
import { authClient, useSession } from "@/lib/auth/auth-client";
|
||||
import { Layers, ChartArea, Settings, ShieldHalf } from "lucide-react";
|
||||
import { SidebarItem, SidebarMenu } from "./SideBarMenu/SideBarMenu";
|
||||
|
||||
export const SidebarContentA = () => {
|
||||
const { data: activeOrganization } = authClient.useActiveOrganization();
|
||||
const { data: organizations } = authClient.useListOrganizations();
|
||||
const { data: session } = useSession();
|
||||
const member = authClient.useActiveMember(); // Moved here — always called
|
||||
|
||||
|
||||
const appItems: SidebarItem[] = [
|
||||
{
|
||||
type: "list",
|
||||
content: {
|
||||
title: "Projects",
|
||||
url: "projects",
|
||||
icon: <Layers />,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "list",
|
||||
content: {
|
||||
title: "Statistics",
|
||||
url: "statistics",
|
||||
icon: <ChartArea />,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
if (activeOrganization && member?.data?.role === "admin" || member?.data?.role === "owner") {
|
||||
appItems.push({
|
||||
type: "list",
|
||||
content: {
|
||||
title: "Settings",
|
||||
url: "settings",
|
||||
icon: <Settings />,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
const adminItems: SidebarItem[] = [
|
||||
{
|
||||
type: "list",
|
||||
content: {
|
||||
title: "Agents",
|
||||
url: "agents",
|
||||
icon: <ShieldHalf />,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "list",
|
||||
content: {
|
||||
title: "Administration panel",
|
||||
url: "admin",
|
||||
icon: <Settings />,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
activeOrganization && (
|
||||
<>
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>Application</SidebarGroupLabel>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu items={appItems} baseUrl={`/dashboard`} />
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
{(session && (session.user.role === "admin" || session.user.role === "superadmin")) && (
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>Administration</SidebarGroupLabel>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu items={adminItems} baseUrl={`/dashboard`} />
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
)}
|
||||
|
||||
</>
|
||||
|
||||
)
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user