From 7b3e22385cd73a4473d1f7346a1723e2a79e0e69 Mon Sep 17 00:00:00 2001 From: narayansharma-21 <97.sharman@gmail.com> Date: Sat, 24 Feb 2024 13:32:36 -0500 Subject: [PATCH 01/43] feat(SingleTask.tsx): Hardcoded screen Need to create API functionality for dynamic --- client/components/BackButton.tsx | 23 +++++++++++++ .../navigation/AppStackBottomTabNavigator.tsx | 10 ++++++ client/screens/SingleTask.tsx | 33 +++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 client/components/BackButton.tsx create mode 100644 client/screens/SingleTask.tsx diff --git a/client/components/BackButton.tsx b/client/components/BackButton.tsx new file mode 100644 index 0000000..a72374b --- /dev/null +++ b/client/components/BackButton.tsx @@ -0,0 +1,23 @@ +import React from 'react'; + +import { useNavigation } from '@react-navigation/native'; +import { Button } from 'react-native-paper'; + +import { AppStackNavigation } from '../navigation/AppNavigation'; + +// TODO style +export function BackButton() { + const navigation = useNavigation(); + + return ( + + ); +} diff --git a/client/navigation/AppStackBottomTabNavigator.tsx b/client/navigation/AppStackBottomTabNavigator.tsx index ae71d1a..7a88f93 100644 --- a/client/navigation/AppStackBottomTabNavigator.tsx +++ b/client/navigation/AppStackBottomTabNavigator.tsx @@ -6,6 +6,7 @@ import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; import Home from '../assets/home.svg'; import GroupScreen from '../screens/Groups'; import MedicationList from '../screens/MedicationList'; +import SingleTaskScreen from '../screens/SingleTask'; const AppStackBottomTab = createBottomTabNavigator(); @@ -30,6 +31,15 @@ export function AppStackBottomTabNavigator() { }} component={GroupScreen} /> + , + tabBarLabel: () => Task + }} + component={SingleTaskScreen} + /> ); } diff --git a/client/screens/SingleTask.tsx b/client/screens/SingleTask.tsx new file mode 100644 index 0000000..ddbe564 --- /dev/null +++ b/client/screens/SingleTask.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import { Text, View } from 'react-native'; + +import { BackButton } from '../components/BackButton'; + +export default function SingleTaskScreen() { + return ( + + + + + + Label Here + + + Category Here | Type of Task Here + + + + Doctor’s Appointment {'\n'} @ 8:00AM + + + + + Description here. Description here. Description here. Description + here. Description here. Description here. Description here. + Description here. Description here. Description here. Description + here. + + + + ); +} From b0c3391bcf4469a1315f293a5550adee8c24475e Mon Sep 17 00:00:00 2001 From: narayansharma-21 <97.sharman@gmail.com> Date: Mon, 26 Feb 2024 14:17:37 -0500 Subject: [PATCH 02/43] feat(SingleTask.tsx): Added route functionality Need to add v4 of the screen and need to handle button functionality --- client/assets/checkmark.svg | 5 ++ client/assets/reject.svg | 5 ++ client/screens/SingleTask.tsx | 87 +++++++++++++++++++++++++++++++---- client/services/task.ts | 47 +++++++++++++++++++ client/types/type.ts | 52 +++++++++++++++++++++ 5 files changed, 188 insertions(+), 8 deletions(-) create mode 100644 client/assets/checkmark.svg create mode 100644 client/assets/reject.svg create mode 100644 client/services/task.ts create mode 100644 client/types/type.ts diff --git a/client/assets/checkmark.svg b/client/assets/checkmark.svg new file mode 100644 index 0000000..f91e71b --- /dev/null +++ b/client/assets/checkmark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/client/assets/reject.svg b/client/assets/reject.svg new file mode 100644 index 0000000..b9cd666 --- /dev/null +++ b/client/assets/reject.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/client/screens/SingleTask.tsx b/client/screens/SingleTask.tsx index ddbe564..d42a939 100644 --- a/client/screens/SingleTask.tsx +++ b/client/screens/SingleTask.tsx @@ -1,33 +1,104 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { Text, View } from 'react-native'; +import CheckMark from '../assets/checkmark.svg'; +import Reject from '../assets/reject.svg'; import { BackButton } from '../components/BackButton'; +import { getTaskId, getTaskLabel } from '../services/task'; +import { Category } from '../types/type'; export default function SingleTaskScreen() { + const [taskId] = useState(); + + // Would extract real information in future and not display default, placeholder info + const [taskInfo, setTaskInfo] = useState({ + created_date: '8:00AM', + task_id: '', + task_info: '{}', + task_type: 'Task Type Here', + notes: + 'Description here. Description here. Description here. Description here. Description here. Description here. Description here. Description here. Description here. Description here. Description here.' + }); + + const [taskLabel, setTaskLabel] = useState('Label Here'); + + useEffect(() => { + if (taskId) { + getTaskId(taskId) + .then((data) => { + const { created_date, task_id, task_info, task_type, notes } = data; + setTaskInfo({ created_date, task_id, task_info, task_type, notes }); + }) + .catch((error) => console.error('Error fetching task info:', error)); + } + }, [taskId]); + + useEffect(() => { + if (taskId) { + getTaskLabel(taskId) + .then((data) => setTaskLabel(data)) + .catch((error) => console.error('Error fetching task label:', error)); + } + }, [taskId]); + + const getCategoryFromTaskInfo = (taskInfo: string): Category => { + try { + // Parse the JSON string to object + const taskInfoObject = JSON.parse(taskInfo); + // Extract the category from the task info object + const category = taskInfoObject.category; + // Return the appropriate category enum value + return Category[category as keyof typeof Category] || Category.ALL; + } catch (error) { + console.error( + 'Error parsing task info to extract category mapping:', + error + ); + return Category.ALL; // Return a default category in case of error + } + }; + + const getTitleFromTaskInfo = (taskInfo: string): string => { + try { + // Parse the JSON string to object + const taskInfoObject = JSON.parse(taskInfo); + const title = taskInfoObject.title; + return title; + } catch (error) { + console.error('Error parsing task info to extract title:', error); + return ''; + } + }; + return ( - Label Here + {taskLabel} - Category Here | Type of Task Here + + {getCategoryFromTaskInfo(taskInfo.task_info) || 'Category Task'} |{' '} + {taskInfo.task_type} + - Doctor’s Appointment {'\n'} @ 8:00AM + {getTitleFromTaskInfo(taskInfo.task_info) || 'Doctor’s Appointment'}{' '} + {'\n'} @ {taskInfo.created_date} - Description here. Description here. Description here. Description - here. Description here. Description here. Description here. - Description here. Description here. Description here. Description - here. + {taskInfo.notes} + + + + ); } diff --git a/client/services/task.ts b/client/services/task.ts new file mode 100644 index 0000000..36def50 --- /dev/null +++ b/client/services/task.ts @@ -0,0 +1,47 @@ +import axios from 'axios'; + +import { api_url } from './api-links'; + +// Retrieve task label (just call the route) +export const getTaskLabel = async (tid: string): Promise => { + try { + const response = await axios.post(`${api_url}/tasks/${tid}/labels`, {}); + console.log('response:', response); + return response.data; + } catch (error) { + console.error('Error retrieving the task label', error); + throw error; + } +}; + +// Retrieve task id and retrieve the json to retrieve notes, task_type, created_date, and map to category type/task type +export const getTaskId = async ( + tid: string +): Promise<{ + created_date: string; + task_id: string; + task_info: string; + task_type: string; + notes: string; +}> => { + try { + const response = await axios.post(`${api_url}/tasks/${tid}`, {}); + console.log('response:', response); + return response.data; + } catch (error) { + console.error('Error fetching task id', error); + throw error; + } +}; + +// Assigning users to a task +export const addTaskToUser = async (taskId: string): Promise => { + try { + const response = await axios.post(`${api_url}/tasks/${taskId}/assign`, {}); + console.log('response:', response); + return response.data; + } catch (error) { + console.error('Error assigning task:', error); + throw error; + } +}; diff --git a/client/types/type.ts b/client/types/type.ts new file mode 100644 index 0000000..6e97756 --- /dev/null +++ b/client/types/type.ts @@ -0,0 +1,52 @@ +export enum TypeOfTask { + MEDICATION_MANAGEMENT = 'Medication Management', + PHYSICIAN_APPT = 'Physician Appointment', + PRESCRIPTION_MGMT = 'Prescription Management', + LABS_OUTPATIENT_SERVICES = 'Labs & Outpatient Services', + REHAB_HOME_THERAPIES = 'Rehab/Home Therapies', + TRANSITIONAL_CARE_COORD = 'Transitional Care Coordination', + FAMILY_CONVERSATIONS = 'Family Conversations', + TRANSPORTATION = 'Transportation', + RESPITE_CAREGIVER_SUPPORT = 'Respite and Caregiver Support', + HOME_SAFETY = 'Home Safety', + HEALTH_INSURANCE = 'Health Insurance', + MANAGING_EXPENSES_BILL_PAYMENTS = 'Managing Expenses & Bill Payments', + LEGAL = 'Legal', + FINANCIAL = 'Financial', + OTHER = 'Other' +} + +export enum Category { + ALL = '', + HEALTH = 'Health & Medication', + PERSONAL = 'Personal', + HOME = 'Home & Lifestyle', + FINANCIAL = 'Financial & Legal' +} + +export const categoryToTypeMap: Record = { + [Category.ALL]: [], + [Category.HEALTH]: [ + TypeOfTask.MEDICATION_MANAGEMENT, + TypeOfTask.PHYSICIAN_APPT, + TypeOfTask.PRESCRIPTION_MGMT, + TypeOfTask.LABS_OUTPATIENT_SERVICES, + TypeOfTask.REHAB_HOME_THERAPIES, + TypeOfTask.TRANSITIONAL_CARE_COORD, + TypeOfTask.HEALTH_INSURANCE + ], + [Category.PERSONAL]: [ + TypeOfTask.FAMILY_CONVERSATIONS, + TypeOfTask.RESPITE_CAREGIVER_SUPPORT + ], + [Category.HOME]: [ + TypeOfTask.TRANSPORTATION, + TypeOfTask.REHAB_HOME_THERAPIES, + TypeOfTask.TRANSITIONAL_CARE_COORD, + TypeOfTask.HOME_SAFETY + ], + [Category.FINANCIAL]: [ + TypeOfTask.FINANCIAL, + TypeOfTask.MANAGING_EXPENSES_BILL_PAYMENTS + ] +}; From b6dc1adc8ebf370bd9647295483ee9ed7255a2a1 Mon Sep 17 00:00:00 2001 From: oliviaseds Date: Mon, 26 Feb 2024 18:56:28 -0500 Subject: [PATCH 03/43] feat: task type rough screen and type/category enum --- backend/schema/tasks/task_test.go | 2 - backend/schema/tasks/transactions.go | 1 - client/components/BackButton.tsx | 22 ++++++++++ client/navigation/AppNavigation.tsx | 7 +++ client/package.json | 3 +- client/screens/TaskType.tsx | 65 +++++++++++++++++++++++++++ client/types/type.ts | 66 ++++++++++++++++++++++++++++ 7 files changed, 162 insertions(+), 4 deletions(-) create mode 100644 client/components/BackButton.tsx create mode 100644 client/screens/TaskType.tsx create mode 100644 client/types/type.ts diff --git a/backend/schema/tasks/task_test.go b/backend/schema/tasks/task_test.go index c8785fe..929d481 100644 --- a/backend/schema/tasks/task_test.go +++ b/backend/schema/tasks/task_test.go @@ -201,8 +201,6 @@ func TestTaskGroup(t *testing.T) { }, } - fmt.Println("Expected: ", expectedTasks) - fmt.Println("Response: ", responseTasks) if !reflect.DeepEqual(expectedTasks, responseTasks) { t.Error("Result was not correct") } diff --git a/backend/schema/tasks/transactions.go b/backend/schema/tasks/transactions.go index 77f87b2..a69a1c9 100644 --- a/backend/schema/tasks/transactions.go +++ b/backend/schema/tasks/transactions.go @@ -135,7 +135,6 @@ func GetTasksByAssignedFromDB(pool *pgx.Conn, userIDs []string) ([]models.Task, print(err, "error scanning task ID") return nil, err } - fmt.Println(task_id) task_ids = append(task_ids, task_id) } } diff --git a/client/components/BackButton.tsx b/client/components/BackButton.tsx new file mode 100644 index 0000000..443a8eb --- /dev/null +++ b/client/components/BackButton.tsx @@ -0,0 +1,22 @@ +import React from 'react'; + +import { useNavigation } from '@react-navigation/native'; +import { Button } from 'react-native-paper'; + +import { AppStackNavigation } from '../navigation/AppNavigation'; + +// TODO style +export function BackButton() { + const navigation = useNavigation(); + + return ( + + ); +} diff --git a/client/navigation/AppNavigation.tsx b/client/navigation/AppNavigation.tsx index 945797f..bce16db 100644 --- a/client/navigation/AppNavigation.tsx +++ b/client/navigation/AppNavigation.tsx @@ -4,9 +4,11 @@ import { NavigationProp } from '@react-navigation/native'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; import LoginPage from '../screens/LoginPage'; +import { TaskType } from '../screens/TaskType'; import { AppStackBottomTabNavigator } from './AppStackBottomTabNavigator'; export type AppStackParamList = { + TaskType: undefined; Main: undefined; Home: undefined; Login: undefined; @@ -19,6 +21,11 @@ const AppStack = createNativeStackNavigator(); export function AppNavigation() { return ( + (); + + const [open, setOpen] = useState(false); + const [selectedCategory, setSelectedCategory] = useState( + null + ); + const [selectedTypes, setSelectedTypes] = useState( + Object.values(TypeOfTask) + ); + + useEffect(() => { + setSelectedTypes( + selectedCategory + ? categoryToTypeMap[selectedCategory] + : Object.values(TypeOfTask) + ); + }, [selectedCategory]); + + const filters = Object.values(Category).map((filter) => ({ + label: filter, + value: filter + })); + + return ( + + + + Step 1 of 2 + + Type of Task + + + {selectedTypes.map((type) => ( + + ))} + + + ); +} diff --git a/client/types/type.ts b/client/types/type.ts new file mode 100644 index 0000000..5b691e6 --- /dev/null +++ b/client/types/type.ts @@ -0,0 +1,66 @@ +export enum TypeOfTask { + MEDICATION = 'Medication Management', + APPOINTMENT = 'Physician Appointment', + // LABS = 'Labs & Outpatient Services', + // REHAB = 'Rehab & Home Therapies', + // TRANSITIONAL = 'Transitional Care', + GROOMING = 'Grooming (Bathing/Toileting)', + CONVERSATIONS = 'Family Conversations', + // TRANSPORTATION = 'Transportation', + // RESPITE = 'Respite', + ERRANDS = 'Groceries, Shopping, & Errands', + BILLS = 'Pay Bills', + // PRESCRIPTION = 'Prescription Management', + // SAFETY = 'Home Safety', + DIET = 'Diet & Nutrition', + ACTIVITIES = 'Activities', + INSURANCE = 'Health Insurance', + // FINANCIAL = 'Financial', + // LEGAL = 'Legal', + OTHER = 'Other' +} + +export enum Category { + ALL = '', + HEALTH = 'Health & Medical', + PERSONAL = 'Personal', + HOME = 'Home & Lifestyle', + FINANCIAL = 'Financial & Legal', + OTHER = 'Other' +} + +export const categoryToTypeMap: Record = { + [Category.ALL]: [], + [Category.HEALTH]: [ + TypeOfTask.MEDICATION, + TypeOfTask.APPOINTMENT, + // TypeOfTask.LABS, + // TypeOfTask.REHAB, + // TypeOfTask.TRANSITIONAL, + TypeOfTask.GROOMING, + // TypeOfTask.PRESCRIPTION, + TypeOfTask.DIET + ], + [Category.PERSONAL]: [ + TypeOfTask.GROOMING, + TypeOfTask.CONVERSATIONS, + // TypeOfTask.TRANSPORTATION, + // TypeOfTask.RESPITE, + TypeOfTask.ERRANDS, + // TypeOfTask.SAFETY, + TypeOfTask.BILLS + ], + [Category.HOME]: [ + // TypeOfTask.REHAB, + // TypeOfTask.SAFETY, + TypeOfTask.DIET, + TypeOfTask.ACTIVITIES + ], + [Category.FINANCIAL]: [ + TypeOfTask.BILLS, + TypeOfTask.INSURANCE + // TypeOfTask.FINANCIAL, + // TypeOfTask.LEGAL + ], + [Category.OTHER]: [TypeOfTask.OTHER] +}; From ae2cd8649566f1ff2d8269adbb917d4348153a77 Mon Sep 17 00:00:00 2001 From: narayansharma-21 <97.sharman@gmail.com> Date: Mon, 26 Feb 2024 23:23:38 -0500 Subject: [PATCH 04/43] feat(SingleTask.tsx): Implemented entirety of v4 of lofi with additional logic --- client/package.json | 1 + client/screens/SingleTask.tsx | 120 ++++++++++++++++++++++++---------- client/services/task.ts | 49 ++++---------- client/types/task.ts | 15 +++++ client/types/taskInfo.ts | 4 ++ client/types/taskLabel.ts | 5 ++ package.json | 6 ++ 7 files changed, 128 insertions(+), 72 deletions(-) create mode 100644 client/types/task.ts create mode 100644 client/types/taskInfo.ts create mode 100644 client/types/taskLabel.ts create mode 100644 package.json diff --git a/client/package.json b/client/package.json index e70c837..71813fb 100644 --- a/client/package.json +++ b/client/package.json @@ -31,6 +31,7 @@ "nativewind": "^2.0.11", "react": "18.2.0", "react-native": "0.73.4", + "react-native-dropdown-picker": "^5.4.6", "react-native-paper": "^5.12.3", "react-native-safe-area-context": "4.8.2", "react-native-screens": "~3.29.0", diff --git a/client/screens/SingleTask.tsx b/client/screens/SingleTask.tsx index d42a939..efba019 100644 --- a/client/screens/SingleTask.tsx +++ b/client/screens/SingleTask.tsx @@ -1,33 +1,50 @@ import React, { useEffect, useState } from 'react'; -import { Text, View } from 'react-native'; +import { Text, TextInput, View } from 'react-native'; + +import DropDownPicker from 'react-native-dropdown-picker'; import CheckMark from '../assets/checkmark.svg'; import Reject from '../assets/reject.svg'; import { BackButton } from '../components/BackButton'; -import { getTaskId, getTaskLabel } from '../services/task'; -import { Category } from '../types/type'; +import { getTaskId, getTaskLabel, getTaskType } from '../services/task'; +import { TaskInfo } from '../types/taskInfo'; +import { TaskLabel } from '../types/taskLabel'; +import { Category, categoryToTypeMap, TypeOfTask } from '../types/type'; export default function SingleTaskScreen() { const [taskId] = useState(); + const [open, setOpen] = useState(false); + + const [taskType, setTaskType] = useState( + TypeOfTask.MEDICATION_MANAGEMENT + ); + // Would extract real information in future and not display default, placeholder info const [taskInfo, setTaskInfo] = useState({ created_date: '8:00AM', - task_id: '', - task_info: '{}', - task_type: 'Task Type Here', + task_id: 1, + task_info: { title: 'Doctors Appointment' }, notes: 'Description here. Description here. Description here. Description here. Description here. Description here. Description here. Description here. Description here. Description here. Description here.' }); - const [taskLabel, setTaskLabel] = useState('Label Here'); + const [taskLabel, setTaskLabel] = useState(); useEffect(() => { if (taskId) { getTaskId(taskId) .then((data) => { - const { created_date, task_id, task_info, task_type, notes } = data; - setTaskInfo({ created_date, task_id, task_info, task_type, notes }); + const { created_date, task_id, task_type, notes } = data; + // Handle cases where task_info and notes might be null or undefined + const updatedTaskInfo = { + created_date, + task_id, + task_info: { title: '' }, + task_type, + notes: notes ?? '' + }; + setTaskInfo(updatedTaskInfo); }) .catch((error) => console.error('Error fetching task info:', error)); } @@ -41,29 +58,39 @@ export default function SingleTaskScreen() { } }, [taskId]); - const getCategoryFromTaskInfo = (taskInfo: string): Category => { - try { - // Parse the JSON string to object - const taskInfoObject = JSON.parse(taskInfo); - // Extract the category from the task info object - const category = taskInfoObject.category; - // Return the appropriate category enum value - return Category[category as keyof typeof Category] || Category.ALL; - } catch (error) { - console.error( - 'Error parsing task info to extract category mapping:', - error - ); - return Category.ALL; // Return a default category in case of error + useEffect(() => { + if (taskId) { + getTaskType(taskId) + .then((data) => setTaskType(data)) + .catch((error) => console.error('Error fetching task type:', error)); } + }, [taskId]); + + const getCategoryFromTaskType = ( + taskType: TypeOfTask | undefined + ): Category => { + console.log(taskType); + if (!taskType) { + return Category.ALL; // Return a default category if taskType is undefined + } + // Iterate over each category in the categoryToTypeMap object + for (const category in categoryToTypeMap) { + // Check if the taskType exists in the current category's array of task types + if (categoryToTypeMap[category as Category].includes(taskType)) { + return category as Category; // Return the category if found + } + } + return Category.ALL; // Return a default category if no match is found }; - const getTitleFromTaskInfo = (taskInfo: string): string => { + // Gets title from the task_info object + const getTitleFromTaskInfo = (taskInfo: TaskInfo): string => { try { - // Parse the JSON string to object - const taskInfoObject = JSON.parse(taskInfo); - const title = taskInfoObject.title; - return title; + if ('title' in taskInfo) { + return taskInfo.title; + } else { + return ''; + } } catch (error) { console.error('Error parsing task info to extract title:', error); return ''; @@ -75,13 +102,32 @@ export default function SingleTaskScreen() { + + + - {taskLabel} + + {' '} + {taskLabel?.label_name || 'Label Here'} + - {getCategoryFromTaskInfo(taskInfo.task_info) || 'Category Task'} |{' '} - {taskInfo.task_type} + {getCategoryFromTaskType(taskType) || 'Category Task'} | {taskType} @@ -91,13 +137,19 @@ export default function SingleTaskScreen() { - + {taskInfo.notes} + + Additional Notes{' '} + + - - + + + {/* Once backend endpoints for assignining tasks are implemented, then can connect these buttons */} + ); diff --git a/client/services/task.ts b/client/services/task.ts index 36def50..404714d 100644 --- a/client/services/task.ts +++ b/client/services/task.ts @@ -1,47 +1,20 @@ import axios from 'axios'; +import { Task } from '../types/task'; +import { TaskLabel } from '../types/taskLabel'; import { api_url } from './api-links'; -// Retrieve task label (just call the route) -export const getTaskLabel = async (tid: string): Promise => { - try { - const response = await axios.post(`${api_url}/tasks/${tid}/labels`, {}); - console.log('response:', response); - return response.data; - } catch (error) { - console.error('Error retrieving the task label', error); - throw error; - } +export const getTaskLabel = async (tid: string): Promise => { + const response = await axios.post(`${api_url}/tasks/${tid}/labels`, {}); + return response.data; }; -// Retrieve task id and retrieve the json to retrieve notes, task_type, created_date, and map to category type/task type -export const getTaskId = async ( - tid: string -): Promise<{ - created_date: string; - task_id: string; - task_info: string; - task_type: string; - notes: string; -}> => { - try { - const response = await axios.post(`${api_url}/tasks/${tid}`, {}); - console.log('response:', response); - return response.data; - } catch (error) { - console.error('Error fetching task id', error); - throw error; - } +export const getTaskId = async (tid: string): Promise => { + const response = await axios.post(`${api_url}/tasks/${tid}`, {}); + return response.data; }; -// Assigning users to a task -export const addTaskToUser = async (taskId: string): Promise => { - try { - const response = await axios.post(`${api_url}/tasks/${taskId}/assign`, {}); - console.log('response:', response); - return response.data; - } catch (error) { - console.error('Error assigning task:', error); - throw error; - } +export const getTaskType = async (tid: string) => { + const response = await axios.post(`${api_url}/tasks/${tid}`, {}); + return response.data.task_type; }; diff --git a/client/types/task.ts b/client/types/task.ts new file mode 100644 index 0000000..870e379 --- /dev/null +++ b/client/types/task.ts @@ -0,0 +1,15 @@ +export interface Task { + task_id: number; + group_id: number; + created_by: string; + created_date: string; + start_date?: string | null; + end_date?: string | null; + notes?: string | null; + repeating: boolean; + repeating_interval?: string | null; + repeating_end_date?: string | null; + task_status: string; + task_type: string; + task_info?: JSON | null; +} diff --git a/client/types/taskInfo.ts b/client/types/taskInfo.ts new file mode 100644 index 0000000..18fd475 --- /dev/null +++ b/client/types/taskInfo.ts @@ -0,0 +1,4 @@ +export interface TaskInfo { + title: string; + // Add other properties if needed +} diff --git a/client/types/taskLabel.ts b/client/types/taskLabel.ts new file mode 100644 index 0000000..3a3e99c --- /dev/null +++ b/client/types/taskLabel.ts @@ -0,0 +1,5 @@ +export interface TaskLabel { + task_id: number; + group_id: number; + label_name: string; +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..8a75a2a --- /dev/null +++ b/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "@tanstack/react-query": "^5.24.1", + "react-native-dropdown-picker": "^5.4.6" + } +} From 5cb2b67fbf68537ea8f3a088d6f0d9fa4c124b77 Mon Sep 17 00:00:00 2001 From: oliviaseds Date: Tue, 27 Feb 2024 17:59:42 -0500 Subject: [PATCH 05/43] feat: all hands screen (no functionality) --- client/assets/back-arrow.svg | 4 ++ client/components/BackButton.tsx | 16 ++++--- client/screens/TaskType.tsx | 72 +++++++++++++++++++------------- client/types/type.ts | 2 +- 4 files changed, 55 insertions(+), 39 deletions(-) create mode 100644 client/assets/back-arrow.svg diff --git a/client/assets/back-arrow.svg b/client/assets/back-arrow.svg new file mode 100644 index 0000000..99dedf4 --- /dev/null +++ b/client/assets/back-arrow.svg @@ -0,0 +1,4 @@ + + + + diff --git a/client/components/BackButton.tsx b/client/components/BackButton.tsx index 443a8eb..633c967 100644 --- a/client/components/BackButton.tsx +++ b/client/components/BackButton.tsx @@ -1,22 +1,20 @@ import React from 'react'; import { useNavigation } from '@react-navigation/native'; -import { Button } from 'react-native-paper'; +import { IconButton } from 'react-native-paper'; +import BackArrow from '../assets/back-arrow.svg'; import { AppStackNavigation } from '../navigation/AppNavigation'; -// TODO style export function BackButton() { const navigation = useNavigation(); return ( - + icon={({ color }) => } + onPress={() => navigation.goBack()} + /> ); } diff --git a/client/screens/TaskType.tsx b/client/screens/TaskType.tsx index c788405..3ad4ecb 100644 --- a/client/screens/TaskType.tsx +++ b/client/screens/TaskType.tsx @@ -1,59 +1,73 @@ -import React, { useEffect, useState } from 'react'; +import React, { useState } from 'react'; import { ScrollView, View } from 'react-native'; import { useNavigation } from '@react-navigation/native'; -import DropDownPicker from 'react-native-dropdown-picker'; import { Button, Text } from 'react-native-paper'; import { SafeAreaView } from 'react-native-safe-area-context'; import { BackButton } from '../components/BackButton'; import { AppStackNavigation } from '../navigation/AppNavigation'; -import { Category, categoryToTypeMap, TypeOfTask } from '../types/type'; +import { TypeOfTask } from '../types/type'; export function TaskType() { const navigation = useNavigation(); - const [open, setOpen] = useState(false); - const [selectedCategory, setSelectedCategory] = useState( - null - ); - const [selectedTypes, setSelectedTypes] = useState( - Object.values(TypeOfTask) - ); + // const [open, setOpen] = useState(false); + // const [selectedCategory, setSelectedCategory] = useState( + // null + // ); + const [selectedTypes] = useState(Object.values(TypeOfTask)); - useEffect(() => { - setSelectedTypes( - selectedCategory - ? categoryToTypeMap[selectedCategory] - : Object.values(TypeOfTask) - ); - }, [selectedCategory]); + // useEffect(() => { + // setSelectedTypes( + // selectedCategory + // ? categoryToTypeMap[selectedCategory] + // : Object.values(TypeOfTask) + // ); + // }, [selectedCategory]); - const filters = Object.values(Category).map((filter) => ({ - label: filter, - value: filter - })); + // const filters = Object.values(Category).map((filter) => ({ + // label: filter, + // value: filter + // })); return ( - - - Step 1 of 2 + + + + + + Step 1 of 2 + + + + Type of Task + + - Type of Task - - + /> */} + + {selectedTypes.map((type) => ( - + const bottomSheetRef = useRef(null); + + const snapToIndex = (index: number) => + bottomSheetRef.current?.snapToIndex(index); + const renderBackdrop = useCallback( + (props: BottomSheetDefaultBackdropProps) => ( + + ), + [] + ); - {/* */} + return ( + + + + + + + + Step 1 of 2 + + - - {selectedTypes.map((type) => ( + Type of Task + - ))} - - + + + + {selectedTypes.map((type) => ( + + ))} + + + + Filter + + + + + ); } From 7a432a8d3c293a924a74473bc8c0056d9e22e9b0 Mon Sep 17 00:00:00 2001 From: narayansharma-21 <97.sharman@gmail.com> Date: Thu, 29 Feb 2024 19:02:36 -0500 Subject: [PATCH 07/43] fix(task.ts): Refactored service routes to use tanStack in the SingleTask screen --- client/screens/SingleTask.tsx | 54 ++++++----------------------------- client/services/task.ts | 37 +++++++++++++++++------- client/types/task.ts | 4 ++- 3 files changed, 38 insertions(+), 57 deletions(-) diff --git a/client/screens/SingleTask.tsx b/client/screens/SingleTask.tsx index efba019..88c6064 100644 --- a/client/screens/SingleTask.tsx +++ b/client/screens/SingleTask.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useState } from 'react'; import { Text, TextInput, View } from 'react-native'; import DropDownPicker from 'react-native-dropdown-picker'; @@ -6,13 +6,12 @@ import DropDownPicker from 'react-native-dropdown-picker'; import CheckMark from '../assets/checkmark.svg'; import Reject from '../assets/reject.svg'; import { BackButton } from '../components/BackButton'; -import { getTaskId, getTaskLabel, getTaskType } from '../services/task'; +import { useGetTaskLabel } from '../services/task'; import { TaskInfo } from '../types/taskInfo'; -import { TaskLabel } from '../types/taskLabel'; import { Category, categoryToTypeMap, TypeOfTask } from '../types/type'; export default function SingleTaskScreen() { - const [taskId] = useState(); + const [taskId] = useState('1'); const [open, setOpen] = useState(false); @@ -20,8 +19,10 @@ export default function SingleTaskScreen() { TypeOfTask.MEDICATION_MANAGEMENT ); + const label = useGetTaskLabel(taskId); + // Would extract real information in future and not display default, placeholder info - const [taskInfo, setTaskInfo] = useState({ + const [taskInfo] = useState({ created_date: '8:00AM', task_id: 1, task_info: { title: 'Doctors Appointment' }, @@ -29,43 +30,7 @@ export default function SingleTaskScreen() { 'Description here. Description here. Description here. Description here. Description here. Description here. Description here. Description here. Description here. Description here. Description here.' }); - const [taskLabel, setTaskLabel] = useState(); - - useEffect(() => { - if (taskId) { - getTaskId(taskId) - .then((data) => { - const { created_date, task_id, task_type, notes } = data; - // Handle cases where task_info and notes might be null or undefined - const updatedTaskInfo = { - created_date, - task_id, - task_info: { title: '' }, - task_type, - notes: notes ?? '' - }; - setTaskInfo(updatedTaskInfo); - }) - .catch((error) => console.error('Error fetching task info:', error)); - } - }, [taskId]); - - useEffect(() => { - if (taskId) { - getTaskLabel(taskId) - .then((data) => setTaskLabel(data)) - .catch((error) => console.error('Error fetching task label:', error)); - } - }, [taskId]); - - useEffect(() => { - if (taskId) { - getTaskType(taskId) - .then((data) => setTaskType(data)) - .catch((error) => console.error('Error fetching task type:', error)); - } - }, [taskId]); - + // Gets category based on Task Type const getCategoryFromTaskType = ( taskType: TypeOfTask | undefined ): Category => { @@ -120,10 +85,7 @@ export default function SingleTaskScreen() { /> - - {' '} - {taskLabel?.label_name || 'Label Here'} - + {label || 'Label Here'} diff --git a/client/services/task.ts b/client/services/task.ts index 404714d..0929567 100644 --- a/client/services/task.ts +++ b/client/services/task.ts @@ -1,20 +1,37 @@ +import { useQuery } from '@tanstack/react-query'; import axios from 'axios'; import { Task } from '../types/task'; -import { TaskLabel } from '../types/taskLabel'; +import { TypeOfTask } from '../types/type'; import { api_url } from './api-links'; -export const getTaskLabel = async (tid: string): Promise => { - const response = await axios.post(`${api_url}/tasks/${tid}/labels`, {}); - return response.data; +export const getTaskLabel = async ( + taskID: string | undefined +): Promise => { + const { data } = await axios.get(`${api_url}/tasks/${taskID}/labels`); + return data.label_name; }; -export const getTaskId = async (tid: string): Promise => { - const response = await axios.post(`${api_url}/tasks/${tid}`, {}); - return response.data; +export const getTask = async (taskID: string): Promise => { + const { data } = await axios.get(`${api_url}/tasks/${taskID}`); + return data; }; -export const getTaskType = async (tid: string) => { - const response = await axios.post(`${api_url}/tasks/${tid}`, {}); - return response.data.task_type; +export const useGetTaskLabel = (taskId: string | undefined): string => { + const { data: label } = useQuery({ + queryKey: ['taskId', taskId], + queryFn: () => getTaskLabel(taskId) + }); + return label ?? ''; // Empty string if no label found +}; + +// Helper Function to get Task Type by ID using getTaskId +export const getTaskType = async (tid: string): Promise => { + try { + const task = await getTask(tid); + return task.task_type; + } catch (error) { + console.error('Error fetching task type:', error); + throw error; + } }; diff --git a/client/types/task.ts b/client/types/task.ts index 870e379..0bdf197 100644 --- a/client/types/task.ts +++ b/client/types/task.ts @@ -1,3 +1,5 @@ +import { TypeOfTask } from './type'; + export interface Task { task_id: number; group_id: number; @@ -10,6 +12,6 @@ export interface Task { repeating_interval?: string | null; repeating_end_date?: string | null; task_status: string; - task_type: string; + task_type: TypeOfTask; task_info?: JSON | null; } From 1574f21998bfcbc096f24ae27437fb6b1533cf2f Mon Sep 17 00:00:00 2001 From: wyattchris Date: Mon, 11 Mar 2024 18:00:56 -0400 Subject: [PATCH 08/43] feat: migrated all changes from previous branch BREAKING CHANGE: --- client/components/DropDownItem.tsx | 30 +++ client/components/FilterModal.tsx | 70 +++++++ client/components/TaskInfoCard.tsx | 57 ++++++ .../navigation/AppStackBottomTabNavigator.tsx | 3 +- client/screens/TaskList.tsx | 172 ++++++++++++++++++ client/services/task.ts | 43 +++++ client/types/label.ts | 5 + client/types/task.ts | 16 ++ 8 files changed, 395 insertions(+), 1 deletion(-) create mode 100644 client/components/DropDownItem.tsx create mode 100644 client/components/FilterModal.tsx create mode 100644 client/components/TaskInfoCard.tsx create mode 100644 client/screens/TaskList.tsx create mode 100644 client/services/task.ts create mode 100644 client/types/label.ts create mode 100644 client/types/task.ts diff --git a/client/components/DropDownItem.tsx b/client/components/DropDownItem.tsx new file mode 100644 index 0000000..7aa866f --- /dev/null +++ b/client/components/DropDownItem.tsx @@ -0,0 +1,30 @@ +import React from 'react'; +import { StyleSheet, Text, View } from 'react-native'; + +const DropdownItem = ({ label }: { label: string }) => { + return ( + + {label} + + ); +}; + +const styles = StyleSheet.create({ + container: { + flexDirection: 'row', + alignItems: 'center', + marginBottom: 10 + }, + dropdownLabel: { + fontSize: 18, + color: 'care-wallet-black', + marginRight: 10 + }, + line: { + flex: 1, + height: 1, + backgroundColor: 'gray' + } +}); + +export default DropdownItem; diff --git a/client/components/FilterModal.tsx b/client/components/FilterModal.tsx new file mode 100644 index 0000000..4c6695e --- /dev/null +++ b/client/components/FilterModal.tsx @@ -0,0 +1,70 @@ +import React from 'react'; +import { + Dimensions, + Modal, + Pressable, + StyleSheet, + Text, + View +} from 'react-native'; + +import DropdownItem from './DropDownItem'; + +const windowHeight = Dimensions.get('window').height; + +const FilterModal = ({ + isVisible, + onClose +}: { + isVisible: boolean; + onClose: () => void; +}) => { + return ( + + + + Filters + + + + + + + + + ); +}; + +const styles = StyleSheet.create({ + modalContainer: { + justifyContent: 'center', + alignItems: 'flex-start', // Align items to the left + backgroundColor: 'white', + borderRadius: 20, + padding: 35, + height: windowHeight / 2, + marginTop: windowHeight / 2 + }, + modalText: { + fontSize: 24, + fontWeight: 'bold', + textAlign: 'left', + color: 'black', + marginBottom: 20 + }, + filterOptions: { + padding: 20 + }, + dropdownSeparator: { + borderBottomWidth: 1, + borderBottomColor: 'grey', + marginVertical: 10 + } +}); + +export default FilterModal; diff --git a/client/components/TaskInfoCard.tsx b/client/components/TaskInfoCard.tsx new file mode 100644 index 0000000..b471399 --- /dev/null +++ b/client/components/TaskInfoCard.tsx @@ -0,0 +1,57 @@ +import React from 'react'; +import { StyleSheet, Text, View } from 'react-native'; + +const TaskInfoComponent = ({ + name, + label, + category, + type, + date +}: { + name: string; + label: string; + category: string; + type: string; + date: Date; +}) => { + const formattedStartDate = date ? new Date(date).toLocaleDateString() : 'N/A'; + + return ( + + + {`Task #${name}`} + {label} + + {`${category} | ${type}`} + {`${formattedStartDate}`} + + ); +}; + +const styles = StyleSheet.create({ + container: { + borderRadius: 10, + borderWidth: 1, + borderColor: '#000000', + padding: 10, + margin: 10, + backgroundColor: '#FFFFFF' + }, + header: { + flexDirection: 'row', + justifyContent: 'space-between', + marginBottom: 10 + }, + taskNumber: { + fontWeight: 'bold', + alignSelf: 'flex-end' + }, + label: { + alignSelf: 'flex-start' + }, + categoryType: { + marginTop: 10 + } +}); + +export default TaskInfoComponent; diff --git a/client/navigation/AppStackBottomTabNavigator.tsx b/client/navigation/AppStackBottomTabNavigator.tsx index 6793920..2421f5a 100644 --- a/client/navigation/AppStackBottomTabNavigator.tsx +++ b/client/navigation/AppStackBottomTabNavigator.tsx @@ -9,6 +9,7 @@ import Home from '../assets/bottom-nav/home.svg'; import User from '../assets/bottom-nav/user.svg'; import MedicationList from '../screens/MedicationList'; import Profile from '../screens/Profile'; +import TaskList from '../screens/TaskList'; const AppStackBottomTab = createBottomTabNavigator(); @@ -36,7 +37,7 @@ export function AppStackBottomTabNavigator() { tabBarIcon: ({ color }) => , tabBarLabel: () => }} - component={MedicationList} + component={TaskList} /> ( + {} + ); + const { tasks, tasksIsLoading } = useFilteredTasks(queryParams); + const [isFilterModalVisible, setIsFilterModalVisible] = useState(false); + + // Fetch task labels for each task (2d array list) + useEffect(() => { + const fetchTaskLabels = async () => { + const labels: { [taskId: string]: string[] } = {}; + if (tasks) { + await Promise.all( + tasks.map(async (task) => { + const labelsForTask = await getTaskLabels(task.task_id.toString()); + labels[task.task_id.toString()] = labelsForTask.map( + (label) => label.label_name + ); + }) + ); + } + setTaskLabels(labels); + }; + + if (tasks) { + fetchTaskLabels(); + } + }, [tasks]); + + // Filter tasks based on search query in multiple fields and labels + const filteredTasks = tasks?.filter((task) => { + const taskFieldsMatch = [ + 'task_id', + 'task_status', + 'task_type', + 'notes' + ].some((field) => + task?.[field] + ?.toString() + .toLowerCase() + .includes(searchQuery.toLowerCase()) + ); + + const labelMatch = taskLabels[task?.task_id?.toString()]?.some((label) => + label.toLowerCase().includes(searchQuery.toLowerCase()) + ); + + return taskFieldsMatch || labelMatch; + }); + + // Filter tasks based on categories + const pastDueTasks = tasks?.filter( + (task) => task?.end_date || '' < String(new Date()) + ); + const inProgressTasks = tasks?.filter( + (task) => task?.task_status === 'PARTIAL' + ); + const inFutureTasks = tasks?.filter( + (task) => task?.start_date || '' > String(new Date()) + ); + const completeTasks = tasks?.filter( + (task) => task?.task_status === 'COMPLETE' + ); + const incompleteTasks = tasks?.filter( + (task) => task?.task_status === 'INCOMPLETE' + ); + + // Abstraction to render each section + const renderSection = (tasks: Task[], title: string) => { + return ( + + {title} + {tasks.map((task, index) => { + return ( + + ); + })} + + ); + }; + + return ( + + + { + setSearchQuery(text); + }} + /> + setIsFilterModalVisible(true)} + > + Filter + + + + Task List (all tasks of all time) + + {renderSection(filteredTasks || [], 'All Tasks')} + {renderSection(pastDueTasks || [], 'Past Due')} + {renderSection(inProgressTasks || [], 'In Progress')} + {renderSection(inFutureTasks || [], 'Future')} + {renderSection(completeTasks || [], 'Done')} + {renderSection(incompleteTasks || [], 'Marked as Incomplete')} + setIsFilterModalVisible(false)} + /> + + ); +} + +// TODO: Migrate this to tailwind +const styles = StyleSheet.create({ + container: { + padding: 20 + }, + searchContainer: { + flexDirection: 'row', + alignItems: 'center', + marginBottom: 10 + }, + searchInput: { + flex: 1, + height: 40, + borderColor: 'gray', + borderWidth: 1, + borderRadius: 20, + marginRight: 10, + padding: 8, + overflow: 'hidden' + }, + filterButton: { + backgroundColor: 'gray', + borderRadius: 5, + padding: 8 + }, + filterButtonText: { + color: 'white' + } +}); \ No newline at end of file diff --git a/client/services/task.ts b/client/services/task.ts new file mode 100644 index 0000000..cc5e167 --- /dev/null +++ b/client/services/task.ts @@ -0,0 +1,43 @@ +import { useQuery, useQueryClient } from '@tanstack/react-query'; +import axios from 'axios'; + +import { Task } from '../types/task'; +import { TaskLabel } from '../types/label'; +import { api_url } from './api-links'; + +type TaskQueryParams = { + taskID?: string; + groupID?: string; + createdBy?: string; + taskStatus?: string; + taskType?: string; + startDate?: string; + endDate?: string; +}; + +const getFilteredTasks = async (queryParams: TaskQueryParams): Promise => { + const { data } = await axios.get(`${api_url}/tasks/filtered?`, { + params: queryParams, + }); + return data; +}; + +export const getTaskLabels = async (taskID: string): Promise => { + const { data } = await axios.get(`${api_url}/tasks/${taskID}/labels`); + return data; +}; + +export const useFilteredTasks = (queryParams: TaskQueryParams) => { + const queryClient = useQueryClient(); + + const { data: tasks, isLoading: tasksIsLoading } = useQuery({ + queryKey: ['filteredTaskList', queryParams], + queryFn: () => getFilteredTasks(queryParams), + refetchInterval: 20000, + }); + + return { + tasks, + tasksIsLoading, + }; +}; \ No newline at end of file diff --git a/client/types/label.ts b/client/types/label.ts new file mode 100644 index 0000000..c91852b --- /dev/null +++ b/client/types/label.ts @@ -0,0 +1,5 @@ +export interface TaskLabel { + task_id: number; + group_id: number; + label_name: string; +} \ No newline at end of file diff --git a/client/types/task.ts b/client/types/task.ts new file mode 100644 index 0000000..104f5d7 --- /dev/null +++ b/client/types/task.ts @@ -0,0 +1,16 @@ +export interface Task { + task_id: number; + group_id: number; + created_by: string; + created_date: string; + start_date?: string | null; + end_date?: string | null; + notes?: string | null; + repeating: boolean; + repeating_interval?: string | null; + repeating_end_date?: string | null; + task_status: string; + task_type: string; + task_info?: string | null; + [key: string]: string | number | boolean | null | undefined; // Index signature for string indexing +}; \ No newline at end of file From 724465bf67790f1a924f0809c8faa374f6e31503 Mon Sep 17 00:00:00 2001 From: oliviaseds Date: Tue, 12 Mar 2024 09:46:53 -0400 Subject: [PATCH 09/43] refactor: remove ScrollView and non-Tailwind styling --- client/assets/close/close1.svg | 3 ++ client/assets/close/close2.svg | 3 ++ client/components/TaskType/CloseButton.tsx | 26 ++++++++++++ client/package.json | 2 +- client/screens/TaskType.tsx | 47 ++++++++++++++-------- 5 files changed, 64 insertions(+), 17 deletions(-) create mode 100644 client/assets/close/close1.svg create mode 100644 client/assets/close/close2.svg create mode 100644 client/components/TaskType/CloseButton.tsx diff --git a/client/assets/close/close1.svg b/client/assets/close/close1.svg new file mode 100644 index 0000000..6528766 --- /dev/null +++ b/client/assets/close/close1.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/client/assets/close/close2.svg b/client/assets/close/close2.svg new file mode 100644 index 0000000..3492923 --- /dev/null +++ b/client/assets/close/close2.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/components/TaskType/CloseButton.tsx b/client/components/TaskType/CloseButton.tsx new file mode 100644 index 0000000..dc5f5d5 --- /dev/null +++ b/client/components/TaskType/CloseButton.tsx @@ -0,0 +1,26 @@ +import React from 'react'; + +import { useNavigation } from '@react-navigation/native'; +import { IconButton } from 'react-native-paper'; + +import Close1 from '../../assets/close/close1.svg'; +import Close2 from '../../assets/close/close2.svg'; +import { AppStackNavigation } from '../../navigation/AppNavigation'; + +export function CloseButton({onPress}: {onPress: () => void}) { +const navigation = useNavigation(); + +return ( + ( + <> + + + + )} + onPress={onPress} + /> +); +} diff --git a/client/package.json b/client/package.json index eda66a1..0bbbc7a 100644 --- a/client/package.json +++ b/client/package.json @@ -24,7 +24,7 @@ "@types/react": "^18.2.55", "axios": "^1.6.4", "clsx": "^2.1.0", - "expo": "^50.0.7", + "expo": "^50.0.11", "expo-document-picker": "~11.10.1", "expo-file-system": "~16.0.6", "expo-status-bar": "~1.11.1", diff --git a/client/screens/TaskType.tsx b/client/screens/TaskType.tsx index fafdffc..41993ee 100644 --- a/client/screens/TaskType.tsx +++ b/client/screens/TaskType.tsx @@ -5,7 +5,7 @@ import React, { useRef, useState } from 'react'; -import { ScrollView, View } from 'react-native'; +import { FlatList, View } from 'react-native'; import BottomSheet, { BottomSheetBackdrop } from '@gorhom/bottom-sheet'; import { BottomSheetDefaultBackdropProps } from '@gorhom/bottom-sheet/lib/typescript/components/bottomSheetBackdrop/types'; @@ -18,6 +18,7 @@ import { SafeAreaView } from 'react-native-safe-area-context'; import { BackButton } from '../components/TaskType/BackButton'; import { AppStackNavigation } from '../navigation/AppNavigation'; import { Category, categoryToTypeMap, TypeOfTask } from '../types/type'; +import { CloseButton } from '../components/TaskType/CloseButton'; export function TaskType() { const navigation = useNavigation(); @@ -43,10 +44,16 @@ export function TaskType() { value: filter })); - const snapPoints = useMemo(() => ['50%'], []); + const snapPoints = useMemo(() => ['60%'], []); const bottomSheetRef = useRef(null); + const closeBottomSheet = () => { + if (bottomSheetRef.current) { + bottomSheetRef.current.close(); // Close the BottomSheet + } + }; + const snapToIndex = (index: number) => bottomSheetRef.current?.snapToIndex(index); const renderBackdrop = useCallback( @@ -84,19 +91,23 @@ export function TaskType() { - - {selectedTypes.map((type) => ( - - ))} - + ( + + ) + } + /> + - Filter + + Filter + + + Date: Tue, 12 Mar 2024 09:56:31 -0400 Subject: [PATCH 10/43] style: prettier --- client/components/TaskType/CloseButton.tsx | 26 ++++++------- client/screens/TaskType.tsx | 44 +++++++++++----------- 2 files changed, 34 insertions(+), 36 deletions(-) diff --git a/client/components/TaskType/CloseButton.tsx b/client/components/TaskType/CloseButton.tsx index dc5f5d5..7cc3003 100644 --- a/client/components/TaskType/CloseButton.tsx +++ b/client/components/TaskType/CloseButton.tsx @@ -7,20 +7,20 @@ import Close1 from '../../assets/close/close1.svg'; import Close2 from '../../assets/close/close2.svg'; import { AppStackNavigation } from '../../navigation/AppNavigation'; -export function CloseButton({onPress}: {onPress: () => void}) { -const navigation = useNavigation(); +export function CloseButton({ onPress }: { onPress: () => void }) { + const navigation = useNavigation(); -return ( + return ( ( - <> - - - - )} - onPress={onPress} + className="align-center m-2 flex h-[50px] w-[52px] justify-center rounded-xl bg-carewallet-gray" + mode="contained" + icon={() => ( + <> + + + + )} + onPress={onPress} /> -); + ); } diff --git a/client/screens/TaskType.tsx b/client/screens/TaskType.tsx index 41993ee..945d48a 100644 --- a/client/screens/TaskType.tsx +++ b/client/screens/TaskType.tsx @@ -16,9 +16,9 @@ import { Button, Text } from 'react-native-paper'; import { SafeAreaView } from 'react-native-safe-area-context'; import { BackButton } from '../components/TaskType/BackButton'; +import { CloseButton } from '../components/TaskType/CloseButton'; import { AppStackNavigation } from '../navigation/AppNavigation'; import { Category, categoryToTypeMap, TypeOfTask } from '../types/type'; -import { CloseButton } from '../components/TaskType/CloseButton'; export function TaskType() { const navigation = useNavigation(); @@ -49,9 +49,9 @@ export function TaskType() { const bottomSheetRef = useRef(null); const closeBottomSheet = () => { - if (bottomSheetRef.current) { - bottomSheetRef.current.close(); // Close the BottomSheet - } + if (bottomSheetRef.current) { + bottomSheetRef.current.close(); // Close the BottomSheet + } }; const snapToIndex = (index: number) => @@ -91,23 +91,21 @@ export function TaskType() { - ( - - ) - } - /> - + ( + + )} + /> + Filter - + - + Date: Tue, 12 Mar 2024 17:15:37 -0400 Subject: [PATCH 11/43] feat: filter button progress BREAKING CHANGE: --- client/navigation/AppNavigation.tsx | 5 - .../navigation/AppStackBottomTabNavigator.tsx | 3 +- client/package.json | 6 +- client/screens/TaskList.tsx | 142 +++++++++++++----- client/screens/TaskType.tsx | 2 +- 5 files changed, 113 insertions(+), 45 deletions(-) diff --git a/client/navigation/AppNavigation.tsx b/client/navigation/AppNavigation.tsx index 5e47e2d..e4b4ddc 100644 --- a/client/navigation/AppNavigation.tsx +++ b/client/navigation/AppNavigation.tsx @@ -22,11 +22,6 @@ const AppStack = createNativeStackNavigator(); export function AppNavigation() { return ( - , tabBarLabel: () => }} - component={MedicationList} + component={TaskType} /> + bottomSheetRef.current?.snapToIndex(index); + const [open, setOpen] = useState(false); + const [selectedLabel, setSelectedLabel] = useState('Test'); + const filters = Object.values(taskLabels || {}).map((filter) => ({ + label: filter[0], + value: filter[0] + })); + const snapPoints = useMemo(() => ['60%'], []); + const bottomSheetRef = useRef(null); + const closeBottomSheet = () => { + if (bottomSheetRef.current) { + bottomSheetRef.current.close(); // Close the BottomSheet + } + }; + const renderBackdrop = useCallback( + (props: BottomSheetDefaultBackdropProps) => ( + + ), + [] + ); // Fetch task labels for each task (2d array list) useEffect(() => { @@ -97,8 +136,8 @@ export default function TaskListScreen() { key={index} name={task?.task_id?.toString() || 'N/A'} label={`Label: ${taskLabels[task.task_id.toString()]?.join(', ') || 'N/A'}`} - category={`Category: ${task?.task_type || 'N/A'}`} - type={`Task Status: ${task?.task_status || 'N/A'}`} + category={`Category: ${task?.task_type || ''}`} + type={`Task Status: ${task?.task_status || ''}`} date={task?.start_date ? new Date(task.start_date) : new Date()} /> ); @@ -108,36 +147,69 @@ export default function TaskListScreen() { }; return ( - - - { - setSearchQuery(text); - }} - /> - setIsFilterModalVisible(true)} + + + + { + setSearchQuery(text); + }} + /> + + + + + + Task List (all tasks of all time) + + {renderSection(filteredTasks || [], 'All Tasks')} + {renderSection(pastDueTasks || [], 'Past Due')} + {renderSection(inProgressTasks || [], 'In Progress')} + {renderSection(inFutureTasks || [], 'Future')} + {renderSection(completeTasks || [], 'Done')} + {renderSection(incompleteTasks || [], 'Marked as Incomplete')} + - Filter - - - - Task List (all tasks of all time) - - {renderSection(filteredTasks || [], 'All Tasks')} - {renderSection(pastDueTasks || [], 'Past Due')} - {renderSection(inProgressTasks || [], 'In Progress')} - {renderSection(inFutureTasks || [], 'Future')} - {renderSection(completeTasks || [], 'Done')} - {renderSection(incompleteTasks || [], 'Marked as Incomplete')} - setIsFilterModalVisible(false)} - /> - + + + Filter + + + + + + + + ); } @@ -169,4 +241,4 @@ const styles = StyleSheet.create({ filterButtonText: { color: 'white' } -}); \ No newline at end of file +}); diff --git a/client/screens/TaskType.tsx b/client/screens/TaskType.tsx index 945d48a..ad5db4c 100644 --- a/client/screens/TaskType.tsx +++ b/client/screens/TaskType.tsx @@ -99,7 +99,7 @@ export function TaskType() { className="m-2 h-[50px] items-center justify-center rounded-xl" textColor="black" mode="outlined" - onPress={() => navigation.navigate('New ' + item + 'Task')} + // onPress={() => navigation.navigate('New')} > {item} From e6447095088fd273b4af8f325fe56477d9f86dba Mon Sep 17 00:00:00 2001 From: Chris <125088905+wyattchris@users.noreply.github.com> Date: Wed, 13 Mar 2024 16:00:13 -0400 Subject: [PATCH 12/43] refactor: refactor all styling to be tailwind + button half implemented --- client/screens/TaskList.tsx | 48 +++++++------------------------------ 1 file changed, 8 insertions(+), 40 deletions(-) diff --git a/client/screens/TaskList.tsx b/client/screens/TaskList.tsx index d2d4af9..de29b29 100644 --- a/client/screens/TaskList.tsx +++ b/client/screens/TaskList.tsx @@ -6,9 +6,7 @@ import React, { useState } from 'react'; import { - Pressable, ScrollView, - StyleSheet, Text, TextInput, View @@ -28,15 +26,15 @@ import { getTaskLabels, useFilteredTasks } from '../services/task'; import { Task } from '../types/task'; export default function TaskListScreen() { - const { user, group } = useCareWalletContext(); - const [queryParams, setQueryParams] = useState({ + const { group } = useCareWalletContext(); + const [queryParams ] = useState({ groupID: group.groupID?.toString() || '1' }); const [searchQuery, setSearchQuery] = useState(''); const [taskLabels, setTaskLabels] = useState<{ [taskId: string]: string[] }>( {} ); - const { tasks, tasksIsLoading } = useFilteredTasks(queryParams); + const { tasks } = useFilteredTasks(queryParams); // Filter button (olivia goated) const snapToIndex = (index: number) => @@ -148,10 +146,10 @@ export default function TaskListScreen() { return ( - - + + { setSearchQuery(text); @@ -177,7 +175,8 @@ export default function TaskListScreen() { {renderSection(inFutureTasks || [], 'Future')} {renderSection(completeTasks || [], 'Done')} {renderSection(incompleteTasks || [], 'Marked as Incomplete')} - + - ); } - -// TODO: Migrate this to tailwind -const styles = StyleSheet.create({ - container: { - padding: 20 - }, - searchContainer: { - flexDirection: 'row', - alignItems: 'center', - marginBottom: 10 - }, - searchInput: { - flex: 1, - height: 40, - borderColor: 'gray', - borderWidth: 1, - borderRadius: 20, - marginRight: 10, - padding: 8, - overflow: 'hidden' - }, - filterButton: { - backgroundColor: 'gray', - borderRadius: 5, - padding: 8 - }, - filterButtonText: { - color: 'white' - } -}); From 4e32defdd0378d5da15c0f405fc2409e76a9dd10 Mon Sep 17 00:00:00 2001 From: Chris <125088905+wyattchris@users.noreply.github.com> Date: Wed, 13 Mar 2024 18:13:19 -0400 Subject: [PATCH 13/43] feat: filter button implementation + pr fixes --- backend/db/migrations/1.user.sql | 4 +- backend/db/migrations/2.group.sql | 3 +- backend/db/migrations/3.task.sql | 4 +- backend/db/migrations/4.label.sql | 8 +- client/components/FilterModal.tsx | 70 --------- client/navigation/AppNavigation.tsx | 1 - .../navigation/AppStackBottomTabNavigator.tsx | 3 +- client/screens/TaskList.tsx | 110 +++++++------- client/screens/TaskType.tsx | 143 ------------------ client/types/type.ts | 66 -------- 10 files changed, 71 insertions(+), 341 deletions(-) delete mode 100644 client/components/FilterModal.tsx delete mode 100644 client/screens/TaskType.tsx delete mode 100644 client/types/type.ts diff --git a/backend/db/migrations/1.user.sql b/backend/db/migrations/1.user.sql index 51cab11..192131b 100644 --- a/backend/db/migrations/1.user.sql +++ b/backend/db/migrations/1.user.sql @@ -28,6 +28,8 @@ VALUES ('onrQs8HVGBVMPNz4Fk1uE94bSxg1', 'Danny', 'Rollo', 'dannyrollo4@gmail.com', '', ''), ('8Sy7xBkGiGQv4ZKphcQfY8PxAqw1', 'Narayan', 'Sharma', 'sharma.na@northeastern.edu', '', ''), ('iL7PnjS4axQffmlPceobjUUZ9DF2', 'Caitlin', 'Flynn', 'flynn.ca@northeastern.edu', '', ''), - ('5JgN2PQxCRM9VoCiiFPlQPNqkL32', 'Linwood', 'Blaisdell', 'blaisdell.l@northeastern.edu', '', '') + ('5JgN2PQxCRM9VoCiiFPlQPNqkL32', 'Linwood', 'Blaisdell', 'blaisdell.l@northeastern.edu', '', ''), + ('P03ggWcw63N0RSY7ltbkeBoR6bd2', 'Chris', 'Wyatt', 'wyatt.c@northeastern.edu', '', '') + -- End Care-Wallet Team ; diff --git a/backend/db/migrations/2.group.sql b/backend/db/migrations/2.group.sql index a85d363..a05e608 100644 --- a/backend/db/migrations/2.group.sql +++ b/backend/db/migrations/2.group.sql @@ -49,6 +49,7 @@ VALUES (5, 'mPeo3d3MiXfnpPJADWgFD9ZcB2M2', 'SECONDARY'), (5, 'onrQs8HVGBVMPNz4Fk1uE94bSxg1', 'SECONDARY'), (5, '8Sy7xBkGiGQv4ZKphcQfY8PxAqw1', 'SECONDARY'), - (5, 'iL7PnjS4axQffmlPceobjUUZ9DF2', 'SECONDARY') + (5, 'iL7PnjS4axQffmlPceobjUUZ9DF2', 'SECONDARY'), + (5, 'P03ggWcw63N0RSY7ltbkeBoR6bd2', 'SECONDARY') -- End Care-Wallet Team ; diff --git a/backend/db/migrations/3.task.sql b/backend/db/migrations/3.task.sql index 7da671b..aeb262b 100644 --- a/backend/db/migrations/3.task.sql +++ b/backend/db/migrations/3.task.sql @@ -43,7 +43,9 @@ VALUES (1, 'user2', '2024-02-03 10:45:00', '2024-02-05 10:00:00', '2024-02-05 11:00:00', 'Pick up medication from pharmacy', 'INCOMPLETE', 'med_mgmt'), (2, 'user3', '2024-02-20 23:59:59', '2024-02-10 14:30:00', NULL, 'Schedule doctor appointment', 'INCOMPLETE', 'other'), (3, 'user4', '2020-02-05 11:00:00', NULL, '2024-02-20 23:59:59', 'Submit insurance claim', 'PARTIAL', 'financial'), - (4, 'user1', '2006-01-02 15:04:05', NULL, NULL, 'Refill water pitcher', 'COMPLETE', 'other') + (4, 'user1', '2006-01-02 15:04:05', NULL, NULL, 'Refill water pitcher', 'COMPLETE', 'other'), + (5, 'P03ggWcw63N0RSY7ltbkeBoR6bd2', '2020-02-05 11:00:00', NULL, '2024-02-20 23:59:59', 'Submit insurance claim', 'PARTIAL', 'financial'), + (5, 'P03ggWcw63N0RSY7ltbkeBoR6bd2', '2024-02-20 23:59:59', '2024-02-10 14:30:00', NULL, 'Schedule doctor appointment', 'INCOMPLETE', 'other') ; INSERT INTO task_assignees (task_id, user_id, assignment_status, assigned_by, assigned_date) diff --git a/backend/db/migrations/4.label.sql b/backend/db/migrations/4.label.sql index 944719b..c592f37 100644 --- a/backend/db/migrations/4.label.sql +++ b/backend/db/migrations/4.label.sql @@ -23,7 +23,9 @@ VALUES (2, 'Appointments', 'green'), (3, 'Financial', 'orange'), (4, 'Household', 'purple'), - (1, 'Household', 'purple') + (1, 'Household', 'purple'), + (5, 'Financial', 'orange'), + (5, 'Appointments', 'green') ; INSERT INTO task_labels (task_id, group_id, label_name) @@ -31,5 +33,7 @@ VALUES (1, 1, 'Medication'), (2, 2, 'Appointments'), (3, 3, 'Financial'), - (4, 4, 'Household') + (4, 4, 'Household'), + (5, 5, 'Financial'), + (6, 5, 'Appointments') ; diff --git a/client/components/FilterModal.tsx b/client/components/FilterModal.tsx deleted file mode 100644 index 4c6695e..0000000 --- a/client/components/FilterModal.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import React from 'react'; -import { - Dimensions, - Modal, - Pressable, - StyleSheet, - Text, - View -} from 'react-native'; - -import DropdownItem from './DropDownItem'; - -const windowHeight = Dimensions.get('window').height; - -const FilterModal = ({ - isVisible, - onClose -}: { - isVisible: boolean; - onClose: () => void; -}) => { - return ( - - - - Filters - - - - - - - - - ); -}; - -const styles = StyleSheet.create({ - modalContainer: { - justifyContent: 'center', - alignItems: 'flex-start', // Align items to the left - backgroundColor: 'white', - borderRadius: 20, - padding: 35, - height: windowHeight / 2, - marginTop: windowHeight / 2 - }, - modalText: { - fontSize: 24, - fontWeight: 'bold', - textAlign: 'left', - color: 'black', - marginBottom: 20 - }, - filterOptions: { - padding: 20 - }, - dropdownSeparator: { - borderBottomWidth: 1, - borderBottomColor: 'grey', - marginVertical: 10 - } -}); - -export default FilterModal; diff --git a/client/navigation/AppNavigation.tsx b/client/navigation/AppNavigation.tsx index e4b4ddc..fba06b2 100644 --- a/client/navigation/AppNavigation.tsx +++ b/client/navigation/AppNavigation.tsx @@ -4,7 +4,6 @@ import { NavigationProp } from '@react-navigation/native'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; import LoginPage from '../screens/LoginPage'; -import { TaskType } from '../screens/TaskType'; import { AppStackBottomTabNavigator } from './AppStackBottomTabNavigator'; export type AppStackParamList = { diff --git a/client/navigation/AppStackBottomTabNavigator.tsx b/client/navigation/AppStackBottomTabNavigator.tsx index 34f5f45..2421f5a 100644 --- a/client/navigation/AppStackBottomTabNavigator.tsx +++ b/client/navigation/AppStackBottomTabNavigator.tsx @@ -10,7 +10,6 @@ import User from '../assets/bottom-nav/user.svg'; import MedicationList from '../screens/MedicationList'; import Profile from '../screens/Profile'; import TaskList from '../screens/TaskList'; -import { TaskType } from '../screens/TaskType'; const AppStackBottomTab = createBottomTabNavigator(); @@ -47,7 +46,7 @@ export function AppStackBottomTabNavigator() { tabBarIcon: ({ color }) => , tabBarLabel: () => }} - component={TaskType} + component={MedicationList} /> ( @@ -49,7 +43,7 @@ export default function TaskListScreen() { const bottomSheetRef = useRef(null); const closeBottomSheet = () => { if (bottomSheetRef.current) { - bottomSheetRef.current.close(); // Close the BottomSheet + bottomSheetRef.current.close(); } }; const renderBackdrop = useCallback( @@ -62,6 +56,12 @@ export default function TaskListScreen() { ), [] ); + // TODO: Implement clearFilters function in dropdown picker + const clearFilters = () => { + setSearchQuery(''); + setSelectedLabel(null); + closeBottomSheet(); + }; // Fetch task labels for each task (2d array list) useEffect(() => { @@ -99,11 +99,13 @@ export default function TaskListScreen() { .includes(searchQuery.toLowerCase()) ); - const labelMatch = taskLabels[task?.task_id?.toString()]?.some((label) => - label.toLowerCase().includes(searchQuery.toLowerCase()) - ); + const labelMatch = + !selectedLabel || + taskLabels[task?.task_id?.toString()]?.some((label) => + label.toLowerCase().includes(selectedLabel.toLowerCase()) + ); - return taskFieldsMatch || labelMatch; + return taskFieldsMatch && labelMatch; }); // Filter tasks based on categories @@ -133,7 +135,7 @@ export default function TaskListScreen() { - - + + { setSearchQuery(text); @@ -157,7 +159,7 @@ export default function TaskListScreen() { /> - - - ( - - )} - /> - - - - - Filter - - - - - - - - - ); -} diff --git a/client/types/type.ts b/client/types/type.ts deleted file mode 100644 index 985283d..0000000 --- a/client/types/type.ts +++ /dev/null @@ -1,66 +0,0 @@ -export enum TypeOfTask { - MEDICATION = 'Medication Management', - APPOINTMENT = 'Physician Appointment', - // LABS = 'Labs & Outpatient Services', - // REHAB = 'Rehab & Home Therapies', - // TRANSITIONAL = 'Transitional Care', - GROOMING = 'Grooming', - CONVERSATIONS = 'Family Conversations', - // TRANSPORTATION = 'Transportation', - // RESPITE = 'Respite', - ERRANDS = 'Groceries, Shopping, & Errands', - BILLS = 'Pay Bills', - // PRESCRIPTION = 'Prescription Management', - // SAFETY = 'Home Safety', - DIET = 'Diet & Nutrition', - ACTIVITIES = 'Activities', - INSURANCE = 'Health Insurance', - // FINANCIAL = 'Financial', - // LEGAL = 'Legal', - OTHER = 'Other' -} - -export enum Category { - ALL = '', - HEALTH = 'Health & Medical', - PERSONAL = 'Personal', - HOME = 'Home & Lifestyle', - FINANCIAL = 'Financial & Legal', - OTHER = 'Other' -} - -export const categoryToTypeMap: Record = { - [Category.ALL]: [], - [Category.HEALTH]: [ - TypeOfTask.MEDICATION, - TypeOfTask.APPOINTMENT, - // TypeOfTask.LABS, - // TypeOfTask.REHAB, - // TypeOfTask.TRANSITIONAL, - TypeOfTask.GROOMING, - // TypeOfTask.PRESCRIPTION, - TypeOfTask.DIET - ], - [Category.PERSONAL]: [ - TypeOfTask.GROOMING, - TypeOfTask.CONVERSATIONS, - // TypeOfTask.TRANSPORTATION, - // TypeOfTask.RESPITE, - TypeOfTask.ERRANDS, - // TypeOfTask.SAFETY, - TypeOfTask.BILLS - ], - [Category.HOME]: [ - // TypeOfTask.REHAB, - // TypeOfTask.SAFETY, - TypeOfTask.DIET, - TypeOfTask.ACTIVITIES - ], - [Category.FINANCIAL]: [ - TypeOfTask.BILLS, - TypeOfTask.INSURANCE - // TypeOfTask.FINANCIAL, - // TypeOfTask.LEGAL - ], - [Category.OTHER]: [TypeOfTask.OTHER] -}; From c0c6d7741601d3ae6d9127f176d470f0490dc62c Mon Sep 17 00:00:00 2001 From: Chris <125088905+wyattchris@users.noreply.github.com> Date: Sat, 16 Mar 2024 13:02:24 -0400 Subject: [PATCH 14/43] refactor: fix cicd --- client/assets/close/close1.svg | 2 +- client/components/DropDownItem.tsx | 6 ++--- client/components/TaskInfoCard.tsx | 8 +++--- client/components/TaskType/CloseButton.tsx | 4 --- client/screens/TaskList.tsx | 14 +++++----- client/services/task.ts | 18 +++++++------ client/types/label.ts | 8 +++--- client/types/task.ts | 30 +++++++++++----------- 8 files changed, 43 insertions(+), 47 deletions(-) diff --git a/client/assets/close/close1.svg b/client/assets/close/close1.svg index 6528766..fcf27d8 100644 --- a/client/assets/close/close1.svg +++ b/client/assets/close/close1.svg @@ -1,3 +1,3 @@ - \ No newline at end of file + diff --git a/client/components/DropDownItem.tsx b/client/components/DropDownItem.tsx index 7aa866f..3278a09 100644 --- a/client/components/DropDownItem.tsx +++ b/client/components/DropDownItem.tsx @@ -1,13 +1,13 @@ import React from 'react'; import { StyleSheet, Text, View } from 'react-native'; -const DropdownItem = ({ label }: { label: string }) => { +function DropdownItem({ label }: { label: string }) { return ( {label} ); -}; +} const styles = StyleSheet.create({ container: { @@ -27,4 +27,4 @@ const styles = StyleSheet.create({ } }); -export default DropdownItem; +export { DropdownItem }; diff --git a/client/components/TaskInfoCard.tsx b/client/components/TaskInfoCard.tsx index b471399..7e2414b 100644 --- a/client/components/TaskInfoCard.tsx +++ b/client/components/TaskInfoCard.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { StyleSheet, Text, View } from 'react-native'; -const TaskInfoComponent = ({ +export function TaskInfoComponent({ name, label, category, @@ -13,7 +13,7 @@ const TaskInfoComponent = ({ category: string; type: string; date: Date; -}) => { +}) { const formattedStartDate = date ? new Date(date).toLocaleDateString() : 'N/A'; return ( @@ -26,7 +26,7 @@ const TaskInfoComponent = ({ {`${formattedStartDate}`} ); -}; +} const styles = StyleSheet.create({ container: { @@ -53,5 +53,3 @@ const styles = StyleSheet.create({ marginTop: 10 } }); - -export default TaskInfoComponent; diff --git a/client/components/TaskType/CloseButton.tsx b/client/components/TaskType/CloseButton.tsx index 7cc3003..45167ee 100644 --- a/client/components/TaskType/CloseButton.tsx +++ b/client/components/TaskType/CloseButton.tsx @@ -1,15 +1,11 @@ import React from 'react'; -import { useNavigation } from '@react-navigation/native'; import { IconButton } from 'react-native-paper'; import Close1 from '../../assets/close/close1.svg'; import Close2 from '../../assets/close/close2.svg'; -import { AppStackNavigation } from '../../navigation/AppNavigation'; export function CloseButton({ onPress }: { onPress: () => void }) { - const navigation = useNavigation(); - return ( { - setSearchQuery(''); - setSelectedLabel(null); - closeBottomSheet(); - }; + // // TODO: Implement clearFilters function in dropdown picker + // const clearFilters = () => { + // setSearchQuery(''); + // setSelectedLabel(null); + // closeBottomSheet(); + // }; // Fetch task labels for each task (2d array list) useEffect(() => { diff --git a/client/services/task.ts b/client/services/task.ts index cc5e167..995f1bd 100644 --- a/client/services/task.ts +++ b/client/services/task.ts @@ -1,8 +1,8 @@ -import { useQuery, useQueryClient } from '@tanstack/react-query'; +import { useQuery } from '@tanstack/react-query'; import axios from 'axios'; -import { Task } from '../types/task'; import { TaskLabel } from '../types/label'; +import { Task } from '../types/task'; import { api_url } from './api-links'; type TaskQueryParams = { @@ -15,9 +15,11 @@ type TaskQueryParams = { endDate?: string; }; -const getFilteredTasks = async (queryParams: TaskQueryParams): Promise => { +const getFilteredTasks = async ( + queryParams: TaskQueryParams +): Promise => { const { data } = await axios.get(`${api_url}/tasks/filtered?`, { - params: queryParams, + params: queryParams }); return data; }; @@ -28,16 +30,16 @@ export const getTaskLabels = async (taskID: string): Promise => { }; export const useFilteredTasks = (queryParams: TaskQueryParams) => { - const queryClient = useQueryClient(); + // const queryClient = useQueryClient(); const { data: tasks, isLoading: tasksIsLoading } = useQuery({ queryKey: ['filteredTaskList', queryParams], queryFn: () => getFilteredTasks(queryParams), - refetchInterval: 20000, + refetchInterval: 20000 }); return { tasks, - tasksIsLoading, + tasksIsLoading }; -}; \ No newline at end of file +}; diff --git a/client/types/label.ts b/client/types/label.ts index c91852b..3a3e99c 100644 --- a/client/types/label.ts +++ b/client/types/label.ts @@ -1,5 +1,5 @@ export interface TaskLabel { - task_id: number; - group_id: number; - label_name: string; -} \ No newline at end of file + task_id: number; + group_id: number; + label_name: string; +} diff --git a/client/types/task.ts b/client/types/task.ts index 104f5d7..f6d0e82 100644 --- a/client/types/task.ts +++ b/client/types/task.ts @@ -1,16 +1,16 @@ export interface Task { - task_id: number; - group_id: number; - created_by: string; - created_date: string; - start_date?: string | null; - end_date?: string | null; - notes?: string | null; - repeating: boolean; - repeating_interval?: string | null; - repeating_end_date?: string | null; - task_status: string; - task_type: string; - task_info?: string | null; - [key: string]: string | number | boolean | null | undefined; // Index signature for string indexing -}; \ No newline at end of file + task_id: number; + group_id: number; + created_by: string; + created_date: string; + start_date?: string | null; + end_date?: string | null; + notes?: string | null; + repeating: boolean; + repeating_interval?: string | null; + repeating_end_date?: string | null; + task_status: string; + task_type: string; + task_info?: string | null; + [key: string]: string | number | boolean | null | undefined; // Index signature for string indexing +} From e49287fbe90b83b84bfa75f0cf28f08acad1a47e Mon Sep 17 00:00:00 2001 From: narayansharma-21 <97.sharman@gmail.com> Date: Sat, 16 Mar 2024 13:07:33 -0400 Subject: [PATCH 15/43] fix(Attempted-to-fix-the-query): SingleTask.tsx --- client/screens/SingleTask.tsx | 20 ++++++++------------ package.json | 6 ------ 2 files changed, 8 insertions(+), 18 deletions(-) delete mode 100644 package.json diff --git a/client/screens/SingleTask.tsx b/client/screens/SingleTask.tsx index 88c6064..5ec479f 100644 --- a/client/screens/SingleTask.tsx +++ b/client/screens/SingleTask.tsx @@ -15,7 +15,7 @@ export default function SingleTaskScreen() { const [open, setOpen] = useState(false); - const [taskType, setTaskType] = useState( + const [taskType, setTaskType] = useState( TypeOfTask.MEDICATION_MANAGEMENT ); @@ -31,9 +31,7 @@ export default function SingleTaskScreen() { }); // Gets category based on Task Type - const getCategoryFromTaskType = ( - taskType: TypeOfTask | undefined - ): Category => { + const getCategoryFromTaskType = (taskType: TypeOfTask): Category => { console.log(taskType); if (!taskType) { return Category.ALL; // Return a default category if taskType is undefined @@ -84,20 +82,18 @@ export default function SingleTaskScreen() { containerStyle={{ height: 40, marginBottom: 8, width: 100 }} /> - - {label || 'Label Here'} - - - - {getCategoryFromTaskType(taskType) || 'Category Task'} | {taskType} - - {getTitleFromTaskInfo(taskInfo.task_info) || 'Doctor’s Appointment'}{' '} {'\n'} @ {taskInfo.created_date} + {label || ''} + + {getCategoryFromTaskType(taskType) || 'Category Task'} | {taskType} + + + {taskInfo.notes} diff --git a/package.json b/package.json deleted file mode 100644 index 8a75a2a..0000000 --- a/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "dependencies": { - "@tanstack/react-query": "^5.24.1", - "react-native-dropdown-picker": "^5.4.6" - } -} From 85dcfe03655128bb70b17454a35888f0c056e352 Mon Sep 17 00:00:00 2001 From: Chris <125088905+wyattchris@users.noreply.github.com> Date: Sat, 16 Mar 2024 13:18:05 -0400 Subject: [PATCH 16/43] refactor(delete-svgs): delete svgs --- client/assets/close/close1.svg | 3 --- client/assets/close/close2.svg | 3 --- 2 files changed, 6 deletions(-) delete mode 100644 client/assets/close/close1.svg delete mode 100644 client/assets/close/close2.svg diff --git a/client/assets/close/close1.svg b/client/assets/close/close1.svg deleted file mode 100644 index fcf27d8..0000000 --- a/client/assets/close/close1.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/client/assets/close/close2.svg b/client/assets/close/close2.svg deleted file mode 100644 index 3492923..0000000 --- a/client/assets/close/close2.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - From d70d20334d68a1ad19fbc1725638fbbfceda4c89 Mon Sep 17 00:00:00 2001 From: narayansharma-21 <97.sharman@gmail.com> Date: Sat, 16 Mar 2024 13:25:38 -0400 Subject: [PATCH 17/43] fix(SingleTask.tsx): Fixed undefined error on xcode --- client/screens/SingleTask.tsx | 8 +++----- client/services/task.ts | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/client/screens/SingleTask.tsx b/client/screens/SingleTask.tsx index 5ec479f..df5834f 100644 --- a/client/screens/SingleTask.tsx +++ b/client/screens/SingleTask.tsx @@ -18,7 +18,6 @@ export default function SingleTaskScreen() { const [taskType, setTaskType] = useState( TypeOfTask.MEDICATION_MANAGEMENT ); - const label = useGetTaskLabel(taskId); // Would extract real information in future and not display default, placeholder info @@ -65,7 +64,7 @@ export default function SingleTaskScreen() { - + @@ -98,9 +98,7 @@ export default function SingleTaskScreen() { {taskInfo.notes} - - Additional Notes{' '} - + Additional Notes diff --git a/client/services/task.ts b/client/services/task.ts index 0929567..885fd10 100644 --- a/client/services/task.ts +++ b/client/services/task.ts @@ -9,7 +9,7 @@ export const getTaskLabel = async ( taskID: string | undefined ): Promise => { const { data } = await axios.get(`${api_url}/tasks/${taskID}/labels`); - return data.label_name; + return data.label_name ?? ''; }; export const getTask = async (taskID: string): Promise => { From 4c3a6fc738f7c1845973b66ebe81c02d752a815b Mon Sep 17 00:00:00 2001 From: Chris <125088905+wyattchris@users.noreply.github.com> Date: Sat, 16 Mar 2024 13:32:23 -0400 Subject: [PATCH 18/43] feat: snapped w my boy matt --- backend/schema/tasks/task_test.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/backend/schema/tasks/task_test.go b/backend/schema/tasks/task_test.go index 9ec9d8d..8165af3 100644 --- a/backend/schema/tasks/task_test.go +++ b/backend/schema/tasks/task_test.go @@ -91,10 +91,19 @@ func TestTaskGroup(t *testing.T) { TaskStatus: "COMPLETE", TaskType: "other", }, + { + TaskID: 6, + GroupID: 5, + CreatedBy: "P03ggWcw63N0RSY7ltbkeBoR6bd2", + CreatedDate: time.Date(2024, 2, 20, 23, 59, 59, 0, time.UTC), + StartDate: &start_date_1, + TaskStatus: "INCOMPLETE", + TaskType: "other", + }, } if !reflect.DeepEqual(expectedTasks, responseTasks) { - t.Error("Result was not correct") + t.Error("Result was not correct", responseTasks, expectedTasks) } }) From 8a2cfa5ef0a37d4507cf9841802fd59b0c3fb664 Mon Sep 17 00:00:00 2001 From: narayansharma-21 <97.sharman@gmail.com> Date: Sat, 16 Mar 2024 13:44:58 -0400 Subject: [PATCH 19/43] fix(SingleTask.tsx): Bug fix --- client/screens/SingleTask.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/client/screens/SingleTask.tsx b/client/screens/SingleTask.tsx index df5834f..be54389 100644 --- a/client/screens/SingleTask.tsx +++ b/client/screens/SingleTask.tsx @@ -15,9 +15,7 @@ export default function SingleTaskScreen() { const [open, setOpen] = useState(false); - const [taskType, setTaskType] = useState( - TypeOfTask.MEDICATION_MANAGEMENT - ); + const [taskType, setTaskType] = useState(TypeOfTask.ACTIVITIES); const label = useGetTaskLabel(taskId); // Would extract real information in future and not display default, placeholder info From 7139ac29458842703eabfe93a1f20eebc0a39b5b Mon Sep 17 00:00:00 2001 From: Matt McCoy Date: Mon, 18 Mar 2024 15:05:11 -0400 Subject: [PATCH 20/43] feat: add title to task db table --- backend/db/migrations/3.task.sql | 11 ++-- backend/docs/docs.go | 8 +++ backend/docs/swagger.json | 8 +++ backend/docs/swagger.yaml | 5 ++ backend/main.go | 17 +++--- backend/models/task.go | 1 + backend/schema/tasks/routes.go | 2 + backend/schema/tasks/task_test.go | 89 +++++++++++++++++++--------- backend/schema/tasks/transactions.go | 31 ++++------ 9 files changed, 112 insertions(+), 60 deletions(-) diff --git a/backend/db/migrations/3.task.sql b/backend/db/migrations/3.task.sql index 7da671b..1565c2b 100644 --- a/backend/db/migrations/3.task.sql +++ b/backend/db/migrations/3.task.sql @@ -8,6 +8,7 @@ CREATE TYPE task_type AS ENUM ('med_mgmt', 'dr_appt', 'financial', 'other'); CREATE TABLE IF NOT EXISTS task ( task_id serial NOT NULL, + task_title varchar NOT NULL, group_id integer NOT NULL, created_by varchar NOT NULL, created_date timestamp NOT NULL, -- add default val with current timestamp? @@ -38,12 +39,12 @@ CREATE TABLE IF NOT EXISTS task_assignees ( FOREIGN KEY (assigned_by) REFERENCES users (user_id) ); -INSERT INTO task (group_id, created_by, created_date, start_date, end_date, notes, task_status, task_type) +INSERT INTO task (task_title, group_id, created_by, created_date, start_date, end_date, notes, task_status, task_type) VALUES - (1, 'user2', '2024-02-03 10:45:00', '2024-02-05 10:00:00', '2024-02-05 11:00:00', 'Pick up medication from pharmacy', 'INCOMPLETE', 'med_mgmt'), - (2, 'user3', '2024-02-20 23:59:59', '2024-02-10 14:30:00', NULL, 'Schedule doctor appointment', 'INCOMPLETE', 'other'), - (3, 'user4', '2020-02-05 11:00:00', NULL, '2024-02-20 23:59:59', 'Submit insurance claim', 'PARTIAL', 'financial'), - (4, 'user1', '2006-01-02 15:04:05', NULL, NULL, 'Refill water pitcher', 'COMPLETE', 'other') + ('task 1', 1, 'user2', '2024-02-03 10:45:00', '2024-02-05 10:00:00', '2024-02-05 11:00:00', 'Pick up medication from pharmacy', 'INCOMPLETE', 'med_mgmt'), + ('task 2', 2, 'user3', '2024-02-20 23:59:59', '2024-02-10 14:30:00', NULL, 'Schedule doctor appointment', 'INCOMPLETE', 'other'), + ('task 3', 3, 'user4', '2020-02-05 11:00:00', NULL, '2024-02-20 23:59:59', 'Submit insurance claim', 'PARTIAL', 'financial'), + ('task 4', 4, 'user1', '2006-01-02 15:04:05', NULL, NULL, 'Refill water pitcher', 'COMPLETE', 'other') ; INSERT INTO task_assignees (task_id, user_id, assignment_status, assigned_by, assigned_date) diff --git a/backend/docs/docs.go b/backend/docs/docs.go index 751b7a3..471098b 100644 --- a/backend/docs/docs.go +++ b/backend/docs/docs.go @@ -535,6 +535,11 @@ const docTemplate = `{ "name": "taskStatus", "in": "query" }, + { + "type": "string", + "name": "taskTitle", + "in": "query" + }, { "type": "string", "name": "taskType", @@ -1187,6 +1192,9 @@ const docTemplate = `{ "task_status": { "type": "string" }, + "task_title": { + "type": "string" + }, "task_type": { "type": "string" } diff --git a/backend/docs/swagger.json b/backend/docs/swagger.json index 1336662..4a43d2d 100644 --- a/backend/docs/swagger.json +++ b/backend/docs/swagger.json @@ -528,6 +528,11 @@ "name": "taskStatus", "in": "query" }, + { + "type": "string", + "name": "taskTitle", + "in": "query" + }, { "type": "string", "name": "taskType", @@ -1180,6 +1185,9 @@ "task_status": { "type": "string" }, + "task_title": { + "type": "string" + }, "task_type": { "type": "string" } diff --git a/backend/docs/swagger.yaml b/backend/docs/swagger.yaml index 91b65c9..6ff3091 100644 --- a/backend/docs/swagger.yaml +++ b/backend/docs/swagger.yaml @@ -102,6 +102,8 @@ definitions: type: string task_status: type: string + task_title: + type: string task_type: type: string type: object @@ -766,6 +768,9 @@ paths: - in: query name: taskStatus type: string + - in: query + name: taskTitle + type: string - in: query name: taskType type: string diff --git a/backend/main.go b/backend/main.go index e5f1ee6..6fb1c0c 100644 --- a/backend/main.go +++ b/backend/main.go @@ -13,6 +13,7 @@ import ( "carewallet/schema/tasks" "carewallet/schema/user" "fmt" + "log" "os" "github.com/gin-gonic/gin" @@ -39,7 +40,14 @@ func main() { defer conn.Close() - r := gin.Default() + // prepare gin + // uncomment below mode if want to get back to release debug mode + //gin.SetMode(gin.ReleaseMode) + + // gin with default setup + r := gin.New() + r.Use(gin.Logger()) + r.Use(gin.Recovery()) v1 := r.Group("/") { @@ -67,10 +75,5 @@ func main() { r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) } - err = r.Run(":8080") - - if err != nil { - fmt.Fprintf(os.Stderr, "%v\n", err) - os.Exit(1) - } + log.Fatalf("%v", r.Run(":8080")) } diff --git a/backend/models/task.go b/backend/models/task.go index 4f700c2..512e6ef 100644 --- a/backend/models/task.go +++ b/backend/models/task.go @@ -6,6 +6,7 @@ import ( type Task struct { TaskID int `json:"task_id"` + TaskTitle string `json:"task_title"` GroupID int `json:"group_id"` CreatedBy string `json:"created_by"` // User ID CreatedDate time.Time `json:"created_date"` diff --git a/backend/schema/tasks/routes.go b/backend/schema/tasks/routes.go index 9452a46..ff83402 100644 --- a/backend/schema/tasks/routes.go +++ b/backend/schema/tasks/routes.go @@ -64,6 +64,7 @@ func (pg *PgModel) GetTaskByID(c *gin.Context) { type TaskQuery struct { TaskID string `form:"taskID"` + TaskTitle string `form:"taskTitle"` GroupID string `form:"groupID"` CreatedBy string `form:"createdBy"` TaskStatus string `form:"taskStatus"` @@ -87,6 +88,7 @@ func (pg *PgModel) GetFilteredTasks(c *gin.Context) { var filterQuery TaskQuery if err := c.ShouldBindQuery(&filterQuery); err != nil { c.JSON(http.StatusBadRequest, err.Error()) + fmt.Println("error binding to query: ", err) return } tasks, err := GetTasksByQueryFromDB(pg.Conn, filterQuery) diff --git a/backend/schema/tasks/task_test.go b/backend/schema/tasks/task_test.go index 9ec9d8d..16462b4 100644 --- a/backend/schema/tasks/task_test.go +++ b/backend/schema/tasks/task_test.go @@ -42,6 +42,7 @@ func TestTaskGroup(t *testing.T) { t.Run("TestGetFilteredTasks", func(t *testing.T) { getRequest := TaskQuery{ + TaskTitle: "", GroupID: "", CreatedBy: "", TaskStatus: "", @@ -64,6 +65,7 @@ func TestTaskGroup(t *testing.T) { if http.StatusOK != w.Code { t.Error("Failed to retrieve tasks by filter query.") + return } var responseTasks []models.Task @@ -71,30 +73,49 @@ func TestTaskGroup(t *testing.T) { if err != nil { t.Error("Failed to unmarshal json") + return } start_date_1 := time.Date(2024, 2, 10, 14, 30, 0, 0, time.UTC) + note := "Schedule doctor appointment" + note2 := "Refill water pitcher" expectedTasks := []models.Task{ { - TaskID: 2, - GroupID: 2, - CreatedBy: "user3", - CreatedDate: time.Date(2024, 2, 20, 23, 59, 59, 0, time.UTC), - StartDate: &start_date_1, - TaskStatus: "INCOMPLETE", - TaskType: "other", + TaskID: 2, + TaskTitle: "task 2", + GroupID: 2, + CreatedBy: "user3", + CreatedDate: time.Date(2024, 2, 20, 23, 59, 59, 0, time.UTC), + StartDate: &start_date_1, + EndDate: nil, + Notes: ¬e, + Repeating: false, + RepeatingInterval: nil, + RepeatingEndDate: nil, + TaskStatus: "INCOMPLETE", + TaskType: "other", + TaskInfo: nil, }, { - TaskID: 4, - GroupID: 4, - CreatedBy: "user1", - CreatedDate: time.Date(2006, 1, 2, 15, 4, 5, 0, time.UTC), - TaskStatus: "COMPLETE", - TaskType: "other", + TaskID: 4, + TaskTitle: "task 4", + GroupID: 4, + CreatedBy: "user1", + CreatedDate: time.Date(2006, 1, 2, 15, 4, 5, 0, time.UTC), + StartDate: nil, + EndDate: nil, + Notes: ¬e2, + Repeating: false, + RepeatingInterval: nil, + RepeatingEndDate: nil, + TaskStatus: "COMPLETE", + TaskType: "other", + TaskInfo: nil, }, } if !reflect.DeepEqual(expectedTasks, responseTasks) { t.Error("Result was not correct") + return } }) @@ -192,13 +213,20 @@ func TestTaskGroup(t *testing.T) { note := "Refill water pitcher" expectedTasks := []models.Task{ { - TaskID: 4, - GroupID: 4, - CreatedBy: "user1", - CreatedDate: time.Date(2006, 1, 2, 15, 4, 5, 0, time.UTC), - Notes: ¬e, - TaskStatus: "COMPLETE", - TaskType: "other", + TaskID: 4, + TaskTitle: "task 4", + GroupID: 4, + CreatedBy: "user1", + CreatedDate: time.Date(2006, 1, 2, 15, 4, 5, 0, time.UTC), + StartDate: nil, + EndDate: nil, + Notes: ¬e, + Repeating: false, + RepeatingInterval: nil, + RepeatingEndDate: nil, + TaskStatus: "COMPLETE", + TaskType: "other", + TaskInfo: nil, }, } @@ -226,13 +254,20 @@ func TestTaskGroup(t *testing.T) { note := "Refill water pitcher" expectedTasks := []models.Task{ { - TaskID: 4, - GroupID: 4, - CreatedBy: "user1", - CreatedDate: time.Date(2006, 1, 2, 15, 4, 5, 0, time.UTC), - Notes: ¬e, - TaskStatus: "COMPLETE", - TaskType: "other", + TaskID: 4, + TaskTitle: "task 4", + GroupID: 4, + CreatedBy: "user1", + CreatedDate: time.Date(2006, 1, 2, 15, 4, 5, 0, time.UTC), + StartDate: nil, + EndDate: nil, + Notes: ¬e, + Repeating: false, + RepeatingInterval: nil, + RepeatingEndDate: nil, + TaskStatus: "COMPLETE", + TaskType: "other", + TaskInfo: nil, }, } diff --git a/backend/schema/tasks/transactions.go b/backend/schema/tasks/transactions.go index ba60f4c..b6294a3 100644 --- a/backend/schema/tasks/transactions.go +++ b/backend/schema/tasks/transactions.go @@ -13,6 +13,7 @@ import ( func GetTasksByQueryFromDB(pool *pgx.Conn, filterQuery TaskQuery) ([]models.Task, error) { query_fields := []string{ filterQuery.TaskID, + filterQuery.TaskTitle, filterQuery.GroupID, filterQuery.CreatedBy, filterQuery.TaskStatus, @@ -20,7 +21,7 @@ func GetTasksByQueryFromDB(pool *pgx.Conn, filterQuery TaskQuery) ([]models.Task filterQuery.StartDate, filterQuery.EndDate} - field_names := []string{"task_id =", "group_id =", "created_by =", "task_status =", "task_type =", "start_date >=", "end_date <="} + field_names := []string{"task_id =", "task_title =", "group_id =", "created_by =", "task_status =", "task_type =", "start_date >=", "end_date <="} var query string var args []interface{} @@ -34,7 +35,7 @@ func GetTasksByQueryFromDB(pool *pgx.Conn, filterQuery TaskQuery) ([]models.Task } } - rows, err := pool.Query("SELECT task_id, group_id, created_by, created_date, start_date, end_date, task_status, task_type FROM task WHERE "+query, args...) + rows, err := pool.Query("SELECT * FROM task WHERE "+query, args...) if err != nil { print(err, "error selecting tasks by query") @@ -47,10 +48,10 @@ func GetTasksByQueryFromDB(pool *pgx.Conn, filterQuery TaskQuery) ([]models.Task for rows.Next() { task := models.Task{} - err := rows.Scan(&task.TaskID, &task.GroupID, &task.CreatedBy, &task.CreatedDate, &task.StartDate, &task.EndDate, &task.TaskStatus, &task.TaskType) + err := rows.Scan(&task.TaskID, &task.TaskTitle, &task.GroupID, &task.CreatedBy, &task.CreatedDate, &task.StartDate, &task.EndDate, &task.Notes, &task.Repeating, &task.RepeatingInterval, &task.RepeatingEndDate, &task.TaskStatus, &task.TaskType, &task.TaskInfo) if err != nil { - print(err, "error scanning tasks by query") + print(err.Error(), "error scanning tasks by query") return nil, err } @@ -143,7 +144,7 @@ func GetTasksByAssignedFromDB(pool *pgx.Conn, userIDs []string) ([]models.Task, // Get all tasks by task ID var task models.Task for _, task_id := range task_ids { - err := pool.QueryRow("SELECT * FROM task WHERE task_id = $1;", task_id).Scan(&task.TaskID, &task.GroupID, &task.CreatedBy, &task.CreatedDate, &task.StartDate, &task.EndDate, &task.Notes, &task.Repeating, &task.RepeatingInterval, &task.RepeatingEndDate, &task.TaskStatus, &task.TaskType, &task.TaskInfo) + err := pool.QueryRow("SELECT * FROM task WHERE task_id = $1;", task_id).Scan(&task.TaskID, &task.TaskTitle, &task.GroupID, &task.CreatedBy, &task.CreatedDate, &task.StartDate, &task.EndDate, &task.Notes, &task.Repeating, &task.RepeatingInterval, &task.RepeatingEndDate, &task.TaskStatus, &task.TaskType, &task.TaskInfo) if err != nil { print(err, "error querying task by ID") return nil, err @@ -158,7 +159,7 @@ func GetTasksByAssignedFromDB(pool *pgx.Conn, userIDs []string) ([]models.Task, // CreateTaskInDB creates a new task in the database and returns its ID func CreateTaskInDB(pool *pgx.Conn, newTask models.Task) (int, error) { query := ` - INSERT INTO task (group_id, created_by, created_date, start_date, end_date, notes, repeating, repeating_interval, repeating_end_date, task_status, task_type, task_info) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) RETURNING task_id` + INSERT INTO task (group_id, created_by, created_date, start_date, end_date, notes, repeating, repeating_interval, repeating_end_date, task_status, task_type, task_info, task_title) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13) RETURNING task_id` var newTaskID int err := pool.QueryRow( @@ -175,6 +176,7 @@ func CreateTaskInDB(pool *pgx.Conn, newTask models.Task) (int, error) { newTask.TaskStatus, newTask.TaskType, newTask.TaskInfo, + newTask.TaskTitle, ).Scan(&newTaskID) return newTaskID, err @@ -200,24 +202,11 @@ func UpdateTaskInfoInDB(pool *pgx.Conn, taskID int, taskInfo json.RawMessage) er // GetTaskByID fetches a task from the database by its ID func GetTaskByID(pool *pgx.Conn, taskID int) (models.Task, error) { - query := ` - SELECT task_id, group_id, created_by, created_date, start_date, end_date, notes, repeating, repeating_interval, repeating_end_date, task_status, task_type, task_info FROM task WHERE task_id = $1` + query := `SELECT * FROM task WHERE task_id = $1` var task models.Task err := pool.QueryRow(query, taskID).Scan( - &task.TaskID, - &task.GroupID, - &task.CreatedBy, - &task.CreatedDate, - &task.StartDate, - &task.EndDate, - &task.Notes, - &task.Repeating, - &task.RepeatingInterval, - &task.RepeatingEndDate, - &task.TaskStatus, - &task.TaskType, - &task.TaskInfo, + &task.TaskID, &task.TaskTitle, &task.GroupID, &task.CreatedBy, &task.CreatedDate, &task.StartDate, &task.EndDate, &task.Notes, &task.Repeating, &task.RepeatingInterval, &task.RepeatingEndDate, &task.TaskStatus, &task.TaskType, &task.TaskInfo, ) return task, err } From d329142d770cdbb99a60a4d66e82829db8b411ed Mon Sep 17 00:00:00 2001 From: Matt McCoy Date: Mon, 18 Mar 2024 15:53:07 -0400 Subject: [PATCH 21/43] fix: cycle import in app nav --- client/navigation/AppNavigation.tsx | 21 +------------------ .../navigation/AppStackBottomTabNavigator.tsx | 8 +++---- client/navigation/types.ts | 19 +++++++++++++++++ client/screens/LoginPage.tsx | 2 +- client/screens/Profile/Profile.tsx | 2 +- client/screens/TaskType.tsx | 4 ++-- 6 files changed, 28 insertions(+), 28 deletions(-) create mode 100644 client/navigation/types.ts diff --git a/client/navigation/AppNavigation.tsx b/client/navigation/AppNavigation.tsx index 309a89b..d84eff0 100644 --- a/client/navigation/AppNavigation.tsx +++ b/client/navigation/AppNavigation.tsx @@ -1,28 +1,9 @@ import React from 'react'; -import { NavigationProp } from '@react-navigation/native'; -import { createNativeStackNavigator } from '@react-navigation/native-stack'; - import LoginPage from '../screens/LoginPage'; import { TaskType } from '../screens/TaskType'; import { AppStackBottomTabNavigator } from './AppStackBottomTabNavigator'; - -export type AppStackParamList = { - Main: undefined; - Home: undefined; - Login: undefined; - Profile: undefined; - PatientView: undefined; - ProfileScreens: undefined; - Landing: undefined; - Calendar: undefined; - Notifications: undefined; - TaskType: undefined; -}; - -export type AppStackNavigation = NavigationProp; - -export const AppStack = createNativeStackNavigator(); +import { AppStack } from './types'; export function AppNavigation() { return ( diff --git a/client/navigation/AppStackBottomTabNavigator.tsx b/client/navigation/AppStackBottomTabNavigator.tsx index 3d42c31..4b3fb45 100644 --- a/client/navigation/AppStackBottomTabNavigator.tsx +++ b/client/navigation/AppStackBottomTabNavigator.tsx @@ -10,9 +10,9 @@ import User from '../assets/bottom-nav/user.svg'; import MedicationList from '../screens/MedicationList'; import PatientView from '../screens/Profile/PatientView'; import Profile from '../screens/Profile/Profile'; -import { AppStack, AppStackParamList } from './AppNavigation'; +import { AppStack } from './types'; -const AppStackBottomTab = createBottomTabNavigator(); +const AppStackBottomTab = createBottomTabNavigator(); export function AppStackBottomTabNavigator() { return ( @@ -56,13 +56,13 @@ export function AppStackBottomTabNavigator() { tabBarIcon: ({ color }) => , tabBarLabel: () => }} - component={AppNavigation} + component={ProfileNavigation} /> ); } -export function AppNavigation() { +export function ProfileNavigation() { return ( ; + +export const AppStack = createNativeStackNavigator(); diff --git a/client/screens/LoginPage.tsx b/client/screens/LoginPage.tsx index 21051a9..e23a132 100644 --- a/client/screens/LoginPage.tsx +++ b/client/screens/LoginPage.tsx @@ -5,7 +5,7 @@ import { onAuthStateChanged } from '@firebase/auth'; import { useNavigation } from '@react-navigation/native'; import { auth } from '../firebase.config'; -import { AppStackNavigation } from '../navigation/AppNavigation'; +import { AppStackNavigation } from '../navigation/types'; import { useAuth } from '../services/auth'; export default function LoginPage() { diff --git a/client/screens/Profile/Profile.tsx b/client/screens/Profile/Profile.tsx index 08a47d7..30f90c0 100644 --- a/client/screens/Profile/Profile.tsx +++ b/client/screens/Profile/Profile.tsx @@ -7,7 +7,7 @@ import { CircleCard } from '../../components/profile/CircleCard'; import { Group } from '../../components/profile/Group'; import { Header } from '../../components/profile/Header'; import { useCareWalletContext } from '../../contexts/CareWalletContext'; -import { AppStackNavigation } from '../../navigation/AppNavigation'; +import { AppStackNavigation } from '../../navigation/types'; import { useAuth } from '../../services/auth'; import { useGroup } from '../../services/group'; import { useUsers } from '../../services/user'; diff --git a/client/screens/TaskType.tsx b/client/screens/TaskType.tsx index 35bc59d..066ab6a 100644 --- a/client/screens/TaskType.tsx +++ b/client/screens/TaskType.tsx @@ -19,7 +19,7 @@ import { Button, Text } from 'react-native-paper'; import { BackButton } from '../components/TaskType/BackButton'; import { CloseButton } from '../components/TaskType/CloseButton'; -import { AppStackNavigation } from '../navigation/AppNavigation'; +import { AppStackNavigation } from '../navigation/types'; import { Category, categoryToTypeMap, TypeOfTask } from '../types/type'; export function TaskType() { @@ -99,7 +99,7 @@ export function TaskType() { renderItem={({ item }) => ( navigation.navigate('New ' + item + ' Task')} + onPress={() => navigation.navigate('Home')} >