-
- Display Name
- setDisplayName(e.target.value)}
- />
-
-
- Location
- setLocationInput(e.target.value)}
- />
-
-
- Profile Image
- {
- const ensureBuckets = async () => {
- try {
- await fetch(
- `${API_BASE}/api/storage/ensure-buckets`,
- {
- method: "POST",
- },
- );
- } catch {}
- };
- const file = e.target.files?.[0];
- if (!file || !user) return;
- const storeDataUrl = () =>
- new Promise((resolve, reject) => {
- const reader = new FileReader();
- reader.onload = () =>
- resolve(reader.result as string);
- reader.onerror = () =>
- reject(new Error("Failed to read file"));
- reader.readAsDataURL(file);
- });
- try {
- await ensureBuckets();
- const path = `${user.id}/avatar-${Date.now()}-${file.name}`;
- let { error } = await supabase.storage
- .from("avatars")
- .upload(path, file, { upsert: true });
- if (
- error &&
- /bucket/i.test(error?.message || "")
- ) {
- await ensureBuckets();
- ({ error } = await supabase.storage
- .from("avatars")
- .upload(path, file, { upsert: true }));
- }
- if (error) throw error;
- const { data } = supabase.storage
- .from("avatars")
- .getPublicUrl(path);
- await updateProfile({
- avatar_url: data.publicUrl,
- } as any);
- computeProfileCompletion({
- ...(profile as any),
- avatar_url: data.publicUrl,
- });
- aethexToast.success({
- title: "Avatar updated",
- });
- } catch (err: any) {
- try {
- const dataUrl = await storeDataUrl();
- await updateProfile({
- avatar_url: dataUrl,
- } as any);
- computeProfileCompletion({
- ...(profile as any),
- avatar_url: dataUrl,
- });
- aethexToast.success({
- title: "Avatar saved (local)",
- });
- } catch (e: any) {
- aethexToast.error({
- title: "Upload failed",
- description:
- err?.message || "Unable to upload image",
- });
- }
- }
- }}
- />
-
-
- Banner Image
- {
- const ensureBuckets = async () => {
- try {
- await fetch(
- `${API_BASE}/api/storage/ensure-buckets`,
- {
- method: "POST",
- },
- );
- } catch {}
- };
- const file = e.target.files?.[0];
- if (!file || !user) return;
- const storeDataUrl = () =>
- new Promise((resolve, reject) => {
- const reader = new FileReader();
- reader.onload = () =>
- resolve(reader.result as string);
- reader.onerror = () =>
- reject(new Error("Failed to read file"));
- reader.readAsDataURL(file);
- });
- try {
- await ensureBuckets();
- const path = `${user.id}/banner-${Date.now()}-${file.name}`;
- let { error } = await supabase.storage
- .from("banners")
- .upload(path, file, { upsert: true });
- if (
- error &&
- /bucket/i.test(error?.message || "")
- ) {
- await ensureBuckets();
- ({ error } = await supabase.storage
- .from("banners")
- .upload(path, file, { upsert: true }));
- }
- if (error) throw error;
- const { data } = supabase.storage
- .from("banners")
- .getPublicUrl(path);
- await updateProfile({
- banner_url: data.publicUrl,
- } as any);
- computeProfileCompletion({
- ...(profile as any),
- banner_url: data.publicUrl,
- });
- aethexToast.success({
- title: "Banner updated",
- });
- } catch (err: any) {
- try {
- const dataUrl = await storeDataUrl();
- await updateProfile({
- banner_url: dataUrl,
- } as any);
- computeProfileCompletion({
- ...(profile as any),
- banner_url: dataUrl,
- });
- aethexToast.success({
- title: "Banner saved (local)",
- });
- } catch (e: any) {
- aethexToast.error({
- title: "Upload failed",
- description:
- err?.message || "Unable to upload image",
- });
- }
- }
- }}
- />
-
-
- Bio
-
-
- Website
- setWebsite(e.target.value)}
- />
-
-
- LinkedIn URL
- setLinkedin(e.target.value)}
- />
-
-
- GitHub URL
- setGithub(e.target.value)}
- />
-
-
- Twitter URL
- setTwitter(e.target.value)}
- />
-
-
-