diff --git a/src/app/app-module.ts b/src/app/app-module.ts index ec14d8c..970fd36 100644 --- a/src/app/app-module.ts +++ b/src/app/app-module.ts @@ -1,9 +1,10 @@ import { CommonModule } from '@angular/common'; import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; -import { FormsModule } from '@angular/forms'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { BrowserModule } from '@angular/platform-browser'; import { provideHttpClient, withFetch } from '@angular/common/http'; + import { AppRoutingModule } from './app-routing-module'; import { App } from './app'; @@ -12,7 +13,11 @@ import { MatTabsModule } from '@angular/material/tabs'; import { MatToolbarModule } from '@angular/material/toolbar'; import { MatProgressBarModule } from '@angular/material/progress-bar'; import { MatSnackBarModule } from '@angular/material/snack-bar'; - +import { MatAutocompleteModule } from '@angular/material/autocomplete'; +import { MatInputModule } from '@angular/material/input'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatIconButton } from '@angular/material/button'; +import { MatDividerModule } from '@angular/material/divider'; import { HeaderComponent } from './header/header.component'; import { HomeComponent } from './home/home.component'; @@ -34,8 +39,10 @@ import { Header2Component } from './header-2/header-2.component'; import { TheaterOverlayComponent } from './theater-overlay/theater-overlay.component'; import { SeatComponent } from './seat/seat.component'; import { SeatRowComponent } from './seat-row/seat-row.component'; -import {MatIconButton} from '@angular/material/button'; import { TheaterLayoutComponent } from './theater-layout/theater-layout.component'; +import { MovieSearchComponent } from './movie-search/movie-search.component'; +import { ScheduleHeaderComponent } from './schedule-header/schedule-header.component'; +import { MovieScheduleNoSearchResultComponent } from './movie-schedule-no-search-result/movie-schedule-no-search-result.component'; @NgModule({ @@ -60,11 +67,15 @@ import { TheaterLayoutComponent } from './theater-layout/theater-layout.componen TheaterOverlayComponent, SeatComponent, SeatRowComponent, - TheaterLayoutComponent + TheaterLayoutComponent, + MovieSearchComponent, + ScheduleHeaderComponent, + MovieScheduleNoSearchResultComponent ], imports: [ AppRoutingModule, BrowserModule, + ReactiveFormsModule, CommonModule, FormsModule, MatIconModule, @@ -72,7 +83,11 @@ import { TheaterLayoutComponent } from './theater-layout/theater-layout.componen MatToolbarModule, MatProgressBarModule, MatSnackBarModule, - MatIconButton + MatAutocompleteModule, + MatInputModule, + MatFormFieldModule, + MatIconButton, + MatDividerModule ], providers: [ provideBrowserGlobalErrorListeners(), diff --git a/src/app/header-2/header-2.component.html b/src/app/header-2/header-2.component.html index 9545660..ce95d56 100644 --- a/src/app/header-2/header-2.component.html +++ b/src/app/header-2/header-2.component.html @@ -6,7 +6,7 @@
-

+

Absolut war gestern, Bewegung ist heute!

diff --git a/src/app/http.service.ts b/src/app/http.service.ts index 5efe788..91dca64 100644 --- a/src/app/http.service.ts +++ b/src/app/http.service.ts @@ -1,4 +1,4 @@ -import {Kinosaal, Sitzplatz, Vorstellung} from '@infinimotion/model-frontend'; +import { Kinosaal, Sitzplatz, Vorstellung, Film } from '@infinimotion/model-frontend'; import { HttpClient } from "@angular/common/http"; import { inject, Injectable } from "@angular/core"; import { Observable } from "rxjs"; @@ -67,6 +67,13 @@ export class HttpService { } + /* Vorstellung APIs */ + + /* GET /api/film */ + getMovies(): Observable { + return this.http.get(`${this.baseUrl}film`); + } + /* Show-Seats APIs*/ diff --git a/src/app/movie-schedule-no-search-result/movie-schedule-no-search-result.component.css b/src/app/movie-schedule-no-search-result/movie-schedule-no-search-result.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/movie-schedule-no-search-result/movie-schedule-no-search-result.component.html b/src/app/movie-schedule-no-search-result/movie-schedule-no-search-result.component.html new file mode 100644 index 0000000..5685ffe --- /dev/null +++ b/src/app/movie-schedule-no-search-result/movie-schedule-no-search-result.component.html @@ -0,0 +1,5 @@ +
+ search_off +

Keine Vorstellungen gefunden

+

Für '{{ search() }}' finden am {{ date().toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric'} )}} kein Vorstellunge statt.

+
diff --git a/src/app/movie-schedule-no-search-result/movie-schedule-no-search-result.component.ts b/src/app/movie-schedule-no-search-result/movie-schedule-no-search-result.component.ts new file mode 100644 index 0000000..4c91a0b --- /dev/null +++ b/src/app/movie-schedule-no-search-result/movie-schedule-no-search-result.component.ts @@ -0,0 +1,12 @@ +import { Component, input } from '@angular/core'; + +@Component({ + selector: 'app-movie-schedule-no-search-result', + standalone: false, + templateUrl: './movie-schedule-no-search-result.component.html', + styleUrl: './movie-schedule-no-search-result.component.css' +}) +export class MovieScheduleNoSearchResultComponent { + search = input.required(); + date = input.required(); +} diff --git a/src/app/movie-search/movie-search.component.css b/src/app/movie-search/movie-search.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/movie-search/movie-search.component.html b/src/app/movie-search/movie-search.component.html new file mode 100644 index 0000000..add7471 --- /dev/null +++ b/src/app/movie-search/movie-search.component.html @@ -0,0 +1,16 @@ +
+ + Film suchen + + + + + + + + @for (option of filteredOptions | async; track option) { + {{option}} + } + + +
diff --git a/src/app/movie-search/movie-search.component.ts b/src/app/movie-search/movie-search.component.ts new file mode 100644 index 0000000..ad27356 --- /dev/null +++ b/src/app/movie-search/movie-search.component.ts @@ -0,0 +1,62 @@ +import { Component, inject, OnInit, output, ViewEncapsulation } from '@angular/core'; +import { FormControl } from '@angular/forms'; +import { Observable, of } from 'rxjs'; +import { catchError, map, startWith, tap } from 'rxjs/operators'; +import { HttpService } from '../http.service'; + +@Component({ + selector: 'app-movie-search', + standalone: false, + templateUrl: './movie-search.component.html', + styleUrl: './movie-search.component.css', + encapsulation: ViewEncapsulation.None +}) +export class MovieSearchComponent implements OnInit { + + movieSearchResult = output(); + + options: string[] = []; + filteredOptions: Observable = new Observable(); + + searchControl = new FormControl('', (control) => { + if (!control.value) return null; + + const value = control.value.toLowerCase(); + const found = this.options.some(option => + option.toLowerCase().includes(value) + ); + return found ? null : { filmNotFound: true }; + }); + + private http = inject(HttpService) + + ngOnInit() { + this.loadMovies(); + this.filteredOptions = this.searchControl.valueChanges.pipe( + startWith(''), + tap(value => this.movieSearchResult.emit(value || '')), + map(value => this._filter(value || '')) + ); + } + + private _filter(value: string): string[] { + const filterValue = value.toLowerCase(); + return this.options.filter(option => + option.toLowerCase().includes(filterValue) + ); + } + + private loadMovies() { + this.http.getMovies().pipe( + tap(movies => { + this.options = movies + .map(movie => movie.title) + .sort(); + }), + catchError(err => { + console.error('Fehler beim Laden der Filme', err); + return of([]); + }) + ).subscribe(); + } +} diff --git a/src/app/navbar/navbar.component.css b/src/app/navbar/navbar.component.css index 27299ec..7d41e7d 100644 --- a/src/app/navbar/navbar.component.css +++ b/src/app/navbar/navbar.component.css @@ -6,7 +6,7 @@ nav { } .navbar { - width: 200px; + width: 250px; background-color: white; padding: 5px; transition: color .2s; diff --git a/src/app/navbar/navbar.component.html b/src/app/navbar/navbar.component.html index e738b6b..75353b1 100644 --- a/src/app/navbar/navbar.component.html +++ b/src/app/navbar/navbar.component.html @@ -7,7 +7,7 @@ + class="text-2xl pl-3 hover:bg-gray-200 gradient-text rounded-sm"> {{ item.label }} diff --git a/src/app/navbar/navbar.component.ts b/src/app/navbar/navbar.component.ts index ac2bf55..b060804 100644 --- a/src/app/navbar/navbar.component.ts +++ b/src/app/navbar/navbar.component.ts @@ -12,7 +12,7 @@ export class NavbarComponent { */ navItems:{label:string, path:string}[] = [ - {label: 'Schedule', path: '/schedule'}, + {label: 'Programm', path: '/schedule'}, {label: 'Kinosaal-test', path: '/theater-overlay'}, ] } diff --git a/src/app/schedule-header/schedule-header.component.css b/src/app/schedule-header/schedule-header.component.css new file mode 100644 index 0000000..343f510 --- /dev/null +++ b/src/app/schedule-header/schedule-header.component.css @@ -0,0 +1,6 @@ +.schedule-header { + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; +} diff --git a/src/app/schedule-header/schedule-header.component.html b/src/app/schedule-header/schedule-header.component.html new file mode 100644 index 0000000..cfb017f --- /dev/null +++ b/src/app/schedule-header/schedule-header.component.html @@ -0,0 +1,10 @@ +
+
+ event +

+ Programmübersicht +

+
+ +
+ diff --git a/src/app/schedule-header/schedule-header.component.ts b/src/app/schedule-header/schedule-header.component.ts new file mode 100644 index 0000000..8ac6849 --- /dev/null +++ b/src/app/schedule-header/schedule-header.component.ts @@ -0,0 +1,11 @@ +import { Component, output } from '@angular/core'; + +@Component({ + selector: 'app-schedule-header', + standalone: false, + templateUrl: './schedule-header.component.html', + styleUrl: './schedule-header.component.css' +}) +export class ScheduleHeaderComponent { + movieSearchResult = output(); +} diff --git a/src/app/schedule/schedule.component.html b/src/app/schedule/schedule.component.html index cfcd93a..f5924df 100644 --- a/src/app/schedule/schedule.component.html +++ b/src/app/schedule/schedule.component.html @@ -1,9 +1,17 @@ + + @for (dateInfo of dates; track dateInfo.date; let i = $index) { @if (getMovieCount(i) > 0) { - @for (group of dateInfo.performances; track group.movie.id) { - + @if (hasSearchResults(i)) { + @for (group of dateInfo.performances; track group.movie.id) { + @if (group.movie.title.toLowerCase().includes(movieSearchResult.toLowerCase())) { + + } + } + } @else { + } } @else { diff --git a/src/app/schedule/schedule.component.ts b/src/app/schedule/schedule.component.ts index c7bbc7a..88482f3 100644 --- a/src/app/schedule/schedule.component.ts +++ b/src/app/schedule/schedule.component.ts @@ -16,6 +16,8 @@ export class ScheduleComponent implements OnInit { dates: { label: string; date: Date; performances: MovieGroup[] }[] = []; performaces: Vorstellung[] = []; + movieSearchResult: string = ''; + private http = inject(HttpService); private loading = inject(LoadingService) @@ -27,6 +29,14 @@ export class ScheduleComponent implements OnInit { this.loadPerformances(); } + hasSearchResults(dateIndex: number): boolean { + if (!this.movieSearchResult) return true; + + return this.dates[dateIndex].performances.some(group => + group.movie.title.toLowerCase().includes(this.movieSearchResult.toLowerCase()) + ); + } + generateDates() { const today = new Date(); for (let i = 0; i < 14; i++) {