feat: build individual user page

This commit is contained in:
pit
2023-09-21 15:10:20 +01:00
parent 775de16d0a
commit 07bf780c3e
3 changed files with 114 additions and 3 deletions

View File

@ -1,8 +1,87 @@
export default function UserPage() {
'use client';
import { Loader } from 'lucide-react';
import { Controller, useForm } from 'react-hook-form';
import { trpc } from '@documenso/trpc/react';
import { Button } from '@documenso/ui/primitives/button';
import { Input } from '@documenso/ui/primitives/input';
import { Label } from '@documenso/ui/primitives/label';
import { SignaturePad } from '@documenso/ui/primitives/signature-pad';
import { useToast } from '@documenso/ui/primitives/use-toast';
import { FormErrorMessage } from '../../../../../components/form/form-error-message';
export default function UserPage({ params }: { params: { id: number } }) {
const toast = useToast();
const result = trpc.profile.getUser.useQuery(
{
id: Number(params.id),
},
{
enabled: !!params.id,
},
);
const {
register,
control,
handleSubmit,
formState: { errors, isSubmitting },
} = useForm();
console.log(result.data);
const onSubmit = async (data) => {
console.log(data);
};
return (
<div>
<h1>Hey</h1>
<h2>Ho</h2>
<h2 className="text-4xl font-semibold">Manage {result.data?.name}'s profile</h2>
<form className="mt-6 flex w-full flex-col gap-y-4" onSubmit={handleSubmit(onSubmit)}>
<div>
<Label htmlFor="name" className="text-muted-foreground">
Name
</Label>
<Input placeholder={result.data?.name} type="text" register={'name'} />
<FormErrorMessage className="mt-1.5" error={errors.name} />
</div>
<div>
<Label htmlFor="email" className="text-muted-foreground">
Email
</Label>
<Input placeholder={result.data?.email} type="text" register={'email'} />
<FormErrorMessage className="mt-1.5" error={errors.email} />
</div>
<div>
<Label htmlFor="signature" className="text-muted-foreground">
Signature
</Label>
<div className="mt-2">
<Controller
control={control}
name="signature"
render={({ field: { onChange } }) => (
<SignaturePad
className="h-44 w-full rounded-lg border bg-white backdrop-blur-sm dark:border-[#e2d7c5] dark:bg-[#fcf8ee]"
defaultValue={result.data?.signature ?? undefined}
onChange={(v) => onChange(v ?? '')}
/>
)}
/>
<FormErrorMessage className="mt-1.5" error={errors.signature} />
</div>
</div>
<div className="mt-4">
<Button type="submit" disabled={isSubmitting}>
{isSubmitting && <Loader className="mr-2 h-5 w-5 animate-spin" />}
Update user
</Button>
</div>
</form>
</div>
);
}

View File

@ -1,6 +1,8 @@
import { TRPCError } from '@trpc/server';
import { isAdmin } from '@documenso/lib/next-auth/guards/is-admin';
import { forgotPassword } from '@documenso/lib/server-only/user/forgot-password';
import { getUserById } from '@documenso/lib/server-only/user/get-user-by-id';
import { resetPassword } from '@documenso/lib/server-only/user/reset-password';
import { updatePassword } from '@documenso/lib/server-only/user/update-password';
import { updateProfile } from '@documenso/lib/server-only/user/update-profile';
@ -9,11 +11,36 @@ import { authenticatedProcedure, procedure, router } from '../trpc';
import {
ZForgotPasswordFormSchema,
ZResetPasswordFormSchema,
ZRetrieveUserByIdQuerySchema,
ZUpdatePasswordMutationSchema,
ZUpdateProfileMutationSchema,
} from './schema';
export const profileRouter = router({
getUser: authenticatedProcedure
.input(ZRetrieveUserByIdQuerySchema)
.query(async ({ input, ctx }) => {
const isUserAdmin = isAdmin(ctx.user);
if (!isUserAdmin) {
throw new TRPCError({
code: 'UNAUTHORIZED',
message: 'Not authorized to perform this action.',
});
}
try {
const { id } = input;
return await getUserById({ id });
} catch (err) {
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'We were unable to retrieve the specified account. Please try again.',
});
}
}),
updateProfile: authenticatedProcedure
.input(ZUpdateProfileMutationSchema)
.mutation(async ({ input, ctx }) => {

View File

@ -1,5 +1,9 @@
import { z } from 'zod';
export const ZRetrieveUserByIdQuerySchema = z.object({
id: z.number().min(1),
});
export const ZUpdateProfileMutationSchema = z.object({
name: z.string().min(1),
signature: z.string(),
@ -18,6 +22,7 @@ export const ZResetPasswordFormSchema = z.object({
token: z.string().min(1),
});
export type TRetrieveUserByIdQuerySchema = z.infer<typeof ZRetrieveUserByIdQuerySchema>;
export type TUpdateProfileMutationSchema = z.infer<typeof ZUpdateProfileMutationSchema>;
export type TUpdatePasswordMutationSchema = z.infer<typeof ZUpdatePasswordMutationSchema>;
export type TForgotPasswordFormSchema = z.infer<typeof ZForgotPasswordFormSchema>;