|
| 1 | +import { zodResolver } from '@hookform/resolvers/zod' |
| 2 | +import { useRouter } from 'next/router' |
| 3 | +import { useForm } from 'react-hook-form' |
| 4 | +import { toast } from 'react-hot-toast' |
| 5 | + |
| 6 | +import { ROLES } from '@/appdata/list' |
| 7 | +import { AdminLayout } from '@/components/common/layout/AdminLayout' |
| 8 | +import { SelectInput } from '@/components/common/Select' |
| 9 | +import type { GetUser } from '@/types/user' |
| 10 | +import { getUser } from '@/types/user' |
| 11 | +import { trpc } from '@/utils/trpc' |
| 12 | + |
| 13 | +export default function Example() { |
| 14 | + const router = useRouter() |
| 15 | + const utils = trpc.useContext() |
| 16 | + const userDetails = trpc.user.getById.useQuery({ |
| 17 | + id: router.query.id as string, |
| 18 | + }) |
| 19 | + const updateUserRole = trpc.user.updateUserRole.useMutation() |
| 20 | + const { |
| 21 | + register, |
| 22 | + handleSubmit, |
| 23 | + formState: { errors, isSubmitting }, |
| 24 | + } = useForm<GetUser>({ |
| 25 | + resolver: zodResolver(getUser), |
| 26 | + defaultValues: { |
| 27 | + role: userDetails.data?.role, |
| 28 | + }, |
| 29 | + }) |
| 30 | + async function submit(val: GetUser) { |
| 31 | + if (val.role === userDetails.data?.role) { |
| 32 | + toast.error('User role is not changed') |
| 33 | + return |
| 34 | + } |
| 35 | + await updateUserRole.mutate( |
| 36 | + { id: router.query.id as string, ...val }, |
| 37 | + { |
| 38 | + onSuccess() { |
| 39 | + toast.success('Changed user role') |
| 40 | + utils.user.getById.invalidate({ |
| 41 | + id: router.query.id as string, |
| 42 | + }) |
| 43 | + }, |
| 44 | + } |
| 45 | + ) |
| 46 | + } |
| 47 | + return ( |
| 48 | + <AdminLayout> |
| 49 | + <section className="section" aria-labelledby="page-title"> |
| 50 | + <h1 id="page-title" className="heading1"> |
| 51 | + User: {router.query.id} |
| 52 | + </h1> |
| 53 | + {userDetails.isLoading && <p>Loading . . .</p>} |
| 54 | + {userDetails.error && ( |
| 55 | + <p className="text-red-500">{userDetails.error.message}</p> |
| 56 | + )} |
| 57 | + {userDetails.data && ( |
| 58 | + <div className="mx-auto my-4 flow-root max-w-7xl rounded border border-gray-300 p-4 dark:border-gray-700"> |
| 59 | + <img |
| 60 | + src={userDetails.data.image ?? '/unknown.webp'} |
| 61 | + alt={userDetails.data.name || 'random'} |
| 62 | + width="50" |
| 63 | + height="50" |
| 64 | + className="float-left rounded-full" |
| 65 | + /> |
| 66 | + <dl className="grid grid-cols-[max-content,max-content] gap-x-4 space-y-0.5"> |
| 67 | + {userDetails.data.name && ( |
| 68 | + <> |
| 69 | + <dt>Name</dt> |
| 70 | + <dd>{userDetails.data.name}</dd> |
| 71 | + </> |
| 72 | + )} |
| 73 | + <dt>Email</dt> |
| 74 | + <dd className="truncate">{userDetails.data.email}</dd> |
| 75 | + <dt>Created on</dt> |
| 76 | + <dd> |
| 77 | + {userDetails.data.createdAt?.toISOString().substring(0, 10)} |
| 78 | + </dd> |
| 79 | + </dl> |
| 80 | + <form |
| 81 | + onSubmit={handleSubmit((v) => submit(v))} |
| 82 | + className="gap-4 border-t border-gray-300 p-2 font-medium tracking-wider dark:border-gray-700" |
| 83 | + > |
| 84 | + <SelectInput |
| 85 | + label="Roles" |
| 86 | + options={ROLES} |
| 87 | + error={errors.role} |
| 88 | + {...register('role')} |
| 89 | + /> |
| 90 | + <button |
| 91 | + disabled={isSubmitting} |
| 92 | + type="submit" |
| 93 | + className="mt-2 max-w-fit self-center rounded-2xl bg-indigo-700 px-4 py-1.5 text-sm text-white transition hover:shadow-lg dark:bg-indigo-500" |
| 94 | + > |
| 95 | + Update |
| 96 | + </button> |
| 97 | + </form> |
| 98 | + </div> |
| 99 | + )} |
| 100 | + </section> |
| 101 | + </AdminLayout> |
| 102 | + ) |
| 103 | +} |
0 commit comments