diff --git a/src/lib/hooks/user/useLogin.tsx b/src/lib/hooks/user/useLogin.tsx index 369a6b5..fc53b58 100644 --- a/src/lib/hooks/user/useLogin.tsx +++ b/src/lib/hooks/user/useLogin.tsx @@ -2,7 +2,7 @@ import { useMutation } from "@tanstack/react-query" import { useNavigate } from "@tanstack/react-router" import { toast } from "sonner" import type z from "zod" -import { loginUser } from "@/lib/server/user" +import { user } from "@/lib/server/user" import { loginFormSchema } from "@/lib/validation/user" import { useValidation } from "../useValidation" @@ -16,9 +16,7 @@ export const useLogin = () => { const loginMutation = useMutation({ mutationKey: ["login"], mutationFn: async (data: TLoginForm) => { - const response = await loginUser({ - data - }) + const response = await user.login({ data }) if (response.error) { throw new Error(response.message) diff --git a/src/lib/hooks/user/useSignup.tsx b/src/lib/hooks/user/useSignup.tsx index 395aaf7..0e9ffc1 100644 --- a/src/lib/hooks/user/useSignup.tsx +++ b/src/lib/hooks/user/useSignup.tsx @@ -2,7 +2,7 @@ import { useMutation } from "@tanstack/react-query" import { useNavigate } from "@tanstack/react-router" import { toast } from "sonner" import type z from "zod" -import { signupUser } from "@/lib/server/user" +import { user } from "@/lib/server/user" import { signupFormSchema } from "@/lib/validation/user" import { useValidation } from "../useValidation" @@ -15,7 +15,7 @@ export const useSignup = () => { }) const signup = useMutation({ mutationKey: ["signup"], - mutationFn: async (data: TSignupForm) => signupUser({ data }), + mutationFn: async (data: TSignupForm) => user.signup({ data }), onSuccess: () => { toast.success("Signup successful! Redirecting to login...", { id: "signup" diff --git a/src/lib/server/places.ts b/src/lib/server/places.ts index acb315f..31d9558 100644 --- a/src/lib/server/places.ts +++ b/src/lib/server/places.ts @@ -10,5 +10,8 @@ export const insertUserPlace = createServerFn({ }) export const getUserPlaces = createServerFn().handler(async () => { -return await db.select().from(places).where(eq(places.id_user, "e6472b9d-01a9-4e2e-8bdc-0ddaa9baf5d8")) // No haría falta el where puedo filtrar mediante RSL que solo pueda ver sus places solo los datos que el ha insertado -}) \ No newline at end of file + return await db + .select() + .from(places) + .where(eq(places.id_user, "e6472b9d-01a9-4e2e-8bdc-0ddaa9baf5d8")) // No haría falta el where puedo filtrar mediante RSL que solo pueda ver sus places solo los datos que el ha insertado +}) diff --git a/src/lib/server/user.ts b/src/lib/server/user.ts index dbea281..261f86a 100644 --- a/src/lib/server/user.ts +++ b/src/lib/server/user.ts @@ -1,9 +1,79 @@ import { redirect } from "@tanstack/react-router" import { createServerFn } from "@tanstack/react-start" import { getSupabaseServerClient } from "@/integrations/supabase/supabase" -import { loginFormSchema, signupFormSchema } from "../validation/user" +import { + loginFormSchema, + signupFormSchema, + userListParamsSchema +} from "../validation/user" -export const getUser = createServerFn().handler(async () => { +const login = createServerFn({ method: "POST" }) + .inputValidator(loginFormSchema) + .handler(async ({ data }) => { + const supabase = getSupabaseServerClient() + + const login = await supabase.auth.signInWithPassword({ + email: data.email, + password: data.password + }) + + if (login.error) { + return { + error: true, + message: login.error.message + } + } + + return { + error: false + } + }) + +const logout = createServerFn().handler(async () => { + const supabase = getSupabaseServerClient() + + const { error } = await supabase.auth.signOut() + if (error) { + return { + error: true, + message: error.message + } + } + + throw redirect({ + to: "/", + viewTransition: true, + replace: true + }) +}) + +const signup = createServerFn({ method: "POST" }) + .inputValidator(signupFormSchema) + .handler(async ({ data }) => { + const supabase = getSupabaseServerClient() + const { error } = await supabase.auth.signUp({ + email: data.email, + password: data.password, + options: { + data: { + name: data.name, + location: data.location + } + } + }) + if (error) { + return { + error: true, + message: error.message + } + } + + throw redirect({ + href: data.redirectUrl || "/" + }) + }) + +const userData = createServerFn().handler(async () => { const supabase = getSupabaseServerClient() const { data, error } = await supabase.auth.getUser() if (error || !data.user) { @@ -24,20 +94,16 @@ export const getUser = createServerFn().handler(async () => { } }) -export const loginUser = createServerFn({ - method: "POST" -}) - .inputValidator(loginFormSchema) +const resendConfirmationEmail = createServerFn({ method: "POST" }) + .inputValidator(signupFormSchema.pick({ email: true })) .handler(async ({ data }) => { const supabase = getSupabaseServerClient() - const login = await supabase.auth.signInWithPassword({ - email: data.email, - password: data.password - }) - if (login.error) { + const { error } = await supabase.auth.resetPasswordForEmail(data.email) + + if (error) { return { error: true, - message: login.error.message + message: error.message } } @@ -46,49 +112,32 @@ export const loginUser = createServerFn({ } }) -export const logoutUser = createServerFn().handler(async () => { - const supabase = getSupabaseServerClient() - - const { error } = await supabase.auth.signOut() - if (error) { - return { - error: true, - message: error.message - } - } - - throw redirect({ - to: "/", - viewTransition: true, - replace: true - }) -}) - -export const signupUser = createServerFn({ method: "POST" }) - .inputValidator(signupFormSchema) +const userList = createServerFn() + .inputValidator(userListParamsSchema) .handler(async ({ data }) => { const supabase = getSupabaseServerClient() - const { error } = await supabase.auth.signUp({ - email: data.email, - password: data.password, - options: { - // Estos son los metadatos - data: { - name: data.name, - location: data.location - } - } + const users = await supabase.auth.admin.listUsers({ + page: data.page, + perPage: data.limit }) - if (error) { + + if (users.error) { return { error: true, - message: error.message + message: users.error.message } } - - throw redirect({ - href: data.redirectUrl || "/" - }) + return { + users: users.data, + error: false + } }) -// TODO: Add resend confirmation email function +export const user = { + login, + logout, + signup, + userData, + resendConfirmationEmail, + userList +} diff --git a/src/lib/validation/user.ts b/src/lib/validation/user.ts index 6b6d245..2476828 100644 --- a/src/lib/validation/user.ts +++ b/src/lib/validation/user.ts @@ -18,3 +18,8 @@ export const profileFormSchema = z.object({ firstName: z.string().min(1, "First name is required"), lastName: z.string().min(1, "Last name is required") }) + +export const userListParamsSchema = z.object({ + page: z.number().min(1).default(1), + limit: z.number().min(1).max(100).default(10) +}) diff --git a/src/routes/__root.tsx b/src/routes/__root.tsx index 65bc7a1..b9d8f1c 100644 --- a/src/routes/__root.tsx +++ b/src/routes/__root.tsx @@ -8,7 +8,7 @@ import { import { TanStackRouterDevtools } from "@tanstack/react-router-devtools" import { HeroUIProvider } from "@/integrations/heroui/provider" import { SonnerProvider } from "@/integrations/sonner/provider" -import { getUser } from "@/lib/server/user" +import { user } from "@/lib/server/user" interface MyRouterContext { queryClient: QueryClient @@ -17,9 +17,9 @@ interface MyRouterContext { export const Route = createRootRouteWithContext()({ beforeLoad: async () => { - const user = await getUser() + const userData = await user.userData() return { - ...user + ...userData } }, head: () => ({ diff --git a/src/routes/logout.tsx b/src/routes/logout.tsx index c498b41..e3c3363 100644 --- a/src/routes/logout.tsx +++ b/src/routes/logout.tsx @@ -1,7 +1,9 @@ import { createFileRoute } from "@tanstack/react-router" -import { logoutUser } from "@/lib/server/user" +import { user } from "@/lib/server/user" export const Route = createFileRoute("/logout")({ - preload: false, - loader: () => logoutUser() + beforeLoad: async () => { + await user.logout() + }, + preload: false })