From 30ce8326ad0ba9fe45b5a31c63486f6cffc837a9 Mon Sep 17 00:00:00 2001 From: Awakich Date: Tue, 7 Apr 2026 16:52:06 +0300 Subject: [PATCH 01/10] add new detail pages for courses & program --- .../detail/course-detail.component.html | 93 ++++++--- .../detail/course-detail.component.scss | 36 +++- .../courses/detail/course-detail.component.ts | 23 ++- .../courses/detail/course-detail.routes.ts | 4 +- .../courses/detail/info/info.component.html | 24 +-- .../courses/detail/info/info.component.scss | 75 +------ .../courses/detail/info/info.component.ts | 53 +---- .../course-about/course-about.component.html | 18 ++ .../course-about/course-about.component.scss | 73 +++++++ .../course-about/course-about.component.ts | 42 ++++ .../course-module-card.component.scss | 8 +- .../features/detail/detail.component.html | 189 +++++++++++------- .../features/detail/detail.component.scss | 69 ++++++- .../features/detail/detail.component.ts | 32 ++- .../office/features/nav/nav.component.html | 3 - .../program-links.component.html | 26 +++ .../program-links.component.scss | 60 ++++++ .../program-links/program-links.component.ts | 19 ++ .../program/detail/main/main.component.html | 70 ++----- .../program/detail/main/main.component.scss | 42 +--- .../program/detail/main/main.component.ts | 24 ++- .../components/button/button.component.scss | 2 +- .../ui/components/modal/modal.component.html | 2 +- .../ui/components/modal/modal.component.scss | 4 + .../ui/components/modal/modal.component.ts | 3 + 25 files changed, 645 insertions(+), 349 deletions(-) create mode 100644 projects/social_platform/src/app/office/courses/shared/course-about/course-about.component.html create mode 100644 projects/social_platform/src/app/office/courses/shared/course-about/course-about.component.scss create mode 100644 projects/social_platform/src/app/office/courses/shared/course-about/course-about.component.ts create mode 100644 projects/social_platform/src/app/office/features/program-links/program-links.component.html create mode 100644 projects/social_platform/src/app/office/features/program-links/program-links.component.scss create mode 100644 projects/social_platform/src/app/office/features/program-links/program-links.component.ts diff --git a/projects/social_platform/src/app/office/courses/detail/course-detail.component.html b/projects/social_platform/src/app/office/courses/detail/course-detail.component.html index e874a8146..da713b6ea 100644 --- a/projects/social_platform/src/app/office/courses/detail/course-detail.component.html +++ b/projects/social_platform/src/app/office/courses/detail/course-detail.component.html @@ -4,44 +4,75 @@
@if(course()) {
- cover - -
- - @if (!isTaskDetail()) { -

{{ course()!.title }}

- } +
+ cover +
+ + @if (!isTaskDetail()) { @if (appWidth > 920) { +

{{ course()!.title }}

+ } } +
-
-
-
- {{ isTaskDetail() ? "назад к модулю" : "назад" }} +
+
+ @if (appWidth < 920) { + + аналитика + + + + о курсе + + } - вернуться в программу + {{ isTaskDetail() ? "назад к модулю" : "назад" }} + + вернуться в программу +
+ + + + }
diff --git a/projects/social_platform/src/app/office/courses/detail/course-detail.component.scss b/projects/social_platform/src/app/office/courses/detail/course-detail.component.scss index 5383399fb..8b1384171 100644 --- a/projects/social_platform/src/app/office/courses/detail/course-detail.component.scss +++ b/projects/social_platform/src/app/office/courses/detail/course-detail.component.scss @@ -10,6 +10,11 @@ $detail-bar-mb: 12px; height: 100%; max-height: 100%; padding-top: 20px; + margin: 0px 20px; + + @include responsive.apply-desktop { + margin: 0; + } &__body { flex-grow: 1; @@ -25,12 +30,16 @@ $detail-bar-mb: 12px; padding: 0; border: none; border-radius: $body-slide; + margin-bottom: 20px; &__cover { position: relative; - width: 100%; height: 136px; - border-radius: 15px 15px 0 0; + border-radius: 15px; + + @include responsive.apply-desktop { + border-radius: 15px 15px 0 0; + } img { position: absolute; @@ -60,6 +69,7 @@ $detail-bar-mb: 12px; align-items: center; cursor: pointer; border-radius: 50%; + transform: translate(-50%, 30%); &--program { bottom: 15px; @@ -102,13 +112,29 @@ $detail-bar-mb: 12px; &__actions { display: grid; grid-template-columns: 1fr 1fr; - gap: 180px; + gap: 12px; align-items: center; - padding: 24px 0 30px; + padding: 24px 10px 0; + + @include responsive.apply-desktop { + gap: 180px; + padding: 24px 0 30px; + } + + &--end { + justify-self: end; + } + + &--full { + grid-column: 1 / -1; + + @include responsive.apply-desktop { + grid-column: auto; + } + } &--disabled { cursor: not-allowed; - opacity: 0.5; } } } diff --git a/projects/social_platform/src/app/office/courses/detail/course-detail.component.ts b/projects/social_platform/src/app/office/courses/detail/course-detail.component.ts index b66e3a03b..a1057f719 100644 --- a/projects/social_platform/src/app/office/courses/detail/course-detail.component.ts +++ b/projects/social_platform/src/app/office/courses/detail/course-detail.component.ts @@ -1,13 +1,16 @@ /** @format */ import { CommonModule } from "@angular/common"; -import { Component, DestroyRef, inject, signal, OnInit } from "@angular/core"; +import { Component, DestroyRef, HostListener, inject, signal, OnInit } from "@angular/core"; import { ActivatedRoute, NavigationEnd, Router, RouterOutlet } from "@angular/router"; import { filter, map, tap } from "rxjs"; import { AvatarComponent } from "@ui/components/avatar/avatar.component"; import { ButtonComponent } from "@ui/components"; +import { IconComponent } from "@uilib"; import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { CourseDetail, CourseStructure } from "@office/models/courses.model"; +import { ModalComponent } from "@ui/components/modal/modal.component"; +import { CourseAboutComponent } from "@office/courses/shared/course-about/course-about.component"; /** * Компонент детального просмотра траектории @@ -17,7 +20,15 @@ import { CourseDetail, CourseStructure } from "@office/models/courses.model"; @Component({ selector: "app-course-detail", standalone: true, - imports: [CommonModule, RouterOutlet, AvatarComponent, ButtonComponent], + imports: [ + CommonModule, + RouterOutlet, + AvatarComponent, + ButtonComponent, + IconComponent, + ModalComponent, + CourseAboutComponent, + ], templateUrl: "./course-detail.component.html", styleUrl: "./course-detail.component.scss", }) @@ -26,8 +37,16 @@ export class CourseDetailComponent implements OnInit { private readonly router = inject(Router); private readonly destroyRef = inject(DestroyRef); + appWidth = window.innerWidth; + + @HostListener("window:resize") + onResize() { + this.appWidth = window.innerWidth; + } + protected readonly isTaskDetail = signal(false); protected readonly isDisabled = signal(false); + isAboutModalOpen = false; protected readonly courseModules = signal([]); protected readonly course = signal(undefined); diff --git a/projects/social_platform/src/app/office/courses/detail/course-detail.routes.ts b/projects/social_platform/src/app/office/courses/detail/course-detail.routes.ts index 8b168483c..5550d2854 100644 --- a/projects/social_platform/src/app/office/courses/detail/course-detail.routes.ts +++ b/projects/social_platform/src/app/office/courses/detail/course-detail.routes.ts @@ -1,9 +1,9 @@ /** @format */ import type { Routes } from "@angular/router"; -import { TrajectoryInfoComponent } from "./info/info.component"; import { CourseDetailComponent } from "./course-detail.component"; import { CoursesDetailResolver } from "./course-detail.resolver"; +import { CourseInfoComponent } from "./info/info.component"; export const COURSE_DETAIL_ROUTES: Routes = [ { @@ -16,7 +16,7 @@ export const COURSE_DETAIL_ROUTES: Routes = [ children: [ { path: "", - component: TrajectoryInfoComponent, + component: CourseInfoComponent, }, { path: "lesson", diff --git a/projects/social_platform/src/app/office/courses/detail/info/info.component.html b/projects/social_platform/src/app/office/courses/detail/info/info.component.html index 1902dec97..2b6776ff7 100644 --- a/projects/social_platform/src/app/office/courses/detail/info/info.component.html +++ b/projects/social_platform/src/app/office/courses/detail/info/info.component.html @@ -4,6 +4,7 @@
+ @if (appWidth > 920) {
+ }
+ @if (appWidth > 920) {
-
-
-

о курсе

- -
- @if (courseDetail()!.description) { -
-

- @if (descriptionExpandable) { -
- {{ readFullDescription ? "cкрыть" : "подробнее" }} -
- } -
- } -
+
+ }
diff --git a/projects/social_platform/src/app/office/courses/detail/info/info.component.scss b/projects/social_platform/src/app/office/courses/detail/info/info.component.scss index fa96d9440..2ab066532 100644 --- a/projects/social_platform/src/app/office/courses/detail/info/info.component.scss +++ b/projects/social_platform/src/app/office/courses/detail/info/info.component.scss @@ -40,8 +40,12 @@ &__details { display: grid; - grid-template-columns: 2fr 5fr 3fr; + grid-template-columns: 1fr; grid-gap: 20px; + + @include responsive.apply-desktop { + grid-template-columns: 2fr 5fr 3fr; + } } &__progress { @@ -92,75 +96,6 @@ } } -.about { - padding: 24px; - background-color: var(--light-white); - border-radius: var(--rounded-lg); - - &__head { - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: 8px; - border-bottom: 0.5px solid var(--accent); - - &--icon { - color: var(--accent); - } - } - - &__title { - margin-bottom: 8px; - color: var(--accent); - } - - /* stylelint-disable value-no-vendor-prefix */ - &__text { - p { - display: -webkit-box; - overflow: hidden; - color: var(--black); - text-overflow: ellipsis; - -webkit-box-orient: vertical; - -webkit-line-clamp: 5; - transition: all 0.7s ease-in-out; - - &.expanded { - -webkit-line-clamp: unset; - } - } - - ::ng-deep a { - color: var(--accent); - text-decoration: underline; - text-decoration-color: transparent; - text-underline-offset: 3px; - transition: text-decoration-color 0.2s; - - &:hover { - text-decoration-color: var(--accent); - } - } - } - /* stylelint-enable value-no-vendor-prefix */ - - &__read-full { - margin-top: 8px; - color: var(--accent); - cursor: pointer; - } -} - -.read-more { - margin-top: 8px; - color: var(--accent); - cursor: pointer; - transition: background-color 0.2s; - - &:hover { - color: var(--accent-dark); - } -} .cancel { display: flex; diff --git a/projects/social_platform/src/app/office/courses/detail/info/info.component.ts b/projects/social_platform/src/app/office/courses/detail/info/info.component.ts index 5e15b937d..40da88b16 100644 --- a/projects/social_platform/src/app/office/courses/detail/info/info.component.ts +++ b/projects/social_platform/src/app/office/courses/detail/info/info.component.ts @@ -1,20 +1,9 @@ /** @format */ -import { - AfterViewInit, - ChangeDetectorRef, - Component, - DestroyRef, - ElementRef, - inject, - OnInit, - signal, - ViewChild, -} from "@angular/core"; +import { Component, DestroyRef, HostListener, inject, OnInit, signal } from "@angular/core"; import { ActivatedRoute, RouterModule } from "@angular/router"; -import { ParseBreaksPipe, ParseLinksPipe } from "@corelib"; import { IconComponent } from "@uilib"; -import { expandElement } from "@utils/expand-element"; +import { CourseAboutComponent } from "@office/courses/shared/course-about/course-about.component"; import { map } from "rxjs"; import { CommonModule } from "@angular/common"; import { SoonCardComponent } from "@office/shared/soon-card/soon-card.component"; @@ -40,25 +29,27 @@ import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; imports: [ IconComponent, RouterModule, - ParseBreaksPipe, - ParseLinksPipe, CommonModule, SoonCardComponent, ModalComponent, ButtonComponent, CourseModuleCardComponent, + CourseAboutComponent, ], templateUrl: "./info.component.html", styleUrl: "./info.component.scss", }) -export class TrajectoryInfoComponent implements OnInit, AfterViewInit { - @ViewChild("descEl") descEl?: ElementRef; +export class CourseInfoComponent implements OnInit { + appWidth = window.innerWidth; + + @HostListener("window:resize") + onResize() { + this.appWidth = window.innerWidth; + } private readonly route = inject(ActivatedRoute); private readonly destroyRef = inject(DestroyRef); - private readonly cdRef = inject(ChangeDetectorRef); - protected readonly courseStructure = signal(undefined); protected readonly courseDetail = signal(undefined); protected readonly isCompleteModule = signal(false); @@ -100,28 +91,4 @@ export class TrajectoryInfoComponent implements OnInit, AfterViewInit { } }); } - - protected descriptionExpandable?: boolean; - protected readFullDescription!: boolean; - - /** - * Проверка возможности расширения описания после инициализации представления - */ - ngAfterViewInit(): void { - const descElement = this.descEl?.nativeElement; - this.descriptionExpandable = descElement?.clientHeight < descElement?.scrollHeight; - - this.cdRef.detectChanges(); - } - - /** - * Переключение развернутого/свернутого состояния описания - * @param elem - HTML элемент описания - * @param expandedClass - CSS класс для развернутого состояния - * @param isExpanded - текущее состояние (развернуто/свернуто) - */ - onExpandDescription(elem: HTMLElement, expandedClass: string, isExpanded: boolean): void { - expandElement(elem, expandedClass, isExpanded); - this.readFullDescription = !isExpanded; - } } diff --git a/projects/social_platform/src/app/office/courses/shared/course-about/course-about.component.html b/projects/social_platform/src/app/office/courses/shared/course-about/course-about.component.html new file mode 100644 index 000000000..2ec404736 --- /dev/null +++ b/projects/social_platform/src/app/office/courses/shared/course-about/course-about.component.html @@ -0,0 +1,18 @@ + + +
+
+

о курсе

+ +
+ @if (description) { +
+

+ @if (descriptionExpandable) { +
+ {{ readFullDescription ? "cкрыть" : "подробнее" }} +
+ } +
+ } +
diff --git a/projects/social_platform/src/app/office/courses/shared/course-about/course-about.component.scss b/projects/social_platform/src/app/office/courses/shared/course-about/course-about.component.scss new file mode 100644 index 000000000..a4d1d7a0f --- /dev/null +++ b/projects/social_platform/src/app/office/courses/shared/course-about/course-about.component.scss @@ -0,0 +1,73 @@ +/** @format */ + +@use "styles/responsive"; + +.about { + padding: 0px; + background-color: transparent; + border-radius: 0px; + + @include responsive.apply-desktop { + padding: 24px; + background-color: var(--light-white); + border-radius: var(--rounded-lg); + } + + &__head { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 8px; + border-bottom: 0.5px solid var(--accent); + + &--icon { + color: var(--accent); + } + } + + &__title { + margin-bottom: 8px; + color: var(--accent); + } + + /* stylelint-disable value-no-vendor-prefix */ + &__text { + p { + display: -webkit-box; + overflow: hidden; + color: var(--black); + text-overflow: ellipsis; + -webkit-box-orient: vertical; + -webkit-line-clamp: 5; + transition: all 0.7s ease-in-out; + + &.expanded { + -webkit-line-clamp: unset; + } + } + + ::ng-deep a { + color: var(--accent); + text-decoration: underline; + text-decoration-color: transparent; + text-underline-offset: 3px; + transition: text-decoration-color 0.2s; + + &:hover { + text-decoration-color: var(--accent); + } + } + } + /* stylelint-enable value-no-vendor-prefix */ +} + +.read-more { + margin-top: 8px; + color: var(--accent); + cursor: pointer; + transition: background-color 0.2s; + + &:hover { + color: var(--accent-dark); + } +} diff --git a/projects/social_platform/src/app/office/courses/shared/course-about/course-about.component.ts b/projects/social_platform/src/app/office/courses/shared/course-about/course-about.component.ts new file mode 100644 index 000000000..685fa33d9 --- /dev/null +++ b/projects/social_platform/src/app/office/courses/shared/course-about/course-about.component.ts @@ -0,0 +1,42 @@ +/** @format */ + +import { + AfterViewInit, + ChangeDetectorRef, + Component, + ElementRef, + inject, + Input, + ViewChild, +} from "@angular/core"; +import { IconComponent } from "@uilib"; +import { ParseBreaksPipe, ParseLinksPipe } from "@corelib"; +import { expandElement } from "@utils/expand-element"; + +@Component({ + selector: "app-course-about", + templateUrl: "./course-about.component.html", + styleUrl: "./course-about.component.scss", + standalone: true, + imports: [IconComponent, ParseBreaksPipe, ParseLinksPipe], +}) +export class CourseAboutComponent implements AfterViewInit { + @Input({ required: true }) description!: string; + @ViewChild("descEl") descEl?: ElementRef; + + private readonly cdRef = inject(ChangeDetectorRef); + + descriptionExpandable = false; + readFullDescription = false; + + ngAfterViewInit(): void { + const el = this.descEl?.nativeElement; + this.descriptionExpandable = el?.clientHeight < el?.scrollHeight; + this.cdRef.detectChanges(); + } + + onExpandDescription(elem: HTMLElement, expandedClass: string, isExpanded: boolean): void { + expandElement(elem, expandedClass, isExpanded); + this.readFullDescription = !isExpanded; + } +} diff --git a/projects/social_platform/src/app/office/courses/shared/course-module-card/course-module-card.component.scss b/projects/social_platform/src/app/office/courses/shared/course-module-card/course-module-card.component.scss index fd009a50b..d5d246422 100644 --- a/projects/social_platform/src/app/office/courses/shared/course-module-card/course-module-card.component.scss +++ b/projects/social_platform/src/app/office/courses/shared/course-module-card/course-module-card.component.scss @@ -1,3 +1,5 @@ +@use "styles/responsive"; + .skill-card { display: flex; align-items: center; @@ -45,7 +47,7 @@ &__expand { position: absolute; bottom: -9px; - left: 17%; + left: 7%; z-index: 10; z-index: -10; width: 300px; @@ -53,6 +55,10 @@ cursor: pointer; background-color: var(--medium-grey-for-outline); border-radius: var(--rounded-xl); + + @include responsive.apply-desktop { + left: 14%; + } i { ::ng-deep { diff --git a/projects/social_platform/src/app/office/features/detail/detail.component.html b/projects/social_platform/src/app/office/features/detail/detail.component.html index b4be4f2ed..f60482841 100644 --- a/projects/social_platform/src/app/office/features/detail/detail.component.html +++ b/projects/social_platform/src/app/office/features/detail/detail.component.html @@ -19,7 +19,13 @@ class="info__avatar" (click)="redirectDetailInfo()" [class.info__avatar--program]="listType === 'program'" - [style.width]="listType === 'project' || listType === 'profile' ? '110px' : '123px'" + [style.width]=" + appWidth < 920 + ? '90px' + : listType === 'project' || listType === 'profile' + ? '110px' + : '123px' + " > @if (chatService.userOnlineStatusCache | async; as cache) { @if (listType === 'project' || listType === 'profile') { @@ -61,65 +69,62 @@
- @if (userType() !== undefined) { @if (!isUserMember && !isUserManager) { @if - (info().name.includes("Кейс-чемпионат MIR")) { - - - зарегистрироваться - - - } @else if (info().registrationLink) { - - - зарегистрироваться - - - } @else { - - - зарегистрироваться - - - } } @if (isUserMember && !isUserManager && !isUserExpert) { - - {{ isProjectAssigned ? "вы подали проект" : "создать заявку" }} - - - } @if ((isUserManager || isUserExpert) && isUserMember) { - + @if (userType() !== undefined) { +
+ @if (!isUserMember && !isUserManager) { @if (info().name.includes("Кейс-чемпионат MIR")) + { + + + зарегистрироваться + + + } @else if (info().registrationLink) { + + + зарегистрироваться + + + } @else { + + + зарегистрироваться + + + } } @if (isUserMember && !isUserManager && !isUserExpert) { - оценка проектов + {{ isProjectAssigned ? "вы подали проект" : "создать заявку" }} + - - } + } @if ((isUserManager || isUserExpert) && isUserMember) { + + + оценка проектов + + + } +
- + + @if (appWidth > 920) { {{ info().name.includes("Технолидеры Будущего") ? "Каталог лучших стартапов 2022/23" @@ -127,7 +132,7 @@ ? "аналитика" : "положение" }} - @if (isUserManager) { + } @if (isUserManager && appWidth > 920) { } @else { - + } + @if (appWidth > 920) {
- - @if (isUserManager || isUserExpert) { + } @if (isUserManager || isUserExpert) { проекты-участники - } @else { + } @else { @if (appWidth > 920) { узнать подробнее + } @else { + + + + } } @if (appWidth < 920) { + + материалы + } @if (isUserManager || isUserExpert) { участники } @else { @if (info().courses?.length) { - - - перейти в курс + + + {{ appWidth > 920 ? "перейти в курс" : "курс" }} } @else { - + @@ -251,6 +283,30 @@ + + + + + + + +
@@ -273,7 +329,6 @@ } @if (!isInProject) { @if (profile) { @if (+profile.id === +info().id) { > } @if (+profile.id === +info().id) { ([]); listType: "project" | "program" | "profile" = "project"; + appWidth = window.innerWidth; + + @HostListener("window:resize") + onResize() { + this.appWidth = window.innerWidth; + } + // Переменная для подсказок isTooltipVisible = false; @@ -128,6 +145,19 @@ export class DeatilComponent implements OnInit, OnDestroy { openSupport = false; // Флаг модального окна поддержки leaderLeaveModal = false; // Флаг модального окна предупреждения лидера isDelayModalOpen = false; + isContactsModalOpen = false; + isMaterialsModalOpen = false; + + get contactLinks(): { label: string; url: string }[] { + return (this.info()?.links ?? []).map((link: string) => ({ label: link, url: link })); + } + + get materialLinks(): { label: string; url: string }[] { + return (this.info()?.materials ?? []).map((m: { title: string; url: string }) => ({ + label: m.title, + url: m.url, + })); + } // Переменные для работы с подтверждением навыков showApproveSkillModal = false; diff --git a/projects/social_platform/src/app/office/features/nav/nav.component.html b/projects/social_platform/src/app/office/features/nav/nav.component.html index 7ded39491..5d0c22b4e 100644 --- a/projects/social_platform/src/app/office/features/nav/nav.component.html +++ b/projects/social_platform/src/app/office/features/nav/nav.component.html @@ -12,9 +12,6 @@ class="nav-bar__icon" > - @if (((notificationService.hasNotifications | async) || hasInvites) && !mobileMenuOpen) { -
- } @if (mobileMenuOpen) { diff --git a/projects/social_platform/src/app/office/features/program-links/program-links.component.html b/projects/social_platform/src/app/office/features/program-links/program-links.component.html new file mode 100644 index 000000000..4ff733576 --- /dev/null +++ b/projects/social_platform/src/app/office/features/program-links/program-links.component.html @@ -0,0 +1,26 @@ + + +
diff --git a/projects/social_platform/src/app/office/features/program-links/program-links.component.scss b/projects/social_platform/src/app/office/features/program-links/program-links.component.scss new file mode 100644 index 000000000..dfc8a3af4 --- /dev/null +++ b/projects/social_platform/src/app/office/features/program-links/program-links.component.scss @@ -0,0 +1,60 @@ +/** @format */ + +.links { + overflow: hidden; + + &__head { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 8px; + border-bottom: 0.5px solid var(--accent); + } + + &__title { + margin-bottom: 8px; + color: var(--accent); + } + + &__icon { + color: var(--accent); + } + + &__list { + display: flex; + flex-direction: column; + gap: 8px; + } + + &__item { + cursor: pointer; + } + + &__link { + display: flex; + gap: 6px; + align-items: center; + color: var(--accent); + transition: color 0.2s; + + &:hover { + color: var(--accent-dark); + } + + i { + display: flex; + flex-shrink: 0; + align-items: center; + justify-content: center; + width: 20px; + height: 20px; + border: 0.5px solid var(--medium-grey-for-outline); + border-radius: var(--rounded-xxl); + } + + span { + overflow: hidden; + text-overflow: ellipsis; + } + } +} diff --git a/projects/social_platform/src/app/office/features/program-links/program-links.component.ts b/projects/social_platform/src/app/office/features/program-links/program-links.component.ts new file mode 100644 index 000000000..6fe221c0e --- /dev/null +++ b/projects/social_platform/src/app/office/features/program-links/program-links.component.ts @@ -0,0 +1,19 @@ +/** @format */ + +import { Component, Input } from "@angular/core"; +import { IconComponent } from "@uilib"; +import { UserLinksPipe } from "@core/pipes/user-links.pipe"; +import { TruncatePipe } from "projects/core/src/lib/pipes/truncate.pipe"; + +@Component({ + selector: "app-program-links", + templateUrl: "./program-links.component.html", + styleUrl: "./program-links.component.scss", + standalone: true, + imports: [IconComponent, UserLinksPipe, TruncatePipe], +}) +export class ProgramLinksComponent { + @Input({ required: true }) title!: string; + @Input({ required: true }) icon!: string; + @Input({ required: true }) links!: { label: string; url: string }[]; +} diff --git a/projects/social_platform/src/app/office/program/detail/main/main.component.html b/projects/social_platform/src/app/office/program/detail/main/main.component.html index 84e3dfa63..6e3c93dcf 100644 --- a/projects/social_platform/src/app/office/program/detail/main/main.component.html +++ b/projects/social_platform/src/app/office/program/detail/main/main.component.html @@ -10,6 +10,7 @@ } @else {
+ @if (appWidth > 920) {
+ }
@@ -58,61 +60,27 @@

о программе

+ @if (appWidth > 920) {
-
+ }
} diff --git a/projects/social_platform/src/app/office/program/detail/main/main.component.scss b/projects/social_platform/src/app/office/program/detail/main/main.component.scss index 8f6e3b020..a721634f7 100644 --- a/projects/social_platform/src/app/office/program/detail/main/main.component.scss +++ b/projects/social_platform/src/app/office/program/detail/main/main.component.scss @@ -65,8 +65,12 @@ &__details { display: grid; - grid-template-columns: 2fr 5fr 3fr; + grid-template-columns: 1fr; grid-gap: 20px; + + @include responsive.apply-desktop { + grid-template-columns: 2fr 5fr 3fr; + } } } @@ -140,42 +144,6 @@ } } -.links { - overflow: hidden; - - &__section { - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: 8px; - border-bottom: 0.5px solid var(--accent); - } - - &__icon { - color: var(--accent); - } - - &__title { - margin-bottom: 8px; - color: var(--accent); - } - - &__item { - cursor: pointer; - } - - ul { - display: flex; - flex-direction: column; - gap: 8px; - overflow: hidden; - - span { - overflow: hidden; - text-overflow: ellipsis; - } - } -} .news { &__form { diff --git a/projects/social_platform/src/app/office/program/detail/main/main.component.ts b/projects/social_platform/src/app/office/program/detail/main/main.component.ts index b7f301fc7..fabde4a54 100644 --- a/projects/social_platform/src/app/office/program/detail/main/main.component.ts +++ b/projects/social_platform/src/app/office/program/detail/main/main.component.ts @@ -3,6 +3,7 @@ import { ChangeDetectorRef, Component, ElementRef, + HostListener, OnDestroy, OnInit, signal, @@ -26,7 +27,7 @@ import { ProgramNewsService } from "@office/program/services/program-news.servic import { FeedNews } from "@office/projects/models/project-news.model"; import { expandElement } from "@utils/expand-element"; import { ParseBreaksPipe, ParseLinksPipe } from "projects/core"; -import { UserLinksPipe } from "@core/pipes/user-links.pipe"; +import { ProgramLinksComponent } from "@office/features/program-links/program-links.component"; import { ProgramNewsCardComponent } from "../shared/news-card/news-card.component"; import { ButtonComponent, IconComponent } from "@ui/components"; import { ApiPagination } from "@models/api-pagination.model"; @@ -40,7 +41,6 @@ import { SoonCardComponent } from "@office/shared/soon-card/soon-card.component" import { NewsFormComponent } from "@office/features/news-form/news-form.component"; import { AsyncPipe } from "@angular/common"; import { AvatarComponent } from "@uilib"; -import { TruncatePipe } from "projects/core/src/lib/pipes/truncate.pipe"; import { NewsCardComponent } from "@office/features/news-card/news-card.component"; import { AuthService } from "@auth/services"; @@ -53,7 +53,6 @@ import { AuthService } from "@auth/services"; IconComponent, ButtonComponent, ProgramNewsCardComponent, - UserLinksPipe, AsyncPipe, ParseBreaksPipe, ParseLinksPipe, @@ -61,9 +60,7 @@ import { AuthService } from "@auth/services"; MatProgressBarModule, SoonCardComponent, NewsFormComponent, - ModalComponent, - MatProgressBarModule, - TruncatePipe, + ProgramLinksComponent, RouterModule, ], }) @@ -86,6 +83,13 @@ export class ProgramDetailMainComponent implements OnInit, OnDestroy { return this.projectAdditionalService.getErrorAssignProjectToProgramModalMessage(); } + appWidth = window.innerWidth; + + @HostListener("window:resize") + onResize() { + this.appWidth = window.innerWidth; + } + news = signal([]); totalNewsCount = signal(0); fetchLimit = signal(10); @@ -367,4 +371,12 @@ export class ProgramDetailMainComponent implements OnInit, OnDestroy { registerDateExpired!: boolean; descriptionExpandable!: boolean; readFullDescription = false; + + get contactLinks(): { label: string; url: string }[] { + return (this.program?.links ?? []).map(link => ({ label: link, url: link })); + } + + get materialLinks(): { label: string; url: string }[] { + return (this.program?.materials ?? []).map(m => ({ label: m.title, url: m.url })); + } } diff --git a/projects/social_platform/src/app/ui/components/button/button.component.scss b/projects/social_platform/src/app/ui/components/button/button.component.scss index 1b8f6b5f0..57d11961c 100644 --- a/projects/social_platform/src/app/ui/components/button/button.component.scss +++ b/projects/social_platform/src/app/ui/components/button/button.component.scss @@ -125,7 +125,7 @@ } &--small { - width: 70px; + width: 100px; padding: 4px 24px; &--icon { diff --git a/projects/social_platform/src/app/ui/components/modal/modal.component.html b/projects/social_platform/src/app/ui/components/modal/modal.component.html index 27a13b455..567450daf 100644 --- a/projects/social_platform/src/app/ui/components/modal/modal.component.html +++ b/projects/social_platform/src/app/ui/components/modal/modal.component.html @@ -3,7 +3,7 @@