Skip to content
Snippets Groups Projects
Verified Commit d48546a7 authored by Jonathan Weth's avatar Jonathan Weth :keyboard:
Browse files

Add mobile view for timetables and improve select for timetables

parent 3f75b026
No related branches found
No related tags found
1 merge request!301New data model based on calendar events
......@@ -26,9 +26,17 @@ export default {
<div class="text-h5 grey--text text--darken-2 mb-2">
{{ $t(titleKey) }}
</div>
<div class="text-body-2 grey--text text--darken-2">
<div
class="text-body-2 grey--text text--darken-2"
v-if="$vuetify.breakpoint.lgAndUp"
>
{{ $t(descriptionKey) }}
</div>
<div v-if="$vuetify.breakpoint.mdAndDown">
<v-btn color="primary" @click="$emit('selectTimetable')" class="mt-4">
{{ $t("chronos.timetable.select") }}
</v-btn>
</div>
</div>
</v-card>
</template>
<script>
import timetableTypes from "./timetableTypes";
export default {
name: "SelectTimetable",
props: {
value: {
type: String | null,
required: true,
},
availableTimetables: {
type: Array,
required: true,
},
},
data() {
return {
selected: null,
selectedFull: null,
search: "",
selectedTypes: ["GROUP", "TEACHER", "ROOM"],
types: timetableTypes,
};
},
watch: {
value(val) {
this.selectedFull = val;
this.selected = val.id;
},
selectedFull(val) {
this.$emit("input", val);
},
},
computed: {
availableTimetablesFiltered() {
// Filter timetables by selected types
return this.availableTimetables.filter((timetable) => {
return this.selectedTypes.indexOf(timetable.type) !== -1;
});
},
},
};
</script>
<template>
<div>
<v-card-text class="mb-0">
<!-- Search field for timetables -->
<v-text-field
search
filled
rounded
clearable
autofocus
v-model="search"
:placeholder="$t('chronos.timetable.search')"
prepend-inner-icon="mdi-magnify"
hide-details="auto"
class="mb-2"
/>
<!-- Filter by timetable types -->
<v-btn-toggle v-model="selectedTypes" dense block multiple class="d-flex">
<v-btn
v-for="type in types"
:key="type.id"
class="flex-grow-1"
:value="type.id"
>
{{ type.name }}
</v-btn>
</v-btn-toggle>
</v-card-text>
<!-- Select of available timetables -->
<v-data-iterator
:items="availableTimetablesFiltered"
item-key="id"
:search="search"
single-expand
disable-pagination
>
<template #default="{ items, isExpanded, expand }">
<v-list class="scrollable-list">
<v-list-item-group v-model="selected">
<v-list-item
v-for="item in items"
@click="selectedFull = item"
:value="item.id"
:key="item.id"
>
<v-list-item-icon color="primary">
<v-icon v-if="item.type in types" color="secondary">
{{ types[item.type].icon }}
</v-icon>
<v-icon v-else color="secondary">mdi-grid</v-icon>
</v-list-item-icon>
<v-list-item-content>
<v-list-item-title>{{ item.name }}</v-list-item-title>
</v-list-item-content>
<v-list-item-action>
<v-icon>mdi-chevron-right</v-icon>
</v-list-item-action>
</v-list-item>
</v-list-item-group>
</v-list>
</template>
</v-data-iterator>
</div>
</template>
<style scoped>
.scrollable-list {
height: 100%;
overflow-y: scroll;
}
</style>
<script>
import { gqlAvailableTimetables } from "./timetables.graphql";
import NoTimetableCard from "./NoTimetableCard.vue";
import SelectTimetable from "./SelectTimetable.vue";
import timetableTypes from "./timetableTypes";
export default {
name: "Timetable",
components: { NoTimetableCard },
components: { NoTimetableCard, SelectTimetable },
apollo: {
availableTimetables: {
query: gqlAvailableTimetables,
......@@ -14,43 +16,26 @@ export default {
return {
availableTimetables: [],
selected: null,
selectedFull: null,
search: "",
selectedTypes: ["GROUP", "TEACHER", "ROOM"],
types: {
GROUP: {
name: "Groups",
id: "GROUP",
icon: "mdi-account-group-outline",
},
TEACHER: {
name: "Teachers",
id: "TEACHER",
icon: "mdi-account-outline",
},
ROOM: { name: "Rooms", id: "ROOM", icon: "mdi-door" },
},
types: timetableTypes,
selectDialog: false,
};
},
watch: {
selected(selected) {
if (selected == null) {
this.selectedFull = null;
}
},
selectedFull(selectedFull) {
// Align navigation with currently selected timetable
if (!selectedFull) {
if (!selected) {
this.$router.push({ name: "chronos.timetable" });
} else if (
selectedFull.objId !== this.$route.params.id ||
selectedFull.type !== this.$route.params.type
selected.objId !== this.$route.params.id ||
selected.type !== this.$route.params.type
) {
this.$router.push({
name: "chronos.timetableWithId",
params: {
type: selectedFull.type.toLowerCase(),
id: selectedFull.objId,
type: selected.type.toLowerCase(),
id: selected.objId,
},
});
}
......@@ -59,7 +44,7 @@ export default {
methods: {
findNextTimetable(offset = 1) {
const currentIndex = this.availableTimetablesIds.indexOf(
this.selectedFull.id
this.selected.id
);
const newIndex = currentIndex + offset;
if (newIndex < 0 || newIndex >= this.availableTimetablesIds.length) {
......@@ -68,8 +53,7 @@ export default {
return this.availableTimetables[newIndex];
},
selectTimetable(timetable) {
this.selected = timetable.id;
this.selectedFull = timetable;
this.selected = timetable;
},
},
computed: {
......@@ -100,88 +84,77 @@ export default {
<template>
<div>
<v-row>
<v-col cols="2">
<v-dialog
v-model="selectDialog"
fullscreen
hide-overlay
transition="dialog-bottom-transition"
>
<v-card>
<v-card-text class="mb-0">
<!-- Search field for timetables -->
<v-text-field
search
filled
rounded
clearable
autofocus
v-model="search"
:placeholder="$t('chronos.timetable.search')"
prepend-inner-icon="mdi-magnify"
hide-details="auto"
class="mb-2"
/>
<!-- Filter by timetable types -->
<v-btn-toggle
v-model="selectedTypes"
dense
block
multiple
class="d-flex"
>
<v-btn
v-for="type in types"
:key="type.id"
class="flex-grow-1"
:value="type.id"
>
{{ type.name }}
</v-btn>
</v-btn-toggle>
</v-card-text>
<v-toolbar dark color="primary">
<v-toolbar-title>{{
$t("chronos.timetable.select")
}}</v-toolbar-title>
<v-spacer></v-spacer>
</v-toolbar>
<select-timetable
v-model="selected"
@input="selectDialog = false"
:availableTimetables="availableTimetables"
/>
</v-card>
</v-dialog>
<!-- Select of available timetables -->
<v-data-iterator
:items="availableTimetablesFiltered"
item-key="id"
:search="search"
single-expand
>
<template #default="{ items, isExpanded, expand }">
<v-list>
<v-list-item-group v-model="selected">
<v-list-item
v-for="item in items"
@click="selectedFull = item"
:value="item.id"
:key="item.id"
>
<v-list-item-icon color="primary">
<v-icon v-if="item.type in types" color="secondary">
{{ types[item.type].icon }}
</v-icon>
<v-icon v-else color="secondary">mdi-grid</v-icon>
</v-list-item-icon>
<v-list-item-content>
<v-list-item-title>{{ item.name }}</v-list-item-title>
</v-list-item-content>
<v-list-item-action>
<v-icon>mdi-chevron-right</v-icon>
</v-list-item-action>
</v-list-item>
</v-list-item-group>
</v-list>
</template>
</v-data-iterator>
<v-col md="3" lg="3" xl="2" v-if="$vuetify.breakpoint.lgAndUp">
<v-card>
<select-timetable
v-model="selected"
:availableTimetables="availableTimetables"
/>
</v-card>
</v-col>
<v-col cols="10" class="full-height">
<v-col sm="12" md="12" lg="9" xl="10" class="full-height">
<!-- No timetable card-->
<no-timetable-card v-if="selectedFull == null" />
<no-timetable-card
v-if="selected == null"
@selectTimetable="selectDialog = true"
/>
<!-- Calendar card-->
<v-card v-else>
<div class="d-flex">
<div class="d-flex flex-column" v-if="$vuetify.breakpoint.smAndDown">
<v-card-title class="pt-2">
<v-btn
icon
:disabled="!prevTimetable"
@click="selectTimetable(prevTimetable)"
:title="$t('chronos.timetable.prev')"
class="mr-1"
>
<v-icon>mdi-chevron-left</v-icon>
</v-btn>
<v-spacer />
<v-chip outlined color="secondary" @click="selectDialog = true">
{{ selected.name }}
<v-icon right>mdi-chevron-down</v-icon>
</v-chip>
<v-spacer />
<v-btn
icon
:disabled="!nextTimetable"
@click="selectTimetable(nextTimetable)"
:title="$t('chronos.timetable.next')"
class="ml-1 float-right"
>
<v-icon>mdi-chevron-right</v-icon>
</v-btn>
</v-card-title>
</div>
<div class="d-flex flex-wrap justify-space-between mb-2" v-else>
<v-card-title>
{{ selectedFull.name }}
{{ selected.name }}
</v-card-title>
<v-spacer />
<div class="pa-2 mt-1">
<v-btn
icon
......@@ -192,7 +165,7 @@ export default {
<v-icon>mdi-chevron-left</v-icon>
</v-btn>
<v-chip label color="secondary" outlined class="mx-1">{{
selectedFull.shortName
selected.shortName
}}</v-chip>
<v-btn
icon
......@@ -206,7 +179,7 @@ export default {
</div>
<calendar-with-controls
:calendar-feeds="[{ name: 'lesson' }]"
:params="{ type: selectedFull.type, id: selectedFull.objId }"
:params="{ type: selected.type, id: selected.objId }"
/>
</v-card>
</v-col>
......
export default {
GROUP: {
name: "Groups",
id: "GROUP",
icon: "mdi-account-group-outline",
},
TEACHER: {
name: "Teachers",
id: "TEACHER",
icon: "mdi-account-outline",
},
ROOM: { name: "Rooms", id: "ROOM", icon: "mdi-door" },
};
......@@ -10,7 +10,8 @@
},
"search": "Search Timetables",
"prev": "Previous Timetable",
"next": "Next Timetable"
"next": "Next Timetable",
"select": "Select Timetable"
},
"lessons": {
"menu_title_daily": "Daily lessons"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment