Skip to content

Commit

Permalink
fill public profile page with content
Browse files Browse the repository at this point in the history
  • Loading branch information
halbekanne committed Dec 17, 2023
1 parent 68d307d commit a8215dd
Show file tree
Hide file tree
Showing 21 changed files with 318 additions and 57 deletions.
6 changes: 3 additions & 3 deletions src/app/chat/data-access/chat-http.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { inject, Injectable } from '@angular/core';
import { catchError, map, Observable, of, switchMap } from 'rxjs';
import { EnvironmentService } from '@shared/data-access/environment.service';
import {
APIResponse,
asError,
asSuccess,
OldAPIResponse,
} from '@shared/util/http/response.types';
import {
ChatDto,
Expand Down Expand Up @@ -43,7 +43,7 @@ export class ChatHttpService {
createMessage$(
chatId: string,
message: CreateMessageRequest
): Observable<APIResponse<void>> {
): Observable<OldAPIResponse<void>> {
return this.http
.post<void>(
`${this.chatApiUrl}/${chatId}/messages`,
Expand Down Expand Up @@ -107,7 +107,7 @@ export class ChatHttpService {
);
}

getChatsAndDancers$(): Observable<APIResponse<ChatsAndDancers>> {
getChatsAndDancers$(): Observable<OldAPIResponse<ChatsAndDancers>> {
return this.http.get<ChatList>(this.chatApiUrl, this.defaultOptions).pipe(
map((chatList) => {
const dancerIds = this.getAllDancerIds(chatList.chats);
Expand Down
7 changes: 5 additions & 2 deletions src/app/home/data-access/contact.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import {
} from '@angular/common/http';
import { EnvironmentService } from '@shared/data-access/environment.service';
import {
APIResponse,
asError,
asSuccess,
OldAPIResponse,
} from '@shared/util/http/response.types';
import { EventLogService } from '@shared/data-access/log/event-log.service';

Expand All @@ -28,7 +28,10 @@ export class ContactService {
private eventLogService: EventLogService
) {}

sendMessage(message: string, sender: string): Observable<APIResponse<void>> {
sendMessage(
message: string,
sender: string
): Observable<OldAPIResponse<void>> {
const apiUrlContact = `${this.environment.getApiUrl()}/contacts`;
const payload = {
sender,
Expand Down
4 changes: 2 additions & 2 deletions src/app/home/feature/contact/contact.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { AuthenticationService } from '@shared/data-access/auth/authentication.s
import { EventLogService } from '@shared/data-access/log/event-log.service';
import { ContactService } from '../../data-access/contact.service';
import { tap } from 'rxjs';
import { APIResponse } from '@shared/util/http/response.types';
import { OldAPIResponse } from '@shared/util/http/response.types';
import { ErrorMessagePipe } from '@shared/util/http/error-message.pipe';
import { MatButtonModule } from '@angular/material/button';
import { RecaptchaModule } from 'ng-recaptcha';
Expand Down Expand Up @@ -40,7 +40,7 @@ import { DataTestDirective } from '@shared/util/data-test.directive';
})
export class ContactComponent implements OnInit {
contactForm!: FormGroup;
contactResponse?: APIResponse<void>;
contactResponse?: OldAPIResponse<void>;

// TODO: refactor, we should solve this in a reactive way (e.g. subscribe in the template)
isCaptchaSolved = false;
Expand Down
4 changes: 2 additions & 2 deletions src/app/profile/data-access/image-upload.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { catchError, map, Observable, of } from 'rxjs';
import { EnvironmentService } from '@shared/data-access/environment.service';
import {
APIResponse,
asError,
asSuccess,
OldAPIResponse,
} from '@shared/util/http/response.types';
import { UploadedImageDao } from './types/profile.types';

Expand Down Expand Up @@ -36,7 +36,7 @@ export class ImageUploadService {

uploadImage$(
croppedImage: string
): Observable<APIResponse<UploadedImageDao>> {
): Observable<OldAPIResponse<UploadedImageDao>> {
const blobFromDataUrl = this.dataURItoBlob(croppedImage);
const formData: FormData = new FormData();
formData.append('file', blobFromDataUrl);
Expand Down
36 changes: 33 additions & 3 deletions src/app/profile/data-access/profile.service.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,42 @@
import { Injectable } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { EnvironmentService } from '@shared/data-access/environment.service';
import { HttpClient } from '@angular/common/http';
import { PublicProfile } from './types/public-profile.types';
import { Observable } from 'rxjs';
import { toApiResponse } from '@shared/util/http/response.utils';
import { ApiResponse } from '@shared/util/http/response.types';
import { ImageService } from '@shared/data-access/image.service';

@Injectable({
providedIn: 'root',
})
export class ProfileService {
constructor() {}
private readonly http = inject(HttpClient);
private readonly imageService = inject(ImageService);
private readonly profileApiUrl = `${inject(
EnvironmentService
).getApiUrl()}/profile`;

// public getOwnProfile(): void {}
//
// public getProfile(dancerId: string): void {}

public getPublicProfile(
dancerId: string
): Observable<ApiResponse<PublicProfile>> {
return toApiResponse(
this.http.get<PublicProfile>(`${this.profileApiUrl}/${dancerId}`)
);
}

getProfileImageSrc(imgHash: string | undefined, width = 150): string {
if (imgHash) {
return this.imageService.getDancerImageSrcOrDefault(imgHash, width);
} else {
return this.imageService.getDancerImageSrcOrDefault(null, width);
}
}

getDefaultProfileImage(): string {
return this.imageService.getDefaultDancerImage();
}
}
15 changes: 15 additions & 0 deletions src/app/profile/data-access/types/public-profile.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Dance, Gender } from './profile.types';

export type PublicProfile = {
id: string;
size: number;
gender: Gender;
dancerName: string;
age: number;
ableTo: Dance[];
wantsTo: Dance[];
city: string;
country: string;
profileImageHash: string;
aboutMe: string;
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
NonNullableFormBuilder,
ReactiveFormsModule,
} from '@angular/forms';
import { APIError, APIResponse } from '@shared/util/http/response.types';
import { APIError, OldAPIResponse } from '@shared/util/http/response.types';
import { ProfileOldService } from '@shared/data-access/profile/profile-old.service';
import {
Profile,
Expand Down Expand Up @@ -56,7 +56,7 @@ export class EditProfileComponent {
});
croppedImage?: string | null;
imageChangedEvent: any = '';
uploadResponse?: APIResponse<UploadedImageDao>;
uploadResponse?: OldAPIResponse<UploadedImageDao>;
error?: APIError;

constructor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Component } from '@angular/core';
import { ImageUploadService } from '../../../data-access/image-upload.service';
import { ImageCroppedEvent, ImageCropperModule } from 'ngx-image-cropper';
import { ProfileOldService } from '@shared/data-access/profile/profile-old.service';
import { APIResponse } from '@shared/util/http/response.types';
import { OldAPIResponse } from '@shared/util/http/response.types';
import { UploadedImageDao } from '../../../data-access/types/profile.types';
import { Router } from '@angular/router';
import { NgIf } from '@angular/common';
Expand All @@ -18,7 +18,7 @@ import { MatButtonModule } from '@angular/material/button';
export class InitProfileImageComponent {
croppedImage?: string | null | undefined;
imageChangedEvent: any = '';
uploadResponse?: APIResponse<UploadedImageDao>;
uploadResponse?: OldAPIResponse<UploadedImageDao>;

constructor(
private imageUploadService: ImageUploadService,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import { ProfileHttpService } from '@shared/data-access/profile/profile-http.ser
import { ProfileOldService } from '@shared/data-access/profile/profile-old.service';
import {
APIError,
APIResponse,
asError,
OldAPIResponse,
ResponseError,
} from '@shared/util/http/response.types';
import { of, switchMap } from 'rxjs';
Expand Down Expand Up @@ -60,7 +60,7 @@ export class InitUserNameComponent {
this.profileHttpService
.checkNameAvailability$(username)
.pipe(
switchMap((response: APIResponse<NameAvailability>) => {
switchMap((response: OldAPIResponse<NameAvailability>) => {
if (!response.isSuccess) {
return of(response as ResponseError);
}
Expand All @@ -70,7 +70,7 @@ export class InitUserNameComponent {
return this.profileService.setDancerName(username);
})
)
.subscribe((response: APIResponse<void>) => {
.subscribe((response: OldAPIResponse<void>) => {
if (response.isSuccess) {
this.router.navigate(['profile/initial-setup/personal-info']);
} else {
Expand Down
130 changes: 123 additions & 7 deletions src/app/profile/feature/public-profile.component.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,135 @@
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ActivatedRoute } from '@angular/router';
import { ActivatedRoute, Router } from '@angular/router';
import { ProfileService } from '../data-access/profile.service';
import { AgePipe } from '@shared/util/age.pipe';
import { DisplayDanceLevelPipe } from '../util/pipes/display-dance-level.pipe';
import { DisplayDanceRolePipe } from '../util/pipes/display-dance-role.pipe';
import { DisplayGenderPipe } from '../util/pipes/display-gender.pipe';
import { ProfileDataEntryComponent } from '../ui/profile-data-entry.component';

@Component({
selector: 'app-public-profile',
standalone: true,
imports: [CommonModule],
imports: [
CommonModule,
AgePipe,
DisplayDanceLevelPipe,
DisplayDanceRolePipe,
DisplayGenderPipe,
ProfileDataEntryComponent,
],
template: `
<p>
public-profile works and the id is
{{ activeRoute.snapshot.params['participantId'] }}
</p>
<!-- TODO: loading and error view -->
<ng-container *ngIf="profileResponse$ | async as profileResponse">
<div
*ngIf="
profileResponse.fetchStatus === 'success' &&
profileResponse.payload as profile
"
class="my-12 mx-auto flex max-w-[1200px] flex-col gap-10 px-4 md:flex-row md:px-10 lg:px-10"
>
<div class="mx-auto lg:px-16">
<!-- TODO: use pipe-->
<img
class="relative h-[250px] w-[250px] max-w-none rounded-full"
alt="Profile Image"
[src]="
profileService.getProfileImageSrc(profile.profileImageHash, 250)
"
(error)="handleMissingImage($event)"
/>
</div>
<div class="grow">
<h1 class="page-header">
<span class="text-gray-500">Profil von</span>
{{ profile.dancerName }}
</h1>
<button
class="mb-4 flex items-center gap-2 rounded border border-red-800 fill-red-800 px-3 py-1 text-red-800 transition-colors hover:bg-red-50"
(click)="openChat(profile.id)"
>
<div class="grow-0">
<svg class="h-6 w-6">
<use href="assets/icons/bootstrap-icons.svg#chat-dots" />
</svg>
</div>
<div class="grow-0">Nachricht schreiben</div>
</button>
<app-profile-data-entry
*ngIf="profile.aboutMe"
icon="info-square"
label="Über mich"
class="block border-t"
[value]="profile.aboutMe"
></app-profile-data-entry>
<app-profile-data-entry
*ngIf="profile.city"
icon="buildings"
label="Wohnort"
[value]="profile.city"
></app-profile-data-entry>
<app-profile-data-entry
*ngIf="profile.age"
icon="calendar3"
label="Alter"
[value]="profile.age.toString()"
></app-profile-data-entry>
<app-profile-data-entry
*ngIf="profile.size"
icon="arrows-vertical"
label="Körpergröße"
[value]="profile.size + ' cm'"
></app-profile-data-entry>
<app-profile-data-entry
*ngIf="profile.gender"
icon="gender-ambiguous"
label="Geschlecht"
[value]="profile.gender | displayGender"
></app-profile-data-entry>
<app-profile-data-entry
*ngFor="let danceExperience of profile.ableTo"
icon="music-note-beamed"
label="Tanzerfahrung"
[value]="
danceExperience.dance +
' (' +
(danceExperience.level | displayDanceLevel) +
', ' +
(danceExperience.leading | displayDanceRole) +
')'
"
></app-profile-data-entry>
</div>
</div>
</ng-container>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class PublicProfileComponent {
public readonly activeRoute = inject(ActivatedRoute);
private readonly activeRoute = inject(ActivatedRoute);
public readonly profileService = inject(ProfileService);
private readonly router = inject(Router);

public readonly profileResponse$ = this.profileService.getPublicProfile(
this.activeRoute.snapshot.params['participantId']
);

handleMissingImage($event: ErrorEvent): void {
($event.target as HTMLImageElement).src =
this.profileService.getDefaultProfileImage();
}

openChat(dancerId: string): void {
this.router.navigate(['chat'], {
queryParams: { participantId: dancerId },
});
}
}
1 change: 1 addition & 0 deletions src/app/profile/profile.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { PublicProfileComponent } from './feature/public-profile.component';
export const PROFILE_ROUTES: Routes = [
{
path: 'view/:participantId',
// add guard: only open if not the own profile...
pathMatch: 'full',
component: PublicProfileComponent,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { EnvironmentService } from '@shared/data-access/environment.service';
import { RecommendationsDto } from './types/recommendations.dto';
import {
APIResponse,
asError,
asSuccess,
OldAPIResponse,
} from '@shared/util/http/response.types';
import { catchError, map, Observable, of } from 'rxjs';

Expand All @@ -28,7 +28,7 @@ export class RecommendationHttpService {
this.recommendationsApiUrl = `${this.environment.getApiUrl()}/recommendations`;
}

getRecommendations$(): Observable<APIResponse<RecommendationsDto>> {
getRecommendations$(): Observable<OldAPIResponse<RecommendationsDto>> {
return this.http
.get<RecommendationsDto>(this.recommendationsApiUrl, this.defaultOptions)
.pipe(
Expand Down
Loading

0 comments on commit a8215dd

Please sign in to comment.