diff --git a/backend/db/migrations/3.task.sql b/backend/db/migrations/3.task.sql
index 1565c2b..86bc854 100644
--- a/backend/db/migrations/3.task.sql
+++ b/backend/db/migrations/3.task.sql
@@ -14,6 +14,7 @@ CREATE TABLE IF NOT EXISTS task (
created_date timestamp NOT NULL, -- add default val with current timestamp?
start_date timestamp,
end_date timestamp,
+ quick_task BOOLEAN DEFAULT FALSE,
notes varchar,
repeating BOOLEAN DEFAULT FALSE,
repeating_interval varchar,
@@ -39,12 +40,15 @@ CREATE TABLE IF NOT EXISTS task_assignees (
FOREIGN KEY (assigned_by) REFERENCES users (user_id)
);
-INSERT INTO task (task_title, 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, quick_task)
VALUES
- ('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')
+ ('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', FALSE),
+ ('task 2', 2, 'user3', '2024-02-20 23:59:59', '2024-02-10 14:30:00', NULL, 'Schedule doctor appointment', 'INCOMPLETE', 'other', FALSE),
+ ('task 3', 3, 'user4', '2020-02-05 11:00:00', NULL, '2024-02-20 23:59:59', 'Submit insurance claim', 'PARTIAL', 'financial', FALSE),
+ ('task 4', 4, 'user1', '2006-01-02 15:04:05', NULL, NULL, 'Refill water pitcher', 'COMPLETE', 'other', TRUE),
+ ('task 5', 5, 'user1', '2024-02-05 11:00:00', '2024-02-05 11:00:00', '2024-02-05 11:00:00', 'Get medications', 'INCOMPLETE', 'dr_appt', TRUE),
+ ('task 6', 5, 'user2', '2024-02-05 11:00:00', '2024-02-05 11:00:00', '2024-02-05 11:00:00', 'File Papers', 'INCOMPLETE', 'med_mgmt', TRUE),
+ ('task 7', 5, 'user3', '2024-02-05 11:00:00', '2024-02-05 11:00:00', '2024-02-05 11:00:00', 'Send check to Drs', 'INCOMPLETE', 'financial', TRUE)
;
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 471098b..823c6de 100644
--- a/backend/docs/docs.go
+++ b/backend/docs/docs.go
@@ -520,6 +520,11 @@ const docTemplate = `{
"name": "groupID",
"in": "query"
},
+ {
+ "type": "string",
+ "name": "quickTask",
+ "in": "query"
+ },
{
"type": "string",
"name": "startDate",
@@ -1171,6 +1176,9 @@ const docTemplate = `{
"notes": {
"type": "string"
},
+ "quick_task": {
+ "type": "boolean"
+ },
"repeating": {
"type": "boolean"
},
@@ -1312,6 +1320,9 @@ const docTemplate = `{
"notes": {
"type": "string"
},
+ "quick_task": {
+ "type": "boolean"
+ },
"repeating": {
"type": "boolean"
},
diff --git a/backend/docs/swagger.json b/backend/docs/swagger.json
index 4a43d2d..412bdeb 100644
--- a/backend/docs/swagger.json
+++ b/backend/docs/swagger.json
@@ -513,6 +513,11 @@
"name": "groupID",
"in": "query"
},
+ {
+ "type": "string",
+ "name": "quickTask",
+ "in": "query"
+ },
{
"type": "string",
"name": "startDate",
@@ -1164,6 +1169,9 @@
"notes": {
"type": "string"
},
+ "quick_task": {
+ "type": "boolean"
+ },
"repeating": {
"type": "boolean"
},
@@ -1305,6 +1313,9 @@
"notes": {
"type": "string"
},
+ "quick_task": {
+ "type": "boolean"
+ },
"repeating": {
"type": "boolean"
},
diff --git a/backend/docs/swagger.yaml b/backend/docs/swagger.yaml
index 6ff3091..fbd55f7 100644
--- a/backend/docs/swagger.yaml
+++ b/backend/docs/swagger.yaml
@@ -88,6 +88,8 @@ definitions:
type: integer
notes:
type: string
+ quick_task:
+ type: boolean
repeating:
type: boolean
repeating_end_date:
@@ -180,6 +182,8 @@ definitions:
type: integer
notes:
type: string
+ quick_task:
+ type: boolean
repeating:
type: boolean
repeating_end_date:
@@ -759,6 +763,9 @@ paths:
- in: query
name: groupID
type: string
+ - in: query
+ name: quickTask
+ type: string
- in: query
name: startDate
type: string
diff --git a/backend/models/task.go b/backend/models/task.go
index 512e6ef..6f23880 100644
--- a/backend/models/task.go
+++ b/backend/models/task.go
@@ -12,6 +12,7 @@ type Task struct {
CreatedDate time.Time `json:"created_date"`
StartDate *time.Time `json:"start_date"`
EndDate *time.Time `json:"end_date"`
+ QuickTask bool `json:"quick_task"`
Notes *string `json:"notes"`
Repeating bool `json:"repeating"`
RepeatingInterval *string `json:"repeating_interval"`
diff --git a/backend/schema/tasks/routes.go b/backend/schema/tasks/routes.go
index ff83402..a042495 100644
--- a/backend/schema/tasks/routes.go
+++ b/backend/schema/tasks/routes.go
@@ -71,6 +71,7 @@ type TaskQuery struct {
TaskType string `form:"taskType"`
StartDate string `form:"startDate"`
EndDate string `form:"endDate"`
+ QuickTask string `form:"quickTask"`
}
// GetFilteredTasks godoc
@@ -194,6 +195,7 @@ type TaskBody struct {
CreatedDate time.Time `json:"created_date"`
StartDate *time.Time `json:"start_date"`
EndDate *time.Time `json:"end_date"`
+ QuickTask bool `json:"quick_task"`
Notes *string `json:"notes"`
Repeating bool `json:"repeating"`
RepeatingInterval *string `json:"repeating_interval"`
diff --git a/backend/schema/tasks/task_test.go b/backend/schema/tasks/task_test.go
index 16462b4..63f2b98 100644
--- a/backend/schema/tasks/task_test.go
+++ b/backend/schema/tasks/task_test.go
@@ -49,6 +49,7 @@ func TestTaskGroup(t *testing.T) {
TaskType: "other",
StartDate: "",
EndDate: "",
+ QuickTask: "",
}
w := httptest.NewRecorder()
@@ -59,6 +60,7 @@ func TestTaskGroup(t *testing.T) {
query.Set("taskType", getRequest.TaskType)
query.Set("startDate", getRequest.StartDate)
query.Set("endDate", getRequest.EndDate)
+ query.Set("quickTask", getRequest.QuickTask)
req, _ := http.NewRequest("GET", "/tasks/filtered?"+query.Encode(), nil)
router.ServeHTTP(w, req)
@@ -76,8 +78,9 @@ func TestTaskGroup(t *testing.T) {
return
}
start_date_1 := time.Date(2024, 2, 10, 14, 30, 0, 0, time.UTC)
- note := "Schedule doctor appointment"
- note2 := "Refill water pitcher"
+ notes_1 := "Schedule doctor appointment"
+ notes_2 := "Refill water pitcher"
+
expectedTasks := []models.Task{
{
TaskID: 2,
@@ -87,7 +90,8 @@ func TestTaskGroup(t *testing.T) {
CreatedDate: time.Date(2024, 2, 20, 23, 59, 59, 0, time.UTC),
StartDate: &start_date_1,
EndDate: nil,
- Notes: ¬e,
+ QuickTask: false,
+ Notes: ¬es_1,
Repeating: false,
RepeatingInterval: nil,
RepeatingEndDate: nil,
@@ -103,10 +107,11 @@ func TestTaskGroup(t *testing.T) {
CreatedDate: time.Date(2006, 1, 2, 15, 4, 5, 0, time.UTC),
StartDate: nil,
EndDate: nil,
- Notes: ¬e2,
Repeating: false,
RepeatingInterval: nil,
RepeatingEndDate: nil,
+ QuickTask: true,
+ Notes: ¬es_2,
TaskStatus: "COMPLETE",
TaskType: "other",
TaskInfo: nil,
@@ -220,6 +225,7 @@ func TestTaskGroup(t *testing.T) {
CreatedDate: time.Date(2006, 1, 2, 15, 4, 5, 0, time.UTC),
StartDate: nil,
EndDate: nil,
+ QuickTask: true,
Notes: ¬e,
Repeating: false,
RepeatingInterval: nil,
@@ -267,6 +273,7 @@ func TestTaskGroup(t *testing.T) {
RepeatingEndDate: nil,
TaskStatus: "COMPLETE",
TaskType: "other",
+ QuickTask: true,
TaskInfo: nil,
},
}
@@ -290,10 +297,10 @@ func TestTaskGroup(t *testing.T) {
TaskID: 1,
GroupID: 1,
CreatedBy: "user1",
- CreatedDate: time.Now().UTC(),
StartDate: &startDate,
EndDate: &endDate,
Notes: ¬es,
+ QuickTask: false,
Repeating: repeating,
RepeatingInterval: &repeatingInterval,
RepeatingEndDate: &repeatingEndDate,
diff --git a/backend/schema/tasks/transactions.go b/backend/schema/tasks/transactions.go
index b6294a3..bc3f444 100644
--- a/backend/schema/tasks/transactions.go
+++ b/backend/schema/tasks/transactions.go
@@ -19,9 +19,10 @@ func GetTasksByQueryFromDB(pool *pgx.Conn, filterQuery TaskQuery) ([]models.Task
filterQuery.TaskStatus,
filterQuery.TaskType,
filterQuery.StartDate,
- filterQuery.EndDate}
+ filterQuery.EndDate,
+ filterQuery.QuickTask}
- field_names := []string{"task_id =", "task_title =", "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 <=", "quick_task ="}
var query string
var args []interface{}
@@ -48,7 +49,7 @@ func GetTasksByQueryFromDB(pool *pgx.Conn, filterQuery TaskQuery) ([]models.Task
for rows.Next() {
task := models.Task{}
- 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)
+ err := rows.Scan(&task.TaskID, &task.TaskTitle, &task.GroupID, &task.CreatedBy, &task.CreatedDate, &task.StartDate, &task.EndDate, &task.QuickTask, &task.Notes, &task.Repeating, &task.RepeatingInterval, &task.RepeatingEndDate, &task.TaskStatus, &task.TaskType, &task.TaskInfo)
if err != nil {
print(err.Error(), "error scanning tasks by query")
@@ -144,7 +145,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.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)
+ 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.QuickTask, &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
@@ -159,7 +160,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, task_title) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13) RETURNING task_id`
+ INSERT INTO task (group_id, created_by, created_date, start_date, end_date, quick_task, 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, $14) RETURNING task_id`
var newTaskID int
err := pool.QueryRow(
@@ -169,6 +170,7 @@ func CreateTaskInDB(pool *pgx.Conn, newTask models.Task) (int, error) {
time.Now(), // Assuming created_date should be the current timestamp
newTask.StartDate,
newTask.EndDate,
+ newTask.QuickTask,
newTask.Notes,
newTask.Repeating,
newTask.RepeatingInterval,
@@ -206,7 +208,21 @@ func GetTaskByID(pool *pgx.Conn, taskID int) (models.Task, error) {
var task models.Task
err := pool.QueryRow(query, taskID).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,
+ &task.TaskID,
+ &task.TaskTitle,
+ &task.GroupID,
+ &task.CreatedBy,
+ &task.CreatedDate,
+ &task.StartDate,
+ &task.EndDate,
+ &task.QuickTask,
+ &task.Notes,
+ &task.Repeating,
+ &task.RepeatingInterval,
+ &task.RepeatingEndDate,
+ &task.TaskStatus,
+ &task.TaskType,
+ &task.TaskInfo,
)
return task, err
}
diff --git a/client/components/QuickTaskCard.tsx b/client/components/QuickTaskCard.tsx
new file mode 100644
index 0000000..302a985
--- /dev/null
+++ b/client/components/QuickTaskCard.tsx
@@ -0,0 +1,26 @@
+import React from 'react';
+import { Text, View } from 'react-native';
+
+interface QuickTaskCardProps {
+ name: string;
+ label: string;
+}
+
+function QuickTaskCard({ name, label }: QuickTaskCardProps): JSX.Element {
+ return (
+
+
+
+
+ {name}
+
+
+
+ {label}
+
+
+
+ );
+}
+
+export { QuickTaskCard };
diff --git a/client/screens/QuickTasks.tsx b/client/screens/QuickTasks.tsx
new file mode 100644
index 0000000..6fca2c1
--- /dev/null
+++ b/client/screens/QuickTasks.tsx
@@ -0,0 +1,92 @@
+// components/TasksPopup.tsx
+import React, { useCallback, useMemo, useRef } from 'react';
+import { ActivityIndicator, FlatList, Text, View } from 'react-native';
+
+import BottomSheet, {
+ BottomSheetBackdrop,
+ BottomSheetBackdropProps
+} from '@gorhom/bottom-sheet/';
+import { GestureHandlerRootView } from 'react-native-gesture-handler';
+import { Button } from 'react-native-paper';
+
+import { QuickTaskCard } from '../components/QuickTaskCard';
+import { useCareWalletContext } from '../contexts/CareWalletContext';
+import { useFilteredTasks } from '../services/task';
+
+function QuickTasks(): JSX.Element {
+ const { group } = useCareWalletContext();
+ const { tasks, tasksIsLoading } = useFilteredTasks({
+ groupID: group.groupID.toString(),
+ quickTask: true
+ });
+
+ const snapPoints = useMemo(() => ['70%'], []);
+ const bottomSheetRef = useRef(null);
+
+ const handleOpenPress = () => {
+ bottomSheetRef.current?.expand();
+ console.log(tasks);
+ };
+ const handleClosePress = () => bottomSheetRef.current?.close();
+
+ const renderBackdrop = useCallback(
+ (props: BottomSheetBackdropProps) => (
+
+ ),
+ []
+ );
+
+ // Todo: Look into if there is a change for this
+ const taskTypeDescriptions: Record = {
+ med_mgmt: 'Medication Management',
+ dr_appt: 'Doctor Appointment',
+ financial: 'Financial Task',
+ other: 'Other Task'
+ };
+
+ if (tasksIsLoading) {
+ return (
+
+
+ Loading Tasks...
+
+ );
+ }
+
+ return (
+
+
+
+
+ Today's Quick Tasks
+
+ }
+ keyExtractor={(item) => item.task_id.toString()}
+ renderItem={({ item }) => (
+
+ )}
+ />
+
+
+ );
+}
+
+export { QuickTasks };
diff --git a/client/services/task.ts b/client/services/task.ts
new file mode 100644
index 0000000..d9be515
--- /dev/null
+++ b/client/services/task.ts
@@ -0,0 +1,43 @@
+import { useQuery } from '@tanstack/react-query';
+import axios from 'axios';
+
+import { TaskLabel } from '../types/label';
+import { Task } from '../types/task';
+import { api_url } from './api-links';
+
+type TaskQueryParams = {
+ taskID?: string;
+ groupID?: string;
+ createdBy?: string;
+ taskStatus?: string;
+ taskType?: string;
+ startDate?: string;
+ endDate?: string;
+ quickTask?: boolean;
+};
+
+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 { data: tasks, isLoading: tasksIsLoading } = useQuery({
+ queryKey: ['filteredTaskList', queryParams],
+ queryFn: () => getFilteredTasks(queryParams),
+ refetchInterval: 20000
+ });
+ return {
+ tasks,
+ tasksIsLoading
+ };
+};
diff --git a/client/types/label.ts b/client/types/label.ts
new file mode 100644
index 0000000..3a3e99c
--- /dev/null
+++ b/client/types/label.ts
@@ -0,0 +1,5 @@
+export interface TaskLabel {
+ task_id: number;
+ group_id: number;
+ label_name: string;
+}
diff --git a/client/types/task.ts b/client/types/task.ts
new file mode 100644
index 0000000..3e3da09
--- /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;
+ repeating: boolean;
+ repeating_interval?: string | null;
+ repeating_end_date?: string | null;
+ quick_task: boolean;
+ task_status: string;
+ task_type: string;
+ task_info?: string | null;
+}