-
Notifications
You must be signed in to change notification settings - Fork 0
feat(profile): implement complete profile management system #83
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Create profile layout with navigation menu and breadcrumbs - Build comprehensive profile edit form with all user/profile fields - Implement backend API with Supabase integration and REST endpoints - Add profile routes with authentication guards - Extend UserService with profile CRUD operations - Add countries dropdown with 83 country options - Standardize T-shirt sizes in constants package - Add US states dropdown with conditional logic - Add contextual guidance banners and tooltips LFXV2-454, LFXV2-465, LFXV2-466, LFXV2-467, LFXV2-468, LFXV2-469, LFXV2-470, LFXV2-471, LFXV2-472, LFXV2-473 --signoff Signed-off-by: Asitha de Silva <[email protected]>
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. Caution Review failedThe pull request is closed. WalkthroughAdds a full user profile feature: client routes and lazy loading, profile layout and stats, edit/email/password pages (edit is functional), shared constants and interfaces, client UserService methods, server ProfileController/routes and SupabaseService methods, registers /api/profile, header nav change, global style tokens, and a cSpell entry for "TSHIRT". Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant Header as HeaderComponent
participant Router as Angular Router
participant Layout as ProfileLayoutComponent
participant UserSvc as UserService (FE)
participant API as /api/profile
participant Ctl as ProfileController
participant SB as SupabaseService
User->>Header: Click "Profile"
Header->>Router: navigate '/profile'
Router->>Layout: init
Layout->>UserSvc: getCurrentUserProfile()
UserSvc->>API: GET /api/profile
API->>Ctl: dispatch GET /
Ctl->>SB: getUser(authUserId)
Ctl->>SB: getProfile(user.id) / createProfileIfNotExists()
SB-->>Ctl: ProfileDetails
Ctl-->>API: 200 CombinedProfile
API-->>UserSvc: CombinedProfile
UserSvc-->>Layout: profile data
Layout-->>User: render profile UI
sequenceDiagram
autonumber
actor User
participant Edit as ProfileEditComponent
participant UserSvc as UserService (FE)
participant APIU as /api/profile/user
participant APID as /api/profile/details
participant Ctl as ProfileController
participant SB as SupabaseService
User->>Edit: Submit form
Edit->>Edit: validate
par update user
Edit->>UserSvc: updateUserInfo(payloadA)
UserSvc->>APIU: PATCH /api/profile/user
APIU->>Ctl: updateCurrentUser
Ctl->>SB: updateUser(...)
SB-->>Ctl: UserProfile
Ctl-->>APIU: 200
and update profile
Edit->>UserSvc: updateProfileDetails(payloadB)
UserSvc->>APID: PATCH /api/profile/details
APID->>Ctl: updateCurrentProfile
Ctl->>SB: updateProfileDetails(...)
SB-->>Ctl: ProfileDetails
Ctl-->>APID: 200
end
Edit->>UserSvc: getCurrentUserProfile() (reload)
UserSvc->>API: GET /api/profile
API-->>Edit: CombinedProfile
Edit-->>User: show success
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro Disabled knowledge base sources:
📒 Files selected for processing (5)
✨ Finishing touches
🧪 Generate unit tests
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR implements a comprehensive profile management system that allows users to edit personal and professional information across two Supabase tables (public.users and public.profiles). The system includes reactive forms, country/state dropdowns, T-shirt size standardization, and automatic profile creation for new users.
Key changes include:
- Complete profile management system with reactive Angular forms and backend API integration
- Standardized country, state, and T-shirt size constants for data consistency
- Profile layout component with navigation and user avatar display
Reviewed Changes
Copilot reviewed 25 out of 25 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/shared/src/interfaces/user-profile.interface.ts | New TypeScript interfaces for user profiles and combined profile data |
| packages/shared/src/constants/*.ts | Standardized constants for countries, US states, and T-shirt sizes |
| apps/lfx-pcc/src/server/ | Backend API routes, controllers, and services for profile management |
| apps/lfx-pcc/src/app/modules/profile/ | Frontend profile editing components and routing |
| apps/lfx-pcc/src/app/layouts/profile-layout/ | Profile layout component with navigation and user display |
| apps/lfx-pcc/src/app/shared/services/user.service.ts | Extended user service with profile management methods |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
✅ E2E Tests PassedBrowser: chromium All E2E tests passed successfully. Test Configuration
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (18)
.vscode/settings.json (1)
29-29: Add lowercase and hyphenated variants for cSpellcSpell is case-sensitive; code uses "tshirt_size". Add "tshirt" and "t-shirt" to avoid false positives.
"cSpell.words": [ @@ - "TSHIRT", + "TSHIRT", + "tshirt", + "t-shirt",apps/lfx-pcc/src/styles.scss (1)
38-41: Use a shared text token fallback for consistencyRoute all form-control text colors through a single base token with fallback to keep themes consistent.
- --p-inputtext-color: #333; - --p-select-color: #333; - --p-multiselect-color: #333; - --p-textarea-color: #333; + --p-inputtext-color: var(--p-text-color, #333); + --p-select-color: var(--p-text-color, #333); + --p-multiselect-color: var(--p-text-color, #333); + --p-textarea-color: var(--p-text-color, #333);Please confirm these vars are honored by the current PrimeNG theme tokens across input/select/multiselect/textarea.
packages/shared/src/constants/tshirt-sizes.constants.ts (1)
7-15: Solid single source of truth; consider a value→label mapThe list and derived type are correct. Optionally export a map for O(1) label lookups in UIs.
export const TSHIRT_SIZES = [ { label: 'Extra Small', value: 'XS' }, @@ ] as const; +export const TSHIRT_LABEL_BY_VALUE = Object.fromEntries( + TSHIRT_SIZES.map((o) => [o.value, o.label]) +) as Record<TShirtSize, string>;packages/shared/src/constants/countries.constants.ts (2)
7-97: Source countries from a canonical list to reduce driftManually curating labels (e.g., “Czech Republic” vs “Czechia”) can drift from ISO/CLDR. Consider generating this list from a canonical source during build or periodically.
107-110: Tighten types and speed up lookupsUse CountryCode in the signature and a precomputed map for O(1) access.
+export const COUNTRY_LABEL_BY_CODE = Object.fromEntries( + COUNTRIES.map((c) => [c.value, c.label]) +) as Record<CountryCode, string>; + -export function getCountryByCode(code: string): string { - const country = COUNTRIES.find((c) => c.value === code); - return country?.label || code; -} +export function getCountryByCode(code: CountryCode): string { + return COUNTRY_LABEL_BY_CODE[code] ?? code; +}packages/shared/src/interfaces/user-profile.interface.ts (2)
20-34: Prefer specific shared types over bare stringsUse CountryCode/USState/TShirtSize to prevent invalid values flowing into the system.
+import type { CountryCode } from '../../constants/countries.constants'; +import type { USState } from '../../constants/states.constants'; +import type { TShirtSize } from '../../constants/tshirt-sizes.constants'; @@ export interface ProfileDetails { id: number; user_id: string; // UUID reference to auth.users.id title: string | null; organization: string | null; - country: string | null; - state: string | null; + country: CountryCode | null; + state: USState | null; city: string | null; address: string | null; zipcode: string | null; phone_number: string | null; - tshirt_size: string | null; + tshirt_size: TShirtSize | null; created_at: string; updated_at: string; }
57-67: Align update request types to shared enumsMirror the stricter field types in the update DTO for earlier validation.
export interface UpdateProfileDetailsRequest { title?: string | null; organization?: string | null; - country?: string | null; - state?: string | null; + country?: CountryCode | null; + state?: USState | null; city?: string | null; address?: string | null; zipcode?: string | null; phone_number?: string | null; - tshirt_size?: string | null; + tshirt_size?: TShirtSize | null; }apps/lfx-pcc/src/app/app.routes.ts (1)
25-30: LGTM: lazy-loaded, guarded profile routeStandalone component import and guard usage match guidelines. Consider adding a route title/breadcrumb in data when ready.
packages/shared/src/interfaces/index.ts (1)
52-53: Guideline: avoid barrel exports in shared packagesProject guideline prefers direct imports over barrels in {apps/lfx-pcc,packages/shared}. If feasible, import
user-profile.interfacedirectly at call sites instead of re-exporting here. If the repo intentionally centralizes interfaces via this index, keep it consistent and consider documenting the exception.apps/lfx-pcc/src/app/modules/profile/password/profile-password.component.ts (1)
15-16: Track TODO for password flow.If helpful, I can scaffold the form + service contract and open a follow-up issue.
apps/lfx-pcc/src/app/shared/components/header/header.component.ts (1)
15-17: Use type-only imports for PrimeNG types to reduce bundle impact.-import { MenuItem } from 'primeng/api'; -import { AutoCompleteCompleteEvent, AutoCompleteSelectEvent } from 'primeng/autocomplete'; +import type { MenuItem } from 'primeng/api'; +import type { AutoCompleteCompleteEvent, AutoCompleteSelectEvent } from 'primeng/autocomplete';apps/lfx-pcc/src/app/modules/profile/email/profile-email.component.ts (1)
15-16: Track TODO for email settings flow.I can propose a minimal contract (verify email, update, resend) wired to your API.
packages/shared/src/constants/index.ts (1)
8-8: Avoid barrel re-exports — migrate consumers to direct constant-file importsRipgrep found many consumers importing constants via barrels (e.g., apps/lfx-pcc/src/server/services/nats.service.ts, apps/lfx-pcc/src/app/modules/profile/edit/profile-edit.component.ts, apps/lfx-pcc/src/app/modules/project/meetings/components/agenda-template-selector/agenda-template-selector.component.ts, docs/architecture.md). Remove the re-exports from packages/shared/src/constants/index.ts and update callers to import directly from the specific files (example:
import { COUNTRIES } from '@lfx-pcc/shared/constants/countries.constants'). Also audit the package root (@lfx-pcc/shared) for re-exports and stop re-exporting these constants.apps/lfx-pcc/src/app/modules/profile/edit/profile-edit.component.ts (5)
48-51: Consider using country codes for better internationalization support.Currently mapping country labels (e.g., "United States") as values instead of ISO country codes (e.g., "US"). This approach could cause issues with:
- Database storage efficiency (storing full names vs 2-letter codes)
- Future internationalization when displaying in different languages
- API integrations that expect standard country codes
Consider using the country code as the value:
- public readonly countryOptions = COUNTRIES.map((country: { label: string; value: string }) => ({ - label: country.label, - value: country.label, - })); + public readonly countryOptions = COUNTRIES.map((country: { label: string; value: string }) => ({ + label: country.label, + value: country.value, + }));Then update the USA check:
- return this.selectedCountrySignal() === 'United States'; + return this.selectedCountrySignal() === 'US';
54-57: Consider using state codes for consistency.Similar to the country options, consider using state codes (e.g., "CA" for California) as values instead of full state names for better data consistency and storage efficiency.
- public readonly stateOptions = US_STATES.map((state) => ({ - label: state.label, - value: state.label, - })); + public readonly stateOptions = US_STATES.map((state) => ({ + label: state.label, + value: state.value, + }));
87-94: Consider preserving state value for non-US countries.The current logic clears the state field whenever the country changes from United States. This could be problematic if:
- A user accidentally changes the country and then switches back
- Other countries also have states/provinces that need to be captured
Consider only clearing the state when switching FROM United States to another country:
this.profileForm.get('country')?.valueChanges.subscribe((country: string) => { + const previousCountry = this.selectedCountrySignal(); this.selectedCountrySignal.set(country || ''); // Clear state field when country changes to avoid invalid state/country combinations - if (country !== 'United States') { + if (previousCountry === 'United States' && country !== 'United States') { this.profileForm.get('state')?.setValue(''); } });
99-100: Provide specific validation feedback to users.The current implementation marks all fields as touched but doesn't provide specific feedback about which fields have validation errors.
Consider adding more specific validation feedback:
if (this.profileForm.invalid) { this.markFormGroupTouched(this.profileForm); + const errors = this.getFormValidationErrors(); + if (errors.length > 0) { + this.messageService.add({ + severity: 'error', + summary: 'Validation Error', + detail: `Please fix the following fields: ${errors.join(', ')}`, + }); + } return; }Add this helper method:
private getFormValidationErrors(): string[] { const errors: string[] = []; Object.keys(this.profileForm.controls).forEach(key => { const control = this.profileForm.get(key); if (control && control.errors) { errors.push(key.replace('_', ' ')); } }); return errors; }
65-81: Add pattern validation for phone numbers and zip codes.Phone numbers and zip codes currently only have maxLength validators. Consider adding pattern validation to ensure data quality.
- zipcode: ['', [Validators.maxLength(20)]], - phone_number: ['', [Validators.maxLength(20)]], + zipcode: ['', [Validators.maxLength(20), Validators.pattern(/^[A-Za-z0-9\s-]+$/)]], + phone_number: ['', [Validators.maxLength(20), Validators.pattern(/^[+]?[0-9\s()-]+$/)]],
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (25)
.vscode/settings.json(1 hunks)apps/lfx-pcc/src/app/app.routes.ts(1 hunks)apps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.html(1 hunks)apps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.scss(1 hunks)apps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.ts(1 hunks)apps/lfx-pcc/src/app/modules/profile/edit/profile-edit.component.html(1 hunks)apps/lfx-pcc/src/app/modules/profile/edit/profile-edit.component.ts(1 hunks)apps/lfx-pcc/src/app/modules/profile/email/profile-email.component.html(1 hunks)apps/lfx-pcc/src/app/modules/profile/email/profile-email.component.ts(1 hunks)apps/lfx-pcc/src/app/modules/profile/password/profile-password.component.html(1 hunks)apps/lfx-pcc/src/app/modules/profile/password/profile-password.component.ts(1 hunks)apps/lfx-pcc/src/app/modules/profile/profile.routes.ts(1 hunks)apps/lfx-pcc/src/app/shared/components/header/header.component.ts(2 hunks)apps/lfx-pcc/src/app/shared/services/user.service.ts(2 hunks)apps/lfx-pcc/src/server/controllers/profile.controller.ts(1 hunks)apps/lfx-pcc/src/server/routes/profile.route.ts(1 hunks)apps/lfx-pcc/src/server/server.ts(3 hunks)apps/lfx-pcc/src/server/services/supabase.service.ts(2 hunks)apps/lfx-pcc/src/styles.scss(1 hunks)packages/shared/src/constants/countries.constants.ts(1 hunks)packages/shared/src/constants/index.ts(1 hunks)packages/shared/src/constants/states.constants.ts(1 hunks)packages/shared/src/constants/tshirt-sizes.constants.ts(1 hunks)packages/shared/src/interfaces/index.ts(1 hunks)packages/shared/src/interfaces/user-profile.interface.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx,js,jsx,html,scss,css}
📄 CodeRabbit inference engine (CLAUDE.md)
Include required license headers on all source files
Files:
apps/lfx-pcc/src/styles.scssapps/lfx-pcc/src/app/modules/profile/email/profile-email.component.htmlapps/lfx-pcc/src/app/modules/profile/password/profile-password.component.htmlapps/lfx-pcc/src/app/modules/profile/password/profile-password.component.tsapps/lfx-pcc/src/app/modules/profile/email/profile-email.component.tsapps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.scsspackages/shared/src/constants/index.tsapps/lfx-pcc/src/app/app.routes.tsapps/lfx-pcc/src/server/server.tspackages/shared/src/constants/tshirt-sizes.constants.tspackages/shared/src/interfaces/user-profile.interface.tspackages/shared/src/constants/countries.constants.tsapps/lfx-pcc/src/app/modules/profile/edit/profile-edit.component.htmlapps/lfx-pcc/src/app/modules/profile/profile.routes.tspackages/shared/src/constants/states.constants.tsapps/lfx-pcc/src/app/shared/services/user.service.tsapps/lfx-pcc/src/server/routes/profile.route.tsapps/lfx-pcc/src/server/controllers/profile.controller.tspackages/shared/src/interfaces/index.tsapps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.htmlapps/lfx-pcc/src/app/modules/profile/edit/profile-edit.component.tsapps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.tsapps/lfx-pcc/src/server/services/supabase.service.tsapps/lfx-pcc/src/app/shared/components/header/header.component.ts
apps/lfx-pcc/src/**/*.{ts,html}
📄 CodeRabbit inference engine (CLAUDE.md)
Use LFX wrapper components instead of importing PrimeNG components directly
Files:
apps/lfx-pcc/src/app/modules/profile/email/profile-email.component.htmlapps/lfx-pcc/src/app/modules/profile/password/profile-password.component.htmlapps/lfx-pcc/src/app/modules/profile/password/profile-password.component.tsapps/lfx-pcc/src/app/modules/profile/email/profile-email.component.tsapps/lfx-pcc/src/app/app.routes.tsapps/lfx-pcc/src/server/server.tsapps/lfx-pcc/src/app/modules/profile/edit/profile-edit.component.htmlapps/lfx-pcc/src/app/modules/profile/profile.routes.tsapps/lfx-pcc/src/app/shared/services/user.service.tsapps/lfx-pcc/src/server/routes/profile.route.tsapps/lfx-pcc/src/server/controllers/profile.controller.tsapps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.htmlapps/lfx-pcc/src/app/modules/profile/edit/profile-edit.component.tsapps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.tsapps/lfx-pcc/src/server/services/supabase.service.tsapps/lfx-pcc/src/app/shared/components/header/header.component.ts
apps/lfx-pcc/src/**/*.html
📄 CodeRabbit inference engine (CLAUDE.md)
apps/lfx-pcc/src/**/*.html: Add data-testid attributes to new components for reliable test targeting
Follow data-testid naming convention: [section]-[component]-[element]
Files:
apps/lfx-pcc/src/app/modules/profile/email/profile-email.component.htmlapps/lfx-pcc/src/app/modules/profile/password/profile-password.component.htmlapps/lfx-pcc/src/app/modules/profile/edit/profile-edit.component.htmlapps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.html
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Prefer TypeScript interfaces over union types when modeling shapes and contracts
Files:
apps/lfx-pcc/src/app/modules/profile/password/profile-password.component.tsapps/lfx-pcc/src/app/modules/profile/email/profile-email.component.tspackages/shared/src/constants/index.tsapps/lfx-pcc/src/app/app.routes.tsapps/lfx-pcc/src/server/server.tspackages/shared/src/constants/tshirt-sizes.constants.tspackages/shared/src/interfaces/user-profile.interface.tspackages/shared/src/constants/countries.constants.tsapps/lfx-pcc/src/app/modules/profile/profile.routes.tspackages/shared/src/constants/states.constants.tsapps/lfx-pcc/src/app/shared/services/user.service.tsapps/lfx-pcc/src/server/routes/profile.route.tsapps/lfx-pcc/src/server/controllers/profile.controller.tspackages/shared/src/interfaces/index.tsapps/lfx-pcc/src/app/modules/profile/edit/profile-edit.component.tsapps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.tsapps/lfx-pcc/src/server/services/supabase.service.tsapps/lfx-pcc/src/app/shared/components/header/header.component.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Do not nest ternary expressions
Files:
apps/lfx-pcc/src/app/modules/profile/password/profile-password.component.tsapps/lfx-pcc/src/app/modules/profile/email/profile-email.component.tspackages/shared/src/constants/index.tsapps/lfx-pcc/src/app/app.routes.tsapps/lfx-pcc/src/server/server.tspackages/shared/src/constants/tshirt-sizes.constants.tspackages/shared/src/interfaces/user-profile.interface.tspackages/shared/src/constants/countries.constants.tsapps/lfx-pcc/src/app/modules/profile/profile.routes.tspackages/shared/src/constants/states.constants.tsapps/lfx-pcc/src/app/shared/services/user.service.tsapps/lfx-pcc/src/server/routes/profile.route.tsapps/lfx-pcc/src/server/controllers/profile.controller.tspackages/shared/src/interfaces/index.tsapps/lfx-pcc/src/app/modules/profile/edit/profile-edit.component.tsapps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.tsapps/lfx-pcc/src/server/services/supabase.service.tsapps/lfx-pcc/src/app/shared/components/header/header.component.ts
apps/lfx-pcc/src/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
apps/lfx-pcc/src/**/*.ts: In the Angular app, use direct imports for standalone components (no barrel imports)
When defining types for PrimeNG usage, reference PrimeNG’s component interfaces
Files:
apps/lfx-pcc/src/app/modules/profile/password/profile-password.component.tsapps/lfx-pcc/src/app/modules/profile/email/profile-email.component.tsapps/lfx-pcc/src/app/app.routes.tsapps/lfx-pcc/src/server/server.tsapps/lfx-pcc/src/app/modules/profile/profile.routes.tsapps/lfx-pcc/src/app/shared/services/user.service.tsapps/lfx-pcc/src/server/routes/profile.route.tsapps/lfx-pcc/src/server/controllers/profile.controller.tsapps/lfx-pcc/src/app/modules/profile/edit/profile-edit.component.tsapps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.tsapps/lfx-pcc/src/server/services/supabase.service.tsapps/lfx-pcc/src/app/shared/components/header/header.component.ts
packages/shared/src/constants/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Place all reusable constants (design tokens, etc.) in the shared package
Files:
packages/shared/src/constants/index.tspackages/shared/src/constants/tshirt-sizes.constants.tspackages/shared/src/constants/countries.constants.tspackages/shared/src/constants/states.constants.ts
{apps/lfx-pcc/src,packages/shared/src}/**/index.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Avoid barrel exports; use direct imports instead of index.ts barrels
Files:
packages/shared/src/constants/index.tspackages/shared/src/interfaces/index.ts
packages/shared/src/interfaces/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Place all shared interfaces in the shared package
Files:
packages/shared/src/interfaces/user-profile.interface.tspackages/shared/src/interfaces/index.ts
🧠 Learnings (4)
📚 Learning: 2025-09-05T18:09:48.792Z
Learnt from: CR
PR: linuxfoundation/lfx-v2-ui#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-05T18:09:48.792Z
Learning: Applies to apps/lfx-pcc/src/**/*.ts : In the Angular app, use direct imports for standalone components (no barrel imports)
Applied to files:
apps/lfx-pcc/src/app/modules/profile/password/profile-password.component.tsapps/lfx-pcc/src/app/modules/profile/email/profile-email.component.ts
📚 Learning: 2025-09-05T18:09:48.792Z
Learnt from: CR
PR: linuxfoundation/lfx-v2-ui#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-05T18:09:48.792Z
Learning: Applies to apps/lfx-pcc/src/**/*.{ts,html} : Use LFX wrapper components instead of importing PrimeNG components directly
Applied to files:
apps/lfx-pcc/src/app/modules/profile/password/profile-password.component.tsapps/lfx-pcc/src/app/modules/profile/email/profile-email.component.ts
📚 Learning: 2025-09-05T18:09:48.792Z
Learnt from: CR
PR: linuxfoundation/lfx-v2-ui#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-05T18:09:48.792Z
Learning: Applies to packages/shared/src/constants/**/*.ts : Place all reusable constants (design tokens, etc.) in the shared package
Applied to files:
packages/shared/src/constants/index.tspackages/shared/src/constants/tshirt-sizes.constants.tspackages/shared/src/constants/countries.constants.ts
📚 Learning: 2025-09-05T18:09:48.792Z
Learnt from: CR
PR: linuxfoundation/lfx-v2-ui#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-05T18:09:48.792Z
Learning: Applies to packages/shared/src/interfaces/**/*.ts : Place all shared interfaces in the shared package
Applied to files:
packages/shared/src/interfaces/index.ts
🧬 Code graph analysis (9)
apps/lfx-pcc/src/app/modules/profile/password/profile-password.component.ts (2)
apps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.ts (1)
Component(16-155)apps/lfx-pcc/src/app/modules/profile/email/profile-email.component.ts (1)
Component(8-16)
apps/lfx-pcc/src/app/modules/profile/email/profile-email.component.ts (2)
apps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.ts (1)
Component(16-155)apps/lfx-pcc/src/app/modules/profile/password/profile-password.component.ts (1)
Component(8-16)
apps/lfx-pcc/src/app/app.routes.ts (1)
apps/lfx-pcc/src/app/shared/guards/auth.guard.ts (1)
authGuard(16-32)
apps/lfx-pcc/src/app/shared/services/user.service.ts (2)
packages/shared/src/interfaces/user-profile.interface.ts (3)
CombinedProfile(39-42)UpdateUserProfileRequest(47-52)UpdateProfileDetailsRequest(57-67)packages/shared/src/interfaces/auth.interface.ts (1)
User(8-41)
apps/lfx-pcc/src/server/routes/profile.route.ts (1)
apps/lfx-pcc/src/server/controllers/profile.controller.ts (1)
ProfileController(15-206)
apps/lfx-pcc/src/server/controllers/profile.controller.ts (3)
apps/lfx-pcc/src/server/helpers/logger.ts (1)
error(52-65)apps/lfx-pcc/src/server/utils/auth-helper.ts (1)
getUsernameFromAuth(10-50)packages/shared/src/interfaces/user-profile.interface.ts (1)
CombinedProfile(39-42)
apps/lfx-pcc/src/app/modules/profile/edit/profile-edit.component.ts (4)
packages/shared/src/interfaces/user-profile.interface.ts (3)
CombinedProfile(39-42)UpdateUserProfileRequest(47-52)UpdateProfileDetailsRequest(57-67)packages/shared/src/constants/tshirt-sizes.constants.ts (1)
TSHIRT_SIZES(7-15)packages/shared/src/constants/countries.constants.ts (1)
COUNTRIES(7-97)packages/shared/src/constants/states.constants.ts (1)
US_STATES(7-59)
apps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.ts (2)
apps/lfx-pcc/src/app/modules/profile/edit/profile-edit.component.ts (1)
Component(19-214)packages/shared/src/interfaces/user-profile.interface.ts (1)
CombinedProfile(39-42)
apps/lfx-pcc/src/server/services/supabase.service.ts (1)
packages/shared/src/interfaces/user-profile.interface.ts (4)
UserProfile(7-15)ProfileDetails(20-34)UpdateUserProfileRequest(47-52)UpdateProfileDetailsRequest(57-67)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: E2E Tests / Playwright E2E Tests
🔇 Additional comments (45)
apps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.scss (1)
1-18: LGTM: scoped, minimal styles with license headers presentThe Tailwind-first approach with small custom hooks looks good. No issues found.
apps/lfx-pcc/src/app/modules/profile/password/profile-password.component.html (1)
6-13: LGTM: Uses LFX wrapper and includes license header.apps/lfx-pcc/src/server/server.ts (2)
24-24: LGTM: Profile API router mounted behind auth middleware.Also applies to: 205-205
226-228: Re-check userinfo fallback condition — fetch userinfo when name OR email is missing.Many IdPs omit "name"; fetch userinfo when either email or name is missing to avoid empty UI fallbacks.
File: apps/lfx-pcc/src/server/server.ts (around lines 226–228)- if (!auth.user?.name) { + if (!auth.user?.email || !auth.user?.name) { auth.user = await req.oidc.fetchUserInfo(); }Automated repo search returned no files — run locally to confirm which claim(s) the UI depends on:
rg -nP -C2 '\bauth\.user\.(email|name|username)\b' -S || git grep -n "auth.user." -- '*.ts' '*.tsx' '*.html' || trueapps/lfx-pcc/src/app/modules/profile/password/profile-password.component.ts (1)
8-16: LGTM: Standalone component with direct imports (no barrels) and LFX card.apps/lfx-pcc/src/app/modules/profile/email/profile-email.component.html (1)
6-13: LGTM: Wrapper usage and license header present.apps/lfx-pcc/src/app/modules/profile/profile.routes.ts (1)
6-19: LGTM: Lazy-loaded standalone components; direct file imports, no barrels.apps/lfx-pcc/src/app/shared/components/header/header.component.ts (1)
52-57: Switch to internal routing for Profile is correct.Works with new '/profile' routes and preserves SPA navigation.
apps/lfx-pcc/src/app/modules/profile/email/profile-email.component.ts (1)
8-16: LGTM: Standalone component with direct imports; matches pattern used for Password.apps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.html (5)
1-3: LGTM - Proper license headersThe file includes the required copyright and license header as specified in the coding guidelines.
8-17: LGTM - Well-structured breadcrumb implementationThe breadcrumb implementation follows the data-testid guidelines and uses proper Angular syntax with signal bindings and ng-template.
23-30: LGTM - Avatar implementation with accessibilityGood use of LFX wrapper components (lfx-avatar) as required by the coding guidelines, proper accessibility attributes, and data-testid for testing.
51-64: LGTM - Menu items implementationProper use of Angular control flow (@for), signal bindings, routerLink navigation, and data-testid attributes following the naming convention.
71-80: LGTM - Conditional content rendering with loading stateClean implementation of loading states with proper data-testid attributes and accessibility considerations.
packages/shared/src/constants/states.constants.ts (3)
1-3: LGTM - Proper license headersThe file includes the required copyright and license header as specified in the coding guidelines.
7-59: LGTM - Well-structured constants with proper typingThe US_STATES constant is properly typed with
as constand includes all 50 states plus DC. Good placement in the shared constants package as required by guidelines.
61-64: LGTM - Type-safe constant type derivationThe USState type properly derives from the constant array, ensuring type safety and consistency.
apps/lfx-pcc/src/server/routes/profile.route.ts (3)
1-3: LGTM - Proper license headersThe file includes the required copyright and license header as specified in the coding guidelines.
4-11: LGTM - Clean route setupGood separation of concerns with proper imports and controller instantiation.
12-26: LGTM - Well-documented route definitionsClear route definitions with proper HTTP methods and documentation. The comment about authentication middleware is helpful.
apps/lfx-pcc/src/app/modules/profile/edit/profile-edit.component.html (7)
1-3: LGTM - Proper license headersThe file includes the required copyright and license header as specified in the coding guidelines.
5-10: LGTM - Loading state implementationClean loading state with proper data-testid attributes and accessibility considerations.
26-85: LGTM - Personal information sectionGood use of LFX wrapper components, proper form bindings, and data-testid attributes following the naming convention.
169-191: LGTM - Conditional state field implementationSmart conditional rendering for USA states vs. text input based on country selection. Good UX pattern.
287-299: LGTM - Form action buttonsGood implementation of form submission with proper loading states and validation checks.
68-72: TooltipModule import present — no action requiredTooltipModule is already imported in the component's imports array at apps/lfx-pcc/src/app/modules/profile/edit/profile-edit.component.ts.
306-307: ToastModule is imported — no change required.
ToastModule appears in the component's standalone imports and MessageService is provided.apps/lfx-pcc/src/app/shared/services/user.service.ts (2)
6-6: LGTM - Updated importsProper import of new interfaces from shared package following TypeScript interface preference guideline.
23-44: LGTM - Profile management methodsWell-documented service methods with proper TypeScript typing and clear API contracts. Good separation between user and profile detail updates.
apps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.ts (5)
1-3: LGTM - Proper license headersThe file includes the required copyright and license header as specified in the coding guidelines.
16-22: LGTM - Component setupGood use of standalone component with proper imports and direct component imports as required by Angular app guidelines.
49-51: LGTM - Profile initialization with reactive patternsClean use of toSignal and finalize for loading state management. Good reactive programming patterns.
53-79: LGTM - User initials calculationWell-structured computed signal with proper fallback hierarchy (first/last name → username → email).
104-131: LGTM - Profile title computationGood fallback logic for profile title with proper null checking and signal-based reactivity.
apps/lfx-pcc/src/server/services/supabase.service.ts (6)
11-22: LGTM - Interface importsProper import of shared interface types following TypeScript interface preference guideline.
531-553: LGTM - User retrieval methodWell-structured method with proper error handling and timeout configuration.
555-577: LGTM - Profile retrieval methodClean implementation with consistent error handling and URL parameter construction.
579-603: LGTM - User update methodGood implementation with automatic timestamp updates and proper error handling.
608-638: LGTM - Profile details update methodWell-structured method that retrieves user first, then updates profile with proper error handling.
643-671: LGTM - Profile creation methodSmart implementation that checks for existing profile before creating, preventing duplicates.
apps/lfx-pcc/src/server/controllers/profile.controller.ts (5)
1-3: LGTM - Proper license headersThe file includes the required copyright and license header as specified in the coding guidelines.
4-16: LGTM - Controller setupClean controller setup with proper imports and service injection.
21-83: LGTM - getCurrentUserProfile implementationWell-structured method with proper authentication checks, error handling, logging, and automatic profile creation when missing.
88-144: LGTM - updateCurrentUser implementationGood implementation with field validation, whitelist approach for allowed fields, and comprehensive logging.
149-206: LGTM - updateCurrentProfile implementationWell-implemented method with proper field validation, comprehensive allowed fields list, and consistent error handling patterns.
apps/lfx-pcc/src/app/modules/profile/email/profile-email.component.html
Outdated
Show resolved
Hide resolved
apps/lfx-pcc/src/app/modules/profile/password/profile-password.component.html
Outdated
Show resolved
Hide resolved
- Move member since and last active to profile layout opposite menu items - Add computed signals for memberSince and lastActive in ProfileLayoutComponent - Remove member info cards from ProfileStatsComponent sidebar - Reorganize profile stats component order: quick actions first, then statistics - Align all profile module data-testid with [section]-[component]-[element] convention - Update profile-email, profile-password, and profile-edit components data-testids Generated with [Claude Code](https://claude.ai/code) Signed-off-by: Asitha de Silva <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 10
♻️ Duplicate comments (1)
apps/lfx-pcc/src/app/modules/profile/edit/profile-edit.component.html (1)
168-191: Unique IDs for conditional State field + dynamic label ‘for’.
Prevents potential a11y/test flakiness and aligns with prior feedback.- <label for="state" class="block text-sm font-medium text-gray-700 mb-1">State/Province</label> + <label [attr.for]="isUSA() ? 'state-select' : 'state-input'" class="block text-sm font-medium text-gray-700 mb-1">State/Province</label> @if (isUSA()) { <lfx-select size="small" [form]="profileForm" control="state" [options]="stateOptions" - id="state" + id="state-select" placeholder="Select your state" styleClass="w-full" [filter]="true" data-testid="profile-edit-location-state-select"> </lfx-select> } @else { <lfx-input-text size="small" [form]="profileForm" control="state" - id="state" + id="state-input" placeholder="Enter your state or province" styleClass="w-full" data-testid="profile-edit-location-state-input"> </lfx-input-text> }
🧹 Nitpick comments (9)
apps/lfx-pcc/src/app/modules/profile/edit/profile-edit.component.html (3)
11-11: Add data-testid to form and card container for stable E2E hooks.
Minimal addition; improves test targeting at container level.- <form [formGroup]="profileForm" (ngSubmit)="onSubmit()"> + <form [formGroup]="profileForm" (ngSubmit)="onSubmit()" data-testid="profile-edit-form"> ... - <lfx-card> + <lfx-card data-testid="profile-edit-card">Also applies to: 26-26
239-247: Use inputmode for phone to improve mobile UX.
If lfx-input-text forwards arbitrary attributes, this enables numeric keypad.- <lfx-input-text + <lfx-input-text size="small" [form]="profileForm" control="phone_number" id="phone" placeholder="Enter your phone number" + inputmode="tel" styleClass="w-full" data-testid="profile-edit-location-phone"> </lfx-input-text>
6-9: Add live region semantics to loading state.
Improves screen reader announcement of loading.- <div class="flex flex-col gap-2 items-center justify-center py-12" data-testid="profile-edit-loading-container"> - <i class="fa-light fa-circle-notch fa-spin text-4xl text-blue-400" data-testid="profile-edit-loading-spinner"></i> - <span class="ml-3 text-gray-600">Loading profile...</span> + <div class="flex flex-col gap-2 items-center justify-center py-12" role="status" aria-live="polite" data-testid="profile-edit-loading-container"> + <i class="fa-light fa-circle-notch fa-spin text-4xl text-blue-400" aria-hidden="true" data-testid="profile-edit-loading-spinner"></i> + <span class="ml-3 text-gray-600">Loading profile...</span> </div>apps/lfx-pcc/src/server/services/supabase.service.ts (2)
531-553: Add response body to error for easier diagnostics; optional: request single-object semanticsIncluding the server’s error text here matches patterns used elsewhere in this file and speeds up debugging. Optionally, consider using PostgREST single-object semantics to assert “exactly one row” when appropriate.
- if (!response.ok) { - throw new Error(`Failed to fetch user profile: ${response.status} ${response.statusText}`); - } + if (!response.ok) { + const errorText = await response.text(); + throw new Error(`Failed to fetch user profile: ${response.status} ${response.statusText}: ${errorText}`); + }
555-577: Mirror error handling style and surface server messageReturn the response text on failure for consistency and better traceability.
- if (!response.ok) { - throw new Error(`Failed to fetch profile details: ${response.status} ${response.statusText}`); - } + if (!response.ok) { + const errorText = await response.text(); + throw new Error(`Failed to fetch profile details: ${response.status} ${response.statusText}: ${errorText}`); + }apps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.html (3)
40-41: Invalid Tailwind class ‘text-black-600’.
Use text-gray-600 for intended weight/tone.- <p class="text-black-600 text-sm mb-2" data-testid="profile-subtitle"> + <p class="text-gray-600 text-sm mb-2" data-testid="profile-subtitle">
50-57: Anchors without href hurt a11y; prefer button or conditional link.
If no profile URL yet, render a button; when available, render an anchor with rel and target.Example:
<!-- When URL available --> <a [href]="githubUrl" target="_blank" rel="noopener noreferrer" aria-label="Open GitHub profile" data-testid="profile-github-profile"> <i class="fa-brands fa-github ..."></i> </a> <!-- Fallback --> <button type="button" aria-label="GitHub profile (not set)" class="text-sm text-gray-600 flex items-center gap-2" data-testid="profile-github-profile"> <i class="fa-brands fa-github ..."></i> </button>
118-121: Improve loading state a11y.
Expose status semantics and hide decorative spinner icon.- <div class="flex flex-col gap-2 items-center justify-center py-12" data-testid="profile-loading"> - <i class="fa-light fa-circle-notch fa-spin text-4xl text-blue-400" data-testid="loading-spinner"></i> + <div class="flex flex-col gap-2 items-center justify-center py-12" data-testid="profile-loading" role="status" aria-live="polite" aria-busy="true" aria-label="Loading profile"> + <i class="fa-light fa-circle-notch fa-spin text-4xl text-blue-400" data-testid="loading-spinner" aria-hidden="true"></i>apps/lfx-pcc/src/app/layouts/profile-layout/components/profile-stats/profile-stats.component.ts (1)
38-57: Duplicate date-delta logic across components — extract to shared util.
Same logic exists in ProfileLayoutComponent; centralize to avoid drift.Proposed shared util API:
export function formatMemberSince(createdAt: string, now = new Date()): string; export function timeAgo(updatedAt: string, now = new Date()): string;I can add packages/shared/src/utils/date-format.util.ts and update both callers.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (11)
apps/lfx-pcc/src/app/layouts/profile-layout/components/profile-stats/profile-stats.component.html(1 hunks)apps/lfx-pcc/src/app/layouts/profile-layout/components/profile-stats/profile-stats.component.scss(1 hunks)apps/lfx-pcc/src/app/layouts/profile-layout/components/profile-stats/profile-stats.component.ts(1 hunks)apps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.html(1 hunks)apps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.ts(1 hunks)apps/lfx-pcc/src/app/modules/profile/edit/profile-edit.component.html(1 hunks)apps/lfx-pcc/src/app/modules/profile/email/profile-email.component.html(1 hunks)apps/lfx-pcc/src/app/modules/profile/password/profile-password.component.html(1 hunks)apps/lfx-pcc/src/server/services/supabase.service.ts(2 hunks)packages/shared/src/interfaces/index.ts(1 hunks)packages/shared/src/interfaces/user-statistics.interface.ts(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- apps/lfx-pcc/src/app/layouts/profile-layout/components/profile-stats/profile-stats.component.scss
🚧 Files skipped from review as they are similar to previous changes (4)
- apps/lfx-pcc/src/app/modules/profile/password/profile-password.component.html
- packages/shared/src/interfaces/index.ts
- apps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.ts
- apps/lfx-pcc/src/app/modules/profile/email/profile-email.component.html
🧰 Additional context used
📓 Path-based instructions (7)
apps/lfx-pcc/src/**/*.{ts,html}
📄 CodeRabbit inference engine (CLAUDE.md)
Use LFX wrapper components instead of importing PrimeNG components directly
Files:
apps/lfx-pcc/src/app/layouts/profile-layout/components/profile-stats/profile-stats.component.htmlapps/lfx-pcc/src/app/layouts/profile-layout/components/profile-stats/profile-stats.component.tsapps/lfx-pcc/src/app/modules/profile/edit/profile-edit.component.htmlapps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.htmlapps/lfx-pcc/src/server/services/supabase.service.ts
apps/lfx-pcc/src/**/*.html
📄 CodeRabbit inference engine (CLAUDE.md)
apps/lfx-pcc/src/**/*.html: Add data-testid attributes to new components for reliable test targeting
Follow data-testid naming convention: [section]-[component]-[element]
Files:
apps/lfx-pcc/src/app/layouts/profile-layout/components/profile-stats/profile-stats.component.htmlapps/lfx-pcc/src/app/modules/profile/edit/profile-edit.component.htmlapps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.html
**/*.{ts,tsx,js,jsx,html,scss,css}
📄 CodeRabbit inference engine (CLAUDE.md)
Include required license headers on all source files
Files:
apps/lfx-pcc/src/app/layouts/profile-layout/components/profile-stats/profile-stats.component.htmlapps/lfx-pcc/src/app/layouts/profile-layout/components/profile-stats/profile-stats.component.tspackages/shared/src/interfaces/user-statistics.interface.tsapps/lfx-pcc/src/app/modules/profile/edit/profile-edit.component.htmlapps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.htmlapps/lfx-pcc/src/server/services/supabase.service.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Prefer TypeScript interfaces over union types when modeling shapes and contracts
Files:
apps/lfx-pcc/src/app/layouts/profile-layout/components/profile-stats/profile-stats.component.tspackages/shared/src/interfaces/user-statistics.interface.tsapps/lfx-pcc/src/server/services/supabase.service.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Do not nest ternary expressions
Files:
apps/lfx-pcc/src/app/layouts/profile-layout/components/profile-stats/profile-stats.component.tspackages/shared/src/interfaces/user-statistics.interface.tsapps/lfx-pcc/src/server/services/supabase.service.ts
apps/lfx-pcc/src/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
apps/lfx-pcc/src/**/*.ts: In the Angular app, use direct imports for standalone components (no barrel imports)
When defining types for PrimeNG usage, reference PrimeNG’s component interfaces
Files:
apps/lfx-pcc/src/app/layouts/profile-layout/components/profile-stats/profile-stats.component.tsapps/lfx-pcc/src/server/services/supabase.service.ts
packages/shared/src/interfaces/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Place all shared interfaces in the shared package
Files:
packages/shared/src/interfaces/user-statistics.interface.ts
🧬 Code graph analysis (2)
apps/lfx-pcc/src/app/layouts/profile-layout/components/profile-stats/profile-stats.component.ts (3)
apps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.ts (1)
Component(18-229)packages/shared/src/interfaces/user-profile.interface.ts (1)
CombinedProfile(39-42)packages/shared/src/interfaces/user-statistics.interface.ts (1)
UserStatistics(7-14)
apps/lfx-pcc/src/server/services/supabase.service.ts (1)
packages/shared/src/interfaces/user-profile.interface.ts (4)
UserProfile(7-15)ProfileDetails(20-34)UpdateUserProfileRequest(47-52)UpdateProfileDetailsRequest(57-67)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: E2E Tests / Playwright E2E Tests
🔇 Additional comments (6)
apps/lfx-pcc/src/app/modules/profile/edit/profile-edit.component.html (2)
1-2: License header present — good.
Complies with header/SPDX requirements.
307-308: Use LFX toast wrapper (or add data-testid) — p-toast found in 3 filesGuideline: use LFX wrapper components in apps/lfx-pcc and add data-testid attributes using [section]-[component]-[element]. Ripgrep shows no lfx-toast wrapper and these usages:
- apps/lfx-pcc/src/app/modules/profile/edit/profile-edit.component.html:308 — replace with (or, if wrapper not available yet, add data-testid: ).
- apps/lfx-pcc/src/app/modules/meeting/meeting.component.html:319 — replace with (or add ).
- apps/lfx-pcc/src/app/app.component.html:3 — replace with (or ).
Either implement a central LFX toast wrapper and switch all usages, or add the data-testid now and follow up with a wrapper PR.
apps/lfx-pcc/src/server/services/supabase.service.ts (1)
11-11: Imports for profile management: LGTMTypes align with shared interfaces and match table shapes.
Also applies to: 15-15, 17-17, 21-21
packages/shared/src/interfaces/user-statistics.interface.ts (1)
7-14: LGTM — clear, minimal interface fits shared surface.
No issues spotted. Re-export usage in consumers looks correct.apps/lfx-pcc/src/app/layouts/profile-layout/components/profile-stats/profile-stats.component.ts (2)
6-8: Import path check (FYI).
Interfaces come from shared barrel; fine. Keep using direct imports only for standalone components per guideline—CardComponent import already complies.
1-3: License header present and correct.
...lfx-pcc/src/app/layouts/profile-layout/components/profile-stats/profile-stats.component.html
Outdated
Show resolved
Hide resolved
apps/lfx-pcc/src/app/layouts/profile-layout/components/profile-stats/profile-stats.component.ts
Show resolved
Hide resolved
apps/lfx-pcc/src/app/layouts/profile-layout/components/profile-stats/profile-stats.component.ts
Show resolved
Hide resolved
apps/lfx-pcc/src/app/layouts/profile-layout/components/profile-stats/profile-stats.component.ts
Show resolved
Hide resolved
apps/lfx-pcc/src/app/layouts/profile-layout/profile-layout.component.html
Show resolved
Hide resolved
Signed-off-by: Asitha de Silva <[email protected]>
Signed-off-by: Asitha de Silva <[email protected]>
🧹 Deployment RemovedThe deployment for PR #83 has been removed. |
Summary
Implements a complete profile management system allowing users to edit their personal and professional information stored across two Supabase tables (public.users and public.profiles).
🚀 Features Implemented
Core Profile System
Enhanced UX Features
Technical Implementation
🎯 User Benefits
🧪 Testing & Quality
📋 Related Issues
🛠️ Database Schema
Integrates with existing Supabase tables:
✅ Ready for Production
All acceptance criteria met, comprehensive testing completed, and feature ready for user access.
🤖 Generated with Claude Code