diff --git a/angular.json b/angular.json index ceb7cd7ca..224dedd50 100644 --- a/angular.json +++ b/angular.json @@ -30,7 +30,8 @@ ], "styles": [ "src/assets/styles/styles.scss", - "src/assets/icons/dist/icons.css" + "src/assets/icons/dist/icons.css", + "node_modules/primeflex/primeflex.css" ], "stylePreprocessorOptions": { "includePaths": ["src"] diff --git a/bun.lock b/bun.lock index 4c2a9f92c..d5d1ef93a 100644 --- a/bun.lock +++ b/bun.lock @@ -16,6 +16,7 @@ "@ngxs/logger-plugin": "^19.0.0", "@ngxs/store": "^19.0.0", "@primeng/themes": "^19.0.9", + "primeflex": "^4.0.0", "primeng": "^19.0.9", "rxjs": "~7.8.0", "tslib": "^2.3.0", @@ -1665,6 +1666,8 @@ "prettier": ["prettier@3.5.2", "", { "bin": "bin/prettier.cjs" }, "sha512-lc6npv5PH7hVqozBR7lkBNOGXV9vMwROAPlumdBkX0wTbbzPu/U1hk5yL8p2pt4Xoc+2mkT8t/sow2YrV/M5qg=="], + "primeflex": ["primeflex@4.0.0", "", {}, "sha512-UOEZCRjR36+sm5bUpDhS1xbA068l9VC6y1aTNVqQPtXuKIdPTqAWHRUxj3mKAoPrQ9W373ooJJMgNVXfiaw04g=="], + "primeng": ["primeng@19.0.9", "", { "dependencies": { "@primeuix/styled": "^0.3.2", "@primeuix/utils": "^0.3.2", "tslib": "^2.3.0" }, "peerDependencies": { "@angular/animations": "^19.0.0", "@angular/cdk": "^19.0.0", "@angular/common": "^19.0.0", "@angular/core": "^19.0.0", "@angular/forms": "^19.0.0", "@angular/platform-browser": "^19.0.0", "@angular/router": "^19.0.0", "rxjs": "^6.0.0 || ^7.8.1" } }, "sha512-Y994f4JDsdjwe1uK1J8Gvq94Mk2qQfV+M1zdW+XClXHK8EXzZp7kvBzfrlk607valJmUhLr/5DxSkVfVQGZhxA=="], "proc-log": ["proc-log@5.0.0", "", {}, "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ=="], diff --git a/package.json b/package.json index bf372b752..6de527dff 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "@ngxs/logger-plugin": "^19.0.0", "@ngxs/store": "^19.0.0", "@primeng/themes": "^19.0.9", + "primeflex": "^4.0.0", "primeng": "^19.0.9", "rxjs": "~7.8.0", "tslib": "^2.3.0", diff --git a/src/app/core/components/breadcrumb/breadcrumb.component.scss b/src/app/core/components/breadcrumb/breadcrumb.component.scss index e69de29bb..c6e2905dd 100644 --- a/src/app/core/components/breadcrumb/breadcrumb.component.scss +++ b/src/app/core/components/breadcrumb/breadcrumb.component.scss @@ -0,0 +1,7 @@ +@use "assets/styles/variables" as var; + +.breadcrumbs { + text-transform: capitalize; + color: var.$dark-blue-1; + font-weight: 600; +} diff --git a/src/app/features/settings/account-settings/account-settings.component.html b/src/app/features/settings/account-settings/account-settings.component.html index 17efe8421..0cc076f96 100644 --- a/src/app/features/settings/account-settings/account-settings.component.html +++ b/src/app/features/settings/account-settings/account-settings.component.html @@ -1 +1,226 @@ -

account-settings works!

+
+ +

Account settings

+
+ +
+
+ + + + + + + +
+ +
+ + + + + + + +
+ +
+ + + + + +
+ +
+ + + + + +
+ +
+ + + + + + + +
+ +
+ + +
+
+ + + Enter your username to reset your password. +
+ +
+
+ + + Enter your username to reset your password. +
+ +
+ + + Enter your username to reset your password. +
+
+
+
+ +
+ + + + + +
+ +
+ + + + Warning: This action cannot be undone once approved. + + + + + +
+
diff --git a/src/app/features/settings/account-settings/account-settings.component.scss b/src/app/features/settings/account-settings/account-settings.component.scss index e69de29bb..9c670a463 100644 --- a/src/app/features/settings/account-settings/account-settings.component.scss +++ b/src/app/features/settings/account-settings/account-settings.component.scss @@ -0,0 +1,105 @@ +@use "assets/styles/mixins" as mix; +@use "assets/styles/variables" as var; + +:host { + display: flex; + flex-direction: column; + flex: 1; + gap: 1.7rem; + color: var(--dark-blue-1); + + .header { + display: flex; + flex: 1; + padding: 7.14rem 1.71rem 3.43rem 1.71rem; + background: var(--gradient-1); + + h1 { + margin-left: 0.85rem; + } + + p-button { + margin-left: auto; + } + + i { + color: var(--dark-blue-1); + font-size: 2.6rem; + } + } + + .content { + display: flex; + flex-direction: column; + gap: 1.7rem; + padding: 1.7rem; + background: var.$white; + } + + .account-setting { + border: 1px solid var.$grey-2; + padding: 1.7rem; + display: flex; + flex-direction: column; + gap: 1.7rem; + border-radius: 0.5rem; + + &-link { + font-weight: 600; + } + + &-radio-group { + display: flex; + flex: 1; + gap: 4rem; + } + + &-radio-item { + display: flex; + align-items: center; + gap: 0.5rem; + } + + &-content { + display: flex; + } + + &-description { + line-height: 2rem; + } + + &-action { + display: flex; + justify-content: flex-end; + } + + &-emails { + display: flex; + flex-direction: column; + gap: 1.7rem; + } + + &-select { + width: 50%; + } + + &-email { + display: flex; + gap: 2rem; + align-items: center; + + &--readonly { + display: flex; + align-items: center; + border: 1px solid var.$grey-2; + padding: 0.285rem 0.85rem; + border-radius: 0.285rem; + } + + &__value { + display: flex; + gap: 0.428rem; + } + } + } +} diff --git a/src/app/features/settings/account-settings/account-settings.component.ts b/src/app/features/settings/account-settings/account-settings.component.ts index 3d790183e..6c22e0822 100644 --- a/src/app/features/settings/account-settings/account-settings.component.ts +++ b/src/app/features/settings/account-settings/account-settings.component.ts @@ -1,9 +1,72 @@ -import { Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { Button } from 'primeng/button'; +import { Select } from 'primeng/select'; +import { MOCK_COUNTRIES } from '@osf/features/settings/account-settings/account-settings.const'; +import { RadioButton } from 'primeng/radiobutton'; +import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { + AccountSettingsPasswordForm, + AccountSettingsPasswordFormControls, +} from '@osf/features/settings/account-settings/account.settings.entities'; +import { InputText } from 'primeng/inputtext'; +import { Message } from 'primeng/message'; +import { DialogService, DynamicDialogRef } from 'primeng/dynamicdialog'; +import { AddEmailComponent } from '@osf/features/settings/account-settings/add-email/add-email.component'; +import { DeactivateAccountComponent } from '@osf/features/settings/account-settings/deactivate-account/deactivate-account/deactivate-account.component'; @Component({ selector: 'osf-account-settings', - imports: [], + imports: [ + Button, + Select, + RadioButton, + ReactiveFormsModule, + InputText, + Message, + ], + providers: [DialogService], templateUrl: './account-settings.component.html', styleUrl: './account-settings.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, }) -export class AccountSettingsComponent {} +export class AccountSettingsComponent { + readonly passwordForm: AccountSettingsPasswordForm = new FormGroup({ + [AccountSettingsPasswordFormControls.OldPassword]: new FormControl('', { + nonNullable: true, + }), + [AccountSettingsPasswordFormControls.NewPassword]: new FormControl('', { + nonNullable: true, + }), + [AccountSettingsPasswordFormControls.ConfirmPassword]: new FormControl('', { + nonNullable: true, + }), + }); + protected readonly optControl = new FormControl(false); + protected readonly MOCK_COUNTRIES = MOCK_COUNTRIES; + protected readonly AccountSettingsPasswordFormControls = + AccountSettingsPasswordFormControls; + private readonly dialogService = inject(DialogService); + private dialogRef: DynamicDialogRef | null = null; + + addEmail() { + this.dialogRef = this.dialogService.open(AddEmailComponent, { + width: '448px', + focusOnShow: false, + header: 'Add alternative email', + closeOnEscape: true, + modal: true, + closable: true, + }); + } + + deactivateAccount() { + this.dialogRef = this.dialogService.open(DeactivateAccountComponent, { + width: '448px', + focusOnShow: false, + header: 'Deactivate account', + closeOnEscape: true, + modal: true, + closable: true, + }); + } +} diff --git a/src/app/features/settings/account-settings/account-settings.const.ts b/src/app/features/settings/account-settings/account-settings.const.ts new file mode 100644 index 000000000..658c0efd8 --- /dev/null +++ b/src/app/features/settings/account-settings/account-settings.const.ts @@ -0,0 +1,15 @@ +export interface Country { + name: string; + code: string; +} + +export const MOCK_COUNTRIES: Country[] = [ + { + name: 'United States', + code: 'US', + }, + { + name: 'Canada', + code: 'CA', + }, +]; diff --git a/src/app/features/settings/account-settings/account.settings.entities.ts b/src/app/features/settings/account-settings/account.settings.entities.ts new file mode 100644 index 000000000..6d1776a9a --- /dev/null +++ b/src/app/features/settings/account-settings/account.settings.entities.ts @@ -0,0 +1,13 @@ +import { FormControl, FormGroup } from '@angular/forms'; + +export enum AccountSettingsPasswordFormControls { + OldPassword = 'oldPassword', + NewPassword = 'newPassword', + ConfirmPassword = 'confirmPassword', +} + +export type AccountSettingsPasswordForm = FormGroup<{ + [AccountSettingsPasswordFormControls.OldPassword]: FormControl; + [AccountSettingsPasswordFormControls.NewPassword]: FormControl; + [AccountSettingsPasswordFormControls.ConfirmPassword]: FormControl; +}>; diff --git a/src/app/features/settings/account-settings/add-email/add-email.component.html b/src/app/features/settings/account-settings/add-email/add-email.component.html new file mode 100644 index 000000000..ffa64fc01 --- /dev/null +++ b/src/app/features/settings/account-settings/add-email/add-email.component.html @@ -0,0 +1,32 @@ +
+
+ + +
+ +
+ + Cancel + + + + Add Email + +
+
diff --git a/src/app/features/settings/account-settings/add-email/add-email.component.scss b/src/app/features/settings/account-settings/add-email/add-email.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/features/settings/account-settings/add-email/add-email.component.spec.ts b/src/app/features/settings/account-settings/add-email/add-email.component.spec.ts new file mode 100644 index 000000000..b5c9107f1 --- /dev/null +++ b/src/app/features/settings/account-settings/add-email/add-email.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AddEmailComponent } from './add-email.component'; + +describe('AddEmailComponent', () => { + let component: AddEmailComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [AddEmailComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(AddEmailComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/features/settings/account-settings/add-email/add-email.component.ts b/src/app/features/settings/account-settings/add-email/add-email.component.ts new file mode 100644 index 000000000..1ad25252e --- /dev/null +++ b/src/app/features/settings/account-settings/add-email/add-email.component.ts @@ -0,0 +1,21 @@ +import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { DynamicDialogRef } from 'primeng/dynamicdialog'; +import { FormControl, ReactiveFormsModule, Validators } from '@angular/forms'; +import { InputText } from 'primeng/inputtext'; +import { Button } from 'primeng/button'; + +@Component({ + selector: 'osf-add-email', + imports: [InputText, ReactiveFormsModule, Button], + templateUrl: './add-email.component.html', + styleUrl: './add-email.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class AddEmailComponent { + readonly dialogRef = inject(DynamicDialogRef); + + protected readonly emailControl = new FormControl('', [ + Validators.email, + Validators.required, + ]); +} diff --git a/src/app/features/settings/account-settings/deactivate-account/deactivate-account/deactivate-account.component.html b/src/app/features/settings/account-settings/deactivate-account/deactivate-account/deactivate-account.component.html new file mode 100644 index 000000000..0a7fc0f86 --- /dev/null +++ b/src/app/features/settings/account-settings/deactivate-account/deactivate-account/deactivate-account.component.html @@ -0,0 +1,18 @@ +
+

Are you sure you want to to deactivate your account?

+ +
+ + + + + Deactivate + +
+
diff --git a/src/app/features/settings/account-settings/deactivate-account/deactivate-account/deactivate-account.component.scss b/src/app/features/settings/account-settings/deactivate-account/deactivate-account/deactivate-account.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/features/settings/account-settings/deactivate-account/deactivate-account/deactivate-account.component.spec.ts b/src/app/features/settings/account-settings/deactivate-account/deactivate-account/deactivate-account.component.spec.ts new file mode 100644 index 000000000..db873e009 --- /dev/null +++ b/src/app/features/settings/account-settings/deactivate-account/deactivate-account/deactivate-account.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DeactivateAccountComponent } from './deactivate-account.component'; + +describe('DeactivateAccountComponent', () => { + let component: DeactivateAccountComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [DeactivateAccountComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(DeactivateAccountComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/features/settings/account-settings/deactivate-account/deactivate-account/deactivate-account.component.ts b/src/app/features/settings/account-settings/deactivate-account/deactivate-account/deactivate-account.component.ts new file mode 100644 index 000000000..63461a312 --- /dev/null +++ b/src/app/features/settings/account-settings/deactivate-account/deactivate-account/deactivate-account.component.ts @@ -0,0 +1,11 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { Button } from 'primeng/button'; + +@Component({ + selector: 'osf-deactivate-account', + imports: [Button], + templateUrl: './deactivate-account.component.html', + styleUrl: './deactivate-account.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class DeactivateAccountComponent {}