Skip to content

Commit 1c53c15

Browse files
authored
Adding Hazard Hunt information into the UI (#144)
1 parent 1d6e38f commit 1c53c15

File tree

8 files changed

+252
-30
lines changed

8 files changed

+252
-30
lines changed

2wr-app/src/api/hazard-hunt-api.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,7 @@ export default {
44
async getDocuments() {
55
return (await baseApiInstance.getInstance()).get('hazardhunt-list');
66
},
7+
async get(id) {
8+
return (await baseApiInstance.getInstance()).get(`hazardhunt-by-id/${id}`);
9+
}
710
};

2wr-app/src/api/hazard-info-api.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ export default {
77

88
async get(id) {
99
return (await baseApiInstance.getInstance()).get(`hazardinfo-by-id/${id}`);
10-
},
10+
}
1111
};

2wr-app/src/components/prepare/hazards/hazard-hunt-list.vue

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,33 @@
22
<v-container class="py-0">
33
<v-app-bar app flat dense fixed color="background">
44
<v-icon class="mr-2" v-on:click="goBack()">mdi-arrow-left</v-icon>
5-
<v-icon class="mr-2">mdi-shield-search</v-icon>
5+
<v-icon class="mr-2">mdi-shield-alert-outline</v-icon>
66
<v-toolbar-title>Hazard Hunt</v-toolbar-title>
77
</v-app-bar>
88
<v-progress-linear
99
v-if="loading"
1010
indeterminate
1111
color="green"
1212
></v-progress-linear>
13-
<v-data-iterator v-if="!loading" :items="hunts" disable-pagination disable-sort hide-default-footer
14-
:search="search">
15-
<template v-slot:header>
16-
<v-text-field
17-
v-model="search"
18-
clearable
19-
label="Search"
20-
append-icon="mdi-magnify">
21-
</v-text-field>
22-
</template>
23-
<template v-slot:default="props">
24-
<v-card v-for="item in props.items" :key="item.id" class="my-4" ripple dark>
25-
<v-card-title class="white--text">
26-
<v-col class="col-9">
27-
<!-- <v-icon class="mr-2 white--text">{{item.icon}}</v-icon> -->{{ item.name }}
28-
</v-col>
29-
</v-card-title>
30-
<v-card-text>{{ item.description }}</v-card-text>
31-
</v-card>
32-
</template>
33-
</v-data-iterator>
13+
<v-row dense>
14+
<v-col
15+
v-for="item in items"
16+
:key="item.id"
17+
cols="6"
18+
>
19+
<v-card
20+
@click="viewItem(item.id)">
21+
<v-img
22+
:src="item.iconUrl"
23+
class="white--text align-end"
24+
gradient="to bottom, rgba(0,0,0,.1), rgba(0,0,0,.5)"
25+
height="200px"
26+
>
27+
<v-card-title v-text="item.name"></v-card-title>
28+
</v-img>
29+
</v-card>
30+
</v-col>
31+
</v-row>
3432
</v-container>
3533
</template>
3634

@@ -45,15 +43,18 @@ export default {
4543
};
4644
},
4745
computed: mapState({
48-
hunts: state => state.hazardHuntStore.list
46+
items: state => state.hazardHuntStore.list
4947
}),
5048
async created() {
5149
await this.$store.dispatch(`hazardHuntStore/getHazardHuntsAsync`);
5250
this.loading = false;
5351
},
5452
methods: {
5553
goBack() {
56-
window.history.length > 1 ? this.$router.go(-1) : this.$router.push('/');
54+
window.history.length > 1 ? this.$router.go(-1) : this.$router.push('/');
55+
},
56+
viewItem(id){
57+
this.$router.push(`/prepare/hazardhunt/${id}`);
5758
}
5859
}
5960
}
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
<template>
2+
<v-container class="py-0">
3+
<v-app-bar app flat dense fixed color="background">
4+
<v-icon class="mr-2" v-on:click="goBack()">mdi-arrow-left</v-icon>
5+
<v-img :src="item.iconUrl" max-height="48" max-width="48" class="mr-2"></v-img>
6+
<v-toolbar-title>{{item ? item.name : 'Hazard Information'}}</v-toolbar-title>
7+
</v-app-bar>
8+
<v-row dense>
9+
<v-col cols="12">
10+
<p class="pa-2 headline">{{item.description}}</p>
11+
</v-col>
12+
<v-col cols="12">
13+
<v-img v-if="mediaUrlIsImage" :src="item.mediaUrl"></v-img>
14+
<!--TODO: Add option for videos once we have some sample videos -->
15+
</v-col>
16+
<v-col cols="12" class="text-center">
17+
<h2>{{item.name}} Safety</h2>
18+
</v-col>
19+
<v-col cols="12" class="text-center">
20+
<v-btn x-large color="primary" width="80%" @click="beforeDialog = true">Before</v-btn>
21+
</v-col>
22+
<v-col cols="12" class="text-center">
23+
<v-btn x-large color="primary" width="80%" @click="duringDialog = true">During</v-btn>
24+
</v-col>
25+
<v-col cols="12" class="text-center">
26+
<v-btn x-large color="primary" width="80%" @click="afterDialog = true">After</v-btn>
27+
</v-col>
28+
<v-col cols="12" class="text-center">
29+
<h2>{{item.name}} Resources</h2>
30+
</v-col>
31+
<v-col cols="12">
32+
<ul class="mb-6">
33+
<li v-for="link in item.externalLinks" :key={link} class="pa-1">
34+
<a :href="link" target="_blank">{{link}}</a><v-icon small class="ml-2">mdi-open-in-new</v-icon></li>
35+
</ul>
36+
</v-col>
37+
</v-row>
38+
<v-dialog
39+
v-model="beforeDialog"
40+
fullscreen
41+
hide-overlay
42+
transition="dialog-bottom-transition"
43+
scrollable
44+
>
45+
<v-card tile color="background">
46+
<v-toolbar class="flex-grow-0 mb-3"
47+
flat
48+
dark
49+
color="primary"
50+
>
51+
<v-btn
52+
icon
53+
dark
54+
@click="beforeDialog = false"
55+
>
56+
<v-icon>mdi-close</v-icon>
57+
</v-btn>
58+
<v-toolbar-title>{{item.name}} Safety: Before</v-toolbar-title>
59+
</v-toolbar>
60+
<v-card-text v-html="item.beforeSafetyDetails">
61+
</v-card-text>
62+
</v-card>
63+
</v-dialog>
64+
<v-dialog
65+
v-model="duringDialog"
66+
fullscreen
67+
hide-overlay
68+
transition="dialog-bottom-transition"
69+
scrollable
70+
>
71+
<v-card tile color="background">
72+
<v-toolbar class="flex-grow-0 mb-3"
73+
flat
74+
dark
75+
color="primary"
76+
>
77+
<v-btn
78+
icon
79+
dark
80+
@click="duringDialog = false"
81+
>
82+
<v-icon>mdi-close</v-icon>
83+
</v-btn>
84+
<v-toolbar-title>{{item.name}} Safety: During</v-toolbar-title>
85+
</v-toolbar>
86+
<v-card-text v-html="item.duringSafetyDetails">
87+
</v-card-text>
88+
</v-card>
89+
</v-dialog>
90+
<v-dialog
91+
v-model="afterDialog"
92+
fullscreen
93+
hide-overlay
94+
transition="dialog-bottom-transition"
95+
scrollable
96+
>
97+
<v-card tile color="background">
98+
<v-toolbar class="flex-grow-0 mb-3"
99+
flat
100+
dark
101+
color="primary"
102+
>
103+
<v-btn
104+
icon
105+
dark
106+
@click="afterDialog = false"
107+
>
108+
<v-icon>mdi-close</v-icon>
109+
</v-btn>
110+
<v-toolbar-title>{{item.name}} Safety: After</v-toolbar-title>
111+
</v-toolbar>
112+
<v-card-text v-html="item.afterSafetyDetails">
113+
</v-card-text>
114+
</v-card>
115+
</v-dialog>
116+
</v-container>
117+
</template>
118+
119+
<script>
120+
import { mapState } from 'vuex';
121+
122+
export default {
123+
data: () => {
124+
return {
125+
beforeDialog: false,
126+
duringDialog: false,
127+
afterDialog: false
128+
};
129+
},
130+
computed: {
131+
...mapState({
132+
item: (state) => state.hazardHuntStore.item,
133+
}),
134+
mediaUrlIsImage: function() {
135+
const mediaUrl = this.item?.mediaUrl?.toLowerCase();
136+
if (!mediaUrl) return false;
137+
138+
return mediaUrl.endsWith(".png") ||
139+
mediaUrl.endsWith(".jpg") ||
140+
mediaUrl.endsWith(".jpeg") ||
141+
mediaUrl.endsWith(".webp") ||
142+
mediaUrl.endsWith(".pjpeg") ||
143+
mediaUrl.endsWith(".svg") ||
144+
mediaUrl.endsWith(".pjp");
145+
}
146+
},
147+
mounted: function () {
148+
// Load the thing
149+
this.$store.dispatch(
150+
`hazardHuntStore/getHazardHuntAsync`,
151+
this.$route.params.id
152+
);
153+
},
154+
methods: {
155+
goBack() {
156+
window.history.length > 1 ? this.$router.go(-1) : this.$router.push('/');
157+
}
158+
}
159+
}
160+
</script>
161+
162+
<style>
163+
164+
</style>

2wr-app/src/components/prepare/prepare-landing.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@
5757
</v-card-text>
5858
</v-card>
5959

60-
<!-- Hiding for now. Requirements in progress
61-
<v-card
60+
61+
<v-card
6262
to="prepare/hazardhunt"
6363
color="primary"
6464
class="my-4"
@@ -72,7 +72,7 @@
7272
<div class="text-subtitle-1">Observe your surroundings and identify common hazards that could
7373
mean danger in certain situations.</div>
7474
</v-card-text>
75-
</v-card> -->
75+
</v-card>
7676

7777
</v-col>
7878
</v-row>

2wr-app/src/router/index.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import EmergencyKitEditPage from '../views/prepare/emergency-kits/emergency-kit-
99
import HazardHuntListing from '../views/prepare/hazards/hazard-hunt-list-view.vue';
1010
import HazardInfoListing from '../views/prepare/hazards/hazard-info-list-view.vue';
1111
import HazardInfo from '../views/prepare/hazards/hazard-info-view.vue';
12+
import HazardHunt from '../views/prepare/hazards/hazard-hunt-view.vue';
1213
import Recent from '../views/recent/recent.vue';
1314
import Settings from '../views/settings/settings.vue';
1415

@@ -65,7 +66,16 @@ const routes = [{
6566
meta: {
6667
requiresAuth: true
6768
}
68-
}, {
69+
},
70+
{
71+
path: '/prepare/hazardhunt/:id',
72+
name: 'hazardhuntdetails',
73+
component: HazardHunt,
74+
meta: {
75+
requiresAuth: true
76+
}
77+
},
78+
{
6979
path: '/prepare/hazardinfo',
7080
name: 'hazardinfolist',
7181
component: HazardInfoListing,

2wr-app/src/store/modules/prepare/hazards/hazard-hunt-store.js

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,21 @@ import localForage from 'localforage';
33

44
const CACHE_KEY = 'HazardHunts';
55
const SET_LIST = 'SET_LIST';
6+
const SET_ITEM = 'SET_ITEM';
67

78
export default {
89
namespaced: true,
910
state: {
10-
list: []
11+
list: [],
12+
item: null
1113
},
1214
mutations: {
1315
[SET_LIST](state, payload) {
1416
state.list = payload;
1517
},
18+
[SET_ITEM](state, payload) {
19+
state.item = payload;
20+
}
1621
},
1722
actions: {
1823
async getHazardHuntsAsync({ commit, rootState }) {
@@ -30,6 +35,31 @@ export default {
3035
}
3136

3237
}
38+
},
39+
async getHazardHuntAsync({ commit, rootState} , id) {
40+
41+
try {
42+
commit("setBusy", null, { root: true });
43+
commit("setError", "", { root: true });
44+
const itemCacheKey = `${CACHE_KEY}/${id}`
45+
if (rootState.globalStore.online) {
46+
let response = await api.get(id);
47+
commit(SET_ITEM, response.data);
48+
await localForage.setItem(itemCacheKey, response.data);
49+
} else {
50+
var data = await localForage.getItem(itemCacheKey)
51+
if (data) {
52+
console.log("Serving from cache");
53+
commit(SET_ITEM, data);
54+
} else {
55+
console.log("Offline without data");
56+
}
57+
}
58+
} catch {
59+
commit("setError", "Could not load hazard hunt.", { root: true });
60+
} finally {
61+
commit("clearBusy", null, { root: true });
62+
}
3363
}
3464
}
3565
};
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<template>
2+
<HazardHuntComponent></HazardHuntComponent>
3+
</template>
4+
5+
<script>
6+
import HazardHuntComponent from '@/components/prepare/hazards/hazard-hunt.vue'
7+
8+
export default {
9+
name: 'HazardHunt',
10+
components: {
11+
HazardHuntComponent
12+
}
13+
}
14+
</script>

0 commit comments

Comments
 (0)