Skip to content

Commit d18dcee

Browse files
committed
feat: update album element view component
- add necessary model - update component to new backend functionality
1 parent 616b7da commit d18dcee

File tree

7 files changed

+226
-32
lines changed

7 files changed

+226
-32
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import {AlbumMinDetailsModel} from "../../album/albums-view/album-min-details.model";
2+
3+
export interface AlbumElementViewGetModel {
4+
id: string;
5+
name: string;
6+
description: string;
7+
rate: number;
8+
imageUrl: string;
9+
album: AlbumMinDetailsModel;
10+
updatedAt: string;
11+
createdAt: string;
12+
}

src/CoinyProject.Client/src/app/album-element/album-element-view/album-element-view.component.css

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<div class="container mx-auto px-20 py-8">
2+
<div class="px-4">
3+
4+
<div *ngIf="!element; else albumSection">
5+
<app-item-no-found></app-item-no-found>
6+
</div>
7+
8+
<ng-template #albumSection>
9+
<div *ngIf="element" class="bg-pastel-yellow-white shadow-md rounded-lg p-6">
10+
<div class="flex flex-col lg:flex-row justify-between items-start lg:items-center lg:space-x-8">
11+
<!-- Left Section: Album Details -->
12+
<div class="lg:w-2/3 pr-6">
13+
<!-- Album Name -->
14+
<h2 class="text-3xl font-bold text-yellow-600 mb-4">{{ element.name }}</h2>
15+
16+
<!-- Album Details -->
17+
<div class="text-gray-700">
18+
<p class="mb-4">
19+
<span class="font-bold">Description: </span>{{ element.description || 'No description available' }}
20+
</p>
21+
22+
<p class="mb-4">
23+
<span class="font-bold text-yellow-600">Rate: </span>{{ element.rate }}
24+
</p>
25+
26+
<p class="mb-4">
27+
<span class="font-bold text-yellow-600">Author: </span>
28+
<a [routerLink]="['/profile', element.album.author.id]" class="text-yellow-600 hover:text-yellow-500 transition">
29+
{{ element.album.author.username }}
30+
</a>
31+
</p>
32+
33+
<p class="mb-4">
34+
<span class="font-bold text-yellow-600">Album: </span>
35+
<a [routerLink]="['/album', element.album.id]" class="text-yellow-600 hover:text-yellow-500 transition">
36+
{{ element.album.name }}
37+
</a>
38+
</p>
39+
40+
<p class="mb-4">
41+
<span class="font-bold text-gray-700">Updated At: </span>{{ element.updatedAt | date: 'dd MMM yyyy, HH:mm' }}
42+
</p>
43+
44+
<p>
45+
<span class="font-bold text-gray-700">Created At: </span>{{ element.createdAt | date: 'dd MMM yyyy, HH:mm' }}
46+
</p>
47+
</div>
48+
</div>
49+
50+
<!-- Right Section: Image and Buttons -->
51+
<div class="lg:w-1/3 flex flex-col items-center mt-6 lg:mt-0">
52+
<!-- Edit and Delete Buttons if 'my=true' -->
53+
<div *ngIf="isMyAlbumElement" class="flex justify-end mb-4 w-full mr-20">
54+
<button (click)="editAlbumElement()"
55+
class="px-4 py-2 bg-yellow-500 text-white font-semibold rounded-lg hover:bg-yellow-600 transition duration-300 mr-2">
56+
Edit
57+
</button>
58+
<button (click)="openModal()"
59+
class="px-4 py-2 bg-red-500 text-white font-semibold rounded-lg hover:bg-red-600 transition duration-300">
60+
Delete
61+
</button>
62+
63+
<!-- Include the modal component for deactivation -->
64+
<app-modal
65+
[title]="'Confirm Deleting'"
66+
[message]="'Are you sure you want to delete this album?'"
67+
[isOpen]="isModalOpen"
68+
[errorMessage]="errorMessage"
69+
(onConfirm)="confirmDelete()"
70+
(onCancel)="closeModal()">
71+
</app-modal>
72+
</div>
73+
74+
<!-- Image Section -->
75+
<div class="relative w-64 h-64 border-4 border-yellow-500 rounded-lg overflow-hidden shadow-md">
76+
<img [src]="element.imageUrl" alt="Album Element Image"
77+
class="absolute inset-0 h-full w-full object-cover"/>
78+
</div>
79+
</div>
80+
</div>
81+
</div>
82+
</ng-template>
83+
</div>
84+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import {Component, OnInit} from '@angular/core';
2+
import {AlbumGetDto} from "../../album/albums-view/album-get.model";
3+
import {UserModel} from "../../services/user.model";
4+
import {ActivatedRoute, Router, RouterLink} from "@angular/router";
5+
import {AlbumService} from "../../services/album.service";
6+
import {AuthService} from "../../services/auth.service";
7+
import {AlbumElementsComponent} from "../album-elements/album-elements.component";
8+
import {DatePipe, NgClass, NgIf} from "@angular/common";
9+
import {ItemNoFoundComponent} from "../../shared/item-no-found/item-no-found.component";
10+
import {ModalComponent} from "../../shared/modal/modal.component";
11+
import {AlbumElementService} from "../../services/album-element.service";
12+
import {AlbumElementViewGetModel} from "./album-element-view-get.model";
13+
14+
@Component({
15+
selector: 'app-album-element-view',
16+
standalone: true,
17+
imports: [
18+
AlbumElementsComponent,
19+
DatePipe,
20+
ItemNoFoundComponent,
21+
ModalComponent,
22+
NgIf,
23+
NgClass,
24+
RouterLink
25+
],
26+
templateUrl: './album-element-view.component.html',
27+
styleUrl: './album-element-view.component.css'
28+
})
29+
export class AlbumElementViewComponent implements OnInit {
30+
element: AlbumElementViewGetModel | null = null;
31+
isMyAlbumElement: boolean = false;
32+
isModalOpen = false;
33+
errorMessage = '';
34+
35+
user: UserModel | undefined;
36+
37+
constructor(
38+
private route: ActivatedRoute,
39+
private albumService: AlbumService,
40+
private albumElementService: AlbumElementService,
41+
private router: Router,
42+
private authService: AuthService
43+
) {}
44+
45+
ngOnInit(): void {
46+
const albumElementId = this.route.snapshot.paramMap.get('id');
47+
48+
if (albumElementId) {
49+
this.albumElementService.getAlbumElementById(albumElementId).subscribe({
50+
next: (element) => {
51+
this.element = element;
52+
this.isMyAlbumElement = this.ifCurrentUserIsOwner();
53+
},
54+
error: (err) => {
55+
this.errorMessage = `Failed to load album element (${err.status})`;
56+
console.error('Failed to load album element:', err);
57+
},
58+
});
59+
}
60+
}
61+
62+
// Handle Edit button
63+
64+
ifCurrentUserIsOwner(): boolean {
65+
this.authService.user().subscribe(user => {
66+
this.user = user;
67+
});
68+
69+
if (this.user && this.element) {
70+
return this.element.album.author.id === this.user.id;
71+
}
72+
return false;
73+
}
74+
editAlbumElement(): void {
75+
if (this.element) {
76+
this.router.navigate(['/album-element-edit', this.element.id]).then(r =>
77+
console.log('Edit album element:', r));
78+
}
79+
}
80+
81+
openModal(): void {
82+
this.isModalOpen = true;
83+
}
84+
85+
closeModal(): void {
86+
this.isModalOpen = false;
87+
}
88+
89+
confirmDelete(): void {
90+
if (this.element) {
91+
this.albumElementService.deleteAlbumElement(this.element.id).subscribe({
92+
next: () => {
93+
this.router.navigate(['/profile'], { queryParams: { my: true } }).then(() => {
94+
console.log('Album element deleted');
95+
});
96+
97+
this.closeModal();
98+
},
99+
error: (err) => {
100+
this.errorMessage = `Failed to delete album element(${err.status})`;
101+
console.error('Failed to delete album element:', err);
102+
},
103+
});
104+
}
105+
}
106+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import {UsernameModel} from "../../services/username.model";
2+
3+
export interface AlbumMinDetailsModel {
4+
id: string;
5+
name: string;
6+
author: UsernameModel;
7+
}

src/CoinyProject.Client/src/app/app.routes.ts

+7
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {AlbumFormComponent} from "./album/album-form/album-form.component";
77
import {authGuard} from "./guards/auth.guard";
88
import {ProfileComponent} from "./profile/profile.component";
99
import {AlbumViewComponent} from "./album/album-view/album-view.component";
10+
import {AlbumElementViewComponent} from "./album-element/album-element-view/album-element-view.component";
1011

1112
export const routes: Routes = [
1213
{ path: '', redirectTo: 'albums', pathMatch: 'full' },
@@ -41,6 +42,12 @@ export const routes: Routes = [
4142
component: AlbumViewComponent,
4243
canActivate: [authGuard],
4344
data: { roles: ['User'] }
45+
},
46+
{
47+
path: 'album-element/:id',
48+
component: AlbumElementViewComponent,
49+
canActivate: [authGuard],
50+
data: { roles: ['User'] }
4451
}
4552

4653
]

src/CoinyProject.Client/src/app/services/album-element.service.ts

+10-32
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {AlbumPostDto} from "../album/album-form/album-post.model";
77
import {AlbumPatchDto} from "../album/album-form/album-patch.model";
88
import {AlbumGetDto} from "../album/albums-view/album-get.model";
99
import {AlbumElementGetModel} from "../album-element/album-elements/album-element-get.model";
10+
import {AlbumElementViewGetModel} from "../album-element/album-element-view/album-element-view-get.model";
1011

1112
@Injectable({
1213
providedIn: 'root'
@@ -28,33 +29,17 @@ export class AlbumElementService {
2829
params = params.append('search', search);
2930
}
3031
params = params.append('addAuth', 'true');
31-
/*if (isCurrentUser) {
32-
params = params.append('addAuth', 'true');
33-
}*/
32+
3433
return this.http.get<PagedResponse<AlbumElementGetModel>>(`${this.baseUrl}/by-album/${albumId}`, {params});
3534
}
3635

37-
getPagedAlbumsByUser(userId: string | null, page: number, size: number, sortItem: string, isAscending: boolean, search: string | null = null): Observable<PagedResponse<AlbumViewGetDto>> {
38-
let params = new HttpParams();
39-
if (userId) {
40-
params = params.append('userId', userId);
41-
}
42-
else {
43-
params = params.append('addAuth', 'true');
44-
}
45-
46-
params = params.append('page', page.toString());
47-
params = params.append('size', size.toString(),);
48-
params = params.append('sortItem', sortItem);
49-
params = params.append('isAscending', isAscending.toString());
50-
51-
if (search) {
52-
params = params.append('search', search);
53-
}
54-
55-
return this.http.get<PagedResponse<AlbumViewGetDto>>(`${this.baseUrl}/by-user`, { params });
36+
// Get album element by ID
37+
getAlbumElementById(id: string): Observable<AlbumElementViewGetModel> {
38+
const params = {
39+
addAuth: true.toString()
40+
};
41+
return this.http.get<AlbumElementViewGetModel>(`${this.baseUrl}/${id}`, {params});
5642
}
57-
5843
// Create a new album
5944
addAlbum(album: AlbumPostDto): Observable<AlbumGetDto> {
6045
return this.http.post<AlbumGetDto>(`${this.baseUrl}?addAuth=true`, album);
@@ -65,20 +50,13 @@ export class AlbumElementService {
6550
return this.http.patch<AlbumGetDto>(`${this.baseUrl}/${id}?addAuth=true`, album);
6651
}
6752

68-
// Get album by ID
69-
getAlbumById(id: string): Observable<AlbumGetDto> {
70-
const params = {
71-
addAuth: true.toString()
72-
};
73-
return this.http.get<AlbumGetDto>(`${this.baseUrl}/${id}`, {params});
74-
}
7553

7654
// Deactivate album by ID
77-
deactivateAlbum(id: string): Observable<void> {
55+
deleteAlbumElement(id: string): Observable<void> {
7856
const params = {
7957
addAuth: true.toString()
8058
};
81-
return this.http.post<void>(`${this.baseUrl}/${id}/deactivate`, null, {params});
59+
return this.http.delete<void>(`${this.baseUrl}/${id}`, {params});
8260
}
8361

8462
activateAlbum(id: string): Observable<void> {

0 commit comments

Comments
 (0)