profile settings
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import { useNavigate, useLocation } from 'react-router-dom'
|
import { useNavigate, useLocation } from 'react-router-dom'
|
||||||
|
import { useState } from 'react'
|
||||||
import { useAuth } from '../contexts/AuthContext'
|
import { useAuth } from '../contexts/AuthContext'
|
||||||
|
|
||||||
export default function BottomNav() {
|
export default function BottomNav() {
|
||||||
@@ -6,7 +7,9 @@ export default function BottomNav() {
|
|||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
const { user, mongoUser } = useAuth()
|
const { user, mongoUser } = useAuth()
|
||||||
const displayName = mongoUser?.displayName || user?.displayName || 'U'
|
const displayName = mongoUser?.displayName || user?.displayName || 'U'
|
||||||
const photoURL = (mongoUser && 'photoURL' in mongoUser) ? (mongoUser.photoURL || null) : (user?.photoURL || null)
|
const mongoPhoto = mongoUser && 'photoURL' in mongoUser ? mongoUser.photoURL : null
|
||||||
|
const photoURL = (mongoPhoto?.startsWith('data:')) ? mongoPhoto : (user?.photoURL || null)
|
||||||
|
const [imgError, setImgError] = useState(false)
|
||||||
|
|
||||||
const isActive = (path: string) => location.pathname === path
|
const isActive = (path: string) => location.pathname === path
|
||||||
|
|
||||||
@@ -54,8 +57,8 @@ export default function BottomNav() {
|
|||||||
onClick={() => navigate('/settings')}
|
onClick={() => navigate('/settings')}
|
||||||
aria-label="Settings"
|
aria-label="Settings"
|
||||||
>
|
>
|
||||||
{photoURL ? (
|
{photoURL && !imgError ? (
|
||||||
<img src={photoURL} alt={displayName} className="bottom-nav-avatar" />
|
<img src={photoURL} alt={displayName} className="bottom-nav-avatar" onError={() => setImgError(true)} />
|
||||||
) : (
|
) : (
|
||||||
<div className="bottom-nav-avatar bottom-nav-avatar-placeholder">
|
<div className="bottom-nav-avatar bottom-nav-avatar-placeholder">
|
||||||
{displayName.charAt(0).toUpperCase()}
|
{displayName.charAt(0).toUpperCase()}
|
||||||
|
|||||||
@@ -77,8 +77,9 @@ export default function SettingsPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const displayName = mongoUser?.displayName || user?.displayName || 'User'
|
const displayName = mongoUser?.displayName || user?.displayName || 'User'
|
||||||
// Prefer mongo photo; only fall back to Google photo if mongo has no photo set
|
// Use custom uploaded photo (base64) if set, otherwise always use Firebase's fresh Google URL
|
||||||
const photoURL = (mongoUser && 'photoURL' in mongoUser) ? (mongoUser.photoURL || null) : (user?.photoURL || null)
|
const mongoPhoto = mongoUser && 'photoURL' in mongoUser ? mongoUser.photoURL : null
|
||||||
|
const photoURL = (mongoPhoto?.startsWith('data:')) ? mongoPhoto : (user?.photoURL || null)
|
||||||
|
|
||||||
const openEditModal = () => {
|
const openEditModal = () => {
|
||||||
setEditName(displayName)
|
setEditName(displayName)
|
||||||
@@ -206,9 +207,11 @@ export default function SettingsPage() {
|
|||||||
<main className="settings-container">
|
<main className="settings-container">
|
||||||
{/* Profile Section */}
|
{/* Profile Section */}
|
||||||
<div id="tour-edit-profile" className="settings-profile">
|
<div id="tour-edit-profile" className="settings-profile">
|
||||||
<div className="settings-avatar">
|
<div className="settings-avatar" onClick={openEditModal} style={{ cursor: 'pointer' }}>
|
||||||
{photoURL ? (
|
{photoURL ? (
|
||||||
<img src={photoURL} alt={displayName} className="settings-avatar-img" />
|
<img src={photoURL} alt={displayName} className="settings-avatar-img"
|
||||||
|
onError={(e) => { (e.target as HTMLImageElement).style.display = 'none'; }}
|
||||||
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="settings-avatar-placeholder" style={{ fontSize: '1.75rem' }}>
|
<div className="settings-avatar-placeholder" style={{ fontSize: '1.75rem' }}>
|
||||||
{displayName.charAt(0).toUpperCase()}
|
{displayName.charAt(0).toUpperCase()}
|
||||||
@@ -465,9 +468,18 @@ export default function SettingsPage() {
|
|||||||
<div className="confirm-modal" onClick={(e) => e.stopPropagation()}>
|
<div className="confirm-modal" onClick={(e) => e.stopPropagation()}>
|
||||||
<h3 className="edit-modal-title">Edit Profile</h3>
|
<h3 className="edit-modal-title">Edit Profile</h3>
|
||||||
|
|
||||||
<div className="edit-modal-avatar" onClick={() => fileInputRef.current?.click()}>
|
<label className="edit-modal-avatar" style={{ cursor: 'pointer' }}>
|
||||||
|
<input
|
||||||
|
ref={fileInputRef}
|
||||||
|
type="file"
|
||||||
|
accept="image/*"
|
||||||
|
style={{ display: 'none' }}
|
||||||
|
onChange={handlePhotoSelect}
|
||||||
|
/>
|
||||||
{editPhotoPreview ? (
|
{editPhotoPreview ? (
|
||||||
<img src={editPhotoPreview} alt="Preview" className="edit-modal-avatar-img" />
|
<img src={editPhotoPreview} alt="Preview" className="edit-modal-avatar-img"
|
||||||
|
onError={(e) => { (e.target as HTMLImageElement).style.display = 'none' }}
|
||||||
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="edit-modal-avatar-placeholder">
|
<div className="edit-modal-avatar-placeholder">
|
||||||
{editName.charAt(0).toUpperCase() || 'U'}
|
{editName.charAt(0).toUpperCase() || 'U'}
|
||||||
@@ -479,14 +491,7 @@ export default function SettingsPage() {
|
|||||||
<circle cx="12" cy="13" r="4" />
|
<circle cx="12" cy="13" r="4" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<input
|
</label>
|
||||||
ref={fileInputRef}
|
|
||||||
type="file"
|
|
||||||
accept="image/*"
|
|
||||||
style={{ display: 'none' }}
|
|
||||||
onChange={handlePhotoSelect}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{editPhotoPreview && (
|
{editPhotoPreview && (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
|||||||
Reference in New Issue
Block a user