Skip to content

Commit

Permalink
wip: profilesettings profile edit section
Browse files Browse the repository at this point in the history
  • Loading branch information
MuhammedKpln committed Mar 29, 2024
1 parent cbd50e0 commit 11e1387
Show file tree
Hide file tree
Showing 2 changed files with 158 additions and 2 deletions.
7 changes: 5 additions & 2 deletions app/(app)/profile-settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Screen from '@lib/components/screen';
import { QueryKeys } from '@lib/models/query_keys.model';
import { IUser } from '@lib/models/user.model';
import ProfilePictureSection from '@lib/modules/profile-settings/ProfilePictureSection';
import ProfileSection from '@lib/modules/profile-settings/ProfileSection';
import { profileService } from '@lib/services/profile.service';
import { useAuthStore } from '@lib/store/auth.store';
import { useSuspenseQuery } from '@tanstack/react-query';
Expand All @@ -12,13 +13,15 @@ export default function ProfileSettingsPage() {
const user = useAuthStore((state) => state.user);
const profileQuery = useSuspenseQuery<IUser>({
queryKey: [QueryKeys.ProfileWithRelations, user?.id],
queryFn: () => profileService.fetchProfile(user!.id)
queryFn: () => profileService.fetchProfile(user!.id),
networkMode: 'offlineFirst'
});

return (
<Suspense fallback={<Spinner />}>
<Screen>
<Screen gap="$5">
<ProfilePictureSection user={profileQuery.data} />
<ProfileSection user={profileQuery.data} />
</Screen>
</Suspense>
);
Expand Down
153 changes: 153 additions & 0 deletions lib/modules/profile-settings/ProfileSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import { zodResolver } from '@hookform/resolvers/zod';
import { QueryKeys } from '@lib/models/query_keys.model';
import { IUserWithPhoneAndSocial } from '@lib/models/user.model';
import { profileService } from '@lib/services/profile.service';
import { useToastController } from '@tamagui/toast';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { useCallback } from 'react';
import { Controller, useForm } from 'react-hook-form';
import {
Button,
Card,
Fieldset,
Form,
Input,
Label,
Spinner,
Text,
TextArea,
View
} from 'tamagui';
import { z } from 'zod';
import { ISectionProps } from '.';

const profileSchema = z.object({
firstName: z.string().optional(),
lastName: z.string().optional(),
bio: z.string().optional()
});

type ProfileSchemaType = z.infer<typeof profileSchema>;

export default function ProfileSection({ user }: ISectionProps) {
const queryClient = useQueryClient();
const toast = useToastController();
const mutation = useMutation<void, void, ProfileSchemaType>({
mutationFn: (data) => profileService.updateProfile(user.id, data),
onSuccess(_data, variables) {
queryClient.setQueryData<IUserWithPhoneAndSocial>(
[QueryKeys.ProfileWithRelations, user.id],
(v) => {
if (!v) return;

return {
...v,
...variables
};
}
);
}
});

const form = useForm<ProfileSchemaType>({
resolver: zodResolver(profileSchema),
defaultValues: {
firstName: user.firstName,
lastName: user.lastName,
bio: user.bio ?? undefined
}
});

const onSubmit = useCallback(async (input: ProfileSchemaType) => {
try {
await mutation.mutateAsync({
...input
});

toast.show('Sparat!', { toastType: 'success' });
} catch (error) {
toast.show('Error!', { toastType: 'error' });
}
}, []);

return (
<Card>
<Card.Header padded>
<Text>Profil</Text>
</Card.Header>

<Form onSubmit={form.handleSubmit(onSubmit)}>
<View p="$4">
<Fieldset>
<Controller
control={form.control}
name="firstName"
render={({ field, fieldState }) => (
<>
<Label htmlFor="firstName">Namn</Label>
<Input
id="firstName"
placeholder="Namn"
value={field.value}
onChange={field.onChange}
onBlur={field.onBlur}
/>
</>
)}
/>
</Fieldset>
<Fieldset>
<Controller
control={form.control}
name="lastName"
render={({ field }) => (
<>
<Label htmlFor="lastName">Efternamn</Label>
<Input
id="lastName"
placeholder="Efternamn"
value={field.value}
onChange={field.onChange}
onBlur={field.onBlur}
/>
</>
)}
/>
</Fieldset>
<Fieldset>
<Controller
control={form.control}
name="bio"
render={({ field }) => (
<>
<Label htmlFor="bio">Biografi</Label>
<TextArea
id="bio"
placeholder="Biografi"
value={field.value}
onChange={field.onChange}
onBlur={field.onBlur}
/>
</>
)}
/>
</Fieldset>
</View>

<Card.Footer padded>
<Form.Trigger
asChild
disabled={mutation.isPending}
>
<Button
theme="active"
icon={mutation.isPending ? <Spinner /> : undefined}
>
Spara
</Button>
</Form.Trigger>
</Card.Footer>
</Form>
</Card>
);
}

0 comments on commit 11e1387

Please sign in to comment.