From e807e2cae44b07b6efab18e1e59af3f4ece5288e Mon Sep 17 00:00:00 2001
From: Chris <125088905+wyattchris@users.noreply.github.com>
Date: Thu, 28 Mar 2024 11:52:35 -0400
Subject: [PATCH 1/8] feat: initial commit
---
client/screens/FileUpload.tsx | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 client/screens/FileUpload.tsx
diff --git a/client/screens/FileUpload.tsx b/client/screens/FileUpload.tsx
new file mode 100644
index 0000000..e69de29
From 0d83559fd4d216381f8cdc1a58919a0e2457727d Mon Sep 17 00:00:00 2001
From: Chris <125088905+wyattchris@users.noreply.github.com>
Date: Thu, 28 Mar 2024 13:55:46 -0400
Subject: [PATCH 2/8] feat: all components for file uploading + styling and
impl
---
client/assets/arrow-left.svg | 4 +-
client/components/ChooseFileButton.tsx | 13 ++
client/components/nav_buttons/BackButton.tsx | 2 +-
.../navigation/AppStackBottomTabNavigator.tsx | 3 +-
client/screens/FileUpload.tsx | 133 ++++++++++++++++++
5 files changed, 151 insertions(+), 4 deletions(-)
create mode 100644 client/components/ChooseFileButton.tsx
diff --git a/client/assets/arrow-left.svg b/client/assets/arrow-left.svg
index 99dedf4..7a7d75d 100644
--- a/client/assets/arrow-left.svg
+++ b/client/assets/arrow-left.svg
@@ -1,4 +1,4 @@
diff --git a/client/components/ChooseFileButton.tsx b/client/components/ChooseFileButton.tsx
new file mode 100644
index 0000000..29b995f
--- /dev/null
+++ b/client/components/ChooseFileButton.tsx
@@ -0,0 +1,13 @@
+import React from 'react';
+import { Text, TouchableOpacity } from 'react-native';
+
+export function ChooseFileButton({ onPress }: { onPress: () => void }) {
+ return (
+
+ Choose File
+
+ );
+}
diff --git a/client/components/nav_buttons/BackButton.tsx b/client/components/nav_buttons/BackButton.tsx
index a34fa00..a73de7b 100644
--- a/client/components/nav_buttons/BackButton.tsx
+++ b/client/components/nav_buttons/BackButton.tsx
@@ -11,7 +11,7 @@ export function BackButton() {
return (
}
onPress={() => navigation.goBack()}
diff --git a/client/navigation/AppStackBottomTabNavigator.tsx b/client/navigation/AppStackBottomTabNavigator.tsx
index 48e1a01..deab285 100644
--- a/client/navigation/AppStackBottomTabNavigator.tsx
+++ b/client/navigation/AppStackBottomTabNavigator.tsx
@@ -9,6 +9,7 @@ import Calendar from '../assets/bottom-nav/calendar.svg';
import Home from '../assets/bottom-nav/home.svg';
import User from '../assets/bottom-nav/user.svg';
import TimelineCalendarScreen from '../screens/Calendar';
+import FileUploadScreen from '../screens/FileUpload';
import MedicationList from '../screens/MedicationList';
import PatientView from '../screens/Profile/PatientView';
import Profile from '../screens/Profile/Profile';
@@ -61,7 +62,7 @@ export function AppStackBottomTabNavigator() {
tabBarIcon: ({ color }) => ,
tabBarLabel: () =>
}}
- component={ProfileNavigation}
+ component={FileUploadScreen}
/>
);
diff --git a/client/screens/FileUpload.tsx b/client/screens/FileUpload.tsx
index e69de29..1b9706a 100644
--- a/client/screens/FileUpload.tsx
+++ b/client/screens/FileUpload.tsx
@@ -0,0 +1,133 @@
+import React, { useState } from 'react';
+import { Text, TextInput, TouchableOpacity, View } from 'react-native';
+
+import { DocumentPickerAsset, getDocumentAsync } from 'expo-document-picker';
+import DropDownPicker from 'react-native-dropdown-picker';
+
+import { ChooseFileButton } from '../components/ChooseFileButton';
+import { BackButton } from '../components/nav_buttons/BackButton';
+import { useCareWalletContext } from '../contexts/CareWalletContext';
+import { useFile } from '../services/file';
+
+// TODO: Add SVGs to background and button, and add functionality for Title, Label, Notes
+export default function FileUploadScreen() {
+ const { user, group } = useCareWalletContext();
+ const { uploadFileMutation } = useFile();
+ const [open, setOpen] = useState(false);
+ const [fileTitle, setFileTitle] = useState('');
+ const [label, setLabel] = useState('Medication');
+ const [additionalNotes, setAdditionalNotes] = useState('');
+ const [pickedFile, setPickedFile] = useState(
+ null
+ );
+
+ const handleFileTitleChange = (text: string) => {
+ setFileTitle(text);
+ };
+
+ const handleAdditionalNotesChange = (text: string) => {
+ setAdditionalNotes(text);
+ };
+
+ const pickDocument = async () => {
+ try {
+ await getDocumentAsync({
+ type: '*/*',
+ copyToCacheDirectory: false
+ }).then((res) => {
+ if (!res.canceled) {
+ setPickedFile(res.assets[0]);
+ }
+ });
+ } catch (err) {
+ console.log('err', err);
+ }
+ };
+
+ const submitFile = async () => {
+ try {
+ if (pickedFile) {
+ uploadFileMutation({
+ file: pickedFile,
+ userId: user.userID,
+ groupId: group.groupID
+ });
+ }
+ } catch (err) {
+ console.log('err', err);
+ }
+ };
+
+ // TODO: Choosefile border color, dropdown styling, fonts, choose file svg
+ return (
+
+
+
+
+
+ File Upload
+
+
+
+
+
+
+ File Title
+
+
+
+ File Label
+
+
+
+
+
+
+ Additional Notes
+
+
+
+
+
+
+
+
+ Submit
+
+
+
+
+
+ );
+}
From 72939f25ef69df18356bfdbab8dc2a03ca6f9020 Mon Sep 17 00:00:00 2001
From: Chris <125088905+wyattchris@users.noreply.github.com>
Date: Thu, 28 Mar 2024 15:08:58 -0400
Subject: [PATCH 3/8] feat: navigation + styling
---
client/assets/file-upload/circle.svg | 3 +++
client/assets/file-upload/heart.svg | 3 +++
client/navigation/AppStackBottomTabNavigator.tsx | 7 ++++++-
client/navigation/types.ts | 1 +
client/screens/Profile/Profile.tsx | 6 ++++++
5 files changed, 19 insertions(+), 1 deletion(-)
create mode 100644 client/assets/file-upload/circle.svg
create mode 100644 client/assets/file-upload/heart.svg
diff --git a/client/assets/file-upload/circle.svg b/client/assets/file-upload/circle.svg
new file mode 100644
index 0000000..990cac9
--- /dev/null
+++ b/client/assets/file-upload/circle.svg
@@ -0,0 +1,3 @@
+
diff --git a/client/assets/file-upload/heart.svg b/client/assets/file-upload/heart.svg
new file mode 100644
index 0000000..bedcfd7
--- /dev/null
+++ b/client/assets/file-upload/heart.svg
@@ -0,0 +1,3 @@
+
diff --git a/client/navigation/AppStackBottomTabNavigator.tsx b/client/navigation/AppStackBottomTabNavigator.tsx
index deab285..1802c3d 100644
--- a/client/navigation/AppStackBottomTabNavigator.tsx
+++ b/client/navigation/AppStackBottomTabNavigator.tsx
@@ -62,7 +62,7 @@ export function AppStackBottomTabNavigator() {
tabBarIcon: ({ color }) => ,
tabBarLabel: () =>
}}
- component={FileUploadScreen}
+ component={ProfileNavigation}
/>
);
@@ -81,6 +81,11 @@ export function ProfileNavigation() {
options={{ headerShown: false }}
component={PatientView}
/>
+
);
}
diff --git a/client/navigation/types.ts b/client/navigation/types.ts
index 320ce2f..dbe5994 100644
--- a/client/navigation/types.ts
+++ b/client/navigation/types.ts
@@ -8,6 +8,7 @@ export type AppStackParamList = {
Profile: undefined;
PatientView: undefined;
ProfileScreens: undefined;
+ FileUploadScreen: undefined;
Landing: undefined;
Calendar: undefined;
Notifications: undefined;
diff --git a/client/screens/Profile/Profile.tsx b/client/screens/Profile/Profile.tsx
index 09643b2..e1236b2 100644
--- a/client/screens/Profile/Profile.tsx
+++ b/client/screens/Profile/Profile.tsx
@@ -74,6 +74,12 @@ export default function Profile() {
+
+ navigation.navigate('FileUploadScreen')}
+ />
+
signOutMutation()} />
From 7b50bae40ed449774156d670686311a4b9fd2696 Mon Sep 17 00:00:00 2001
From: Chris <125088905+wyattchris@users.noreply.github.com>
Date: Mon, 1 Apr 2024 15:05:57 -0400
Subject: [PATCH 4/8] feat: add label, additional notes to backend routes +
tanstack on FE
---
backend/db/migrations/5.files.sql | 5 ++++-
backend/docs/docs.go | 19 +++++++++++++++++++
backend/docs/swagger.json | 19 +++++++++++++++++++
backend/docs/swagger.yaml | 13 +++++++++++++
backend/models/file.go | 2 ++
backend/schema/files/routes.go | 4 ++++
backend/schema/files/transactions.go | 4 ++--
client/screens/FileUpload.tsx | 8 ++++++--
client/services/file.ts | 10 ++++++++--
9 files changed, 77 insertions(+), 7 deletions(-)
diff --git a/backend/db/migrations/5.files.sql b/backend/db/migrations/5.files.sql
index 82b38cf..0c7ac28 100644
--- a/backend/db/migrations/5.files.sql
+++ b/backend/db/migrations/5.files.sql
@@ -8,8 +8,11 @@ CREATE TABLE IF NOT EXISTS files (
upload_date timestamp,
file_size integer NOT NULL,
task_id integer,
+ notes varchar,
+ label_name varchar NOT NULL,
PRIMARY KEY (file_id),
FOREIGN KEY (group_id) REFERENCES care_group (group_id),
FOREIGN KEY (upload_by) REFERENCES users (user_id),
- FOREIGN KEY (task_id) REFERENCES task (task_id)
+ FOREIGN KEY (task_id) REFERENCES task (task_id),
+ FOREIGN KEY (group_id, label_name) REFERENCES label (group_id, label_name)
);
diff --git a/backend/docs/docs.go b/backend/docs/docs.go
index df089af..1d33deb 100644
--- a/backend/docs/docs.go
+++ b/backend/docs/docs.go
@@ -43,6 +43,19 @@ const docTemplate = `{
"name": "group_id",
"in": "formData",
"required": true
+ },
+ {
+ "type": "string",
+ "description": "Notes for the file",
+ "name": "notes",
+ "in": "formData",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "Label name for the file",
+ "name": "label_name",
+ "in": "formData"
}
],
"responses": {
@@ -1223,6 +1236,12 @@ const docTemplate = `{
"group_id": {
"type": "integer"
},
+ "label_name": {
+ "type": "string"
+ },
+ "notes": {
+ "type": "string"
+ },
"task_id": {
"type": "integer"
},
diff --git a/backend/docs/swagger.json b/backend/docs/swagger.json
index cf5ea38..86db0ca 100644
--- a/backend/docs/swagger.json
+++ b/backend/docs/swagger.json
@@ -36,6 +36,19 @@
"name": "group_id",
"in": "formData",
"required": true
+ },
+ {
+ "type": "string",
+ "description": "Notes for the file",
+ "name": "notes",
+ "in": "formData",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "Label name for the file",
+ "name": "label_name",
+ "in": "formData"
}
],
"responses": {
@@ -1216,6 +1229,12 @@
"group_id": {
"type": "integer"
},
+ "label_name": {
+ "type": "string"
+ },
+ "notes": {
+ "type": "string"
+ },
"task_id": {
"type": "integer"
},
diff --git a/backend/docs/swagger.yaml b/backend/docs/swagger.yaml
index 657f177..3edd7f5 100644
--- a/backend/docs/swagger.yaml
+++ b/backend/docs/swagger.yaml
@@ -33,6 +33,10 @@ definitions:
type: integer
group_id:
type: integer
+ label_name:
+ type: string
+ notes:
+ type: string
task_id:
type: integer
upload_by:
@@ -237,6 +241,15 @@ paths:
name: group_id
required: true
type: integer
+ - description: Notes for the file
+ in: formData
+ name: notes
+ required: true
+ type: string
+ - description: Label name for the file
+ in: formData
+ name: label_name
+ type: string
responses:
"200":
description: OK
diff --git a/backend/models/file.go b/backend/models/file.go
index b0878e4..b931270 100644
--- a/backend/models/file.go
+++ b/backend/models/file.go
@@ -8,4 +8,6 @@ type File struct {
UploadDate string `json:"upload_date"`
FileSize int64 `json:"file_size"`
TaskID int `json:"task_id"`
+ Notes string `json:"notes"`
+ LabelName string `json:"label_name"`
}
diff --git a/backend/schema/files/routes.go b/backend/schema/files/routes.go
index 3e426fb..6db4f46 100644
--- a/backend/schema/files/routes.go
+++ b/backend/schema/files/routes.go
@@ -32,6 +32,8 @@ func FileGroup(v1 *gin.RouterGroup, c *PgModel) *gin.RouterGroup {
// @param file_data formData file true "Body with file zip"
// @param upload_by formData string true "The userId of the uploader"
// @param group_id formData int true "The groupId of the uploader"
+// @param notes formData string true "Notes for the file"
+// @param label_name formData string false "Label name for the file"
//
// @success 200 {object} models.File
// @failure 400 {object} string
@@ -48,6 +50,8 @@ func (pg *PgModel) UploadFile(c *gin.Context) {
fileResponse := form.File["file_data"][0]
file.UploadBy = form.Value["upload_by"][0]
file.GroupID, err = strconv.Atoi(form.Value["group_id"][0])
+ file.Notes = form.Value["notes"][0]
+ file.LabelName = form.Value["label_name"][0]
if err != nil {
c.JSON(http.StatusBadRequest, "Failed to parse groupid")
diff --git a/backend/schema/files/transactions.go b/backend/schema/files/transactions.go
index 2085a9e..348ba07 100644
--- a/backend/schema/files/transactions.go
+++ b/backend/schema/files/transactions.go
@@ -30,8 +30,8 @@ func UploadFile(pool *pgxpool.Pool, file models.File, data *multipart.FileHeader
}
// Insert file into database
- err := pool.QueryRow(context.Background(), "INSERT INTO files (file_name, group_id, upload_by, upload_date, file_size) VALUES ($1, $2, $3, $4, $5) RETURNING file_id;",
- file.FileName, file.GroupID, file.UploadBy, file.UploadDate, data.Size).Scan(&file.FileID)
+ err := pool.QueryRow(context.Background(), "INSERT INTO files (file_name, group_id, upload_by, upload_date, file_size, notes, label_name) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING file_id;",
+ file.FileName, file.GroupID, file.UploadBy, file.UploadDate, data.Size, file.Notes, file.LabelName).Scan(&file.FileID)
if err != nil {
fmt.Println(err.Error())
return err
diff --git a/client/screens/FileUpload.tsx b/client/screens/FileUpload.tsx
index 1b9706a..2d8e2de 100644
--- a/client/screens/FileUpload.tsx
+++ b/client/screens/FileUpload.tsx
@@ -15,7 +15,7 @@ export default function FileUploadScreen() {
const { uploadFileMutation } = useFile();
const [open, setOpen] = useState(false);
const [fileTitle, setFileTitle] = useState('');
- const [label, setLabel] = useState('Medication');
+ const [label, setLabel] = useState('Financial');
const [additionalNotes, setAdditionalNotes] = useState('');
const [pickedFile, setPickedFile] = useState(
null
@@ -23,10 +23,12 @@ export default function FileUploadScreen() {
const handleFileTitleChange = (text: string) => {
setFileTitle(text);
+ console.log('fileTitle', fileTitle);
};
const handleAdditionalNotesChange = (text: string) => {
setAdditionalNotes(text);
+ console.log('notes', additionalNotes);
};
const pickDocument = async () => {
@@ -50,7 +52,9 @@ export default function FileUploadScreen() {
uploadFileMutation({
file: pickedFile,
userId: user.userID,
- groupId: group.groupID
+ groupId: group.groupID,
+ label: label,
+ notes: additionalNotes
});
}
} catch (err) {
diff --git a/client/services/file.ts b/client/services/file.ts
index 6a25312..7fd93a7 100644
--- a/client/services/file.ts
+++ b/client/services/file.ts
@@ -13,12 +13,16 @@ interface UploadFileProps {
file: DocumentPickerAsset;
userId: string;
groupId: number;
+ label: string;
+ notes: string;
}
const uploadFile = async ({
file,
userId,
- groupId
+ groupId,
+ label,
+ notes
}: UploadFileProps): Promise => {
const uploadResumable = createUploadTask(
`${api_url}/files/upload`,
@@ -29,7 +33,9 @@ const uploadFile = async ({
fieldName: 'file_data',
parameters: {
upload_by: userId,
- group_id: groupId.toString()
+ group_id: groupId.toString(),
+ label_name: label,
+ notes: notes
}
}
);
From be9660d6710a0d0dc9e02cad9a861d65740e69cf Mon Sep 17 00:00:00 2001
From: Chris <125088905+wyattchris@users.noreply.github.com>
Date: Wed, 3 Apr 2024 15:08:38 -0400
Subject: [PATCH 5/8] feat: fetch labels from BE using group id + scroll view
---
client/components/ChooseFileButton.tsx | 2 +-
client/screens/FileUpload.tsx | 171 +++++++++++++++----------
client/services/task.ts | 7 +
3 files changed, 110 insertions(+), 70 deletions(-)
diff --git a/client/components/ChooseFileButton.tsx b/client/components/ChooseFileButton.tsx
index 29b995f..b0c7354 100644
--- a/client/components/ChooseFileButton.tsx
+++ b/client/components/ChooseFileButton.tsx
@@ -5,7 +5,7 @@ export function ChooseFileButton({ onPress }: { onPress: () => void }) {
return (
Choose File
diff --git a/client/screens/FileUpload.tsx b/client/screens/FileUpload.tsx
index 2d8e2de..77d0edd 100644
--- a/client/screens/FileUpload.tsx
+++ b/client/screens/FileUpload.tsx
@@ -1,5 +1,11 @@
-import React, { useState } from 'react';
-import { Text, TextInput, TouchableOpacity, View } from 'react-native';
+import React, { useEffect, useState } from 'react';
+import {
+ ScrollView,
+ Text,
+ TextInput,
+ TouchableOpacity,
+ View
+} from 'react-native';
import { DocumentPickerAsset, getDocumentAsync } from 'expo-document-picker';
import DropDownPicker from 'react-native-dropdown-picker';
@@ -8,8 +14,8 @@ import { ChooseFileButton } from '../components/ChooseFileButton';
import { BackButton } from '../components/nav_buttons/BackButton';
import { useCareWalletContext } from '../contexts/CareWalletContext';
import { useFile } from '../services/file';
+import { getLabelsByGroup } from '../services/task';
-// TODO: Add SVGs to background and button, and add functionality for Title, Label, Notes
export default function FileUploadScreen() {
const { user, group } = useCareWalletContext();
const { uploadFileMutation } = useFile();
@@ -20,15 +26,34 @@ export default function FileUploadScreen() {
const [pickedFile, setPickedFile] = useState(
null
);
+ const [allLabels, setAllLabels] = useState([]); // Store all unique labels as a list of strings
+ DropDownPicker.setTheme('DARK');
+
+ // Fetch all labels by the group id
+ useEffect(() => {
+ const fetchLabels = async () => {
+ try {
+ console.log('Group:', group);
+ const labels = await getLabelsByGroup(group.groupID);
+ const uniqueLabels = Array.from(
+ new Set(labels.map((label) => label.label_name))
+ );
+ setAllLabels(uniqueLabels);
+ console.log('Labels:', allLabels);
+ } catch (error) {
+ console.error('Error fetching labels:', error);
+ }
+ };
+
+ fetchLabels();
+ }, [group]);
const handleFileTitleChange = (text: string) => {
setFileTitle(text);
- console.log('fileTitle', fileTitle);
};
const handleAdditionalNotesChange = (text: string) => {
setAdditionalNotes(text);
- console.log('notes', additionalNotes);
};
const pickDocument = async () => {
@@ -64,74 +89,82 @@ export default function FileUploadScreen() {
// TODO: Choosefile border color, dropdown styling, fonts, choose file svg
return (
-
-
-
-
-
- File Upload
-
-
-
-
-
-
- File Title
-
-
-
- File Label
-
+
+
+
+
+
+
+ File Upload
+
+
-
-
-
-
- Additional Notes
-
-
+
+
+
+
+ File Title
+
+
+
+
+
+ File Label
+
+ ({
+ label,
+ value: label
+ }))}
+ setOpen={setOpen}
+ setValue={setLabel}
+ placeholder="Select Label"
+ style={{
+ backgroundColor: '#1A56C4',
+ borderColor: 'transparent'
+ }}
+ textStyle={{
+ color: 'white'
+ }}
+ disabledStyle={{
+ opacity: 0.5
+ }}
+ />
+
-
-
-
-
-
- Submit
+
+
+
+ Additional Notes
-
+
+
+
+
+
+
+
+ Submit
+
+
+
-
+
);
}
diff --git a/client/services/task.ts b/client/services/task.ts
index 68744b3..d14087b 100644
--- a/client/services/task.ts
+++ b/client/services/task.ts
@@ -21,6 +21,13 @@ const getTask = async (taskID: string): Promise => {
return data;
};
+export const getLabelsByGroup = async (
+ groupID: number
+): Promise => {
+ const { data } = await axios.get(`${api_url}/group/${groupID}/labels`);
+ return data;
+};
+
const getTaskByAssigned = async (userId: string): Promise => {
const { data } = await axios.get(
`${api_url}/tasks/assigned?userIDs=${userId}`
From dec424fdcca0ff052d6af236885d4b313b3718c0 Mon Sep 17 00:00:00 2001
From: Chris <125088905+wyattchris@users.noreply.github.com>
Date: Wed, 3 Apr 2024 16:38:37 -0400
Subject: [PATCH 6/8] refactor(styling-+-navigation): styling + navigation
---
client/assets/arrow-left.svg | 4 +--
client/components/ChooseFileButton.tsx | 7 ++++-
client/components/nav_buttons/BackButton.tsx | 4 +--
.../navigation/AppStackBottomTabNavigator.tsx | 6 ++++
client/screens/FileUpload.tsx | 29 ++++++++++---------
client/screens/Profile/PatientView.tsx | 9 +++++-
package.json | 6 ----
7 files changed, 39 insertions(+), 26 deletions(-)
delete mode 100644 package.json
diff --git a/client/assets/arrow-left.svg b/client/assets/arrow-left.svg
index 7a7d75d..54e84eb 100644
--- a/client/assets/arrow-left.svg
+++ b/client/assets/arrow-left.svg
@@ -1,4 +1,4 @@
diff --git a/client/components/ChooseFileButton.tsx b/client/components/ChooseFileButton.tsx
index b0c7354..5f0db8b 100644
--- a/client/components/ChooseFileButton.tsx
+++ b/client/components/ChooseFileButton.tsx
@@ -1,13 +1,18 @@
import React from 'react';
import { Text, TouchableOpacity } from 'react-native';
+import Upload from '../assets/profile/upload.svg';
+
export function ChooseFileButton({ onPress }: { onPress: () => void }) {
return (
- Choose File
+
+
+ CHOOSE FILE
+
);
}
diff --git a/client/components/nav_buttons/BackButton.tsx b/client/components/nav_buttons/BackButton.tsx
index a73de7b..1ce4968 100644
--- a/client/components/nav_buttons/BackButton.tsx
+++ b/client/components/nav_buttons/BackButton.tsx
@@ -11,9 +11,9 @@ export function BackButton() {
return (
}
+ icon={() => }
onPress={() => navigation.goBack()}
/>
);
diff --git a/client/navigation/AppStackBottomTabNavigator.tsx b/client/navigation/AppStackBottomTabNavigator.tsx
index 44a4d6d..0efe99d 100644
--- a/client/navigation/AppStackBottomTabNavigator.tsx
+++ b/client/navigation/AppStackBottomTabNavigator.tsx
@@ -9,6 +9,7 @@ import Calendar from '../assets/bottom-nav/calendar.svg';
import HomeIcon from '../assets/bottom-nav/home.svg';
import User from '../assets/bottom-nav/user.svg';
import TimelineCalendarScreen from '../screens/Calendar';
+import FileUploadScreen from '../screens/FileUpload';
import Home from '../screens/Home';
import PatientView from '../screens/Profile/PatientView';
import Profile from '../screens/Profile/Profile';
@@ -89,6 +90,11 @@ export function ProfileNavigation() {
options={{ headerShown: false }}
component={Settings}
/>
+
);
}
diff --git a/client/screens/FileUpload.tsx b/client/screens/FileUpload.tsx
index 77d0edd..abb3bfb 100644
--- a/client/screens/FileUpload.tsx
+++ b/client/screens/FileUpload.tsx
@@ -90,31 +90,31 @@ export default function FileUploadScreen() {
// TODO: Choosefile border color, dropdown styling, fonts, choose file svg
return (
-
-
+
+
-
-
- File Upload
+
+
+ Upload File
-
- File Title
+
+ FILE TITLE
-
- File Label
+
+ FILE LABEL
-
- Additional Notes
+
+ ADDITIONAL NOTES
-
+
Submit
diff --git a/client/screens/Profile/PatientView.tsx b/client/screens/Profile/PatientView.tsx
index 3eb90ea..afdbb25 100644
--- a/client/screens/Profile/PatientView.tsx
+++ b/client/screens/Profile/PatientView.tsx
@@ -1,12 +1,15 @@
import React from 'react';
import { Pressable, Text, View } from 'react-native';
+import { useNavigation } from '@react-navigation/native';
+
import FileDock from '../../assets/profile/filedock.svg';
import Upload from '../../assets/profile/upload.svg';
import { Header } from '../../components/profile/Header';
import { HealthStats } from '../../components/profile/HealthStats';
import { PatientHeader } from '../../components/profile/PatientHeader';
import { useCareWalletContext } from '../../contexts/CareWalletContext';
+import { AppStackNavigation } from '../../navigation/types';
import { useGroup } from '../../services/group';
import { useUsers } from '../../services/user';
import { Role } from '../../types/group';
@@ -16,6 +19,7 @@ export default function PatientView() {
const { roles } = useGroup(group.groupID);
const { users } = useUsers(roles?.map((role) => role.user_id) ?? []);
const patientId = roles?.find((role) => role.role === Role.PATIENT)?.user_id;
+ const navigation = useNavigation();
return (
@@ -31,7 +35,10 @@ export default function PatientView() {
-
+ navigation.navigate('FileUploadScreen')}
+ className="ml-10 mt-5 flex h-10 w-[38vw] flex-row items-center justify-center space-x-2 rounded-lg border border-carewallet-lightgray bg-carewallet-white"
+ >
Upload Files
diff --git a/package.json b/package.json
deleted file mode 100644
index 284b17d..0000000
--- a/package.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "dependencies": {
- "@expo-google-fonts/manrope": "^0.2.3",
- "@expo-google-fonts/montserrat": "^0.2.3"
- }
-}
From e617922e89545d4ef5bf781b0f9154a83cfa73d3 Mon Sep 17 00:00:00 2001
From: Matt McCoy
Date: Wed, 3 Apr 2024 19:11:18 -0400
Subject: [PATCH 7/8] fix: show image on select, virtualized list error
---
client/assets/filledarrowdown.svg | 3 ++
client/components/ChooseFileButton.tsx | 40 +++++++++++++---
client/components/Dropdown.tsx | 64 ++++++++++++++++++++++++++
client/screens/FileUpload.tsx | 44 ++++++------------
4 files changed, 113 insertions(+), 38 deletions(-)
create mode 100644 client/assets/filledarrowdown.svg
create mode 100644 client/components/Dropdown.tsx
diff --git a/client/assets/filledarrowdown.svg b/client/assets/filledarrowdown.svg
new file mode 100644
index 0000000..f9611b3
--- /dev/null
+++ b/client/assets/filledarrowdown.svg
@@ -0,0 +1,3 @@
+
diff --git a/client/components/ChooseFileButton.tsx b/client/components/ChooseFileButton.tsx
index 5f0db8b..d317ddb 100644
--- a/client/components/ChooseFileButton.tsx
+++ b/client/components/ChooseFileButton.tsx
@@ -1,18 +1,44 @@
import React from 'react';
-import { Text, TouchableOpacity } from 'react-native';
+import { Dimensions, Image, Text, TouchableOpacity, View } from 'react-native';
+
+import { clsx } from 'clsx';
+import { DocumentPickerAsset } from 'expo-document-picker';
import Upload from '../assets/profile/upload.svg';
-export function ChooseFileButton({ onPress }: { onPress: () => void }) {
+export function ChooseFileButton({
+ onPress,
+ picked
+}: {
+ onPress: () => void;
+ picked: DocumentPickerAsset | null;
+}) {
return (
-
-
- CHOOSE FILE
-
+ {picked ? (
+
+
+
+ ) : (
+ <>
+
+
+ CHOOSE FILE
+
+ >
+ )}
);
}
diff --git a/client/components/Dropdown.tsx b/client/components/Dropdown.tsx
new file mode 100644
index 0000000..02461bc
--- /dev/null
+++ b/client/components/Dropdown.tsx
@@ -0,0 +1,64 @@
+import React, { useState } from 'react';
+import { Text, View } from 'react-native';
+
+import { clsx } from 'clsx';
+
+import ArrowDown from '../assets/filledarrowdown.svg';
+
+export function CWDropdown({
+ selected,
+ items,
+ setLabel
+}: {
+ selected: string;
+ items?: string[];
+ setLabel: (label: string) => void;
+}) {
+ const [isOpen, setIsOpen] = useState(false);
+ return (
+
+ setIsOpen(!isOpen)}
+ >
+
+ {selected}
+
+
+ {isOpen ? (
+
+
+
+ ) : (
+
+ )}
+
+
+
+ {isOpen && (
+
+ {items?.map(
+ (item, index) =>
+ item !== selected && (
+ {
+ setLabel(item);
+ setIsOpen(false);
+ }}
+ >
+
+ {item}
+
+
+ )
+ )}
+
+ )}
+
+ );
+}
diff --git a/client/screens/FileUpload.tsx b/client/screens/FileUpload.tsx
index abb3bfb..8e5c548 100644
--- a/client/screens/FileUpload.tsx
+++ b/client/screens/FileUpload.tsx
@@ -8,9 +8,9 @@ import {
} from 'react-native';
import { DocumentPickerAsset, getDocumentAsync } from 'expo-document-picker';
-import DropDownPicker from 'react-native-dropdown-picker';
import { ChooseFileButton } from '../components/ChooseFileButton';
+import { CWDropdown } from '../components/Dropdown';
import { BackButton } from '../components/nav_buttons/BackButton';
import { useCareWalletContext } from '../contexts/CareWalletContext';
import { useFile } from '../services/file';
@@ -19,7 +19,6 @@ import { getLabelsByGroup } from '../services/task';
export default function FileUploadScreen() {
const { user, group } = useCareWalletContext();
const { uploadFileMutation } = useFile();
- const [open, setOpen] = useState(false);
const [fileTitle, setFileTitle] = useState('');
const [label, setLabel] = useState('Financial');
const [additionalNotes, setAdditionalNotes] = useState('');
@@ -27,7 +26,6 @@ export default function FileUploadScreen() {
null
);
const [allLabels, setAllLabels] = useState([]); // Store all unique labels as a list of strings
- DropDownPicker.setTheme('DARK');
// Fetch all labels by the group id
useEffect(() => {
@@ -87,10 +85,9 @@ export default function FileUploadScreen() {
}
};
- // TODO: Choosefile border color, dropdown styling, fonts, choose file svg
return (
-
-
+
+
@@ -99,7 +96,7 @@ export default function FileUploadScreen() {
-
+
@@ -113,36 +110,21 @@ export default function FileUploadScreen() {
/>
-
+
FILE LABEL
- ({
- label,
- value: label
- }))}
- setOpen={setOpen}
- setValue={setLabel}
- placeholder="Select Label"
- style={{
- backgroundColor: '#1A56C4',
- borderColor: 'transparent'
- }}
- textStyle={{
- fontFamily: 'Manrope_400Regular',
- color: 'white'
- }}
- disabledStyle={{
- opacity: 0.5
- }}
- />
+
+
+
-
+
ADDITIONAL NOTES
Date: Wed, 3 Apr 2024 19:38:40 -0400
Subject: [PATCH 8/8] fix: allow a label to not have to be selected
---
backend/db/migrations/5.files.sql | 5 ++---
client/screens/FileUpload.tsx | 36 ++++++++++---------------------
client/services/label.ts | 27 +++++++++++++++++++++++
client/services/task.ts | 11 ++--------
4 files changed, 42 insertions(+), 37 deletions(-)
create mode 100644 client/services/label.ts
diff --git a/backend/db/migrations/5.files.sql b/backend/db/migrations/5.files.sql
index 0c7ac28..ae14204 100644
--- a/backend/db/migrations/5.files.sql
+++ b/backend/db/migrations/5.files.sql
@@ -9,10 +9,9 @@ CREATE TABLE IF NOT EXISTS files (
file_size integer NOT NULL,
task_id integer,
notes varchar,
- label_name varchar NOT NULL,
+ label_name varchar,
PRIMARY KEY (file_id),
FOREIGN KEY (group_id) REFERENCES care_group (group_id),
FOREIGN KEY (upload_by) REFERENCES users (user_id),
- FOREIGN KEY (task_id) REFERENCES task (task_id),
- FOREIGN KEY (group_id, label_name) REFERENCES label (group_id, label_name)
+ FOREIGN KEY (task_id) REFERENCES task (task_id)
);
diff --git a/client/screens/FileUpload.tsx b/client/screens/FileUpload.tsx
index 8e5c548..6ed2249 100644
--- a/client/screens/FileUpload.tsx
+++ b/client/screens/FileUpload.tsx
@@ -1,4 +1,4 @@
-import React, { useEffect, useState } from 'react';
+import React, { useState } from 'react';
import {
ScrollView,
Text,
@@ -14,37 +14,18 @@ import { CWDropdown } from '../components/Dropdown';
import { BackButton } from '../components/nav_buttons/BackButton';
import { useCareWalletContext } from '../contexts/CareWalletContext';
import { useFile } from '../services/file';
-import { getLabelsByGroup } from '../services/task';
+import { useLabelsByGroup } from '../services/label';
export default function FileUploadScreen() {
const { user, group } = useCareWalletContext();
const { uploadFileMutation } = useFile();
const [fileTitle, setFileTitle] = useState('');
- const [label, setLabel] = useState('Financial');
+ const [label, setLabel] = useState('Select Label');
const [additionalNotes, setAdditionalNotes] = useState('');
const [pickedFile, setPickedFile] = useState(
null
);
- const [allLabels, setAllLabels] = useState([]); // Store all unique labels as a list of strings
-
- // Fetch all labels by the group id
- useEffect(() => {
- const fetchLabels = async () => {
- try {
- console.log('Group:', group);
- const labels = await getLabelsByGroup(group.groupID);
- const uniqueLabels = Array.from(
- new Set(labels.map((label) => label.label_name))
- );
- setAllLabels(uniqueLabels);
- console.log('Labels:', allLabels);
- } catch (error) {
- console.error('Error fetching labels:', error);
- }
- };
-
- fetchLabels();
- }, [group]);
+ const { labels } = useLabelsByGroup(group.groupID);
const handleFileTitleChange = (text: string) => {
setFileTitle(text);
@@ -76,9 +57,14 @@ export default function FileUploadScreen() {
file: pickedFile,
userId: user.userID,
groupId: group.groupID,
- label: label,
+ label: label === 'Select Label' ? '' : label,
notes: additionalNotes
});
+
+ setFileTitle('');
+ setLabel('Select Label');
+ setAdditionalNotes('');
+ setPickedFile(null);
}
} catch (err) {
console.log('err', err);
@@ -116,7 +102,7 @@ export default function FileUploadScreen() {
label.label_name)}
setLabel={setLabel}
/>
diff --git a/client/services/label.ts b/client/services/label.ts
new file mode 100644
index 0000000..ae15706
--- /dev/null
+++ b/client/services/label.ts
@@ -0,0 +1,27 @@
+import { useQuery } from '@tanstack/react-query';
+import axios from 'axios';
+
+import { TaskLabel } from '../types/label';
+import { api_url } from './api-links';
+
+// This is used to get unique labels used by a group it should not be used for fetching labels for a task or other items
+const getLabelsByGroup = async (groupID: number): Promise => {
+ const { data } = await axios.get(`${api_url}/group/${groupID}/labels`);
+
+ const uniques = (data as TaskLabel[]).filter((item, index, self) => {
+ return (
+ self.findIndex((obj) => obj.label_name === item.label_name) === index
+ );
+ });
+
+ return uniques;
+};
+
+export const useLabelsByGroup = (groupID: number) => {
+ const { data: labels, isLoading: labelsIsLoading } = useQuery({
+ queryKey: ['labels', groupID],
+ queryFn: () => getLabelsByGroup(groupID)
+ });
+
+ return { labels, labelsIsLoading };
+};
diff --git a/client/services/task.ts b/client/services/task.ts
index 367593f..44dcdb8 100644
--- a/client/services/task.ts
+++ b/client/services/task.ts
@@ -21,13 +21,6 @@ const getTask = async (taskID: string): Promise => {
return data;
};
-export const getLabelsByGroup = async (
- groupID: number
-): Promise => {
- const { data } = await axios.get(`${api_url}/group/${groupID}/labels`);
- return data;
-};
-
const getTaskByAssigned = async (userId: string): Promise => {
const { data } = await axios.get(
`${api_url}/tasks/assigned?userIDs=${userId}`
@@ -112,7 +105,7 @@ export const addNewTaskMutation = () => {
const { mutate: addTaskMutation } = useMutation({
mutationFn: (newTask: Task) => addNewTask(newTask),
onSuccess: () => {
- queryClient.invalidateQueries('filteredTaskList');
+ queryClient.invalidateQueries({ queryKey: ['filteredTaskList'] });
},
onError: (err) => {
console.error('ERROR: Failed to Add Task. Code:', err);
@@ -134,7 +127,7 @@ export const editTaskMutation = () => {
updatedTask: Task;
}) => editTask(taskId, updatedTask),
onSuccess: () => {
- queryClient.invalidateQueries('filteredTaskList');
+ queryClient.invalidateQueries({ queryKey: ['filteredTaskList'] });
},
onError: (err) => {
console.error('ERROR: Failed to Edit Task. Code:', err);