feat: wire photo upload/delete changes upward for instant page-wide refresh
This commit is contained in:
@@ -82,6 +82,10 @@ export default function ProfilePage() {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleImageChange = (url: string | null) => {
|
||||||
|
setProfile((prev) => (prev ? { ...prev, image: url } : null))
|
||||||
|
}
|
||||||
|
|
||||||
const tabs: { id: Tab; label: string; icon: typeof Bookmark }[] = [
|
const tabs: { id: Tab; label: string; icon: typeof Bookmark }[] = [
|
||||||
{ id: "overview", label: "Overview", icon: TrendingUp },
|
{ id: "overview", label: "Overview", icon: TrendingUp },
|
||||||
{ id: "saved", label: "Saved Games", icon: Bookmark },
|
{ id: "saved", label: "Saved Games", icon: Bookmark },
|
||||||
@@ -178,6 +182,7 @@ export default function ProfilePage() {
|
|||||||
createdAt={profile.createdAt}
|
createdAt={profile.createdAt}
|
||||||
image={profile.image}
|
image={profile.image}
|
||||||
userId={profile.id}
|
userId={profile.id}
|
||||||
|
onImageChange={handleImageChange}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ interface ProfilePhotoUploadProps {
|
|||||||
currentImage: string | null
|
currentImage: string | null
|
||||||
userName: string
|
userName: string
|
||||||
userId: string
|
userId: string
|
||||||
|
onImageChange?: (url: string | null) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const ALLOWED_TYPES = ["image/jpeg", "image/png", "image/webp"]
|
const ALLOWED_TYPES = ["image/jpeg", "image/png", "image/webp"]
|
||||||
@@ -22,7 +23,7 @@ function getInitials(name: string): string {
|
|||||||
return name.charAt(0).toUpperCase()
|
return name.charAt(0).toUpperCase()
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ProfilePhotoUpload({ currentImage, userName, userId }: ProfilePhotoUploadProps) {
|
export function ProfilePhotoUpload({ currentImage, userName, userId, onImageChange }: ProfilePhotoUploadProps) {
|
||||||
const [previewUrl, setPreviewUrl] = useState<string | null>(currentImage)
|
const [previewUrl, setPreviewUrl] = useState<string | null>(currentImage)
|
||||||
const [uploadState, setUploadState] = useState<"idle" | "uploading" | "success" | "error">("idle")
|
const [uploadState, setUploadState] = useState<"idle" | "uploading" | "success" | "error">("idle")
|
||||||
const [errorMessage, setErrorMessage] = useState<string | null>(null)
|
const [errorMessage, setErrorMessage] = useState<string | null>(null)
|
||||||
@@ -89,6 +90,7 @@ export function ProfilePhotoUpload({ currentImage, userName, userId }: ProfilePh
|
|||||||
if (data.url) {
|
if (data.url) {
|
||||||
setPreviewUrl(data.url)
|
setPreviewUrl(data.url)
|
||||||
cleanupTempUrl()
|
cleanupTempUrl()
|
||||||
|
onImageChange?.(data.url)
|
||||||
}
|
}
|
||||||
setUploadState("success")
|
setUploadState("success")
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -139,6 +141,7 @@ export function ProfilePhotoUpload({ currentImage, userName, userId }: ProfilePh
|
|||||||
setPreviewUrl(null)
|
setPreviewUrl(null)
|
||||||
setUploadState("idle")
|
setUploadState("idle")
|
||||||
setErrorMessage(null)
|
setErrorMessage(null)
|
||||||
|
onImageChange?.(null)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setErrorMessage(err instanceof Error ? err.message : "Delete failed")
|
setErrorMessage(err instanceof Error ? err.message : "Delete failed")
|
||||||
setUploadState("error")
|
setUploadState("error")
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ interface SettingsContainerProps {
|
|||||||
createdAt: string
|
createdAt: string
|
||||||
image?: string | null
|
image?: string | null
|
||||||
userId: string
|
userId: string
|
||||||
|
onImageChange?: (url: string | null) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SettingsContainer({
|
export function SettingsContainer({
|
||||||
@@ -37,6 +38,7 @@ export function SettingsContainer({
|
|||||||
createdAt,
|
createdAt,
|
||||||
image,
|
image,
|
||||||
userId,
|
userId,
|
||||||
|
onImageChange,
|
||||||
}: SettingsContainerProps) {
|
}: SettingsContainerProps) {
|
||||||
const [activeSubTab, setActiveSubTab] = useState<SettingsSubTab>("profile")
|
const [activeSubTab, setActiveSubTab] = useState<SettingsSubTab>("profile")
|
||||||
const [authMethods, setAuthMethods] = useState<AuthMethods | null>(null)
|
const [authMethods, setAuthMethods] = useState<AuthMethods | null>(null)
|
||||||
@@ -126,6 +128,7 @@ export function SettingsContainer({
|
|||||||
createdAt={createdAt}
|
createdAt={createdAt}
|
||||||
image={image}
|
image={image}
|
||||||
userId={userId}
|
userId={userId}
|
||||||
|
onImageChange={onImageChange}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{activeSubTab === "security" && (
|
{activeSubTab === "security" && (
|
||||||
|
|||||||
@@ -14,9 +14,10 @@ interface SettingsProfileTabProps {
|
|||||||
createdAt: string
|
createdAt: string
|
||||||
image?: string | null
|
image?: string | null
|
||||||
userId: string
|
userId: string
|
||||||
|
onImageChange?: (url: string | null) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SettingsProfileTab({ name, email, role, createdAt, image, userId }: SettingsProfileTabProps) {
|
export function SettingsProfileTab({ name, email, role, createdAt, image, userId, onImageChange }: SettingsProfileTabProps) {
|
||||||
const [displayName, setDisplayName] = useState(name)
|
const [displayName, setDisplayName] = useState(name)
|
||||||
const [isSaving, setIsSaving] = useState(false)
|
const [isSaving, setIsSaving] = useState(false)
|
||||||
const [message, setMessage] = useState<{ type: "success" | "error"; text: string } | null>(null)
|
const [message, setMessage] = useState<{ type: "success" | "error"; text: string } | null>(null)
|
||||||
@@ -54,7 +55,15 @@ export function SettingsProfileTab({ name, email, role, createdAt, image, userId
|
|||||||
className="space-y-6"
|
className="space-y-6"
|
||||||
>
|
>
|
||||||
{/* Profile Photo */}
|
{/* Profile Photo */}
|
||||||
<ProfilePhotoUpload currentImage={image ?? null} userName={name} userId={userId} />
|
<ProfilePhotoUpload
|
||||||
|
currentImage={image ?? null}
|
||||||
|
userName={name}
|
||||||
|
userId={userId}
|
||||||
|
onImageChange={async (url) => {
|
||||||
|
onImageChange?.(url)
|
||||||
|
await authClient.updateUser({ image: url ?? "" })
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Display Name */}
|
{/* Display Name */}
|
||||||
<div className="rounded-xl border border-border bg-text/[0.03] p-5">
|
<div className="rounded-xl border border-border bg-text/[0.03] p-5">
|
||||||
|
|||||||
Reference in New Issue
Block a user