Min-max date selection range
The <input type="date"> field allows the user to select any date within 1 year in the future. That may sound ridiculous, but let’s stick with it for now. (Anything later than a month should go to a calendar. But I may have plans to add a feature to categorize some tasks.)
Regardless of how far the maximum date should be, the fact remains that there should be a maximum date and it should be the same for all tasks. Which means a single value should be passed to all instances of the Task component.
This didn’t occur to me at first. I used two (min and max) values each in every task.
But I fixed it later. One minimum date and one maximum date were calculated in the TaskList component and then passed to all tasks.
MySQL datetime and JS Date
Since the MySQL datetime type
accepts date(time)s in yyyy-mm-dd hh:mm:ss format, it’s quite easy to pass it a date-time value from JS. All you have to do is use .toISOString() on the JS Date object and remove the T from the first part.
Merging the date and the time input to create the date-time value was the problem. I had to merge the date input and the time input into a string and get a JS Date object to parse it to check it they were valid:
function updateTask() {
const string = this.newDate + this.newTime;
const newDueTime = new Date(string);
if (!newDueTime.getTime()) {
return;
}
// More stuff related to actually updating tasks
}
This works. But seems like it could be cleaner.
Timezones were a huge pain. It was all my fault though. I kept either counting the timezone twice or forgetting it. Things got especially confusing because I was passing the string I got from the database to new Date() and then using .toISOString() on it to format the date-time a bit nicely so that the date part and the time part are in the format I needed.
<input v-model="newDate" type="date"
:min="newDateMinValue"
:max="newDateMaxValue"
>
data() {
return {
now: new Date()
}
},
computed: {
newDateMinValue() {
// Using ".toISOString()" for formatting is bad!
return this.now.toISOString().split('T')[0];
},
newDateMaxValue() {
const nowPlus1Year = new Date(
this.now.getTime() + 31536000000
);
// Using ".toISOString()" for formatting is bad!
return nowPlus1Year.toISOString().split('T')[0];
}
}
All that chaos because I was doing formatting at the wrong place. I was changing the date-time value by using .toISOString() just because <input type="date"> would only accept values in yyyy-mm-dd format. That’s a good example of why presentation and logical layers should be kept separate.
(Anyway, later I decided I probably should use two separate columns for date and time in the database. That way, time can be null too.)
Check out Mantle on GitHub here