Many esthetic changes
This commit is contained in:
@@ -1,9 +0,0 @@
|
|||||||
root = true
|
|
||||||
|
|
||||||
[*]
|
|
||||||
charset = utf-8
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 2
|
|
||||||
end_of_line = lf
|
|
||||||
insert_final_newline = true
|
|
||||||
trim_trailing_whitespace = true
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"singleQuote": true,
|
|
||||||
"semi": true
|
|
||||||
}
|
|
||||||
@@ -48,7 +48,7 @@ module.exports = configure(function (/* ctx */) {
|
|||||||
|
|
||||||
// Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#build
|
// Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#build
|
||||||
build: {
|
build: {
|
||||||
env: require('dotenv').config({ path: '.env.local' }).parsed,
|
env: require('dotenv').config().parsed,
|
||||||
target: {
|
target: {
|
||||||
browser: ['es2019', 'edge88', 'firefox78', 'chrome87', 'safari13.1'],
|
browser: ['es2019', 'edge88', 'firefox78', 'chrome87', 'safari13.1'],
|
||||||
node: 'node16',
|
node: 'node16',
|
||||||
|
|||||||
@@ -1,64 +1,78 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<CalendarHeaderComponent v-model="selectedDate" />
|
<q-card>
|
||||||
<div class="boat-schedule-table-component">
|
<q-toolbar>
|
||||||
<QCalendarDay
|
<q-toolbar-title>Select a Boat and Time</q-toolbar-title>
|
||||||
ref="calendar"
|
<q-btn icon="close" flat round dense v-close-popup />
|
||||||
class="q-pa-xs"
|
</q-toolbar>
|
||||||
flat
|
<q-separator />
|
||||||
animated
|
<CalendarHeaderComponent v-model="selectedDate" />
|
||||||
dense
|
<div class="boat-schedule-table-component">
|
||||||
:disabled-before="disabledBefore"
|
<QCalendarDay
|
||||||
interval-height="24"
|
ref="calendar"
|
||||||
interval-count="18"
|
class="q-pa-xs"
|
||||||
interval-start="06:00"
|
flat
|
||||||
:short-interval-label="true"
|
animated
|
||||||
v-model="selectedDate"
|
dense
|
||||||
:column-count="boats.length"
|
:disabled-before="disabledBefore"
|
||||||
v-touch-swipe.left.right="handleSwipe"
|
interval-height="24"
|
||||||
>
|
interval-count="18"
|
||||||
<template #head-day="{ scope }">
|
interval-start="06:00"
|
||||||
<div style="text-align: center; font-weight: 800">
|
:short-interval-label="true"
|
||||||
{{ getBoatDisplayName(scope) }}
|
v-model="selectedDate"
|
||||||
</div>
|
:column-count="boats.length"
|
||||||
</template>
|
v-touch-swipe.left.right="handleSwipe"
|
||||||
|
>
|
||||||
|
<template #head-day="{ scope }">
|
||||||
|
<div style="text-align: center; font-weight: 800">
|
||||||
|
{{ getBoatDisplayName(scope) }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template #day-body="{ scope }">
|
<template #day-body="{ scope }">
|
||||||
<div v-for="block in getBoatBlocks(scope)" :key="block.$id">
|
<div v-for="block in getBoatBlocks(scope)" :key="block.$id">
|
||||||
<div
|
<div
|
||||||
class="timeblock"
|
class="timeblock"
|
||||||
:class="selectedBlock?.$id === block.$id ? 'selected' : ''"
|
:class="selectedBlock?.$id === block.$id ? 'selected' : ''"
|
||||||
:style="
|
:style="
|
||||||
blockStyles(block, scope.timeStartPos, scope.timeDurationHeight)
|
blockStyles(
|
||||||
"
|
block,
|
||||||
:id="block.id"
|
scope.timeStartPos,
|
||||||
@click="selectBlock($event, scope, block)"
|
scope.timeDurationHeight
|
||||||
>
|
)
|
||||||
{{ boats[scope.columnIndex].name }}<br />
|
"
|
||||||
{{ selectedBlock?.$id === block.$id ? 'Selected' : 'Available' }}
|
:id="block.id"
|
||||||
|
@click="selectBlock($event, scope, block)"
|
||||||
|
v-close-popup
|
||||||
|
>
|
||||||
|
{{ boats[scope.columnIndex].name }}<br />
|
||||||
|
{{
|
||||||
|
selectedBlock?.$id === block.$id ? 'Selected' : 'Available'
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-for="reservation in getBoatReservations(scope)"
|
|
||||||
:key="reservation.$id"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
class="reservation"
|
v-for="reservation in getBoatReservations(scope)"
|
||||||
:style="
|
:key="reservation.$id"
|
||||||
reservationStyles(
|
|
||||||
reservation,
|
|
||||||
scope.timeStartPos,
|
|
||||||
scope.timeDurationHeight
|
|
||||||
)
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
{{ getUserName(reservation.user) || 'loading...' }}<br />
|
<div
|
||||||
{{ reservation.reason }}
|
class="reservation"
|
||||||
|
:style="
|
||||||
|
reservationStyles(
|
||||||
|
reservation,
|
||||||
|
scope.timeStartPos,
|
||||||
|
scope.timeDurationHeight
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ getUserName(reservation.user) || 'loading...' }}<br />
|
||||||
|
<q-chip icon="key">{{ reservation.reason }}</q-chip>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
</template>
|
</QCalendarDay>
|
||||||
</QCalendarDay>
|
</div></q-card
|
||||||
</div>
|
>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -1,92 +1,119 @@
|
|||||||
<template>
|
<template>
|
||||||
<q-page>
|
<div class="q-pa-md row q-gutter-sm">
|
||||||
<q-list>
|
<q-card
|
||||||
<q-form @reset="onReset" class="q-gutter-sm">
|
flat
|
||||||
|
bordered
|
||||||
|
class="col-md-4 col-sm-8 col-xs-12">
|
||||||
|
<q-card-section>
|
||||||
|
<div class="text-h5 q-mt-none q-mb-xs">New Booking</div>
|
||||||
|
<div class="text-caption text-grey-8">for: {{ bookingForm.name }}</div>
|
||||||
|
</q-card-section>
|
||||||
|
<q-separator />
|
||||||
|
<q-item
|
||||||
|
clickable
|
||||||
|
@click="boatSelect = true">
|
||||||
|
<q-item-section avatar>
|
||||||
|
<q-icon
|
||||||
|
color="primary"
|
||||||
|
name="event" />
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section>
|
||||||
|
<q-card v-if="bookingForm.boat">
|
||||||
|
<q-card-section>
|
||||||
|
<q-img
|
||||||
|
:src="bookingForm.boat?.imgSrc"
|
||||||
|
:fit="'scale-down'">
|
||||||
|
<div class="row absolute-top">
|
||||||
|
<div class="col text-h6 text-left">
|
||||||
|
{{ bookingForm.boat?.name }}
|
||||||
|
</div>
|
||||||
|
<div class="col text-right">
|
||||||
|
{{ bookingForm.boat?.class }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</q-img>
|
||||||
|
</q-card-section>
|
||||||
|
<q-separator />
|
||||||
|
<q-card-section class="q-py-none">
|
||||||
|
<q-list
|
||||||
|
dense
|
||||||
|
class="row">
|
||||||
|
<q-item>
|
||||||
|
<q-item-section avatar>
|
||||||
|
<q-badge
|
||||||
|
outline
|
||||||
|
color="primary"
|
||||||
|
label="Start" />
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section>
|
||||||
|
{{
|
||||||
|
date.formatDate(
|
||||||
|
new Date(bookingForm.startDate as string),
|
||||||
|
'ddd MMM Do @ hh:mm A'
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item class="q-ma-none">
|
||||||
|
<q-item-section avatar>
|
||||||
|
<q-badge
|
||||||
|
outline
|
||||||
|
color="primary"
|
||||||
|
label="End" />
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section>
|
||||||
|
{{
|
||||||
|
date.formatDate(
|
||||||
|
new Date(bookingForm.endDate as string),
|
||||||
|
'ddd MMM Do @ hh:mm A'
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
<div v-else>Tap to Select a Boat / Time</div>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-list dense>
|
||||||
<q-item>
|
<q-item>
|
||||||
<q-item-section :avatar="true">
|
<q-item-section avatar>
|
||||||
<q-icon name="person"
|
<q-icon
|
||||||
/></q-item-section>
|
color="primary"
|
||||||
|
name="category" />
|
||||||
|
</q-item-section>
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label> Name: {{ bookingForm.name }} </q-item-label>
|
<q-select
|
||||||
|
filled
|
||||||
|
v-model="bookingForm.reason"
|
||||||
|
:options="reason_options"
|
||||||
|
label="Reason for sail" />
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
<q-expansion-item
|
</q-list>
|
||||||
expand-separator
|
<q-card-actions align="right">
|
||||||
v-model="resourceView"
|
<q-btn
|
||||||
icon="calendar_month"
|
label="Reset"
|
||||||
label="Boat and Time"
|
@click="onReset"
|
||||||
default-opened
|
color="secondary"
|
||||||
class="q-mt-none"
|
size="md" />
|
||||||
:caption="bookingSummary"
|
<q-btn
|
||||||
>
|
label="Submit"
|
||||||
<q-separator />
|
@click="onSubmit"
|
||||||
<q-banner :class="$q.dark.isActive ? 'bg-grey-9' : 'bg-grey-3'">
|
color="primary" />
|
||||||
Use the calendar to pick a date. Select an available boat and
|
</q-card-actions>
|
||||||
timeslot below.
|
</q-card>
|
||||||
</q-banner>
|
<q-dialog
|
||||||
<BoatScheduleTableComponent v-model="interval" />
|
v-model="boatSelect"
|
||||||
|
full-width>
|
||||||
<q-banner
|
<BoatScheduleTableComponent v-model="interval" />
|
||||||
rounded
|
</q-dialog>
|
||||||
class="bg-warning text-grey-10"
|
</div>
|
||||||
style="max-width: 95vw; margin: auto"
|
|
||||||
v-if="bookingForm.boat && bookingForm.boat.defects.length > 0"
|
|
||||||
>
|
|
||||||
<template v-slot:avatar>
|
|
||||||
<q-icon name="warning" color="grey-10" />
|
|
||||||
</template>
|
|
||||||
{{ bookingForm.boat.name }} currently has the following notices:
|
|
||||||
<ol>
|
|
||||||
<li
|
|
||||||
v-for="defect in bookingForm.boat.defects"
|
|
||||||
:key="defect.description"
|
|
||||||
>
|
|
||||||
{{ defect.description }}
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
</q-banner>
|
|
||||||
<q-card-section>
|
|
||||||
<q-btn
|
|
||||||
color="primary"
|
|
||||||
class="full-width"
|
|
||||||
icon="keyboard_arrow_down"
|
|
||||||
icon-right="keyboard_arrow_down"
|
|
||||||
label="Next: Booking Details"
|
|
||||||
@click="resourceView = false"
|
|
||||||
/></q-card-section>
|
|
||||||
</q-expansion-item>
|
|
||||||
<q-expansion-item
|
|
||||||
expand-separator
|
|
||||||
icon="people"
|
|
||||||
label="Booking Details"
|
|
||||||
default-opened
|
|
||||||
>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-auto">
|
|
||||||
<q-select
|
|
||||||
filled
|
|
||||||
v-model="bookingForm.reason"
|
|
||||||
:options="reason_options"
|
|
||||||
label="Reason for sail"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</q-expansion-item>
|
|
||||||
|
|
||||||
<q-item-section>
|
|
||||||
<q-btn
|
|
||||||
label="Submit"
|
|
||||||
type="submit"
|
|
||||||
@click="onSubmit"
|
|
||||||
color="primary"
|
|
||||||
/>
|
|
||||||
</q-item-section> </q-form
|
|
||||||
></q-list>
|
|
||||||
</q-page>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
import { useAuthStore } from 'src/stores/auth';
|
import { useAuthStore } from 'src/stores/auth';
|
||||||
import { Boat, useBoatStore } from 'src/stores/boat';
|
import { Boat, useBoatStore } from 'src/stores/boat';
|
||||||
import { date, useQuasar } from 'quasar';
|
import { date, useQuasar } from 'quasar';
|
||||||
@@ -110,9 +137,8 @@ interface BookingForm {
|
|||||||
const reason_options = ['Open Sail', 'Private Sail', 'Racing', 'Other'];
|
const reason_options = ['Open Sail', 'Private Sail', 'Racing', 'Other'];
|
||||||
|
|
||||||
const auth = useAuthStore();
|
const auth = useAuthStore();
|
||||||
const resourceView = ref(true);
|
|
||||||
const interval = ref<Interval>();
|
const interval = ref<Interval>();
|
||||||
const bookingForm = ref<BookingForm>({
|
const newForm = {
|
||||||
bookingId: getNewId(),
|
bookingId: getNewId(),
|
||||||
name: auth.currentUser?.name,
|
name: auth.currentUser?.name,
|
||||||
boat: <Boat | undefined>undefined,
|
boat: <Boat | undefined>undefined,
|
||||||
@@ -121,10 +147,12 @@ const bookingForm = ref<BookingForm>({
|
|||||||
reason: 'Open Sail',
|
reason: 'Open Sail',
|
||||||
members: [],
|
members: [],
|
||||||
guests: [],
|
guests: [],
|
||||||
});
|
};
|
||||||
|
const bookingForm = ref<BookingForm>({ ...newForm });
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const reservationStore = useReservationStore();
|
const reservationStore = useReservationStore();
|
||||||
const $q = useQuasar();
|
const $q = useQuasar();
|
||||||
|
const boatSelect = ref(false);
|
||||||
|
|
||||||
watch(interval, (new_interval) => {
|
watch(interval, (new_interval) => {
|
||||||
bookingForm.value.boat = useBoatStore().boats.find(
|
bookingForm.value.boat = useBoatStore().boats.find(
|
||||||
@@ -135,9 +163,8 @@ watch(interval, (new_interval) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const onReset = () => {
|
const onReset = () => {
|
||||||
// TODO
|
bookingForm.value = { ...newForm };
|
||||||
};
|
};
|
||||||
|
|
||||||
const onSubmit = () => {
|
const onSubmit = () => {
|
||||||
console.log('SUBMIT!');
|
console.log('SUBMIT!');
|
||||||
const booking = bookingForm.value;
|
const booking = bookingForm.value;
|
||||||
@@ -166,30 +193,4 @@ const onSubmit = () => {
|
|||||||
});
|
});
|
||||||
router.go(-1);
|
router.go(-1);
|
||||||
};
|
};
|
||||||
|
|
||||||
const bookingDuration = computed(() => {
|
|
||||||
if (bookingForm.value.endDate && bookingForm.value.startDate) {
|
|
||||||
const diff = date.getDateDiff(
|
|
||||||
bookingForm.value.endDate,
|
|
||||||
bookingForm.value.startDate,
|
|
||||||
'minutes'
|
|
||||||
);
|
|
||||||
return diff <= 0
|
|
||||||
? 'Invalid'
|
|
||||||
: (diff > 60 ? Math.trunc(diff / 60) + ' hours' : '') +
|
|
||||||
(diff % 60 > 0 ? ' ' + (diff % 60) + ' minutes' : '');
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const bookingSummary = computed(() => {
|
|
||||||
return bookingForm.value.boat &&
|
|
||||||
bookingForm.value.startDate &&
|
|
||||||
bookingForm.value.endDate
|
|
||||||
? `${bookingForm.value.boat.name} @ ${new Date(
|
|
||||||
bookingForm.value.startDate
|
|
||||||
).toLocaleString()} for ${bookingDuration.value}`
|
|
||||||
: '';
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user