39 Commits

Author SHA1 Message Date
052cae2c2e Update project
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m27s
2024-03-10 12:54:49 -04:00
29170f9e13 Add personas to docs 2024-03-10 11:45:00 -04:00
25ed6df62a Update quasar
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m11s
2024-03-07 21:49:38 -05:00
2f86700fb7 Change Number
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m33s
2024-02-13 14:56:41 -05:00
e7a79736b7 Change icons to blue
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 3m3s
2024-01-16 14:19:38 -05:00
2d585d499e Final build working
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m50s
2024-01-01 18:56:12 -05:00
284d5ffcb4 Move env file creation to the right place
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 3m2s
2024-01-01 18:48:58 -05:00
27a476ae00 Test
Some checks failed
Build BAB Application Deployment Artifact / build (push) Has been cancelled
2024-01-01 18:47:11 -05:00
ee7f79550c Fix name of .env file
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 3m1s
2024-01-01 18:42:57 -05:00
2ef801905b Update envfile
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 3m3s
2024-01-01 18:30:54 -05:00
752421c9fc Add the env file, so app builds with correct API info
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 3m3s
2024-01-01 17:39:11 -05:00
ce169f6a61 reorder install
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m56s
2024-01-01 13:42:03 -05:00
622b9fc82d Install dependencies with yarn
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m58s
2024-01-01 13:19:10 -05:00
275f23c421 Remove npm package-lock.json
Some checks failed
Build BAB Application Deployment Artifact / build (push) Failing after 59s
2024-01-01 13:12:48 -05:00
88ed4caf5b Update all yarn packages
Some checks failed
Build BAB Application Deployment Artifact / build (push) Failing after 2m2s
2024-01-01 13:10:30 -05:00
346e395e15 Build tar, as all the dates are messed up with zip
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m23s
2023-12-31 15:32:09 -05:00
f30848803b Update Boat selection component
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m33s
2023-12-31 15:04:53 -05:00
96dab93483 Fix URL Path
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m29s
2023-12-29 23:58:04 -05:00
a6abee1ddf Enable verbosity for debugging
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m29s
2023-12-29 12:45:19 -05:00
b20f2bffd6 Remove Secret
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m29s
2023-12-29 12:33:36 -05:00
f6689cbc5c Change url from secret to var
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m37s
2023-12-29 12:19:39 -05:00
8383605115 Disable SSL verification
Some checks failed
Build BAB Application Deployment Artifact / build (push) Failing after 2m31s
2023-12-29 12:14:20 -05:00
f69614d5c7 Fix URL again
Some checks failed
Build BAB Application Deployment Artifact / build (push) Failing after 2m40s
2023-12-29 12:06:24 -05:00
f7902011cc Fix action url
Some checks failed
Build BAB Application Deployment Artifact / build (push) Failing after 5s
2023-12-29 12:04:21 -05:00
e86876ba69 Update Actions
Some checks failed
Build BAB Application Deployment Artifact / build (push) Failing after 5s
2023-12-29 11:29:31 -05:00
cd6f2e3ba2 Updates to selection component
Some checks failed
Build BAB Application Deployment Artifact / build (push) Failing after 2m27s
2023-12-29 09:22:28 -05:00
66e2169f45 Adapting to time blocks for bookings
Some checks failed
Build BAB Application Deployment Artifact / build (push) Failing after 2m11s
2023-12-23 11:39:54 -05:00
489cc2646b Try v4 of the upload-artifact action
Some checks failed
Build BAB Application Deployment Artifact / build (push) Failing after 2m15s
2023-12-20 14:23:42 -05:00
295f1f7449 Don't bother tar/gz, as it's adding an extra, unnecessary step
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m20s
2023-12-20 13:59:50 -05:00
33a1bc24f6 Test run number addition to build
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m21s
2023-12-20 12:27:27 -05:00
d18780bb21 Begin implementation of timeblocks. Update workflow to build on devel branch
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m21s
2023-12-20 10:48:51 -05:00
ef569ac3b1 Merge minor edits from development.
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m30s
2023-12-18 20:50:51 -05:00
9390b7035c Change interval to 1h. Create StatusTypes 2023-12-18 20:44:01 -05:00
ac1730401a Add a shortened displayName for boats for a better mobile experience 2023-12-18 20:23:17 -05:00
bc41b1a7a1 Add bordered logo
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 3m42s
2023-12-18 18:10:05 -05:00
ea566d4a42 Add docs folder and design of users
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m31s
2023-12-18 14:26:03 -05:00
573e327a0f Move hard-coded API settings to .env file 2023-12-03 08:51:01 -05:00
831e81e892 Update package.json 2023-12-03 08:19:57 -05:00
39a6ab5fcc New workflow steps to use version
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 3m9s
2023-12-02 23:19:02 -05:00
17 changed files with 1395 additions and 919 deletions

View File

@@ -1,9 +1,10 @@
name: Build BAB Application Deployment Artifact
run-name: ${{ gitea.actor }} is building an artifact 🚀
run-name: ${{ gitea.actor }} is building a BAB App artifact 🚀
on:
push:
branches:
- main
- devel
jobs:
build:
@@ -15,16 +16,35 @@ jobs:
uses: actions/setup-node@v2
with:
node-version: '20.x'
- name: Install dependencies
run: npm install
- name: Install yarn
run: npm install --global yarn
- name: Install yarn dependencies
run: yarn install
- name: Install Quasar CLI
run: npm install -g @quasar/cli
run: yarn global add @quasar/cli
- name: Create env file
run: |
echo "${{ vars.ENV_FILE }}" > .env.local
- name: Show env file
run: |
/bin/cat .env.local
- name: Build Project
run: quasar build -m pwa
# - name: Archive Production Artifact
# uses: actions/upload-artifact@v2
# with:
# name: build-artifact
# path: dist/pwa
- name: Get Version Number
id: get_version
run: echo "::set-output name=VERSION::$(node -p "require('./package.json').version")"
- name: Tarfile
run: |
cd dist/pwa
tar czf ../../build-${{ steps.get_version.outputs.VERSION }}.tar.gz .
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: build-artifact-${{ steps.get_version.outputs.VERSION }}.${{ gitea.run_number }}
path: build-${{ steps.get_version.outputs.VERSION }}.tar.gz
- name: Trigger Ansible Deploy Playbook
uses: https://github.com/distributhor/workflow-webhook@v3
with:
webhook_url: ${{ vars.WEBHOOK_URL }}
verbose: true
data: '{ "artifact_url": "${{ gitea.server_url }}/${{ gitea.repository }}/actions/runs/${{ gitea.run_id}}/artifacts/build-artifact-${{ steps.get_version.outputs.VERSION }}.${{ gitea.run_number }}" }'

View File

@@ -0,0 +1,8 @@
# Personas
- BAB Member
- Certified Skipper
- Program Administrator
- Boatswain
- Volunteer
- Instructor

View File

@@ -0,0 +1,40 @@
# Users, Roles and Permissions
This is the design document for https://gitea.toal.ca/oys/bab-app/issues/11
## Backend Concepts
Utilizing the AppWrite backend provides us with some basic concepts we can use:
### Users, Groups, and Labels
#### Teams
Teams are AppWrite groups of users. Teams can be assigned roles, which can be assigned permissions. Teams "contain" users. A team has more permissions to manage it's members than labels, which are assigned / removed, rather than 'invited / left'.
#### Labels
Labels are AppWrite tags for users. Users have Labels as attributes. Like teams, labels can be used for Role / Permission mapping.
### Permissions
https://appwrite.io/docs/advanced/platform/permissions
Permissions are fine-grained access control for users and objects. They follow standard "CRUD" patterns.
## BAB Concepts
For teams, there will, to start, be the following:
- `staff` : Individuals with authority / responsibilities
- `maintenance` : Staff responsible for maintenance (eg: Boatswain)
- `admin`: Administrators of the program / application
- `school` : Members of the Sailing School (Instructors & Students)
- `student` role : A student in the school
- `instructor` role: An instructor in the school
- `bab` : Members of the BAB program
- `skipper` role: A member who has passed skipper certification
The following are the initial labels:
- TBD

View File

@@ -16,21 +16,22 @@
"@quasar/extras": "^1.16.4",
"appwrite": "^13.0.0",
"pinia": "^2.1.7",
"quasar": "^2.6.0",
"vue": "^3.0.0",
"vue-router": "^4.0.0"
"vue": "3",
"vue-router": "4"
},
"devDependencies": {
"@quasar/app-vite": "^1.3.0",
"@quasar/app-vite": "^1.7.4",
"@quasar/quasar-app-extension-qcalendar": "^4.0.0-beta.15",
"@types/node": "^12.20.21",
"@typescript-eslint/eslint-plugin": "^5.10.0",
"@typescript-eslint/parser": "^5.10.0",
"autoprefixer": "^10.4.2",
"dotenv": "^16.3.1",
"eslint": "^8.10.0",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-vue": "^9.0.0",
"prettier": "^2.5.1",
"quasar": "^2.14.6",
"typescript": "^4.5.4",
"workbox-build": "^7.0.0",
"workbox-cacheable-response": "^7.0.0",
@@ -38,10 +39,11 @@
"workbox-expiration": "^7.0.0",
"workbox-precaching": "^7.0.0",
"workbox-routing": "^7.0.0",
"workbox-strategies": "^7.0.0"
"workbox-strategies": "^7.0.0",
"yarn": "^1.22.21"
},
"engines": {
"node": "^18 || ^16 || ^14.19",
"node": "^20 || ^18 || ^16 || ^14.19",
"npm": ">= 6.13.4",
"yarn": ">= 1.21.1"
}

View File

@@ -48,6 +48,7 @@ module.exports = configure(function (/* ctx */) {
// Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#build
build: {
env: require('dotenv').config({ path: '.env.local' }).parsed,
target: {
browser: ['es2019', 'edge88', 'firefox78', 'chrome87', 'safari13.1'],
node: 'node16',

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

View File

@@ -14,8 +14,8 @@ const client = new Client();
// Private self-hosted appwrite
client
.setEndpoint('https://apidev.bab.toal.ca/v1')
.setProject('655a7116479b4d5a815f');
.setEndpoint(process.env.APPWRITE_API_ENDPOINT)
.setProject(process.env.APPWRITE_API_PROJECT);
//TODO
const appDatabaseId = '';

View File

@@ -1,3 +1,4 @@
<!-- This has been abandoned for now. Going to block-based booking. Will probably need the schedule viewer functionality at some point in the future, though -->
<template>
<q-card-section>
<div class="text-caption text-justify">
@@ -55,11 +56,13 @@
v-model="selectedDate"
:model-resources="boatStore.boats"
resource-key="id"
resource-label="name"
:interval-start="12"
:interval-count="36"
:interval-minutes="30"
resource-label="displayName"
resource-width="32"
:interval-start="6"
:interval-count="18"
:interval-minutes="60"
cell-width="48"
style="--calendar-resources-width: 48px"
resource-min-height="40"
animated
bordered
@@ -79,8 +82,8 @@
</template>
<template #resource-label="{ scope: { resource } }">
<div class="col-12">
{{ resource.name }}
<div class="col-12 .col-md-auto">
{{ resource.displayName }}
<q-icon v-if="resource.defects" name="warning" color="warning" />
</div>
</template>
@@ -98,7 +101,6 @@
><template v-slot:append><q-icon name="timelapse" /></template></q-select
></q-card-section>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import {
@@ -114,6 +116,17 @@ 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';
type EventData = {
event: object;
scope: {
timestamp: object;
columnindex: number;
activeDate: boolean;
droppable: boolean;
};
};
const durations = [1, 1.5, 2, 2.5, 3, 3.5, 4];
@@ -179,7 +192,7 @@ function getStyle(event: {
left: number;
width: number;
title: string;
status: 'tentative' | 'confirmed' | 'pending';
status: StatusTypes;
}) {
return {
position: 'absolute',
@@ -200,14 +213,16 @@ function onPrev() {
function onNext() {
calendar.value.next();
}
function onClickDate(data) {
return;
function onClickDate(data: EventData) {
return data;
}
function onClickTime(data) {
function onClickTime(data: EventData) {
// TODO: Add a duration picker, here.
emit('onClickTime', data);
}
function onUpdateDuration(value) {
function onUpdateDuration(value: EventData) {
emit('onUpdateDuration', value);
}
// eslint-disable-next-line @typescript-eslint/no-empty-function

View File

@@ -0,0 +1,193 @@
<template>
<q-card-section style="max-width: 320px">
<div class="text-caption">
Use the calendar to pick a date. Select an available boat and timeslot
below.
</div>
<div
style="
width: 100%;
max-width: 320px;
display: flex;
justify-content: center;
"
>
<div
style="
width: 50%;
max-width: 350px;
display: flex;
justify-content: space-between;
"
>
<span
class="q-button"
style="cursor: pointer; user-select: none"
@click="onPrev"
>&lt;</span
>
{{ formattedMonth }}
<span
class="q-button"
style="cursor: pointer; user-select: none"
@click="onNext"
>&gt;</span
>
</div>
</div>
<div
style="
display: flex;
justify-content: center;
align-items: center;
flex-wrap: nowrap;
"
>
<div style="display: flex; width: 100%">
<q-calendar-month
ref="calendar"
v-model="selectedDate"
:disabled-before="disabledBefore"
:disabled-days="disabledDays()"
animated
bordered
mini-mode
date-type="rounded"
@click-date="onClickDate"
@change="onChange"
/>
</div></div
></q-card-section>
<q-card-section style="max-width: 320px">
<div v-for="boat in boatStore.boats" :key="boat.name">
<q-item-label header>{{ boat.name }}</q-item-label>
<q-item>
<q-item-section>
<q-option-group
:options="boatoptions(boat)"
type="radio"
v-model="selectedBoatTime"
>
<template v-slot:label="opt">
<div class="row items-center">
{{ opt.label }} &nbsp;
<span class="text-caption" v-if="opt.disable"
>Reserved by {{ opt.user }}</span
>
</div></template
>
</q-option-group>
</q-item-section>
</q-item>
</div>
</q-card-section>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import {
today,
parseTimestamp,
addToDate,
Timestamp,
} from '@quasar/quasar-ui-qcalendar';
import { Boat, useBoatStore } from 'src/stores/boat';
import { useScheduleStore, Timeblock } from 'src/stores/schedule';
import { computed } from 'vue';
import { date } from 'quasar';
type EventData = {
event: object;
scope: {
timestamp: object;
columnindex: number;
activeDate: boolean;
droppable: boolean;
};
};
const calendar = ref();
const boatStore = useBoatStore();
const scheduleStore = useScheduleStore();
const selectedDate = ref(today());
const selectedBoatTime = ref();
const formattedMonth = computed(() => {
const date = new Date(selectedDate.value);
return monthFormatter()?.format(date);
});
const disabledBefore = computed(() => {
const todayTs = parseTimestamp(today()) as Timestamp;
return addToDate(todayTs, { day: -1 }).date;
});
function monthFormatter() {
try {
return new Intl.DateTimeFormat('en-CA' || undefined, {
month: 'long',
timeZone: 'UTC',
});
} catch (e) {
//
}
}
const disabledDays = () => {
// Placeholder. This should actually compute days when boats aren't available.
const days = [];
const todayTs = parseTimestamp(today()) as Timestamp;
days.push(addToDate(todayTs, { day: 2 }).date);
return days;
};
const boatoptions = (boat: Boat) => {
const options = useScheduleStore()
.getTimeblocksForDate(date.extractDate(selectedDate.value, 'YYYY-MM-DD'))
.map((x: Timeblock) => {
const conflicts = getConflicts(x, boat);
return {
label: x.start.time + ' to ' + x.end.time,
value: boat.id + ':' + x.start.time,
disable: conflicts.length > 0,
user: conflicts[0]?.user,
boat: boat,
timeblock: x,
};
});
return options;
};
const emit = defineEmits(['onClickTime', 'onUpdateDuration']);
function onPrev() {
calendar.value.prev();
}
function onNext() {
calendar.value.next();
}
function onClickDate(data: EventData) {
return data;
}
function onChange(data: EventData) {
return data;
}
const getConflicts = (timeblock: Timeblock, boat: Boat) => {
const start = date.buildDate({
hour: timeblock.start.hour,
minute: timeblock.start.minute,
second: 0,
millisecond: 0,
});
const end = date.buildDate({
hour: timeblock.end.hour,
minute: timeblock.end.minute,
second: 0,
millisecond: 0,
});
return scheduleStore.getConflictingReservations(boat, start, end);
};
</script>

View File

@@ -17,7 +17,7 @@
<q-avatar icon="numbers" />
</q-item-section>
<q-item-section>
12345
123456
<q-item-label caption>Member ID</q-item-label>
</q-item-section>
</q-item>
@@ -25,13 +25,13 @@
<q-item>
<q-item-section>
<q-item-label overline>Certifications</q-item-label>
<q-chip square icon="verified" color="primary" text-color="white"
<q-chip square icon="verified" color="blue" text-color="white"
>J/27</q-chip
>
<q-chip square icon="verified" color="green" text-color="white"
<q-chip square icon="verified" color="blue" text-color="white"
>Capri25</q-chip
>
<q-chip square icon="verified" color="grey-8" text-color="white"
<q-chip square icon="verified" color="blue" text-color="white"
>Night</q-chip
>
</q-item-section>

View File

@@ -0,0 +1,8 @@
<template>
<q-page padding>
<!-- content -->
</q-page>
</template>
<script setup lang="ts">
</script>

View File

@@ -21,14 +21,8 @@
:caption="bookingSummary"
>
<q-separator />
<resource-schedule-viewer-component
@on-click-time="onClickTime"
@on-update-duration="
(value) => {
bookingForm.duration = value;
}
"
/>
<boat-selection />
<q-banner
rounded
class="bg-warning text-grey-10"
@@ -78,7 +72,7 @@ import { reactive, ref, computed, watch } from 'vue';
import { useAuthStore } from 'src/stores/auth';
import { Boat, useBoatStore } from 'src/stores/boat';
import { Dialog, date } from 'quasar';
import ResourceScheduleViewerComponent from 'src/components/ResourceScheduleViewerComponent.vue';
import BoatSelection from 'src/components/scheduling/BoatSelection.vue';
import { makeDateTime } from '@quasar/quasar-ui-qcalendar';
import { useScheduleStore, Reservation } from 'src/stores/schedule';
@@ -113,7 +107,7 @@ watch(bookingForm, (b, a) => {
status: 'tentative',
};
//TODO: Turn this into a validator.
scheduleStore.isOverlapped(newRes)
scheduleStore.isReservationOverlapped(newRes)
? Dialog.create({ message: 'This booking overlaps another!' })
: scheduleStore.addOrCreateReservation(newRes);
});

View File

@@ -5,6 +5,7 @@ import { defineStore } from 'pinia';
export interface Boat {
id: number;
name: string;
displayName?: string;
class?: string;
year?: number;
imgsrc?: string;
@@ -27,6 +28,7 @@ const getSampleData = () => [
{
id: 1,
name: 'ProjectX',
displayName: 'PX',
class: 'J/27',
year: 1981,
imgsrc: '/tmpimg/j27.png',
@@ -52,6 +54,7 @@ and rough engine performance.`,
{
id: 2,
name: 'Take5',
displayName: 'T5',
class: 'J/27',
year: 1985,
imgsrc: '/tmpimg/j27.png',
@@ -60,6 +63,7 @@ and rough engine performance.`,
{
id: 3,
name: 'WeeBeestie',
displayName: 'WB',
class: 'Capri 25',
year: 1989,
imgsrc: '/tmpimg/capri25.png',

View File

@@ -3,24 +3,55 @@ import { ref } from 'vue';
import { Boat, useBoatStore } from './boat';
import { date } from 'quasar';
import { DateOptions } from 'quasar';
import {
Timestamp,
parseTimestamp,
TimestampArray,
} from '@quasar/quasar-ui-qcalendar';
import { timeStamp } from 'console';
export interface Reservation {
export type StatusTypes = 'tentative' | 'confirmed' | 'pending' | undefined;
export type Reservation = {
id: number;
user: string;
start: Date;
end: Date;
resource: Boat;
reservationDate: Date;
status?: string;
}
status?: StatusTypes;
};
function getSampleData(): Reservation[] {
export type Timeblock = {
start: Timestamp;
end: Timestamp;
};
const sampleBlocks = [
{
start: { time: '09:00', hour: 9, minute: 0, hasDay: false, hasTime: true },
end: { time: '12:00', hour: 12, minute: 0, hasDay: false, hasTime: true },
},
{
start: { time: '12:00', hour: 12, minute: 0, hasDay: false, hasTime: true },
end: { time: '15:00', hour: 15, minute: 0, hasDay: false, hasTime: true },
},
{
start: { time: '15:00', hour: 15, minute: 0, hasDay: false, hasTime: true },
end: { time: '18:00', hour: 18, minute: 0, hasDay: false, hasTime: true },
},
{
start: { time: '18:00', hour: 18, minute: 0, hasDay: false, hasTime: true },
end: { time: '21:00', hour: 21, minute: 0, hasDay: false, hasTime: true },
},
] as Timeblock[];
function getSampleReservations(): Reservation[] {
const sampleData = [
{
id: 1,
user: 'John Smith',
start: '12:00',
end: '14:00',
end: '15:00',
boat: 1,
status: 'confirmed',
},
@@ -28,31 +59,31 @@ function getSampleData(): Reservation[] {
id: 2,
user: 'Bob Barker',
start: '18:00',
end: '20:00',
end: '21:00',
boat: 1,
status: 'confirmed',
},
{
id: 3,
user: 'Peter Parker',
start: '8:00',
end: '10:00',
start: '9:00',
end: '12:00',
boat: 2,
status: 'tentative',
},
{
id: 4,
user: 'Vince McMahon',
start: '13:00',
end: '17:00',
start: '15:00',
end: '18:00',
boat: 2,
status: 'pending',
},
{
id: 5,
user: 'Heather Graham',
start: '06:00',
end: '09:00',
start: '09:00',
end: '12:00',
boat: 3,
status: 'confirmed',
},
@@ -60,7 +91,7 @@ function getSampleData(): Reservation[] {
id: 6,
user: 'Lawrence Fishburne',
start: '18:00',
end: '20:00',
end: '21:00',
boat: 3,
},
];
@@ -70,7 +101,12 @@ function getSampleData(): Reservation[] {
return x.split(':');
};
const makeOpts = (x: string[]): DateOptions => {
return { hour: parseInt(x[0]), minute: parseInt(x[1]) };
return {
hour: parseInt(x[0]),
minute: parseInt(x[1]),
seconds: 0,
milliseconds: 0,
};
};
return sampleData.map((entry): Reservation => {
@@ -82,13 +118,18 @@ function getSampleData(): Reservation[] {
end: date.adjustDate(now, makeOpts(splitTime(entry.end))),
resource: boat,
reservationDate: now,
status: entry.status,
status: entry.status as StatusTypes,
};
});
}
export const useScheduleStore = defineStore('schedule', () => {
const reservations = ref<Reservation[]>(getSampleData());
// TODO: Implement functions to dynamically pull this data.
const reservations = ref<Reservation[]>(getSampleReservations());
const timeblocks = sampleBlocks;
const getTimeblocksForDate = (date: Date): Timeblock[] => timeblocks;
const getBoatReservations = (
boat: number | string,
curDate: Date
@@ -105,15 +146,30 @@ export const useScheduleStore = defineStore('schedule', () => {
});
};
const isOverlapped = (res: Reservation) => {
const lapped = reservations.value.filter(
const getConflictingReservations = (
resource: Boat,
start: Date,
end: Date
): Reservation[] => {
const overlapped = reservations.value.filter(
(entry: Reservation) =>
entry.id != res.id &&
entry.resource == res.resource &&
((entry.start <= res.start && entry.end > res.start) ||
(entry.end >= res.end && entry.start <= res.end))
entry.resource.id == resource.id &&
entry.start < end &&
entry.end > start
);
return lapped.length > 0;
return overlapped;
};
const isResourceTimeOverlapped = (
resource: Boat,
start: Date,
end: Date
): boolean => {
return getConflictingReservations(resource, start, end).length > 0;
};
const isReservationOverlapped = (res: Reservation): boolean => {
return isResourceTimeOverlapped(res.resource, res.start, res.end);
};
const getNewId = () => {
@@ -133,8 +189,11 @@ export const useScheduleStore = defineStore('schedule', () => {
return {
reservations,
getBoatReservations,
getConflictingReservations,
getTimeblocksForDate,
getNewId,
addOrCreateReservation,
isOverlapped,
isReservationOverlapped,
isResourceTimeOverlapped,
};
});

87
src/stores/task.ts Normal file
View File

@@ -0,0 +1,87 @@
import { defineStore } from 'pinia';
export const useCounterStore = defineStore('counter', {
state: () => ({
counter: 0,
}),
getters: {
doubleCount(state) {
return state.counter * 2;
},
},
actions: {
increment() {
this.counter++;
},
},
});
export interface Task {
id: number;
title: string;
description: string;
iconsrc?: string;
due: Date;
created: Date;
}
const getSampleData = () => [
{
id: 1,
name: 'ProjectX',
displayName: 'PX',
class: 'J/27',
year: 1981,
imgsrc: '/tmpimg/j27.png',
iconsrc: '/tmpimg/projectx_avatar256.png',
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',
},
{
id: 3,
name: 'WeeBeestie',
displayName: 'WB',
class: 'Capri 25',
year: 1989,
imgsrc: '/tmpimg/capri25.png',
},
];
export const useBoatStore = defineStore('boat', {
state: () => ({
boats: getSampleData(),
}),
getters: {},
actions: {
// update () {
// }
},
});

1749
yarn.lock

File diff suppressed because it is too large Load Diff