add month calendar

This commit is contained in:
Roland Schneider 2019-09-27 23:03:03 +02:00 committed by Roland Schneider
parent bee08c2092
commit 51788f2194
33 changed files with 698 additions and 25 deletions

View File

@ -5937,6 +5937,11 @@
} }
} }
}, },
"moment": {
"version": "2.24.0",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
},
"move-concurrently": { "move-concurrently": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",

View File

@ -23,6 +23,7 @@
"@fortawesome/fontawesome-svg-core": "^1.2.19", "@fortawesome/fontawesome-svg-core": "^1.2.19",
"@fortawesome/free-solid-svg-icons": "^5.9.0", "@fortawesome/free-solid-svg-icons": "^5.9.0",
"bootstrap": "^4.3.1", "bootstrap": "^4.3.1",
"moment": "^2.24.0",
"ngx-bootstrap": "^5.0.0", "ngx-bootstrap": "^5.0.0",
"rxjs": "~6.4.0", "rxjs": "~6.4.0",
"tslib": "^1.9.0", "tslib": "^1.9.0",

View File

@ -1,23 +1,22 @@
import {Injectable} from "@angular/core"; import {Injectable} from "@angular/core";
import { import {
HttpRequest, HTTP_INTERCEPTORS,
HttpResponse,
HttpHandler,
HttpEvent, HttpEvent,
HttpHandler,
HttpInterceptor, HttpInterceptor,
HTTP_INTERCEPTORS HttpRequest,
HttpResponse
} from '@angular/common/http'; } from '@angular/common/http';
import {Observable, of, throwError} from 'rxjs'; import {Observable, of, throwError} from 'rxjs';
import {delay, mergeMap, materialize, dematerialize} from 'rxjs/operators'; import {delay, dematerialize, materialize, mergeMap} from 'rxjs/operators';
import {Event, EventType, Trainer} from "../services/event.service"; import {DayToDisplay, Event, EventType, Trainer} from "../services/event.service";
import {identifierModuleUrl} from "@angular/compiler"; import * as moment from "moment";
;
/* /*
FAKE BACKEND FAKE BACKEND
This will serve as a standalone backend with delayed response so that it can imitate a real backend - using This will serve as a standalone backend with delayed response so that it can imitate a real backend - using
DELAYED OBSERVABLE DELAYED OBSERVABLE
1. It will check the user credentails that come from "Authentication Service" during login 1. It will check the user credentails that come from "Authentication Service" during login
@ -66,8 +65,7 @@ export class FakeBackendInterceptor implements HttpInterceptor {
name: "weight lift Trainer" name: "weight lift Trainer"
}; };
let events: Event[] = [ let events: Event[] = [];
];
let id = 1000; let id = 1000;
for (let dayIndex = 0; dayIndex < 28; dayIndex++) { for (let dayIndex = 0; dayIndex < 28; dayIndex++) {
@ -75,7 +73,7 @@ export class FakeBackendInterceptor implements HttpInterceptor {
for (let itemIndex = 0; itemIndex < 3; itemIndex++) { for (let itemIndex = 0; itemIndex < 3; itemIndex++) {
id = id + 1; id = id + 1;
let reservedAt = id % 2 ? this.createEventDate(0,1) : null; let reservedAt = id % 2 ? this.createEventDate(0, 1) : null;
events.push( events.push(
{ {
id: id, id: id,
@ -85,7 +83,7 @@ export class FakeBackendInterceptor implements HttpInterceptor {
trainer: [trainer1, trainer2][id % 2], trainer: [trainer1, trainer2][id % 2],
eventType: eventTypes[id % eventTypes.length], eventType: eventTypes[id % eventTypes.length],
reservedAt: reservedAt, reservedAt: reservedAt,
reservationCount: id% 11, reservationCount: id % 11,
seatCount: 10, seatCount: 10,
} }
) )
@ -113,7 +111,7 @@ export class FakeBackendInterceptor implements HttpInterceptor {
firstName: testUser.firstName, firstName: testUser.firstName,
lastName: testUser.lastName, lastName: testUser.lastName,
token: '0000-fake-jwt-token-0000' token: '0000-fake-jwt-token-0000'
} };
return of(new HttpResponse({status: 200, body})) return of(new HttpResponse({status: 200, body}))
} else { } else {
@ -161,6 +159,60 @@ export class FakeBackendInterceptor implements HttpInterceptor {
}); });
} }
} }
if (request.url.endsWith('/events/available') && request.method === 'GET') {
const data = {
days: [],
events: []
};
moment.locale("hu");
let _moment = moment();
const today = _moment.startOf('day');
const startOfWeek = _moment.clone().startOf("week").startOf('day');
const nextDays :DayToDisplay[] = [];
for (let i = 0; i < 21; i++) {
let active = false;
let nextDay = startOfWeek.clone().add(i, 'd').startOf("day");
if (nextDay.isAfter(today) || nextDay.isSameOrAfter(today)) {
active = true;
}
nextDays.push(
{
date: nextDay.toDate().getTime(),
active: active
} as DayToDisplay
);
}
data.days = nextDays;
nextDays.forEach(value => {
value.events = [];
const startOfDay = value.date
const endOfDay = moment(startOfDay).add(1,'d').toDate().getTime();
events.forEach( event => {
if ( event.start >= value.date && event.start < endOfDay){
value.events.push(event);
}
} )
});
//
// const until = nextDays[nextDays.length - 1].toDate().getTime();
// const availableEvents = events.filter(value => {
// return value.start < until;
// });
//
// nextDays.forEach(value => {
// data.days.push(value.toDate().getTime());
// });
// data.events = availableEvents;
return of(new HttpResponse({status: 200, body: data}));
}
if (request.url.indexOf('/events') >= 0 && request.method === 'GET') { if (request.url.indexOf('/events') >= 0 && request.method === 'GET') {
@ -186,8 +238,8 @@ export class FakeBackendInterceptor implements HttpInterceptor {
const length = GET_EVENT.length; const length = GET_EVENT.length;
pos = pos + length; pos = pos + length;
let idEvent = request.url.substr(pos); let idEvent = request.url.substr(pos);
let event = events.find(value => value.id == +idEvent ); let event = events.find(value => value.id == +idEvent);
return of(new HttpResponse({status: 200, body: event }) ); return of(new HttpResponse({status: 200, body: event}));
} else { } else {
// invalid JWT token found in request header // invalid JWT token found in request header
return throwError({ return throwError({
@ -201,9 +253,9 @@ export class FakeBackendInterceptor implements HttpInterceptor {
if (request.headers.get('Authorization') === 'Bearer 0000-fake-jwt-token-0000') { if (request.headers.get('Authorization') === 'Bearer 0000-fake-jwt-token-0000') {
if (request.url.indexOf('event/register&id_event=') && request.method === 'POST') { if (request.url.indexOf('event/register&id_event=') && request.method === 'POST') {
return of(new HttpResponse({status: 200, body: {} }) ); return of(new HttpResponse({status: 200, body: {}}));
}else if (request.url.indexOf('event/cancel&id_event=') && request.method === 'POST') { } else if (request.url.indexOf('event/cancel&id_event=') && request.method === 'POST') {
return of(new HttpResponse({status: 200, body: {} }) ); return of(new HttpResponse({status: 200, body: {}}));
} }
} else { } else {
// invalid JWT token found in request header // invalid JWT token found in request header
@ -232,7 +284,6 @@ export class FakeBackendInterceptor implements HttpInterceptor {
} }
} }
// creating a PROVIDER // creating a PROVIDER
export let fakeBackendProvider = { export let fakeBackendProvider = {
// use fake backend in place of Http service for backend-less development // use fake backend in place of Http service for backend-less development

View File

@ -1,3 +1,4 @@
export * from './error.interceptor'; export * from './error.interceptor';
export * from './fake-backend'; export * from './fake-backend';
export * from './jwt.interceptor'; export * from './jwt.interceptor';
export {DayToDisplay} from "../services/event.service";

View File

@ -5,6 +5,7 @@ import {LoginComponent} from "./pages/login/login.component";
import {ProfileComponent} from "./pages/profile/profile.component"; import {ProfileComponent} from "./pages/profile/profile.component";
import {AuthGuard} from "./_guards"; import {AuthGuard} from "./_guards";
import {EventsComponent} from "./pages/events/events.component"; import {EventsComponent} from "./pages/events/events.component";
import {EventDetailsComponent} from "./pages/event-details/event-details.component";
const routes: Routes = [ const routes: Routes = [
{ path: 'home', component: HomeComponent }, { path: 'home', component: HomeComponent },
@ -13,6 +14,7 @@ const routes: Routes = [
{ path: 'logout', redirectTo: '/login' , pathMatch: 'full'}, { path: 'logout', redirectTo: '/login' , pathMatch: 'full'},
{ path: 'profile', component: ProfileComponent, canActivate: [AuthGuard] }, { path: 'profile', component: ProfileComponent, canActivate: [AuthGuard] },
{ path: 'events', component: EventsComponent, canActivate: [AuthGuard] }, { path: 'events', component: EventsComponent, canActivate: [AuthGuard] },
{ path: 'event-details/:idEvent', component: EventDetailsComponent, canActivate: [AuthGuard] , pathMatch: 'full' },
]; ];
@NgModule({ @NgModule({

View File

@ -23,6 +23,11 @@ import {FontAwesomeModule} from "@fortawesome/angular-fontawesome";
import { library } from '@fortawesome/fontawesome-svg-core'; import { library } from '@fortawesome/fontawesome-svg-core';
import { faUserPlus , faUserMinus } from '@fortawesome/free-solid-svg-icons'; import { faUserPlus , faUserMinus } from '@fortawesome/free-solid-svg-icons';
import { FitWeekdaySelectorComponent } from './components/fit-weekday-selector/fit-weekday-selector.component';
import { MonthCalendarComponent } from './components/month-calendar/month-calendar.component';
import { MonthCalendarDayComponent } from './components/month-calendar-day/month-calendar-day.component';
import { MonthCalendarEventComponent } from './components/month-calendar-event/month-calendar-event.component';
import { EventDetailsComponent } from './pages/event-details/event-details.component';
@ -40,6 +45,11 @@ registerLocaleData(localeHu, 'hu');
ProfileComponent, ProfileComponent,
EventsComponent, EventsComponent,
FitEventTypesComponent, FitEventTypesComponent,
FitWeekdaySelectorComponent,
MonthCalendarComponent,
MonthCalendarDayComponent,
MonthCalendarEventComponent,
EventDetailsComponent,
], ],
imports: [ imports: [
BrowserModule, BrowserModule,

View File

@ -0,0 +1,11 @@
<p>fit-weekday-selector works!</p>
<div *ngIf="days" class="row">
<div class="col-md-3" *ngFor="let nextDay of days ">
<p>
{{ formatDayName( nextDay ) }}
</p>
<p>
{{ formatDate( nextDay ) }}
</p>
</div>
</div>

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { FitWeekdaySelectorComponent } from './fit-weekday-selector.component';
describe('FitWeekdaySelectorComponent', () => {
let component: FitWeekdaySelectorComponent;
let fixture: ComponentFixture<FitWeekdaySelectorComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ FitWeekdaySelectorComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(FitWeekdaySelectorComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,29 @@
import {Component, Input, OnInit} from '@angular/core';
import * as moment from 'moment';
@Component({
selector: 'app-fit-weekday-selector',
templateUrl: './fit-weekday-selector.component.html',
styleUrls: ['./fit-weekday-selector.component.scss']
})
export class FitWeekdaySelectorComponent implements OnInit {
@Input()
days: number[] = [];
constructor() { }
ngOnInit() {
moment.locale("hu");
}
formatDayName(dateNum){
return moment(dateNum).format("dddd");
}
formatDate(dateNum){
return moment(dateNum).format("YYYY-MM-DD");
}
}

View File

@ -0,0 +1,15 @@
<h5 class="row align-items-center">
<span class="date col-1">{{getDateOfDay()}}</span>
<small class="col d-sm-none text-center text-muted">{{getDayOfWeekName()}}</small>
<span class="col-1"></span>
</h5>
<p *ngIf="!hasEvents()" class="d-sm-none">No events</p>
<ng-container *ngIf="hasEvents()">
<app-month-calendar-event
*ngFor="let event of day.events"
[event]="event"
(onEvent)="handleEvent($event)"
></app-month-calendar-event>
</ng-container>

View File

@ -0,0 +1,20 @@
@media (max-width:575px) {
.display-4 {
font-size: 1.5rem;
}
.day h5 {
background-color: #f8f9fa;
padding: 3px 5px 5px;
margin: -8px -8px 8px -8px;
}
.date {
padding-left: 16px;
}
}
@media (min-width: 576px) {
.day {
min-height: 14.2857vw;
}
}

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { MonthCalendarDayComponent } from './month-calendar-day.component';
describe('MonthCalendarDayComponent', () => {
let component: MonthCalendarDayComponent;
let fixture: ComponentFixture<MonthCalendarDayComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ MonthCalendarDayComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MonthCalendarDayComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,54 @@
import {Component, EventEmitter, HostBinding, Input, OnInit, Output} from '@angular/core';
import {dateToMoment, Day, MonthCalendarEvent} from "../month-calendar/month-calendar.component";
import {DayToDisplay} from "../../_helpers";
@Component({
selector: '[app-month-calendar-day]',
templateUrl: './month-calendar-day.component.html',
styleUrls: ['./month-calendar-day.component.scss']
})
export class MonthCalendarDayComponent implements OnInit {
@Input()
day: DayToDisplay;
@Output()
onEvent: EventEmitter<MonthCalendarEvent> = new EventEmitter<MonthCalendarEvent>();
oMoment: any;
constructor() { }
ngOnInit() {
if ( this.day ){
console.info(this.day);
this.oMoment = dateToMoment(this.day.date);
}
}
getDayOfWeekName(){
return this.oMoment.format('dddd');
}
getDateOfDay(){
return this.oMoment.format('DD');
}
hasEvents(){
return this.day.active && this.day.events && this.day.events.length;
}
@HostBinding('class') get styleClass(){
let styleClass = "day col-sm p-2 border border-left-0 border-top-0 text-truncate";
if ( !this.day.active ){
styleClass += " d-none d-sm-inline-block bg-light text-muted";
}
return styleClass;
}
handleEvent($event){
this.onEvent.emit($event);
}
}

View File

@ -0,0 +1,9 @@
<a
(click)="selectEvent()"
class="event d-block p-1 pl-2 pr-2 mb-1 rounded text-truncate small bg-success text-white" title="Test Event 2">
{{formatTime()}}:{{event.eventType.name}}
<ng-container *ngIf="hasTrainer()">
<br>
{{formatTrainer()}}
</ng-container>
</a>

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { MonthCalendarEventComponent } from './month-calendar-event.component';
describe('MonthCalendarEventComponent', () => {
let component: MonthCalendarEventComponent;
let fixture: ComponentFixture<MonthCalendarEventComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ MonthCalendarEventComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MonthCalendarEventComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,44 @@
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {Event} from "../../services/event.service";
import * as moment from "moment";
import {MonthCalendarEvent} from "../month-calendar/month-calendar.component";
@Component({
selector: 'app-month-calendar-event',
templateUrl: './month-calendar-event.component.html',
styleUrls: ['./month-calendar-event.component.scss']
})
export class MonthCalendarEventComponent implements OnInit {
@Input()
event: Event;
@Output()
onEvent = new EventEmitter<MonthCalendarEvent>();
constructor() {
}
ngOnInit() {
}
formatTime() {
return moment(this.event.start).format('HH:mm');
}
hasTrainer() {
return !!this.event.trainer;
}
formatTrainer() {
const trainer = this.event.trainer;
return trainer.name;
}
selectEvent() {
this.onEvent.emit({
type: 'SELECT_EVENT',
event: this.event
})
}
}

View File

@ -0,0 +1,15 @@
<div class="container-fluid">
<header>
<h4 class="display-4 mb-4 text-center">Naptár</h4>
<div class="row d-none d-sm-flex p-1 bg-dark text-white">
<h5 *ngFor="let dayOfWeek of daysOfWeek" class="col-sm p-1 text-center name-of-day-of-week">{{dayOfWeek.name}}</h5>
</div>
</header>
<div *ngIf="eventsAvailableResponse" class="row border border-right-0 border-bottom-0">
<ng-container *ngFor="let day of eventsAvailableResponse.days; let i = index">
<div app-month-calendar-day [day]="day" (onEvent)="handleEvent($event)" ></div>
<div *ngIf="i > 0 && ( ((i+1) % 7) == 0)" class="w-100"></div>
</ng-container>
</div>
</div>

View File

@ -0,0 +1,22 @@
@media (max-width:575px) {
.display-4 {
font-size: 1.5rem;
}
.day h5 {
background-color: #f8f9fa;
padding: 3px 5px 5px;
margin: -8px -8px 8px -8px;
}
.date {
padding-left: 4px;
}
}
@media (min-width: 576px) {
.day {
min-height: 14.2857vw;
}
}
.name-of-day-of-week{
text-transform: capitalize;
}

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { MonthCalendarComponent } from './month-calendar.component';
describe('MonthCalendarComponent', () => {
let component: MonthCalendarComponent;
let fixture: ComponentFixture<MonthCalendarComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ MonthCalendarComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MonthCalendarComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,91 @@
import {Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges} from '@angular/core';
import {Event, EventsAvailableResponse} from "../../services/event.service";
import * as moment from "moment";
@Component({
selector: 'app-month-calendar',
templateUrl: './month-calendar.component.html',
styleUrls: ['./month-calendar.component.scss']
})
export class MonthCalendarComponent implements OnInit, OnChanges {
minDate: number;
maxDate: number;
daysOfWeek: DayOfWeek[];
days: Day[];
@Input()
eventsAvailableResponse: EventsAvailableResponse;
@Output()
onEvent: EventEmitter<MonthCalendarEvent> = new EventEmitter<MonthCalendarEvent>();
constructor( ) { }
ngOnInit() {
moment.locale('hu');
//
this.fillDaysOfWeek();
//
// let firstDay = moment().startOf('week');
//
// this.days = [];
// if ( this.eventsAvailableResponse ){
//
// for ( let i = 0; i < this.eventsAvailableResponse.days.length; i++){
// this.days.push({
// date: this.eventsAvailableResponse.days[i],
// events: [],
// active: true
// })
// }
// }
}
fillDaysOfWeek(){
this.daysOfWeek = [];
let startOfWeek = moment().startOf("week");
for ( let i = 0; i < 7 ; i++ ){
let momWeekDay = startOfWeek.clone().add(i,'d');
const dayOfWeek = {
name: momWeekDay.format("dddd"),
};
this.daysOfWeek.push(dayOfWeek);
}
}
ngOnChanges(changes: SimpleChanges): void {
console.info(changes);
if ( changes.hasOwnProperty('eventsAvailableResponse')){
}
}
handleEvent($event){
this.onEvent.emit($event);
}
}
export interface Day {
date: number;
events: Event[];
active: boolean;
}
export interface DayOfWeek {
name: string;
}
export function dateToMoment(date: number) {
return moment(date);
}
export interface MonthCalendarEvent {
type: string; // type of the month calendar event
event: Event; // the fitness event
}

View File

@ -0,0 +1,36 @@
<div class="container" *ngIf="event">
<div class="row">
<div class="col-lg-3 col-sm-12"><span class="title">Edzés típusa</span></div>
<div class="col-lg-9 col-sm-12"><span>{{event.eventType.name}}</span></div>
</div>
<div class="row" *ngIf="event.trainer">
<div class="col-lg-3 col-sm-12"><span class="title">Edző</span></div>
<div class="col-lg-9 col-sm-12"><span>{{event.trainer.name}}</span></div>
</div>
<div class="row">
<div class="col-lg-3 col-sm-12"><span class="title">Edzés kezdési időpontja</span></div>
<div class="col-lg-9 col-sm-12"><span>{{event.start | date:'yyyy.MM.dd HH:mm'}}</span></div>
</div>
<div class="row">
<div class="col-lg-3 col-sm-12"><span class="title">Edzés vége</span></div>
<div class="col-lg-9 col-sm-12"><span>{{event.end | date:'yyyy.MM.dd HH:mm'}}</span></div>
</div>
<div class="row">
<div class="col-lg-3 col-sm-12"><span class="title">Férőhelyek száma</span></div>
<div class="col-lg-9 col-sm-12"><span>{{event.seatCount }}</span></div>
</div>
<!-- <div class="row">-->
<!-- <div class="col-lg-3 col-sm-12"><span class="title">Szabad helyek száma</span></div>-->
<!-- <div class="col-lg-9 col-sm-12"><span>{{event.seatCount - event.reservationCount }}</span></div>-->
<!-- </div>-->
<div class="row">
<div class="col-lg-9 col-sm-12 pt-2">
<a *ngIf="mayRegister(event)" class="btn btn-primary " (click)="register(event)" >Foglalás</a>
<a *ngIf="mayCancel(event)" class="btn btn-primary" (click)="cancel(event)" >Lemondás</a>
<span *ngIf="!mayCancel(event) && noFreeSeat(event)">Már nincs szabad hely</span>
</div>
<div class="col-lg-3 text-lg-right col-sm-12 pt-2">
<a class="btn btn-primary " (click)="goBack(event)" >Vissza</a>
</div>
</div>
</div>

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { EventDetailsComponent } from './event-details.component';
describe('EventDetailsComponent', () => {
let component: EventDetailsComponent;
let fixture: ComponentFixture<EventDetailsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ EventDetailsComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(EventDetailsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,53 @@
import { Component, OnInit } from '@angular/core';
import {Event, EventService} from "../../services/event.service";
import {ActivatedRoute, RouterState} from "@angular/router";
import {NavigationService} from "../../services/navigation.service";
@Component({
selector: 'app-event-details',
templateUrl: './event-details.component.html',
styleUrls: ['./event-details.component.scss']
})
export class EventDetailsComponent implements OnInit {
event: Event;
constructor(
private eventService: EventService,
private route: ActivatedRoute,
private navigationService: NavigationService
) { }
ngOnInit() {
let idEvent = +this.route.snapshot.paramMap.get('idEvent');
this.eventService.findEvent(idEvent).subscribe(
value => this.event = value
);
}
mayRegister(event: Event) {
return event.reservedAt == null && event.reservationCount < event.seatCount;
}
mayCancel(event: Event) {
return event.reservedAt;
}
noFreeSeat(event: Event) {
return event.reservedAt == null && event.reservationCount >= event.seatCount;
}
goBack(event: Event) {
this.navigationService.navigateToHome();
}
register(event: Event) {
}
cancel(event: Event) {
}
}

View File

@ -1 +1,9 @@
<p>home works!</p> <div class="container">
<!-- <app-fit-weekday-selector [days]="(availableEvents | async)?.days" ></app-fit-weekday-selector>-->
<ng-container *ngIf="availableEvents | async">
<app-month-calendar
(onEvent)="handleEvent($event)"
[eventsAvailableResponse]="availableEvents | async "></app-month-calendar>
</ng-container>
</div>

View File

@ -1,4 +1,8 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import {EventsAvailableResponse, EventService} from "../../services/event.service";
import {Observable} from "rxjs";
import {MonthCalendarEvent} from "../../components/month-calendar/month-calendar.component";
import {NavigationService} from "../../services/navigation.service";
@Component({ @Component({
selector: 'app-home', selector: 'app-home',
@ -7,9 +11,20 @@ import { Component, OnInit } from '@angular/core';
}) })
export class HomeComponent implements OnInit { export class HomeComponent implements OnInit {
constructor() { } availableEvents: Observable<EventsAvailableResponse>;
constructor(private eventService: EventService,
private navigationService: NavigationService) { }
ngOnInit() { ngOnInit() {
this.availableEvents = this.eventService.findEventsAvailable();
} }
handleEvent($event: MonthCalendarEvent) {
console.info($event);
this.navigationService.navigateToEventDetails($event.event.id);
}
} }

View File

@ -29,4 +29,9 @@ export class Endpoints {
return `${this.baseUrl}/event-type`; return `${this.baseUrl}/event-type`;
} }
public static GET_EVENTS_AVAILABLE(){
return `${this.baseUrl}/events/available`;
}
} }

View File

@ -1,7 +1,8 @@
import { Injectable } from '@angular/core'; import {Injectable} from '@angular/core';
import {HttpClient} from "@angular/common/http"; import {HttpClient} from "@angular/common/http";
import {Endpoints} from "./endpoints"; import {Endpoints} from "./endpoints";
import {Observable} from "rxjs"; import {Observable} from "rxjs";
import {DayToDisplay} from "../_helpers";
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@ -31,6 +32,10 @@ export class EventService {
return this.http.post(Endpoints.POST_EVENT_CANCEL( idEvent ),{}) as Observable<Event>; return this.http.post(Endpoints.POST_EVENT_CANCEL( idEvent ),{}) as Observable<Event>;
} }
findEventsAvailable(): Observable<EventsAvailableResponse>{
return this.http.get(Endpoints.GET_EVENTS_AVAILABLE()) as Observable<EventsAvailableResponse>;
}
} }
export interface Trainer { export interface Trainer {
@ -55,4 +60,14 @@ export interface EventType {
name: string; name: string;
} }
export interface DayToDisplay {
date: number;
active: true;
events: Event[];
}
export interface EventsAvailableResponse {
days: DayToDisplay[];
events: Event[];
}

View File

@ -0,0 +1,12 @@
import { TestBed } from '@angular/core/testing';
import { NavigationService } from './navigation.service';
describe('NavigationService', () => {
beforeEach(() => TestBed.configureTestingModule({}));
it('should be created', () => {
const service: NavigationService = TestBed.get(NavigationService);
expect(service).toBeTruthy();
});
});

View File

@ -0,0 +1,24 @@
import { Injectable } from '@angular/core';
import {NavigationExtras, Router} from "@angular/router";
@Injectable({
providedIn: 'root'
})
export class NavigationService {
constructor(private navigation: Router) { }
public navigate(commands: any[], extras?: NavigationExtras){
this.navigation.navigate( commands,extras );
}
public navigateToEventDetails(idEvent: number){
this.navigate(['/event-details/'+idEvent ])
}
public navigateToHome(){
this.navigate(['/home' ])
}
}

View File

@ -36,7 +36,7 @@ body{
background: #e5ce48; background: #e5ce48;
border: 1px solid #e5ce48; border: 1px solid #e5ce48;
color: #000; } color: #000; }
.btn.btn-primary:hover { .btn.btn-primary:hover,.btn.btn-primary:active, .btn-primary:not(:disabled):not(.disabled):active {
border: 1px solid #e5ce48; border: 1px solid #e5ce48;
background: transparent; background: transparent;
color: #e5ce48; } color: #e5ce48; }