Skip to content

Commit 519335d

Browse files
refactor uploadToUrl functionality
1 parent d20c289 commit 519335d

File tree

3 files changed

+76
-68
lines changed

3 files changed

+76
-68
lines changed

app/(app)/alpha/additional-details/_client.tsx

Lines changed: 17 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ import { Divider } from "@/components/ui-components/divider";
4242
import { Avatar } from "@/components/ui-components/avatar";
4343
import { Text } from "@/components/ui-components/text";
4444
import { api } from "@/server/trpc/react";
45-
import { uploadFile } from "@/utils/s3helpers";
45+
import { uploadToUrl } from "@/utils/fileUpload";
4646

4747
type UserDetails = {
4848
username: string;
@@ -126,53 +126,36 @@ function SlideOne({ details }: { details: UserDetails }) {
126126
resolver: zodResolver(slideOneSchema),
127127
defaultValues: { username, name, location },
128128
});
129-
const uploadToUrl = async (signedUrl: string, file: File) => {
130-
setProfilePhoto({ status: "loading", url: "" });
131129

132-
if (!file) {
133-
setProfilePhoto({ status: "error", url: "" });
134-
toast.error("Invalid file upload.");
135-
return;
136-
}
137-
try {
138-
const response = await uploadFile(signedUrl, file);
139-
const { fileLocation } = response;
140-
await updateUserPhotoUrl({
141-
url: fileLocation,
142-
});
143-
144-
return fileLocation;
145-
} catch (error) {
146-
setProfilePhoto({ status: "error", url: "" });
147-
toast.error("Failed to upload profile photo. Please try again.");
148-
return null;
149-
}
150-
};
151130
const imageChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
152131
if (e.target.files && e.target.files.length > 0) {
153132
const file = e.target.files[0];
154133
const { size, type } = file;
155134

135+
setProfilePhoto({ status: "loading", url: "" });
136+
156137
await getUploadUrl(
157138
{ size, type },
158139
{
159140
onError(error) {
160-
if (error) return toast.error(error.message);
161-
return toast.error(
162-
"Something went wrong uploading the photo, please retry.",
141+
toast.error(
142+
error.message ||
143+
"Something went wrong uploading the photo, please retry.",
163144
);
145+
setProfilePhoto({ status: "error", url: "" });
164146
},
165147
async onSuccess(signedUrl) {
166-
const url = await uploadToUrl(signedUrl, file);
167-
if (!url) {
168-
return toast.error(
169-
"Something went wrong uploading the photo, please retry.",
170-
);
148+
const { status, fileLocation } = await uploadToUrl({
149+
signedUrl,
150+
file,
151+
updateUserPhotoUrl,
152+
});
153+
154+
if (status === "success" && fileLocation) {
155+
setProfilePhoto({ status: "success", url: fileLocation });
156+
} else {
157+
setProfilePhoto({ status: "error", url: "" });
171158
}
172-
setProfilePhoto({ status: "success", url });
173-
toast.success(
174-
"Profile photo successfully updated. This may take a few minutes to update around the site.",
175-
);
176159
},
177160
},
178161
);

app/(app)/settings/_client.tsx

Lines changed: 20 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { toast } from "sonner";
99
import type { saveSettingsInput } from "@/schema/profile";
1010
import { saveSettingsSchema } from "@/schema/profile";
1111

12-
import { uploadFile } from "@/utils/s3helpers";
1312
import type { user } from "@/server/db/schema";
1413
import { Button } from "@/components/ui-components/button";
1514
import { Loader2 } from "lucide-react";
@@ -25,6 +24,7 @@ import { Textarea } from "@/components/ui-components/textarea";
2524
import { Switch } from "@/components/ui-components/switch";
2625
import { Divider } from "@/components/ui-components/divider";
2726
import { Text } from "@/components/ui-components/text";
27+
import { uploadToUrl } from "@/utils/fileUpload";
2828

2929
type User = Pick<
3030
typeof user.$inferSelect,
@@ -75,10 +75,10 @@ const Settings = ({ profile }: { profile: User }) => {
7575
});
7676

7777
const { mutate, isError, isSuccess } = api.profile.edit.useMutation();
78-
const { mutate: getUploadUrl } = api.profile.getUploadUrl.useMutation();
79-
const { mutate: updateUserPhotoUrl } =
78+
const { mutateAsync: getUploadUrl } = api.profile.getUploadUrl.useMutation();
79+
const { mutateAsync: updateUserPhotoUrl } =
8080
api.profile.updateProfilePhotoUrl.useMutation();
81-
const { mutate: updateEmail } = api.profile.updateEmail.useMutation();
81+
const { mutateAsync: updateEmail } = api.profile.updateEmail.useMutation();
8282

8383
const fileInputRef = useRef<HTMLInputElement>(null);
8484

@@ -104,49 +104,35 @@ const Settings = ({ profile }: { profile: User }) => {
104104
mutate({ ...values, newsletter: weeklyNewsletter, emailNotifications });
105105
};
106106

107-
const uploadToUrl = async (signedUrl: string, file: File) => {
108-
setProfilePhoto({ status: "loading", url: "" });
109-
110-
if (!file) {
111-
setProfilePhoto({ status: "error", url: "" });
112-
toast.error("Invalid file upload.");
113-
return;
114-
}
115-
116-
const response = await uploadFile(signedUrl, file);
117-
const { fileLocation } = response;
118-
await updateUserPhotoUrl({
119-
url: fileLocation,
120-
});
121-
122-
return fileLocation;
123-
};
124-
125107
const imageChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
126108
if (e.target.files && e.target.files.length > 0) {
127109
const file = e.target.files[0];
128110
const { size, type } = file;
129111

112+
setProfilePhoto({ status: "loading", url: "" });
113+
130114
await getUploadUrl(
131115
{ size, type },
132116
{
133117
onError(error) {
134-
if (error) return toast.error(error.message);
135-
return toast.error(
136-
"Something went wrong uploading the photo, please retry.",
118+
toast.error(
119+
error.message ||
120+
"Something went wrong uploading the photo, please retry.",
137121
);
122+
setProfilePhoto({ status: "error", url: "" });
138123
},
139124
async onSuccess(signedUrl) {
140-
const url = await uploadToUrl(signedUrl, file);
141-
if (!url) {
142-
return toast.error(
143-
"Something went wrong uploading the photo, please retry.",
144-
);
125+
const { status, fileLocation } = await uploadToUrl({
126+
signedUrl,
127+
file,
128+
updateUserPhotoUrl,
129+
});
130+
131+
if (status === "success" && fileLocation) {
132+
setProfilePhoto({ status: "success", url: fileLocation });
133+
} else {
134+
setProfilePhoto({ status: "error", url: "" });
145135
}
146-
setProfilePhoto({ status: "success", url });
147-
toast.success(
148-
"Profile photo successfully updated. This may take a few minutes to update around the site.",
149-
);
150136
},
151137
},
152138
);

utils/fileUpload.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { toast } from "sonner";
2+
import { uploadFile } from "./s3helpers";
3+
4+
type UploadToUrlProps = {
5+
signedUrl: string;
6+
file: File;
7+
updateUserPhotoUrl: (params: {
8+
url: string;
9+
}) => Promise<{ role: string; id: string; name: string }>;
10+
};
11+
12+
type UploadResult = {
13+
status: "success" | "error" | "loading";
14+
fileLocation: string | null;
15+
};
16+
17+
export const uploadToUrl = async ({
18+
signedUrl,
19+
file,
20+
updateUserPhotoUrl,
21+
}: UploadToUrlProps): Promise<UploadResult> => {
22+
if (!file) {
23+
toast.error("Invalid file upload.");
24+
return { status: "error", fileLocation: null };
25+
}
26+
27+
try {
28+
const response = await uploadFile(signedUrl, file);
29+
const { fileLocation } = response;
30+
31+
await updateUserPhotoUrl({ url: fileLocation });
32+
toast.success("Profile photo successfully updated.");
33+
34+
return { status: "success", fileLocation };
35+
} catch (error) {
36+
toast.error("Failed to upload profile photo. Please try again.");
37+
return { status: "error", fileLocation: null };
38+
}
39+
};

0 commit comments

Comments
 (0)