validate date input
This commit is contained in:
parent
75b02685ec
commit
450a96d2de
3 changed files with 234 additions and 115 deletions
|
|
@ -7,125 +7,158 @@
|
||||||
(ngSubmit)="onSubmit(taskForm)"
|
(ngSubmit)="onSubmit(taskForm)"
|
||||||
#taskForm="ngForm"
|
#taskForm="ngForm"
|
||||||
onsubmit="return false"
|
onsubmit="return false"
|
||||||
class="content"
|
|
||||||
>
|
>
|
||||||
<div class="left-side">
|
<div class="content">
|
||||||
<div class="title">
|
<div class="left-side">
|
||||||
<p>Title<span class="red-dot">*</span></p>
|
<div class="title">
|
||||||
<input
|
<p>Title<span class="red-dot">*</span></p>
|
||||||
type="text"
|
<input
|
||||||
id="title"
|
type="text"
|
||||||
name="title"
|
id="title"
|
||||||
#title="ngModel"
|
name="title"
|
||||||
(input)="saveTaskData()"
|
#title="ngModel"
|
||||||
placeholder="{{ taskData.title }}"
|
(input)="saveTaskData()"
|
||||||
[(ngModel)]="taskData.title"
|
placeholder="{{
|
||||||
autocomplete="off"
|
taskData.title ? taskData.title : 'Enter a title'
|
||||||
required
|
}}"
|
||||||
/>
|
[(ngModel)]="taskData.title"
|
||||||
<div class="error-msg">
|
autocomplete="off"
|
||||||
@if (!title.valid && title.touched) {
|
required
|
||||||
<p>You must enter a title.</p>
|
/>
|
||||||
}
|
<div class="error-msg">
|
||||||
|
@if (!title.valid && title.touched) {
|
||||||
|
<p>You must enter a title.</p>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="description">
|
||||||
|
<p>Description<span class="red-dot">*</span></p>
|
||||||
|
<textarea
|
||||||
|
id="description"
|
||||||
|
rows="6"
|
||||||
|
name="description"
|
||||||
|
#description="ngModel"
|
||||||
|
minlength="10"
|
||||||
|
(input)="saveTaskData()"
|
||||||
|
placeholder="{{
|
||||||
|
taskData.description
|
||||||
|
? taskData.description
|
||||||
|
: 'Enter a description'
|
||||||
|
}}"
|
||||||
|
[(ngModel)]="taskData.description"
|
||||||
|
autocomplete="off"
|
||||||
|
required
|
||||||
|
></textarea>
|
||||||
|
<div class="error-msg">
|
||||||
|
@if (!description.valid && description.touched) {
|
||||||
|
<p>You must enter a description. (min. 10 letters)</p>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="middle-spacer"><div class="line"></div></div>
|
||||||
<p>Description<span class="red-dot">*</span></p>
|
<div class="right-side">
|
||||||
<textarea
|
<div class="date">
|
||||||
id="description"
|
<p>Due date<span class="red-dot">*</span></p>
|
||||||
rows="6"
|
<input
|
||||||
name="description"
|
type="date"
|
||||||
#description="ngModel"
|
id="date"
|
||||||
minlength="10"
|
name="date"
|
||||||
(input)="saveTaskData()"
|
#date="ngModel"
|
||||||
placeholder="{{ taskData.description }}"
|
(input)="checkDateInput()"
|
||||||
[(ngModel)]="taskData.description"
|
placeholder="{{ taskData.date }}"
|
||||||
autocomplete="off"
|
[(ngModel)]="taskData.date"
|
||||||
required
|
autocomplete="off"
|
||||||
></textarea>
|
required
|
||||||
<div class="error-msg">
|
/>
|
||||||
@if (!description.valid && description.touched) {
|
<div class="error-msg">
|
||||||
<p>You must enter a description. (min. 10 letters)</p>
|
@if (!date.valid && date.touched) {
|
||||||
}
|
<p>You must enter a date.</p>
|
||||||
|
} @if (dateInPast && date.valid) {
|
||||||
|
<p>The date must be in the future</p>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="priority">
|
||||||
|
<p>Prio<span class="red-dot">*</span></p>
|
||||||
|
<div class="btns">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn"
|
||||||
|
[ngClass]="{
|
||||||
|
'btn-active': taskData.priority == 'urgent'
|
||||||
|
}"
|
||||||
|
[ngStyle]="{
|
||||||
|
'background-color':
|
||||||
|
taskData.priority == 'urgent' ? 'red' : 'white'
|
||||||
|
}"
|
||||||
|
(click)="tooglePriority('urgent')"
|
||||||
|
>
|
||||||
|
<div class="btn-text">
|
||||||
|
<span>Urgent</span>
|
||||||
|
<img src="./../../../assets/img/urgent.svg" alt="" />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn"
|
||||||
|
[ngClass]="{
|
||||||
|
'btn-active': taskData.priority == 'medium'
|
||||||
|
}"
|
||||||
|
[ngStyle]="{
|
||||||
|
'background-color':
|
||||||
|
taskData.priority == 'medium' ? 'orange' : 'white'
|
||||||
|
}"
|
||||||
|
(click)="tooglePriority('medium')"
|
||||||
|
>
|
||||||
|
<div class="btn-text">
|
||||||
|
<span>Medium</span>
|
||||||
|
<img src="./../../../assets/img/medium.svg" alt="" />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn"
|
||||||
|
[ngClass]="{
|
||||||
|
'btn-active': taskData.priority == 'low'
|
||||||
|
}"
|
||||||
|
[ngStyle]="{
|
||||||
|
'background-color':
|
||||||
|
taskData.priority == 'low' ? 'green' : 'white'
|
||||||
|
}"
|
||||||
|
(click)="tooglePriority('low')"
|
||||||
|
>
|
||||||
|
<div class="btn-text">
|
||||||
|
<span>Low</span>
|
||||||
|
<img src="./../../../assets/img/low.svg" alt="" />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="middle-spacer"><div class="line"></div></div>
|
<div class="form-buttons">
|
||||||
<div class="right-side">
|
<input
|
||||||
<div class="date">
|
class="btn-clear"
|
||||||
<p>Due date<span class="red-dot">*</span></p>
|
type="button"
|
||||||
<input
|
value="Clear"
|
||||||
type="date"
|
(click)="removeTaskData()"
|
||||||
id="date"
|
/>
|
||||||
name="date"
|
<input
|
||||||
#date="ngModel"
|
class="btn-submit"
|
||||||
(input)="saveTaskData()"
|
type="submit"
|
||||||
placeholder="{{ taskData.date }}"
|
value="Create Task"
|
||||||
[(ngModel)]="taskData.date"
|
[disabled]="
|
||||||
autocomplete="off"
|
title.invalid ||
|
||||||
required
|
!taskData.title ||
|
||||||
/>
|
description.invalid ||
|
||||||
<div class="error-msg">
|
!taskData.description ||
|
||||||
@if (!date.valid && date.touched) {
|
date.invalid ||
|
||||||
<p>You must enter a date.</p>
|
!taskData.date ||
|
||||||
}
|
!taskData.priority ||
|
||||||
</div>
|
dateInPast
|
||||||
</div>
|
"
|
||||||
<div class="priority">
|
/>
|
||||||
<p>Prio<span class="red-dot">*</span></p>
|
|
||||||
<div class="btns">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="btn"
|
|
||||||
[ngClass]="{
|
|
||||||
'btn-active': taskData.priority == 'urgent'
|
|
||||||
}"
|
|
||||||
[ngStyle]="{
|
|
||||||
'background-color':
|
|
||||||
taskData.priority == 'urgent' ? 'red' : 'white'
|
|
||||||
}"
|
|
||||||
(click)="tooglePriority('urgent')"
|
|
||||||
>
|
|
||||||
<div class="btn-text">
|
|
||||||
<span>Urgent</span>
|
|
||||||
<img src="./../../../assets/img/urgent.svg" alt="" />
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="btn"
|
|
||||||
[ngClass]="{
|
|
||||||
'btn-active': taskData.priority == 'medium'
|
|
||||||
}"
|
|
||||||
[ngStyle]="{
|
|
||||||
'background-color':
|
|
||||||
taskData.priority == 'medium' ? 'orange' : 'white'
|
|
||||||
}"
|
|
||||||
(click)="tooglePriority('medium')"
|
|
||||||
>
|
|
||||||
<div class="btn-text">
|
|
||||||
<span>Medium</span>
|
|
||||||
<img src="./../../../assets/img/medium.svg" alt="" />
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="btn"
|
|
||||||
[ngClass]="{
|
|
||||||
'btn-active': taskData.priority == 'low'
|
|
||||||
}"
|
|
||||||
[ngStyle]="{
|
|
||||||
'background-color': taskData.priority == 'low' ? 'green' : 'white'
|
|
||||||
}"
|
|
||||||
(click)="tooglePriority('low')"
|
|
||||||
>
|
|
||||||
<div class="btn-text">
|
|
||||||
<span>Low</span>
|
|
||||||
<img src="./../../../assets/img/low.svg" alt="" />
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -111,3 +111,56 @@ p {
|
||||||
.btn:hover {
|
.btn:hover {
|
||||||
box-shadow: 2px 2px 2px 0px rgba(0, 0, 0, 0.3);
|
box-shadow: 2px 2px 2px 0px rgba(0, 0, 0, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*------------- SUBMIT BUTTON -------------*/
|
||||||
|
|
||||||
|
.form-buttons {
|
||||||
|
display: flex;
|
||||||
|
justify-content: end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-submit {
|
||||||
|
width: 183px;
|
||||||
|
height: 56px;
|
||||||
|
padding: 12px;
|
||||||
|
margin: 12px 12px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 1px solid var(--black) !important;
|
||||||
|
background-color: var(--light-gray);
|
||||||
|
font-size: 23px;
|
||||||
|
font-weight: 400;
|
||||||
|
transition: 125ms ease-in-out;
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
box-shadow: 2px 2px 2px 0px rgba(0, 0, 0, 0.3);
|
||||||
|
background-color: var(--light-blue) !important;
|
||||||
|
border: 1px solid var(--light-blue) !important;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
&:not(:disabled) {
|
||||||
|
background-color: var(--very-dark-blue) !important;
|
||||||
|
color: var(--white);
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-clear {
|
||||||
|
width: 110px;
|
||||||
|
height: 56px;
|
||||||
|
padding: 12px;
|
||||||
|
margin: 12px 12px;
|
||||||
|
border-radius: 10px;
|
||||||
|
color: var(--black);
|
||||||
|
background-color: var(--white);
|
||||||
|
border: 1px solid var(--black);
|
||||||
|
font-size: 23px;
|
||||||
|
font-weight: 400;
|
||||||
|
transition: 125ms ease-in-out;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
color: var(--light-blue);
|
||||||
|
border-color: var(--light-bluek);
|
||||||
|
box-shadow: 2px 2px 2px 0px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { Component } from '@angular/core';
|
import { Component, ViewChild } from '@angular/core';
|
||||||
import { FormsModule, NgForm } from '@angular/forms';
|
import { FormsModule, NgForm, NgModel } from '@angular/forms';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-add-task',
|
selector: 'app-add-task',
|
||||||
|
|
@ -10,7 +10,11 @@ import { FormsModule, NgForm } from '@angular/forms';
|
||||||
styleUrl: './add-task.component.scss',
|
styleUrl: './add-task.component.scss',
|
||||||
})
|
})
|
||||||
export class AddTaskComponent {
|
export class AddTaskComponent {
|
||||||
|
@ViewChild('title', { static: true }) titleField!: NgModel;
|
||||||
|
@ViewChild('description', { static: true }) descriptionField!: NgModel;
|
||||||
|
|
||||||
currentDate: string = new Date().toISOString().split('T')[0];
|
currentDate: string = new Date().toISOString().split('T')[0];
|
||||||
|
dateInPast: boolean = false;
|
||||||
|
|
||||||
taskData = {
|
taskData = {
|
||||||
title: '',
|
title: '',
|
||||||
|
|
@ -26,6 +30,17 @@ export class AddTaskComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkDateInput() {
|
||||||
|
const currentDateForm = this.taskData.date.replaceAll('-', '');
|
||||||
|
const currentDate = new Date()
|
||||||
|
.toISOString()
|
||||||
|
.split('T')[0]
|
||||||
|
.replaceAll('-', '');
|
||||||
|
currentDateForm < currentDate
|
||||||
|
? (this.dateInPast = true)
|
||||||
|
: (this.dateInPast = false);
|
||||||
|
}
|
||||||
|
|
||||||
tooglePriority(prio: string) {
|
tooglePriority(prio: string) {
|
||||||
this.taskData.priority !== prio
|
this.taskData.priority !== prio
|
||||||
? (this.taskData.priority = prio)
|
? (this.taskData.priority = prio)
|
||||||
|
|
@ -37,9 +52,27 @@ export class AddTaskComponent {
|
||||||
localStorage.setItem('taskData', JSON.stringify(this.taskData));
|
localStorage.setItem('taskData', JSON.stringify(this.taskData));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
removeTaskData() {
|
||||||
|
localStorage.removeItem('taskData');
|
||||||
|
this.untouchedFormFields();
|
||||||
|
this.clearFormData();
|
||||||
|
}
|
||||||
|
|
||||||
|
untouchedFormFields() {
|
||||||
|
this.titleField.control.markAsUntouched();
|
||||||
|
this.descriptionField.control.markAsUntouched();
|
||||||
|
}
|
||||||
|
|
||||||
|
clearFormData() {
|
||||||
|
this.taskData.title = '';
|
||||||
|
this.taskData.description = '';
|
||||||
|
this.taskData.date = this.currentDate;
|
||||||
|
}
|
||||||
|
|
||||||
onSubmit(ngForm: NgForm) {
|
onSubmit(ngForm: NgForm) {
|
||||||
if (ngForm.submitted && ngForm.form.valid) {
|
if (ngForm.submitted && ngForm.form.valid) {
|
||||||
console.log('Send completed');
|
console.log('Send completed');
|
||||||
|
this.removeTaskData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue