Skip to content

Commit 67b6542

Browse files
committed
refactor(account-feature-shell): melhora usabilidade no form de habilidades
1 parent 8d07201 commit 67b6542

18 files changed

+295
-140
lines changed

packages/account/feature-shell/src/lib/containers/account/account.container.html

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
<devmx-account-skills />
1010

1111
<footer>
12-
<button mat-flat-button>Salvar</button>
12+
<button mat-flat-button [disabled]="state()">
13+
{{state() ? state() : 'Salvar'}}
14+
</button>
1315
</footer>
1416
</section>
1517

packages/account/feature-shell/src/lib/containers/account/account.container.ts

+19-4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { SelectFileComponent } from '@devmx/shared-ui-global/image';
22
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
33
import { ProfileComponent } from './profile/profile.component';
44
import { ContactComponent } from './contact/contact.component';
5+
import { debounceTime, filter, skip, take, timer } from 'rxjs';
56
import { SkillsComponent } from './skills/skills.component';
67
import { SocialComponent } from './social/social.component';
78
import { UserPhoto, provideUserPhoto } from '../../dialogs';
@@ -11,7 +12,6 @@ import { UpdatePhoto } from '@devmx/account-data-access';
1112
import { UserComponent } from './user/user.component';
1213
import { ReactiveFormsModule } from '@angular/forms';
1314
import { UserForm } from '../../forms/user';
14-
import { filter, take } from 'rxjs';
1515
import {
1616
inject,
1717
signal,
@@ -24,7 +24,6 @@ import {
2424
AuthenticationFacade,
2525
} from '@devmx/account-data-access';
2626

27-
2827
@Component({
2928
selector: 'devmx-account',
3029
templateUrl: './account.container.html',
@@ -53,6 +52,10 @@ export class AccountContainer {
5352

5453
photo = signal('');
5554

55+
state = signal<string | null>(null);
56+
57+
i = 0;
58+
5659
constructor() {
5760
this.userFacade.selected$
5861
.pipe(
@@ -65,6 +68,8 @@ export class AccountContainer {
6568
}
6669

6770
this.form.patch(user);
71+
72+
console.log((this.i += 1));
6873
});
6974

7075
this.authFacade.auth$
@@ -73,6 +78,10 @@ export class AccountContainer {
7378
takeUntilDestroyed()
7479
)
7580
.subscribe((auth) => this.userFacade.loadOne(auth.id));
81+
82+
this.form.valueChanges
83+
.pipe(takeUntilDestroyed(), debounceTime(4000), skip(1))
84+
.subscribe(() => this.onSubmit());
7685
}
7786

7887
changePhoto(file: File) {
@@ -88,11 +97,17 @@ export class AccountContainer {
8897
}
8998

9099
onSubmit() {
100+
const timer$ = timer(1000).pipe(take(1));
101+
91102
if (this.form.valid) {
92103
const value = this.form.getRawValue() as UpdateUser;
93-
return this.userFacade.update(value);
104+
this.state.set('Salvando...');
105+
this.userFacade.update(value);
106+
107+
return timer$.subscribe(() => this.state.set(null));
94108
}
95109

96-
return this.form.markAllAsTouched();
110+
this.form.markAllAsTouched();
111+
return timer$.subscribe(() => this.state.set(null));
97112
}
98113
}
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,38 @@
1-
<div formArrayName="skills">
2-
<ol class="skill-list" cdkDropList (cdkDropListDropped)="drop($event)">
3-
@for (item of form.skills.controls; track item.value.skill?.id; let index =
4-
$index) {
5-
<li cdkDrag [cdkDragData]="item" [formGroupName]="index">
6-
<devmx-icon name="drag/handle" cdkDragHandle />
7-
8-
<div>
9-
<div>
10-
{{ item.value.skill?.name }}
11-
</div>
12-
13-
<mat-slider
14-
min="0"
15-
max="100"
16-
step="10"
17-
discrete
18-
color="primary"
19-
showTickMarks
20-
[displayWith]="formatLabel"
21-
>
22-
<input matSliderThumb formControlName="weight" />
23-
</mat-slider>
24-
</div>
1+
<mat-accordion
2+
hideToggle
3+
cdkDropList
4+
class="skills-list"
5+
formArrayName="skills"
6+
(cdkDropListDropped)="drop($event)"
7+
>
8+
@for (item of form.skills.controls; track item.value.skill?.id; let index =
9+
$index) {
10+
<mat-expansion-panel
11+
cdkDrag
12+
class="skill-item"
13+
[cdkDragData]="item"
14+
[formGroupName]="index"
15+
>
16+
<mat-expansion-panel-header>
17+
<mat-panel-title> {{ item.value.skill?.name }} </mat-panel-title>
18+
<mat-panel-description> {{ item.value.weight }}% </mat-panel-description>
19+
<devmx-icon name="drag/indicator" cdkDragHandle />
20+
</mat-expansion-panel-header>
2521

26-
<strong> {{ item.value.weight }}% </strong>
27-
</li>
28-
}
29-
</ol>
30-
</div>
22+
<div>
23+
<mat-slider
24+
min="0"
25+
max="100"
26+
step="10"
27+
discrete
28+
showTickMarks
29+
[displayWith]="formatLabel"
30+
>
31+
<input matSliderThumb formControlName="weight" />
32+
</mat-slider>
33+
</div>
34+
</mat-expansion-panel>
35+
}
36+
</mat-accordion>
3137

32-
<mat-form-field>
33-
<mat-label>Adicionar habilidade</mat-label>
34-
<input matInput [formControl]="searchControl" [matAutocomplete]="auto" />
35-
<mat-autocomplete
36-
#auto="matAutocomplete"
37-
[displayWith]="displayFn"
38-
(optionSelected)="onOptionSelected($event.option.value)"
39-
>
40-
@if (skillFacade.response$ | async; as response) { @for (option of
41-
response.data; track option.id) {
42-
<mat-option [value]="option">{{ option.name }}</mat-option>
43-
} }
44-
</mat-autocomplete>
45-
</mat-form-field>
38+
<devmx-search-skill (selected)="onNewSkill($event)" />
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,20 @@
11
:host {
2+
gap: 1em;
23
display: flex;
34
flex-direction: column;
45

5-
.skill-list {
6-
padding: 0;
7-
8-
gap: 1em;
9-
display: flex;
10-
flex-direction: column;
11-
12-
devmx-icon {
13-
cursor: grab;
14-
15-
&:active {
16-
cursor: grabbing;
17-
}
18-
}
19-
20-
li {
21-
gap: 1.2em;
22-
display: flex;
23-
align-items: center;
24-
25-
& > div {
26-
flex: 1;
27-
display: flex;
28-
flex-direction: column;
29-
30-
div {
31-
padding-left: 0.5em;
32-
}
33-
}
34-
}
6+
.cdk-drag-preview {
7+
border: none;
8+
box-sizing: border-box;
359
}
3610

3711
.skills-list {
38-
width: 500px;
39-
max-width: 100%;
40-
overflow: hidden;
41-
42-
43-
li {
44-
min-height: 3em;
45-
box-sizing: border-box;
46-
cursor: move;
12+
div {
13+
display: flex;
14+
flex-direction: column;
4715
}
4816
}
4917

50-
.cdk-drag-preview {
51-
border: none;
52-
box-sizing: border-box;
53-
box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2),
54-
0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12);
55-
}
56-
5718
.cdk-drag-placeholder {
5819
opacity: 0;
5920
}
@@ -62,7 +23,22 @@
6223
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
6324
}
6425

65-
.skills-list.cdk-drop-list-dragging .skills-list li:not(.cdk-drag-placeholder) {
26+
.skills-list.cdk-drop-list-dragging
27+
.skills-list
28+
.skill-item:not(.cdk-drag-placeholder) {
6629
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
6730
}
6831
}
32+
33+
.mat-accordion .mat-expansion-panel:first-of-type {
34+
border-top-right-radius: none;
35+
border-top-left-radius: none;
36+
}
37+
38+
.mat-accordion .mat-expansion-panel:not([class*='mat-elevation-z']) {
39+
box-shadow: none;
40+
}
41+
42+
.mat-accordion .mat-expansion-panel {
43+
background: transparent;
44+
}

packages/account/feature-shell/src/lib/containers/account/skills/skills.component.ts

+10-45
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,16 @@
1-
import { MatAutocompleteModule } from '@angular/material/autocomplete';
1+
import { ControlContainer, ReactiveFormsModule } from '@angular/forms';
22
import { MatProgressBarModule } from '@angular/material/progress-bar';
3+
import { CdkDragDrop, DragDropModule, moveItemInArray } from '@angular/cdk/drag-drop';
34
import { inject, Component, ChangeDetectorRef } from '@angular/core';
4-
import { MatFormFieldModule } from '@angular/material/form-field';
5-
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
5+
import { SearchSkillComponent } from '@devmx/learn-ui-shared';
66
import { MatButtonModule } from '@angular/material/button';
77
import { MatSliderModule } from '@angular/material/slider';
88
import { UserForm, UserSkillForm } from '../../../forms';
9-
import { MatInputModule } from '@angular/material/input';
10-
import { MatListModule } from '@angular/material/list';
119
import { SkillFacade } from '@devmx/learn-data-access';
1210
import { Skill } from '@devmx/shared-api-interfaces';
13-
import { debounceTime, filter } from 'rxjs';
14-
import { AsyncPipe } from '@angular/common';
15-
import {
16-
FormControl,
17-
ControlContainer,
18-
ReactiveFormsModule,
19-
} from '@angular/forms';
11+
import { MatCardModule } from '@angular/material/card';
12+
import { MatExpansionModule } from '@angular/material/expansion';
2013
import { IconComponent } from '@devmx/shared-ui-global/icon';
21-
import {
22-
CdkDragDrop,
23-
DragDropModule,
24-
moveItemInArray,
25-
} from '@angular/cdk/drag-drop';
2614

2715
@Component({
2816
selector: 'devmx-account-skills',
@@ -35,17 +23,15 @@ import {
3523
},
3624
],
3725
imports: [
38-
MatAutocompleteModule,
3926
MatProgressBarModule,
27+
SearchSkillComponent,
4028
ReactiveFormsModule,
41-
MatFormFieldModule,
29+
MatExpansionModule,
4230
MatButtonModule,
43-
MatSliderModule,
4431
DragDropModule,
45-
MatInputModule,
46-
MatListModule,
32+
MatCardModule,
4733
IconComponent,
48-
AsyncPipe,
34+
MatSliderModule,
4935
],
5036
})
5137
export class SkillsComponent {
@@ -59,29 +45,8 @@ export class SkillsComponent {
5945
return this.container.control as UserForm;
6046
}
6147

62-
searchControl = new FormControl<string | Skill>('');
63-
64-
constructor() {
65-
this.searchControl.valueChanges
66-
.pipe(
67-
filter((value) => typeof value === 'string'),
68-
filter((value) => value.length > 1),
69-
takeUntilDestroyed(),
70-
debounceTime(600)
71-
)
72-
.subscribe((name) => {
73-
this.skillFacade.setFilter({ name });
74-
this.skillFacade.load();
75-
});
76-
}
77-
78-
displayFn(skill: Skill) {
79-
return skill && skill.name ? skill.name : '';
80-
}
81-
82-
onOptionSelected(skill: Skill) {
48+
onNewSkill(skill: Skill) {
8349
this.form.skills.add({ skill, weight: 0 });
84-
this.searchControl.setValue('');
8550
}
8651

8752
formatLabel(value: number) {

packages/learn/ui-shared/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
export * from './lib/components';
12
export * from './lib/dialogs';
23
export * from './lib/forms';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './search-skill/search-skill.component';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<mat-form-field>
2+
<mat-label>{{ label() }}</mat-label>
3+
<input matInput [formControl]="control" [matAutocomplete]="auto" />
4+
<mat-autocomplete
5+
#auto="matAutocomplete"
6+
[displayWith]="displayFn"
7+
(optionSelected)="onOptionSelected($event.option.value)"
8+
>
9+
@if (skillFacade.response$ | async; as response) {
10+
<!-- -->
11+
@for (option of response.data; track option.id) {
12+
<mat-option [value]="option">{{ option.name }}</mat-option>
13+
}
14+
<!-- -->
15+
}
16+
</mat-autocomplete>
17+
</mat-form-field>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
:host {
2+
flex: 1;
3+
display: flex;
4+
flex-direction: column;
5+
}

0 commit comments

Comments
 (0)