refactor: Simplify ChoresPage structure and enhance form functionality
- Removed redundant form elements and improved the layout for better readability. - Streamlined the chore creation and editing process with enhanced validation and auto-save features. - Updated keyboard shortcuts for improved accessibility and user experience. - Enhanced modal interactions and improved loading states during data fetching. - Cleaned up unused code and optimized the overall component structure.
This commit is contained in:
parent
a7fbc454a9
commit
679169e4fb
@ -300,7 +300,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted, computed, onUnmounted, watch, onBeforeUnmount } from 'vue'
|
import { ref, onMounted, computed, onUnmounted, watch, onBeforeUnmount } from 'vue'
|
||||||
import { format, startOfDay, addDays, addWeeks, isBefore, isEqual, startOfMonth, endOfMonth, eachDayOfInterval, isSameMonth, isToday as isTodayDate } from 'date-fns'
|
import { format, startOfDay, addDays, addWeeks, isBefore, isEqual, startOfMonth, endOfMonth, eachDayOfInterval, isSameMonth, isToday as isTodayDate } from 'date-fns'
|
||||||
import { choreService } from '../services/choreService' // Assuming choreService exists
|
import { choreService } from '../services/choreService'
|
||||||
import { useNotificationStore } from '../stores/notifications'
|
import { useNotificationStore } from '../stores/notifications'
|
||||||
import type { Chore as OriginalChore, ChoreCreate as OriginalChoreCreate, ChoreUpdate, ChoreFrequency } from '../types/chore' // Assuming these types exist
|
import type { Chore as OriginalChore, ChoreCreate as OriginalChoreCreate, ChoreUpdate, ChoreFrequency } from '../types/chore' // Assuming these types exist
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
@ -317,6 +317,10 @@ interface ChoreCreate extends OriginalChoreCreate {
|
|||||||
completed_at: string | null;
|
completed_at: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ChoreUpdate extends OriginalChoreUpdate {
|
||||||
|
is_completed?: boolean;
|
||||||
|
completed_at?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
const notificationStore = useNotificationStore()
|
const notificationStore = useNotificationStore()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
@ -329,19 +333,24 @@ const showDeleteDialog = ref(false)
|
|||||||
const isEditing = ref(false)
|
const isEditing = ref(false)
|
||||||
const selectedChore = ref<Chore | null>(null)
|
const selectedChore = ref<Chore | null>(null)
|
||||||
const showShortcutsModal = ref(false)
|
const showShortcutsModal = ref(false)
|
||||||
|
const activeView = ref('today')
|
||||||
|
const viewMode = ref<'calendar' | 'list'>('calendar')
|
||||||
|
const currentDate = ref(new Date())
|
||||||
|
const isLoading = ref(true)
|
||||||
|
|
||||||
const cachedChores = useStorage<Chore[]>('cached-chores-v2', []) // Changed key to avoid conflicts with old cache
|
const cachedChores = useStorage<Chore[]>('cached-chores-v2', [])
|
||||||
const cachedTimestamp = useStorage<number>('cached-chores-timestamp-v2', 0)
|
const cachedTimestamp = useStorage<number>('cached-chores-timestamp-v2', 0)
|
||||||
const CACHE_DURATION = 5 * 60 * 1000;
|
const CACHE_DURATION = 5 * 60 * 1000;
|
||||||
|
|
||||||
const loadCachedData = () => {
|
const loadCachedData = () => {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
if (cachedChores.value.length > 0 && (now - cachedTimestamp.value) < CACHE_DURATION) {
|
if (cachedChores.value.length > 0 && (now - cachedTimestamp.value) < CACHE_DURATION) {
|
||||||
chores.value = cachedChores.value.map(c => ({ // Ensure cached items have new properties
|
chores.value = cachedChores.value.map(c => ({
|
||||||
...c,
|
...c,
|
||||||
is_completed: c.is_completed || false,
|
is_completed: c.is_completed || false,
|
||||||
completed_at: c.completed_at || null
|
completed_at: c.completed_at || null
|
||||||
}));
|
}));
|
||||||
|
isLoading.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -370,33 +379,25 @@ const frequencyOptions = [
|
|||||||
{ label: 'Custom', value: 'custom' as ChoreFrequency }
|
{ label: 'Custom', value: 'custom' as ChoreFrequency }
|
||||||
]
|
]
|
||||||
|
|
||||||
// Add loading state
|
|
||||||
const isLoading = ref(true)
|
|
||||||
|
|
||||||
const loadChores = async () => {
|
const loadChores = async () => {
|
||||||
isLoading.value = true
|
|
||||||
try {
|
try {
|
||||||
const fetchedChores = await choreService.getAllChores() as OriginalChore[]
|
const fetchedChores = await choreService.getAllChores();
|
||||||
chores.value = fetchedChores.map(c => ({
|
chores.value = fetchedChores.map(chore => ({
|
||||||
...c,
|
...chore,
|
||||||
is_completed: (c as Chore).is_completed || false,
|
is_completed: (chore as Chore).is_completed || false,
|
||||||
completed_at: (c as Chore).completed_at || null,
|
completed_at: (chore as Chore).completed_at || null
|
||||||
}))
|
} as Chore));
|
||||||
cachedChores.value = chores.value
|
cachedChores.value = [...chores.value];
|
||||||
cachedTimestamp.value = Date.now()
|
cachedTimestamp.value = Date.now();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to load all chores:', error)
|
console.error('Failed to load chores:', error);
|
||||||
notificationStore.addNotification({ message: 'Failed to load chores', type: 'error' })
|
notificationStore.addNotification({ message: 'Failed to load chores', type: 'error' });
|
||||||
if (cachedChores.value.length === 0) chores.value = []
|
|
||||||
} finally {
|
} finally {
|
||||||
isLoading.value = false
|
isLoading.value = false;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Calendar state
|
// Calendar state
|
||||||
const viewMode = ref<'calendar' | 'list'>('calendar')
|
|
||||||
const currentDate = ref(new Date())
|
|
||||||
|
|
||||||
const weekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
|
const weekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
|
||||||
|
|
||||||
const currentMonthYear = computed(() => {
|
const currentMonthYear = computed(() => {
|
||||||
@ -443,7 +444,7 @@ const nextMonth = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const openCreateChoreModal = (groupId: number | null, date?: Date) => {
|
const openCreateChoreModal = (groupId: number | null, date?: Date) => {
|
||||||
console.log('Opening create modal', { groupId, date }) // Debug log
|
console.log('Opening create modal', { groupId, date })
|
||||||
isEditing.value = false
|
isEditing.value = false
|
||||||
choreForm.value = {
|
choreForm.value = {
|
||||||
name: '',
|
name: '',
|
||||||
@ -460,7 +461,7 @@ const openCreateChoreModal = (groupId: number | null, date?: Date) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const openEditChoreModal = (chore: Chore) => {
|
const openEditChoreModal = (chore: Chore) => {
|
||||||
console.log('Opening edit modal', chore) // Debug log
|
console.log('Opening edit modal', chore)
|
||||||
isEditing.value = true
|
isEditing.value = true
|
||||||
selectedChore.value = chore
|
selectedChore.value = chore
|
||||||
choreForm.value = {
|
choreForm.value = {
|
||||||
@ -478,33 +479,40 @@ const openEditChoreModal = (chore: Chore) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const onSubmit = async () => {
|
const onSubmit = async () => {
|
||||||
if (!validateForm()) return
|
if (!validateForm()) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const choreData: ChoreCreate | ChoreUpdate = { ...choreForm.value }
|
|
||||||
|
|
||||||
if (choreData.frequency !== 'custom') {
|
|
||||||
choreData.custom_interval_days = undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
let notificationMessage = ''
|
|
||||||
|
|
||||||
if (isEditing.value && selectedChore.value) {
|
if (isEditing.value && selectedChore.value) {
|
||||||
await choreService.updateChore(selectedChore.value.id, choreData as ChoreUpdate)
|
// Update existing chore
|
||||||
notificationMessage = `Chore updated successfully`
|
const updateData: ChoreUpdate = {
|
||||||
|
...choreForm.value,
|
||||||
|
is_completed: selectedChore.value.is_completed,
|
||||||
|
completed_at: selectedChore.value.completed_at
|
||||||
|
};
|
||||||
|
const updatedChore = await choreService.updateChore(selectedChore.value.id, updateData);
|
||||||
|
const index = chores.value.findIndex(c => c.id === selectedChore.value?.id);
|
||||||
|
if (index !== -1) {
|
||||||
|
chores.value[index] = { ...updatedChore, is_completed: selectedChore.value.is_completed, completed_at: selectedChore.value.completed_at } as Chore;
|
||||||
|
}
|
||||||
|
notificationStore.addNotification({ message: 'Chore updated successfully', type: 'success' });
|
||||||
} else {
|
} else {
|
||||||
await choreService.createChore(choreData as ChoreCreate)
|
// Create new chore
|
||||||
notificationMessage = `Chore created successfully`
|
const createData: ChoreCreate = {
|
||||||
|
...choreForm.value,
|
||||||
|
is_completed: false,
|
||||||
|
completed_at: null
|
||||||
|
};
|
||||||
|
const newChore = await choreService.createChore(createData);
|
||||||
|
chores.value.push(newChore as Chore);
|
||||||
|
notificationStore.addNotification({ message: 'Chore created successfully', type: 'success' });
|
||||||
}
|
}
|
||||||
|
showChoreModal.value = false;
|
||||||
notificationStore.addNotification({ message: notificationMessage, type: 'success' })
|
hasUnsavedChanges.value = false;
|
||||||
showChoreModal.value = false
|
|
||||||
loadChores()
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to save chore:', error)
|
console.error('Failed to save chore:', error);
|
||||||
notificationStore.addNotification({ message: `Failed to ${isEditing.value ? 'update' : 'create'} chore`, type: 'error' })
|
notificationStore.addNotification({ message: 'Failed to save chore', type: 'error' });
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const confirmDeleteChore = (chore: Chore) => {
|
const confirmDeleteChore = (chore: Chore) => {
|
||||||
selectedChore.value = chore
|
selectedChore.value = chore
|
||||||
|
Loading…
Reference in New Issue
Block a user