Skip to content

Commit 4e40316

Browse files
committed
change design of modal for submit project & add logic for submit project to program
1 parent 4da8bac commit 4e40316

15 files changed

Lines changed: 167 additions & 279 deletions

File tree

projects/social_platform/src/app/office/program/detail/main/main.component.html

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -237,35 +237,28 @@ <h3 class="links__title text-body-12">материалы</h3>
237237
<div class="cancel" style="width: 500px; padding: 40px 0px 40px">
238238
<div class="cancel__top">
239239
<i appIcon icon="cross" class="cancel__cross" (click)="closeModal()"></i>
240-
<p class="cancel__title text-bold-body-16">
241-
Вы не являетесь экспертом или организатором программы!
240+
<p class="cancel__title text-body-14">
241+
вы не являетесь экспертом или организатором программы!
242242
</p>
243243
</div>
244244

245245
@if (showProgramModalErrorMessage()) {
246-
<p class="text-body-12 cancel__text">
246+
<p class="text-body-10 cancel__text">
247247
{{ showProgramModalErrorMessage() }}
248248
</p>
249249
}
250250

251251
<app-button class="cancel__button" (click)="closeModal()" customTypographyClass="text-body-12"
252-
>Хорошо</app-button
252+
>хорошо</app-button
253253
>
254254
</div>
255255
</app-modal>
256256

257257
<app-modal [open]="showSubmitProjectModal()" (openChange)="toggleSubmitProjectModal()">
258258
<div class="cancel">
259259
<div class="cancel__top">
260-
<i
261-
(click)="toggleSubmitProjectModal()"
262-
appIcon
263-
appSquare="24"
264-
icon="cross"
265-
class="cancel__cross"
266-
></i>
267260
<p class="cancel__title text-body-14">выберите проект для подачи</p>
268-
<p class="cancel__text text-body-10" style="width: 41%">
261+
<p class="cancel__text text-body-10">
269262
после выбора проекта будет создан дубликат данного проекта для заполнения под конкретный
270263
конкурс
271264
</p>
@@ -282,7 +275,6 @@ <h3 class="links__title text-body-12">материалы</h3>
282275
</div>
283276
<app-input
284277
type="radio"
285-
name="goalLeaderSelection"
286278
[appValue]="project.id.toLocaleString()"
287279
[checked]="selectedProjectId === project.id"
288280
(change)="onProjectRadioChange($event)"
@@ -304,4 +296,53 @@ <h3 class="links__title text-body-12">материалы</h3>
304296
</app-button>
305297
</div>
306298
</app-modal>
299+
300+
<app-modal
301+
[open]="isAssignProjectToProgramError"
302+
(openChange)="isAssignProjectToProgramError ? clearAssignProjectToProgramError() : null"
303+
>
304+
<div class="cancel" style="padding: 24px">
305+
<div class="cancel__top">
306+
<p class="cancel__title text-body-14">ошибка привязки проекта к программе!</p>
307+
</div>
308+
309+
<p class="text-body-10 cancel__text">
310+
{{ (errorAssignProjectToProgramModalMessage()?.non_field_errors)![0] }}
311+
</p>
312+
313+
<app-button
314+
size="medium"
315+
class="cancel__button"
316+
customTypographyClass="text-body-12"
317+
(click)="clearAssignProjectToProgramError()"
318+
>понятно</app-button
319+
>
320+
</div>
321+
</app-modal>
322+
323+
<app-modal
324+
[open]="isAssignProjectToProgramModalOpen()"
325+
(openChange)="isAssignProjectToProgramModalOpen.set(!isAssignProjectToProgramModalOpen)"
326+
>
327+
<div class="cancel" style="padding: 24px">
328+
<div class="cancel__top">
329+
<p class="cancel__title text-body-14">поздравляем!</p>
330+
</div>
331+
332+
<p class="text-body-10 cancel__text">
333+
мы создали дубликат проекта, который вы привязали к выбранной программе
334+
<span
335+
><strong>{{ assignProjectToProgramModalMessage()?.partnerProgram }}</strong></span
336+
>, теперь его можно отредактировать!
337+
</p>
338+
339+
<app-button
340+
size="medium"
341+
class="cancel__button"
342+
customTypographyClass="text-body-12"
343+
(click)="closeAssignProjectToProgramModal()"
344+
>вперед</app-button
345+
>
346+
</div>
347+
</app-modal>
307348
}

projects/social_platform/src/app/office/program/detail/main/main.component.scss

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@
8686
}
8787

8888
.project {
89-
margin-top: 40px;
9089

9190
&__list {
9291
display: flex;
@@ -107,6 +106,7 @@
107106
align-items: center;
108107
justify-content: space-between;
109108
width: 300px;
109+
margin-left: 40px;
110110
margin-bottom: 12px;
111111

112112
&--info {
@@ -375,18 +375,6 @@
375375
max-height: calc(100vh - 40px);
376376
padding: 24px 54px;
377377

378-
&__cross {
379-
position: absolute;
380-
top: 0;
381-
right: 0;
382-
cursor: pointer;
383-
384-
@include responsive.apply-desktop {
385-
top: 8px;
386-
right: 8px;
387-
}
388-
}
389-
390378
&__top {
391379
display: flex;
392380
flex-direction: column;
@@ -401,6 +389,8 @@
401389

402390
&__text {
403391
text-align: center;
392+
color: var(--dark-grey);
393+
width: 40%;
404394
}
405395

406396
&__button {

projects/social_platform/src/app/office/program/detail/main/main.component.ts

Lines changed: 66 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ import { MatProgressBarModule } from "@angular/material/progress-bar";
3939
import { AsyncPipe } from "@angular/common";
4040
import { LoadingService } from "@office/services/loading.service";
4141
import { Project } from "@office/models/project.model";
42+
import { HttpErrorResponse } from "@angular/common/http";
43+
import { ProjectAssign } from "@office/projects/models/project-assign.model";
44+
import { ProjectAdditionalService } from "@office/projects/edit/services/project-additional.service";
4245

4346
@Component({
4447
selector: "app-main",
@@ -67,23 +70,46 @@ export class ProgramDetailMainComponent implements OnInit, OnDestroy {
6770
private readonly programService: ProgramService,
6871
private readonly programNewsService: ProgramNewsService,
6972
private readonly projectService: ProjectService,
73+
private readonly projectAdditionalService: ProjectAdditionalService,
7074
private readonly router: Router,
7175
private readonly route: ActivatedRoute,
7276
private readonly cdRef: ChangeDetectorRef,
7377
private readonly loadingService: LoadingService
7478
) {}
7579

80+
get isAssignProjectToProgramError() {
81+
return this.projectAdditionalService.getIsAssignProjectToProgramError()();
82+
}
83+
84+
get errorAssignProjectToProgramModalMessage() {
85+
return this.projectAdditionalService.getErrorAssignProjectToProgramModalMessage();
86+
}
87+
7688
news = signal<FeedNews[]>([]);
7789
totalNewsCount = signal(0);
7890
fetchLimit = signal(10);
7991
fetchPage = signal(0);
8092

93+
// Сигналы для работы с модальными окнами с текстом
8194
showProgramModal = signal(false);
8295
showProgramModalErrorMessage = signal<string | null>(null);
96+
assignProjectToProgramModalMessage = signal<ProjectAssign | null>(null);
8397

98+
// Сигналы для управления состоянием
8499
showSubmitProjectModal = signal(false);
100+
isAssignProjectToProgramModalOpen = signal(false);
101+
102+
// Методы для управления состоянием ошибок через сервис
103+
setAssignProjectToProgramError(error: { non_field_errors: string[] }): void {
104+
this.projectAdditionalService.setAssignProjectToProgramError(error);
105+
}
106+
107+
clearAssignProjectToProgramError(): void {
108+
this.projectAdditionalService.clearAssignProjectToProgramError();
109+
}
85110

86111
selectedProjectId = 0;
112+
dubplicatedProjectId = 0;
87113

88114
programId?: number;
89115

@@ -150,7 +176,7 @@ export class ProgramDetailMainComponent implements OnInit, OnDestroy {
150176

151177
const memeberProjects$ = this.projectService.getMy().subscribe({
152178
next: projects => {
153-
this.memberProjects = projects.results;
179+
this.memberProjects = projects.results.filter(project => !project.draft);
154180
},
155181
});
156182

@@ -276,6 +302,18 @@ export class ProgramDetailMainComponent implements OnInit, OnDestroy {
276302
}
277303
}
278304

305+
/**
306+
* Обработчик изменения радио-кнопки для выбора проекта
307+
*/
308+
onProjectRadioChange(event: Event): void {
309+
const target = event.target as HTMLInputElement;
310+
this.selectedProjectId = +target.value;
311+
312+
if (this.selectedProjectId) {
313+
this.memberProjects.find(project => project.id === this.selectedProjectId);
314+
}
315+
}
316+
279317
/**
280318
* Добавление проекта на программу
281319
*/
@@ -288,53 +326,41 @@ export class ProgramDetailMainComponent implements OnInit, OnDestroy {
288326
project => project.id === this.selectedProjectId
289327
);
290328

291-
console.log("Submitting project:", {
292-
projectId: this.selectedProjectId,
293-
projectName: selectedProject?.name,
294-
programId: this.programId,
295-
});
296-
297-
this.toggleSubmitProjectModal();
298-
this.selectedProjectId = 0;
329+
this.assignProjectToProgram(selectedProject!);
299330
}
300331

332+
/** Эмитим логику для привязки проекта к программе */
301333
/**
302-
* Обработчик изменения радио-кнопки для выбора проекта
334+
* Привязка проекта к программе выбранной
335+
* Перенаправление её на редактирование "нового" проекта
303336
*/
304-
onProjectRadioChange(event: Event): void {
305-
const target = event.target as HTMLInputElement;
306-
this.selectedProjectId = +target.value;
307-
308-
if (this.selectedProjectId) {
309-
const selectedProject = this.memberProjects.find(
310-
project => project.id === this.selectedProjectId
311-
);
337+
assignProjectToProgram(project: Project): void {
338+
if (this.programId) {
339+
this.projectService.assignProjectToProgram(project.id, this.programId).subscribe({
340+
next: r => {
341+
this.dubplicatedProjectId = r.newProjectId;
342+
this.assignProjectToProgramModalMessage.set(r);
343+
this.isAssignProjectToProgramModalOpen.set(true);
344+
this.toggleSubmitProjectModal();
345+
this.selectedProjectId = 0;
346+
},
312347

313-
console.log("Selected Project ID:", this.selectedProjectId);
314-
console.log("Selected Project Info:", selectedProject);
348+
error: err => {
349+
if (err instanceof HttpErrorResponse) {
350+
if (err.status === 400) {
351+
this.setAssignProjectToProgramError(err.error);
352+
}
353+
}
354+
},
355+
});
315356
}
316357
}
317358

318-
addProject(): void {
319-
this.loadingService.show();
320-
321-
this.projectService.create().subscribe({
322-
next: project => {
323-
this.projectService.projectsCount.next({
324-
...this.projectService.projectsCount.getValue(),
325-
my: this.projectService.projectsCount.getValue().my + 1,
326-
});
327-
this.router
328-
.navigateByUrl(`/office/projects/${project.id}/edit?editingStep=main`)
329-
.then(() => {
330-
console.debug("Route change from ProjectsComponent");
331-
});
332-
},
333-
error: error => {
334-
this.loadingService.hide();
335-
console.error("Project creation error:", error);
336-
},
337-
});
359+
closeAssignProjectToProgramModal(): void {
360+
this.isAssignProjectToProgramModalOpen.set(false);
361+
this.router.navigateByUrl(
362+
`/office/projects/${this.dubplicatedProjectId}/edit?editingStep=main`
363+
);
338364
}
339365

340366
onOpenDetailProgram(): void {

projects/social_platform/src/app/office/program/services/program.service.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,4 @@ export class ProgramService {
109109
{}
110110
);
111111
}
112-
113-
programTags$ = new BehaviorSubject<ProgramTag[]>([]);
114-
programTags(): Observable<ProgramTag[]> {
115-
return this.apiService.get<ProgramTag[]>(`${this.AUTH_USERS_CURRENT_URL}/programs/tags/`).pipe(
116-
tap(programs => {
117-
this.programTags$.next(programs);
118-
})
119-
);
120-
}
121112
}

projects/social_platform/src/app/office/program/shared/program-card/program-card.component.html

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,18 @@
1212
<p
1313
class="text-body-10 card__description card__registration"
1414
[ngClass]="{
15-
'card__registration--actual': type === 'actual',
16-
'card__registration--participating': type === 'participating',
17-
'card__registration--ended': type === 'ended',
15+
'card__registration--actual': (!registerDateExpired && (!program.isUserMember || !program.isUserManager)),
16+
'card__registration--participating': program.isUserMember,
17+
'card__registration--ended': registerDateExpired,
1818
}"
1919
>
20-
Регистрация до:
21-
{{ program.datetimeRegistrationEnds | date: "dd MMMM" }}
20+
{{
21+
!registerDateExpired && (!program.isUserMember || !program.isUserManager)
22+
? "Регистрация до:" + " " + (program.datetimeRegistrationEnds | date: "dd MMMM")
23+
: registerDateExpired
24+
? "программа завершена"
25+
: "ты уже участвуешь!"
26+
}}
2227
</p>
2328

2429
<div class="card__dates">

projects/social_platform/src/app/office/program/shared/program-card/program-card.component.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,9 @@ export class ProgramCardComponent implements OnInit {
4343

4444
@Input({ required: true }) program?: Program;
4545

46-
ngOnInit(): void {}
46+
ngOnInit(): void {
47+
this.registerDateExpired = Date.now() > Date.parse(this.program!.datetimeRegistrationEnds);
48+
}
4749

48-
// TODO: изменить когда у нас появятся в информации о программе состояние о завершенности/участии
49-
type = "actual";
50+
registerDateExpired?: boolean;
5051
}

0 commit comments

Comments
 (0)