Basic calendar view
This commit is contained in:
165
src/pages/schedule/BoatReservationPage.vue
Normal file
165
src/pages/schedule/BoatReservationPage.vue
Normal file
@@ -0,0 +1,165 @@
|
||||
<template>
|
||||
<div class="row justify-center">
|
||||
<q-btn-group rounded>
|
||||
<q-btn
|
||||
color="primary"
|
||||
rounded
|
||||
icon="keyboard_arrow_left"
|
||||
label="Prev"
|
||||
@click="onPrev"
|
||||
/>
|
||||
<q-btn
|
||||
color="primary"
|
||||
rounded
|
||||
icon="today"
|
||||
label="Today"
|
||||
@click="onToday"
|
||||
/>
|
||||
<q-btn
|
||||
color="primary"
|
||||
rounded
|
||||
icon-right="keyboard_arrow_right"
|
||||
label="Next"
|
||||
@click="onNext"
|
||||
/>
|
||||
</q-btn-group>
|
||||
</div>
|
||||
<div class="row justify-center">
|
||||
<div style="display: flex; max-width: 1024px; width: 100%">
|
||||
<q-calendar-resource
|
||||
ref="calendar"
|
||||
v-model="selectedDate"
|
||||
:model-resources="resources"
|
||||
resource-key="id"
|
||||
resource-label="name"
|
||||
:interval-start="6"
|
||||
:interval-count="12"
|
||||
animated
|
||||
bordered
|
||||
@change="onChange"
|
||||
@moved="onMoved"
|
||||
@resource-expanded="onResourceExpanded"
|
||||
@click-date="onClickDate"
|
||||
@click-time="onClickTime"
|
||||
@click-resource="onClickResource"
|
||||
@click-head-resources="onClickHeadResources"
|
||||
@click-interval="onClickInterval"
|
||||
>
|
||||
<template #resource-intervals="{ scope }">
|
||||
<template v-for="(event, index) in getEvents(scope)" :key="index">
|
||||
<q-badge
|
||||
outline
|
||||
color="primary"
|
||||
:label="event.title"
|
||||
:style="getStyle(event)"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
</q-calendar-resource>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue';
|
||||
import { QCalendarResource, today } from '@quasar/quasar-ui-qcalendar';
|
||||
|
||||
const selectedDate = ref(today());
|
||||
type Resource = {
|
||||
id: string;
|
||||
name: string;
|
||||
expanded?: boolean;
|
||||
children?: Resource[];
|
||||
};
|
||||
|
||||
type Event = {
|
||||
start: string;
|
||||
title: string;
|
||||
duration: number;
|
||||
left?: number;
|
||||
width?: number;
|
||||
};
|
||||
|
||||
type ResourceIntervalScope = {
|
||||
resource: Resource;
|
||||
intervals: [];
|
||||
timeStartPosX(start: string): number;
|
||||
timeDurationWidth(duration: number): number;
|
||||
};
|
||||
|
||||
const calendar = ref(null);
|
||||
const resources = reactive<Resource[]>([
|
||||
{ id: '1', name: 'ProjectX' },
|
||||
{ id: '2', name: 'Take 5' },
|
||||
{ id: '3', name: 'WeeBeestie' },
|
||||
]);
|
||||
|
||||
const events = reactive<{ [key: string]: Event[] }>({
|
||||
1: [
|
||||
{ start: '06:00', title: 'John Smith', duration: 90 },
|
||||
{ start: '12:00', title: 'Bob Barker', duration: 60 },
|
||||
],
|
||||
2: [
|
||||
{ start: '08:00', title: 'Peter Parker', duration: 120 },
|
||||
{ start: '11:00', title: 'Vince McMahon', duration: 240 },
|
||||
],
|
||||
3: [
|
||||
{ start: '08:00', title: 'Heather Graham', duration: 240 },
|
||||
{ start: '14:00', title: 'Lawrence Fishburne', duration: 60 },
|
||||
],
|
||||
});
|
||||
|
||||
function getEvents(scope: ResourceIntervalScope) {
|
||||
const resourceEvents = events[scope.resource.id];
|
||||
return resourceEvents.map((event) => ({
|
||||
left: scope.timeStartPosX(event.start),
|
||||
width: scope.timeDurationWidth(event.duration),
|
||||
title: event.title,
|
||||
}));
|
||||
}
|
||||
|
||||
function getStyle(event: { left: number; width: number; title: string }) {
|
||||
return {
|
||||
position: 'absolute',
|
||||
background: 'white',
|
||||
left: `${event.left}px`,
|
||||
width: `${event.width}px`,
|
||||
height: '40px',
|
||||
overflow: 'hidden',
|
||||
};
|
||||
}
|
||||
|
||||
function onToday() {
|
||||
calendar.value.moveToToday();
|
||||
}
|
||||
function onPrev() {
|
||||
calendar.value.prev();
|
||||
}
|
||||
function onNext() {
|
||||
calendar.value.next();
|
||||
}
|
||||
function onMoved(data) {
|
||||
console.log('onMoved', data);
|
||||
}
|
||||
function onChange(data) {
|
||||
console.log('onChange', data);
|
||||
}
|
||||
function onResourceExpanded(data) {
|
||||
console.log('onResourceExpanded', data);
|
||||
}
|
||||
function onClickDate(data) {
|
||||
console.log('onClickDate', data);
|
||||
}
|
||||
function onClickTime(data) {
|
||||
console.log('onClickTime', data);
|
||||
}
|
||||
function onClickResource(data) {
|
||||
console.log('onClickResource', data);
|
||||
}
|
||||
function onClickHeadResources(data) {
|
||||
console.log('onClickHeadResources', data);
|
||||
}
|
||||
function onClickInterval(data) {
|
||||
console.log('onClickInterval', data);
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user