@worksafevictoria/wcl7.5 1.18.1 → 1.19.0-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/components/Global/AppHeaderNew/mobile.scss +0 -2
- package/src/components/Paragraphs/RTWPlanner/CardContainer/index.vue +3 -27
- package/src/components/Paragraphs/RTWPlanner/CardContainer/styles.scss +28 -0
- package/src/components/Paragraphs/RTWPlanner/Constants.js +135 -3
- package/src/components/Paragraphs/RTWPlanner/Footer/index.vue +3 -3
- package/src/components/Paragraphs/RTWPlanner/Header/index.vue +3 -3
- package/src/components/Paragraphs/RTWPlanner/HomePage/index.vue +8 -27
- package/src/components/Paragraphs/RTWPlanner/Injuries/HowTo.vue +168 -0
- package/src/components/Paragraphs/RTWPlanner/Injuries/index.vue +67 -14
- package/src/components/Paragraphs/RTWPlanner/Planners/PlanTasks.vue +411 -108
- package/src/components/Paragraphs/RTWPlanner/Planners/PlannerNameModal.vue +47 -50
- package/src/components/Paragraphs/RTWPlanner/Planners/PlannersStorage.js +29 -0
- package/src/components/Paragraphs/RTWPlanner/Planners/index.vue +119 -223
- package/src/components/Paragraphs/RTWPlanner/index.vue +1 -2
- package/src/components/Paragraphs/SelectableCards/index.vue +6 -3
- package/src/components/Paragraphs/TextMedia/index.vue +5 -11
- package/src/index.js +2 -1
|
@@ -9,6 +9,7 @@ import Breadcrumb from './../../../SubComponents/Breadcrumb/index.vue'
|
|
|
9
9
|
import RichText from './../../RichText/index.vue'
|
|
10
10
|
import SelectableCards from './../../SelectableCards/index.vue'
|
|
11
11
|
import PlannerNameModal from './../Planners/PlannerNameModal.vue'
|
|
12
|
+
import HowTo from './HowTo.vue'
|
|
12
13
|
|
|
13
14
|
const props = defineProps({
|
|
14
15
|
injuryPage: {
|
|
@@ -43,15 +44,13 @@ const props = defineProps({
|
|
|
43
44
|
type: Array,
|
|
44
45
|
default: () => [],
|
|
45
46
|
},
|
|
46
|
-
showModalOnButtonRole: {
|
|
47
|
-
type: Boolean,
|
|
48
|
-
default: false,
|
|
49
|
-
},
|
|
50
47
|
})
|
|
51
48
|
|
|
52
49
|
const screen = ref(1)
|
|
53
50
|
const selectedCard = ref(null)
|
|
54
51
|
const showModal = ref(false)
|
|
52
|
+
const step = ref(1)
|
|
53
|
+
const plannerId = ref(null)
|
|
55
54
|
|
|
56
55
|
// local copy of breadcrumb items allowed to mutate
|
|
57
56
|
const breadcrumbItemsLocal = ref([...props.breadcrumbItems])
|
|
@@ -96,6 +95,16 @@ function onCrumbClick({ index }) {
|
|
|
96
95
|
function nextScreenAgent(card) {
|
|
97
96
|
showModal.value = true
|
|
98
97
|
}
|
|
98
|
+
|
|
99
|
+
/* -----------------------
|
|
100
|
+
Modal submit
|
|
101
|
+
------------------------ */
|
|
102
|
+
function onSubmit(planner) {
|
|
103
|
+
if (!planner) return
|
|
104
|
+
|
|
105
|
+
plannerId.value = planner.id
|
|
106
|
+
step.value = 2
|
|
107
|
+
}
|
|
99
108
|
</script>
|
|
100
109
|
|
|
101
110
|
<template>
|
|
@@ -123,7 +132,7 @@ function nextScreenAgent(card) {
|
|
|
123
132
|
:titles="titles.physical"
|
|
124
133
|
:cards="cards"
|
|
125
134
|
:button-role="'modal-quest'"
|
|
126
|
-
:showModalOnButtonRole="
|
|
135
|
+
:showModalOnButtonRole="true"
|
|
127
136
|
@nextScreen="nextScreen"
|
|
128
137
|
/>
|
|
129
138
|
</div>
|
|
@@ -172,22 +181,66 @@ function nextScreenAgent(card) {
|
|
|
172
181
|
</div>
|
|
173
182
|
|
|
174
183
|
<div v-if="injuryPage === 'selectAgent'">
|
|
175
|
-
<
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
184
|
+
<div v-if="step === 1">
|
|
185
|
+
<card-container
|
|
186
|
+
ref="selectAgentContainer"
|
|
187
|
+
:columns="4"
|
|
188
|
+
:title="titles.cardContactInformaton?.heading"
|
|
189
|
+
:cards="contactCards"
|
|
190
|
+
:button-role="'link'"
|
|
191
|
+
@nextScreen="nextScreenAgent"
|
|
192
|
+
/>
|
|
193
|
+
</div>
|
|
194
|
+
<div v-if="step === 2">
|
|
195
|
+
<HowTo
|
|
196
|
+
mainTitle="How to use the Return to Work planner"
|
|
197
|
+
subTitle="Let's get started"
|
|
198
|
+
mainText="Read the information on a page, complete the actions and scroll to the bottom to tick off the task."
|
|
199
|
+
buttonText="Next"
|
|
200
|
+
skipLinkText=""
|
|
201
|
+
@next="step = 3"
|
|
202
|
+
/>
|
|
203
|
+
</div>
|
|
204
|
+
<div v-if="step === 3">
|
|
205
|
+
<HowTo
|
|
206
|
+
mainTitle="How to use the Return to Work planner"
|
|
207
|
+
subTitle="Contact your employee"
|
|
208
|
+
mainText="Start at Task 1. Read the information and contact your employee. If you have already done this you then go onto the next screen."
|
|
209
|
+
buttonText="Step 1. Contact your employee"
|
|
210
|
+
skipLinkText="I've already contacted my employee"
|
|
211
|
+
:mock="2"
|
|
212
|
+
@next="emit('startPlanner', plannerId)"
|
|
213
|
+
@skip="emit('skipContact', plannerId)"
|
|
214
|
+
/>
|
|
215
|
+
</div>
|
|
183
216
|
</div>
|
|
184
217
|
|
|
185
|
-
<PlannerNameModal
|
|
218
|
+
<PlannerNameModal
|
|
219
|
+
class="injuries-app__new-planner"
|
|
220
|
+
v-model="showModal"
|
|
221
|
+
@onsubmit="onSubmit"
|
|
222
|
+
/>
|
|
186
223
|
</div>
|
|
187
224
|
</template>
|
|
188
225
|
|
|
189
226
|
<style lang="scss" scoped>
|
|
227
|
+
$fuchsia: #ea338f;
|
|
228
|
+
|
|
190
229
|
.injuries-app {
|
|
230
|
+
:deep(.control_selectcard .card-grid-item__card) {
|
|
231
|
+
border: 4px solid #d8d5d1;
|
|
232
|
+
}
|
|
233
|
+
:deep(.control_selectcard .card-grid-item__card:hover) {
|
|
234
|
+
background-color: white;
|
|
235
|
+
border: 4px solid #5664ac;
|
|
236
|
+
opacity: unset;
|
|
237
|
+
border-radius: 10px;
|
|
238
|
+
}
|
|
239
|
+
:deep(.control_selectcard .card-grid-item__card:focus) {
|
|
240
|
+
background-color: #e9ebf4;
|
|
241
|
+
border: 4px solid #5664ac;
|
|
242
|
+
outline: solid 3px $fuchsia !important;
|
|
243
|
+
}
|
|
191
244
|
.wcl-hero-header {
|
|
192
245
|
border: none;
|
|
193
246
|
}
|
|
@@ -1,108 +1,80 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<Container>
|
|
3
|
-
<Row>
|
|
4
|
-
<Column col="12">
|
|
5
|
-
<h2 class="fw-bold my-4">{{ props.activePlanner?.name }}'s planner</h2>
|
|
6
|
-
</Column>
|
|
7
|
-
</Row>
|
|
8
|
-
<Row>
|
|
9
|
-
<Column col="12" md="8">
|
|
10
|
-
<div class="card shadow-sm border-3 rounded-3 p-4">
|
|
11
|
-
<BCardText v-html="activeContent.html"></BCardText>
|
|
12
|
-
<CtaButton
|
|
13
|
-
:rtl="
|
|
14
|
-
isTaskCompleted(activeTask.id, activeContent.id) ? true : false
|
|
15
|
-
"
|
|
16
|
-
:workwell="
|
|
17
|
-
isTaskCompleted(activeTask.id, activeContent.id) ? true : false
|
|
18
|
-
"
|
|
19
|
-
@click="toggleTask(activeTask.id, activeContent.id)"
|
|
20
|
-
class="mt-1"
|
|
21
|
-
>
|
|
22
|
-
{{
|
|
23
|
-
isTaskCompleted(activeTask.id, activeContent.id)
|
|
24
|
-
? 'Completed'
|
|
25
|
-
: 'Mark Done'
|
|
26
|
-
}}
|
|
27
|
-
</CtaButton>
|
|
28
|
-
</div>
|
|
29
|
-
<div
|
|
30
|
-
role="button"
|
|
31
|
-
class="card shadow-sm border-3 rounded-3 p-4 mt-4 text-end"
|
|
32
|
-
:class="getNextTask() ? '' : 'disabled'"
|
|
33
|
-
@click="setActiveContent(getNextTask().task, getNextTask().content)"
|
|
34
|
-
>
|
|
35
|
-
<h4 class="fw-bold mt-0 mb-3">Go to next task</h4>
|
|
36
|
-
<p class="text-muted mb-0">
|
|
37
|
-
<span class="text-decoration-underline">
|
|
38
|
-
{{
|
|
39
|
-
getNextTask() ? getNextTask().content.btnText : 'No more tasks'
|
|
40
|
-
}}
|
|
41
|
-
</span>
|
|
42
|
-
</p>
|
|
43
|
-
</div>
|
|
44
|
-
</Column>
|
|
45
|
-
<Column col="12" md="4">
|
|
46
|
-
<div class="card shadow-sm border-3 rounded-3 p-4">
|
|
47
|
-
<h4 class="fw-bold mb-3">All tasks</h4>
|
|
48
|
-
<div v-for="task in props.tasks" :key="task.id" class="mb-3">
|
|
49
|
-
<p class="fw-bold">{{ task.title }}</p>
|
|
50
|
-
<div v-for="content in task.content" :key="content.id">
|
|
51
|
-
<button
|
|
52
|
-
class="d-flex justify-content-between align-items-center w-100 border-0 rounded-2 p-2 mb-2 text-start"
|
|
53
|
-
:class="
|
|
54
|
-
isTaskCompleted(task.id, content.id)
|
|
55
|
-
? activeContent.id === content.id
|
|
56
|
-
? 'bg-success-subtle text-dark fw-bold active-done'
|
|
57
|
-
: 'bg-success-subtle text-dark fw-bold'
|
|
58
|
-
: activeContent.id === content.id
|
|
59
|
-
? 'active'
|
|
60
|
-
: 'bg-light text-muted'
|
|
61
|
-
"
|
|
62
|
-
@click="setActiveContent(task, content)"
|
|
63
|
-
>
|
|
64
|
-
<span class="text-decoration-underline">
|
|
65
|
-
{{ content.btnText }}
|
|
66
|
-
</span>
|
|
67
|
-
<span
|
|
68
|
-
v-if="isTaskCompleted(task.id, content.id)"
|
|
69
|
-
class="text-success"
|
|
70
|
-
>
|
|
71
|
-
<TickCircleIcon
|
|
72
|
-
class="ms-2"
|
|
73
|
-
style="width: 2em; height: 2em"
|
|
74
|
-
/>
|
|
75
|
-
</span>
|
|
76
|
-
<span v-else class="text-muted">
|
|
77
|
-
<TickCircleIcon
|
|
78
|
-
class="ms-2"
|
|
79
|
-
style="width: 2em; height: 2em"
|
|
80
|
-
/>
|
|
81
|
-
</span>
|
|
82
|
-
</button>
|
|
83
|
-
</div>
|
|
84
|
-
</div>
|
|
85
|
-
</div>
|
|
86
|
-
</Column>
|
|
87
|
-
</Row>
|
|
88
|
-
</Container>
|
|
89
|
-
</template>
|
|
90
|
-
|
|
91
1
|
<script setup>
|
|
92
|
-
import { ref } from 'vue'
|
|
93
|
-
|
|
2
|
+
import { computed, ref, onMounted, onBeforeUnmount, watch } from 'vue'
|
|
3
|
+
import { BCard, BCardText, BButton } from 'bootstrap-vue-next'
|
|
4
|
+
import Column from './../../../Containers/Column/index.vue'
|
|
5
|
+
import Container from './../../../Containers/Container/index.vue'
|
|
6
|
+
import Row from './../../../Containers/Row/index.vue'
|
|
94
7
|
import TickCircleIcon from './../icons/TickCircleIcon.vue'
|
|
8
|
+
import ChevRightIcon from './../icons/ChevRightIcon.vue'
|
|
95
9
|
|
|
96
10
|
const props = defineProps({
|
|
97
11
|
activePlanner: { type: Object, required: true },
|
|
98
12
|
tasks: { type: Array, required: true },
|
|
99
13
|
})
|
|
100
14
|
|
|
101
|
-
const emit = defineEmits(['updatePlanner'])
|
|
102
|
-
|
|
103
|
-
const
|
|
104
|
-
const
|
|
105
|
-
|
|
15
|
+
const emit = defineEmits(['updatePlanner', 'taskResource', 'allCompleted'])
|
|
16
|
+
|
|
17
|
+
const showTasksModal = ref(false)
|
|
18
|
+
const isMobile = ref(false)
|
|
19
|
+
|
|
20
|
+
let mq = null
|
|
21
|
+
function handleMq(e) {
|
|
22
|
+
isMobile.value = e.matches
|
|
23
|
+
if (!isMobile.value) showTasksModal.value = false
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
onMounted(() => {
|
|
27
|
+
mq = window.matchMedia('(max-width: 767.98px)')
|
|
28
|
+
isMobile.value = mq.matches
|
|
29
|
+
if (mq.addEventListener) {
|
|
30
|
+
mq.addEventListener('change', handleMq)
|
|
31
|
+
} else {
|
|
32
|
+
mq.addListener(handleMq)
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
onBeforeUnmount(() => {
|
|
37
|
+
if (!mq) return
|
|
38
|
+
if (mq.removeEventListener) {
|
|
39
|
+
mq.removeEventListener('change', handleMq)
|
|
40
|
+
} else {
|
|
41
|
+
mq.removeListener(handleMq)
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
function findFirstUncompleted() {
|
|
46
|
+
const completed = props.activePlanner?.tasksCompleted || []
|
|
47
|
+
for (const task of props.tasks || []) {
|
|
48
|
+
for (const content of task.content || []) {
|
|
49
|
+
const key = `${task.id}_${content.id}`
|
|
50
|
+
if (!completed.includes(key)) {
|
|
51
|
+
return { task, content }
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const firstTask = props.tasks?.[0] || { id: '', title: '', content: [] }
|
|
56
|
+
const firstContent = firstTask.content?.[0] || {
|
|
57
|
+
id: '',
|
|
58
|
+
btnText: '',
|
|
59
|
+
html: '',
|
|
60
|
+
}
|
|
61
|
+
return { task: firstTask, content: firstContent }
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const initial = findFirstUncompleted()
|
|
65
|
+
const activeTask = ref(initial.task)
|
|
66
|
+
const activeContent = ref(initial.content)
|
|
67
|
+
|
|
68
|
+
watch(
|
|
69
|
+
activeContent,
|
|
70
|
+
(content) => {
|
|
71
|
+
if (content?.resources) {
|
|
72
|
+
emit('taskResource', content.resources)
|
|
73
|
+
} else {
|
|
74
|
+
emit('taskResource', null)
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
{ immediate: true },
|
|
106
78
|
)
|
|
107
79
|
|
|
108
80
|
const toggleTask = (taskId, contentId) => {
|
|
@@ -112,11 +84,8 @@ const toggleTask = (taskId, contentId) => {
|
|
|
112
84
|
tasksCompleted: [...props.activePlanner.tasksCompleted],
|
|
113
85
|
}
|
|
114
86
|
const index = updatedPlanner.tasksCompleted.indexOf(key)
|
|
115
|
-
if (index === -1)
|
|
116
|
-
|
|
117
|
-
} else {
|
|
118
|
-
updatedPlanner.tasksCompleted.splice(index, 1)
|
|
119
|
-
}
|
|
87
|
+
if (index === -1) updatedPlanner.tasksCompleted.push(key)
|
|
88
|
+
else updatedPlanner.tasksCompleted.splice(index, 1)
|
|
120
89
|
emit('updatePlanner', updatedPlanner)
|
|
121
90
|
}
|
|
122
91
|
|
|
@@ -126,12 +95,20 @@ const isTaskCompleted = (taskId, contentId) => {
|
|
|
126
95
|
}
|
|
127
96
|
|
|
128
97
|
const setActiveContent = (task, content) => {
|
|
129
|
-
console.log('🚀 ~ setActiveContent ~ task:', task)
|
|
130
98
|
activeTask.value = task
|
|
131
99
|
activeContent.value = content
|
|
132
|
-
scrollTo(0,
|
|
100
|
+
window.scrollTo({ top: 0, behavior: 'smooth' })
|
|
133
101
|
}
|
|
134
102
|
|
|
103
|
+
const setActiveContentFromModal = (task, content) => {
|
|
104
|
+
setActiveContent(task, content)
|
|
105
|
+
if (isMobile.value) showTasksModal.value = false
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const totalTaskCount = computed(() => {
|
|
109
|
+
return props.tasks.reduce((sum, task) => sum + (task.content?.length || 0), 0)
|
|
110
|
+
})
|
|
111
|
+
|
|
135
112
|
const getNextTask = () => {
|
|
136
113
|
for (const task of props.tasks) {
|
|
137
114
|
for (const content of task.content) {
|
|
@@ -149,12 +126,244 @@ const getNextTask = () => {
|
|
|
149
126
|
}
|
|
150
127
|
}
|
|
151
128
|
}
|
|
129
|
+
return null
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const handleNextTask = () => {
|
|
133
|
+
const next = getNextTask()
|
|
134
|
+
|
|
135
|
+
// ✅ No more tasks → emit completion
|
|
136
|
+
if (!next) {
|
|
137
|
+
emit('allCompleted')
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// otherwise go to next task
|
|
142
|
+
setActiveContent(next.task, next.content)
|
|
152
143
|
}
|
|
153
144
|
</script>
|
|
154
145
|
|
|
146
|
+
<template>
|
|
147
|
+
<Container>
|
|
148
|
+
<Row>
|
|
149
|
+
<Column cols="12">
|
|
150
|
+
<h2 class="fw-bold my-4">{{ props.activePlanner?.name }}'s planner</h2>
|
|
151
|
+
</Column>
|
|
152
|
+
</Row>
|
|
153
|
+
|
|
154
|
+
<Row>
|
|
155
|
+
<Column cols="12" md="7">
|
|
156
|
+
<BCard class="shadow-sm border-3 rounded-3 p-1">
|
|
157
|
+
<Row class="mb-3 d-md-none">
|
|
158
|
+
<Column cols="7">
|
|
159
|
+
<h6 class="fw-bold mt-0 mb-0">
|
|
160
|
+
<span
|
|
161
|
+
v-if="isTaskCompleted(activeTask.id, activeContent.id)"
|
|
162
|
+
class="text-success"
|
|
163
|
+
>
|
|
164
|
+
<TickCircleIcon style="width: 1em; height: 1em" />
|
|
165
|
+
</span>
|
|
166
|
+
<span v-else class="text-muted">
|
|
167
|
+
<TickCircleIcon
|
|
168
|
+
class="opacity-25"
|
|
169
|
+
style="width: 1em; height: 1em"
|
|
170
|
+
/>
|
|
171
|
+
</span>
|
|
172
|
+
{{ activeTask.title }}
|
|
173
|
+
</h6>
|
|
174
|
+
</Column>
|
|
175
|
+
<Column cols="5" class="text-end">
|
|
176
|
+
<BButton
|
|
177
|
+
class="rounded-2"
|
|
178
|
+
@click="showTasksModal = true"
|
|
179
|
+
variant="outline-secondary"
|
|
180
|
+
>
|
|
181
|
+
View All tasks
|
|
182
|
+
<ChevRightIcon class="ms-2" style="width: 1em; height: 1em" />
|
|
183
|
+
</BButton>
|
|
184
|
+
</Column>
|
|
185
|
+
</Row>
|
|
186
|
+
|
|
187
|
+
<h4 class="fw-bold mt-0 mb-3 d-none d-md-block">
|
|
188
|
+
<span
|
|
189
|
+
v-if="isTaskCompleted(activeTask.id, activeContent.id)"
|
|
190
|
+
class="text-success"
|
|
191
|
+
>
|
|
192
|
+
<TickCircleIcon style="width: 1em; height: 1em" />
|
|
193
|
+
</span>
|
|
194
|
+
<span v-else class="text-muted">
|
|
195
|
+
<TickCircleIcon
|
|
196
|
+
class="opacity-25"
|
|
197
|
+
style="width: 1em; height: 1em"
|
|
198
|
+
/>
|
|
199
|
+
</span>
|
|
200
|
+
{{ activeTask.title }}
|
|
201
|
+
</h4>
|
|
202
|
+
|
|
203
|
+
<BCardText v-html="activeContent.html"> </BCardText>
|
|
204
|
+
<BButton
|
|
205
|
+
class="task-btn w-100 d-flex justify-content-between align-items-center"
|
|
206
|
+
:class="{
|
|
207
|
+
completed: isTaskCompleted(activeTask.id, activeContent.id),
|
|
208
|
+
}"
|
|
209
|
+
@click="toggleTask(activeTask.id, activeContent.id)"
|
|
210
|
+
>
|
|
211
|
+
<span>
|
|
212
|
+
{{
|
|
213
|
+
isTaskCompleted(activeTask.id, activeContent.id)
|
|
214
|
+
? "You've completed this task"
|
|
215
|
+
: 'Mark this task as completed'
|
|
216
|
+
}}
|
|
217
|
+
</span>
|
|
218
|
+
|
|
219
|
+
<span
|
|
220
|
+
v-if="isTaskCompleted(activeTask.id, activeContent.id)"
|
|
221
|
+
class="completed"
|
|
222
|
+
>
|
|
223
|
+
<TickCircleIcon class="ms-2" style="width: 2em; height: 2em" />
|
|
224
|
+
</span>
|
|
225
|
+
<span v-else class="text-muted">
|
|
226
|
+
<TickCircleIcon
|
|
227
|
+
class="ms-2 opacity-25"
|
|
228
|
+
style="width: 2em; height: 2em"
|
|
229
|
+
/>
|
|
230
|
+
</span>
|
|
231
|
+
</BButton>
|
|
232
|
+
</BCard>
|
|
233
|
+
|
|
234
|
+
<BButton
|
|
235
|
+
v-show="getNextTask()"
|
|
236
|
+
class="next-task card w-100 d-flex shadow-sm border-3 rounded-3 p-4 mt-4 text-end"
|
|
237
|
+
:class="{
|
|
238
|
+
completed: isTaskCompleted(activeTask.id, activeContent.id),
|
|
239
|
+
}"
|
|
240
|
+
@click="handleNextTask"
|
|
241
|
+
>
|
|
242
|
+
<h4 class="fw-bold mt-0 mb-3">
|
|
243
|
+
Go to next task
|
|
244
|
+
<ChevRightIcon style="width: 1em; height: 1em" />
|
|
245
|
+
</h4>
|
|
246
|
+
<p class="mb-0">
|
|
247
|
+
<span class="text-decoration-underline">
|
|
248
|
+
<strong>
|
|
249
|
+
{{
|
|
250
|
+
getNextTask()
|
|
251
|
+
? getNextTask().content.btnText
|
|
252
|
+
: 'No more tasks'
|
|
253
|
+
}}
|
|
254
|
+
</strong>
|
|
255
|
+
</span>
|
|
256
|
+
</p>
|
|
257
|
+
</BButton>
|
|
258
|
+
</Column>
|
|
259
|
+
|
|
260
|
+
<Column cols="12" md="5" class="d-none d-md-block">
|
|
261
|
+
<BCard class="shadow-sm border-3 rounded-3 p-1">
|
|
262
|
+
<h4 class="fw-bold mb-3">All tasks</h4>
|
|
263
|
+
|
|
264
|
+
<div v-for="task in props.tasks" :key="task.id" class="mb-3">
|
|
265
|
+
<h5 class="fw-bold">{{ task.title }}</h5>
|
|
266
|
+
<div v-for="content in task.content" :key="content.id">
|
|
267
|
+
<BButton
|
|
268
|
+
class="task-list-btn d-flex justify-content-between align-items-center w-100 border-0 rounded-2 p-2 mb-2 text-start text-dark fw-bold"
|
|
269
|
+
:class="
|
|
270
|
+
isTaskCompleted(task.id, content.id)
|
|
271
|
+
? activeContent.id === content.id
|
|
272
|
+
? 'bg-success-subtle active-done'
|
|
273
|
+
: 'bg-success-subtle fw-bold'
|
|
274
|
+
: activeContent.id === content.id
|
|
275
|
+
? 'active'
|
|
276
|
+
: 'bg-light'
|
|
277
|
+
"
|
|
278
|
+
@click="setActiveContent(task, content)"
|
|
279
|
+
>
|
|
280
|
+
<span class="text-decoration-underline">
|
|
281
|
+
{{ content.btnText }}
|
|
282
|
+
</span>
|
|
283
|
+
<span
|
|
284
|
+
v-if="isTaskCompleted(task.id, content.id)"
|
|
285
|
+
class="text-success"
|
|
286
|
+
>
|
|
287
|
+
<TickCircleIcon
|
|
288
|
+
class="ms-2"
|
|
289
|
+
style="width: 1.5em; height: 1.5em"
|
|
290
|
+
/>
|
|
291
|
+
</span>
|
|
292
|
+
<span v-else class="text-muted">
|
|
293
|
+
<TickCircleIcon
|
|
294
|
+
class="ms-2 opacity-25"
|
|
295
|
+
style="width: 1.5em; height: 1.5em"
|
|
296
|
+
/>
|
|
297
|
+
</span>
|
|
298
|
+
</BButton>
|
|
299
|
+
</div>
|
|
300
|
+
</div>
|
|
301
|
+
</BCard>
|
|
302
|
+
</Column>
|
|
303
|
+
</Row>
|
|
304
|
+
|
|
305
|
+
<Row>
|
|
306
|
+
<Column>
|
|
307
|
+
<BModal
|
|
308
|
+
v-if="showTasksModal"
|
|
309
|
+
v-model="showTasksModal"
|
|
310
|
+
title="All tasks"
|
|
311
|
+
size="xl"
|
|
312
|
+
no-footer
|
|
313
|
+
>
|
|
314
|
+
<div>
|
|
315
|
+
<div v-for="task in props.tasks" :key="'m-' + task.id" class="mb-3">
|
|
316
|
+
<h5 class="fw-bold">{{ task.title }}</h5>
|
|
317
|
+
<div
|
|
318
|
+
v-for="content in task.content"
|
|
319
|
+
:key="'mcontent-' + content.id"
|
|
320
|
+
>
|
|
321
|
+
<BButton
|
|
322
|
+
class="task-list-btn d-flex justify-content-between align-items-center w-100 border-0 rounded-2 p-2 mb-2 text-start text-dark fw-bold"
|
|
323
|
+
:class="
|
|
324
|
+
isTaskCompleted(task.id, content.id)
|
|
325
|
+
? activeContent.id === content.id
|
|
326
|
+
? 'bg-success-subtle active-done'
|
|
327
|
+
: 'bg-success-subtle fw-bold'
|
|
328
|
+
: activeContent.id === content.id
|
|
329
|
+
? 'active'
|
|
330
|
+
: 'bg-light'
|
|
331
|
+
"
|
|
332
|
+
@click="setActiveContentFromModal(task, content)"
|
|
333
|
+
>
|
|
334
|
+
<span class="text-decoration-underline">
|
|
335
|
+
{{ content.btnText }}
|
|
336
|
+
</span>
|
|
337
|
+
<span
|
|
338
|
+
v-if="isTaskCompleted(task.id, content.id)"
|
|
339
|
+
class="text-success"
|
|
340
|
+
>
|
|
341
|
+
<TickCircleIcon
|
|
342
|
+
class="ms-2"
|
|
343
|
+
style="width: 1.5em; height: 1.5em"
|
|
344
|
+
/>
|
|
345
|
+
</span>
|
|
346
|
+
<span v-else class="text-muted">
|
|
347
|
+
<TickCircleIcon
|
|
348
|
+
class="ms-2 opacity-25"
|
|
349
|
+
style="width: 1.5em; height: 1.5em"
|
|
350
|
+
/>
|
|
351
|
+
</span>
|
|
352
|
+
</BButton>
|
|
353
|
+
</div>
|
|
354
|
+
</div>
|
|
355
|
+
</div>
|
|
356
|
+
</BModal>
|
|
357
|
+
</Column>
|
|
358
|
+
</Row>
|
|
359
|
+
</Container>
|
|
360
|
+
</template>
|
|
361
|
+
|
|
155
362
|
<style lang="scss" scoped>
|
|
156
363
|
@import './../../../../includes/scss/all.scss';
|
|
157
364
|
|
|
365
|
+
$fuchsia: #ea338f;
|
|
366
|
+
|
|
158
367
|
.active {
|
|
159
368
|
color: black !important;
|
|
160
369
|
background-color: $yellow !important;
|
|
@@ -162,9 +371,103 @@ const getNextTask = () => {
|
|
|
162
371
|
.active-done {
|
|
163
372
|
border-left: 10px solid $green !important;
|
|
164
373
|
}
|
|
165
|
-
.disabled {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
374
|
+
// .disabled {
|
|
375
|
+
// pointer-events: none;
|
|
376
|
+
// opacity: 0.5;
|
|
377
|
+
// cursor: not-allowed;
|
|
378
|
+
// }
|
|
379
|
+
:deep(span.blockquote) {
|
|
380
|
+
display: block;
|
|
381
|
+
font-style: italic;
|
|
382
|
+
color: #222;
|
|
383
|
+
background-color: #f6f6f6;
|
|
384
|
+
border-left: 4px solid #ccc;
|
|
385
|
+
padding: 0.75rem 1rem;
|
|
386
|
+
margin: 1rem 0;
|
|
387
|
+
border-radius: 4px;
|
|
388
|
+
font-size: 1rem;
|
|
389
|
+
line-height: 1.5;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
.next-task {
|
|
393
|
+
background-color: #fff; // default gray background
|
|
394
|
+
color: #000;
|
|
395
|
+
font-weight: 600;
|
|
396
|
+
padding: 1rem;
|
|
397
|
+
font-size: 1rem;
|
|
398
|
+
transition: all 0.2s ease-in-out;
|
|
399
|
+
|
|
400
|
+
/* Active/completed state */
|
|
401
|
+
&.completed {
|
|
402
|
+
background-color: #f6f6f6;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/* Hover state */
|
|
406
|
+
&:hover {
|
|
407
|
+
background-color: #fff;
|
|
408
|
+
border-color: #222;
|
|
409
|
+
border-width: 3px;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/* Focus state */
|
|
413
|
+
&:focus {
|
|
414
|
+
background-color: #fff;
|
|
415
|
+
border-color: #222;
|
|
416
|
+
border-width: 3px;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
.task-btn {
|
|
421
|
+
background-color: #f2f1f5; // default gray background
|
|
422
|
+
color: #000;
|
|
423
|
+
font-weight: 600;
|
|
424
|
+
border: 2px solid transparent;
|
|
425
|
+
border-radius: 0.5rem;
|
|
426
|
+
padding: 1rem;
|
|
427
|
+
font-size: 1rem;
|
|
428
|
+
transition: all 0.2s ease-in-out;
|
|
429
|
+
|
|
430
|
+
/* Hover state */
|
|
431
|
+
&:hover {
|
|
432
|
+
background-color: #fff;
|
|
433
|
+
border-color: #222;
|
|
434
|
+
border-width: 2px;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/* Focus state */
|
|
438
|
+
&:focus {
|
|
439
|
+
background-color: #fff;
|
|
440
|
+
border-color: #222;
|
|
441
|
+
border-width: 3px;
|
|
442
|
+
outline: solid 3px $fuchsia !important;
|
|
443
|
+
outline-offset: 3px;
|
|
444
|
+
border-radius: 0.5rem !important;
|
|
445
|
+
box-shadow: none !important;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/* Active/completed state */
|
|
449
|
+
&.completed {
|
|
450
|
+
background-color: #4b8750;
|
|
451
|
+
color: #fff;
|
|
452
|
+
border-color: #4b8750;
|
|
453
|
+
border-width: 3px;
|
|
454
|
+
outline: solid 3px transparent !important;
|
|
455
|
+
outline-offset: 3px;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
.task-list-btn {
|
|
460
|
+
transition:
|
|
461
|
+
background-color 0.2s ease-in-out,
|
|
462
|
+
color 0.2s ease-in-out;
|
|
463
|
+
&:hover {
|
|
464
|
+
background: #5562a9 !important;
|
|
465
|
+
color: #fff !important;
|
|
466
|
+
border-color: transparent;
|
|
467
|
+
|
|
468
|
+
svg {
|
|
469
|
+
color: #fff !important;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
169
472
|
}
|
|
170
473
|
</style>
|