Repository navigation
HeaderPanelProfile
The HeaderPanelProfile component displays comprehensive user profile information, preferences, and account actions within the header panel. It provides client/district selection and logout functionality.
This component does not accept any props. It manages its own state through context hooks.
import HeaderPanelProfile from "@/components/Layout/HeaderPanelProfile";
// Typically used within LayoutHeaderPanel
<HeaderPanel>
<HeaderPanelProfile />
</HeaderPanel>;- Large Avatar: User initials in a circular avatar
- Full Name: First and last name display
- UserID: Identity provider and username (e.g., "IDIR\jdoe")
- User Role: Comma-separated list of assigned roles
- Email: User's email address
Conditional selection based on user role:
- Client Role Users (VIEWER, SUBMITTER): Client selection interface
- Organization Role Users (ADMIN, DISTRICT_MANAGER, AREA_MANAGER): District/organization selection interface
- Logout: Sign out button with icon
┌─────────────────────────────────┐
│ [Avatar] John Doe │
│ IDIR\jdoe │
│ Email: jdoe@gov.bc.ca│
├─────────────────────────────────┤
│ Select district/client │
│ [?] Help tooltip │
│ │
│ [District/Client Listing] │
│ │
├─────────────────────────────────┤
│ [Exit Icon] Log out │
└─────────────────────────────────┘
<div className="user-info-section">
<div className="user-image">
<AvatarImage
userName={`${user?.firstName} ${user?.lastName}`}
size="large"
/>
</div>
<div className="user-data">
<p className="user-name">{`${user?.firstName} ${user?.lastName}`}</p>
<p>{`${user?.idpProvider ? user?.idpProvider + "\\" : null}${user?.userName}`}</p>
<p>{`Role: ${user?.roles?.map((r) => r.role)?.join(", ") ?? ""}`}</p>
<p>{`Email: ${user?.email}`}</p>
</div>
</div><Tooltip label={tooltipText}>
<div className="panel-section-light">
<span>Select {entityType}</span>
<Help aria-label={`Help: About selecting a default ${entityType}`} tabIndex={0} />
</div>
</Tooltip>
<div className="district-selection-container">
{isClientUser ? <ClientListing /> : <DistrictListing />}
</div><SideNavLink className="cursor-pointer" renderIcon={Exit} onClick={logout}>
Log out
</SideNavLink>const CLIENT_ROLES = new Set([Role.VIEWER, Role.SUBMITTER]);
const isClientUser =
user?.roles?.some((r) => CLIENT_ROLES.has(r.role)) ?? false;
const entityType = isClientUser ? "client" : "organization";Users with VIEWER or SUBMITTER roles are client users and see client selection. All other users (ADMIN, DISTRICT_MANAGER, AREA_MANAGER) see organization/district selection.
Dynamic tooltip based on user role:
const tooltipText =
`Optional: Select a default ${entityType}.` +
` This can help you do your searches faster if you work with one ${entityType} much more than others.` +
` You can change or remove this at any time.`;For client users (VIEWER, SUBMITTER): "Select a default client..." For other users (ADMIN, DISTRICT_MANAGER, AREA_MANAGER): "Select a default organization..."
{isClientUser ? <ClientListing /> : <DistrictListing />}Based on the determined isClientUser flag, the component conditionally renders either the client or district listing interface.
const { logout, user } = useAuth();Provides:
-
logout: Function to sign out the user -
user: Current user object with profile information
-
firstName: User's first name -
lastName: User's last name -
userName: Login username -
email: User's email address -
idpProvider: Identity provider (BCEIDBUSINESS, IDIR, etc.)
.my-profile-container {
display: flex;
flex-direction: column;
flex-grow: 1;
}.user-info-section {
padding: 1rem;
display: flex;
.user-data {
margin-left: 2rem;
}
.user-image {
display: flex;
align-items: center;
justify-content: center;
}
}
.user-name {
@include font-weight(semibold);
}.district-panel {
display: flex;
flex-direction: column;
flex-grow: 1;
div.district-selection-container {
display: flex;
flex-direction: column;
flex-grow: 1;
}
}.panel-section-light {
height: 3rem;
display: flex;
flex-direction: row;
align-items: center;
padding: 0.94rem 1rem;
background: var(--layer-02);
display: flex;
gap: 0.5rem;
}
.panel-section-light > span {
@include type.type-style("label-01");
color: var(--text-secondary);
user-select: none;
}.divisory {
border: 1px solid var(--border-subtle-01);
}- Background:
--layer-02 - Text primary: Applied to user name
- Text secondary:
--text-secondary(for labels) - Border:
--border-subtle-01 - Typography: Carbon
label-01
data-testid="user-fullname"aria-label={`Help: About selecting a default ${entityType}`}- Help icon is focusable (
tabIndex={0}) - Logout link is keyboard accessible
- All interactive elements support keyboard navigation
- Proper heading hierarchy
- Navigation element with list structure
- Horizontal rule for visual separation
Provides contextual help for entity selection:
"Optional: Select a default {entityType}. This can help you do your
searches faster if you work with one {entityType} much more than others.
You can change or remove this at any time."
- Appears on hover/focus
- Icon is keyboard accessible
- ARIA label describes purpose
<SideNavLink className="cursor-pointer" renderIcon={Exit} onClick={logout}>
Log out
</SideNavLink>- Exit icon for visual clarity
- Uses Carbon's SideNavLink for consistency
- Executes logout function from AuthContext
- Styled as a cursor pointer
- AuthProvider: For user info and logout functionality
- PreferenceProvider: Required by ClientListing/DistrictListing
- AvatarImage: Large user avatar
- ClientListing: Client selection for business users
- DistrictListing: District selection for IDIR users
-
SideNavLink: Logout button styling -
Tooltip: Help text display -
Help: Help icon
-
Exit: Logout icon -
Help: Help tooltip icon
import { AuthProvider } from "@/context/auth/AuthProvider";
import { PreferenceProvider } from "@/context/preference/PreferenceProvider";
import HeaderPanelProfile from "@/components/Layout/HeaderPanelProfile";
function ProfilePanel() {
return (
<AuthProvider>
<PreferenceProvider>
<HeaderPanelProfile />
</PreferenceProvider>
</AuthProvider>
);
}- User opens profile panel
- Sees their avatar, name, and email
- Can view currently selected client/district
- User scrolls to entity selection section
- Reads tooltip for guidance
- Selects from available clients/districts
- Selection persists across sessions
- User scrolls to bottom of panel
- Clicks logout button
- Redirected to login page
- Session cleared
BCEIDBUSINESS\username
IDIR\username
PROVIDERNAME\username
- LayoutHeaderPanel: Parent panel container
- AvatarImage: User avatar display
- ClientListing: Business client selection
- DistrictListing: Government district selection
- Context Providers: Ensure AuthProvider and PreferenceProvider are available
- User Data: Validate user object exists before rendering
- Entity Type: Handle different identity providers appropriately
- Logout Handling: Ensure logout function clears all user data
- Accessibility: Maintain keyboard navigation and screen reader support
- Component flexes to fill available panel height
- District/client selection takes up remaining space
- User information is always visible at the top
- Logout is anchored at the bottom
- Follows BC Government design patterns
- Username format includes identity provider prefix
This wiki documents NR Waste Plus for users and developers. Verify security and deployment guidance against the current application configuration before applying it elsewhere.
- Report an issue or ask a question in the GitHub repository.
- Follow the Contributing Guidelines to propose an update.
- Read the Code of Conduct.
Collection indexes support human browsing and machine retrieval. Keep both current when adding or moving wiki pages.
NR Waste Plus Wiki | GitHub Repository