From 63597bda981068c9d6d243336417151a3df804bd Mon Sep 17 00:00:00 2001 From: Gui Seek Date: Sun, 1 Dec 2024 09:34:07 -0300 Subject: [PATCH] =?UTF-8?q?feat(event):=20adiciona=20rsvp=20button=20na=20?= =?UTF-8?q?p=C3=A1gina=20p=C3=BAblica?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/devmx/src/app/handlers/auth-error.ts | 3 +- apps/devmx/src/index.html | 5 +- .../src/scss/components/_links.theme.scss | 5 + devmx.code-workspace | 105 ++++++++++++++++++ .../lib/application/authentication.facade.ts | 2 + .../about-user/about-user.container.html | 2 +- .../about-user/about-user.container.ts | 4 +- .../authentication.container.html | 7 +- .../authentication.container.ts | 7 +- .../registration/registration.container.ts | 20 +++- .../containers/account/account.container.html | 4 + .../containers/account/account.container.ts | 2 + .../event-page/event-page.container.html | 102 +++++++++-------- .../event-page/event-page.container.scss | 33 +++++- .../event-page/event-page.container.ts | 68 ++++++++++-- .../rsvp-button/rsvp-button.component.html | 1 + 16 files changed, 298 insertions(+), 72 deletions(-) create mode 100644 devmx.code-workspace diff --git a/apps/devmx/src/app/handlers/auth-error.ts b/apps/devmx/src/app/handlers/auth-error.ts index ec167864..9c135dc8 100644 --- a/apps/devmx/src/app/handlers/auth-error.ts +++ b/apps/devmx/src/app/handlers/auth-error.ts @@ -33,7 +33,8 @@ export class AuthErrorHandler implements ErrorHandler { this.showMessage(error.status, message); if (error.status === 401) { - this.router.navigateByUrl('/conta/autenticacao'); + const queryParams = { redirectTo: this.router.url }; + this.router.navigate(['/', 'conta', 'autenticacao'], { queryParams }); localStorage.removeItem('accessToken'); } } diff --git a/apps/devmx/src/index.html b/apps/devmx/src/index.html index afbabefa..c24c1e95 100644 --- a/apps/devmx/src/index.html +++ b/apps/devmx/src/index.html @@ -12,10 +12,7 @@ - + { const request$ = this.createUserUseCase.execute(data); request$.pipe(take(1)).subscribe(); + + return request$; } signOut() { diff --git a/packages/account/feature-about/src/lib/containers/about-user/about-user.container.html b/packages/account/feature-about/src/lib/containers/about-user/about-user.container.html index 963fe0c6..40fd6e79 100644 --- a/packages/account/feature-about/src/lib/containers/about-user/about-user.container.html +++ b/packages/account/feature-about/src/lib/containers/about-user/about-user.container.html @@ -38,7 +38,7 @@

{{'@' + user.name}}

@if (user.profile && user.profile.minibio) { - + } diff --git a/packages/account/feature-about/src/lib/containers/about-user/about-user.container.ts b/packages/account/feature-about/src/lib/containers/about-user/about-user.container.ts index c71c352c..b0f4eaf1 100644 --- a/packages/account/feature-about/src/lib/containers/about-user/about-user.container.ts +++ b/packages/account/feature-about/src/lib/containers/about-user/about-user.container.ts @@ -2,7 +2,7 @@ import { PresentationCardListComponent } from '@devmx/presentation-ui-shared'; import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; import { MatProgressBarModule } from '@angular/material/progress-bar'; import { PresentationFacade } from '@devmx/presentation-data-access'; -import { MarkdownComponent } from '@devmx/shared-ui-global/editor'; +import { MarkdownViewComponent } from '@devmx/shared-ui-global/markdown'; import { AuthenticationFacade } from '@devmx/account-data-access'; import { EventCardListComponent } from '@devmx/event-ui-shared'; import { IconComponent } from '@devmx/shared-ui-global/icon'; @@ -24,7 +24,7 @@ import { RolePipe } from '@devmx/account-ui-shared'; changeDetection: ChangeDetectionStrategy.OnPush, imports: [ MatCardModule, - MarkdownComponent, + MarkdownViewComponent, PresentationCardListComponent, EventCardListComponent, MatProgressBarModule, diff --git a/packages/account/feature-auth/src/lib/containers/authentication/authentication.container.html b/packages/account/feature-auth/src/lib/containers/authentication/authentication.container.html index 7c607573..7a1998ca 100644 --- a/packages/account/feature-auth/src/lib/containers/authentication/authentication.container.html +++ b/packages/account/feature-auth/src/lib/containers/authentication/authentication.container.html @@ -7,7 +7,12 @@ - Quero criar minha conta + Quero criar minha conta { - if (connected) this.router.navigate(['/']); + const { redirectTo } = this.route.snapshot.queryParams; + if (connected && redirectTo) this.router.navigateByUrl(redirectTo); + else if (connected) this.router.navigate(['/']); }); this.form.controls.code.valueChanges diff --git a/packages/account/feature-auth/src/lib/containers/registration/registration.container.ts b/packages/account/feature-auth/src/lib/containers/registration/registration.container.ts index d16c720b..16c6cf05 100644 --- a/packages/account/feature-auth/src/lib/containers/registration/registration.container.ts +++ b/packages/account/feature-auth/src/lib/containers/registration/registration.container.ts @@ -8,8 +8,9 @@ import { MatInputModule } from '@angular/material/input'; import { MessageService } from '@devmx/shared-ui-global'; import { MatCardModule } from '@angular/material/card'; import { ReactiveFormsModule } from '@angular/forms'; -import { RouterLink } from '@angular/router'; +import { ActivatedRoute, Router, RouterModule } from '@angular/router'; import { CreateUserForm } from '../../forms'; +import { take } from 'rxjs'; @Component({ selector: 'devmx-registration', @@ -23,22 +24,33 @@ import { CreateUserForm } from '../../forms'; MatButtonModule, MatInputModule, MatCardModule, - RouterLink, + RouterModule, ], }) export class RegistrationContainer { + authFacade = inject(AuthenticationFacade); + message = inject(MessageService); dialog = inject(DialogFacade); - authFacade = inject(AuthenticationFacade); + route = inject(ActivatedRoute); + + router = inject(Router); form = new CreateUserForm(); onSubmit() { if (this.form.valid) { const value = this.form.getRawValue(); - this.authFacade.createUser(value); + const create$ = this.authFacade.createUser(value); + create$.pipe(take(1)).subscribe(() => { + const { redirectTo } = this.route.snapshot.queryParams; + + const queryParams = { redirectTo }; + const path = ['/', 'conta', 'autenticacao', 'acessar']; + this.router.navigate(path, { queryParams }); + }); const message = `Conta ${value.name} criada`; this.message.open({ message }); diff --git a/packages/account/feature-shell/src/lib/containers/account/account.container.html b/packages/account/feature-shell/src/lib/containers/account/account.container.html index f1eb9b5a..91787f87 100644 --- a/packages/account/feature-shell/src/lib/containers/account/account.container.html +++ b/packages/account/feature-shell/src/lib/containers/account/account.container.html @@ -30,6 +30,10 @@ /> + + Acessar página pública + + diff --git a/packages/account/feature-shell/src/lib/containers/account/account.container.ts b/packages/account/feature-shell/src/lib/containers/account/account.container.ts index 185d13cc..54f3ad35 100644 --- a/packages/account/feature-shell/src/lib/containers/account/account.container.ts +++ b/packages/account/feature-shell/src/lib/containers/account/account.container.ts @@ -24,6 +24,7 @@ import { UserFacade, AuthenticationFacade, } from '@devmx/account-data-access'; +import { RouterLink } from '@angular/router'; @Component({ @@ -43,6 +44,7 @@ import { SelectFileComponent, MatButtonModule, AvatarComponent, + RouterLink ], }) export class AccountContainer { diff --git a/packages/event/feature-page/src/lib/containers/event-page/event-page.container.html b/packages/event/feature-page/src/lib/containers/event-page/event-page.container.html index 9aefc44c..d17a31a8 100644 --- a/packages/event/feature-page/src/lib/containers/event-page/event-page.container.html +++ b/packages/event/feature-page/src/lib/containers/event-page/event-page.container.html @@ -30,52 +30,64 @@

@if ((event.format | showEventLink) && event.link) { } + + - - - -
- -
-
-
- @if (event.presentations.length) { - - - - @for (presentation of event.presentations; track presentation) { - - -
{{ presentation.title }}
-
{{ presentation.owner.displayName }}
- -
- } -
-
-
- } - - - - - -
{{ event.owner.displayName }}
-
- @if (event.leaders.length) { - - @for (leader of event.leaders; track leader) { - - -
{{ leader.displayName }}
-
- } - - } -
-
-
-
+
+
+ + + + + + +
+ +
+
+
+ @if (event.presentations.length) { + + + + @for (presentation of event.presentations; track presentation) { + + +
{{ presentation.title }}
+
{{ presentation.owner.displayName }}
+ +
+ } +
+
+
+ } + + + + + +
{{ event.owner.displayName }}
+
+ @if (event.leaders.length) { + + @for (leader of event.leaders; track leader) { + + +
{{ leader.displayName }}
+
+ } + + } +
+
+
+
+
} diff --git a/packages/event/feature-page/src/lib/containers/event-page/event-page.container.scss b/packages/event/feature-page/src/lib/containers/event-page/event-page.container.scss index 81ef4b64..0b40a947 100644 --- a/packages/event/feature-page/src/lib/containers/event-page/event-page.container.scss +++ b/packages/event/feature-page/src/lib/containers/event-page/event-page.container.scss @@ -30,9 +30,38 @@ background-blend-mode: multiply; nav { - display: flex; - flex-direction: row; gap: 1em; + width: 100%; + display: flex; + flex-flow: row wrap; + justify-content: flex-start; + } + } + + form { + display: flex; + justify-content: flex-end; + + @media (max-width: 767px) { + justify-content: center; + } + } + + .event-page-content { + position: relative; + + .rsvp-button { + position: absolute; + z-index: 100; + right: 0.4em; + top: -0.4em; + + @media (max-width: 767px) { + position: relative; + margin-bottom: 1em; + right: 0; + top: 0; + } } } diff --git a/packages/event/feature-page/src/lib/containers/event-page/event-page.container.ts b/packages/event/feature-page/src/lib/containers/event-page/event-page.container.ts index d07ef5f9..d306f090 100644 --- a/packages/event/feature-page/src/lib/containers/event-page/event-page.container.ts +++ b/packages/event/feature-page/src/lib/containers/event-page/event-page.container.ts @@ -1,30 +1,33 @@ -import { MarkdownComponent } from '@devmx/shared-ui-global/editor'; +import { MarkdownViewComponent } from '@devmx/shared-ui-global/markdown'; import { ActivatedRoute, RouterModule } from '@angular/router'; import { MatSidenavModule } from '@angular/material/sidenav'; import { IconComponent } from '@devmx/shared-ui-global/icon'; import { MatToolbarModule } from '@angular/material/toolbar'; import { MatButtonModule } from '@angular/material/button'; -import { EventPage } from '@devmx/shared-api-interfaces'; +import { EventPage, RSVP } from '@devmx/shared-api-interfaces'; import { MatTabsModule } from '@angular/material/tabs'; import { MatCardModule } from '@angular/material/card'; import { MatListModule } from '@angular/material/list'; import { AsyncPipe, DatePipe } from '@angular/common'; -import { filter, map } from 'rxjs'; -import { - inject, - Component, - ChangeDetectionStrategy, -} from '@angular/core'; +import { combineLatest, filter, map, tap } from 'rxjs'; +import { inject, Component, ChangeDetectionStrategy } from '@angular/core'; import { MapsButtonComponent, CalendarButtonComponent, YoutubeButtonComponent, HeartButtonComponent, + WhatsAppButtonComponent, } from '@devmx/shared-ui-global/button'; import { ShowEventLinkPipe, ShowEventAddressPipe, + RSVPButtonComponent, + RSVPForm, } from '@devmx/event-ui-shared'; +import { ReactiveFormsModule } from '@angular/forms'; +import { RSVPFacade } from '@devmx/event-data-access'; +import { AuthenticationFacade } from '@devmx/account-data-access'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ selector: 'devmx-event-page', @@ -33,12 +36,15 @@ import { changeDetection: ChangeDetectionStrategy.OnPush, imports: [ RouterModule, - MarkdownComponent, + MarkdownViewComponent, + ReactiveFormsModule, CalendarButtonComponent, YoutubeButtonComponent, + WhatsAppButtonComponent, MapsButtonComponent, HeartButtonComponent, ShowEventAddressPipe, + RSVPButtonComponent, ShowEventLinkPipe, MatSidenavModule, MatToolbarModule, @@ -52,10 +58,52 @@ import { ], }) export class EventPageContainer { + authFacade = inject(AuthenticationFacade); + rsvpFacade = inject(RSVPFacade); route = inject(ActivatedRoute); event$ = this.route.data.pipe( filter(({ page }) => !!page), - map(({ page }) => page as EventPage) + map(({ page }) => page as EventPage), + tap((event) => this.setRSVPEvent(event.id)) ); + + form = new RSVPForm(); + + constructor() { + if (localStorage.getItem('accessToken')) { + this.authFacade.load(); + + const user$ = this.authFacade.auth$.pipe( + filter((user) => !!user), + map((user) => user.id) + ); + + const rsvp$ = this.rsvpFacade.response$.pipe( + filter((rsvp) => rsvp.length > 0) + ); + + combineLatest([user$, rsvp$]) + .pipe(takeUntilDestroyed()) + .subscribe(([id, rsvp]) => { + const item = rsvp.find((item) => item.user.id === id); + if (item) this.setRSVPStatus(item); + }); + } + } + + setRSVPEvent = (event: string) => { + this.form.patchValue({ event }); + this.rsvpFacade.loadConfirmed(event); + }; + + setRSVPStatus({ status }: RSVP) { + this.form.patchValue({ status }, { emitEvent: false }); + } + + onStatusChange() { + if (this.form.valid) { + this.rsvpFacade.create(this.form.getRawValue()); + } + } } diff --git a/packages/event/ui-shared/src/lib/components/rsvp-button/rsvp-button.component.html b/packages/event/ui-shared/src/lib/components/rsvp-button/rsvp-button.component.html index 9d261265..ce659299 100644 --- a/packages/event/ui-shared/src/lib/components/rsvp-button/rsvp-button.component.html +++ b/packages/event/ui-shared/src/lib/components/rsvp-button/rsvp-button.component.html @@ -2,6 +2,7 @@ [formControl]="control" (change)="statusChange.emit()" aria-label="Presença" + class="button-group" > Vou! Não vou