Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
NoorFatima01 committed May 4, 2024
2 parents 7a84774 + 1a6fa7d commit 108dd1f
Show file tree
Hide file tree
Showing 3 changed files with 196 additions and 4 deletions.
29 changes: 26 additions & 3 deletions src/app/my-profile/[name]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,34 @@
import React from 'react';

import UserProfile from '@/components/user-profile';
import { getUser } from '@/lib/server-user';
import { createSupabaseServerClient } from '@/lib/supabase/server-clients';

const AccountPage = () => {
import { ProfileForm } from '@/components/forms/profile-form';
import PageDescriptionHeader from '@/components/layout/page-description-header';

const AccountPage = async () => {
const user = await getUser();
const user_id = user?.id;

if (!user_id) return <div>Not logged In</div>;
const serverSupabase = createSupabaseServerClient();

const { data: userData } = await serverSupabase
.from('profiles')
.select('username, email, role')
.eq('id', user_id)
.single();
const defaultValues = {
username: userData?.username as string,
email: userData?.email as string,
};
return (
<div>
<UserProfile />
<PageDescriptionHeader
title='Account'
description='Edit your account details'
/>
<ProfileForm defaultValues={defaultValues} role={userData?.role} />
</div>
);
};
Expand Down
144 changes: 144 additions & 0 deletions src/components/forms/profile-form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
'use client';

import { zodResolver } from '@hookform/resolvers/zod';
import { useFieldArray, useForm } from 'react-hook-form';
import toast from 'react-hot-toast';

import { profileFormSchema, profileFormSchemaType } from '@/lib/schemas';
import { cn } from '@/lib/utils';

import { Button } from '@/components/ui/button';
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/form';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';

interface ProfileFormProps {
defaultValues: Pick<profileFormSchemaType, 'username' | 'email'>;
role: string;
}

// eslint-disable-next-line unused-imports/no-unused-vars
export function ProfileForm({ defaultValues, role }: ProfileFormProps) {
const form = useForm<profileFormSchemaType>({
resolver: zodResolver(profileFormSchema),
defaultValues: {
...defaultValues,
bio: '',
urls: [],
},
mode: 'onChange',
});

const { fields, append } = useFieldArray({
name: 'urls',
control: form.control,
});

// eslint-disable-next-line unused-imports/no-unused-vars
function onSubmit(data: profileFormSchemaType) {
toast.success('Profile updated successfully');
}

return (
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className='mx-auto grid w-full max-w-md gap-6 '
>
<div className='flex justify-between gap-1'>
<div className='flex-1'>
<FormField
control={form.control}
name='username'
render={({ field }) => (
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl>
<Input placeholder='Your Username' {...field} />
</FormControl>

<FormMessage />
</FormItem>
)}
/>
</div>
<div className='flex-1'>
<FormField
control={form.control}
name='email'
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input placeholder='Email' type='email' {...field} />
</FormControl>

<FormMessage />
</FormItem>
)}
/>
</div>
</div>
<FormField
control={form.control}
name='bio'
render={({ field }) => (
<FormItem>
<FormLabel>Bio</FormLabel>
<FormControl>
<Textarea
placeholder='Tell us a little bit about yourself'
className='resize-none'
{...field}
/>
</FormControl>

<FormMessage />
</FormItem>
)}
/>
<div>
{fields.map((field, index) => (
<FormField
control={form.control}
key={field.id}
name={`urls.${index}.value`}
render={({ field }) => (
<FormItem>
<FormLabel className={cn(index !== 0 && 'sr-only')}>
URLs
</FormLabel>
<FormDescription className={cn(index !== 0 && 'sr-only')}>
Add links to your website, blog, or social media profiles.
</FormDescription>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
))}
<Button
type='button'
variant='outline'
size='sm'
className='mt-2'
onClick={() => append({ value: '' })}
>
Add URL
</Button>
</div>
<Button type='submit'>Update profile</Button>
</form>
</Form>
);
}
27 changes: 26 additions & 1 deletion src/lib/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,37 @@ export const taskSchema = z.object({
project_id: z.string().uuid(),
});

const fileRecordSchema = z.object({
export const fileRecordSchema = z.object({
file_id: z.string().uuid(),
created_at: z.string().default(new Date().toISOString()),
path: z.string(),
uploader_id: z.string().uuid(),
});

export const profileFormSchema = z.object({
username: z
.string()
.min(2, {
message: 'Username must be at least 2 characters.',
})
.max(30, {
message: 'Username must not be longer than 30 characters.',
}),
email: z
.string({
required_error: 'Please select an email to display.',
})
.email(),
bio: z.string().max(160).min(4),
urls: z
.array(
z.object({
value: z.string().url({ message: 'Please enter a valid URL.' }),
})
)
.optional(),
});

export type fileSchemaType = z.infer<typeof fileSchema>;
export type userSignupFormSchemaType = z.infer<typeof userSignupFormSchema>;
export type userProfileSchemaType = z.infer<typeof userProfileSchema>;
Expand All @@ -157,3 +181,4 @@ export type projectSchemaType = z.infer<typeof projectSchema>;
export type taskFormSchemaType = z.infer<typeof taskFormSchema>;
export type taskSchemaType = z.infer<typeof taskSchema>;
export type fileRecordSchemaType = z.infer<typeof fileRecordSchema>;
export type profileFormSchemaType = z.infer<typeof profileFormSchema>;

0 comments on commit 108dd1f

Please sign in to comment.