diff --git a/App.js b/App.js index 54ce933..1d2d310 100644 --- a/App.js +++ b/App.js @@ -2,15 +2,8 @@ import { useEffect } from "react"; import AppProvider from "./Context/AppProvider"; import Wrapper from "./Wrapper"; -import { dbSetup, testInsert, testQuery } from "./queries/tableSetup"; function App() { - useEffect(() => { - dbSetup(); - testInsert(); - testQuery(); - }, []); - return ( diff --git a/Wrapper.js b/Wrapper.js index da938a9..4a2d04f 100644 --- a/Wrapper.js +++ b/Wrapper.js @@ -3,10 +3,30 @@ import BottomNavigator from "./components/BottomNavigator/BottomNavigator"; import { NavigationContainer } from "@react-navigation/native"; import { NativeBaseProvider } from "native-base"; import AppContext from "./Context/AppContext"; +import { dbSetup, createTodayRow, testQuery } from "./queries/tableSetup"; + +import { checkOnboarding, setGoal, setUnit } from "./utils/asyncStorage"; import React from "react"; function Wrapper() { + React.useEffect(() => { + dbSetup(); + async function fetchOnboardingData() { + const onboarding = await checkOnboarding(); + await setGoal(); + await setUnit(); + + // Set onboarding === true to true after testing + if (onboarding === "false") { + createTodayRow(); + testQuery(); + } + } + + fetchOnboardingData(); + }, []); + const { statusBarColor } = React.useContext(AppContext); return ( diff --git a/assets/goal.png b/assets/goal.png new file mode 100644 index 0000000..3e7d07d Binary files /dev/null and b/assets/goal.png differ diff --git a/assets/notification.png b/assets/notification.png new file mode 100644 index 0000000..e0639be Binary files /dev/null and b/assets/notification.png differ diff --git a/assets/target.png b/assets/target.png new file mode 100644 index 0000000..0850449 Binary files /dev/null and b/assets/target.png differ diff --git a/assets/water.png b/assets/water.png new file mode 100644 index 0000000..c51a25c Binary files /dev/null and b/assets/water.png differ diff --git a/components/BottomNavigator/BottomNavigator.js b/components/BottomNavigator/BottomNavigator.js index 6156499..3561015 100644 --- a/components/BottomNavigator/BottomNavigator.js +++ b/components/BottomNavigator/BottomNavigator.js @@ -4,6 +4,10 @@ import Settings from "../../screens/Settings/Settings"; import AppContext from "../../Context/AppContext"; ("../../Context/AppProvider"); import React from "react"; +import History from "../../screens/History/History"; +import { Ionicons } from "@expo/vector-icons"; +import { MaterialIcons } from "@expo/vector-icons"; + const Tab = createBottomTabNavigator(); function BottomNavigator() { @@ -19,10 +23,40 @@ function BottomNavigator() { tabBarStyle: { backgroundColor: bg, }, + tabBarActiveTintColor: "#0891b2", }} > - - + ( + + ), + }} + component={History} + /> + ( + + ), + }} + component={Home} + /> + ( + + ), + }} + component={Settings} + /> ); } diff --git a/components/CustomIntake/CustomIntake.js b/components/CustomIntake/CustomIntake.js new file mode 100644 index 0000000..534c8a0 --- /dev/null +++ b/components/CustomIntake/CustomIntake.js @@ -0,0 +1,70 @@ +import React from "react"; +import { + Text, + View, + Heading, + Input, + KeyboardAvoidingView, + ScrollView, + Button, + Pressable, +} from "native-base"; +import { Ionicons } from "@expo/vector-icons"; +import { TouchableWithoutFeedback } from "react-native-gesture-handler"; +import { Keyboard, TouchableWithoutFeedbackComponent } from "react-native"; +import { MaterialCommunityIcons } from "@expo/vector-icons"; +import { TouchableOpacity } from "react-native"; + +function CustomIntake(props) { + const [intake, setIntake] = React.useState("1000"); + return ( + + Custom Intake + + { + setIntake(e.nativeEvent.text); + }} + color={"primary.600"} + fontSize={"2xl"} + clearTextOnFocus={true} + borderRadius={10} + InputRightElement={ + + ml{" "} + + } + > + + + + ); +} + +export default CustomIntake; diff --git a/components/ModifyGoal/ModifyGoal.js b/components/ModifyGoal/ModifyGoal.js new file mode 100644 index 0000000..c4b2abd --- /dev/null +++ b/components/ModifyGoal/ModifyGoal.js @@ -0,0 +1,87 @@ +import React from "react"; +import { + Text, + View, + Heading, + Input, + KeyboardAvoidingView, + ScrollView, + Button, + Pressable, +} from "native-base"; +import { Ionicons } from "@expo/vector-icons"; +import { TouchableWithoutFeedback } from "react-native-gesture-handler"; +import { Keyboard, TouchableWithoutFeedbackComponent } from "react-native"; +import { MaterialCommunityIcons } from "@expo/vector-icons"; +import { TouchableOpacity } from "react-native"; +import { modifyGoal } from "../../utils/asyncStorage"; +function ModifyGoal(props) { + const { goal, handleGoalChange, onClose } = props; + const [localGoal, setLocalGoal] = React.useState(goal); + + const setDBGoal = async (goal) => { + await modifyGoal(goal); + }; + + const handleGoalUpdate = () => { + Keyboard.dismiss(); + async function updateGoal() { + await setDBGoal(localGoal); + } + updateGoal(); + handleGoalChange(localGoal); + onClose(); + + // handleGoalChange(localGoal); + }; + + return ( + + Modify Daily Goal + + { + setLocalGoal(e.nativeEvent.text); + }} + color={"primary.600"} + fontSize={"2xl"} + clearTextOnFocus={true} + borderRadius={10} + InputRightElement={ + + ml{" "} + + } + > + + + + ); +} + +export default ModifyGoal; diff --git a/package-lock.json b/package-lock.json index ad59e5a..67aaef8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "gallon", "version": "1.0.0", "dependencies": { + "@react-native-async-storage/async-storage": "1.17.11", "@react-navigation/bottom-tabs": "^6.5.7", "@react-navigation/native": "^6.1.6", "@react-navigation/native-stack": "^6.9.12", @@ -17,10 +18,13 @@ "expo-sqlite": "~11.1.1", "expo-status-bar": "~1.4.4", "metro": "^0.76.5", + "moment": "^2.29.4", "native-base": "^3.4.28", "react": "18.2.0", "react-native": "0.71.8", + "react-native-circular-progress": "^1.3.8", "react-native-gesture-handler": "~2.9.0", + "react-native-progress": "^5.0.0", "react-native-safe-area-context": "4.5.0", "react-native-screens": "~3.20.0", "react-native-svg": "13.4.0" @@ -4129,6 +4133,17 @@ "react-native": "*" } }, + "node_modules/@react-native-async-storage/async-storage": { + "version": "1.17.11", + "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.17.11.tgz", + "integrity": "sha512-bzs45n5HNcDq6mxXnSsOHysZWn1SbbebNxldBXCQs8dSvF8Aor9KCdpm+TpnnGweK3R6diqsT8lFhX77VX0NFw==", + "dependencies": { + "merge-options": "^3.0.4" + }, + "peerDependencies": { + "react-native": "^0.0.0-0 || 0.60 - 0.71 || 1000.0.0" + } + }, "node_modules/@react-native-community/cli": { "version": "10.2.2", "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-10.2.2.tgz", @@ -9657,6 +9672,14 @@ "node": ">=8" } }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "engines": { + "node": ">=8" + } + }, "node_modules/is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -10942,6 +10965,17 @@ "resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz", "integrity": "sha512-OcjA+jzjOYzKmKS6IQVALHLVz+rNTMPoJvCztFaZxwG14wtAW7VRZjwTQu06vKCYOxh4jVnik7ya0SXTB0W+xA==" }, + "node_modules/merge-options": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz", + "integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==", + "dependencies": { + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -12636,6 +12670,14 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "engines": { + "node": "*" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -13979,6 +14021,19 @@ "react": "18.2.0" } }, + "node_modules/react-native-circular-progress": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/react-native-circular-progress/-/react-native-circular-progress-1.3.8.tgz", + "integrity": "sha512-XcGO6MzOLvGCEQqPlqsbxzv0R8JEF1W7enyKaZMIihCbrneH+BSPmec/9emlroNUNqRg9LrbNtZMy9843ixMCg==", + "dependencies": { + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-native": ">=0.50.0", + "react-native-svg": ">=7.0.0" + } + }, "node_modules/react-native-codegen": { "version": "0.71.5", "resolved": "https://registry.npmjs.org/react-native-codegen/-/react-native-codegen-0.71.5.tgz", @@ -14011,6 +14066,17 @@ "resolved": "https://registry.npmjs.org/react-native-gradle-plugin/-/react-native-gradle-plugin-0.71.18.tgz", "integrity": "sha512-7F6bD7B8Xsn3JllxcwHhFcsl9aHIig47+3eN4IHFNqfLhZr++3ElDrcqfMzugM+niWbaMi7bJ0kAkAL8eCpdWg==" }, + "node_modules/react-native-progress": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/react-native-progress/-/react-native-progress-5.0.0.tgz", + "integrity": "sha512-KjnGIt3r9i5Kn2biOD9fXLJocf0bwxPRxOyAgXEnZTJQU2O+HyzgGFRCbM5h3izm9kKIkSc1txh8aGmMafCD9A==", + "dependencies": { + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "react-native-svg": "*" + } + }, "node_modules/react-native-safe-area-context": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-4.5.0.tgz", @@ -19320,6 +19386,14 @@ "@react-aria/utils": "^3.3.0" } }, + "@react-native-async-storage/async-storage": { + "version": "1.17.11", + "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.17.11.tgz", + "integrity": "sha512-bzs45n5HNcDq6mxXnSsOHysZWn1SbbebNxldBXCQs8dSvF8Aor9KCdpm+TpnnGweK3R6diqsT8lFhX77VX0NFw==", + "requires": { + "merge-options": "^3.0.4" + } + }, "@react-native-community/cli": { "version": "10.2.2", "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-10.2.2.tgz", @@ -23544,6 +23618,11 @@ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==" }, + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==" + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -24543,6 +24622,14 @@ "resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz", "integrity": "sha512-OcjA+jzjOYzKmKS6IQVALHLVz+rNTMPoJvCztFaZxwG14wtAW7VRZjwTQu06vKCYOxh4jVnik7ya0SXTB0W+xA==" }, + "merge-options": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz", + "integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==", + "requires": { + "is-plain-obj": "^2.1.0" + } + }, "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -25861,6 +25948,11 @@ "minimist": "^1.2.6" } }, + "moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -26881,6 +26973,14 @@ } } }, + "react-native-circular-progress": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/react-native-circular-progress/-/react-native-circular-progress-1.3.8.tgz", + "integrity": "sha512-XcGO6MzOLvGCEQqPlqsbxzv0R8JEF1W7enyKaZMIihCbrneH+BSPmec/9emlroNUNqRg9LrbNtZMy9843ixMCg==", + "requires": { + "prop-types": "^15.8.1" + } + }, "react-native-codegen": { "version": "0.71.5", "resolved": "https://registry.npmjs.org/react-native-codegen/-/react-native-codegen-0.71.5.tgz", @@ -26909,6 +27009,14 @@ "resolved": "https://registry.npmjs.org/react-native-gradle-plugin/-/react-native-gradle-plugin-0.71.18.tgz", "integrity": "sha512-7F6bD7B8Xsn3JllxcwHhFcsl9aHIig47+3eN4IHFNqfLhZr++3ElDrcqfMzugM+niWbaMi7bJ0kAkAL8eCpdWg==" }, + "react-native-progress": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/react-native-progress/-/react-native-progress-5.0.0.tgz", + "integrity": "sha512-KjnGIt3r9i5Kn2biOD9fXLJocf0bwxPRxOyAgXEnZTJQU2O+HyzgGFRCbM5h3izm9kKIkSc1txh8aGmMafCD9A==", + "requires": { + "prop-types": "^15.7.2" + } + }, "react-native-safe-area-context": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-4.5.0.tgz", diff --git a/package.json b/package.json index d86e91d..0c13ac4 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "web": "expo start --web" }, "dependencies": { + "@react-native-async-storage/async-storage": "1.17.11", "@react-navigation/bottom-tabs": "^6.5.7", "@react-navigation/native": "^6.1.6", "@react-navigation/native-stack": "^6.9.12", @@ -18,10 +19,13 @@ "expo-sqlite": "~11.1.1", "expo-status-bar": "~1.4.4", "metro": "^0.76.5", + "moment": "^2.29.4", "native-base": "^3.4.28", "react": "18.2.0", "react-native": "0.71.8", + "react-native-circular-progress": "^1.3.8", "react-native-gesture-handler": "~2.9.0", + "react-native-progress": "^5.0.0", "react-native-safe-area-context": "4.5.0", "react-native-screens": "~3.20.0", "react-native-svg": "13.4.0" @@ -30,4 +34,4 @@ "@babel/core": "^7.20.0" }, "private": true -} \ No newline at end of file +} diff --git a/queries/historyQueries.js b/queries/historyQueries.js new file mode 100644 index 0000000..570cec6 --- /dev/null +++ b/queries/historyQueries.js @@ -0,0 +1,9 @@ +import { db } from "../utils/db"; +import { executeQuery } from "./tableSetup"; + +const fetchLogsData = async () => { + const result = executeQuery("SELECT * FROM data", []); + return result; +}; + +export { fetchLogsData }; diff --git a/queries/homeQueries.js b/queries/homeQueries.js new file mode 100644 index 0000000..0cc7ed4 --- /dev/null +++ b/queries/homeQueries.js @@ -0,0 +1,38 @@ +import { db } from "../utils/db"; + +const fetchIntake = async () => { + let date = new Date(); + date.setHours(0, 0, 0, 0); + date = date.toString(); + + return new Promise(async (resolve, reject) => { + try { + await db.transaction((tx) => { + tx.executeSql( + "SELECT * FROM data ORDER BY id DESC LIMIT 1", + [date, "0"], + (_, { rows }) => { + console.log(rows._array[0].intake, "intake"); + resolve(rows._array[0].intake); + } + ); + }); + } catch (error) { + reject(error); + } + }); +}; + +const increaseIntake = async (value) => { + let date = new Date(); + date.setHours(0, 0, 0, 0); + date = date.toString(); + await db.transaction((tx) => { + tx.executeSql("UPDATE data SET intake = intake + ? WHERE date = ?", [ + value, + date, + ]); + }); +}; + +export { fetchIntake, increaseIntake }; diff --git a/queries/tableSetup.js b/queries/tableSetup.js index e5135c9..4e2b064 100644 --- a/queries/tableSetup.js +++ b/queries/tableSetup.js @@ -1,27 +1,75 @@ import { db } from "../utils/db"; const dbSetup = () => { - db.transaction((tx) => { - tx.executeSql( - "CREATE TABLE IF NOT EXISTS gallons (id INTEGER PRIMARY KEY AUTOINCREMENT, gallons INTEGER, date TEXT);" - ); + db.transaction((tx) => { + tx.executeSql( + "CREATE TABLE IF NOT EXISTS data (id INTEGER PRIMARY KEY AUTOINCREMENT, date TEXT, intake INTEGER, goal INTEGER);" + ); + }); +}; + +const createTodayRow = async () => { + let date = new Date(); + date.setHours(0, 0, 0, 0); + date = date.toString(); + const latestDate = await db.transaction((tx) => { + tx.executeSql( + "SELECT * FROM data ORDER BY id DESC LIMIT 1", + [date, "0"], + (_, { rows }) => { + if (rows.length === 0 || rows._array[0].date !== date) { + db.transaction((tx) => { + tx.executeSql( + "INSERT INTO data (date, intake, goal) VALUES (?, ?, ?)", + [date, 0, 0] + ); + }); + } + } + ); + }); +}; + +const testQuery = async () => { + // await db.transaction(async (tx) => { + // await tx.executeSql("DELETE FROM data"); + // }); + // console.log("Table cleared successfully."); + + await db.transaction((tx) => { + testQuery2(); + tx.executeSql("SELECT * FROM data", [], (_, { rows }) => { + for (let i = 0; i < rows.length; i++) { + console.log(rows._array[i], "row"); + } }); + }); }; -const testInsert = () => { - db.transaction((tx) => { - tx.executeSql( - "INSERT INTO gallons (gallons, date) VALUES (1, '2021-01-01');" - ); +const testQuery2 = async () => { + await db.transaction((tx) => { + tx.executeSql("SELECT * FROM data", [], (_, { rows }) => { + console.log(rows._array[0], "test"); }); + }); }; -const testQuery = () => { +const executeQuery = (sql, params) => { + return new Promise((resolve, reject) => { db.transaction((tx) => { - tx.executeSql("SELECT * FROM gallons", [], (_, { rows }) => { - console.log(rows._array.forEach((row) => console.log(row.date))); - }); + tx.executeSql( + sql, + params, + (_, { rows }) => { + resolve(rows._array); + }, + (_, error) => { + console.log(error); + reject(error); + } + ); }); + }); }; -export { dbSetup, testInsert, testQuery }; +export { dbSetup, createTodayRow, testQuery, testQuery2, executeQuery }; diff --git a/screens/FirstLaunch/FirstLaunch.js b/screens/FirstLaunch/FirstLaunch.js new file mode 100644 index 0000000..ec2724e --- /dev/null +++ b/screens/FirstLaunch/FirstLaunch.js @@ -0,0 +1,84 @@ +import Onboarding from 'react-native-onboarding-swiper'; +import { View, Image, Text, TouchableOpacity } from 'react-native'; +import React from "react"; +import styles from './styles'; +import AppContext from "../../Context/AppContext"; + +function FirstLaunch({ navigation }) { + const { bg, textColor } = React.useContext(AppContext); + + //Custom Done button + const Done = ({ ...props }) => ( + + Get Started + + ) + //Customizable dots indicator + const Dots = ({ selected }) => { + let backgroundColor; + backgroundColor = selected ? '#077d9a' : 'black' + return ( + + ) + } + return ( + navigation.replace("Home")} + + //To handle the navigation to the Homepage after Done is clicked + onDone={() => navigation.replace("Home")} + + DoneButtonComponent={Done} + + DotComponent={Dots} + + pages={[ + { + backgroundColor: bg, + image: , + title: 'Welcome', + titleStyles: styles.Heading, + subtitle: 'With our application, being healthy and slender is easy.', + subTitleStyles: styles.Subheading, + }, + { + backgroundColor: bg, + image: , + title: 'Notifications', + titleStyles: styles.Heading, + subtitle: 'Turn on useful notifications not to forget to drink water.', + subTitleStyles: styles.Subheading, + }, + { + backgroundColor: bg, + image: , + title: 'Dialy Goal', + titleStyles: styles.Heading, + subtitle: 'We will calculate your recommended water intake.', + subTitleStyles: styles.Subheading, + }, + { + backgroundColor: bg, + image: , + title: 'Awards', + titleStyles: styles.Heading, + subtitle: 'Our achivements will motivate you to new achievments Good Luck!', + subTitleStyles: styles.Subheading, + } + ]} + /> + + ); +} + +export default FirstLaunch; diff --git a/screens/FirstLaunch/styles.js b/screens/FirstLaunch/styles.js new file mode 100644 index 0000000..cd0eba2 --- /dev/null +++ b/screens/FirstLaunch/styles.js @@ -0,0 +1,14 @@ +import { StyleSheet } from "react-native"; + +export default StyleSheet.create({ + Heading: { + fontSize: 20, color: '#0891b2', fontWeight: 'bold' + }, + Subheading: { + color: '#077d9a' + }, + Done: { + fontSize: 16, + marginHorizontal: 20 + }, +}); \ No newline at end of file diff --git a/screens/History/History.js b/screens/History/History.js new file mode 100644 index 0000000..cbf75cd --- /dev/null +++ b/screens/History/History.js @@ -0,0 +1,14 @@ +import { Text } from "native-base"; +import React from "react"; +import { SafeAreaView } from "react-native"; +import Logs from "./Logs/logs" + +function History() { + return ( + + + + ); +} + +export default History; diff --git a/screens/History/Logs/logs.js b/screens/History/Logs/logs.js new file mode 100644 index 0000000..779b5ed --- /dev/null +++ b/screens/History/Logs/logs.js @@ -0,0 +1,81 @@ +import { Text } from "native-base"; +import React from "react"; +import { SafeAreaView, View } from "react-native"; +import styles from "./styles"; +import { + Divider, + Stack, + Heading, + VStack, + HStack, + ScrollView, + Center, + Box, + Progress, +} from "native-base"; +import { useIsFocused } from "@react-navigation/native"; +import { fetchLogsData } from "../../../queries/historyQueries"; +import Moment from "moment"; + +function Logs() { + const [logs, setLogs] = React.useState([]); + + const isFocused = useIsFocused(); + + React.useEffect(() => { + if (isFocused) { + async function fetchLogs() { + const data = await fetchLogsData(); + setLogs(data); + } + fetchLogs(); + } + }, [isFocused]); + + const month = "April"; + const day = "1"; + const year = "2023"; + var logsDay = ""; + + return ( + + {logs && + logs.map((item, key) => ( + + +
+ + {Moment(item.date).format("MMM")} + + {" "} + {Moment(item.date).format("D")}{" "} + + {Moment(item.date).format("YYYY")} + +
+
+ + + +
+
+ + {item.intake}/{item.goal} + +
+
+
+ ))} +
+ ); +} + +export default Logs; diff --git a/screens/History/Logs/styles.js b/screens/History/Logs/styles.js new file mode 100644 index 0000000..eecd678 --- /dev/null +++ b/screens/History/Logs/styles.js @@ -0,0 +1,26 @@ +import { StyleSheet } from "react-native"; + + +export default StyleSheet.create({ + + container: { + padding: 20, + }, + H1: { + fontSize: 20 + , + color: '#0891b2', + fontWeight: 'bold', + }, + flexContainer: { + flexDirection: 'row', + flex: 1, + justifyContent: 'space-around', + }, + flexRow: { + height: 20, + textAlignVertical: 'center', + }, + + +}); \ No newline at end of file diff --git a/screens/Home/Home.js b/screens/Home/Home.js index 274f96a..9ee1924 100644 --- a/screens/Home/Home.js +++ b/screens/Home/Home.js @@ -1,13 +1,185 @@ -import { View } from "native-base"; -import { Text } from "native-base"; +import { Button, View } from "native-base"; +import { Text, VStack, Heading, HStack } from "native-base"; +import { AnimatedCircularProgress } from "react-native-circular-progress"; +import React from "react"; +import { StyleSheet } from "react-native"; +import { SafeAreaView } from "react-native-safe-area-context"; +import { unitValueDisplay } from "../../utils/helpers"; +import { getUnit, getGoal } from "../../utils/asyncStorage"; +import { fetchIntake, increaseIntake } from "../../queries/homeQueries"; +import { MaterialCommunityIcons } from "@expo/vector-icons"; +import { Ionicons } from "@expo/vector-icons"; function Home() { - return ( - - Home Screen + const [fill, setFill] = React.useState(0); + const [goal, setGoal] = React.useState(0); + const [unit, setUnit] = React.useState("ml"); + const [progress, setProgress] = React.useState(2); + React.useEffect(() => { + console.log("useEffect"); + async function fetchUnit() { + const unit = await getUnit(); + setUnit(unit); + } + async function fetchGoal() { + const goal = await getGoal(); + console.log(goal, "goal"); + setGoal(goal); + } + async function fetchProgress() { + const progress = await fetchIntake(); + setProgress(progress); + console.log(progress, "prog"); + } + fetchProgress(); + fetchGoal(); + fetchUnit(); + if (progress && goal) { + progressCircle(); + } + + console.log(unit, goal, progress); + }, [progress]); + const progressCircle = () => { + console.log("sdf", progress, goal); + const fill = Math.ceil((progress * 100) / goal); + console.log("sdf", fill); + setFill(fill); + }; + const increaseProgress = (value) => { + console.log(typeof progress, "value"); + increaseIntake(value); + setProgress(progress + value); + }; + return ( + + + + {new Date().toDateString()} + + + console.log("onAnimationComplete")} + backgroundColor={"#164e63"} + > + {(fill) => {fill}%} + + + + + + + + + + + + + + - ); + + + Today's Progress + + {progress} / {goal} {unit} + + + + + + ); } +const styles = StyleSheet.create({ + container: { + display: "flex", + paddingRight: 30, + paddingLeft: 30, + paddingBottom: 30, + paddingTop: 30, + }, + actionsContainer: { + marginTop: 30, + width: "100%", + }, + progressContainer: { + justifyContent: "center", + alignItems: "center", + }, + headerContainer: { + justifyContent: "center", + alignItems: "center", + marginBottom: 30, + }, + buttonContainer: { + width: "33.3%", + }, + dataContainer: { + backgroundColor: "white", + height: 120, + marginTop: 30, + padding: 15, + borderRadius: 20, + }, +}); + export default Home; diff --git a/utils/asyncStorage.js b/utils/asyncStorage.js new file mode 100644 index 0000000..c4c11af --- /dev/null +++ b/utils/asyncStorage.js @@ -0,0 +1,59 @@ +import AsyncStorage from "@react-native-async-storage/async-storage"; + +async function checkOnboarding() { + try { + const value = await AsyncStorage.getItem("onboarding"); + if (value == null) { + await AsyncStorage.setItem("onboarding", "false"); + } + return value; + } catch (e) { + // error reading value + } +} + +async function setUnit() { + try { + const value = await AsyncStorage.getItem("unit"); + if (value == null) { + await AsyncStorage.setItem("unit", "ml"); + } + return value; + } catch (e) { + // error reading value + } +} + +async function setGoal() { + try { + // const value = await AsyncStorage.getItem("goal"); + // if (value == null) { + console.log("setting goal"); + await AsyncStorage.setItem("goal", "2500"); + // } + return value; + } catch (e) { + // error reading value + } +} + +async function getGoal() { + let result; + await AsyncStorage.getItem("goal").then((value) => { + console.log(value, "value"); + result = value; + }); + return result; +} + +async function getUnit() { + try { + const value = await AsyncStorage.getItem("unit"); + + return value; + } catch (e) { + // error reading value + } +} + +export { checkOnboarding, setUnit, getUnit, setGoal, getGoal }; diff --git a/utils/db.js b/utils/db.js index 4469856..c379cba 100644 --- a/utils/db.js +++ b/utils/db.js @@ -1,5 +1,5 @@ import * as SQLite from "expo-sqlite"; -const db = SQLite.openDatabase("gallon.db"); +const db = SQLite.openDatabase("gallonV3.db"); export { db }; diff --git a/utils/helpers.js b/utils/helpers.js new file mode 100644 index 0000000..642158c --- /dev/null +++ b/utils/helpers.js @@ -0,0 +1,14 @@ +import { getUnit } from "./asyncStorage"; +function unitValueDisplay(ml) { + getUnit().then((unit) => { + if (unit == "ml") { + return ml; + } + const factor = Math.pow(10, 1); // Change the 0 to any number of decimal places you want to keep + const oz = ml * 0.033814; + const roundedOz = Math.ceil(oz * factor) / factor; + return roundedOz; + }); +} + +export { unitValueDisplay };