Clean up all kinds of typescript issues

This commit is contained in:
2024-05-05 15:58:58 -04:00
parent 634cff507c
commit 8e73650462
21 changed files with 380 additions and 159 deletions

View File

@@ -3,9 +3,16 @@
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { defineComponent, onMounted } from 'vue';
import { useBoatStore } from './stores/boat';
import { useScheduleStore } from './stores/schedule';
export default defineComponent({
name: 'OYS Borrow-a-Boat',
});
onMounted(async () => {
await useBoatStore().fetchBoats();
await useScheduleStore().fetchTimeBlocks();
});
</script>

View File

@@ -13,9 +13,10 @@ const client = new Client();
// const appDatabaseId = '654ac5044d1c446feb71';
// Private self-hosted appwrite
client
.setEndpoint(process.env.APPWRITE_API_ENDPOINT)
.setProject(process.env.APPWRITE_API_PROJECT);
if (process.env.APPWRITE_API_ENDPOINT && process.env.APPWRITE_API_PROJECT)
client
.setEndpoint(process.env.APPWRITE_API_ENDPOINT)
.setProject(process.env.APPWRITE_API_PROJECT);
//TODO move this to config file
const AppwriteIds = {

View File

@@ -1,64 +0,0 @@
<template>
<div>
<p>{{ title }}</p>
<ul>
<li v-for="todo in todos" :key="todo.id" @click="increment">
{{ todo.id }} - {{ todo.content }}
</li>
</ul>
<p>Count: {{ todoCount }} / {{ meta.totalCount }}</p>
<p>Active: {{ active ? 'yes' : 'no' }}</p>
<p>Clicks on todos: {{ clickCount }}</p>
</div>
</template>
<script lang="ts">
import {
defineComponent,
PropType,
computed,
ref,
toRef,
Ref,
} from 'vue';
import { Todo, Meta } from './models';
function useClickCount() {
const clickCount = ref(0);
function increment() {
clickCount.value += 1
return clickCount.value;
}
return { clickCount, increment };
}
function useDisplayTodo(todos: Ref<Todo[]>) {
const todoCount = computed(() => todos.value.length);
return { todoCount };
}
export default defineComponent({
name: 'ExampleComponent',
props: {
title: {
type: String,
required: true
},
todos: {
type: Array as PropType<Todo[]>,
default: () => []
},
meta: {
type: Object as PropType<Meta>,
required: true
},
active: {
type: Boolean
}
},
setup (props) {
return { ...useClickCount(), ...useDisplayTodo(toRef(props, 'todos')) };
},
});
</script>

View File

@@ -116,7 +116,7 @@ import { Boat, useBoatStore } from 'src/stores/boat';
import { useScheduleStore } from 'src/stores/schedule';
import { date } from 'quasar';
import { computed } from 'vue';
import type { StatusTypes } from 'src/stores/schedule';
import type { StatusTypes } from 'src/stores/schedule.types';
interface EventData {
event: object;
@@ -172,7 +172,7 @@ function monthFormatter() {
function getEvents(scope: ResourceIntervalScope) {
const resourceEvents = scheduleStore.getBoatReservations(
date.extractDate(selectedDate.value, 'YYYY-MM-DD'),
parseDate(date.extractDate(selectedDate.value, 'YYYY-MM-DD')) as Timestamp,
scope.resource.$id
);

View File

@@ -15,7 +15,6 @@
:short-interval-label="true"
v-model="selectedDate"
:column-count="boatData.length"
@change="changeEvent"
v-touch-swipe.left.right="handleSwipe"
>
<template #head-day="{ scope }">
@@ -71,15 +70,13 @@ import {
parseTimestamp,
parseDate,
addToDate,
makeDateTime,
} from '@quasar/quasar-ui-qcalendar';
import CalendarHeaderComponent from './CalendarHeaderComponent.vue';
import { ref, computed, onMounted } from 'vue';
import { Boat, useBoatStore } from 'src/stores/boat';
import { useBoatStore } from 'src/stores/boat';
import { useScheduleStore } from 'src/stores/schedule';
import { Reservation, Timeblock } from 'src/stores/schedule.types';
import { date } from 'quasar';
import { Timeblock } from 'src/stores/schedule.types';
const scheduleStore = useScheduleStore();
const boatStore = useBoatStore();
@@ -98,18 +95,18 @@ onMounted(async () => {
function handleSwipe({ ...event }) {
event.direction === 'right' ? calendar.value?.prev() : calendar.value?.next();
}
function reservationStyles(
reservation: Reservation,
timeStartPos: (t: string) => string,
timeDurationHeight: (d: number) => string
) {
return genericBlockStyle(
parseDate(reservation.start) as Timestamp,
parseDate(reservation.end) as Timestamp,
timeStartPos,
timeDurationHeight
);
}
// function reservationStyles(
// reservation: Reservation,
// timeStartPos: (t: string) => string,
// timeDurationHeight: (d: number) => string
// ) {
// return genericBlockStyle(
// parseDate(reservation.start) as Timestamp,
// parseDate(reservation.end) as Timestamp,
// timeStartPos,
// timeDurationHeight
// );
// }
function blockStyles(
block: Timeblock,
@@ -190,33 +187,33 @@ function getBoatBlocks(scope: DayBodyScope): Timeblock[] {
: [];
}
function changeEvent({ start }: { start: string }) {
// const newBlocks = scheduleStore.getTimeblocksForDate(start);
// const reservations = scheduleStore.getBoatReservations(
// parsed(start) as Timestamp
// );
// boatData.value.map((boat) => {
// boat.reservations = reservations.filter(
// (reservation) => reservation.resource === boat
// );
// boat.blocks = newBlocks.filter(
// (block) =>
// block.boatId === boat.$id &&
// boat.reservations?.filter(
// (r: Reservation) =>
// r.start <
// date.addToDate(makeDateTime(parsed(block.end) as Timestamp), {
// hours: 4,
// }) &&
// r.end >
// date.addToDate(makeDateTime(parsed(block.start) as Timestamp), {
// hours: 4,
// })
// ).length == 0
// );
// });
// setTimeout(() => calendar.value?.scrollToTime('09:00'), 100); // Should figure out why we need this setTimeout...
}
// function changeEvent({ start }: { start: string }) {
// const newBlocks = scheduleStore.getTimeblocksForDate(start);
// const reservations = scheduleStore.getBoatReservations(
// parsed(start) as Timestamp
// );
// boatData.value.map((boat) => {
// boat.reservations = reservations.filter(
// (reservation) => reservation.resource === boat
// );
// boat.blocks = newBlocks.filter(
// (block) =>
// block.boatId === boat.$id &&
// boat.reservations?.filter(
// (r: Reservation) =>
// r.start <
// date.addToDate(makeDateTime(parsed(block.end) as Timestamp), {
// hours: 4,
// }) &&
// r.end >
// date.addToDate(makeDateTime(parsed(block.start) as Timestamp), {
// hours: 4,
// })
// ).length == 0
// );
// });
// setTimeout(() => calendar.value?.scrollToTime('09:00'), 100); // Should figure out why we need this setTimeout...
// }
const disabledBefore = computed(() => {
const todayTs = parseTimestamp(today()) as Timestamp;

View File

@@ -57,7 +57,7 @@ import { ref, reactive, computed } from 'vue';
const selectedDate = defineModel<string>();
const weekdays = reactive([0, 1, 2, 3, 4, 5, 6]),
const weekdays = reactive([1, 2, 3, 4, 5, 6, 0]),
locale = ref('en-CA'),
monthFormatter = monthFormatterFunc(),
dayFormatter = dayFormatterFunc(),
@@ -124,8 +124,14 @@ function dayClass(day: Timestamp) {
}
function monthFormatterFunc() {
const longOptions = { timeZone: 'UTC', month: 'long' };
const shortOptions = { timeZone: 'UTC', month: 'short' };
const longOptions: Intl.DateTimeFormatOptions = {
timeZone: 'UTC',
month: 'long',
};
const shortOptions: Intl.DateTimeFormatOptions = {
timeZone: 'UTC',
month: 'short',
};
return createNativeLocaleFormatter(locale.value, (_tms, short) =>
short ? shortOptions : longOptions
@@ -133,17 +139,28 @@ function monthFormatterFunc() {
}
function weekdayFormatterFunc() {
const longOptions = { timeZone: 'UTC', weekday: 'long' };
const shortOptions = { timeZone: 'UTC', weekday: 'short' };
const longOptions: Intl.DateTimeFormatOptions = {
timeZone: 'UTC',
weekday: 'long',
};
const shortOptions: Intl.DateTimeFormatOptions = {
timeZone: 'UTC',
weekday: 'short',
};
return createNativeLocaleFormatter(locale.value, (_tms, short) =>
short ? shortOptions : longOptions
);
}
function dayFormatterFunc() {
const longOptions = { timeZone: 'UTC', day: '2-digit' };
const shortOptions = { timeZone: 'UTC', day: 'numeric' };
const longOptions: Intl.DateTimeFormatOptions = {
timeZone: 'UTC',
day: '2-digit',
};
const shortOptions: Intl.DateTimeFormatOptions = {
timeZone: 'UTC',
day: 'numeric',
};
return createNativeLocaleFormatter(locale.value, (_tms, short) =>
short ? shortOptions : longOptions

View File

@@ -20,5 +20,5 @@
import { defineProps } from 'vue';
import type { Task } from 'src/stores/task';
const props = defineProps<{ task: Task }>();
defineProps<{ task: Task }>();
</script>

View File

@@ -162,7 +162,7 @@ import { useRouter } from 'vue-router';
import { useTaskStore, TASKSTATUS } from 'src/stores/task';
import type { TaskTag, SkillTag, Task } from 'src/stores/task';
import { date } from 'quasar';
import { Boat, useBoatStore } from 'src/stores/boat';
import { useBoatStore } from 'src/stores/boat';
const props = defineProps<{ taskId?: string }>();
const taskStore = useTaskStore();
@@ -187,7 +187,7 @@ const targetTask = taskId && taskStore.tasks.find((t) => t.$id === taskId);
const modifiedTask = reactive(targetTask ? targetTask : defaultTask);
let tasks = taskStore.tasks;
const boatList = ref<Boat[]>(useBoatStore().boats);
const boatList = useBoatStore().boats;
const skillTagOptions = ref<SkillTag[]>(taskStore.skillTags);
const taskTagOptions = ref<TaskTag[]>(taskStore.taskTags);

View File

@@ -30,7 +30,7 @@
rounded
class="bg-warning text-grey-10"
style="max-width: 95vw; margin: auto"
v-if="bookingForm.boat?.defects"
v-if="bookingForm.boat && bookingForm.boat.defects.length > 0"
>
<template v-slot:avatar>
<q-icon name="warning" color="grey-10" />
@@ -63,7 +63,7 @@
><q-banner v-if="bookingForm.boat"
>Passengers:
{{ bookingForm.members.length + bookingForm.guests.length }} /
{{ bookingForm.boat.booking?.maxPassengers }}</q-banner
{{ bookingForm.boat.maxPassengers }}</q-banner
>
<q-item
class="q-my-sm"

View File

@@ -85,22 +85,22 @@ function slotStyle(
function reservationEvents(timestamp: Timestamp) {
return scheduleStore.getBoatReservations(timestamp);
}
function onMoved(data) {
function onMoved(data: Event) {
console.log('onMoved', data);
}
function onChange(data) {
function onChange(data: Event) {
console.log('onChange', data);
}
function onClickDate(data) {
function onClickDate(data: Event) {
console.log('onClickDate', data);
}
function onClickTime(data) {
function onClickTime(data: Event) {
console.log('onClickTime', data);
}
function onClickInterval(data) {
function onClickInterval(data: Event) {
console.log('onClickInterval', data);
}
function onClickHeadDay(data) {
function onClickHeadDay(data: Event) {
console.log('onClickHeadDay', data);
}
</script>

View File

@@ -0,0 +1,47 @@
<template>
<div class="fit row wrap justify-start items-start content-start">
<div class="col-9">
<div class="scheduler">
<q-calendar-scheduler
ref="calendar"
v-model="selectedDate"
v-model:model-resources="resources"
view="week"
:drag-enter-func="onDragEnter"
:drag-over-func="onDragOver"
:drag-leave-func="onDragLeave"
:drop-func="onDrop"
:weekday-class="onWeekdayClass"
:day-class="onDayClass"
:weekdays="[1, 2, 3, 4, 5]"
hoverable
animated
bordered
:day-min-height="50"
:day-height="0"
style="max-width: 800px; width: 100%"
@change="onChange"
@moved="onMoved"
@click-date="onClickDate"
@click-day-resource="onClickDayResource"
@click-resource="onClickResource"
@click-head-resources="onClickHeadResources"
@click-head-day="onClickHeadDay"
></q-calendar-scheduler>
</div>
</div>
HI!
<div class="col-3">
<!---->
</div>
</div>
</template>
<script setup type="ts">
import {QCalendarScheduler, today} from '@quasar/quasar-ui-qcalendar'
import { useBoatStore } from 'src/stores/boat';
import { ref } from 'vue';
const selectedDate = ref(today())
const resources = ref(useBoatStore().boats)
</script>

View File

@@ -23,5 +23,6 @@ const navlinks = [
label: 'Create a Reservation',
},
{ icon: 'calendar_month', to: '/schedule/view', label: 'View Schedule' },
{ icon: 'edit_calendar', to: '/schedule/manage', label: 'Manage Calendar' },
];
</script>

View File

@@ -40,6 +40,11 @@ const routes: RouteRecordRaw[] = [
component: () => import('src/pages/schedule/BoatScheduleView.vue'),
name: 'boat-schedule',
},
{
path: 'manage',
component: () => import('src/pages/schedule/ManageCalendar.vue'),
name: 'manage-schedule',
},
],
},
{

View File

@@ -1,6 +1,6 @@
import { defineStore } from 'pinia';
import { ID, account } from 'boot/appwrite';
import type { Models } from 'appwrite';
import { OAuthProvider, type Models } from 'appwrite';
import { ref } from 'vue';
export const useAuthStore = defineStore('auth', () => {
@@ -21,12 +21,12 @@ export const useAuthStore = defineStore('auth', () => {
return await login(email, password);
}
async function login(email: string, password: string) {
await account.createEmailSession(email, password);
await account.createEmailPasswordSession(email, password);
currentUser.value = await account.get();
}
async function googleLogin() {
account.createOAuth2Session(
'google',
OAuthProvider.Google,
'https://bab.toal.ca/',
'https://bab.toal.ca/#/login'
);

View File

@@ -13,10 +13,10 @@ export interface Boat extends Models.Document {
year?: number;
imgSrc?: string;
iconSrc?: string;
bookingAvailable?: boolean;
bookingAvailable: boolean;
requiredCerts: string[];
maxPassengers: number;
defects?: {
defects: {
type: string;
severity: string;
description: string;

View File

@@ -44,7 +44,7 @@ export function getSampleTimeBlocks(): Timeblock[] {
for (let i = 0; i <= 30; i++) {
const template = templateB;
result.push(
...boats
...boats.value
.map((b): Timeblock[] => {
return template.blocks.map((t): Timeblock => {
return {
@@ -126,7 +126,7 @@ export function getSampleReservations(): Reservation[] {
};
return sampleData.map((entry): Reservation => {
const boat = <Boat>boatStore.boats.find((b) => b.$id == entry.boat);
const boat = <Boat>boatStore.boats.value.find((b) => b.$id == entry.boat);
return {
id: entry.id,
user: entry.user,

View File

@@ -18,12 +18,12 @@ export interface Reservation {
objects in here? */
export type timeTuple = [start: string, end: string];
export interface Timeblock extends Models.Document {
export type Timeblock = Partial<Models.Document> & {
boatId: string;
start: string;
end: string;
selected?: false;
}
};
export interface TimeBlockTemplate {
id: string;