chore: Update dependencies to latest
Some checks failed
Build BAB Application Deployment Artifact / build (push) Failing after 1m17s
Some checks failed
Build BAB Application Deployment Artifact / build (push) Failing after 1m17s
fix: claude fixes to various errors
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { boot } from 'quasar/wrappers';
|
||||
import { defineBoot } from '#q-app/wrappers';
|
||||
import {
|
||||
Client,
|
||||
Account,
|
||||
@@ -43,7 +43,6 @@ type AppwriteIDConfig = {
|
||||
|
||||
let AppwriteIds = <AppwriteIDConfig>{};
|
||||
|
||||
console.log(API_ENDPOINT);
|
||||
AppwriteIds = {
|
||||
databaseId: 'bab_prod',
|
||||
collection: {
|
||||
@@ -67,7 +66,7 @@ const teams = new Teams(client);
|
||||
|
||||
let appRouter: Router;
|
||||
|
||||
export default boot(async ({ router }) => {
|
||||
export default defineBoot(async ({ router }) => {
|
||||
// Initialize store
|
||||
const authStore = useAuthStore();
|
||||
await authStore.init();
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
<template>
|
||||
<q-btn
|
||||
@click="auth.discordLogin()"
|
||||
style="width: 300px">
|
||||
<q-avatar
|
||||
left
|
||||
size="sm"
|
||||
class="q-ma-xs">
|
||||
<img
|
||||
src="https://cdn.prod.website-files.com/6257adef93867e50d84d30e2/636e0a6a49cf127bf92de1e2_icon_clyde_blurple_RGB.png" />
|
||||
</q-avatar>
|
||||
Login with Discord
|
||||
</q-btn>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useAuthStore } from 'src/stores/auth';
|
||||
const auth = useAuthStore();
|
||||
</script>
|
||||
@@ -1,19 +0,0 @@
|
||||
<template>
|
||||
<q-btn
|
||||
@click="auth.googleLogin()"
|
||||
style="width: 300px">
|
||||
<q-avatar
|
||||
left
|
||||
class="q-ma-xs"
|
||||
size="sm">
|
||||
<img
|
||||
src="https://lh3.googleusercontent.com/COxitqgJr1sJnIDe8-jiKhxDx1FrYbtRHKJ9z_hELisAlapwE9LUPh6fcXIfb5vwpbMl4xl9H9TRFPc5NOO8Sb3VSgIBrfRYvW6cUA" />
|
||||
</q-avatar>
|
||||
<div>Login with Google</div>
|
||||
</q-btn>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useAuthStore } from 'src/stores/auth';
|
||||
const auth = useAuthStore();
|
||||
</script>
|
||||
@@ -49,6 +49,13 @@
|
||||
</div>
|
||||
</q-list>
|
||||
</template>
|
||||
<q-item
|
||||
clickable
|
||||
v-ripple
|
||||
@click="showAbout()">
|
||||
<q-item-section avatar><q-icon name="info" /></q-item-section>
|
||||
<q-item-section>About</q-item-section>
|
||||
</q-item>
|
||||
<q-item
|
||||
clickable
|
||||
v-ripple
|
||||
@@ -63,8 +70,18 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { defineComponent } from 'vue';
|
||||
import { Dialog } from 'quasar';
|
||||
import { enabledLinks } from 'src/router/navlinks.js';
|
||||
import { logout } from 'boot/appwrite';
|
||||
import { logout } from 'src/boot/appwrite';
|
||||
import { APP_VERSION } from 'src/version';
|
||||
|
||||
function showAbout() {
|
||||
Dialog.create({
|
||||
title: 'OYS Borrow a Boat',
|
||||
message: `Version ${APP_VERSION}<br>Manage a Borrow a Boat program for a Yacht Club.<br><br>© Ottawa Yacht Squadron`,
|
||||
html: true,
|
||||
});
|
||||
}
|
||||
|
||||
defineProps(['drawer']);
|
||||
defineEmits(['drawer-toggle']);
|
||||
|
||||
@@ -111,6 +111,7 @@
|
||||
import { ref } from 'vue';
|
||||
import {
|
||||
QCalendarResource,
|
||||
QCalendarMonth,
|
||||
TimestampOrNull,
|
||||
today,
|
||||
parseTimestamp,
|
||||
@@ -169,11 +170,11 @@ const disabledBefore = computed(() => {
|
||||
|
||||
function monthFormatter() {
|
||||
try {
|
||||
return new Intl.DateTimeFormat('en-CA' || undefined, {
|
||||
return new Intl.DateTimeFormat('en-CA', {
|
||||
month: 'long',
|
||||
timeZone: 'UTC',
|
||||
});
|
||||
} catch (e) {
|
||||
} catch {
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -233,16 +234,10 @@ function onClickTime(data: EventData) {
|
||||
function onUpdateDuration(value: EventData) {
|
||||
emit('onUpdateDuration', value);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
const onClickInterval = () => {};
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
const onClickHeadResources = () => {};
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
const onClickResource = () => {};
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
const onResourceExpanded = () => {};
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
const onMoved = () => {};
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
const onChange = () => {};
|
||||
</script>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
class="row">
|
||||
<q-card
|
||||
v-for="boat in boats"
|
||||
:key="boat.id"
|
||||
:key="boat.$id"
|
||||
class="q-ma-sm col-xs-12 col-sm-6 col-xl-3">
|
||||
<q-card-section>
|
||||
<q-img
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
scope.timeDurationHeight
|
||||
)
|
||||
"
|
||||
:id="block.id"
|
||||
:id="block.$id"
|
||||
@click="selectBlock($event, scope, block)">
|
||||
{{ boats[scope.columnIndex].name }}
|
||||
<br />
|
||||
@@ -113,7 +113,7 @@ const selectedDate = ref(today());
|
||||
const { getAvailableIntervals } = useIntervalStore();
|
||||
const calendar = ref<QCalendarDay | null>(null);
|
||||
const now = ref(new Date());
|
||||
let intervalId: string | number | NodeJS.Timeout | undefined;
|
||||
let intervalId: ReturnType<typeof setInterval> | undefined;
|
||||
|
||||
onMounted(async () => {
|
||||
await useBoatStore().fetchBoats();
|
||||
@@ -125,8 +125,12 @@ onMounted(async () => {
|
||||
|
||||
onUnmounted(() => clearInterval(intervalId));
|
||||
|
||||
function handleSwipe({ ...event }) {
|
||||
event.direction === 'right' ? calendar.value?.prev() : calendar.value?.next();
|
||||
function handleSwipe({ direction }: { direction: string }) {
|
||||
if (direction === 'right') {
|
||||
calendar.value?.prev();
|
||||
} else {
|
||||
calendar.value?.next();
|
||||
}
|
||||
}
|
||||
function reservationStyles(
|
||||
reservation: Reservation,
|
||||
|
||||
@@ -48,7 +48,6 @@ import {
|
||||
createNativeLocaleFormatter,
|
||||
getEndOfWeek,
|
||||
getStartOfWeek,
|
||||
getWeekdaySkips,
|
||||
parseTimestamp,
|
||||
today,
|
||||
} from '@quasar/quasar-ui-qcalendar';
|
||||
@@ -63,10 +62,6 @@ const weekdays = reactive([1, 2, 3, 4, 5, 6, 0]),
|
||||
dayFormatter = dayFormatterFunc(),
|
||||
weekdayFormatter = weekdayFormatterFunc();
|
||||
|
||||
const weekdaySkips = computed(() => {
|
||||
return getWeekdaySkips(weekdays);
|
||||
});
|
||||
|
||||
const parsedStart = computed(() =>
|
||||
getStartOfWeek(
|
||||
parseTimestamp(selectedDate.value || today()) as Timestamp,
|
||||
@@ -93,7 +88,7 @@ const days = computed(() => {
|
||||
parsedStart.value,
|
||||
parsedEnd.value,
|
||||
today2.value as Timestamp,
|
||||
weekdaySkips.value
|
||||
weekdays
|
||||
);
|
||||
}
|
||||
return [];
|
||||
|
||||
@@ -5,19 +5,10 @@
|
||||
<q-item-label caption lines="2">{{ task.description }} </q-item-label>
|
||||
<q-item-label caption>Due: {{ task.due_date }}</q-item-label>
|
||||
</q-item-section>
|
||||
<q-expansion-item
|
||||
v-if="task.subtasks && task.subtasks.length"
|
||||
expand-separator
|
||||
label="Subtasks"
|
||||
default-opened
|
||||
>
|
||||
<TaskListComponent :tasks="task.subtasks" />
|
||||
</q-expansion-item>
|
||||
</q-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineProps } from 'vue';
|
||||
import type { Task } from 'src/stores/task';
|
||||
|
||||
defineProps<{ task: Task }>();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="q-pa-md" style="max-width: 350px">
|
||||
<q-list>
|
||||
<div v-for="task in tasks" :key="task.id">
|
||||
<div v-for="task in tasks" :key="task.$id">
|
||||
<TaskCardComponent :task="task" />
|
||||
</div>
|
||||
</q-list>
|
||||
|
||||
@@ -212,7 +212,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, defineProps, ref } from 'vue';
|
||||
import { computed, ref } from 'vue';
|
||||
import { useTaskStore, Task, SkillTag, TaskTag } from 'src/stores/task';
|
||||
import { QTableProps, date, useQuasar } from 'quasar';
|
||||
import { Boat, useBoatStore } from 'src/stores/boat';
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// app global css in SASS form
|
||||
@import '@quasar/quasar-ui-qcalendar/dist/index.css'
|
||||
.mobile-card
|
||||
width: 100%
|
||||
max-width: 450px
|
||||
|
||||
@@ -34,24 +34,20 @@
|
||||
<q-card-section class="q-pa-none">
|
||||
<div class="row justify-center q-ma-sm">
|
||||
<q-btn
|
||||
v-if="!userId"
|
||||
type="button"
|
||||
@click="doTokenLogin"
|
||||
color="primary"
|
||||
label="Login with E-mail"
|
||||
@click="sendMagicLink"
|
||||
color="secondary"
|
||||
label="Send Magic Link"
|
||||
style="width: 300px" />
|
||||
</div>
|
||||
<div class="row justify-center q-ma-sm">
|
||||
<GoogleOauthComponent />
|
||||
</div>
|
||||
<div class="row justify-center q-ma-sm">
|
||||
<DiscordOauthComponent />
|
||||
</div>
|
||||
<div class="row justify-center">
|
||||
<q-btn
|
||||
flat
|
||||
color="secondary"
|
||||
to="/pwreset"
|
||||
label="Forgot Password?" />
|
||||
type="button"
|
||||
@click="doTokenLogin"
|
||||
color="primary"
|
||||
:label="userId ? 'Login' : 'Send Code'"
|
||||
style="width: 300px" />
|
||||
</div>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
@@ -76,21 +72,54 @@
|
||||
</style>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import GoogleOauthComponent from 'src/components/GoogleOauthComponent.vue';
|
||||
import DiscordOauthComponent from 'src/components/DiscordOauthComponent.vue';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { Dialog, Notify } from 'quasar';
|
||||
import { useAuthStore } from 'src/stores/auth';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { AppwriteException } from 'appwrite';
|
||||
import { APP_VERSION } from 'src/version.js';
|
||||
|
||||
const email = ref('');
|
||||
const token = ref('');
|
||||
const userId = ref();
|
||||
const router = useRouter();
|
||||
const authStore = useAuthStore();
|
||||
|
||||
console.log('version:' + APP_VERSION);
|
||||
onMounted(async () => {
|
||||
const query = router.currentRoute.value.query;
|
||||
if (query.userId && query.secret) {
|
||||
const notification = Notify.create({
|
||||
type: 'primary',
|
||||
position: 'top',
|
||||
spinner: true,
|
||||
message: 'Logging you in...',
|
||||
timeout: 8000,
|
||||
group: false,
|
||||
});
|
||||
try {
|
||||
await authStore.magicURLLogin(query.userId as string, query.secret as string);
|
||||
notification({ type: 'positive', message: 'Logged in!', timeout: 2000, spinner: false, icon: 'check_circle' });
|
||||
router.replace({ name: 'index' });
|
||||
} catch (error: unknown) {
|
||||
notification({ type: 'negative', message: 'Magic link login failed.', timeout: 3000, spinner: false });
|
||||
if (error instanceof AppwriteException) {
|
||||
Dialog.create({ title: 'Login Error', message: error.message, persistent: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const sendMagicLink = async () => {
|
||||
if (!email.value) {
|
||||
Dialog.create({ message: 'Please enter your e-mail address.' });
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await authStore.createMagicURLSession(email.value);
|
||||
Dialog.create({ message: 'Check your e-mail for a magic login link.' });
|
||||
} catch {
|
||||
Dialog.create({ message: 'An error occurred. Please ask for help in Discord.' });
|
||||
}
|
||||
};
|
||||
|
||||
const doTokenLogin = async () => {
|
||||
const authStore = useAuthStore();
|
||||
@@ -99,7 +128,7 @@ const doTokenLogin = async () => {
|
||||
const sessionToken = await authStore.createTokenSession(email.value);
|
||||
userId.value = sessionToken.userId;
|
||||
Dialog.create({ message: 'Check your e-mail for your login code.' });
|
||||
} catch (e) {
|
||||
} catch {
|
||||
Dialog.create({
|
||||
message: 'An error occurred. Please ask for help in Discord',
|
||||
});
|
||||
|
||||
@@ -61,7 +61,7 @@ import { useAuthStore } from 'src/stores/auth';
|
||||
import NewPasswordComponent from 'src/components/NewPasswordComponent.vue';
|
||||
import { Dialog } from 'quasar';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { APP_VERSION } from 'src/version.js';
|
||||
import { APP_VERSION } from 'src/version';
|
||||
|
||||
const email = ref('');
|
||||
const password = ref('');
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
:transparent="interval.user != undefined"
|
||||
:color="interval.user ? 'secondary' : 'primary'"
|
||||
:outline="!interval.user"
|
||||
:id="interval.id">
|
||||
:id="interval.$id">
|
||||
{{
|
||||
interval.user
|
||||
? useAuthStore().getUserNameById(interval.user)
|
||||
@@ -132,7 +132,11 @@ const createReservationFromInterval = (interval: Interval | Reservation) => {
|
||||
};
|
||||
|
||||
function handleSwipe({ ...event }) {
|
||||
event.direction === 'right' ? calendar.value?.prev() : calendar.value?.next();
|
||||
if (event.direction === 'right') {
|
||||
calendar.value?.prev();
|
||||
} else {
|
||||
calendar.value?.next();
|
||||
}
|
||||
}
|
||||
const boatReservationEvents = (
|
||||
timestamp: Timestamp,
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
<template
|
||||
v-for="block in sortedIntervals(scope.timestamp, scope.resource)
|
||||
.value"
|
||||
:key="block.id">
|
||||
:key="block.$id">
|
||||
<q-chip class="cursor-pointer">
|
||||
{{ date.formatDate(block.start, 'HH:mm') }} -
|
||||
{{ date.formatDate(block.end, 'HH:mm') }}
|
||||
|
||||
2
src/quasar.d.ts
vendored
2
src/quasar.d.ts
vendored
@@ -1,5 +1,3 @@
|
||||
/* eslint-disable */
|
||||
|
||||
// Forces TS to apply `@quasar/app-vite` augmentations of `quasar` package
|
||||
// Removing this would break `quasar/wrappers` imports as those typings are declared
|
||||
// into `@quasar/app-vite`
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { route } from 'quasar/wrappers';
|
||||
import { defineRouter } from '#q-app/wrappers';
|
||||
import {
|
||||
createMemoryHistory,
|
||||
createRouter,
|
||||
@@ -22,7 +22,7 @@ const publicRoutes = routes
|
||||
* with the Router instance.
|
||||
*/
|
||||
|
||||
export default route(function (/* { store, ssrContext } */) {
|
||||
export default defineRouter(function (/* { store, ssrContext } */) {
|
||||
const createHistory = process.env.SERVER
|
||||
? createMemoryHistory
|
||||
: process.env.VUE_ROUTER_MODE === 'history'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { ID, account, functions, teams } from 'boot/appwrite';
|
||||
import { ExecutionMethod, OAuthProvider, type Models } from 'appwrite';
|
||||
import { ExecutionMethod, type Models } from 'appwrite';
|
||||
import { computed, ref } from 'vue';
|
||||
import { useBoatStore } from './boat';
|
||||
import { useReservationStore } from './reservation';
|
||||
@@ -49,22 +49,12 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
return await account.createEmailToken(ID.unique(), email);
|
||||
}
|
||||
|
||||
async function googleLogin() {
|
||||
await account.createOAuth2Session(
|
||||
OAuthProvider.Google,
|
||||
'https://oys.undock.ca',
|
||||
'https://oys.undock.ca/login'
|
||||
async function createMagicURLSession(email: string) {
|
||||
return await account.createMagicURLToken(
|
||||
ID.unique(),
|
||||
email,
|
||||
window.location.origin + '/login'
|
||||
);
|
||||
await init();
|
||||
}
|
||||
|
||||
async function discordLogin() {
|
||||
await account.createOAuth2Session(
|
||||
OAuthProvider.Discord,
|
||||
'https://oys.undock.ca',
|
||||
'https://oys.undock.ca/login'
|
||||
);
|
||||
await init();
|
||||
}
|
||||
|
||||
async function tokenLogin(userId: string, token: string) {
|
||||
@@ -72,6 +62,11 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
await init();
|
||||
}
|
||||
|
||||
async function magicURLLogin(userId: string, secret: string) {
|
||||
await account.updateMagicURLSession(userId, secret);
|
||||
await init();
|
||||
}
|
||||
|
||||
function getUserNameById(id: string | undefined | null): string {
|
||||
if (!id) return 'No User';
|
||||
try {
|
||||
@@ -115,10 +110,10 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
register,
|
||||
updateName,
|
||||
login,
|
||||
googleLogin,
|
||||
discordLogin,
|
||||
createTokenSession,
|
||||
createMagicURLSession,
|
||||
tokenLogin,
|
||||
magicURLLogin,
|
||||
logout,
|
||||
init,
|
||||
};
|
||||
|
||||
@@ -33,7 +33,7 @@ export const useBoatStore = defineStore('boat', () => {
|
||||
AppwriteIds.databaseId,
|
||||
AppwriteIds.collection.boat
|
||||
);
|
||||
boats.value = response.documents as Boat[];
|
||||
boats.value = response.documents as unknown as Boat[];
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch boats', error);
|
||||
}
|
||||
|
||||
@@ -1,18 +1,5 @@
|
||||
import { store } from 'quasar/wrappers';
|
||||
import { defineStore } from '#q-app/wrappers';
|
||||
import { createPinia } from 'pinia';
|
||||
import { Router } from 'vue-router';
|
||||
|
||||
/*
|
||||
* When adding new properties to stores, you should also
|
||||
* extend the `PiniaCustomProperties` interface.
|
||||
* @see https://pinia.vuejs.org/core-concepts/plugins.html#typing-new-store-properties
|
||||
*/
|
||||
declare module 'pinia' {
|
||||
export interface PiniaCustomProperties {
|
||||
readonly router: Router;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If not building with SSR mode, you can
|
||||
* directly export the Store instantiation;
|
||||
@@ -22,7 +9,7 @@ declare module 'pinia' {
|
||||
* with the Store instance.
|
||||
*/
|
||||
|
||||
export default store((/* { ssrContext } */) => {
|
||||
export default defineStore((/* { ssrContext } */) => {
|
||||
const pinia = createPinia();
|
||||
|
||||
// You can add Pinia plugins here
|
||||
|
||||
@@ -22,7 +22,7 @@ export const useIntervalStore = defineStore('interval', () => {
|
||||
realtimeStore.register(
|
||||
`databases.${AppwriteIds.databaseId}.collections.${AppwriteIds.collection.interval}.documents`,
|
||||
(response) => {
|
||||
const payload = response.payload as Interval;
|
||||
const payload = response.payload as unknown as Interval;
|
||||
if (!payload.$id) return;
|
||||
if (
|
||||
response.events.includes('databases.*.collections.*.documents.*.delete')
|
||||
@@ -92,7 +92,7 @@ export const useIntervalStore = defineStore('interval', () => {
|
||||
]
|
||||
);
|
||||
response.documents.forEach((d) =>
|
||||
intervals.value.set(d.$id, d as Interval)
|
||||
intervals.value.set(d.$id, d as unknown as Interval)
|
||||
);
|
||||
dateStatus.value.set(dateString, 'loaded');
|
||||
console.info(`Loaded ${response.documents.length} intervals from server`);
|
||||
@@ -110,7 +110,7 @@ export const useIntervalStore = defineStore('interval', () => {
|
||||
ID.unique(),
|
||||
interval
|
||||
);
|
||||
intervals.value.set(response.$id, response as Interval);
|
||||
intervals.value.set(response.$id, response as unknown as Interval);
|
||||
} catch (e) {
|
||||
console.error('Error creating Interval: ' + e);
|
||||
}
|
||||
@@ -124,7 +124,7 @@ export const useIntervalStore = defineStore('interval', () => {
|
||||
interval.$id,
|
||||
{ ...interval, $id: undefined }
|
||||
);
|
||||
intervals.value.set(response.$id, response as Interval);
|
||||
intervals.value.set(response.$id, response as unknown as Interval);
|
||||
console.info(`Saved Interval: ${interval.$id}`);
|
||||
} else {
|
||||
console.error('Update interval called without an ID');
|
||||
|
||||
@@ -20,14 +20,13 @@ export const useIntervalTemplateStore = defineStore('intervalTemplate', () => {
|
||||
AppwriteIds.databaseId,
|
||||
AppwriteIds.collection.intervalTemplate
|
||||
);
|
||||
intervalTemplates.value = response.documents.map(
|
||||
(d: Models.Document): IntervalTemplate => {
|
||||
return {
|
||||
...d,
|
||||
timeTuples: arrayToTimeTuples(d.timeTuple),
|
||||
} as IntervalTemplate;
|
||||
}
|
||||
);
|
||||
intervalTemplates.value = response.documents.map((d): IntervalTemplate => {
|
||||
const doc = d as unknown as { timeTuple: string[] } & Models.Document;
|
||||
return {
|
||||
...doc,
|
||||
timeTuples: arrayToTimeTuples(doc.timeTuple),
|
||||
} as unknown as IntervalTemplate;
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch timeblock templates', error);
|
||||
}
|
||||
@@ -41,7 +40,7 @@ export const useIntervalTemplateStore = defineStore('intervalTemplate', () => {
|
||||
ID.unique(),
|
||||
{ name: template.name, timeTuple: template.timeTuples.flat(2) }
|
||||
);
|
||||
intervalTemplates.value.push(response as IntervalTemplate);
|
||||
intervalTemplates.value.push(response as unknown as IntervalTemplate);
|
||||
} catch (e) {
|
||||
console.error('Error updating IntervalTemplate: ' + e);
|
||||
}
|
||||
@@ -79,8 +78,10 @@ export const useIntervalTemplateStore = defineStore('intervalTemplate', () => {
|
||||
? b
|
||||
: ({
|
||||
...response,
|
||||
timeTuples: arrayToTimeTuples(response.timeTuple),
|
||||
} as IntervalTemplate)
|
||||
timeTuples: arrayToTimeTuples(
|
||||
(response as unknown as { timeTuple: string[] }).timeTuple
|
||||
),
|
||||
} as unknown as IntervalTemplate)
|
||||
);
|
||||
} catch (e) {
|
||||
console.error('Error updating IntervalTemplate: ' + e);
|
||||
|
||||
@@ -20,33 +20,33 @@ function getSampleData(): ReferenceEntry[] {
|
||||
content: `Its hard to imagine that a modern 27 foot sailboat with a classic look, superb
|
||||
stability, and easy to manage rig is such a fast boat. 123-126 PHRF. No longer do you
|
||||
have to substitute speed for comfort, or own separate boats for racing and cruising. The
|
||||
8\’ long cockpit seats 4 to 5 comfortably. Below deck you can sleep 5. And with head and
|
||||
8’ long cockpit seats 4 to 5 comfortably. Below deck you can sleep 5. And with head and
|
||||
stove, the J/27 is the perfect weekend cruiser.
|
||||
|
||||
Fun and Fast. There are some impressive victories to back this up, but that doesn\’t
|
||||
Fun and Fast. There are some impressive victories to back this up, but that doesn’t
|
||||
tell the whole story. The J/27 is fun and responsive. Nothing is more exhilarating than
|
||||
popping the J/27\’s kite in a good breeze for a downhill sleigh ride. 15+ knots planing
|
||||
off the wave-tops is easy. And most importantly, this off-wind speed doesn\’t sacrifice
|
||||
popping the J/27’s kite in a good breeze for a downhill sleigh ride. 15+ knots planing
|
||||
off the wave-tops is easy. And most importantly, this off-wind speed doesn’t sacrifice
|
||||
upwind performance. Going to windward in the J/27 is a dream, it has the solid, balanced
|
||||
"feel" of a traditional keelboat. The J/27 points higher and goes faster than many 30-35
|
||||
footers!
|
||||
|
||||
One-Design Racing. Even more fun is sailing a one-design race around the buoys. The
|
||||
J/27\’s close-windedness makes it very tactical, as even 5 degree wind shifts bring
|
||||
significant gains. Then off wind, you quickly learn to play gibe angles as the boat\’s
|
||||
J/27’s close-windedness makes it very tactical, as even 5 degree wind shifts bring
|
||||
significant gains. Then off wind, you quickly learn to play gibe angles as the boat’s
|
||||
acceleration gains you valuable ground on the competition. The J/27 is remarkably agile
|
||||
and responsive in lighter winds, which is unusual for a boat that feels so solid.
|
||||
|
||||
All-Day Comfort. Sailing past larger boats is always satisfying... especially when it\’s
|
||||
effortless and you can\’t be written off as being wet and uncomfortable. Design is the
|
||||
difference. It\’s all done from a cockpit which holds several people more than is possible
|
||||
All-Day Comfort. Sailing past larger boats is always satisfying... especially when it’s
|
||||
effortless and you can’t be written off as being wet and uncomfortable. Design is the
|
||||
difference. It’s all done from a cockpit which holds several people more than is possible
|
||||
on other 27-footers. Correctly angled backrests and decks at elbow level provide restful
|
||||
and secure seating. Harken mainsheet, vang, traveler, and backstay systems; four Barient
|
||||
winches; a beautiful double spreader, tapered, fractional rig spar by Hall . . . make
|
||||
control and adjustment easy for crew members no matter what the wind.
|
||||
|
||||
Get-away Weekend Cruiser. Take a break from the pace of life on land and spend time with
|
||||
family and friends sailing the J/27. It's a fun boat to sail, so everyone becomes involved.
|
||||
family and friends sailing the J/27. It’s a fun boat to sail, so everyone becomes involved.
|
||||
|
||||
The visibility, when steering with a responsive tiller gives the inexperienced that sense
|
||||
of control not found when spinning a tiny wheel on small cruisers with large trunk cabins.
|
||||
@@ -57,14 +57,14 @@ function getSampleData(): ReferenceEntry[] {
|
||||
starboard is a comfortable quarter berth. Enough room below for a family of four or a
|
||||
couple for a nice weekend romp to your favorite sailing anchorage.
|
||||
|
||||
Durable and Stable. The J/27\’s secure big boat feel is created by concentrating 1530
|
||||
Durable and Stable. The J/27’s secure big boat feel is created by concentrating 1530
|
||||
pounds of lead very low in the keel while using high strength to eight ratio laminates
|
||||
in the hull. Unidirectional E-glass on either side of pre-sealed Baltek CK57 aircraft
|
||||
grade, Lloyd\’s approved, end grain balsa sandwich construction means superior torsion and
|
||||
grade, Lloyd’s approved, end grain balsa sandwich construction means superior torsion and
|
||||
impact resistance. Light ends, low freeboard, and the low center of gravity of a lead keel
|
||||
coupled with low wetted surface and a generous sailplan of 362 sq. ft. achieves exceptional
|
||||
sail area and stability relative to displacement. Hence, sparkling performance in both
|
||||
light and heavy air...something that doesn\’t happen with iron keels and box-like hulls.
|
||||
light and heavy air...something that doesn’t happen with iron keels and box-like hulls.
|
||||
|
||||
Strong Class Strict Rules. The J/27 Class Association, owner driven and over 190 boats
|
||||
strong, sail in North American, Midwinter, and Regional championships. A superb J/27 Class
|
||||
|
||||
@@ -22,7 +22,7 @@ export const useReservationStore = defineStore('reservation', () => {
|
||||
realtimeStore.register(
|
||||
`databases.${AppwriteIds.databaseId}.collections.${AppwriteIds.collection.reservation}.documents`,
|
||||
(response) => {
|
||||
const payload = response.payload as Reservation;
|
||||
const payload = response.payload as unknown as Reservation;
|
||||
if (payload.$id) {
|
||||
if (
|
||||
response.events.includes(
|
||||
@@ -62,7 +62,7 @@ export const useReservationStore = defineStore('reservation', () => {
|
||||
);
|
||||
|
||||
response.documents.forEach((d) =>
|
||||
reservations.set(d.$id, d as Reservation)
|
||||
reservations.set(d.$id, d as unknown as Reservation)
|
||||
);
|
||||
setDateLoaded(startDate, endDate, 'loaded');
|
||||
} catch (error) {
|
||||
@@ -77,7 +77,7 @@ export const useReservationStore = defineStore('reservation', () => {
|
||||
AppwriteIds.collection.reservation,
|
||||
id
|
||||
);
|
||||
return response as Reservation;
|
||||
return response as unknown as Reservation;
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch reservation: ', error);
|
||||
}
|
||||
@@ -103,10 +103,10 @@ export const useReservationStore = defineStore('reservation', () => {
|
||||
reservation
|
||||
);
|
||||
}
|
||||
reservations.set(response.$id, response as Reservation);
|
||||
userReservations.set(response.$id, response as Reservation);
|
||||
reservations.set(response.$id, response as unknown as Reservation);
|
||||
userReservations.set(response.$id, response as unknown as Reservation);
|
||||
console.info('Reservation booked: ', response);
|
||||
return response as Reservation;
|
||||
return response as unknown as Reservation;
|
||||
} catch (e) {
|
||||
console.error('Error creating Reservation: ' + e);
|
||||
throw e;
|
||||
@@ -244,7 +244,7 @@ export const useReservationStore = defineStore('reservation', () => {
|
||||
[Query.equal('user', authStore.currentUser.$id)]
|
||||
);
|
||||
response.documents.forEach((d) =>
|
||||
userReservations.set(d.$id, d as Reservation)
|
||||
userReservations.set(d.$id, d as unknown as Reservation)
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch reservations for user: ', error);
|
||||
|
||||
@@ -16,7 +16,7 @@ import type {
|
||||
} from '../schedule.types';
|
||||
|
||||
export const templateA: IntervalTemplate = {
|
||||
id: '1',
|
||||
$id: '1',
|
||||
name: 'WeekdayBlocks',
|
||||
timeTuples: [
|
||||
['08:00', '12:00'],
|
||||
@@ -26,7 +26,7 @@ export const templateA: IntervalTemplate = {
|
||||
};
|
||||
|
||||
export const templateB: IntervalTemplate = {
|
||||
id: '2',
|
||||
$id: '2',
|
||||
name: 'WeekendBlocks',
|
||||
timeTuples: [
|
||||
['07:00', '10:00'],
|
||||
@@ -47,7 +47,7 @@ export function getSampleIntervals(): Interval[] {
|
||||
result.push(
|
||||
...boats
|
||||
.map((b): Interval[] => {
|
||||
return template.blocks.map((t: TimeTuple): Interval => {
|
||||
return template.timeTuples.map((t: TimeTuple): Interval => {
|
||||
return {
|
||||
$id: 'id' + Math.random().toString(32).slice(2),
|
||||
resource: b.$id,
|
||||
@@ -135,14 +135,13 @@ export function getSampleReservations(): Reservation[] {
|
||||
return sampleData.map((entry): Reservation => {
|
||||
const boat = <Boat>boatStore.boats.find((b) => b.$id == entry.boat);
|
||||
return {
|
||||
id: entry.id,
|
||||
$id: entry.id,
|
||||
user: entry.user,
|
||||
start: date
|
||||
.adjustDate(now, makeOpts(splitTime(entry.start)))
|
||||
.toISOString(),
|
||||
end: date.adjustDate(now, makeOpts(splitTime(entry.end))).toISOString(),
|
||||
resource: boat.$id,
|
||||
reservationDate: now,
|
||||
reason: entry.reason,
|
||||
status: entry.status as StatusTypes,
|
||||
comment: '',
|
||||
|
||||
@@ -22,6 +22,7 @@ export type Interval = Partial<Models.Document> & {
|
||||
resource: string;
|
||||
start: string;
|
||||
end: string;
|
||||
user?: string;
|
||||
};
|
||||
|
||||
export type IntervalTemplate = Partial<Models.Document> & {
|
||||
|
||||
10
src/stores/store-flag.d.ts
vendored
10
src/stores/store-flag.d.ts
vendored
@@ -1,10 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// THIS FEATURE-FLAG FILE IS AUTOGENERATED,
|
||||
// REMOVAL OR CHANGES WILL CAUSE RELATED TYPES TO STOP WORKING
|
||||
import "quasar/dist/types/feature-flag";
|
||||
|
||||
declare module "quasar/dist/types/feature-flag" {
|
||||
interface QuasarFeatureFlags {
|
||||
store: true;
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,7 @@ export const useTaskStore = defineStore('tasks', {
|
||||
AppwriteIds.databaseId,
|
||||
AppwriteIds.collection.task
|
||||
);
|
||||
this.tasks = response.documents as Task[];
|
||||
this.tasks = response.documents as unknown as Task[];
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch tasks', error);
|
||||
}
|
||||
@@ -62,7 +62,7 @@ export const useTaskStore = defineStore('tasks', {
|
||||
AppwriteIds.databaseId,
|
||||
AppwriteIds.collection.taskTags
|
||||
);
|
||||
this.taskTags = response.documents as TaskTag[];
|
||||
this.taskTags = response.documents as unknown as TaskTag[];
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch task tags', error);
|
||||
}
|
||||
@@ -74,7 +74,7 @@ export const useTaskStore = defineStore('tasks', {
|
||||
AppwriteIds.databaseId,
|
||||
AppwriteIds.collection.skillTags
|
||||
);
|
||||
this.skillTags = response.documents as SkillTag[];
|
||||
this.skillTags = response.documents as unknown as SkillTag[];
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch skill tags', error);
|
||||
}
|
||||
@@ -106,7 +106,7 @@ export const useTaskStore = defineStore('tasks', {
|
||||
ID.unique(),
|
||||
newTask
|
||||
);
|
||||
this.tasks.push(response as Task);
|
||||
this.tasks.push(response as unknown as Task);
|
||||
} catch (error) {
|
||||
console.error('Failed to add task:', error);
|
||||
}
|
||||
@@ -129,7 +129,7 @@ export const useTaskStore = defineStore('tasks', {
|
||||
task.$id,
|
||||
newTask
|
||||
);
|
||||
this.tasks.push(response as Task);
|
||||
this.tasks.push(response as unknown as Task);
|
||||
} catch (error) {
|
||||
console.error('Failed to update task:', error);
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export const APP_VERSION = '0.0.0';
|
||||
Reference in New Issue
Block a user