diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 42f4e47..2bf9e76 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -23,7 +23,9 @@ "@angular/router": "^16.2.7", "angular-calendar": "^0.31.0", "date-fns": "^2.29.3", + "luxon": "^3.4.3", "moment": "^2.29.4", + "ngx-material-timepicker": "^13.1.1", "rxjs": "~7.5.0", "tslib": "^2.3.0", "zone.js": "~0.13.3" @@ -4395,6 +4397,12 @@ "integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==", "dev": true }, + "node_modules/@types/luxon": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.3.4.tgz", + "integrity": "sha512-H9OXxv4EzJwE75aTPKpiGXJq+y4LFxjpsdgKwSmr503P5DkWc3AG7VAFYrFNVvqemT5DfgZJV9itYhqBHSGujA==", + "peer": true + }, "node_modules/@types/mime": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.3.tgz", @@ -9170,6 +9178,14 @@ "yallist": "^3.0.2" } }, + "node_modules/luxon": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.3.tgz", + "integrity": "sha512-tFWBiv3h7z+T/tDaoxA8rqTxy1CHV6gHS//QdaH4pulbq/JuBSGgQspQQqcgnwdAx6pNI7cmvz5Sv/addzHmUg==", + "engines": { + "node": ">=12" + } + }, "node_modules/magic-string": { "version": "0.30.1", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.1.tgz", @@ -9737,6 +9753,18 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "node_modules/ngx-material-timepicker": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/ngx-material-timepicker/-/ngx-material-timepicker-13.1.1.tgz", + "integrity": "sha512-GST4IBFXrPSBB5VP5LVxoOk1yHbdSnaB293tjuyu+vusg+pQ/3+AtcxQEIadk6Nmsdt8zKsbXNgvLrI4nbYRKQ==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@types/luxon": ">= 1.11.1", + "luxon": ">= 1.24.0" + } + }, "node_modules/nice-napi": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", diff --git a/frontend/package.json b/frontend/package.json index 5e11c63..eabd35d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -25,7 +25,9 @@ "@angular/router": "^16.2.7", "angular-calendar": "^0.31.0", "date-fns": "^2.29.3", + "luxon": "^3.4.3", "moment": "^2.29.4", + "ngx-material-timepicker": "^13.1.1", "rxjs": "~7.5.0", "tslib": "^2.3.0", "zone.js": "~0.13.3" diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index 65cc369..4016609 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -75,6 +75,8 @@ import { OverdueTaskOverviewComponent } from './overdue-task-overview/overdue-ta import { UpcomingTaskOverviewComponent } from './upcoming-task-overview/upcoming-task-overview.component'; import { ActiveTaskOverviewComponent } from './active-task-overview/active-task-overview.component'; import { AdvancedSchedulerComponent } from './schedules/advanced-scheduler/advanced-scheduler.component'; +import {NgxMaterialTimepickerModule} from "ngx-material-timepicker"; +import { DateTimePickerComponent } from './date-time-picker/date-time-picker.component'; @NgModule({ declarations: [ AppComponent, @@ -112,7 +114,8 @@ import { AdvancedSchedulerComponent } from './schedules/advanced-scheduler/advan OverdueTaskOverviewComponent, UpcomingTaskOverviewComponent, ActiveTaskOverviewComponent, - AdvancedSchedulerComponent + AdvancedSchedulerComponent, + DateTimePickerComponent ], imports: [ BrowserModule, @@ -149,7 +152,8 @@ import { AdvancedSchedulerComponent } from './schedules/advanced-scheduler/advan CalendarModule.forRoot({provide: DateAdapter, useFactory: adapterFactory}), MatSelectModule, MatTreeModule, - MatAutocompleteModule + MatAutocompleteModule, + NgxMaterialTimepickerModule ], providers: [ HttpClientModule, diff --git a/frontend/src/app/date-time-picker/date-time-picker.component.css b/frontend/src/app/date-time-picker/date-time-picker.component.css new file mode 100644 index 0000000..d62f37f --- /dev/null +++ b/frontend/src/app/date-time-picker/date-time-picker.component.css @@ -0,0 +1,3 @@ +mat-form-field { + width: 50%; +} diff --git a/frontend/src/app/date-time-picker/date-time-picker.component.html b/frontend/src/app/date-time-picker/date-time-picker.component.html new file mode 100644 index 0000000..329f670 --- /dev/null +++ b/frontend/src/app/date-time-picker/date-time-picker.component.html @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/frontend/src/app/date-time-picker/date-time-picker.component.spec.ts b/frontend/src/app/date-time-picker/date-time-picker.component.spec.ts new file mode 100644 index 0000000..8bf6096 --- /dev/null +++ b/frontend/src/app/date-time-picker/date-time-picker.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DateTimePickerComponent } from './date-time-picker.component'; + +describe('DateTimePickerComponent', () => { + let component: DateTimePickerComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [DateTimePickerComponent] + }); + fixture = TestBed.createComponent(DateTimePickerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/date-time-picker/date-time-picker.component.ts b/frontend/src/app/date-time-picker/date-time-picker.component.ts new file mode 100644 index 0000000..a5ffd9e --- /dev/null +++ b/frontend/src/app/date-time-picker/date-time-picker.component.ts @@ -0,0 +1,43 @@ +import {Component, EventEmitter, Output, ViewChild} from "@angular/core"; +import {MatDatepicker} from "@angular/material/datepicker"; +import {NgxMaterialTimepickerComponent, NgxMaterialTimepickerToggleComponent} from "ngx-material-timepicker"; +import {FormControl, Validators} from "@angular/forms"; + +@Component({ + selector: 'app-date-time-picker', + templateUrl: './date-time-picker.component.html', + styleUrls: ['./date-time-picker.component.css'] +}) +export class DateTimePickerComponent { + @ViewChild('picker') picker?: MatDatepicker; + @ViewChild('toggleTimepicker') toggleTimepicker?: NgxMaterialTimepickerComponent + @Output('onTimeSet') timeSet: EventEmitter = new EventEmitter(); + + dateControl: FormControl = new FormControl('', [Validators.required]) + timeControl: FormControl = new FormControl('', [Validators.required]) + constructor() { } + + ngOnInit() { + + } + + setDateTime(date: Date) { + console.log(date) + this.dateControl.setValue(date); + const timeString = date.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false }); + this.timeControl.setValue(timeString); + } + + openTimePicker() { + this.toggleTimepicker!.open(); + } + + onTimeSet(time: string) { + let selectedDate = new Date(this.dateControl.value) + const [hours, minutes] = time.split(":") + selectedDate.setHours(parseInt(hours, 10)); + selectedDate.setMinutes(parseInt(minutes, 10)); + + this.timeSet.emit(selectedDate); + } +} diff --git a/frontend/src/app/schedules/advanced-scheduler/advanced-scheduler.component.css b/frontend/src/app/schedules/advanced-scheduler/advanced-scheduler.component.css index e69de29..9dbfc9e 100644 --- a/frontend/src/app/schedules/advanced-scheduler/advanced-scheduler.component.css +++ b/frontend/src/app/schedules/advanced-scheduler/advanced-scheduler.component.css @@ -0,0 +1,3 @@ +app-date-time-picker { + margin-right: 20px; +} diff --git a/frontend/src/app/schedules/advanced-scheduler/advanced-scheduler.component.html b/frontend/src/app/schedules/advanced-scheduler/advanced-scheduler.component.html index 12b4f1c..22ac923 100644 --- a/frontend/src/app/schedules/advanced-scheduler/advanced-scheduler.component.html +++ b/frontend/src/app/schedules/advanced-scheduler/advanced-scheduler.component.html @@ -1,16 +1,12 @@
- - - MM/DD/YYYY - - - - - - MM/DD/YYYY - - - + + +
+ + +
+
diff --git a/frontend/src/app/schedules/advanced-scheduler/advanced-scheduler.component.ts b/frontend/src/app/schedules/advanced-scheduler/advanced-scheduler.component.ts index 0c5fb8c..1034079 100644 --- a/frontend/src/app/schedules/advanced-scheduler/advanced-scheduler.component.ts +++ b/frontend/src/app/schedules/advanced-scheduler/advanced-scheduler.component.ts @@ -1,6 +1,7 @@ -import {Component, Input} from '@angular/core'; +import {Component, Input, ViewChild} from '@angular/core'; import {TaskgroupEntityInfo, TaskShortInfo} from "../../../api"; import {FormControl, Validators} from "@angular/forms"; +import {DateTimePickerComponent} from "../../date-time-picker/date-time-picker.component"; @Component({ selector: 'app-advanced-scheduler', @@ -12,15 +13,28 @@ export class AdvancedSchedulerComponent { @Input() task: TaskShortInfo | undefined; @Input() taskgroup: TaskgroupEntityInfo | undefined + @ViewChild('startTimePicker') startTimePicker?: DateTimePickerComponent; + @ViewChild('stopTimePicker') stopTimePicker?: DateTimePickerComponent; - startCtrl = new FormControl('', [Validators.required]) - endCtrl = new FormControl('', [Validators.required]) + + selectedStartTime: Date | undefined + selectedStopTime: Date | undefined setDate(clickedDate: Date) { - if(this.startCtrl.value == undefined) { - this.startCtrl.setValue(clickedDate.toISOString()); - } else if(new Date(Date.parse(this.startCtrl.value)) < clickedDate) { - this.endCtrl.setValue(clickedDate.toISOString()); + if(this.selectedStartTime == undefined) { + this.startTimePicker!.setDateTime(clickedDate); + this.selectedStartTime = clickedDate; + } else { + this.stopTimePicker!.setDateTime(clickedDate); + this.selectedStopTime = clickedDate; } } + + onStartTimeSet(selectedDate: Date) { + this.selectedStartTime = selectedDate; + } + + onStopTimeSet(selectedDate: Date) { + this.selectedStopTime = selectedDate; + } }