Skip to content

Commit 56d6a49

Browse files
committed
add skip registration & validators to years & skills trajectory block
1 parent 73431ec commit 56d6a49

21 files changed

Lines changed: 1290 additions & 126 deletions

projects/skills/src/app/profile/home/profile-home.component.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
</div> -->
88
@if (profileData()) {
99
<!-- <app-month-block [months]="profileData()['months']" class="profile__month"></app-month-block> -->
10+
@if(type === 'months') {
1011
<app-month-block [months]="mockMonts" class="profile__month"></app-month-block>
12+
} @else {
13+
<app-trajectory-block class="profile__month"></app-trajectory-block>
14+
}
1115
<app-skills-block class="profile__skills"></app-skills-block>
1216
<app-progress-block></app-progress-block>
1317
}
Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,51 @@
11
/** @format */
22

3-
import { Component, inject } from "@angular/core";
3+
import { Component, inject, OnDestroy, OnInit } from "@angular/core";
44
import { CommonModule } from "@angular/common";
55
import { MonthBlockComponent } from "../shared/month-block/month-block.component";
66
import { SkillsBlockComponent } from "../shared/skills-block/skills-block.component";
77
import { ProgressBlockComponent } from "../shared/progress-block/progress-block.component";
88
import { ActivatedRoute } from "@angular/router";
99
import { toSignal } from "@angular/core/rxjs-interop";
10-
import { map } from "rxjs";
10+
import { map, Subscription } from "rxjs";
1111
import { mockMonthsList } from "projects/core/src/consts/list-mock-months";
12+
import { ProfileService } from "../services/profile.service";
13+
import { TrajectoryBlockComponent } from "../shared/trajectory-block/trajectory-block.component";
1214

1315
@Component({
1416
selector: "app-skills",
1517
standalone: true,
16-
imports: [CommonModule, MonthBlockComponent, SkillsBlockComponent, ProgressBlockComponent],
18+
imports: [
19+
CommonModule,
20+
MonthBlockComponent,
21+
SkillsBlockComponent,
22+
ProgressBlockComponent,
23+
TrajectoryBlockComponent,
24+
],
1725
templateUrl: "./profile-home.component.html",
1826
styleUrl: "./profile-home.component.scss",
1927
})
20-
export class ProfileHomeComponent {
21-
route = inject(ActivatedRoute);
28+
export class ProfileHomeComponent implements OnInit, OnDestroy {
29+
readonly mockMonts = mockMonthsList;
30+
31+
private readonly route = inject(ActivatedRoute);
32+
private readonly profileService = inject(ProfileService);
2233

2334
profileData = toSignal(this.route.data.pipe(map(r => r["data"])));
2435

25-
readonly mockMonts = mockMonthsList;
36+
type: "months" | "trajectory" = "months";
37+
38+
subscription$: Subscription[] = [];
39+
40+
ngOnInit(): void {
41+
const isSubscribedSub$ = this.profileService.getSubscriptionData().subscribe(r => {
42+
this.type = r.isSubscribed ? "trajectory" : "months";
43+
});
44+
45+
isSubscribedSub$ && this.subscription$.push(isSubscribedSub$);
46+
}
47+
48+
ngOnDestroy(): void {
49+
this.subscription$.forEach($ => $.unsubscribe());
50+
}
2651
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<!-- @format -->
2+
3+
<div class="trajectory">
4+
<img
5+
alt="trajectory image"
6+
src="/assets/images/profile/trajectory.png"
7+
class="trajectory__image"
8+
/>
9+
<app-button (click)="navigateToTrajectory()" customTypographyClass="text-body-12"
10+
>Запустить</app-button
11+
>
12+
</div>
13+
14+
<app-modal [open]="isErrorTrajectoryModalOpen" (openChange)="onOpenErorTrajectoryModalChange()">
15+
<div class="cancel">
16+
<i (click)="isErrorTrajectoryModalOpen = false" appIcon icon="cross" class="cancel__cross"></i>
17+
18+
<p class="cancel__title">У вас нет активной траектории!</p>
19+
<p class="text-body-14 cancel__text">Выберите нужную вам траекторию!</p>
20+
<app-button customTypographyClass="text-body-12" (click)="isErrorTrajectoryModalOpen = false"
21+
>Ок</app-button
22+
>
23+
</div>
24+
</app-modal>
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
@use "styles/typography";
2+
@use "styles/responsive";
3+
4+
.trajectory {
5+
position: relative;
6+
width: 100%;
7+
height: 130px;
8+
overflow: hidden;
9+
white-space: nowrap;
10+
border-radius: 15px;
11+
transition: ease 0.3s;
12+
cursor: pointer;
13+
// padding: 50px 50px 50px 18px;
14+
// background-color: var(--white);
15+
16+
&:hover {
17+
box-shadow: 0 0 6px var(--gray);
18+
}
19+
20+
@include responsive.apply-desktop {
21+
height: 100px;
22+
}
23+
24+
&__image {
25+
height: 100%;
26+
object-fit: cover;
27+
28+
@include responsive.apply-desktop {
29+
width: 100%;
30+
height: auto;
31+
object-fit: fill;
32+
}
33+
}
34+
35+
::ng-deep {
36+
app-button {
37+
position: absolute;
38+
width: 30%;
39+
top: 17%;
40+
right: 0%;
41+
42+
@include responsive.apply-desktop {
43+
top: 30%;
44+
right: 3%;
45+
width: 20%;
46+
}
47+
}
48+
}
49+
}
50+
51+
.cancel {
52+
display: flex;
53+
flex-direction: column;
54+
align-items: center;
55+
justify-content: center;
56+
max-height: calc(100vh - 40px);
57+
padding: 20px 0 50px;
58+
overflow-y: auto;
59+
60+
@include responsive.apply-desktop {
61+
padding: 20px 0 60px;
62+
}
63+
64+
&__cross {
65+
position: absolute;
66+
top: 0;
67+
right: 0;
68+
width: 32px;
69+
height: 32px;
70+
cursor: pointer;
71+
72+
@include responsive.apply-desktop {
73+
top: 8px;
74+
right: 8px;
75+
}
76+
}
77+
78+
&__title {
79+
margin-top: 10px;
80+
margin-bottom: 5px;
81+
color: var(--black);
82+
text-align: center;
83+
inline-size: 280px;
84+
85+
@include typography.heading-3;
86+
87+
@include responsive.apply-desktop {
88+
inline-size: 500px;
89+
}
90+
}
91+
92+
&__text {
93+
margin-bottom: 24px;
94+
color: var(--grey-for-text);
95+
}
96+
97+
app-button {
98+
width: 70%;
99+
100+
@include responsive.apply-desktop {
101+
width: 40%;
102+
}
103+
}
104+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/** @format */
2+
3+
import { ComponentFixture, TestBed } from "@angular/core/testing";
4+
5+
import { TrajectoryBlockComponent } from "./trajectory-block.component";
6+
7+
describe("TrajectoryBlockComponent", () => {
8+
let component: TrajectoryBlockComponent;
9+
let fixture: ComponentFixture<TrajectoryBlockComponent>;
10+
11+
beforeEach(async () => {
12+
await TestBed.configureTestingModule({
13+
imports: [TrajectoryBlockComponent],
14+
}).compileComponents();
15+
16+
fixture = TestBed.createComponent(TrajectoryBlockComponent);
17+
component = fixture.componentInstance;
18+
fixture.detectChanges();
19+
});
20+
21+
it("should create", () => {
22+
expect(component).toBeTruthy();
23+
});
24+
});
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/** @format */
2+
3+
import { Component, inject } from "@angular/core";
4+
import { CommonModule } from "@angular/common";
5+
import { ButtonComponent } from "@ui/components";
6+
import { IconComponent } from "@uilib";
7+
import { Router } from "@angular/router";
8+
import { HttpErrorResponse } from "@angular/common/http";
9+
import { ModalComponent } from "@ui/components/modal/modal.component";
10+
11+
@Component({
12+
selector: "app-trajectory-block",
13+
standalone: true,
14+
imports: [CommonModule, ButtonComponent, IconComponent, ModalComponent],
15+
templateUrl: "./trajectory-block.component.html",
16+
styleUrl: "./trajectory-block.component.scss",
17+
})
18+
export class TrajectoryBlockComponent {
19+
private readonly router = inject(Router);
20+
21+
isErrorTrajectoryModalOpen = false;
22+
23+
onOpenErorTrajectoryModalChange = (): void => {
24+
this.isErrorTrajectoryModalOpen = !this.isErrorTrajectoryModalOpen;
25+
};
26+
27+
navigateToTrajectory = (): void => {
28+
this.router.navigateByUrl("/trackCar/1").catch(err => {
29+
if (err instanceof HttpErrorResponse) {
30+
if (err.status === 404) {
31+
this.isErrorTrajectoryModalOpen = true;
32+
}
33+
}
34+
});
35+
};
36+
}
25.5 KB
Loading

projects/social_platform/src/app/office/onboarding/stage-one/stage-one.component.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ <h4 class="text-heading-4 content__section-heading content__right-heading">Би
4545
</div>
4646
</section>
4747
<div class="content__actions">
48+
<app-button (click)="onSkipRegistration()" color="grey" [loader]="skipSubmitting()"
49+
>Закончить регистрацию позже</app-button
50+
>
4851
<app-button type="submit" [loader]="stageSubmitting()" (click)="onSubmit()"
4952
>Продолжить</app-button
5053
>

projects/social_platform/src/app/office/onboarding/stage-one/stage-one.component.scss

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,21 @@
4848
grid-column: 1/2;
4949
order: 3;
5050
margin-top: auto;
51+
display: flex;
52+
flex-direction: column;
53+
gap: 20px;
54+
55+
@include responsive.apply-desktop {
56+
flex-direction: row;
57+
58+
:first-child {
59+
width: 100%;
60+
}
61+
62+
:last-child {
63+
width: 60%;
64+
}
65+
}
5166
}
5267

5368
&__specs-groups {

projects/social_platform/src/app/office/onboarding/stage-one/stage-one.component.ts

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/** @format */
22

3-
import { Component, OnDestroy, OnInit, signal } from "@angular/core";
3+
import { ChangeDetectorRef, Component, OnDestroy, OnInit, signal } from "@angular/core";
44
import { NonNullableFormBuilder, ReactiveFormsModule, Validators } from "@angular/forms";
5-
import { map, Observable, Subscription, take } from "rxjs";
5+
import { concatMap, map, Observable, Subscription, take } from "rxjs";
66
import { AuthService } from "@auth/services";
77
import { ControlErrorPipe, ValidationService } from "@corelib";
88
import { ActivatedRoute, Router } from "@angular/router";
@@ -43,11 +43,12 @@ export class OnboardingStageOneComponent implements OnInit, OnDestroy {
4343
private readonly validationService: ValidationService,
4444
private readonly specsService: SpecializationsService,
4545
private readonly router: Router,
46-
private readonly route: ActivatedRoute
46+
private readonly route: ActivatedRoute,
47+
private readonly cdref: ChangeDetectorRef
4748
) {}
4849

4950
stageForm = this.nnFb.group({
50-
speciality: ["", Validators.required],
51+
speciality: [""],
5152
});
5253

5354
nestedSpecializations$: Observable<SpecializationsGroup[]> = this.route.data.pipe(
@@ -57,6 +58,7 @@ export class OnboardingStageOneComponent implements OnInit, OnDestroy {
5758
inlineSpecializations = signal<Specialization[]>([]);
5859

5960
stageSubmitting = signal(false);
61+
skipSubmitting = signal(false);
6062

6163
errorMessage = ErrorMessage;
6264

@@ -76,22 +78,42 @@ export class OnboardingStageOneComponent implements OnInit, OnDestroy {
7678
this.subscriptions$().push(formValueState$, formValueChange$);
7779
}
7880

81+
ngAfterViewInit(): void {
82+
const specialityProfile$ = this.onboardingService.formValue$.subscribe(fv => {
83+
this.stageForm.patchValue({ speciality: fv.speciality });
84+
});
85+
86+
this.cdref.detectChanges();
87+
88+
specialityProfile$ && this.subscriptions$().push(specialityProfile$);
89+
}
90+
7991
ngOnDestroy(): void {
8092
this.subscriptions$().forEach($ => $.unsubscribe());
8193
}
8294

95+
onSkipRegistration(): void {
96+
if (!this.validationService.getFormValidation(this.stageForm)) {
97+
return;
98+
}
99+
100+
this.completeRegistration(null);
101+
}
102+
83103
onSubmit(): void {
84104
if (!this.validationService.getFormValidation(this.stageForm)) {
85105
return;
86106
}
87107

88108
this.stageSubmitting.set(true);
89109

90-
this.authService.saveProfile(this.stageForm.value).subscribe(() => {
91-
this.router
92-
.navigateByUrl("/office/onboarding/stage-2")
93-
.then(() => console.debug("Route changed from OnboardingStageOneComponent"));
94-
});
110+
this.authService
111+
.saveProfile(this.stageForm.value)
112+
.pipe(concatMap(() => this.authService.setOnboardingStage(2)))
113+
.subscribe({
114+
next: () => this.completeRegistration(2),
115+
error: () => this.stageSubmitting.set(false),
116+
});
95117
}
96118

97119
onSelectSpec(speciality: Specialization): void {
@@ -106,4 +128,13 @@ export class OnboardingStageOneComponent implements OnInit, OnDestroy {
106128
this.inlineSpecializations.set(results);
107129
});
108130
}
131+
132+
private completeRegistration(stage: number | null): void {
133+
this.skipSubmitting.set(true);
134+
this.onboardingService.setFormValue(this.stageForm.value);
135+
this.authService.setOnboardingStage(stage).subscribe(() => {
136+
this.router.navigateByUrl(stage !== null ? "/office/onboarding/stage-2" : "/office/feed");
137+
});
138+
this.skipSubmitting.set(false);
139+
}
109140
}

0 commit comments

Comments
 (0)