fix: show profile button while a logbook is open
Extract ProfileHeaderButton and open UserProfilePage from any screen without leaving the active logbook. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+12
-4
@@ -44,6 +44,7 @@ import { useLiveQuery } from 'dexie-react-hooks'
|
|||||||
import { Ship, LogOut, ChevronLeft, Users, FileText, Settings, Wifi, WifiOff, Languages, BarChart2 } from 'lucide-react'
|
import { Ship, LogOut, ChevronLeft, Users, FileText, Settings, Wifi, WifiOff, Languages, BarChart2 } from 'lucide-react'
|
||||||
import DisclaimerHeaderButton from './components/DisclaimerHeaderButton.tsx'
|
import DisclaimerHeaderButton from './components/DisclaimerHeaderButton.tsx'
|
||||||
import FeedbackHeaderButton from './components/FeedbackHeaderButton.tsx'
|
import FeedbackHeaderButton from './components/FeedbackHeaderButton.tsx'
|
||||||
|
import ProfileHeaderButton from './components/ProfileHeaderButton.tsx'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { cycleAppLanguage } from './utils/i18nLanguages.js'
|
import { cycleAppLanguage } from './utils/i18nLanguages.js'
|
||||||
import {
|
import {
|
||||||
@@ -557,22 +558,27 @@ function App() {
|
|||||||
const isLogbookOwner =
|
const isLogbookOwner =
|
||||||
activeAccessRole === 'OWNER' || activeLogbookRecord?.isShared !== 1
|
activeAccessRole === 'OWNER' || activeLogbookRecord?.isShared !== 1
|
||||||
|
|
||||||
if (!activeLogbookId) {
|
if (showUserProfile) {
|
||||||
return (
|
return (
|
||||||
<div style={{ display: 'contents' }}>
|
<div style={{ display: 'contents' }}>
|
||||||
{pwaInstallBanner}
|
{pwaInstallBanner}
|
||||||
{showUserProfile ? (
|
|
||||||
<UserProfilePage
|
<UserProfilePage
|
||||||
onBack={() => setShowUserProfile(false)}
|
onBack={() => setShowUserProfile(false)}
|
||||||
onLogout={handleLogout}
|
onLogout={handleLogout}
|
||||||
/>
|
/>
|
||||||
) : (
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!activeLogbookId) {
|
||||||
|
return (
|
||||||
|
<div style={{ display: 'contents' }}>
|
||||||
|
{pwaInstallBanner}
|
||||||
<LogbookDashboard
|
<LogbookDashboard
|
||||||
onSelectLogbook={selectLogbook}
|
onSelectLogbook={selectLogbook}
|
||||||
onLogout={handleLogout}
|
onLogout={handleLogout}
|
||||||
onOpenProfile={() => setShowUserProfile(true)}
|
onOpenProfile={() => setShowUserProfile(true)}
|
||||||
/>
|
/>
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -622,6 +628,8 @@ function App() {
|
|||||||
<Languages size={18} />
|
<Languages size={18} />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<ProfileHeaderButton onClick={() => setShowUserProfile(true)} />
|
||||||
|
|
||||||
<DisclaimerHeaderButton />
|
<DisclaimerHeaderButton />
|
||||||
|
|
||||||
<FeedbackHeaderButton
|
<FeedbackHeaderButton
|
||||||
|
|||||||
@@ -8,9 +8,10 @@ import BetaBadge from './BetaBadge.tsx'
|
|||||||
import { PlausibleEvents, trackPlausibleEvent } from '../services/analytics.js'
|
import { PlausibleEvents, trackPlausibleEvent } from '../services/analytics.js'
|
||||||
import { logoutUser } from '../services/auth.js'
|
import { logoutUser } from '../services/auth.js'
|
||||||
import { useDialog } from './ModalDialog.tsx'
|
import { useDialog } from './ModalDialog.tsx'
|
||||||
import { BookOpen, Plus, Trash2, LogOut, Languages, RefreshCw, Ship, User, Wifi, WifiOff, Search, X, CalendarDays, CaseSensitive, ArrowUp, ArrowDown } from 'lucide-react'
|
import { BookOpen, Plus, Trash2, LogOut, Languages, RefreshCw, Ship, Wifi, WifiOff, Search, X, CalendarDays, CaseSensitive, ArrowUp, ArrowDown } from 'lucide-react'
|
||||||
import DisclaimerHeaderButton from './DisclaimerHeaderButton.tsx'
|
import DisclaimerHeaderButton from './DisclaimerHeaderButton.tsx'
|
||||||
import FeedbackHeaderButton from './FeedbackHeaderButton.tsx'
|
import FeedbackHeaderButton from './FeedbackHeaderButton.tsx'
|
||||||
|
import ProfileHeaderButton from './ProfileHeaderButton.tsx'
|
||||||
|
|
||||||
interface LogbookDashboardProps {
|
interface LogbookDashboardProps {
|
||||||
onSelectLogbook: (id: string, title: string) => void
|
onSelectLogbook: (id: string, title: string) => void
|
||||||
@@ -74,7 +75,6 @@ export default function LogbookDashboard({ onSelectLogbook, onLogout, onOpenProf
|
|||||||
const [sortDirection, setSortDirection] = useState<LogbookSortDirection>('desc')
|
const [sortDirection, setSortDirection] = useState<LogbookSortDirection>('desc')
|
||||||
const filterInputRef = useRef<HTMLInputElement>(null)
|
const filterInputRef = useRef<HTMLInputElement>(null)
|
||||||
const [online, setOnline] = useState(navigator.onLine)
|
const [online, setOnline] = useState(navigator.onLine)
|
||||||
const [username] = useState(localStorage.getItem('active_username') || 'Skipper')
|
|
||||||
|
|
||||||
const { pendingCount, showSpinner, showPendingWarning, connStatusClassName } = useSyncIndicator()
|
const { pendingCount, showSpinner, showPendingWarning, connStatusClassName } = useSyncIndicator()
|
||||||
|
|
||||||
@@ -370,18 +370,7 @@ export default function LogbookDashboard({ onSelectLogbook, onLogout, onOpenProf
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Skipper profile */}
|
<ProfileHeaderButton onClick={onOpenProfile} />
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="btn-icon skipper-badge"
|
|
||||||
onClick={onOpenProfile}
|
|
||||||
title={t('dashboard.open_profile', { name: username })}
|
|
||||||
aria-label={t('dashboard.open_profile', { name: username })}
|
|
||||||
data-tour="nav-profile"
|
|
||||||
>
|
|
||||||
<User size={18} aria-hidden="true" />
|
|
||||||
<span className="skipper-badge__name">{username}</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
{/* Lang toggle */}
|
{/* Lang toggle */}
|
||||||
<button className="btn-icon" onClick={toggleLanguage} title="Switch Language">
|
<button className="btn-icon" onClick={toggleLanguage} title="Switch Language">
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { User } from 'lucide-react'
|
||||||
|
|
||||||
|
interface ProfileHeaderButtonProps {
|
||||||
|
onClick: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ProfileHeaderButton({ onClick }: ProfileHeaderButtonProps) {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const username = localStorage.getItem('active_username') || 'Skipper'
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn-icon skipper-badge"
|
||||||
|
onClick={onClick}
|
||||||
|
title={t('dashboard.open_profile', { name: username })}
|
||||||
|
aria-label={t('dashboard.open_profile', { name: username })}
|
||||||
|
data-tour="nav-profile"
|
||||||
|
>
|
||||||
|
<User size={18} aria-hidden="true" />
|
||||||
|
<span className="skipper-badge__name">{username}</span>
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user