Skip to content

Commit 73d0789

Browse files
authored
Merge pull request #37 from diging/DS-23
DS-23: Allow multiple availability time picking in scheduling
2 parents 18a11af + e17050d commit 73d0789

File tree

10 files changed

+45128
-26061
lines changed

10 files changed

+45128
-26061
lines changed

package-lock.json

Lines changed: 35493 additions & 16868 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"jwt-decode": "^3.1.2",
2020
"material-design-icons-iconfont": "^5.0.1",
2121
"moment": "^2.29.4",
22+
"reflect-metadata": "^0.1.13",
2223
"vue": "^2.6.10",
2324
"vue-class-component": "^7.0.2",
2425
"vue-property-decorator": "^8.3.0",
@@ -37,9 +38,9 @@
3738
"@vue/cli-plugin-router": "^4.5.11",
3839
"@vue/cli-plugin-typescript": "^4.5.11",
3940
"@vue/cli-plugin-vuex": "^4.5.11",
40-
"@vue/cli-service": "^5.0.8",
41+
"@vue/cli-service": "^4.5.11",
4142
"axios": "^0.21.2",
42-
"chromedriver": "^77.0.0",
43+
"chromedriver": "^98.0.0",
4344
"geckodriver": "^3.0.2",
4445
"sass": "^1.19.0",
4546
"sass-loader": "^8.0.0",

src/components/Bases/ScheduleBase.ts

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,59 @@
1-
21
import Vue from 'vue'
32
import Component from 'vue-class-component'
4-
import {schedule, formattedSchedule} from '@/interfaces/GlobalTypes'
3+
import {schedule, formattedSchedule, time} from '@/interfaces/GlobalTypes'
54
import moment from 'moment'
5+
66
@Component
77
export class ScheduleBase extends Vue {
88

9-
109
protected maxHours: string = '0.0'
1110

12-
13-
parseStatus(status: number | string | undefined) {
11+
parseStatus(status: number | undefined) {
1412
switch(status) {
1513
case 0:
16-
return 'Pending';
14+
return 'Pending'
1715
case 1:
18-
return 'Approved';
16+
return 'Approved'
1917
case 2:
2018
return 'Denied'
2119
default:
2220
console.log("Nothing")
2321
}
2422
}
2523

26-
2724
parseTime(key: string, schedule: any) {
28-
let data = moment(schedule[`${key}_start_1`], 'HH:mm:ss').format('h:mm A') + ' - ' + moment(schedule[`${key}_end_1`], 'HH:mm:ss').format('h:mm A');
29-
if(data === '12:00 AM - 12:00 AM'){
30-
return 'OFF';
25+
let data = moment(schedule[`${key}_start_1`], 'HH:mm:ss').format('h:mm A') + ' - ' + moment(schedule[`${key}_end_1`], 'HH:mm:ss').format('h:mm A')
26+
if(data === '12:00 AM - 12:00 AM') {
27+
return 'OFF'
3128
} else {
32-
return data;
29+
return data
3330
}
3431
}
3532

36-
37-
timeFormat(schedule: schedule, schedules: formattedSchedule[]) {
33+
formatScheduleTime(schedule: schedule, schedules: formattedSchedule[]) {
3834
let formattedSchedule: formattedSchedule = {
3935
'created': moment(schedule['created']).format('MM/DD/YYYY'),
4036
'mon': this.parseTime("mon", schedule),
4137
'tue': this.parseTime("tue", schedule),
4238
'wed': this.parseTime("wed", schedule),
43-
'thu': this.parseTime("thur", schedule),
39+
'thu': this.parseTime("thu", schedule),
4440
'fri': this.parseTime("fri", schedule),
4541
'max_hours': schedule['max_hours'],
4642
// this works but vueter doesn't recognize it.
47-
'status': this.parseStatus(schedule['status']),
43+
'status': this.parseStatus(schedule.status),
4844
'id': schedule.id
4945
}
50-
5146
schedules.push(formattedSchedule)
5247
}
5348

49+
formatDayTime(times: time) {
50+
let formatted_day = moment(times['startTime1'], 'HH:mm:ss').format('h:mm A') + ' - ' + moment(times['endTime1'], 'HH:mm:ss').format('h:mm A')
51+
if(formatted_day === '12:00 AM - 12:00 AM') {
52+
return 'OFF'
53+
} else {
54+
return formatted_day
55+
}
56+
}
5457

5558
formatMaxHours() {
5659
if(!this.maxHours.includes('.')) {
@@ -62,7 +65,7 @@ export class ScheduleBase extends Vue {
6265
this.maxHours = '.' + this.maxHours
6366
}
6467
} else {
65-
let split = this.maxHours.split('.').join("");
68+
let split = this.maxHours.split('.').join("")
6669
if(split.length > 2) {
6770
let last = split.slice(-2)
6871
let rest = split.slice(0, -2)

src/components/admin/Availability.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ export default class Availability extends ScheduleBase {
8989
this.$axios.get('schedules/availability/list')
9090
.then(response => {
9191
response.data.forEach((schedule: schedule) => {
92-
this.timeFormat(schedule, this.schedules)
92+
this.formatScheduleTime(schedule, this.schedules)
9393
});
9494
this.loading = false;
9595
})
@@ -108,7 +108,7 @@ export default class Availability extends ScheduleBase {
108108
maxHours: maxHoursDecimal
109109
})
110110
.then((response: any) => {
111-
this.timeFormat(response.data, this.schedules)
111+
this.formatScheduleTime(response.data, this.schedules)
112112
})
113113
.catch(function (error: any) {
114114
console.log(error);

src/components/employee/Availability.vue

Lines changed: 92 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -5,57 +5,70 @@ div
55
v-container
66
p(class="body-2 mb-10") Lab hours are from 9:00 AM to 4:30 PM.
77
div(v-for="day in days" :key="day")
8-
v-row
9-
v-col(cols='3')
10-
p(class="font-weight-medium body-2") {{day}}
11-
v-col(cols='4')
12-
timePicker(:index = 'startTime1' :day='day')
13-
v-col(cols='4')
14-
timePicker(:index = 'endTime1' :day='day')
15-
v-col(cols='1')
16-
v-btn(icon color="#F2594B" v-on:click="isHidden=true")
17-
v-icon mdi-plus-circle-outline
8+
div(v-if="availabilityTimes[day].length===0")
9+
v-row
10+
v-col(cols='3')
11+
p(class="font-weight-medium body-2") {{day}}
12+
v-col(cols='4')
13+
timePicker(:day='day' :index='startTime1')
14+
v-col(cols='4')
15+
timePicker(:day='day' :index='endTime1')
16+
v-col(cols='1')
17+
v-btn(icon color="#F2594B" @click="updateAvailability(day)")
18+
v-icon mdi-plus-circle-outline
19+
div(v-else)
20+
div(v-for="(avItem, avIndex) in availabilityTimes[day]" :key="day + avIndex.toString()")
21+
v-row
22+
v-col(cols='3')
23+
p(class="font-weight-medium body-2") {{day}}
24+
v-col(cols='4')
25+
timePicker(:day='day' :index='startTime1')
26+
v-col(cols='4')
27+
timePicker(:day='day' :index='endTime1')
28+
v-col(cols='1')
29+
v-btn(icon color="#F2594B" @click="updateAvailability(day)")
30+
v-icon mdi-plus-circle-outline
1831
v-row(class="mt-n6 mb-4" v-if="isHidden")
1932
v-col(cols='3')
2033
v-col(cols='4')
21-
timePicker(:index = 'startTime2' :day='day')
22-
v-col(cols='4')
23-
timePicker(:index = 'endTime2' :day='day')
34+
timePicker(:day='day' :index='startTime2')
35+
v-col(cols='4')
36+
timePicker(:day='day' :index='endTime2')
2437
v-col(cols='1')
2538
v-row
2639
v-col.pt-4(cols='3')
27-
p.pt-3(class="font-weight-medium body-2") Max Hours
40+
p.pt-3(class="font-weight-medium body-2") Max Hours
2841
v-col(cols='3')
29-
v-text-field(v-model="maxHours" @input='formatMaxHours()' outlined dense)
42+
v-text-field(v-model="maxHours" @input='formatMaxHours()' outlined dense)
3043
v-card-actions
3144
v-spacer
3245
v-btn(color="grey" text @click="dialog = false") Cancel
3346
v-btn(color="#F2594B" medium class="white--text" @click="postSched()") Submit
3447

3548
h3.mb-5 Previous Schedules
36-
v-data-table(:headers="headers"
37-
:items="schedules"
38-
:items-per-page="5"
39-
item-key='id'
40-
class="elevation-1"
41-
:single-select="singleSelect"
42-
:loading='loading'
49+
v-data-table(:headers="headers"
50+
:items="schedules"
51+
:items-per-page="5"
52+
item-key='id'
53+
class="elevation-1"
54+
:single-select="singleSelect"
55+
:loading='loading'
4356
:loading-text="loadingText"
4457
:sort-by="['created']"
4558
:sort-desc="[true]"
4659
)
4760
template(v-slot:item.actions="{ item }")
4861
v-icon(v-if="item.status == 'Pending'" @click="deleteAvail(item.id)") mdi-delete
62+
4963
</template>
5064
<script lang="ts">
5165
import '@mdi/font/css/materialdesignicons.css'
52-
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
66+
import { Component, Prop, Vue, Watch } from 'vue-property-decorator'
5367
import { mixins } from 'vue-class-component'
54-
import Vuex from 'vuex';
68+
import Vuex from 'vuex'
5569
import timePicker from '@/components/global/timePicker.vue'
56-
import store from '@/store';
70+
import store from '@/store'
5771
import {formattedSchedule, schedule} from '@/interfaces/GlobalTypes'
58-
5972
import { ScheduleBase } from '@/components/Bases/ScheduleBase'
6073
6174
const axios = require('axios')
@@ -69,12 +82,21 @@ const axios = require('axios')
6982
})
7083
7184
export default class Availability extends ScheduleBase {
72-
73-
private singleSelect: boolean = false;
74-
private loading: boolean = false;
85+
86+
private singleSelect: boolean = false
87+
private loading: boolean = false
7588
private loadingText: string = 'The sched-o-matic is working hard on your request'
7689
private dialog: boolean = false
77-
private schedules: formattedSchedule[] = [];
90+
private startTime1: string = "startTime1"
91+
private endTime1: string = "endTime1"
92+
private startTime2: string = "startTime2"
93+
private endTime2: string = "endTime2"
94+
private isHidden: boolean = false
95+
private availabilityTimes: { [x: string]: any[]; } = {}
96+
private days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
97+
private time_suffixes = ['_start_1', '_start_2', '_end_1', '_end_2']
98+
private day_time_strings: string[] = []
99+
private schedules: formattedSchedule[] = []
78100
79101
headers = [
80102
{text: 'Submitted', value: 'created'},
@@ -87,61 +109,79 @@ export default class Availability extends ScheduleBase {
87109
{text: 'Max Hours', value: 'max_hours'},
88110
{text: 'Delete', value: 'actions'},
89111
//d-none must have leading space in string to work. Hide from table but id is still attached
90-
{text: 'Id', value: 'id', align: ' d-none'}
91-
];
92-
112+
{text: 'Id', value: 'id', align: ' d-none'}
113+
]
93114
94115
constructor() {
95-
super();
116+
super()
96117
}
97118
119+
updateAvailability(day: string) {
120+
this.day_time_strings = []
121+
var day_abbrev = day.slice(0, 3).toLowerCase()
122+
for (var time of this.time_suffixes) {
123+
this.day_time_strings.push(day_abbrev + time)
124+
}
125+
this.$axios.patch('/schedules/availability/update', {
126+
time_strings: this.day_time_strings,
127+
sched_times: store.getters.getDaySched(day)
128+
})
129+
.then((response: any) => {
130+
var updated_time = this.formatDayTime(response.data.day)
131+
var index = this.schedules.length - 1
132+
this.schedules[index][day_abbrev] = updated_time
133+
})
134+
.catch(function (error: any) {
135+
console.log(error)
136+
})
137+
}
98138
99139
created() {
100-
this.loading = true;
101-
this.$axios.get('/schedules/user/availability')
140+
for (var day of this.days) {
141+
this.availabilityTimes[day] = []
142+
}
143+
this.loading = true
144+
this.$axios.get('/schedules/user/availability')
102145
.then(response => {
103146
response.data.forEach((schedule: schedule) => {
104-
this.timeFormat(schedule, this.schedules)
105-
});
106-
this.loading = false;
147+
this.formatScheduleTime(schedule, this.schedules)
148+
})
149+
this.loading = false
107150
})
108151
.catch(function (error: any) {
109-
console.log(error);
152+
console.log(error)
110153
})
111154
.then(function () {
112155
// always executed
113-
});
156+
})
114157
}
115158
116-
117-
118159
postSched() {
119-
let maxHoursDecimal = Number.parseFloat(this.maxHours).toFixed(2);
160+
let maxHoursDecimal = Number.parseFloat(this.maxHours).toFixed(2)
120161
this.$axios.post('/schedules/availability/create', {
121162
schedule: store.getters.timeValues,
122163
maxHours: maxHoursDecimal
123164
})
124165
.then((response: any) => {
125-
this.timeFormat(response.data,this.schedules)
166+
this.formatScheduleTime(response.data,this.schedules)
126167
})
127168
.catch(function (error: any) {
128-
console.log(error);
169+
console.log(error)
129170
})
130171
}
131172
132173
deleteAvail(id: number) {
133174
this.$axios.delete('/schedules/availability/delete/' + id)
134175
.then((response: any) => {
135-
var removeIndex = this.schedules.map(item => item.id).indexOf(id);
136-
~removeIndex && this.schedules.splice(removeIndex, 1);
176+
var removeIndex = this.schedules.map(item => item.id).indexOf(id)
177+
~removeIndex && this.schedules.splice(removeIndex, 1)
137178
})
138179
.catch(function (error: any) {
139-
console.log(error);
180+
console.log(error)
140181
})
141-
}
142-
143-
182+
}
144183
}
184+
145185
</script>
146186

147187
<style scoped>

0 commit comments

Comments
 (0)