Skip to content

Commit

Permalink
wip: edit profiles form
Browse files Browse the repository at this point in the history
  • Loading branch information
katallaxie committed Jan 17, 2024
1 parent 5555358 commit 868a633
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 76 deletions.

This file was deleted.

20 changes: 15 additions & 5 deletions packages/app/src/app/dashboard/profiles/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,28 @@ import {
SubNavSubtitle,
SubNavActions
} from '@/components/sub-nav'
import type { PropsWithChildren } from 'react'
import { Section } from '@/components/section'
import { api } from '@/trpc/server-http'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Separator } from '@/components/ui/separator'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import DateFormat from '@/components/date-format'
import { ActionsDropdown } from './components/actions-dropdown'
import { ActionsDropdown } from '@/components/dashboard/profiles/actions-dropdown'
import { EditProfileForm } from '@/components/dashboard/profiles/edit-form'

export type PageProps = {
params: { id: string }
export interface NextPageProps<IdType = string> {
params: { id: IdType }
searchParams?: { [key: string]: string | string[] | undefined }
}

export default async function Page({ params }: PageProps) {
export default async function Page({
params,
searchParams
}: PropsWithChildren<NextPageProps>) {
const profile = await api.getProfile.query(params?.id)
const questions = await api.listProfilesQuestions.query()
const editable = searchParams && searchParams['editable'] !== undefined

return (
<>
Expand Down Expand Up @@ -68,7 +74,11 @@ export default async function Page({ params }: PageProps) {
</CardContent>
</Card>
{profile && (
<EditProfileForm profile={profile} questions={questions} />
<EditProfileForm
profile={profile}
questions={questions}
editable={editable}
/>
)}
</div>
</TabsContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import {
DropdownMenuShortcut,
DropdownMenuTrigger
} from '@/components/ui/dropdown-menu'
import Link from 'next/link'
import { useRouter } from 'next/navigation'
import type { Profile } from '@/db/models/profile'
import { useAction } from '@/trpc/client'
import { rhfActionDeleteProfile } from '@/actions/profile.action'
import { Separator } from '@/components/ui/separator'

interface ActionsDropdownProps {
profile?: Profile | null
Expand All @@ -35,6 +37,15 @@ export function ActionsDropdown({ profile }: ActionsDropdownProps) {
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-[160px]">
{profile && (
<Link href={`/dashboard/profiles/${profile?.id}?editable=true`}>
<DropdownMenuItem>
Edit
<DropdownMenuShortcut>⌘⌫</DropdownMenuShortcut>
</DropdownMenuItem>
</Link>
)}
<Separator />
<DropdownMenuItem onClick={handleOnClickDelete}>
Delete
<DropdownMenuShortcut>⌘⌫</DropdownMenuShortcut>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ export const columns: ColumnDef<Profile>[] = [
header: ({ column }) => (
<DataTableColumnHeader column={column} title="ID" />
),
cell: ({ row }) => <div className="w-[120px]">{row.getValue('id')}</div>,
cell: ({ row }) => (
<div className="w-[120px] truncate">{row.getValue('id')}</div>
),
enableSorting: false,
enableHiding: false
},
Expand All @@ -47,7 +49,7 @@ export const columns: ColumnDef<Profile>[] = [
return (
<div className="flex space-x-2">
{/* {label && <Badge variant="outline">{label.label}</Badge>} */}
<span className="max-w-[500px] truncate font-medium">
<span className="max-w-[500px] font-medium">
<Link href={`/dashboard/profiles/${row.getValue('id')}`}>
{row.getValue('name')}
</Link>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { z } from 'zod'

export const rhfActionSchema = z.object({
selectedChoices: z.record(z.string(), z.array(z.string()).min(1))
})

export type EditProfileFormValues = z.infer<typeof rhfActionSchema>
export const rhfEditProfileActionSchema = z.record(
z.string(),
z.array(z.string()).min(1)
)
export type EditProfileFormValues = z.infer<typeof rhfEditProfileActionSchema>
export const defaultValues: Partial<EditProfileFormValues> = {}
87 changes: 46 additions & 41 deletions packages/app/src/components/dashboard/profiles/edit-form.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client'

import { PropsWithChildren, useDeferredValue, useMemo, useState } from 'react'
import { PropsWithChildren, useMemo, useState } from 'react'
import {
Form,
FormControl,
Expand All @@ -20,13 +20,15 @@ import {
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import { zodResolver } from '@hookform/resolvers/zod'
import { rhfActionSchema } from './new-form.schema'
import { useForm } from 'react-hook-form'
import { z } from 'zod'
import { ProfileQuestion } from '@/db/models/profile-question'
import { Checkbox } from '@/components/ui/checkbox'
import { defaultValues } from './new-form.schema'
import { Profile } from '@/db/models/profile'
import {
EditProfileFormValues,
rhfEditProfileActionSchema,
defaultValues
} from './edit-form.schema'

export type EditProfileFormProps = {
editable?: boolean
Expand All @@ -41,39 +43,42 @@ export function EditProfileForm({
}: PropsWithChildren<EditProfileFormProps>) {
const [isEditable, setIsEditable] = useState(editable)
const selectedChoices = useMemo(() => {
const selected = profile?.answers?.reduce<Record<string, string[]>>(
(prev, curr) => {
if (curr?.question?.ref && curr?.question?.ref in prev) {
return {
...prev,
[curr.question.ref]: [...prev[curr.question.ref], curr.id]
}
}
const question = questions?.reduce(
(questions, question) => ({
...questions,
[question.ref]: []
}),
{} as Record<string, string[]>
)

return {
...prev,
[curr?.question?.ref ?? '']: [curr.id]
}
},
{}
profile?.answers?.forEach(
answer =>
question &&
answer?.question &&
question[answer.question.ref].push(answer.id)
)

return selected
}, [profile])
return question
}, [profile?.answers, questions])

const form = useForm<z.infer<typeof rhfActionSchema>>({
resolver: zodResolver(rhfActionSchema),
defaultValues: {
...defaultValues,
selectedChoices
},
const form = useForm<EditProfileFormValues>({
resolver: zodResolver(rhfEditProfileActionSchema),
defaultValues: selectedChoices,
mode: 'onChange'
})

async function onSubmit(data: EditProfileFormValues) {
console.log(data)
}

return (
<>
<Form {...form}>
<form className="space-y-8" autoComplete="off">
<form
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-8"
autoComplete="off"
>
{questions?.map((question, idx) => (
<Card key={idx}>
<CardHeader>
Expand All @@ -87,7 +92,7 @@ export function EditProfileForm({
key={choice.id}
disabled={!isEditable}
control={form.control}
name={`selectedChoices.${question.ref}`}
name={question.ref}
render={({ field, ...rest }) => {
return (
<FormItem
Expand All @@ -102,20 +107,21 @@ export function EditProfileForm({
onCheckedChange={checked => {
return checked
? field.onChange([
...field.value,
choice.id
])
...field.value,
choice.id
])
: field.onChange(
field.value?.filter(
value => value !== choice.id
)
field.value?.filter(
value => value !== choice.id
)
)
}}
/>
</FormControl>
<FormLabel className="font-normal">
{choice.name}
</FormLabel>
<FormMessage />
</FormItem>
)
}}
Expand All @@ -126,7 +132,7 @@ export function EditProfileForm({
<FormField
key={idx}
control={form.control}
name={`selectedChoices.${question.ref}`}
name={question.ref}
render={({ field }) => (
<div className="grid w-full">
<FormControl>
Expand Down Expand Up @@ -163,12 +169,11 @@ export function EditProfileForm({
</Card>
))}

<Button
type="submit"
disabled={form.formState.isSubmitting || !form.formState.isValid}
>
Add Profile
</Button>
{isEditable && (
<Button type="submit" disabled={form.formState.isSubmitting}>
Update Profile
</Button>
)}
<input
autoComplete="false"
name="hidden"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { z } from 'zod'

export const rhfActionSchema = z.object({
name: z.string().min(1).max(256).default(''),
description: z.string().min(20).max(2048).default(''),
description: z.string().min(20).max(2048).default('').optional(),
selectedChoices: z.record(z.string(), z.array(z.string()).min(1))
})

Expand Down

0 comments on commit 868a633

Please sign in to comment.