Skip to content

Commit 3fd5239

Browse files
committed
fix: simple usage
1 parent e062b3d commit 3fd5239

File tree

3 files changed

+59
-62
lines changed

3 files changed

+59
-62
lines changed

src/features/account/AccountProfileForm.tsx

+28-25
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import React from 'react';
22

33
import { Button, ButtonGroup, Stack } from '@chakra-ui/react';
44
import { zodResolver } from '@hookform/resolvers/zod';
5-
import { SubmitHandler, useForm } from 'react-hook-form';
5+
import { useMutation } from '@tanstack/react-query';
6+
import { useForm } from 'react-hook-form';
67
import { useTranslation } from 'react-i18next';
78

89
import { ErrorPage } from '@/components/ErrorPage';
@@ -22,7 +23,7 @@ import {
2223
AVAILABLE_LANGUAGES,
2324
DEFAULT_LANGUAGE_KEY,
2425
} from '@/lib/i18n/constants';
25-
import { useUploadFileMutation } from '@/lib/s3/client';
26+
import { uploadFile } from '@/lib/s3/client';
2627
import { FILES_COLLECTIONS_CONFIG } from '@/lib/s3/config';
2728
import { trpc } from '@/lib/trpc/client';
2829

@@ -33,9 +34,24 @@ export const AccountProfileForm = () => {
3334
staleTime: Infinity,
3435
});
3536

36-
const uploadAvatar = useUploadFileMutation('avatar');
37-
38-
const updateAccount = trpc.account.update.useMutation({
37+
const updateAccount = useMutation({
38+
mutationFn: async ({ image, ...values }: FormFieldsAccountProfile) => {
39+
return await trpcUtils.client.account.update.mutate({
40+
...values,
41+
image: image?.file
42+
? await uploadFile({
43+
trpcClient: trpcUtils.client,
44+
collection: 'avatar',
45+
file: image.file,
46+
onError: () => {
47+
form.setError('image', {
48+
message: t('account:profile.feedbacks.uploadError.title'),
49+
});
50+
},
51+
})
52+
: account.data?.image,
53+
});
54+
},
3955
onSuccess: async () => {
4056
await trpcUtils.account.invalidate();
4157
toastCustom({
@@ -61,31 +77,18 @@ export const AccountProfileForm = () => {
6177
},
6278
});
6379

64-
const onSubmit: SubmitHandler<FormFieldsAccountProfile> = async ({
65-
image,
66-
...values
67-
}) => {
68-
try {
69-
updateAccount.mutate({
70-
...values,
71-
image: image?.file
72-
? await uploadAvatar.mutateAsync(image.file)
73-
: account.data?.image,
74-
});
75-
} catch {
76-
form.setError('image', {
77-
message: t('account:profile.feedbacks.uploadError.title'),
78-
});
79-
}
80-
};
81-
8280
return (
8381
<>
8482
{account.isLoading && <LoaderFull />}
8583
{account.isError && <ErrorPage />}
8684
{account.isSuccess && (
8785
<Stack spacing={4}>
88-
<Form {...form} onSubmit={onSubmit}>
86+
<Form
87+
{...form}
88+
onSubmit={(values) => {
89+
updateAccount.mutate(values);
90+
}}
91+
>
8992
<Stack spacing={4}>
9093
<FormField>
9194
<FormFieldLabel>
@@ -129,7 +132,7 @@ export const AccountProfileForm = () => {
129132
<Button
130133
type="submit"
131134
variant="@primary"
132-
isLoading={updateAccount.isLoading || uploadAvatar.isLoading}
135+
isLoading={updateAccount.isLoading}
133136
>
134137
{t('account:profile.actions.update')}
135138
</Button>

src/lib/s3/client.ts

+29-35
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,42 @@
1-
import { useMutation } from '@tanstack/react-query';
2-
import { TRPCError } from '@trpc/server';
31
import { stringify } from 'superjson';
42

53
import { env } from '@/env.mjs';
64
import { trpc } from '@/lib/trpc/client';
75
import { RouterInputs } from '@/lib/trpc/types';
86

9-
export const useUploadFileMutation = (
10-
collection: RouterInputs['files']['uploadPresignedUrl']['collection'],
11-
params: {
12-
getMetadata?: (file: File) => Record<string, string>;
13-
} = {}
14-
) => {
15-
const uploadPresignedUrl = trpc.files.uploadPresignedUrl.useMutation();
16-
return useMutation({
17-
mutationFn: async (file: File) => {
18-
const presignedUrlOutput = await uploadPresignedUrl.mutateAsync({
7+
export const uploadFile = async (params: {
8+
file: File;
9+
trpcClient: ReturnType<typeof trpc.useUtils>['client'];
10+
collection: RouterInputs['files']['uploadPresignedUrl']['collection'];
11+
metadata?: Record<string, string>;
12+
onError?: (file: File, error: unknown) => void;
13+
}) => {
14+
try {
15+
const presignedUrlOutput =
16+
await params.trpcClient.files.uploadPresignedUrl.mutate({
1917
// Metadata is a Record<string, string> but should be serialized for trpc-openapi
20-
metadata: stringify({
21-
...params.getMetadata?.(file),
22-
}),
23-
collection,
24-
type: file.type,
25-
size: file.size,
26-
name: file.name,
18+
metadata: params.metadata ? stringify(params.metadata) : undefined,
19+
collection: params.collection,
20+
type: params.file.type,
21+
size: params.file.size,
22+
name: params.file.name,
2723
});
2824

29-
try {
30-
await fetch(presignedUrlOutput.signedUrl, {
31-
method: 'PUT',
32-
headers: { 'Content-Type': file.type },
33-
body: file,
34-
});
35-
} catch (e) {
36-
throw new TRPCError({
37-
code: 'INTERNAL_SERVER_ERROR',
38-
message: 'Unable to upload the file',
39-
cause: e,
40-
});
41-
}
25+
const response = await fetch(presignedUrlOutput.signedUrl, {
26+
method: 'PUT',
27+
headers: { 'Content-Type': params.file.type },
28+
body: params.file,
29+
});
4230

43-
return presignedUrlOutput.key;
44-
},
45-
});
31+
if (!response.ok) {
32+
throw new Error('Failed to upload file');
33+
}
34+
35+
return presignedUrlOutput.key;
36+
} catch (error) {
37+
params.onError?.(params.file, error);
38+
throw error;
39+
}
4640
};
4741

4842
export const getFilePublicUrl = (key: string | null | undefined) => {

src/lib/s3/utils.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export const validateFile = (params: {
1717
}): ValidateReturn => {
1818
if (
1919
params.config.maxSize &&
20-
(params.input.size ?? 0) >= params.config.maxSize
20+
(params.input.size ?? 0) > params.config.maxSize
2121
) {
2222
return {
2323
error: {
@@ -30,7 +30,7 @@ export const validateFile = (params: {
3030

3131
if (
3232
params.config.allowedTypes &&
33-
!params.config.allowedTypes.includes(params.input.type ?? '')
33+
!params.config.allowedTypes.includes(params.input.type?.toLowerCase() ?? '')
3434
) {
3535
return {
3636
error: {

0 commit comments

Comments
 (0)