From 2d86881f943485d90a85efce7c91a7eb98ca06aa Mon Sep 17 00:00:00 2001 From: Jose Selesan Date: Thu, 9 Apr 2026 23:01:09 -0300 Subject: [PATCH] Added 'No show' status. Edit user profile --- apps/frontend/package.json | 2 + apps/frontend/src/components/ui/form.tsx | 174 +++++++++++++ .../complex/components/court-form-section.tsx | 2 +- apps/frontend/src/features/home/home-page.tsx | 31 ++- .../src/features/layout/root-layout.tsx | 7 - .../src/features/profile/profile-page.tsx | 238 +++++++++++++++--- apps/frontend/src/lib/auth.tsx | 31 +++ 7 files changed, 440 insertions(+), 45 deletions(-) create mode 100644 apps/frontend/src/components/ui/form.tsx diff --git a/apps/frontend/package.json b/apps/frontend/package.json index 2ff3ab3..83709d9 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -12,6 +12,8 @@ "dependencies": { "@fontsource-variable/geist": "^5.2.8", "@hookform/resolvers": "^5.2.2", + "@radix-ui/react-label": "^2.1.8", + "@radix-ui/react-slot": "^1.2.4", "@repo/api-contract": "workspace:*", "@supabase/supabase-js": "^2.101.1", "@tanstack/react-query": "^5.96.1", diff --git a/apps/frontend/src/components/ui/form.tsx b/apps/frontend/src/components/ui/form.tsx new file mode 100644 index 0000000..e984e3f --- /dev/null +++ b/apps/frontend/src/components/ui/form.tsx @@ -0,0 +1,174 @@ +import * as React from "react" +import * as LabelPrimitive from "@radix-ui/react-label" +import { Slot } from "@radix-ui/react-slot" +import type { + ControllerProps, + FieldPath, + FieldValues, +} from "react-hook-form" +import { Controller, FormProvider, useFormContext } from "react-hook-form" + +import { cn } from "@/lib/utils" +import { Label } from "@/components/ui/label" + +const Form = FormProvider + +type FormFieldContextValue< + TFieldValues extends FieldValues = FieldValues, + TName extends FieldPath = FieldPath +> = { + name: TName +} + +const FormFieldContext = React.createContext( + {} as FormFieldContextValue +) + +const FormField = < + TFieldValues extends FieldValues = FieldValues, + TName extends FieldPath = FieldPath +>({ + ...props +}: ControllerProps) => { + return ( + + + + ) +} + +const useFormField = () => { + const fieldContext = React.useContext(FormFieldContext) + const itemContext = React.useContext(FormItemContext) + const { getFieldState, formState } = useFormContext() + + const fieldState = getFieldState(fieldContext.name, formState) + + if (!fieldContext) { + throw new Error("useFormField should be used within ") + } + + const { id } = itemContext + + return { + id, + name: fieldContext.name, + formItemId: `${id}-form-item`, + formDescriptionId: `${id}-form-item-description`, + formMessageId: `${id}-form-item-message`, + ...fieldState, + } +} + +type FormItemContextValue = { + id: string +} + +const FormItemContext = React.createContext( + {} as FormItemContextValue +) + +const FormItem = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => { + const id = React.useId() + + return ( + +
+ + ) +}) +FormItem.displayName = "FormItem" + +const FormLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => { + const { error, formItemId } = useFormField() + + return ( +
) } diff --git a/apps/frontend/src/lib/auth.tsx b/apps/frontend/src/lib/auth.tsx index f950f62..4f7fd15 100644 --- a/apps/frontend/src/lib/auth.tsx +++ b/apps/frontend/src/lib/auth.tsx @@ -21,6 +21,14 @@ type SignUpParams = { fullName: string } +type UpdateProfileParams = { + fullName: string +} + +type UpdatePasswordParams = { + password: string +} + export type AuthContextValue = { user: User | null session: Session | null @@ -31,6 +39,8 @@ export type AuthContextValue = { avatarUrl: string | null signInWithPassword: (params: SignInParams) => Promise signUp: (params: SignUpParams) => Promise<{ requiresEmailConfirmation: boolean }> + updateProfile: (params: UpdateProfileParams) => Promise + updatePassword: (params: UpdatePasswordParams) => Promise signOut: () => Promise } @@ -143,6 +153,27 @@ export function AuthProvider({ children }: PropsWithChildren) { requiresEmailConfirmation: !data.session, } }, + updateProfile: async ({ fullName }) => { + const { error } = await supabase.auth.updateUser({ + data: { + full_name: fullName, + name: fullName, + }, + }) + + if (error) { + throw error + } + }, + updatePassword: async ({ password }) => { + const { error } = await supabase.auth.updateUser({ + password, + }) + + if (error) { + throw error + } + }, signOut: async () => { const { error } = await supabase.auth.signOut() if (error) {