diff --git a/src/queries/UserQueries.jsx b/src/queries/UserQueries.jsx
index d414ec3..c9a97d8 100644
--- a/src/queries/UserQueries.jsx
+++ b/src/queries/UserQueries.jsx
@@ -46,6 +46,10 @@ export const useUserProfile = () => {
const { data, error, isLoading } = useQuery({
queryKey: ['userProfile'],
queryFn: async () => {
+ // the below code deleted because it cause issue when token expire and screen is off
+ // and then user comes back to the app after long time. the user profile fetch would fail
+ // and there is no retry for some reason. remove this seem to fix the issue.
+
if (!isTokenValid()) {
throw new Error('Invalid or expired token, cannot fetch user profile')
}
diff --git a/src/utils/Chores.jsx b/src/utils/Chores.jsx
index 8beb774..74e5226 100644
--- a/src/utils/Chores.jsx
+++ b/src/utils/Chores.jsx
@@ -345,3 +345,25 @@ export const ChoreFilters = userId => ({
return chore.createdBy && chore.createdBy === userId
},
})
+
+// Project filter function - separate from ChoreFilters since it's independent
+export const filterByProject = (chores, selectedProject) => {
+ if (
+ !selectedProject ||
+ selectedProject === 'Default Project' ||
+ selectedProject === 'default'
+ ) {
+ // Default project should show tasks without a project (projectId is null/undefined/empty)
+ // Based on ChoreEdit.jsx, default projects save projectId as null
+ return chores.filter(
+ chore =>
+ !chore.projectId || chore.projectId === null || chore.projectId === '',
+ )
+ }
+
+ // For custom projects, match by project ID
+ return chores.filter(chore => {
+ // Match by project ID (this should be the primary way chores are linked to projects)
+ return chore.projectId === selectedProject
+ })
+}
diff --git a/src/utils/Fetcher.jsx b/src/utils/Fetcher.jsx
index ca1ffe9..c6456a2 100644
--- a/src/utils/Fetcher.jsx
+++ b/src/utils/Fetcher.jsx
@@ -186,6 +186,14 @@ const RejectChore = id => {
})
}
+const UndoChoreAction = id => {
+ return Fetch(`/chores/${id}/undo`, {
+ method: 'POST',
+ headers: HEADERS(),
+ body: JSON.stringify({}),
+ })
+}
+
const NudgeChore = (id, { message, notifyAllAssignees }) => {
return Fetch(`/chores/${id}/nudge`, {
method: 'POST',
@@ -565,12 +573,15 @@ const RefreshToken = async () => {
const basedURL = apiManager.getApiURL()
// Check if running on native platform
- const isNative = typeof window !== 'undefined' && window.Capacitor?.isNativePlatform?.()
+ const isNative =
+ typeof window !== 'undefined' && window.Capacitor?.isNativePlatform?.()
if (isNative) {
// For native platforms, send refresh token in request body
const { Preferences } = await import('@capacitor/preferences')
- const { value: refreshToken } = await Preferences.get({ key: 'refresh_token' })
+ const { value: refreshToken } = await Preferences.get({
+ key: 'refresh_token',
+ })
if (!refreshToken) {
throw new Error('No refresh token available')
@@ -782,6 +793,44 @@ const DeleteChildUser = childUserId => {
})
}
+// Project-related API functions
+const GetProjects = () => {
+ return Fetch(`/projects`, {
+ method: 'GET',
+ headers: HEADERS(),
+ })
+}
+
+const GetProjectById = id => {
+ return Fetch(`/projects/${id}`, {
+ method: 'GET',
+ headers: HEADERS(),
+ })
+}
+
+const CreateProject = project => {
+ return Fetch(`/projects`, {
+ method: 'POST',
+ headers: HEADERS(),
+ body: JSON.stringify(project),
+ })
+}
+
+const UpdateProject = (id, project) => {
+ return Fetch(`/projects/${id}`, {
+ method: 'PUT',
+ headers: HEADERS(),
+ body: JSON.stringify(project),
+ })
+}
+
+const DeleteProject = id => {
+ return Fetch(`/projects/${id}`, {
+ method: 'DELETE',
+ headers: HEADERS(),
+ })
+}
+
export {
AcceptCircleMemberRequest,
ApproveChore,
@@ -798,6 +847,7 @@ export {
createChore,
CreateLabel,
CreateLongLiveToken,
+ CreateProject,
CreateThing,
DeleteChildUser,
DeleteChore,
@@ -805,6 +855,7 @@ export {
DeleteCircleMember,
DeleteLabel,
DeleteLongLiveToken,
+ DeleteProject,
DeleteThing,
DeleteTimeSession,
DeleteUser,
@@ -825,6 +876,8 @@ export {
GetLabels,
GetLongLiveTokens,
GetMFAStatus,
+ GetProjectById,
+ GetProjects,
GetResource,
GetStorageUsage,
GetSubscriptionSession,
@@ -855,6 +908,7 @@ export {
SkipChore,
StartChore,
UnArchiveChore,
+ UndoChoreAction,
UnregisterDeviceToken,
UpdateChildPassword,
UpdateChoreAssignee,
@@ -865,6 +919,7 @@ export {
UpdateMemberRole,
UpdateNotificationTarget,
UpdatePassword,
+ UpdateProject,
UpdateThingState,
UpdateTimeSession,
UpdateUserDetails,
diff --git a/src/views/components/ChoreActionMenu.jsx b/src/views/components/ChoreActionMenu.jsx
index fdd288f..57c58e8 100644
--- a/src/views/components/ChoreActionMenu.jsx
+++ b/src/views/components/ChoreActionMenu.jsx
@@ -9,8 +9,8 @@ import {
MoreVert,
NextWeek,
Nfc,
- Notifications,
NoteAdd,
+ Notifications,
RecordVoiceOver,
SwitchAccessShortcut,
Today,
diff --git a/src/views/components/NavBar.jsx b/src/views/components/NavBar.jsx
index 076c077..8a4fc41 100644
--- a/src/views/components/NavBar.jsx
+++ b/src/views/components/NavBar.jsx
@@ -2,6 +2,7 @@ import { Capacitor } from '@capacitor/core'
import {
Archive,
ArrowBack,
+ FolderOpen,
History,
Inbox,
ListAlt,
@@ -54,6 +55,11 @@ const links = [
label: 'Labels',
icon: ,
},
+ {
+ to: 'projects',
+ label: 'Projects',
+ icon: ,
+ },
{
to: 'activities',
label: 'Activities',
@@ -87,8 +93,8 @@ const links = [
]
import { SafeArea } from 'capacitor-plugin-safe-area'
-import { useAuth } from '../../hooks/useAuth.jsx'
import Z_INDEX from '../../constants/zIndex'
+import { useAuth } from '../../hooks/useAuth.jsx'
import { useResource } from '../../queries/ResourceQueries'
const publicPages = ['/landing', '/privacy', '/terms']