-
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
# Summary - Se agrega ventana de modificación de datos básicos de usuario ## Reference ![profile](https://github.com/user-attachments/assets/c9ea1c07-b7ad-49eb-8987-df0c343295bd) ![edit_profile](https://github.com/user-attachments/assets/a8c25e7d-436d-4ef8-8136-299b6d60e23b)
- Loading branch information
Showing
16 changed files
with
671 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
import { zodResolver } from "@hookform/resolvers/zod"; | ||
import { Link, useNavigate } from "@remix-run/react"; | ||
import { useEffect } from "react"; | ||
import { useForm } from "react-hook-form"; | ||
import { toast } from "sonner"; | ||
import { z } from "zod"; | ||
|
||
import { useMyProfileSuspenseQuery } from "~/components/Profile/graphql/myProfile.generated"; | ||
import { Button, buttonVariants } from "~/components/ui/button"; | ||
import { Card, CardContent, CardTitle } from "~/components/ui/card"; | ||
import { | ||
Form, | ||
FormControl, | ||
FormField, | ||
FormItem, | ||
FormLabel, | ||
FormMessage, | ||
} from "~/components/ui/form"; | ||
import { Input } from "~/components/ui/input"; | ||
import { urls } from "~/utils/urls"; | ||
import { cn } from "~/utils/utils"; | ||
|
||
import { useUpdateUserMutation } from "./graphql/updateUser.generated"; | ||
|
||
const UpdateUserSchema = z.object({ | ||
name: z | ||
.string({ required_error: "El nombre es requerido." }) | ||
.min(1, "El nombre es requerido."), | ||
lastName: z | ||
.string({ required_error: "El apellido es requerido." }) | ||
.min(1, "El apellido es requerido."), | ||
username: z | ||
.string({ required_error: "El nombre de usaurio es requerido." }) | ||
.min(1, "El nombre de usaurio es requerido."), | ||
}); | ||
|
||
const USERNAME_ALREADY_EXISTS = | ||
'duplicate key value violates unique constraint "users_username_unique"'; | ||
|
||
export const MyProfileInfo = () => { | ||
const navigate = useNavigate(); | ||
const { data } = useMyProfileSuspenseQuery(); | ||
const [updateUser, { loading: isLoading }] = useUpdateUserMutation(); | ||
|
||
const form = useForm<z.infer<typeof UpdateUserSchema>>({ | ||
resolver: zodResolver(UpdateUserSchema), | ||
defaultValues: { | ||
name: "", | ||
lastName: "", | ||
username: "", | ||
}, | ||
}); | ||
|
||
useEffect(() => { | ||
form.setValue("name", data.me?.name ?? ""); | ||
form.setValue("lastName", data.me?.lastName ?? ""); | ||
form.setValue("username", data.me?.username ?? ""); | ||
}, [form, data]); | ||
|
||
const onSubmit = async ({ | ||
name, | ||
lastName, | ||
username, | ||
}: z.infer<typeof UpdateUserSchema>) => { | ||
await updateUser({ | ||
variables: { | ||
input: { | ||
id: data.me.id, | ||
name, | ||
lastName, | ||
username, | ||
}, | ||
}, | ||
onCompleted() { | ||
toast.success("Datos Actualizados.", { | ||
description: "Los datos se han actualizado correctamente.", | ||
}); | ||
navigate(urls.profile.root); | ||
}, | ||
onError(error) { | ||
const message = | ||
error.message == USERNAME_ALREADY_EXISTS | ||
? "Nombre de usuario en uso. Debes elegir otro nombre de usuario" | ||
: "Error Desconocido"; | ||
|
||
toast.error("Hubo un error.", { | ||
description: `${message}. Verifica que hayas ingresado correctamente la información e intenta nuevamente, si el error persiste comunicate con el equipo.`, | ||
}); | ||
}, | ||
}); | ||
}; | ||
|
||
return ( | ||
<div className="mx-auto w-full max-w-[800px] md:p-4"> | ||
<div> | ||
<Card className="mx-auto w-full max-w-md rounded-xl shadow-md lg:w-96"> | ||
<CardTitle className="p-6 pb-4 text-xl font-semibold"> | ||
Datos Básicos | ||
</CardTitle> | ||
<CardContent> | ||
<Form {...form}> | ||
<form | ||
onSubmit={(event) => void form.handleSubmit(onSubmit)(event)} | ||
className={"grid w-full items-start gap-6 pt-0"} | ||
> | ||
<FormField | ||
control={form.control} | ||
name="name" | ||
render={({ field }) => ( | ||
<FormItem> | ||
<FormLabel>Nombre</FormLabel> | ||
<FormControl> | ||
<Input placeholder="Nombre" {...field} /> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
|
||
<FormField | ||
control={form.control} | ||
name="lastName" | ||
render={({ field }) => ( | ||
<FormItem> | ||
<FormLabel>Apellido</FormLabel> | ||
<FormControl> | ||
<Input placeholder="Apellido" {...field} /> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
|
||
<FormField | ||
control={form.control} | ||
name="username" | ||
render={({ field }) => ( | ||
<FormItem> | ||
<FormLabel>Nombre de Usuario</FormLabel> | ||
<FormControl> | ||
<Input placeholder="Nombre de Usuario" {...field} /> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
<div className="flex flex-col justify-end gap-4 md:flex-row"> | ||
{isLoading ? ( | ||
<Button variant="secondary" disabled> | ||
Cancelar | ||
</Button> | ||
) : ( | ||
<Link | ||
to={urls.profile.root} | ||
className={cn(buttonVariants({ variant: "secondary" }))} | ||
> | ||
Cancelar | ||
</Link> | ||
)} | ||
<Button disabled={isLoading}>Guardar</Button> | ||
</div> | ||
</form> | ||
</Form> | ||
</CardContent> | ||
</Card> | ||
</div> | ||
</div> | ||
); | ||
}; |
47 changes: 47 additions & 0 deletions
47
app/components/Profile/Info/MyProfileInfoLoadingSkeleton.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { Button } from "~/components/ui/button"; | ||
import { Card, CardTitle, CardContent } from "~/components/ui/card"; | ||
import { Label } from "~/components/ui/label"; | ||
import { Skeleton } from "~/components/ui/skeleton"; | ||
|
||
const LoadingCard = () => { | ||
return ( | ||
<div className="mx-auto w-full max-w-[800px] md:p-4"> | ||
<div> | ||
<Card className="mx-auto w-full max-w-md rounded-xl shadow-md lg:w-96"> | ||
<CardTitle className="p-6 pb-4 text-xl font-semibold"> | ||
Datos Básicos | ||
</CardTitle> | ||
<CardContent> | ||
<div className="grid w-full items-start gap-6 pt-0"> | ||
<div className="grid space-y-2"> | ||
<Label className="leading-5">Nombre</Label> | ||
<Skeleton className="mt-1 h-10 w-full" /> | ||
</div> | ||
|
||
<div className="grid space-y-2"> | ||
<Label className="leading-5">Apellido</Label> | ||
<Skeleton className="mt-1 h-10 w-full" /> | ||
</div> | ||
|
||
<div className="grid space-y-2"> | ||
<Label className="leading-5">Nombre de Usuario</Label> | ||
<Skeleton className="mt-1 h-10 w-full" /> | ||
</div> | ||
<div className="flex flex-col justify-end gap-4 md:flex-row"> | ||
<Button variant="secondary">Cancelar</Button> | ||
<Button className="">Guardar</Button> | ||
</div> | ||
</div> | ||
</CardContent> | ||
</Card> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
export const MyProfileInfoLoadingSkeleton = () => { | ||
return ( | ||
<div className="flex flex-col gap-6"> | ||
<LoadingCard /> | ||
</div> | ||
); | ||
}; |
Oops, something went wrong.