Cleanup linting messages. Also, break some things

This commit is contained in:
2024-05-04 12:08:16 -04:00
parent c92f737612
commit fa4d83e42d
13 changed files with 196 additions and 174 deletions

4
appwrite.json Normal file
View File

@@ -0,0 +1,4 @@
{
"projectId": "65ede55a213134f2b688",
"projectName": ""
}

View File

@@ -24,7 +24,9 @@ const AppwriteIds = {
task: '65ee1cd5b550023fae4f',
taskTags: '65ee21d72d5c8007c34c',
skillTags: '66072582a74d94a4bd01',
boats: '66341910003e287cd71c',
boat: '66341910003e287cd71c',
timeBlock: '66361869002883fb4c4b',
timeBlockTemplate: '66361f480007fdd639af',
},
};

View File

@@ -1,23 +1,26 @@
<template>
<q-card v-for="boat in boats" :key="boat.id" flat class="mobile-card">
<q-card-section>
<q-img :src="boat.imgSrc" :fit="'scale-down'">
<div class="row absolute-top">
<div class="col text-h6 text-left">{{ boat.name }}</div>
<div class="col text-right">{{ boat.class }}</div>
</div>
</q-img>
</q-card-section>
<div v-if="boats">
<q-card v-for="boat in boats" :key="boat.id" flat class="mobile-card">
<q-card-section>
<q-img :src="boat.imgSrc" :fit="'scale-down'">
<div class="row absolute-top">
<div class="col text-h6 text-left">{{ boat.name }}</div>
<div class="col text-right">{{ boat.class }}</div>
</div>
</q-img>
</q-card-section>
<q-separator />
<q-separator />
<q-card-actions align="evenly">
<q-btn flat>Info</q-btn>
<q-btn flat>Book</q-btn>
<q-btn flat>Check-Out</q-btn>
<q-btn flat>Check-In</q-btn>
</q-card-actions>
</q-card>
<q-card-actions align="evenly">
<q-btn flat>Info</q-btn>
<q-btn flat>Book</q-btn>
<q-btn flat>Check-Out</q-btn>
<q-btn flat>Check-In</q-btn>
</q-card-actions>
</q-card>
</div>
<div v-else><q-card>Sorry, no boats to show you!</q-card></div>
</template>
<script setup lang="ts">

View File

@@ -133,7 +133,7 @@
<q-separator />
<q-list dense>
<q-item
v-for="col in props.cols.filter((col) => col.name !== 'desc')"
v-for="col in props.cols.filter((col:Boat) => col.name !== 'desc')"
:key="col.name"
>
<q-item-section>
@@ -215,10 +215,8 @@
import { computed, defineProps, ref } from 'vue';
import { useTaskStore, Task, SkillTag, TaskTag } from 'src/stores/task';
import { QTableProps, date, useQuasar } from 'quasar';
import { useBoatStore } from 'src/stores/boat';
import { useRouter } from 'vue-router';
import { Boat, useBoatStore } from 'src/stores/boat';
const router = useRouter();
const selected = ref([]);
const loading = ref(false); // Placeholder
const fabShow = ref(false);
@@ -266,7 +264,7 @@ const columns = <QTableProps['columns']>[
align: 'left',
label: 'Boat',
field: (row) =>
useBoatStore().boats.find((boat) => boat.$id === row.boat)?.name,
useBoatStore().boats.value.find((boat) => boat.$id === row.boat)?.name,
sortable: true,
},
{
@@ -301,44 +299,51 @@ const columns = <QTableProps['columns']>[
{ name: 'actions', align: 'center', label: 'Actions', field: '$id' },
];
const props = defineProps<{ tasks: Task[] }>();
defineProps<{ tasks: Task[] }>();
const taskStore = useTaskStore();
const $q = useQuasar();
const searchFilter = ref({
interface SearchObject {
title: string;
skillTags: SkillTag[];
taskTags: TaskTag[];
}
const searchFilter = ref<SearchObject>({
title: '',
skillTags: <SkillTag[]>[],
taskTags: <TaskTag[]>[],
skillTags: [],
taskTags: [],
});
const skillTagOptions = ref<SkillTag[]>(taskStore.skillTags);
const taskTagOptions = ref<TaskTag[]>(taskStore.taskTags);
function onRowClick(evt: Event, row: Task) {
router.push({ name: 'edit-task', params: { id: row.$id } });
}
// function onRowClick(evt: Event, row: Task) {
// router.push({ name: 'edit-task', params: { id: row.$id } });
// }
// TODO: Implement server side search
const filterRows = computed(
() => (rows: readonly Task[], terms: any, cols: any, cellValueFn: any) => {
let result = rows;
result = rows.filter((row) =>
terms.title
? row.title.toLowerCase().includes(terms.title.toLowerCase())
: true
);
result = result.filter((row) =>
terms.skillTags && terms.skillTags.length > 0
? row.required_skills.some((req_skill) =>
terms.skillTags.map((t) => t.$id).includes(req_skill)
)
: true
);
result = result.filter((row) =>
terms.taskTags && terms.taskTags.length > 0
? row.tags.some((tag) => terms.taskTags.map((t) => t.$id).includes(tag))
: true
);
return result;
() => (rows: readonly Task[], terms: SearchObject) => {
return rows
.filter((row) =>
terms.title
? row.title.toLowerCase().includes(terms.title.toLowerCase())
: true
)
.filter((row) =>
terms.skillTags && terms.skillTags.length > 0
? row.required_skills.some((req_skill) =>
terms.skillTags.map((t) => t.$id).includes(req_skill)
)
: true
)
.filter((row) =>
terms.taskTags && terms.taskTags.length > 0
? row.tags.some((tag) =>
terms.taskTags.map((t) => t.$id).includes(tag)
)
: true
);
}
);

View File

@@ -11,5 +11,7 @@ import { ref } from 'vue';
import { useBoatStore } from 'src/stores/boat';
import ToolbarComponent from 'src/components/ToolbarComponent.vue';
const boatStore = useBoatStore();
boatStore.fetchBoats();
const boats = ref(useBoatStore().boats);
</script>

View File

@@ -8,32 +8,25 @@
<q-avatar icon="person" />
</q-item-section>
<q-item-section>
Ricky Gervais
{{ authStore.currentUser?.name }}
<q-item-label caption>Name</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-avatar icon="numbers" />
</q-item-section>
<q-item-section>
123456
<q-item-label caption>Member ID</q-item-label>
</q-item-section>
</q-item>
<q-separator />
<q-item>
<q-item-section>
<q-item-label overline>Certifications</q-item-label>
<q-chip square icon="verified" color="green" text-color="white"
>J/27</q-chip
>
<q-chip square icon="verified" color="blue" text-color="white"
>Capri25</q-chip
>
<q-chip square icon="verified" color="red" text-color="white"
>Night</q-chip
>
<div>
<q-chip square icon="verified" color="green" text-color="white"
>J/27</q-chip
>
<q-chip square icon="verified" color="blue" text-color="white"
>Capri25</q-chip
>
<q-chip square icon="verified" color="grey-9" text-color="white"
>Night</q-chip
>
</div>
</q-item-section>
</q-item>
</q-list>
@@ -42,4 +35,7 @@
<script setup lang="ts">
import ToolbarComponent from 'src/components/ToolbarComponent.vue';
import { useAuthStore } from 'src/stores/auth';
const authStore = useAuthStore();
</script>

View File

@@ -50,25 +50,17 @@
</template>
<script setup lang="ts">
import { Reservation, useScheduleStore } from 'src/stores/schedule';
import { useScheduleStore } from 'src/stores/schedule';
import { Reservation } from 'src/stores/schedule.types';
import { ref } from 'vue';
const scheduleStore = useScheduleStore();
import {
TimestampOrNull,
makeDateTime,
makeDate,
parseDate,
today,
} from '@quasar/quasar-ui-qcalendar';
import { TimestampOrNull, parseDate, today } from '@quasar/quasar-ui-qcalendar';
import { QCalendarDay } from '@quasar/quasar-ui-qcalendar';
import { date } from 'quasar';
import { Timestamp } from '@quasar/quasar-ui-qcalendar';
const selectedDate = ref(today());
// Use ref to get a reference to the QCalendarDay component
const calendarRef = ref(QCalendarDay);
// Method declarations
function slotStyle(
@@ -93,16 +85,6 @@ function slotStyle(
function reservationEvents(timestamp: Timestamp) {
return scheduleStore.getBoatReservations(timestamp);
}
function onToday() {
calendarRef.value.moveToToday();
}
function onPrev() {
calendarRef.value.prev();
}
function onNext() {
calendarRef.value.next();
}
function onMoved(data) {
console.log('onMoved', data);
}

View File

@@ -1,8 +1,11 @@
import { Models } from 'appwrite';
import { defineStore } from 'pinia';
import { AppwriteIds, databases } from 'src/boot/appwrite';
import { computed, ref } from 'vue';
// const boatSource = null;
export interface Boat {
export interface Boat extends Models.Document {
$id: string;
name: string;
displayName?: string;
@@ -21,81 +24,27 @@ export interface Boat {
}[];
}
const getSampleData = () => [
{
$id: '1',
name: 'ProjectX',
displayName: 'PX',
class: 'J/27',
year: 1981,
imgSrc: '/tmpimg/j27.png',
iconSrc: '/tmpimg/projectx_avatar256.png',
bookingAvailable: true,
maxPassengers: 8,
requiredCerts: [],
defects: [
{
type: 'engine',
severity: 'moderate',
description: 'Fuel line leaks at engine fitting.',
detail: `The gasket in the end of the fuel hose is damaged, and does not properly seal.
This will cause fuel to leak, and will allow air into the fuel chamber, causing a lean mixture,
and rough engine performance.`,
},
{
type: 'rigging',
severity: 'moderate',
description: 'Tiller extension is broken.',
detail:
'The tiller extension swivel is broken, and will not attach to the tiller.',
},
],
},
{
$id: '2',
name: 'Take5',
displayName: 'T5',
class: 'J/27',
year: 1985,
imgSrc: '/tmpimg/j27.png',
iconsrc: '/tmpimg/take5_avatar32.png',
bookingAvailable: true,
maxPassengers: 8,
requiredCerts: [],
},
{
$id: '3',
name: 'WeeBeestie',
displayName: 'WB',
class: 'Capri 25',
year: 1989,
imgSrc: '/tmpimg/capri25.png',
bookingAvailable: true,
maxPassengers: 6,
requiredCerts: [],
},
{
$id: '4',
name: 'Just My Imagination',
displayName: 'JMI',
class: 'Sirius 28',
year: 1989,
imgSrc: '/tmpimg/JMI.jpg',
bookingAvailable: true,
maxPassengers: 8,
requiredCerts: [],
},
];
export const useBoatStore = defineStore('boat', () => {
const boatData = ref<Boat[]>([]);
export const useBoatStore = defineStore('boat', {
state: () => ({
boats: getSampleData(),
}),
async function fetchBoats() {
try {
const response = await databases.listDocuments(
AppwriteIds.databaseId,
AppwriteIds.collection.boat
);
boatData.value = response.documents as Boat[];
} catch (error) {
console.error('Failed to fetch boats', error);
}
}
getters: {},
const boats = computed(() => {
if (!boatData.value) {
fetchBoats();
}
return boatData;
});
actions: {
// update () {
// }
},
return { boats, fetchBoats };
});

View File

@@ -0,0 +1,65 @@
export const getSampleData = () => [
{
$id: '1',
name: 'ProjectX',
displayName: 'PX',
class: 'J/27',
year: 1981,
imgSrc: '/tmpimg/j27.png',
iconSrc: '/tmpimg/projectx_avatar256.png',
bookingAvailable: true,
maxPassengers: 8,
requiredCerts: [],
defects: [
{
type: 'engine',
severity: 'moderate',
description: 'Fuel line leaks at engine fitting.',
detail: `The gasket in the end of the fuel hose is damaged, and does not properly seal.
This will cause fuel to leak, and will allow air into the fuel chamber, causing a lean mixture,
and rough engine performance.`,
},
{
type: 'rigging',
severity: 'moderate',
description: 'Tiller extension is broken.',
detail:
'The tiller extension swivel is broken, and will not attach to the tiller.',
},
],
},
{
$id: '2',
name: 'Take5',
displayName: 'T5',
class: 'J/27',
year: 1985,
imgSrc: '/tmpimg/j27.png',
iconsrc: '/tmpimg/take5_avatar32.png',
bookingAvailable: true,
maxPassengers: 8,
requiredCerts: [],
},
{
$id: '3',
name: 'WeeBeestie',
displayName: 'WB',
class: 'Capri 25',
year: 1989,
imgSrc: '/tmpimg/capri25.png',
bookingAvailable: true,
maxPassengers: 6,
requiredCerts: [],
},
{
$id: '4',
name: 'Just My Imagination',
displayName: 'JMI',
class: 'Sirius 28',
year: 1989,
imgSrc: '/tmpimg/JMI.jpg',
bookingAvailable: true,
maxPassengers: 8,
requiredCerts: [],
},
];

View File

@@ -48,7 +48,7 @@ export function getSampleTimeBlocks(): Timeblock[] {
.map((b): Timeblock[] => {
return template.blocks.map((t): Timeblock => {
return {
id: 'id' + Math.random().toString(32).slice(2),
$id: 'id' + Math.random().toString(32).slice(2),
boatId: b.$id,
start: addToDate(tsToday, { day: i }).date + ' ' + t[0],
end: addToDate(tsToday, { day: i }).date + ' ' + t[1],

View File

@@ -9,17 +9,18 @@ import {
} from '@quasar/quasar-ui-qcalendar';
import { Reservation, Timeblock } from './schedule.types';
import {
getSampleReservations,
getSampleTimeBlocks,
} from './sampledata/schedule';
import { AppwriteIds, databases } from 'src/boot/appwrite';
export const useScheduleStore = defineStore('schedule', () => {
// TODO: Implement functions to dynamically pull this data.
const reservations = ref<Reservation[]>(getSampleReservations());
const timeblocks = ref<Timeblock[]>(getSampleTimeBlocks());
const reservations = ref<Reservation[]>([]);
const timeblocks = ref<Timeblock[]>([]);
const getTimeblocksForDate = (date: string): Timeblock[] => {
// TODO: This needs to actually make sure we have the dates we need, stay in sync, etc.
if (!timeblocks.value) {
fetchTimeBlocks();
}
return timeblocks.value.filter((b) =>
compareDate(parsed(b.start) as Timestamp, parsed(date) as Timestamp)
);
@@ -40,6 +41,17 @@ export const useScheduleStore = defineStore('schedule', () => {
});
};
async function fetchTimeBlocks() {
try {
const response = await databases.listDocuments(
AppwriteIds.databaseId,
AppwriteIds.collection.timeBlock
);
timeblocks.value = response.documents as Timeblock[];
} catch (error) {
console.error('Failed to fetch timeblocks', error);
}
}
// const getConflicts = (timeblock: Timeblock, boat: Boat) => {
// const start = date.buildDate({
// hour: timeblock.start.hour,
@@ -55,6 +67,7 @@ export const useScheduleStore = defineStore('schedule', () => {
// });
// return scheduleStore.getConflictingReservations(boat, start, end);
// };
const getConflictingReservations = (
resource: Boat,
start: Date,

View File

@@ -1,3 +1,4 @@
import { Models } from 'appwrite';
import type { Boat } from './boat';
export type StatusTypes = 'tentative' | 'confirmed' | 'pending' | undefined;
@@ -17,8 +18,7 @@ export interface Reservation {
objects in here? */
export type timeTuple = [start: string, end: string];
export interface Timeblock {
id: string;
export interface Timeblock extends Models.Document {
boatId: string;
start: string;
end: string;

View File

@@ -92,6 +92,7 @@ export const useTaskStore = defineStore('tasks', {
docId
);
this.tasks = this.tasks.filter((task) => docId !== task.$id);
console.log(response);
} catch (error) {
// Need some better error handling, here.
console.error('Failed to delete task:', error);