diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..d7bc79c Binary files /dev/null and b/.DS_Store differ diff --git a/backend/controllers/issueController.js b/backend/controllers/issueController.js index dcbb96d..af21949 100644 --- a/backend/controllers/issueController.js +++ b/backend/controllers/issueController.js @@ -101,12 +101,14 @@ export const createGeneralPrinciple = async (req, res) => { } // Extract data from the request body - const { title, overview, content } = req.body; + const { title, overview, bullet, subtitle, content } = req.body; // Create a new GeneralPrinciple instance const newGeneralPrinciple = new GeneralPrinciple({ title, overview, + bullet, + subtitle, content, }); diff --git a/backend/controllers/versionController.js b/backend/controllers/versionController.js index 5405ddb..5e54e5c 100644 --- a/backend/controllers/versionController.js +++ b/backend/controllers/versionController.js @@ -1,5 +1,6 @@ import { Version } from "../models/versionModel.js"; import { Emergency, GeneralPrinciple } from "../models/issueModel.js"; +import { Category } from "../models/categoryModel.js"; export const getVersion = async (req, res) => { try { @@ -35,8 +36,9 @@ export const getAllWithVersion = async (req, res) => { try { const emergencies = await Emergency.find(); const generalPrinciples = await GeneralPrinciple.find(); + const categories = await Category.find(); const version = await Version.find(); - res.json({ version, emergencies, generalPrinciples }); + res.json({ version, emergencies, generalPrinciples, categories }); } catch (error) { res.status(500).json({ error: error.message }); } diff --git a/backend/models/issueModel.js b/backend/models/issueModel.js index 150fc1a..0ac3e48 100644 --- a/backend/models/issueModel.js +++ b/backend/models/issueModel.js @@ -4,12 +4,11 @@ const medicalEmergencySchema = new mongoose.Schema({ title: String, overview: {}, treatment: {}, - content: {}, }); const generalPrincipleSchema = new mongoose.Schema({ title: String, - overview: {}, + subtitle: String, content: {}, }); diff --git a/dfm-sideline-sidekick-app/%ProgramData%/Microsoft/Windows/UUS/State/_active.uusver b/dfm-sideline-sidekick-app/%ProgramData%/Microsoft/Windows/UUS/State/_active.uusver new file mode 100644 index 0000000..263a6a8 --- /dev/null +++ b/dfm-sideline-sidekick-app/%ProgramData%/Microsoft/Windows/UUS/State/_active.uusver @@ -0,0 +1 @@ +1214.2401.18012.1 \ No newline at end of file diff --git a/dfm-sideline-sidekick-app/App.tsx b/dfm-sideline-sidekick-app/App.tsx index 45b89f1..eb37a4e 100644 --- a/dfm-sideline-sidekick-app/App.tsx +++ b/dfm-sideline-sidekick-app/App.tsx @@ -7,10 +7,12 @@ import React from "react"; import { StyleSheet } from "react-native"; import AppInitializer from "./AppInitializer"; -import { DataProvider } from "./DataContext"; import { BottomNavBar, NavItem } from "./components/bar"; +import ViewAll from "./components/viewAll"; +import { DataProvider } from "./functions/DataContext"; import ConditionsSection from "./pages/ConditionsSection"; import HomePage from "./pages/HomePage"; +import MainPrinciples from "./pages/MainPrinciples"; import SearchPage from "./pages/SearchPage"; // import TabPage from "./pages/TabPage"; import GeneralPrinciples from "./pages/generalPrinciples"; @@ -28,10 +30,13 @@ type DocumentBase = { type RootStackParamList = { Home: undefined; Search: undefined; + ViewAll: undefined; GPM: undefined; Tab: undefined; MedicalConditions: { emergency: DocumentBase }; GeneralPrinciples: { contentProp: DocumentBase }; + EmergencyPrinciples: { generalPrinciple: DocumentBase }; + MainPrinciples: { generalPrinciple: DocumentBase }; }; type StackNavigation = StackNavigationProp; @@ -75,9 +80,14 @@ export default function App() { - + - + + + diff --git a/dfm-sideline-sidekick-app/AppInitializer.tsx b/dfm-sideline-sidekick-app/AppInitializer.tsx index 0cbee56..cde842d 100644 --- a/dfm-sideline-sidekick-app/AppInitializer.tsx +++ b/dfm-sideline-sidekick-app/AppInitializer.tsx @@ -1,9 +1,10 @@ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ +/* eslint-disable @typescript-eslint/no-unsafe-argument */ import { useEffect } from "react"; import { Platform } from "react-native"; -import { useData } from "./DataContext"; -import { checkConnection } from "./download/connection/checkConnection"; import { downloadJSON } from "./download/downloadFromAPI"; +import { useData } from "./functions/DataContext"; function AppInitializer() { const { updateJsonData } = useData(); @@ -11,32 +12,22 @@ function AppInitializer() { const deviceType = Platform.OS; // makes it so that it only checks the version once per app launch - let attempted = false; // true when there's connection - let connected = false; // checks on app open, connect change useEffect(() => { - // stores if connected - console.log("ATTEMPTED BEFORE:", attempted); - async function matchConditions() { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - connected = await checkConnection(); // if also connected, attempt to redownload - if (connected && !attempted) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const jsonData = await downloadJSON("data.json", deviceType); - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - updateJsonData(jsonData); - - attempted = true; // latches - } + let jsonData = await downloadJSON("data.json", deviceType, false); + updateJsonData(jsonData); + + jsonData = await downloadJSON("data.json", deviceType, true); + updateJsonData(jsonData); } void matchConditions(); - }, [connected]); + }, []); return null; } diff --git a/dfm-sideline-sidekick-app/HomeScreen.tsx b/dfm-sideline-sidekick-app/HomeScreen.tsx deleted file mode 100644 index a2dc2c6..0000000 --- a/dfm-sideline-sidekick-app/HomeScreen.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { useNavigation } from "@react-navigation/native"; -import { useEffect, useState } from "react"; -import { Pressable, Text } from "react-native"; - -import { getEmergency } from "./emergencies"; - -export default function HomeScreen() { - const navigation = useNavigation(); - const [emergency, setEmergency] = useState(null); - - useEffect(() => { - async function fetchEmergency() { - try { - //It seems to work on Android and iPad - //Test Case: Cervical Spine Injury - demonstrate recursive rendering - const emergencyObjectId = "65b36d110c9c60394b37f7a1"; - //Separate Test Case here: To Be Deleted Emergency - demonstrates textual rendering - //const emergencyObjectId = "65b369a8e8fe96a404d4fd6b"; - //Test Case: New Emergency Placeholder Four - demonstrates blank rendering (only title in db) - //const emergencyObjectId = "65c2ef26b87b638ac61beb09"; - //Test Case: Cervical Strain - demonstrates simple placeholder headers - //const emergencyObjectId = "65b36f12640d62464e0dd129"; - const result = await getEmergency(emergencyObjectId); - if (result.success) { - setEmergency(result.data); - } else { - console.error("Error fetching emergency data:", result.error); - } - } catch (error) { - console.error("Error fetching emergency data:", error); - } - } - - void fetchEmergency(); - }, []); - - const handlePress = () => { - if (emergency !== null) { - navigation.navigate("Conditions", { emergency }); - } - }; - - return ( - - Navigate to ConditionsSection - - ); -} diff --git a/dfm-sideline-sidekick-app/app.json b/dfm-sideline-sidekick-app/app.json index 6599919..8db64fe 100644 --- a/dfm-sideline-sidekick-app/app.json +++ b/dfm-sideline-sidekick-app/app.json @@ -2,7 +2,7 @@ "expo": { "name": "dfm-sideline-sidekick-app", "slug": "dfm-sideline-sidekick-app", - "version": "1.0.0", + "version": "1.1.0", "orientation": "portrait", "icon": "./assets/icon.png", "userInterfaceStyle": "light", @@ -13,16 +13,23 @@ }, "assetBundlePatterns": ["**/*"], "ios": { - "supportsTablet": true + "supportsTablet": true, + "bundleIdentifier": "dfmsidelinesidekickapp" }, "android": { "adaptiveIcon": { "foregroundImage": "./assets/adaptive-icon.png", "backgroundColor": "#ffffff" - } + }, + "package": "com.anthonyp0329.dfmsidelinesidekickapp" }, "web": { "favicon": "./assets/favicon.png" + }, + "extra": { + "eas": { + "projectId": "81d4d973-577a-4924-aa62-1a57fda7e880" + } } } } diff --git a/dfm-sideline-sidekick-app/assets/icon.png b/dfm-sideline-sidekick-app/assets/icon.png index a0b1526..1900c04 100644 Binary files a/dfm-sideline-sidekick-app/assets/icon.png and b/dfm-sideline-sidekick-app/assets/icon.png differ diff --git a/dfm-sideline-sidekick-app/components/ArrayPage.tsx b/dfm-sideline-sidekick-app/components/ArrayPage.tsx deleted file mode 100644 index b9bf519..0000000 --- a/dfm-sideline-sidekick-app/components/ArrayPage.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { Roboto_400Regular, Roboto_700Bold } from "@expo-google-fonts/roboto"; -import { useNavigation } from "@react-navigation/native"; -import { StackNavigationProp } from "@react-navigation/stack"; -import { useFonts } from "expo-font"; -import React from "react"; -import { FlatList, Text, TouchableOpacity, View } from "react-native"; -import Icon from "react-native-vector-icons/FontAwesome"; - -import styles from "./ArrayPageStyles"; - -type ContentItem = Record; - -type Content = { - title: string; - content: ContentItem; -}; - -export type RootStackParamList = { - GeneralPrinciples: { titleProp: string; contentProp: Content } | undefined; -}; - -type ArrayProps = { - arrayProp: Content[]; - title: string; -}; - -const temp = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor."; - -const ArrayPage: React.FC = ({ arrayProp, title }) => { - const navigation = useNavigation>(); - - const [fontsLoaded] = useFonts({ - "Roboto-Regular": Roboto_400Regular, - "Roboto-Bold": Roboto_700Bold, - }); - if (!fontsLoaded) { - return Loading...; - } - - const handleItemPress = (item: Content) => { - navigation.navigate("GeneralPrinciples", { titleProp: item.title, contentProp: item }); - }; - - const renderListItem = ({ item, index }: { item: Content; index: number }) => ( - { - handleItemPress(item); - }} - > - - {index + 1} - - {item.title} - {temp} - - - - - ); - - return ( - - - { - navigation.goBack(); - }} - style={styles.backButtonContainer} - > - - - {title} - item.title} - ItemSeparatorComponent={() => } - renderItem={renderListItem} - /> - - - ); -}; - -export default ArrayPage; diff --git a/dfm-sideline-sidekick-app/components/ArrayPageStyles.tsx b/dfm-sideline-sidekick-app/components/ArrayPageStyles.tsx deleted file mode 100644 index 8b6ae9d..0000000 --- a/dfm-sideline-sidekick-app/components/ArrayPageStyles.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { StyleSheet } from "react-native"; - -const styles = StyleSheet.create({ - container: { - // flex: 1, - // padding: 10, - }, - backButtonContainer: { - paddingTop: 20, - paddingBottom: 20, - }, - backButton: { - fontSize: 16, - }, - title: { - color: "#182B49", - fontSize: 28, - fontFamily: "Roboto-Bold", - fontWeight: "700", - marginBottom: 20, - textAlign: "left", - paddingTop: 10, - }, - listItemContainer: { - flexDirection: "row", - alignItems: "center", - paddingVertical: 8, - }, - enumeration: { - marginRight: 8, - fontSize: 40, - paddingRight: 10, - }, - listItemTextContainer: { - flex: 1, - }, - listItemTitle: { - fontSize: 18, - fontWeight: "500", - paddingBottom: 10, - }, - listItemSubtitle: { - fontSize: 13, - color: "grey", - }, - divider: { - height: 1, - backgroundColor: "lightgrey", - marginVertical: 10, - marginRight: 15, - marginLeft: 35, - }, -}); -export default styles; diff --git a/dfm-sideline-sidekick-app/components/BulletRenderer.tsx b/dfm-sideline-sidekick-app/components/BulletRenderer.tsx new file mode 100644 index 0000000..ae565d4 --- /dev/null +++ b/dfm-sideline-sidekick-app/components/BulletRenderer.tsx @@ -0,0 +1,70 @@ +import React from "react"; +import { Text, View } from "react-native"; + +import styles from "./BulletRendererStyles"; + +type StringValue = string | string[] | { [key: string]: StringValue } | undefined; + +type Props = { + data: StringValue; + level: number; +}; + +const renderSubpoint = (subpoint: string, index = 0, level = 0) => { + // const subpoints = subpointsString.split("\n"); + + const markers = [ + ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], // Level 0 markers + ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"], // Level 1 markers + ["i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix", "x"], // Level 2 markers + ]; + + // ensure the level has defined markers, if not, default to numeric + const currentMarkers = markers[level] || markers[0]; + + return ( + + + {`${currentMarkers[index % currentMarkers.length]}. `} + {subpoint} + + {/* {subpoint.subpoints && ( + {renderSubpoints(subpoint.subpoints, level + 1)} + )} */} + + ); +}; + +const BulletList: React.FC<{ items: string[]; level: number }> = ({ items, level }) => ( + + {items.map((item: string, index: number) => ( + + {/* {"\u2022"} + {item} */} + {item && renderSubpoint(item, index, level)} + + ))} + +); + +const BulletRenderer: React.FC = ({ data, level }) => { + if (Array.isArray(data) && data.every((item) => typeof item === "string")) { + return ; + } else if (typeof data === "object") { + return ( + + {Object.keys(data).map((key, index) => ( + + {key && renderSubpoint(key, index, level)} + {/* {key} */} + {/* {key && renderSubpoint(key, index, level)} */} + + + ))} + + ); + } + return null; +}; + +export default BulletRenderer; diff --git a/dfm-sideline-sidekick-app/components/BulletRendererStyles.tsx b/dfm-sideline-sidekick-app/components/BulletRendererStyles.tsx new file mode 100644 index 0000000..fc3f42d --- /dev/null +++ b/dfm-sideline-sidekick-app/components/BulletRendererStyles.tsx @@ -0,0 +1,166 @@ +import { StyleSheet } from "react-native"; + +const styles = StyleSheet.create({ + container: { + flexDirection: "row", + alignItems: "center", + paddingTop: 15, + }, + circle: { + width: 24, // this should be a "props"-value in future + height: 24, // this should be a "props"-value in future + borderRadius: 24 / 2, + backgroundColor: "#00629B", + alignItems: "center", + justifyContent: "center", + }, + + circleCaption: { + fontSize: 14, + color: "white", + fontWeight: "600", + }, + mainText: { + color: "black", + fontSize: 16, + fontFamily: "Roboto-Bold", + fontWeight: "700", + paddingLeft: 7, + paddingRight: 27, + }, + subpoints: { + paddingTop: 5, + paddingLeft: 38, + paddingRight: 25, + fontFamily: "Roboto-Regular", + }, + point: { + fontSize: 15, + fontFamily: "Roboto-Regular", + }, + // container: { + // flex: 1, + // backgroundColor: "#fff", + // alignItems: "flex-start", + // justifyContent: "center", + // ...Platform.select({ + // ios: { + // paddingTop: 80, + // }, + // android: { + // paddingTop: 40, + // }, + // default: { + // paddingTop: 50, + // }, + // }), + // }, + margin: { + marginLeft: 16, + marginTop: 20, + }, + menu: { + display: "flex", + flexDirection: "row", + alignItems: "flex-start", + justifyContent: "space-evenly", + width: "100%", + marginTop: 16, + }, + topRightContainer: { + position: "absolute", + top: 80, + right: 0, + padding: 10, + zIndex: 1, + }, + menuText: { + fontFamily: "Roboto-Regular", + fontSize: 16, + color: "#000000", + textAlign: "left", + marginLeft: 16, + }, + menuButton: { + borderBottomWidth: 3, + borderColor: "#D5D5D5", + width: "50%", + }, + menuButtonSelected: { + borderBottomWidth: 3, + borderColor: "#000000", + width: "50%", + }, + menuTextSelected: { + fontFamily: "Roboto-Bold", + fontSize: 16, + color: "#000000", + textAlign: "left", + marginLeft: 16, + }, + subtitle: { + fontFamily: "Roboto-Bold", + fontSize: 18, + color: "#00629B", + marginLeft: 2, + }, + title: { + fontFamily: "Roboto-Bold", + fontSize: 32, + color: "#182B49", + marginLeft: 2, + }, + image: { + width: 24, + height: 24, + marginLeft: 16, + marginBottom: 22, + }, + information: { + marginLeft: 16, + marginTop: 0, + marginRight: 16, + }, + overview: {}, + howToTreat: {}, + overviewHidden: { + display: "none", + }, + howToTreatHidden: { + display: "none", + }, + descriptionTitle: { + fontFamily: "Roboto-Bold", + fontSize: 18, + color: "#000000", + }, + descriptionInfo: { + marginTop: 5, + fontFamily: "Roboto-Regular", + fontSize: 16, + color: "#000000", + }, + infoSection: { + marginTop: 15, + }, + list: { + paddingLeft: 10, + marginRight: 50, + marginTop: 5, + }, + listItem: { + flexDirection: "row", + }, + bullet: { + marginRight: 5, + fontSize: 18, + color: "#000000", + }, + itemText: { + fontSize: 16, + fontFamily: "Roboto-Regular", + color: "#000000", + }, +}); + +export default styles; diff --git a/dfm-sideline-sidekick-app/components/NumbersSection.tsx b/dfm-sideline-sidekick-app/components/NumbersSection.tsx new file mode 100644 index 0000000..e126e10 --- /dev/null +++ b/dfm-sideline-sidekick-app/components/NumbersSection.tsx @@ -0,0 +1,24 @@ +import PropTypes from "prop-types"; +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import React from "react"; +import { Text, View } from "react-native"; + +import styles from "./NumbersSectionStyles"; + +type Props = { + property1: number; +}; + +export const NumbersSection = ({ property1 }: Props): JSX.Element => { + return ( + + + {<>{property1}} + + + ); +}; + +NumbersSection.propTypes = { + property1: PropTypes.oneOf([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]), +}; diff --git a/dfm-sideline-sidekick-app/components/NumbersSectionStyles.tsx b/dfm-sideline-sidekick-app/components/NumbersSectionStyles.tsx new file mode 100644 index 0000000..bcf85b2 --- /dev/null +++ b/dfm-sideline-sidekick-app/components/NumbersSectionStyles.tsx @@ -0,0 +1,33 @@ +import { StyleSheet } from "react-native"; + +const styles = StyleSheet.create({ + container: { + flexDirection: "row", + alignItems: "center", + paddingTop: 15, + }, + numbersSection: { + height: 50, + position: "relative", + width: 50, + }, + numbersSectionElement: { + color: "--dfm-navy", + fontSize: 32, + fontWeight: 400, + left: 0, + letterSpacing: 0.64, + lineHeight: 48, + position: "absolute", + top: -1, + whitespace: "nowrap", + width: 40, + }, + numbersSectionText: { + fontSize: 32, + fontWeight: "400", + color: "rgba(24, 43, 73, 1)", + }, +}); + +export default styles; diff --git a/dfm-sideline-sidekick-app/SearchBarComponent.tsx b/dfm-sideline-sidekick-app/components/SearchBarComponent.tsx similarity index 93% rename from dfm-sideline-sidekick-app/SearchBarComponent.tsx rename to dfm-sideline-sidekick-app/components/SearchBarComponent.tsx index 3060f7d..040a17e 100644 --- a/dfm-sideline-sidekick-app/SearchBarComponent.tsx +++ b/dfm-sideline-sidekick-app/components/SearchBarComponent.tsx @@ -36,6 +36,8 @@ const SearchBar: React.FC = ({ value={query} onChangeText={setQuery} onFocus={onFocus} + // eslint-disable-next-line jsx-a11y/no-autofocus + autoFocus={isFocused} onBlur={onBlur} selectionColor="#909090" /> diff --git a/dfm-sideline-sidekick-app/SearchBarStyles.tsx b/dfm-sideline-sidekick-app/components/SearchBarStyles.tsx similarity index 100% rename from dfm-sideline-sidekick-app/SearchBarStyles.tsx rename to dfm-sideline-sidekick-app/components/SearchBarStyles.tsx diff --git a/dfm-sideline-sidekick-app/components/StringRenderer.tsx b/dfm-sideline-sidekick-app/components/StringRenderer.tsx index d211d08..7532cb6 100644 --- a/dfm-sideline-sidekick-app/components/StringRenderer.tsx +++ b/dfm-sideline-sidekick-app/components/StringRenderer.tsx @@ -30,7 +30,7 @@ const StringRenderer: React.FC = ({ data }) => { {Object.keys(data).map((key, index) => ( - {key} + {key} ))} diff --git a/dfm-sideline-sidekick-app/components/bar.tsx b/dfm-sideline-sidekick-app/components/bar.tsx index 2bccbd2..579704a 100644 --- a/dfm-sideline-sidekick-app/components/bar.tsx +++ b/dfm-sideline-sidekick-app/components/bar.tsx @@ -3,9 +3,9 @@ import React, { useEffect, useState } from "react"; import { TouchableOpacity, View } from "react-native"; // import { BookmarkIcon } from "../icons/bookmarkIcon"; -import { HomeIcon } from "../icons/homeIcon"; import { CircleIcon } from "../icons/circleIcon"; import { GeneralPrinciplesIcon } from "../icons/generalPrinciplesIcon"; +import { HomeIcon } from "../icons/homeIcon"; import styles from "./barStyles"; @@ -17,7 +17,7 @@ export type NavItem = { }; export const BottomNavBar: React.FC<{ items: NavItem[] }> = ({ items }) => { - const [selectedItemId, setSelectedItemId] = useState(2); + const [selectedItemId, setSelectedItemId] = useState(1); const currentRouteName = useNavigationState((state) => { if (state !== undefined && state !== null) { return state.routes[state.index].name; @@ -47,7 +47,7 @@ export const BottomNavBar: React.FC<{ items: NavItem[] }> = ({ items }) => { > {item.icon === "search" ? ( - + ) : item.icon === "home" ? ( diff --git a/dfm-sideline-sidekick-app/components/barStyles.tsx b/dfm-sideline-sidekick-app/components/barStyles.tsx index 4cb63f1..725c786 100644 --- a/dfm-sideline-sidekick-app/components/barStyles.tsx +++ b/dfm-sideline-sidekick-app/components/barStyles.tsx @@ -5,13 +5,21 @@ const styles = StyleSheet.create({ flexDirection: "row", justifyContent: "space-around", alignItems: "center", - backgroundColor: "#f0f0f0", + backgroundColor: "#ffffff", padding: 8, position: "absolute", bottom: 0, left: 0, right: 0, height: 79, + elevation: 10, + + shadowColor: "rgba(0, 0, 0, 0.5)", + + // To add shadows for IOS devices + shadowOffset: { width: 0, height: 2 }, + shadowOpacity: 1, + shadowRadius: 2, }, }); diff --git a/dfm-sideline-sidekick-app/components/bookmarkRoutes.tsx b/dfm-sideline-sidekick-app/components/bookmarkRoutes.tsx index f2df891..f8657d4 100644 --- a/dfm-sideline-sidekick-app/components/bookmarkRoutes.tsx +++ b/dfm-sideline-sidekick-app/components/bookmarkRoutes.tsx @@ -20,10 +20,7 @@ export const createBookmark = async (item: Bookmark) => { throw new Error("Bookmark already exists!"); } bookmarks.push(item); - console.log(item); - console.log(bookmarks); await asyncStorage.setItem("bookmarks", JSON.stringify(bookmarks)); - console.log("Bookmark created:", item); } catch (error) { console.error("Error creating bookmark: ", error); throw new Error("Error creating bookmark: " + error); @@ -40,7 +37,6 @@ export const deleteBookmark = async (item: Bookmark) => { if (index !== -1) { existingBookmarks.splice(index, 1); await asyncStorage.setItem("bookmarks", JSON.stringify(existingBookmarks)); - console.log("Bookmark deleted!"); } else { console.log("Bookmark not found!"); } @@ -78,7 +74,6 @@ export const getAllBookmarks = async (): Promise => { export const clearBookmarks = async () => { try { await asyncStorage.removeItem("bookmarks"); - console.log("Bookmarks cleared successfully."); } catch (error) { console.error("Error clearing bookmarks:", error); } diff --git a/dfm-sideline-sidekick-app/components/carousel.tsx b/dfm-sideline-sidekick-app/components/carousel.tsx index 989fba2..8bf1898 100644 --- a/dfm-sideline-sidekick-app/components/carousel.tsx +++ b/dfm-sideline-sidekick-app/components/carousel.tsx @@ -66,11 +66,6 @@ export const Carousel: React.FC = ({ items, cardColor }) => { ); - items.forEach((item) => { - console.log(item); - console.log(item.content); - }); - return ( ; +}; + +type ViewAllProps = { + route: RouteProp; + navigation: StackNavigationProp; + arrayProp: Bookmark[] | MedicalEmergency[] | GeneralPrinciple[]; + title: string; +}; + +const Card = ({ emergency, navigation }: CardProps) => { + return ( + { + //@ts-expect-error Because content prop not defined for emergencies + if (emergency.content !== undefined) { + navigation.navigate("GeneralPrinciples", { + titleProp: emergency.title, + contentProp: emergency, + }); + } else { + navigation.navigate("MedicalConditions", { emergency }); + } + }} + > + + + + + {emergency.title} + {emergency.subtitle} + + + + + ); +}; + +const ViewAll: React.FC = ({ navigation, route }) => { + const { params } = route; + + const [fontsLoaded] = useFonts({ + "Roboto-Regular": Roboto_400Regular, + "Roboto-Bold": Roboto_700Bold, + }); + if (!fontsLoaded) { + return Loading...; + } + + return ( + + + { + navigation.goBack(); + }} + style={styles.backButtonContainer} + > + {/* eslint-disable-next-line @typescript-eslint/no-unsafe-assignment */} + + + + + {params.title} + + + + + {params.arrayProp.length} items + {params.arrayProp.map((emergency: GeneralPrinciple | MedicalEmergency | Bookmark) => ( + + ))} + + + + ); +}; + +export default ViewAll; diff --git a/dfm-sideline-sidekick-app/components/viewAllStyles.tsx b/dfm-sideline-sidekick-app/components/viewAllStyles.tsx new file mode 100644 index 0000000..554a4d6 --- /dev/null +++ b/dfm-sideline-sidekick-app/components/viewAllStyles.tsx @@ -0,0 +1,133 @@ +import { StyleSheet } from "react-native"; + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: "white", + paddingTop: 50, + textAlign: "left", + alignSelf: "stretch", + }, + title: { + color: "#182B49", + fontSize: 28, + fontFamily: "Roboto-Bold", + fontWeight: "700", + marginBottom: 20, + textAlign: "left", + paddingTop: 10, + paddingLeft: 12, + }, + containerCard: { + flex: 1, + justifyContent: "center", + alignItems: "center", + backgroundColor: "white", + paddingBottom: 10, + paddingTop: 10, + }, + card: { + backgroundColor: "white", + borderRadius: 15, + padding: 16, + shadowColor: "black", + shadowOffset: { + width: 0, + height: 4, + }, + shadowOpacity: 0.3, + shadowRadius: 6, + elevation: 14, + width: 350, + height: 100, + justifyContent: "center", + alignItems: "center", + }, + containerCard2: { + backgroundColor: "white", + flexDirection: "row", + borderRadius: 15, + // padding: 16, + shadowColor: "gray", + shadowOffset: { + width: 0, + height: 4, + }, + shadowOpacity: 0.3, + shadowRadius: 3, + elevation: 14, + width: 350, + height: 105, + justifyContent: "center", + alignItems: "center", + }, + grayArea: { + width: "35%", + height: "100%", + backgroundColor: "#E5EFF5", + padding: 10, + borderBottomLeftRadius: 15, + borderTopLeftRadius: 15, + }, + textArea: { + width: "65%", + padding: 10, + }, + textTitle: { + alignSelf: "center", + fontSize: 14, + fontWeight: "bold", + paddingBottom: 5, + textAlign: "center", + }, + text: { + alignSelf: "center", + textAlign: "center", + fontSize: 13, + }, + lenItems: { + color: "#182B49", + fontWeight: "bold", + paddingLeft: 12, + paddingBottom: 15, + }, + backButtonContainer: { + paddingTop: 20, + paddingBottom: 5, + paddingLeft: 12, + }, + backButton: { + fontSize: 20, + }, + headerShadowContainer: { + overflow: "hidden", + paddingBottom: 5, + }, + headerShadow: { + // shadowOffset: { width: 1, height: 3 }, + // shadowOpacity: 0.28, + // shadowRadius: 2, + // elevation: 5, + + backgroundColor: "white", + // flexDirection: 'row', + // borderRadius: 15, + // padding: 16, + shadowColor: "gray", + shadowOffset: { + width: 0, + height: 5, + }, + shadowOpacity: 0.4, + shadowRadius: 3, + elevation: 14, + }, + scroll: { + paddingTop: 20, + }, + bottomPad: { + paddingBottom: 140, + }, +}); + +export default styles; diff --git a/dfm-sideline-sidekick-app/download/File Preprocess/existenceChecker.ts b/dfm-sideline-sidekick-app/download/File Preprocess/existenceChecker.ts index 932f5c2..f81f093 100644 --- a/dfm-sideline-sidekick-app/download/File Preprocess/existenceChecker.ts +++ b/dfm-sideline-sidekick-app/download/File Preprocess/existenceChecker.ts @@ -11,12 +11,8 @@ export const checkDirectoryExists = async (fileDir: string) => { // checks if directory info const dir = await FileSystem.getInfoAsync(fileDir); - console.log("DIRECTORY PATH:", fileDir); - // if it doesn't exist if (!dir.exists) { - console.log("CREATING DIRECTORY"); - // make a new directory to store the files await FileSystem.makeDirectoryAsync(fileDir, { intermediates: true }); // intermediates make it so that it doesn't throw error when there is no directory } diff --git a/dfm-sideline-sidekick-app/download/checkDevice/checkDevice.ts b/dfm-sideline-sidekick-app/download/checkDevice/checkDevice.ts index c5cf1fa..34ecafc 100644 --- a/dfm-sideline-sidekick-app/download/checkDevice/checkDevice.ts +++ b/dfm-sideline-sidekick-app/download/checkDevice/checkDevice.ts @@ -3,7 +3,6 @@ import * as Device from "expo-device"; // Returns true if device, false if emulator export const checkDevice = () => { const isDevice: boolean = Device.isDevice; - console.log("CURRENTLY ON A PHYSICAL DEVICE: ", isDevice); return isDevice; }; diff --git a/dfm-sideline-sidekick-app/download/connection/checkConnection.ts b/dfm-sideline-sidekick-app/download/connection/checkConnection.ts index 868a259..2a81b54 100644 --- a/dfm-sideline-sidekick-app/download/connection/checkConnection.ts +++ b/dfm-sideline-sidekick-app/download/connection/checkConnection.ts @@ -5,8 +5,6 @@ export const checkConnection = async () => { let connected; await NetInfo.fetch().then((state) => { - console.log("CONNECTION TYPE: ", state.type); - console.log("IS CONNECTED: ", state.isConnected); connected = state.isConnected; }); diff --git a/dfm-sideline-sidekick-app/download/downloadFromAPI.ts b/dfm-sideline-sidekick-app/download/downloadFromAPI.ts index 08812dc..e33e185 100644 --- a/dfm-sideline-sidekick-app/download/downloadFromAPI.ts +++ b/dfm-sideline-sidekick-app/download/downloadFromAPI.ts @@ -4,11 +4,12 @@ import * as FileSystem from "expo-file-system"; import { checkDirectoryExists, checkFileExists } from "./File Preprocess/existenceChecker"; import { checkDevice } from "./checkDevice/checkDevice"; +import { checkConnection } from "./connection/checkConnection"; import { createResumable } from "./createResumable/createResumable"; import { getCurrentVersion } from "./versionControl/getCurrentVersion"; import { getStoredVersion, setStoredVersion } from "./versionControl/storedVersion"; -export const downloadJSON = async (fileName: string, OS: string) => { +export const downloadJSON = async (fileName: string, OS: string, fetchNew: boolean) => { let localhost; // check if currently running on an emulator or device @@ -18,11 +19,11 @@ export const downloadJSON = async (fileName: string, OS: string) => { localhost = process.env.EXPO_PUBLIC_IP_ADDRESS; // PUT YOUR IP ADDRESS OF YOUR LAPTOP HERE (for running on physical devices) [1. go to command line, 2. type ipconfig /all 3. it's under IPv4 address] } else { // compatibility for type of device - localhost = OS === "android" ? "10.0.2.2" : "127.0.0.1"; + localhost = OS === "android" ? "http://10.0.2.2:3001" : "http://127.0.0.1:3001"; } - const url = `http://${localhost}:3001/api/allWithVersion`; // all data - const versionUrl = `http://${localhost}:3001/api/version`; // newest version + const url = `${localhost}/api/allWithVersion`; // all data + const versionUrl = `${localhost}/api/version`; // newest version // directory in local storage to store files at const fileDir = FileSystem.documentDirectory + "expo/"; @@ -37,16 +38,17 @@ export const downloadJSON = async (fileName: string, OS: string) => { // will store the path to our file let uri = ""; - const newestVersion = (await getCurrentVersion(versionUrl))[0].version as string; const storedVersion = await getStoredVersion(); - - console.log(); // feel free to remove these extra logs, they're just for output clarity when debugging - - console.log("PRINT VERSIONS BEFORE UPDATE"); - console.log("UPDATED DEVICE VERSION:", storedVersion); - console.log("NEWEST VERSION:", newestVersion); - - console.log(); + let newestVersion: string | number | null | undefined; + if (fetchNew && (await checkConnection())) { + try { + newestVersion = (await getCurrentVersion(versionUrl))[0].version as string; + } catch (error) { + newestVersion = storedVersion; + } + } else { + newestVersion = storedVersion; + } // no stored version or current doesn't match stored version if (!fileExists || !storedVersion || storedVersion !== newestVersion) { @@ -55,16 +57,7 @@ export const downloadJSON = async (fileName: string, OS: string) => { // deletes file if it exists if (fileExists) { - console.log("DELETING EXISTING FILE"); await FileSystem.deleteAsync(fileDir + fileName); - - // Check if the file still exists - const fileStillExists = await checkFileExists(fileDir, fileName); - if (!fileStillExists) { - console.log("FILE SUCCESSFULLY DELETED"); - } else { - console.log("FILE DELETION FAILED"); - } } // downloads file from api and stores in result @@ -76,43 +69,16 @@ export const downloadJSON = async (fileName: string, OS: string) => { // update the stored version to the newest version if (newestVersion) { await setStoredVersion(newestVersion.toString()); - } else { - console.log("NO VERSIONS CURRENTLY EXIST"); } } else { - console.log("FILE ALREADY EXISTS AND IS UP TO DATE"); uri = fileDir + fileName; } - // gets info about file - const output = await FileSystem.getInfoAsync(uri); - // reads in the file as a string const str = await FileSystem.readAsStringAsync(uri); // gets JSON version of string const jsonOutput = JSON.parse(str); - - console.log("OUTPUT", output); - console.log("VERSION:", jsonOutput.version[0].version); - - const updatedStoredVersion = await getStoredVersion(); - - console.log("PRINT UPDATED VERSIONS (should be the same):"); - console.log("UPDATED DEVICE VERSION:", updatedStoredVersion); - console.log("NEWEST VERSION:", newestVersion); - - console.log(); - - // prints emergencies and general principles - console.log("EMERGENCIES JSON:"); - console.log(jsonOutput.emergencies); - - console.log(); - - console.log("GENERAL PRINCIPLES JSON:"); - console.log(jsonOutput.generalPrinciples); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return return jsonOutput; } catch (err) { diff --git a/dfm-sideline-sidekick-app/download/versionControl/storedVersion.ts b/dfm-sideline-sidekick-app/download/versionControl/storedVersion.ts index e77d0ac..95b7597 100644 --- a/dfm-sideline-sidekick-app/download/versionControl/storedVersion.ts +++ b/dfm-sideline-sidekick-app/download/versionControl/storedVersion.ts @@ -15,8 +15,6 @@ export const getStoredVersion = async () => { }; export const setStoredVersion = async (version: string) => { - console.log("STORED VERSION:", version); - try { await AsyncStorage.setItem("version", version.toString()); } catch (e) { diff --git a/dfm-sideline-sidekick-app/eas.json b/dfm-sideline-sidekick-app/eas.json new file mode 100644 index 0000000..72dd4b8 --- /dev/null +++ b/dfm-sideline-sidekick-app/eas.json @@ -0,0 +1,25 @@ +{ + "cli": { + "version": ">= 8.0.0" + }, + "build": { + "development": { + "developmentClient": true, + "distribution": "internal", + "env": { + "EXPO_PUBLIC_IP_ADDRESS": "https://sideline-sidekick-app.web.app" + } + }, + "preview": { + "distribution": "internal" + }, + "production": { + "env": { + "EXPO_PUBLIC_IP_ADDRESS": "https://sideline-sidekick-app.web.app" + } + } + }, + "submit": { + "production": {} + } +} diff --git a/dfm-sideline-sidekick-app/emergencies.ts b/dfm-sideline-sidekick-app/emergencies.ts deleted file mode 100644 index 39943fd..0000000 --- a/dfm-sideline-sidekick-app/emergencies.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { get, handleAPIError, post, put } from "./requests"; - -import type { APIResult } from "./requests"; - -// export type Emergency = { -// _id: string; -// title: string; -// overview?: { -// Importance?: string; -// "Mechanism of Injury"?: string[]; -// Diagnosis?: string[]; -// "Physical Exam"?: string[]; -// }; -// treatment?: { -// "Acute Management"?: string[]; -// Dispo?: string[]; -// Considerations?: { -// Header?: string; -// Content?: string[]; -// }; -// }; -// content?: object; -// }; - -export type Emergency = { - _id: string; - title: string; - overview?: object; - treatment?: object; - content?: object; -}; - -/** - * The expected inputs when we want to create a new Task object. In the MVP, we only - * need to provide the title and optionally the description, but in the course of - * this tutorial you'll likely want to add more fields here. - */ -export type CreateEmergencyRequest = { - title: string; - overview?: object; - treatment?: object; - content?: object; -}; - -/** - * The expected inputs when we want to update an existing Task object. Similar to - * `CreateTaskRequest`. - */ -export type UpdateEmergencyRequest = { - _id: string; - title: string; - overview?: object; - treatment?: object; - content?: object; -}; - -/** - * The implementations of these API client functions are provided as part of the - * MVP. You can use them as a guide for writing the other client functions. - */ -export async function createEmergency( - emergency: CreateEmergencyRequest, -): Promise> { - try { - const response = await post("/api/emergencies", emergency); - const json = (await response.json()) as Emergency; - return { success: true, data: json }; - } catch (error) { - return handleAPIError(error); - } -} - -export async function getEmergency(id: string): Promise> { - try { - const response = await get(`/api/emergencies/${id}`); - const json = (await response.json()) as Emergency; - return { success: true, data: json }; - } catch (error) { - return handleAPIError(error); - } -} - -export async function getAllEmergencies(): Promise> { - try { - const response = await get(`/api/emergencies/`); - const json = (await response.json()) as Emergency[]; - // const parsedJson = json.map((element) => (element)); - return { success: true, data: json }; - // your code here - } catch (error) { - return handleAPIError(error); - } -} - -export async function updateEmergency( - emergency: UpdateEmergencyRequest, -): Promise> { - try { - // your code here - const response = await put(`/api/emergencies/${emergency._id}`, emergency); - const json = (await response.json()) as Emergency; - return { success: true, data: json }; - } catch (error) { - return handleAPIError(error); - } -} diff --git a/dfm-sideline-sidekick-app/DataContext.tsx b/dfm-sideline-sidekick-app/functions/DataContext.tsx similarity index 84% rename from dfm-sideline-sidekick-app/DataContext.tsx rename to dfm-sideline-sidekick-app/functions/DataContext.tsx index e8c80ee..655aa1f 100644 --- a/dfm-sideline-sidekick-app/DataContext.tsx +++ b/dfm-sideline-sidekick-app/functions/DataContext.tsx @@ -1,21 +1,28 @@ import React, { ReactNode, createContext, useContext, useState } from "react"; -type MedicalEmergency = { +export type MedicalEmergency = { title: string; overview: object; treatment: object; - content: object; + subtitle; }; -type GeneralPrinciple = { +export type GeneralPrinciple = { title: string; - overview: object; content: object; + subtitle: string; +}; + +export type Category = { + title: string; + items: string[]; + type: string; }; type JsonDataStructure = { emergencies?: MedicalEmergency[]; // Optional array of MedicalEmergency generalPrinciples?: GeneralPrinciple[]; // Optional array of GeneralPrinciple + categories?: Category[]; }; type DataContextType = { diff --git a/dfm-sideline-sidekick-app/HandleSearch.tsx b/dfm-sideline-sidekick-app/functions/HandleSearch.tsx similarity index 100% rename from dfm-sideline-sidekick-app/HandleSearch.tsx rename to dfm-sideline-sidekick-app/functions/HandleSearch.tsx diff --git a/dfm-sideline-sidekick-app/package-lock.json b/dfm-sideline-sidekick-app/package-lock.json index c7770e7..804b1cf 100644 --- a/dfm-sideline-sidekick-app/package-lock.json +++ b/dfm-sideline-sidekick-app/package-lock.json @@ -10,7 +10,7 @@ "dependencies": { "@ant-design/icons": "^5.2.6", "@expo-google-fonts/roboto": "^0.2.3", - "@react-native-async-storage/async-storage": "^1.22.3", + "@react-native-async-storage/async-storage": "1.18.2", "@react-native-community/masked-view": "^0.1.11", "@react-native-community/netinfo": "9.3.10", "@react-navigation/native": "^6.1.10", @@ -20,6 +20,7 @@ "axios": "^1.6.7", "expo": "~49.0.15", "expo-app-loading": "^2.1.1", + "expo-dev-client": "~2.4.13", "expo-device": "~5.4.0", "expo-file-system": "~15.4.5", "expo-font": "~11.4.0", @@ -50,7 +51,8 @@ "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", "husky": "^8.0.3", - "prettier": "^3.1.1" + "prettier": "^3.1.1", + "react-devtools-core": "^5.2.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -4497,14 +4499,14 @@ } }, "node_modules/@react-native-async-storage/async-storage": { - "version": "1.23.1", - "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.23.1.tgz", - "integrity": "sha512-Qd2kQ3yi6Y3+AcUlrHxSLlnBvpdCEMVGFlVBneVOjaFaPU61g1huc38g339ysXspwY1QZA2aNhrk/KlHGO+ewA==", + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.18.2.tgz", + "integrity": "sha512-dM8AfdoeIxlh+zqgr0o5+vCTPQ0Ru1mrPzONZMsr7ufp5h+6WgNxQNza7t0r5qQ6b04AJqTlBNixTWZxqP649Q==", "dependencies": { "merge-options": "^3.0.4" }, "peerDependencies": { - "react-native": "^0.0.0-0 || >=0.60 <1.0" + "react-native": "^0.0.0-0 || 0.60 - 0.72 || 1000.0.0" } }, "node_modules/@react-native-community/cli": { @@ -9571,6 +9573,88 @@ "expo": "*" } }, + "node_modules/expo-dev-client": { + "version": "2.4.13", + "resolved": "https://registry.npmjs.org/expo-dev-client/-/expo-dev-client-2.4.13.tgz", + "integrity": "sha512-EBNJlPntw+DZy7mKxYvpdrmE2GU4YjcEpxSLpwNn2GDwy7e2xXAC2k/25E13BGy3yKPLo1iBXNgB01uleIDdVg==", + "dependencies": { + "expo-dev-launcher": "2.4.15", + "expo-dev-menu": "3.2.4", + "expo-dev-menu-interface": "1.3.0", + "expo-manifests": "~0.7.0", + "expo-updates-interface": "~0.10.0" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-dev-launcher": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/expo-dev-launcher/-/expo-dev-launcher-2.4.15.tgz", + "integrity": "sha512-6oF4NsxlKwuafnyIZvVtMp4OTxRu4Arsw6qJ9s4jDjZuGJtGwgEj9ux3R0YLkDPs8xhsK9Awp0q17RqbQzs1qg==", + "dependencies": { + "expo-dev-menu": "3.2.3", + "resolve-from": "^5.0.0", + "semver": "^7.5.3" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-dev-launcher/node_modules/expo-dev-menu": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/expo-dev-menu/-/expo-dev-menu-3.2.3.tgz", + "integrity": "sha512-DneF3okTC4AAfAZgaOIylQ/UngSO8SnUT6bRV6nHhJU/jQS1OIP1cZoNW23I100+2yj6x6mobL21PxyiI5VA8g==", + "dependencies": { + "expo-dev-menu-interface": "1.3.0", + "semver": "^7.5.3" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-dev-launcher/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/expo-dev-menu": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/expo-dev-menu/-/expo-dev-menu-3.2.4.tgz", + "integrity": "sha512-jPvEY4xGTsiVL6A8M6xThNG+tgCHKlDaWqmWHT+wy2EXgFf/7zE0daVYoFms0KJ1XtZc+/DmDRgIPTR86qIGTg==", + "dependencies": { + "expo-dev-menu-interface": "1.3.0", + "semver": "^7.5.3" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-dev-menu-interface": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expo-dev-menu-interface/-/expo-dev-menu-interface-1.3.0.tgz", + "integrity": "sha512-WtRP7trQ2lizJJTTFXUSGGn1deIeHaYej0sUynvu/uC69VrSP4EeSnYOxbmEO29kuT/MsQBMGu0P/AkMQOqCOg==", + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-dev-menu/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/expo-device": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/expo-device/-/expo-device-5.4.0.tgz", @@ -9626,6 +9710,11 @@ "expo": "*" } }, + "node_modules/expo-json-utils": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/expo-json-utils/-/expo-json-utils-0.7.1.tgz", + "integrity": "sha512-L0lyH8diXQtV0q5BLbFlcoxTqPF5im79xDHPhybB0j36xYdm65hjwRJ4yMrPIN5lR18hj48FUZeONiDHRyEvIg==" + }, "node_modules/expo-keep-awake": { "version": "12.3.0", "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-12.3.0.tgz", @@ -9634,6 +9723,14 @@ "expo": "*" } }, + "node_modules/expo-manifests": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/expo-manifests/-/expo-manifests-0.7.2.tgz", + "integrity": "sha512-xlhL0XI2zw3foJ0q2Ra4ieBhU0V2yz+Rv6GpVEaaIHFlIC/Dbx+mKrX5dgenZEMERr/MG7sRJaRbAVB2PaAYhA==", + "dependencies": { + "expo-json-utils": "~0.7.0" + } + }, "node_modules/expo-modules-autolinking": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-1.5.1.tgz", @@ -10035,6 +10132,14 @@ "resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-1.6.0.tgz", "integrity": "sha512-e//Oi2WPdomMlMDD3skE4+1ZarKCJ/suvcB4Jo/nO427niKug5oppcPNYO+csR6y3ZglGuypS+3pp/hJ+Xp6fQ==" }, + "node_modules/expo-updates-interface": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/expo-updates-interface/-/expo-updates-interface-0.10.1.tgz", + "integrity": "sha512-I6JMR7EgjXwckrydDmrkBEX/iw750dcqpzQVsjznYWfi0HTEOxajLHB90fBFqQkUV5i5s4Fd3hYQ1Cn0oMzUbA==", + "peerDependencies": { + "expo": "*" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -15183,9 +15288,10 @@ } }, "node_modules/react-devtools-core": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-4.28.5.tgz", - "integrity": "sha512-cq/o30z9W2Wb4rzBefjv5fBalHU0rJGZCHAkf/RHSBWSSYwh8PlQTqqOJmgIIbBtpj27T6FIPXeomIjZtCNVqA==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-5.2.0.tgz", + "integrity": "sha512-vZK+/gvxxsieAoAyYaiRIVFxlajb7KXhgBDV7OsoMzaAE+IqGpoxusBjIgq5ibqA2IloKu0p9n7tE68z1xs18A==", + "dev": true, "dependencies": { "shell-quote": "^1.6.1", "ws": "^7" @@ -15195,6 +15301,7 @@ "version": "7.5.9", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "dev": true, "engines": { "node": ">=8.3.0" }, @@ -15444,6 +15551,35 @@ "asap": "~2.0.6" } }, + "node_modules/react-native/node_modules/react-devtools-core": { + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-4.28.5.tgz", + "integrity": "sha512-cq/o30z9W2Wb4rzBefjv5fBalHU0rJGZCHAkf/RHSBWSSYwh8PlQTqqOJmgIIbBtpj27T6FIPXeomIjZtCNVqA==", + "dependencies": { + "shell-quote": "^1.6.1", + "ws": "^7" + } + }, + "node_modules/react-native/node_modules/react-devtools-core/node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/react-native/node_modules/regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", @@ -20878,9 +21014,9 @@ "optional": true }, "@react-native-async-storage/async-storage": { - "version": "1.23.1", - "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.23.1.tgz", - "integrity": "sha512-Qd2kQ3yi6Y3+AcUlrHxSLlnBvpdCEMVGFlVBneVOjaFaPU61g1huc38g339ysXspwY1QZA2aNhrk/KlHGO+ewA==", + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.18.2.tgz", + "integrity": "sha512-dM8AfdoeIxlh+zqgr0o5+vCTPQ0Ru1mrPzONZMsr7ufp5h+6WgNxQNza7t0r5qQ6b04AJqTlBNixTWZxqP649Q==", "requires": { "merge-options": "^3.0.4" } @@ -24648,6 +24784,66 @@ "uuid": "^3.3.2" } }, + "expo-dev-client": { + "version": "2.4.13", + "resolved": "https://registry.npmjs.org/expo-dev-client/-/expo-dev-client-2.4.13.tgz", + "integrity": "sha512-EBNJlPntw+DZy7mKxYvpdrmE2GU4YjcEpxSLpwNn2GDwy7e2xXAC2k/25E13BGy3yKPLo1iBXNgB01uleIDdVg==", + "requires": { + "expo-dev-launcher": "2.4.15", + "expo-dev-menu": "3.2.4", + "expo-dev-menu-interface": "1.3.0", + "expo-manifests": "~0.7.0", + "expo-updates-interface": "~0.10.0" + } + }, + "expo-dev-launcher": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/expo-dev-launcher/-/expo-dev-launcher-2.4.15.tgz", + "integrity": "sha512-6oF4NsxlKwuafnyIZvVtMp4OTxRu4Arsw6qJ9s4jDjZuGJtGwgEj9ux3R0YLkDPs8xhsK9Awp0q17RqbQzs1qg==", + "requires": { + "expo-dev-menu": "3.2.3", + "resolve-from": "^5.0.0", + "semver": "^7.5.3" + }, + "dependencies": { + "expo-dev-menu": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/expo-dev-menu/-/expo-dev-menu-3.2.3.tgz", + "integrity": "sha512-DneF3okTC4AAfAZgaOIylQ/UngSO8SnUT6bRV6nHhJU/jQS1OIP1cZoNW23I100+2yj6x6mobL21PxyiI5VA8g==", + "requires": { + "expo-dev-menu-interface": "1.3.0", + "semver": "^7.5.3" + } + }, + "semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==" + } + } + }, + "expo-dev-menu": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/expo-dev-menu/-/expo-dev-menu-3.2.4.tgz", + "integrity": "sha512-jPvEY4xGTsiVL6A8M6xThNG+tgCHKlDaWqmWHT+wy2EXgFf/7zE0daVYoFms0KJ1XtZc+/DmDRgIPTR86qIGTg==", + "requires": { + "expo-dev-menu-interface": "1.3.0", + "semver": "^7.5.3" + }, + "dependencies": { + "semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==" + } + } + }, + "expo-dev-menu-interface": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expo-dev-menu-interface/-/expo-dev-menu-interface-1.3.0.tgz", + "integrity": "sha512-WtRP7trQ2lizJJTTFXUSGGn1deIeHaYej0sUynvu/uC69VrSP4EeSnYOxbmEO29kuT/MsQBMGu0P/AkMQOqCOg==", + "requires": {} + }, "expo-device": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/expo-device/-/expo-device-5.4.0.tgz", @@ -24679,12 +24875,25 @@ "fontfaceobserver": "^2.1.0" } }, + "expo-json-utils": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/expo-json-utils/-/expo-json-utils-0.7.1.tgz", + "integrity": "sha512-L0lyH8diXQtV0q5BLbFlcoxTqPF5im79xDHPhybB0j36xYdm65hjwRJ4yMrPIN5lR18hj48FUZeONiDHRyEvIg==" + }, "expo-keep-awake": { "version": "12.3.0", "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-12.3.0.tgz", "integrity": "sha512-ujiJg1p9EdCOYS05jh5PtUrfiZnK0yyLy+UewzqrjUqIT8eAGMQbkfOn3C3fHE7AKd5AefSMzJnS3lYZcZYHDw==", "requires": {} }, + "expo-manifests": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/expo-manifests/-/expo-manifests-0.7.2.tgz", + "integrity": "sha512-xlhL0XI2zw3foJ0q2Ra4ieBhU0V2yz+Rv6GpVEaaIHFlIC/Dbx+mKrX5dgenZEMERr/MG7sRJaRbAVB2PaAYhA==", + "requires": { + "expo-json-utils": "~0.7.0" + } + }, "expo-modules-autolinking": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-1.5.1.tgz", @@ -25003,6 +25212,12 @@ "resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-1.6.0.tgz", "integrity": "sha512-e//Oi2WPdomMlMDD3skE4+1ZarKCJ/suvcB4Jo/nO427niKug5oppcPNYO+csR6y3ZglGuypS+3pp/hJ+Xp6fQ==" }, + "expo-updates-interface": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/expo-updates-interface/-/expo-updates-interface-0.10.1.tgz", + "integrity": "sha512-I6JMR7EgjXwckrydDmrkBEX/iw750dcqpzQVsjznYWfi0HTEOxajLHB90fBFqQkUV5i5s4Fd3hYQ1Cn0oMzUbA==", + "requires": {} + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -28717,9 +28932,10 @@ } }, "react-devtools-core": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-4.28.5.tgz", - "integrity": "sha512-cq/o30z9W2Wb4rzBefjv5fBalHU0rJGZCHAkf/RHSBWSSYwh8PlQTqqOJmgIIbBtpj27T6FIPXeomIjZtCNVqA==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-5.2.0.tgz", + "integrity": "sha512-vZK+/gvxxsieAoAyYaiRIVFxlajb7KXhgBDV7OsoMzaAE+IqGpoxusBjIgq5ibqA2IloKu0p9n7tE68z1xs18A==", + "dev": true, "requires": { "shell-quote": "^1.6.1", "ws": "^7" @@ -28729,6 +28945,7 @@ "version": "7.5.9", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "dev": true, "requires": {} } } @@ -28817,6 +29034,23 @@ "asap": "~2.0.6" } }, + "react-devtools-core": { + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-4.28.5.tgz", + "integrity": "sha512-cq/o30z9W2Wb4rzBefjv5fBalHU0rJGZCHAkf/RHSBWSSYwh8PlQTqqOJmgIIbBtpj27T6FIPXeomIjZtCNVqA==", + "requires": { + "shell-quote": "^1.6.1", + "ws": "^7" + }, + "dependencies": { + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + } + } + }, "regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", diff --git a/dfm-sideline-sidekick-app/package.json b/dfm-sideline-sidekick-app/package.json index c106917..987dd3a 100644 --- a/dfm-sideline-sidekick-app/package.json +++ b/dfm-sideline-sidekick-app/package.json @@ -17,34 +17,35 @@ "dependencies": { "@ant-design/icons": "^5.2.6", "@expo-google-fonts/roboto": "^0.2.3", - "@react-native-async-storage/async-storage": "^1.22.3", + "@react-native-async-storage/async-storage": "1.18.2", "@react-native-community/masked-view": "^0.1.11", + "@react-native-community/netinfo": "9.3.10", "@react-navigation/native": "^6.1.10", "@react-navigation/native-stack": "^6.9.18", "@react-navigation/stack": "^6.3.21", - "@react-native-community/netinfo": "9.3.10", "@types/react": "~18.2.14", "axios": "^1.6.7", "expo": "~49.0.15", "expo-app-loading": "^2.1.1", - "expo-font": "~11.4.0", + "expo-dev-client": "~2.4.13", "expo-device": "~5.4.0", "expo-file-system": "~15.4.5", + "expo-font": "~11.4.0", "expo-status-bar": "~1.6.0", "next": "^14.1.0", "node-localstorage": "^3.0.5", "react": "18.2.0", "react-native": "^0.72.10", + "react-native-dotenv": "^3.4.10", + "react-native-gesture-handler": "~2.12.0", "react-native-safe-area-context": "4.6.3", "react-native-screens": "~3.22.0", "react-native-svg": "13.9.0", "react-native-vector-icons": "^10.0.3", "react-navigation": "^5.0.0", "react-router-dom": "^6.22.0", - "react-native-dotenv": "^3.4.10", "react-router-native": "^6.22.1", - "typescript": "^5.1.3", - "react-native-gesture-handler": "~2.12.0" + "typescript": "^5.1.3" }, "devDependencies": { "@babel/core": "^7.20.0", @@ -57,7 +58,8 @@ "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", "husky": "^8.0.3", - "prettier": "^3.1.1" + "prettier": "^3.1.1", + "react-devtools-core": "^5.2.0" }, "private": true } diff --git a/dfm-sideline-sidekick-app/pages/BookmarkPage.tsx b/dfm-sideline-sidekick-app/pages/BookmarkPage.tsx deleted file mode 100644 index 928c340..0000000 --- a/dfm-sideline-sidekick-app/pages/BookmarkPage.tsx +++ /dev/null @@ -1,13 +0,0 @@ -// eslint-disable-next-line @typescript-eslint/no-unused-vars -import React from "react"; -import { Text, View } from "react-native"; - -const BookmarkPage = () => { - return ( - - Bookmark Dummy Page - - ); -}; - -export default BookmarkPage; diff --git a/dfm-sideline-sidekick-app/pages/ConditionSectionStyles.tsx b/dfm-sideline-sidekick-app/pages/ConditionSectionStyles.tsx index 4aa9eb3..5482abd 100644 --- a/dfm-sideline-sidekick-app/pages/ConditionSectionStyles.tsx +++ b/dfm-sideline-sidekick-app/pages/ConditionSectionStyles.tsx @@ -20,7 +20,7 @@ export default StyleSheet.create({ }, margin: { marginLeft: 16, - marginTop: 20, + marginTop: 0, }, menu: { display: "flex", diff --git a/dfm-sideline-sidekick-app/pages/ConditionsSection.tsx b/dfm-sideline-sidekick-app/pages/ConditionsSection.tsx index 08bd280..f14a078 100644 --- a/dfm-sideline-sidekick-app/pages/ConditionsSection.tsx +++ b/dfm-sideline-sidekick-app/pages/ConditionsSection.tsx @@ -19,11 +19,11 @@ import { Bookmark } from "../components/bookmark"; import styles from "./ConditionSectionStyles"; -import type { Emergency } from "../emergencies"; +import type { MedicalEmergency } from "../functions/DataContext"; export type RootStackParamList = { // Define the parameters for your screens here - Conditions: { emergency: Emergency }; // Example parameter + Conditions: { emergency: MedicalEmergency }; // Example parameter } & ParamListBase; // Define the type for the route parameters @@ -47,11 +47,9 @@ export default function ConditionsSection({ route, navigation }: Props) { const [overviewValues, setOverviewValues] = useState([]); const [treatmentHeaders, setTreatmentHeaders] = useState([]); const [treatmentValues, setTreatmentValues] = useState([]); - const [contentHeaders, setContentHeaders] = useState([]); - const [contentValues, setContentValues] = useState([]); const { params } = route; // Destructure params from the route object - const [emergency, setEmergency] = useState(); + const [emergency, setEmergency] = useState(); useEffect(() => { async function loadFont() { @@ -89,17 +87,12 @@ export default function ConditionsSection({ route, navigation }: Props) { useEffect(() => { if (emergency?.overview && typeof emergency.overview === "object") { setOverviewHeaders(Object.keys(emergency.overview)); - setOverviewValues(Object.values(emergency.overview) as StringValue[]); + setOverviewValues(Object.values(emergency.overview)); } if (emergency?.treatment && typeof emergency.treatment === "object") { setTreatmentHeaders(Object.keys(emergency.treatment)); - setTreatmentValues(Object.values(emergency.treatment) as StringValue[]); - } - - if (emergency?.content && typeof emergency.content === "object") { - setContentHeaders(Object.keys(emergency.content)); - setContentValues(Object.values(emergency.content) as StringValue[]); + setTreatmentValues(Object.values(emergency.treatment)); } }, [emergency]); @@ -171,7 +164,7 @@ export default function ConditionsSection({ route, navigation }: Props) { {overviewHeaders.map((header, index) => ( - {header} + {header !== '""' && {header}} ))} @@ -190,29 +183,12 @@ export default function ConditionsSection({ route, navigation }: Props) { {treatmentHeaders.map((header, index) => ( - {header} + {header !== '""' && {header}} ))} )} - - {emergency?.content && typeof emergency.content === "string" && ( - - {emergency?.content} - - )} - - {emergency?.content && typeof emergency.content === "object" && ( - - {contentHeaders.map((header, index) => ( - - {header} - - - ))} - - )} diff --git a/dfm-sideline-sidekick-app/pages/EmergencyCare.tsx b/dfm-sideline-sidekick-app/pages/EmergencyCare.tsx deleted file mode 100644 index 855e754..0000000 --- a/dfm-sideline-sidekick-app/pages/EmergencyCare.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { Roboto_400Regular, Roboto_700Bold } from "@expo-google-fonts/roboto"; -import { useFonts } from "expo-font"; -import { Text, TouchableOpacity, View } from "react-native"; -import AntIcon from "react-native-vector-icons/AntDesign"; - -import BulletPoint from "../components/BulletPoint"; -import { Bookmark } from "../components/bookmark"; - -import styles from "./generalPrinciplesStyles"; - -const EmergencyCare = () => { - const [fontsLoaded] = useFonts({ - "Roboto-Regular": Roboto_400Regular, - "Roboto-Bold": Roboto_700Bold, - }); - if (!fontsLoaded) { - return Loading...; - } - return ( - - - - - - - - Emergency Care - Emergency Care - - - - - ); -}; - -export default EmergencyCare; diff --git a/dfm-sideline-sidekick-app/pages/Home.tsx b/dfm-sideline-sidekick-app/pages/Home.tsx deleted file mode 100644 index bef56a2..0000000 --- a/dfm-sideline-sidekick-app/pages/Home.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { useNavigation } from "@react-navigation/native"; -import { StackNavigationProp } from "@react-navigation/stack"; -import { Button, StyleSheet, View } from "react-native"; - -import { RootStackParamList } from "./generalPrinciples"; - -const title = "Emergency Action Plan"; - -// const content = -// { -// title: 'General Principles', -// content: { -// '"If you see it, flee it; if you can hear it, clear it.” (National Lightning Safety Institute)': "", -// "Assign roles": "Weather Monitor\n Chain of Command/Decision-maker" -// } -// } -// ; - -const content = [ - { - title: "General Principles", - content: { - '"If you see it, flee it; if you can hear it, clear it.” (National Lightning Safety Institute)': - "", - "Assign roles": "Weather Monitor\n Chain of Command/Decision-maker", - }, - }, - { - title: "General Principles 2", - content: { - '"If you see it, flee it; if you can hear it, clear it.” (National Lightning Safety Institute)': - "", - "Assign roles": "Weather Monitor\n Chain of Command/Decision-maker", - }, - }, -]; - -const styles = StyleSheet.create({ - container2: { - width: "100%", - }, -}); - -export default function Home() { - const navigation = useNavigation>(); - - const handleNavigation = () => { - navigation.navigate("GeneralPrinciples", { titleProp: title, contentProp: content }); - }; - - return ( - -