use zustand to store management
This commit is contained in:
parent
b4eb2dc1ba
commit
22265fc2d2
|
@ -1,6 +1,6 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import * as React from "react";
|
import { useEffect } from "react";
|
||||||
|
|
||||||
import { NavMain } from "@/app/(pages)/(admin)/_components/navigations/nav-main";
|
import { NavMain } from "@/app/(pages)/(admin)/_components/navigations/nav-main";
|
||||||
import { NavReports } from "@/app/(pages)/(admin)/_components/navigations/nav-report";
|
import { NavReports } from "@/app/(pages)/(admin)/_components/navigations/nav-report";
|
||||||
|
@ -17,26 +17,25 @@ import { NavPreMain } from "./navigations/nav-pre-main";
|
||||||
import { navData } from "@/prisma/data/nav";
|
import { navData } from "@/prisma/data/nav";
|
||||||
import { TeamSwitcher } from "../../../_components/team-switcher";
|
import { TeamSwitcher } from "../../../_components/team-switcher";
|
||||||
import { useGetCurrentUserQuery } from "../dashboard/user-management/_queries/queries";
|
import { useGetCurrentUserQuery } from "../dashboard/user-management/_queries/queries";
|
||||||
|
import { useUserStore } from "@/app/_utils/zustand/stores/user";
|
||||||
|
import { useUserActionsHandler } from "../dashboard/user-management/_handlers/actions/use-user-actions";
|
||||||
|
|
||||||
|
|
||||||
export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
||||||
const { data: user, isPending, error } = useGetCurrentUserQuery()
|
const { data: user, isPending, error } = useGetCurrentUserQuery()
|
||||||
|
|
||||||
// React.useEffect(() => {
|
const { setUser, setIsPending } = useUserStore();
|
||||||
// async function fetchUser() {
|
|
||||||
// try {
|
|
||||||
// setIsLoading(true);
|
|
||||||
// const userData = await getCurrentUser();
|
|
||||||
// setUser(userData.data.user);
|
|
||||||
// } catch (error) {
|
|
||||||
// console.error("Failed to fetch user:", error);
|
|
||||||
// } finally {
|
|
||||||
// setIsLoading(false);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fetchUser();
|
// Set pending state
|
||||||
// }, []);
|
useEffect(() => {
|
||||||
|
setIsPending(isPending);
|
||||||
|
}, [isPending, setIsPending]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (user) {
|
||||||
|
setUser(user);
|
||||||
|
}
|
||||||
|
}, [user, setUser]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sidebar collapsible="icon" {...props}>
|
<Sidebar collapsible="icon" {...props}>
|
||||||
|
@ -49,7 +48,7 @@ export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
||||||
<NavReports reports={navData.reports} />
|
<NavReports reports={navData.reports} />
|
||||||
</SidebarContent>
|
</SidebarContent>
|
||||||
<SidebarFooter>
|
<SidebarFooter>
|
||||||
<NavUser user={user ?? null} />
|
<NavUser />
|
||||||
</SidebarFooter>
|
</SidebarFooter>
|
||||||
<SidebarRail />
|
<SidebarRail />
|
||||||
</Sidebar>
|
</Sidebar>
|
||||||
|
|
|
@ -29,8 +29,18 @@ import type { IUserSchema } from "@/src/entities/models/users/users.model";
|
||||||
import { SettingsDialog } from "../settings/setting-dialog";
|
import { SettingsDialog } from "../settings/setting-dialog";
|
||||||
import { AlertDialog, AlertDialogTrigger, AlertDialogContent, AlertDialogHeader, AlertDialogFooter, AlertDialogTitle, AlertDialogDescription, AlertDialogCancel, AlertDialogAction } from "@/app/_components/ui/alert-dialog";
|
import { AlertDialog, AlertDialogTrigger, AlertDialogContent, AlertDialogHeader, AlertDialogFooter, AlertDialogTitle, AlertDialogDescription, AlertDialogCancel, AlertDialogAction } from "@/app/_components/ui/alert-dialog";
|
||||||
import { useSignOutHandler } from "@/app/(pages)/(auth)/_handlers/use-sign-out";
|
import { useSignOutHandler } from "@/app/(pages)/(auth)/_handlers/use-sign-out";
|
||||||
|
import { useGetCurrentUserQuery } from "../../dashboard/user-management/_queries/queries";
|
||||||
|
import { useUserStore } from "@/app/_utils/zustand/stores/user";
|
||||||
|
|
||||||
|
interface NavUserProps {
|
||||||
|
user: IUserSchema | null;
|
||||||
|
isPending: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function NavUser() {
|
||||||
|
|
||||||
|
const { user, isPending } = useUserStore()
|
||||||
|
|
||||||
export function NavUser({ user }: { user: IUserSchema | null }) {
|
|
||||||
const { isMobile } = useSidebar();
|
const { isMobile } = useSidebar();
|
||||||
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
||||||
|
|
||||||
|
@ -59,9 +69,9 @@ export function NavUser({ user }: { user: IUserSchema | null }) {
|
||||||
return "U";
|
return "U";
|
||||||
};
|
};
|
||||||
|
|
||||||
const { handleSignOut, isPending, errors, error } = useSignOutHandler();
|
const { handleSignOut, isPending: isSignOutPending, errors, error: isSignOutError } = useSignOutHandler();
|
||||||
|
|
||||||
function LogoutButton({ handleSignOut, isPending }: { handleSignOut: () => void; isPending: boolean }) {
|
function LogoutButton({ handleSignOut, isSignOutPending }: { handleSignOut: () => void; isSignOutPending: boolean }) {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -72,11 +82,20 @@ export function NavUser({ user }: { user: IUserSchema | null }) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setOpen(true); // Buka dialog saat diklik
|
setOpen(true); // Buka dialog saat diklik
|
||||||
}}
|
}}
|
||||||
disabled={isPending}
|
disabled={isSignOutPending}
|
||||||
className="space-x-2"
|
className="space-x-2"
|
||||||
>
|
>
|
||||||
|
{isSignOutPending ? (
|
||||||
|
<>
|
||||||
|
<Loader2 className="size-4 animate-spin" />
|
||||||
|
<span>Logging out...</span>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
<IconLogout className="size-4" />
|
<IconLogout className="size-4" />
|
||||||
<span>Log out</span>
|
<span>Log out</span>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
|
||||||
{/* Alert Dialog */}
|
{/* Alert Dialog */}
|
||||||
|
@ -94,14 +113,14 @@ export function NavUser({ user }: { user: IUserSchema | null }) {
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleSignOut();
|
handleSignOut();
|
||||||
|
|
||||||
if (!isPending) {
|
if (!isSignOutPending) {
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
disabled={isPending}
|
disabled={isSignOutPending}
|
||||||
>
|
>
|
||||||
{isPending ? (
|
{isSignOutPending ? (
|
||||||
<>
|
<>
|
||||||
<Loader2 className="size-4" />
|
<Loader2 className="size-4" />
|
||||||
<span>Logging You Out...</span>
|
<span>Logging You Out...</span>
|
||||||
|
@ -126,6 +145,16 @@ export function NavUser({ user }: { user: IUserSchema | null }) {
|
||||||
size="lg"
|
size="lg"
|
||||||
className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
|
className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
|
||||||
>
|
>
|
||||||
|
{isPending ? (
|
||||||
|
<div className="flex items-center space-x-2 animate-pulse">
|
||||||
|
<div className="h-8 w-8 rounded-lg bg-muted" />
|
||||||
|
<div className="flex-1 space-y-1">
|
||||||
|
<div className="h-4 w-24 rounded bg-muted" />
|
||||||
|
<div className="h-3 w-16 rounded bg-muted" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
<Avatar className="h-8 w-8 rounded-lg">
|
<Avatar className="h-8 w-8 rounded-lg">
|
||||||
<AvatarImage src={userAvatar || ""} alt={username} />
|
<AvatarImage src={userAvatar || ""} alt={username} />
|
||||||
<AvatarFallback className="rounded-lg">
|
<AvatarFallback className="rounded-lg">
|
||||||
|
@ -137,8 +166,11 @@ export function NavUser({ user }: { user: IUserSchema | null }) {
|
||||||
<span className="truncate text-xs">{userEmail}</span>
|
<span className="truncate text-xs">{userEmail}</span>
|
||||||
</div>
|
</div>
|
||||||
<ChevronsUpDown className="ml-auto size-4" />
|
<ChevronsUpDown className="ml-auto size-4" />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</SidebarMenuButton>
|
</SidebarMenuButton>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
|
{!isPending && (
|
||||||
<DropdownMenuContent
|
<DropdownMenuContent
|
||||||
className="w-[--radix-dropdown-menu-trigger-width] min-w-56 rounded-lg"
|
className="w-[--radix-dropdown-menu-trigger-width] min-w-56 rounded-lg"
|
||||||
side={isMobile ? "bottom" : "right"}
|
side={isMobile ? "bottom" : "right"}
|
||||||
|
@ -171,7 +203,6 @@ export function NavUser({ user }: { user: IUserSchema | null }) {
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuGroup>
|
<DropdownMenuGroup>
|
||||||
<SettingsDialog
|
<SettingsDialog
|
||||||
user={user}
|
|
||||||
trigger={
|
trigger={
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
className="space-x-2"
|
className="space-x-2"
|
||||||
|
@ -186,8 +217,9 @@ export function NavUser({ user }: { user: IUserSchema | null }) {
|
||||||
/>
|
/>
|
||||||
</DropdownMenuGroup>
|
</DropdownMenuGroup>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<LogoutButton handleSignOut={handleSignOut} isPending={isPending} />
|
<LogoutButton handleSignOut={handleSignOut} isSignOutPending={isSignOutPending} />
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
|
)}
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</SidebarMenuItem>
|
</SidebarMenuItem>
|
||||||
</SidebarMenu>
|
</SidebarMenu>
|
||||||
|
|
|
@ -46,65 +46,6 @@ interface ProfileSettingsProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ProfileSettings({ user }: ProfileSettingsProps) {
|
export function ProfileSettings({ user }: ProfileSettingsProps) {
|
||||||
// const [isPending, setIsepisPending] = useState(false);
|
|
||||||
// const fileInputRef = useRef<HTMLInputElement>(null);
|
|
||||||
|
|
||||||
// // Use profile data with fallbacks
|
|
||||||
// const username = user?.profile?.username || "";
|
|
||||||
// const email = user?.email || "";
|
|
||||||
// const userAvatar = user?.profile?.avatar || "";
|
|
||||||
|
|
||||||
// const form = useForm<ProfileFormValues>({
|
|
||||||
// resolver: zodResolver(profileFormSchema),
|
|
||||||
// defaultValues: {
|
|
||||||
// username: username || "",
|
|
||||||
// avatar: userAvatar || "",
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
|
|
||||||
// const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
||||||
// const file = e.target.files?.[0];
|
|
||||||
|
|
||||||
// if (!file || !user?.id || !user?.email) return;
|
|
||||||
|
|
||||||
// try {
|
|
||||||
// setIsepisPending(true);
|
|
||||||
|
|
||||||
// // Upload avatar to storage
|
|
||||||
// // const publicUrl = await uploadAvatar(user.id, user.email, file);
|
|
||||||
|
|
||||||
// // console.log("publicUrl", publicUrl);
|
|
||||||
|
|
||||||
// // Update the form value
|
|
||||||
// // form.setValue("avatar", publicUrl);
|
|
||||||
// } catch (error) {
|
|
||||||
// console.error("Error uploading avatar:", error);
|
|
||||||
// } finally {
|
|
||||||
// setIsepisPending(false);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// const handleAvatarClick = () => {
|
|
||||||
// fileInputRef.current?.click();
|
|
||||||
// };
|
|
||||||
|
|
||||||
// async function onSubmit(data: ProfileFormValues) {
|
|
||||||
// try {
|
|
||||||
// if (!user?.id) return;
|
|
||||||
|
|
||||||
// // Update profile in database
|
|
||||||
// const { error } = await updateUser(user.id, {
|
|
||||||
// profile: {
|
|
||||||
// avatar: data.avatar || undefined,
|
|
||||||
// username: data.username || undefined,
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
|
|
||||||
// if (error) throw error;
|
|
||||||
// } catch (error) {
|
|
||||||
// console.error("Error updating profile:", error);
|
|
||||||
// }
|
|
||||||
|
|
||||||
const email = user?.email || "";
|
const email = user?.email || "";
|
||||||
const username = user?.profile?.username || "";
|
const username = user?.profile?.username || "";
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import type { User } from "@/src/entities/models/users/users.model";
|
|
||||||
import { Button } from "@/app/_components/ui/button";
|
import { Button } from "@/app/_components/ui/button";
|
||||||
import { Separator } from "@/app/_components/ui/separator";
|
import { Separator } from "@/app/_components/ui/separator";
|
||||||
|
import { IUserSchema } from "@/src/entities/models/users/users.model";
|
||||||
|
|
||||||
interface SecuritySettingsProps {
|
interface SecuritySettingsProps {
|
||||||
user: User | null;
|
user: IUserSchema | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SecuritySettings({ user }: SecuritySettingsProps) {
|
export function SecuritySettings({ user }: SecuritySettingsProps) {
|
||||||
|
|
|
@ -36,9 +36,9 @@ import NotificationsSetting from "./notification-settings";
|
||||||
import PreferencesSettings from "./preference-settings";
|
import PreferencesSettings from "./preference-settings";
|
||||||
import ImportData from "./import-data";
|
import ImportData from "./import-data";
|
||||||
import { IUserSchema } from "@/src/entities/models/users/users.model";
|
import { IUserSchema } from "@/src/entities/models/users/users.model";
|
||||||
|
import { useUserStore } from "@/app/_utils/zustand/stores/user";
|
||||||
|
|
||||||
interface SettingsDialogProps {
|
interface SettingsDialogProps {
|
||||||
user: IUserSchema | null;
|
|
||||||
trigger: React.ReactNode;
|
trigger: React.ReactNode;
|
||||||
defaultTab?: string;
|
defaultTab?: string;
|
||||||
open?: boolean;
|
open?: boolean;
|
||||||
|
@ -58,12 +58,14 @@ interface SettingsSection {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SettingsDialog({
|
export function SettingsDialog({
|
||||||
user,
|
|
||||||
trigger,
|
trigger,
|
||||||
defaultTab = "account",
|
defaultTab = "account",
|
||||||
open,
|
open,
|
||||||
onOpenChange,
|
onOpenChange,
|
||||||
}: SettingsDialogProps) {
|
}: SettingsDialogProps) {
|
||||||
|
|
||||||
|
const { user, isPending } = useUserStore();
|
||||||
|
|
||||||
const [selectedTab, setSelectedTab] = useState(defaultTab);
|
const [selectedTab, setSelectedTab] = useState(defaultTab);
|
||||||
|
|
||||||
// Get user display name
|
// Get user display name
|
||||||
|
@ -130,13 +132,23 @@ export function SettingsDialog({
|
||||||
<ScrollArea className="h-[600px]">
|
<ScrollArea className="h-[600px]">
|
||||||
<div className="p-2">
|
<div className="p-2">
|
||||||
<div className="flex items-center gap-2 px-3 py-2">
|
<div className="flex items-center gap-2 px-3 py-2">
|
||||||
|
{isPending ? (
|
||||||
|
<div className="h-8 w-8 rounded-full bg-muted animate-pulse" />
|
||||||
|
) : (
|
||||||
<Avatar className="h-8 w-8">
|
<Avatar className="h-8 w-8">
|
||||||
<AvatarImage src={userAvatar} alt={displayName} />
|
<AvatarImage src={userAvatar} alt={displayName} />
|
||||||
<AvatarFallback>
|
<AvatarFallback>
|
||||||
{displayName[0].toUpperCase()}
|
{displayName[0].toUpperCase()}
|
||||||
</AvatarFallback>
|
</AvatarFallback>
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<span className="text-sm font-medium">{displayName}</span>
|
)}
|
||||||
|
<span className="text-sm font-medium">
|
||||||
|
{isPending ? (
|
||||||
|
<div className="h-4 w-24 rounded bg-muted animate-pulse" />
|
||||||
|
) : (
|
||||||
|
displayName
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{sections.map((section, index) => (
|
{sections.map((section, index) => (
|
||||||
<div key={section.title} className="py-2">
|
<div key={section.title} className="py-2">
|
||||||
|
@ -173,7 +185,13 @@ export function SettingsDialog({
|
||||||
|
|
||||||
{/* Content */}
|
{/* Content */}
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<div className="flex-1">{currentTab?.content}</div>
|
<div className="flex-1">
|
||||||
|
{isPending ? (
|
||||||
|
<div className="h-full w-full animate-pulse bg-muted" />
|
||||||
|
) : (
|
||||||
|
currentTab?.content
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
|
|
|
@ -39,9 +39,8 @@ export const useSignInWithPasswordHandler = () => {
|
||||||
formData.append('email', data.email);
|
formData.append('email', data.email);
|
||||||
formData.append('password', data.password);
|
formData.append('password', data.password);
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
toast.promise(
|
await toast.promise(
|
||||||
signInWithPassword(formData),
|
signInWithPassword(formData),
|
||||||
{
|
{
|
||||||
loading: 'Signing in...',
|
loading: 'Signing in...',
|
||||||
|
@ -52,6 +51,7 @@ export const useSignInWithPasswordHandler = () => {
|
||||||
},
|
},
|
||||||
error: (err) => {
|
error: (err) => {
|
||||||
const errorMessage = err?.message || 'Failed to send email.';
|
const errorMessage = err?.message || 'Failed to send email.';
|
||||||
|
|
||||||
setError(errorMessage);
|
setError(errorMessage);
|
||||||
return errorMessage;
|
return errorMessage;
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,7 @@ export const useSignInWithPasswordHandler = () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Extract the validation error message for the email field
|
// Extract the validation error message for the email field
|
||||||
const getFieldErrorMessage = (fieldName: keyof ISignInWithPasswordSchema) => {
|
const getFieldErrorMessage = (fieldName: keyof ISignInWithPasswordSchema) => {
|
||||||
return formErrors[fieldName]?.message || '';
|
return formErrors[fieldName]?.message || '';
|
||||||
|
|
|
@ -62,8 +62,12 @@ export async function signInWithPassword(formData: FormData) {
|
||||||
const email = formData.get("email")?.toString()
|
const email = formData.get("email")?.toString()
|
||||||
const password = formData.get("password")?.toString()
|
const password = formData.get("password")?.toString()
|
||||||
|
|
||||||
|
console.log("woi:", email + " " + password)
|
||||||
|
|
||||||
const signInWithPasswordController = getInjection("ISignInWithPasswordController")
|
const signInWithPasswordController = getInjection("ISignInWithPasswordController")
|
||||||
return await signInWithPasswordController({ email, password })
|
await signInWithPasswordController({ email, password })
|
||||||
|
|
||||||
|
return { success: true }
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err instanceof InputParseError) {
|
if (err instanceof InputParseError) {
|
||||||
return { error: err.message }
|
return { error: err.message }
|
||||||
|
|
|
@ -29,6 +29,7 @@ export function SignInWithPasswordForm({
|
||||||
// Get the current active handler based on state
|
// Get the current active handler based on state
|
||||||
const activeHandler = isSignInWithPassword ? passwordHandler : passwordlessHandler;
|
const activeHandler = isSignInWithPassword ? passwordHandler : passwordlessHandler;
|
||||||
|
|
||||||
|
|
||||||
// Toggle password form field
|
// Toggle password form field
|
||||||
const togglePasswordField = () => {
|
const togglePasswordField = () => {
|
||||||
setIsSignInWithPassword(!isSignInWithPassword);
|
setIsSignInWithPassword(!isSignInWithPassword);
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { IUserSchema } from "@/src/entities/models/users/users.model";
|
||||||
|
import { create } from "zustand";
|
||||||
|
|
||||||
|
interface UserState {
|
||||||
|
user: IUserSchema | null;
|
||||||
|
isPending: boolean;
|
||||||
|
setUser: (user: IUserSchema | null) => void;
|
||||||
|
setIsPending: (isPending: boolean) => void;
|
||||||
|
logout: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useUserStore = create<UserState>((set) => ({
|
||||||
|
user: null,
|
||||||
|
isPending: false,
|
||||||
|
setUser: (user) => set({ user }),
|
||||||
|
setIsPending: (isPending) => set({ isPending }),
|
||||||
|
logout: () => set({ user: null, isPending: false }),
|
||||||
|
}));
|
|
@ -50,7 +50,8 @@
|
||||||
"resend": "^4.1.2",
|
"resend": "^4.1.2",
|
||||||
"sonner": "^2.0.1",
|
"sonner": "^2.0.1",
|
||||||
"vaul": "^1.1.2",
|
"vaul": "^1.1.2",
|
||||||
"zod": "^3.24.2"
|
"zod": "^3.24.2",
|
||||||
|
"zustand": "^5.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tanstack/eslint-plugin-query": "^5.67.2",
|
"@tanstack/eslint-plugin-query": "^5.67.2",
|
||||||
|
@ -10787,6 +10788,35 @@
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/colinhacks"
|
"url": "https://github.com/sponsors/colinhacks"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"node_modules/zustand": {
|
||||||
|
"version": "5.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.3.tgz",
|
||||||
|
"integrity": "sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.20.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": ">=18.0.0",
|
||||||
|
"immer": ">=9.0.6",
|
||||||
|
"react": ">=18.0.0",
|
||||||
|
"use-sync-external-store": ">=1.2.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"immer": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"use-sync-external-store": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,8 @@
|
||||||
"resend": "^4.1.2",
|
"resend": "^4.1.2",
|
||||||
"sonner": "^2.0.1",
|
"sonner": "^2.0.1",
|
||||||
"vaul": "^1.1.2",
|
"vaul": "^1.1.2",
|
||||||
"zod": "^3.24.2"
|
"zod": "^3.24.2",
|
||||||
|
"zustand": "^5.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tanstack/eslint-plugin-query": "^5.67.2",
|
"@tanstack/eslint-plugin-query": "^5.67.2",
|
||||||
|
|
|
@ -59,6 +59,8 @@ export class AuthenticationService implements IAuthenticationService {
|
||||||
const supabase = await this.supabaseServer
|
const supabase = await this.supabaseServer
|
||||||
|
|
||||||
const { email, password } = credentials
|
const { email, password } = credentials
|
||||||
|
|
||||||
|
|
||||||
const signIn = supabase.auth.signInWithPassword({ email, password })
|
const signIn = supabase.auth.signInWithPassword({ email, password })
|
||||||
|
|
||||||
const { data: { session }, error } = await this.instrumentationService.startSpan({
|
const { data: { session }, error } = await this.instrumentationService.startSpan({
|
||||||
|
|
Loading…
Reference in New Issue