-
{user.email}
-
- {user.status === 'NONE' ? 'Not Invited' : user.status}
-
+
+
+
+
+ {user.name || 'Unnamed Member'}
+
+
+
{user.email}
+
+ {user.status === 'NONE' ? 'Not Invited' : user.status}
+
+
{(user.status === 'NONE' || user.status === 'INVITED') && (
diff --git a/src/components/shared/avatar-upload.tsx b/src/components/shared/avatar-upload.tsx
index 3025d0d..b6b00a8 100644
--- a/src/components/shared/avatar-upload.tsx
+++ b/src/components/shared/avatar-upload.tsx
@@ -139,16 +139,23 @@ export function AvatarUpload({
})
// Upload cropped blob directly to storage
- const uploadResponse = await fetch(uploadUrl, {
- method: 'PUT',
- body: croppedBlob,
- headers: {
- 'Content-Type': 'image/jpeg',
- },
- })
+ let uploadResponse: Response
+ try {
+ uploadResponse = await fetch(uploadUrl, {
+ method: 'PUT',
+ body: croppedBlob,
+ headers: {
+ 'Content-Type': 'image/jpeg',
+ },
+ })
+ } catch (fetchError) {
+ console.error('Avatar upload network error (possible CORS issue):', fetchError)
+ throw new Error('Network error uploading file. The storage server may not be reachable.')
+ }
if (!uploadResponse.ok) {
- throw new Error('Failed to upload file')
+ console.error('Avatar upload failed:', uploadResponse.status, uploadResponse.statusText)
+ throw new Error(`Upload failed (${uploadResponse.status}). Please try again.`)
}
// Confirm upload
diff --git a/src/components/shared/logo-upload.tsx b/src/components/shared/logo-upload.tsx
index 450f8e7..a5f61ab 100644
--- a/src/components/shared/logo-upload.tsx
+++ b/src/components/shared/logo-upload.tsx
@@ -142,16 +142,23 @@ export function LogoUpload({
})
// Upload cropped blob directly to storage
- const uploadResponse = await fetch(uploadUrl, {
- method: 'PUT',
- body: croppedBlob,
- headers: {
- 'Content-Type': 'image/png',
- },
- })
+ let uploadResponse: Response
+ try {
+ uploadResponse = await fetch(uploadUrl, {
+ method: 'PUT',
+ body: croppedBlob,
+ headers: {
+ 'Content-Type': 'image/png',
+ },
+ })
+ } catch (fetchError) {
+ console.error('Logo upload network error (possible CORS issue):', fetchError)
+ throw new Error('Network error uploading file. The storage server may not be reachable.')
+ }
if (!uploadResponse.ok) {
- throw new Error('Failed to upload file')
+ console.error('Logo upload failed:', uploadResponse.status, uploadResponse.statusText)
+ throw new Error(`Upload failed (${uploadResponse.status}). Please try again.`)
}
// Confirm upload with the provider type that was used
diff --git a/src/components/shared/project-logo-upload.tsx b/src/components/shared/project-logo-upload.tsx
index 218b560..fea8e35 100644
--- a/src/components/shared/project-logo-upload.tsx
+++ b/src/components/shared/project-logo-upload.tsx
@@ -128,14 +128,21 @@ export function ProjectLogoUpload({
contentType: 'image/png',
})
- const uploadResponse = await fetch(uploadUrl, {
- method: 'PUT',
- body: croppedBlob,
- headers: { 'Content-Type': 'image/png' },
- })
+ let uploadResponse: Response
+ try {
+ uploadResponse = await fetch(uploadUrl, {
+ method: 'PUT',
+ body: croppedBlob,
+ headers: { 'Content-Type': 'image/png' },
+ })
+ } catch (fetchError) {
+ console.error('Logo upload network error (possible CORS issue):', fetchError)
+ throw new Error('Network error uploading file. The storage server may not be reachable.')
+ }
if (!uploadResponse.ok) {
- throw new Error('Failed to upload file')
+ console.error('Logo upload failed:', uploadResponse.status, uploadResponse.statusText)
+ throw new Error(`Upload failed (${uploadResponse.status}). Please try again.`)
}
await confirmUpload.mutateAsync({ projectId, key, providerType })
diff --git a/src/server/routers/user.ts b/src/server/routers/user.ts
index e803563..c8357b5 100644
--- a/src/server/routers/user.ts
+++ b/src/server/routers/user.ts
@@ -5,7 +5,7 @@ import { UserRole } from '@prisma/client'
import { router, protectedProcedure, adminProcedure, superAdminProcedure, publicProcedure } from '../trpc'
import { sendInvitationEmail, sendMagicLinkEmail } from '@/lib/email'
import { hashPassword, validatePassword } from '@/lib/password'
-import { attachAvatarUrls } from '@/server/utils/avatar-url'
+import { attachAvatarUrls, getUserAvatarUrl } from '@/server/utils/avatar-url'
import { logAudit } from '@/server/utils/audit'
import { generateInviteToken, getInviteExpiryHours, getInviteExpiryMs } from '@/server/utils/invite'
@@ -353,7 +353,8 @@ export const userRouter = router({
},
},
})
- return user
+ const avatarUrl = await getUserAvatarUrl(user.profileImageKey, user.profileImageProvider)
+ return { ...user, avatarUrl }
}),
/**
diff --git a/src/server/utils/avatar-url.ts b/src/server/utils/avatar-url.ts
index 8c96ab7..2c174ab 100644
--- a/src/server/utils/avatar-url.ts
+++ b/src/server/utils/avatar-url.ts
@@ -14,7 +14,8 @@ export async function getUserAvatarUrl(
const providerType = (profileImageProvider as StorageProviderType) || 's3'
const provider = createStorageProvider(providerType)
return await provider.getDownloadUrl(profileImageKey)
- } catch {
+ } catch (error) {
+ console.error('[AvatarURL] Failed to generate URL for key:', profileImageKey, error)
return null
}
}
diff --git a/src/server/utils/project-logo-url.ts b/src/server/utils/project-logo-url.ts
index ee9cdfd..3d24dd5 100644
--- a/src/server/utils/project-logo-url.ts
+++ b/src/server/utils/project-logo-url.ts
@@ -14,7 +14,8 @@ export async function getProjectLogoUrl(
const providerType = (logoProvider as StorageProviderType) || 's3'
const provider = createStorageProvider(providerType)
return await provider.getDownloadUrl(logoKey)
- } catch {
+ } catch (error) {
+ console.error('[LogoURL] Failed to generate URL for key:', logoKey, error)
return null
}
}