Added angular website, with login, registration & searching.

This commit is contained in:
Tom
2025-06-24 18:56:19 +00:00
parent a0e8506027
commit e20231639c
71 changed files with 16742 additions and 0 deletions

View File

@ -0,0 +1,43 @@
.result-item {
background-color: #EEE;
padding: 10px;
border-radius: 15px;
display: flex;
flex-direction: row;
}
.result-info {
margin-left: 10px;
}
.title {
display: inline;
}
.volume {
background-color: hsl(0, 0%, 84%);
display: inline;
margin-left: 10px;
padding: 3px;
border-radius: 4px;
}
.tags {
display: inline-flex;
margin-bottom: 15px;
}
.tag {
padding: 0 5px;
margin: 0 3px;
background-color: rgb(199, 199, 199);
border-radius: 4px;
}
.body {
margin: 5px 10px;
}
.footer {
text-align: right;
}

View File

@ -0,0 +1,18 @@
<div class="result-item">
<img class="result-image" [src]="media().thumbnail" />
<div class="result-info">
<div class="header">
<h2 class="title">{{media().title}}</h2>
@if (media().volume != null) {
<label class="volume">volume {{media().volume}}</label>
}
</div>
<div class="subheader tags">
@for (tag of tags(); track $index) {
<label class="tag">{{tag}}</label>
}
</div>
<p class="body description">{{media().desc}}</p>
<p class="footer">Metadata provided by {{provider()}}</p>
</div>
</div>

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MediaSearchItemComponent } from './media-search-item.component';
describe('MediaSearchItemComponent', () => {
let component: MediaSearchItemComponent;
let fixture: ComponentFixture<MediaSearchItemComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [MediaSearchItemComponent]
})
.compileComponents();
fixture = TestBed.createComponent(MediaSearchItemComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,39 @@
import { Component, computed, input } from '@angular/core';
import { BookSearchResultDto } from '../../shared/dto/book-search-result.dto';
@Component({
selector: 'media-search-item',
standalone: true,
imports: [],
templateUrl: './media-search-item.component.html',
styleUrl: './media-search-item.component.css'
})
export class MediaSearchItemComponent {
media = input.required<BookSearchResultDto>();
tags = computed(() => {
const tags = [];
if (this.media().language)
tags.push(this.media().language);
if (this.media().publisher)
tags.push(this.media().publisher);
if (this.media().categories)
tags.push.apply(tags, this.media().categories);
if (this.media().maturityRating.replaceAll('_', ' '))
tags.push(this.media().maturityRating);
if (this.media().publishedAt) {
tags.push(new Date(this.media().publishedAt).getFullYear());
}
return tags;
});
provider = computed(() => {
const value = this.media().provider;
return value.split(' ')
.map(s => s[0].toUpperCase() + s.substring(1))
.join(' ')
.split('-')
.map(s => s[0].toUpperCase() + s.substring(1))
.join('-');
});
}