Skip to content

Commit

Permalink
feat(ux): some UX improvements (#34)
Browse files Browse the repository at this point in the history
* feat(engine-hours): allow decimals in the engine hour amount

* feat(responsive): add ux flair when a logbook entry is being saved
  • Loading branch information
hutchic authored Aug 30, 2024
1 parent 9b0f444 commit 74e6468
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 53 deletions.
41 changes: 32 additions & 9 deletions app/components/BookedByUserCell.vue
Original file line number Diff line number Diff line change
@@ -1,39 +1,43 @@
<template>
<UCard>
<UForm :state="logbookEntry" class="logbook-form" @submit="saveLogbook">
<UForm :state="logbookEntry" :disabled="loading" class="logbook-form" @submit="saveLogbook">
<h3 class="text-lg font-bold mb-4">Log Entry for {{ formatDate(date) }}</h3>
<UFormGroup class="mb-4">
<div class="grid grid-cols-2 gap-4">
<div>
<label :for="`start-fuel-${date}`" class="block mb-2">Starting Fuel:</label>
<FuelSlider v-model="logbookEntry.startFuel" />
<FuelSlider v-model="logbookEntry.startFuel" :disabled="loading" />
</div>
<div>
<label :for="`end-fuel-${date}`" class="block mb-2">Ending Fuel:</label>
<FuelSlider v-model="logbookEntry.endFuel" />
<FuelSlider v-model="logbookEntry.endFuel" :disabled="loading" />
</div>
</div>
</UFormGroup>
<UFormGroup class="mb-4">
<div class="grid grid-cols-2 gap-4">
<div>
<label :for="`start-engine-hours-${date}`" class="block mb-2">Starting Engine Hours:</label>
<UInput type="number" :id="`start-engine-hours-${date}`" v-model="logbookEntry.startEngineHours" :min="0" />
<UInput type="number" :id="`start-engine-hours-${date}`" v-model.number="logbookEntry.startEngineHours" :min="0" step="0.1" :disabled="loading" />
</div>
<div>
<label :for="`end-engine-hours-${date}`" class="block mb-2">Ending Engine Hours:</label>
<UInput type="number" :id="`end-engine-hours-${date}`" v-model="logbookEntry.endEngineHours" :min="0" />
<UInput type="number" :id="`end-engine-hours-${date}`" v-model.number="logbookEntry.endEngineHours" :min="0" step="0.1" :disabled="loading" />
</div>
</div>
</UFormGroup>
<UFormGroup class="mb-4">
<URadioGroup v-model="logbookEntry.addFuel" :options="fuelOptions" legend="Did you add fuel?" />
<URadioGroup v-model="logbookEntry.addFuel" :options="fuelOptions" legend="Did you add fuel?" :disabled="loading" />
</UFormGroup>
<UFormGroup v-if="logbookEntry.addFuel === 'yes'" class="mb-4">
<label :for="`fuel-amount-${date}`" class="block mb-2">Total Money Spent on Fuel:</label>
<UInput type="number" :id="`fuel-amount-${date}`" v-model.number="logbookEntry.fuelAmount" :min="0" step="0.01" placeholder="Enter amount in dollars" :disabled="loading" />
</UFormGroup>
<UFormGroup class="mb-4">
<label :for="`comments-${date}`" class="block mb-2">Comments:</label>
<UTextarea :id="`comments-${date}`" v-model="logbookEntry.comments" />
<UTextarea :id="`comments-${date}`" v-model="logbookEntry.comments" :disabled="loading" />
</UFormGroup>
<UButton type="submit" label="Save Logbook" icon="i-heroicons-save" color="primary" variant="solid" size="lg" block />
<UButton type="submit" :label="buttonLabel" :disabled="loading" icon="i-heroicons-save" color="primary" variant="solid" size="lg" block />
</UForm>
</UCard>
</template>
Expand All @@ -50,11 +54,14 @@ interface LogBookEntry {
startEngineHours: number;
endEngineHours: number;
addFuel: string;
fuelAmount?: number; // Add fuelAmount property
comments: string;
}
const props = defineProps<{ date: string, event: any, lastLogEntry: LogBookEntry | null }>();
const emit = defineEmits(['logbookSaved']);
const loading = ref(false);
const buttonLabel = ref('Save Logbook');
const logbookEntry = ref<LogBookEntry>({
date: props.date,
Expand All @@ -63,6 +70,7 @@ const logbookEntry = ref<LogBookEntry>({
startEngineHours: props.lastLogEntry ? props.lastLogEntry.endEngineHours : 0,
endEngineHours: 0,
addFuel: '',
fuelAmount: undefined, // Initialize fuelAmount
comments: '',
});
Expand All @@ -76,7 +84,7 @@ const formatDate = (dateString: string) => {
return format(date, 'PPP');
};
const isJSON = (str) => {
const isJSON = (str: string) => {
try {
JSON.parse(str);
return true;
Expand All @@ -92,6 +100,7 @@ const loadLogbookEntry = () => {
logbookEntry.value.endFuel = 0;
logbookEntry.value.endEngineHours = 0;
logbookEntry.value.addFuel = '';
logbookEntry.value.fuelAmount = undefined; // Initialize fuelAmount
logbookEntry.value.comments = '';
// Attempt to parse and override with event description
Expand All @@ -114,6 +123,9 @@ const loadLogbookEntry = () => {
if (typeof logData.addFuel === 'string') {
logbookEntry.value.addFuel = logData.addFuel;
}
if (logData.fuelAmount !== undefined) {
logbookEntry.value.fuelAmount = logData.fuelAmount; // Set fuelAmount value
}
if (typeof logData.comments === 'string') {
logbookEntry.value.comments = logData.comments;
}
Expand All @@ -124,12 +136,16 @@ const loadLogbookEntry = () => {
};
const saveLogbook = async () => {
loading.value = true;
buttonLabel.value = 'Saving...';
const logData = {
startFuel: logbookEntry.value.startFuel,
endFuel: logbookEntry.value.endFuel,
startEngineHours: logbookEntry.value.startEngineHours,
endEngineHours: logbookEntry.value.endEngineHours,
addFuel: logbookEntry.value.addFuel,
fuelAmount: logbookEntry.value.fuelAmount, // Include fuelAmount in saved data
comments: logbookEntry.value.comments,
};
Expand All @@ -156,10 +172,17 @@ const saveLogbook = async () => {
throw new Error('Failed to update calendar event');
}
buttonLabel.value = 'Logbook Saved';
emit('logbookSaved', props.date);
console.log('Logbook entry saved:', logbookEntry.value);
} catch (error) {
buttonLabel.value = 'Error Saving Logbook';
console.error('Error saving logbook entry', error);
} finally {
setTimeout(() => {
buttonLabel.value = 'Save Logbook';
loading.value = false;
}, 2000); // Add a slight delay before enabling the form again
}
};
Expand Down
66 changes: 22 additions & 44 deletions app/pages/secure.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@
</template>

<script setup lang="ts">
import { ref, onMounted, shallowRef, markRaw } from 'vue';
import { useRuntimeConfig } from '#app';
import { useRouter } from 'vue-router';
import { isFuture, addMonths, startOfMonth, endOfMonth, format } from 'date-fns';
import BookedByUserCell from '~/components/BookedByUserCell.vue';
import BookedByOthersCell from '~/components/BookedByOthersCell.vue';
Expand Down Expand Up @@ -133,51 +130,32 @@ const fetchUserProfile = async () => {
};
const generateCalendarDays = () => {
const today = new Date();
const daysInMonth = new Date(today.getFullYear(), today.getMonth() + 1, 0).getDate();
calendarDays.value = Array.from({ length: daysInMonth }, (_, i) => {
const date = new Date(today.getFullYear(), today.getMonth(), i + 1).toISOString().split('T')[0];
return { date, isBooked: false, isUserBooking: false, tooltipText: '' };
});
const startOfPrevMonth = startOfMonth(addMonths(new Date(), -1));
const endOfNextMonth = endOfMonth(addMonths(new Date(), 1));
calendarDays.value = [];
for (let d = new Date(startOfPrevMonth); d <= endOfNextMonth; d.setDate(d.getDate() + 1)) {
const date = new Date(d).toISOString().split('T')[0];
calendarDays.value.push({ date, isBooked: false, isUserBooking: false, tooltipText: '' });
}
events.value.forEach(event => {
events.value.forEach((event: { start: { date: string | number | Date; }; end: { date: string | number | Date; }; creator: { email: any; }; }) => {
const startDate = new Date(event.start.date);
const endDate = new Date(event.end.date);
// Adjust for single-day events that end on the same day they start
if (startDate.getTime() === endDate.getTime()) {
endDate.setDate(endDate.getDate() + 1);
}
// Ensure the event spans the correct date range, adding one day
for (let d = new Date(startDate); d < endDate; d.setDate(d.getDate() + 1)) {
const adjustedDate = new Date(d);
adjustedDate.setDate(adjustedDate.getDate() + 1); // Adding one day
const dayIndex = adjustedDate.getDate() - 1;
if (calendarDays.value[dayIndex]) {
calendarDays.value[dayIndex].isBooked = true;
calendarDays.value[dayIndex].isUserBooking = event.creator.email === userEmail.value;
calendarDays.value[dayIndex].email = event.creator.email;
calendarDays.value[dayIndex].tooltipText = `Booked by: ${event.creator.email}`;
calendarDays.value[dayIndex].event = event; // Store the event object
// Update the last log entry with the current event's end fuel and engine hours
if (isJSON(event.description)) {
try {
const logData = JSON.parse(event.description);
lastLogEntry.value = {
date: event.start.date,
startFuel: logData.endFuel || 0,
endFuel: logData.endFuel || 0,
startEngineHours: logData.endEngineHours || 0,
endEngineHours: logData.endEngineHours || 0,
addFuel: '',
comments: ''
};
} catch (error) {
console.error('Error parsing last logbook entry:', error);
}
}
const adjustedDate = new Date(d).toISOString().split('T')[0];
const day = calendarDays.value.find((day: { date: string; }) => day.date === adjustedDate);
if (day) {
day.isBooked = true;
day.isUserBooking = event.creator.email === userEmail.value;
day.email = event.creator.email;
day.tooltipText = `Booked by: ${event.creator.email}`;
day.event = event;
}
}
});
Expand All @@ -188,7 +166,7 @@ const generateCalendarDays = () => {
const accordionItems = shallowRef([]);
const createAccordionItems = () => {
accordionItems.value = calendarDays.value.map(day => {
accordionItems.value = calendarDays.value.map((day: { date: string; isBooked: any; isUserBooking: any; email: any; event: any; }) => {
const dayDate = new Date(day.date + 'T00:00:00');
const isFutureDate = isFuture(dayDate);
Expand Down Expand Up @@ -247,7 +225,7 @@ const formatDate = (dateString: string) => {
};
const handleDayBooked = (bookedDate: string) => {
const day = calendarDays.value.find(day => day.date === bookedDate);
const day = calendarDays.value.find((day: { date: string; }) => day.date === bookedDate);
if (day) {
day.isBooked = true;
day.isUserBooking = true;
Expand All @@ -257,7 +235,7 @@ const handleDayBooked = (bookedDate: string) => {
};
const handleBookingDeleted = (deletedDate: string) => {
const day = calendarDays.value.find(day => day.date === deletedDate);
const day = calendarDays.value.find((day: { date: string; }) => day.date === deletedDate);
if (day) {
day.isBooked = false;
day.isUserBooking = false;
Expand All @@ -267,7 +245,7 @@ const handleBookingDeleted = (deletedDate: string) => {
}
};
const isJSON = (str) => {
const isJSON = (str: string) => {
try {
JSON.parse(str);
return true;
Expand Down

0 comments on commit 74e6468

Please sign in to comment.