mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-07-25 08:34:29 +00:00
274 lines
8.0 KiB
JavaScript
274 lines
8.0 KiB
JavaScript
import {CoreFilterCmpt} from "../../../components/filter/Filter.js";
|
|
import VueDatePicker from '../../vueDatepicker.js.php';
|
|
import ApiOrt from '../../../api/factory/ort.js'
|
|
export const Raumsuche = {
|
|
name: "Raumsuche",
|
|
components: {
|
|
VueDatePicker,
|
|
CoreFilterCmpt,
|
|
InputNumber: primevue.inputnumber,
|
|
},
|
|
inject: ["isMobile"],
|
|
data() {
|
|
return {
|
|
phrasenPromise: null,
|
|
phrasenResolved: false,
|
|
tabulatorUuid: Vue.ref(0),
|
|
tableBuiltResolve: null,
|
|
tableBuiltPromise: null,
|
|
roomtypes: null,
|
|
defaultType: {
|
|
raumtyp_kurzbz: '',
|
|
beschreibung: Vue.computed(() => this.$p.t('global/alle'))
|
|
},
|
|
anzahl: 1,
|
|
selectedType: null,
|
|
datum: new Date(),
|
|
von: Vue.ref({
|
|
hours: new Date().getHours(),
|
|
minutes: new Date().getMinutes()
|
|
}),
|
|
bis: Vue.ref({
|
|
hours: new Date().getHours() + 1,
|
|
minutes: new Date().getMinutes()
|
|
}),
|
|
datepickerTextInputOptions: {
|
|
enterSubmit: true,
|
|
tabSubmit: true,
|
|
selectOnFocus: true,
|
|
format: 'dd.MM.yyyy',
|
|
escClose: true
|
|
},
|
|
timepickerTextInputOptions: {
|
|
enterSubmit: true,
|
|
tabSubmit: true,
|
|
selectOnFocus: true,
|
|
format: 'HH:mm',
|
|
escClose: true
|
|
},
|
|
raumsucheTableOptions: {
|
|
height: Vue.ref(400),
|
|
index: 'ort_kurzbz',
|
|
layout: 'fitColumns',
|
|
placeholder: this.$p.t('global/noDataAvailable'),
|
|
columns: [
|
|
{title: Vue.computed(() => this.$p.t('rauminfo/raum_kurzbz')), field: 'ort_kurzbz', widthGrow: 1},
|
|
{title: Vue.computed(() => this.$p.t('global/bezeichnung')), field: 'bezeichnung', widthGrow: 2},
|
|
{title: Vue.computed(() => this.$p.t('rauminfo/raumnummer')), field: 'nummer', widthGrow: 1},
|
|
{title: Vue.computed(() => this.$p.t('rauminfo/personcap')), field: 'personen', widthGrow: 1},
|
|
{title: Vue.computed(() => this.$p.t('rauminfo/rauminfo')),
|
|
field: 'linkInfo', formatter: this.linkFormatter, widthGrow: 1},
|
|
{title: Vue.computed(() => this.$p.t('rauminfo/roomReservations')),
|
|
field: 'linkRes', formatter: this.linkFormatter, widthGrow: 1}
|
|
],
|
|
persistence: false,
|
|
},
|
|
raumsucheTableEventHandlers: [{
|
|
event: "tableBuilt",
|
|
handler: async () => {
|
|
this.tableBuiltResolve()
|
|
}
|
|
}
|
|
]};
|
|
},
|
|
computed: {
|
|
isDarkMode(){
|
|
return this.$theme.theme_name.value == 'dark';
|
|
}
|
|
},
|
|
methods: {
|
|
tableResolve(resolve) {
|
|
this.tableBuiltResolve = resolve
|
|
},
|
|
linkFormatter(cell) {
|
|
const val = cell.getValue();
|
|
const field = cell.getField();
|
|
const arialabel = (field === 'linkInfo')
|
|
? this.$p.t('rauminfo/rauminfo')
|
|
: this.$p.t('rauminfo/roomReservations');
|
|
if(val) {
|
|
return '<div style="display: flex; justify-content: center; align-items: center; height: 100%">' +
|
|
'<a href="'+val+'" aria-label="' + arialabel + '">' +
|
|
'<i class="fa fa-arrow-up-right-from-square me-1 fhc-primary-color" ></i>' +
|
|
'</a></div>'
|
|
} else {
|
|
return '<div style="display: flex; justify-content: center; align-items: center; height: 100%">' +
|
|
'-</div>'
|
|
}
|
|
},
|
|
roomPlanLink(room) {
|
|
return FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router
|
|
+ '/CisVue/Cms/getRoomInformation/' + room.ort_kurzbz
|
|
},
|
|
roomInfoLink(room) {
|
|
return FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router
|
|
+ '/CisVue/Cms/content/' + room.content_id
|
|
},
|
|
getTimeString(time) {
|
|
const hours = String(time.hours).padStart(2, '0');
|
|
const minutes = String(time.minutes).padStart(2, '0');
|
|
return `${hours}:${minutes}`
|
|
},
|
|
setupData(data){
|
|
const d = data.map(room => {
|
|
return {
|
|
ort_kurzbz: room.ort_kurzbz,
|
|
bezeichnung: room.bezeichnung.replace('&', '&'),
|
|
nummer: room.planbezeichnung,
|
|
personen: room.max_person,
|
|
linkInfo: room.content_id ? this.roomInfoLink(room) : null,
|
|
linkRes: this.roomPlanLink(room)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
this.$refs.raumsucheTable.tabulator.setData(d);
|
|
},
|
|
loadRoomTypes() {
|
|
this.$api.call(ApiOrt.getRoomTypes())
|
|
.then(res => {
|
|
res?.data?.forEach(type => {
|
|
type.beschreibung = type.beschreibung.replace('&', '&')
|
|
})
|
|
this.selectedType = this.defaultType
|
|
this.roomtypes = res?.data ?? []
|
|
})
|
|
},
|
|
loadRooms() {
|
|
this.$api.call(ApiOrt.getRooms(this.datum.toISOString(), this.getTimeString(this.von), this.getTimeString(this.bis), this.selectedType?.raumtyp_kurzbz ?? '', this.anzahl))
|
|
.then(res => {
|
|
if(res?.data?.retval) this.setupData(res.data.retval)
|
|
})
|
|
},
|
|
handleUuidDefined(uuid) {
|
|
this.tabulatorUuid = uuid
|
|
},
|
|
search(){
|
|
this.loadRooms()
|
|
},
|
|
setRoute(val) {
|
|
// TODO: router push
|
|
},
|
|
dateFormat(date) {
|
|
const day = String(date.getDate()).padStart(2, '0');
|
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
const year = date.getFullYear();
|
|
return `${day}.${month}.${year}`
|
|
},
|
|
timeFormat(date) {
|
|
const hours = String(date.getHours()).padStart(2, '0');
|
|
const minutes = String(date.getMinutes()).padStart(2, '0');
|
|
return `${hours}:${minutes}`;
|
|
},
|
|
async setupMounted() {
|
|
|
|
this.tableBuiltPromise = new Promise(this.tableResolve)
|
|
await this.tableBuiltPromise
|
|
|
|
this.loadRoomTypes()
|
|
this.loadRooms()
|
|
|
|
const tableID = this.tabulatorUuid ? ('-' + this.tabulatorUuid) : ''
|
|
const tableDataSet = document.getElementById('filterTableDataset' + tableID);
|
|
if(!tableDataSet) return
|
|
const rect = tableDataSet.getBoundingClientRect();
|
|
|
|
const h = window.visualViewport.height - rect.top - 100
|
|
if(this.$refs.raumsucheTable) {
|
|
this.$refs.raumsucheTable.$refs.table.style.setProperty('height', h+'px')
|
|
}
|
|
|
|
}
|
|
},
|
|
created() {
|
|
this.phrasenPromise = this.$p.loadCategory(['rauminfo', 'global'])
|
|
this.phrasenPromise.then(()=> {this.phrasenResolved = true})
|
|
},
|
|
mounted() {
|
|
this.setupMounted()
|
|
},
|
|
template: `
|
|
<h1 class="h3">{{$p.t('rauminfo/roomSearch')}}</h1>
|
|
<hr>
|
|
<div class="row">
|
|
<div :class="{'pb-1': isMobile}" class="col-12 col-lg-2">
|
|
<VueDatePicker
|
|
@contextmenu="(e) => {if (isMobile) {e.preventDefault();}}"
|
|
v-model="datum"
|
|
:dark="isDarkMode"
|
|
:clearable="false"
|
|
:enable-time-picker="false"
|
|
:format="dateFormat"
|
|
:text-input="datepickerTextInputOptions"
|
|
:min-date="new Date()"
|
|
date-picker
|
|
auto-apply
|
|
>
|
|
</VueDatePicker>
|
|
</div>
|
|
<div :class="{'pb-1': isMobile}" class="col-12 col-lg-1">
|
|
<VueDatePicker
|
|
@contextmenu="(e) => {if (isMobile) {e.preventDefault();}}"
|
|
v-model="von"
|
|
:dark="isDarkMode"
|
|
:clearable="false"
|
|
:format="timeFormat"
|
|
:text-input="timepickerTextInputOptions"
|
|
:is-24="true"
|
|
time-picker
|
|
auto-apply
|
|
>
|
|
</VueDatePicker>
|
|
</div>
|
|
<div :class="{'pb-1': isMobile}" class="col-12 col-lg-1">
|
|
<VueDatePicker
|
|
@contextmenu="(e) => {if (isMobile) {e.preventDefault();}}"
|
|
v-model="bis"
|
|
:dark="isDarkMode"
|
|
:clearable="false"
|
|
:format="timeFormat"
|
|
:text-input="timepickerTextInputOptions"
|
|
:is-24="true"
|
|
time-picker
|
|
auto-apply>
|
|
</VueDatePicker>
|
|
</div>
|
|
|
|
<div :class="{'pb-1': isMobile}" class="col-12 col-lg-3">
|
|
<select ref="raumtyp" id="raumtypSelect" v-model="selectedType" class="form-select"
|
|
:aria-label="$p.t('global/studiensemester_auswaehlen')" @change="setRoute($event.target.value)">
|
|
<option :key="defaultType" selected :value="defaultType">{{defaultType.beschreibung}}</option>
|
|
<option v-for="typ in roomtypes" :key="typ" :value="typ">{{typ.beschreibung}}</option>
|
|
</select>
|
|
</div>
|
|
|
|
|
|
<div :class="{'pb-2': isMobile}" class="col-12 col-lg-3">
|
|
<InputNumber v-model="anzahl"
|
|
:prefix="$p.t('rauminfo/minCapacity') + ': '"
|
|
inputId="anzahlInput" :min="1" :max="1000"
|
|
:style="{'width': '100%'}"
|
|
/>
|
|
</div>
|
|
<div class="col-12 col-lg-2">
|
|
<button class="btn btn-primary border-0" @click="search">{{ $p.t('rauminfo/roomSearch') }} <i class="fa fa-magnifying-glass"></i></button>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<core-filter-cmpt
|
|
v-if="phrasenResolved"
|
|
@uuidDefined="handleUuidDefined"
|
|
:title="''"
|
|
ref="raumsucheTable"
|
|
:tabulator-options="raumsucheTableOptions"
|
|
:tabulator-events="raumsucheTableEventHandlers"
|
|
tableOnly
|
|
:sideMenu="false"
|
|
/>
|
|
`,
|
|
};
|
|
|
|
export default Raumsuche;
|