From 5b7230db4a025e4e2af4094d699fbec2b23ef8bc Mon Sep 17 00:00:00 2001 From: Alexandre Date: Thu, 6 Mar 2025 12:55:43 +0100 Subject: [PATCH] Added some features --- App.js | 101 +++------- components/ColorPicker.js | 39 ++++ constants/Colors.js | 0 context/SettingsContext.js | 44 +++++ package-lock.json | 388 ++++++++++++++++++++++++++++++++++++- package.json | 8 +- screens/Landing.js | 41 ++++ screens/MainScreen.js | 111 +++++++++++ screens/Settings.js | 68 +++++++ 9 files changed, 726 insertions(+), 74 deletions(-) create mode 100644 components/ColorPicker.js create mode 100644 constants/Colors.js create mode 100644 context/SettingsContext.js create mode 100644 screens/Landing.js create mode 100644 screens/MainScreen.js create mode 100644 screens/Settings.js diff --git a/App.js b/App.js index 85154e9..3817e30 100644 --- a/App.js +++ b/App.js @@ -1,79 +1,38 @@ -import { StatusBar } from "expo-status-bar"; -import { - KeyboardAvoidingView, - Platform, - StyleSheet, - Text, - TextInput, - View, - TouchableOpacity, - Keyboard, - ScrollView, -} from "react-native"; -import React, { useState } from "react"; -import Task from "./components/Task"; +import "react-native-gesture-handler"; +import { useState } from "react"; +import { NavigationContainer } from "@react-navigation/native"; +import { createDrawerNavigator } from "@react-navigation/drawer"; +import { SettingsProvider } from "./context/SettingsContext"; +import LandingScreen from "./screens/LandingScreen"; +import MainScreen from "./screens/MainScreen"; +import SettingsScreen from "./screens/SettingsScreen"; + +const Drawer = createDrawerNavigator(); export default function App() { - const [task, setTask] = useState(); - const [taskItems, setTaskItems] = useState([]); + const [showLanding, setShowLanding] = useState(true); - const handleAddTask = () => { - Keyboard.dismiss(); - setTaskItems([...taskItems, task]); - setTask(null); - }; - - const completeTask = (index) => { - let itemsCopy = [...taskItems]; - itemsCopy.splice(index, 1); - setTaskItems(itemsCopy); - }; + if (showLanding) { + return setShowLanding(false)} />; + } return ( - - - {/* Today's Tasks */} - - Today's tasks - - {/* This is where the tasks will go! */} - {taskItems.map((item, index) => { - return ( - completeTask(index)} - > - - - ); - })} - - - - - {/* Write a task */} - - setTask(text)} - /> - handleAddTask()}> - - + - - - - + + + + + + + + ); } diff --git a/components/ColorPicker.js b/components/ColorPicker.js new file mode 100644 index 0000000..55e5700 --- /dev/null +++ b/components/ColorPicker.js @@ -0,0 +1,39 @@ +import { View, TouchableOpacity, StyleSheet } from "react-native"; +import { useSettings } from "../context/SettingsContext"; + +const COLORS = ["#5784BA", "#9C6ADE", "#FF6B6B", "#4ECDC4", "#45B7D1"]; + +export default function ColorPicker({ selectedColor, onColorSelect }) { + return ( + + {COLORS.map((color) => ( + onColorSelect(color)} + /> + ))} + + ); +} + +const styles = StyleSheet.create({ + container: { + flexDirection: "row", + gap: 10, + }, + colorOption: { + width: 30, + height: 30, + borderRadius: 15, + borderWidth: 2, + borderColor: "transparent", + }, + selected: { + borderColor: "black", + }, +}); diff --git a/constants/Colors.js b/constants/Colors.js new file mode 100644 index 0000000..e69de29 diff --git a/context/SettingsContext.js b/context/SettingsContext.js new file mode 100644 index 0000000..776ea59 --- /dev/null +++ b/context/SettingsContext.js @@ -0,0 +1,44 @@ +import React, { createContext, useState, useEffect } from "react"; +import AsyncStorage from "@react-native-async-storage/async-storage"; + +const defaultSettings = { + theme: "light", + accentColor: "#5784BA", + notifications: true, +}; + +const SettingsContext = createContext(); + +export const SettingsProvider = ({ children }) => { + const [settings, setSettings] = useState(defaultSettings); + + useEffect(() => { + loadSettings(); + }, []); + + const loadSettings = async () => { + try { + const storedSettings = await AsyncStorage.getItem("@settings"); + if (storedSettings) setSettings(JSON.parse(storedSettings)); + } catch (e) { + console.error("Failed to load settings"); + } + }; + + const saveSettings = async (newSettings) => { + try { + await AsyncStorage.setItem("@settings", JSON.stringify(newSettings)); + setSettings(newSettings); + } catch (e) { + console.error("Failed to save settings"); + } + }; + + return ( + + {children} + + ); +}; + +export const useSettings = () => React.useContext(SettingsContext); diff --git a/package-lock.json b/package-lock.json index 01cbc75..7d73bb4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,10 +9,16 @@ "version": "1.0.0", "license": "0BSD", "dependencies": { + "@react-native-async-storage/async-storage": "1.23.1", + "@react-navigation/drawer": "^7.1.2", + "@react-navigation/native": "^7.0.15", + "async-storage": "^0.1.0", "expo": "~52.0.37", "expo-status-bar": "~2.0.1", "react": "18.3.1", - "react-native": "0.76.7" + "react-native": "0.76.7", + "react-native-gesture-handler": "~2.20.2", + "react-native-reanimated": "~3.16.1" }, "devDependencies": { "@babel/core": "^7.20.0", @@ -1803,7 +1809,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.26.8.tgz", "integrity": "sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.26.5" }, @@ -2179,6 +2184,18 @@ "node": ">=6.9.0" } }, + "node_modules/@egjs/hammerjs": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz", + "integrity": "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==", + "license": "MIT", + "dependencies": { + "@types/hammerjs": "^2.0.36" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/@expo/bunyan": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@expo/bunyan/-/bunyan-4.0.1.tgz", @@ -3215,6 +3232,18 @@ "node": ">=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==", + "license": "MIT", + "dependencies": { + "merge-options": "^3.0.4" + }, + "peerDependencies": { + "react-native": "^0.0.0-0 || >=0.60 <1.0" + } + }, "node_modules/@react-native-community/cli": { "version": "17.0.0", "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-17.0.0.tgz", @@ -4856,6 +4885,92 @@ } } }, + "node_modules/@react-navigation/core": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-7.4.0.tgz", + "integrity": "sha512-URiDluFl7cLA7GtOAsEvRqPmEMlSSXadqQ3wi9+Dl43dNRMqnoF76WQ9BCXeUPLydJq4yVte9XeMPyD6a0lY1g==", + "license": "MIT", + "dependencies": { + "@react-navigation/routers": "^7.2.0", + "escape-string-regexp": "^4.0.0", + "nanoid": "3.3.8", + "query-string": "^7.1.3", + "react-is": "^18.2.0", + "use-latest-callback": "^0.2.1", + "use-sync-external-store": "^1.2.2" + }, + "peerDependencies": { + "react": ">= 18.2.0" + } + }, + "node_modules/@react-navigation/drawer": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@react-navigation/drawer/-/drawer-7.1.2.tgz", + "integrity": "sha512-EIlS5PPzVQ9WJ4xQZytAUTXiVbZcUYfPFlkaAWZHIl7O/suoJIpu52yXwjbjG0XhNu6Vup23W35HJWHxpgKQEQ==", + "license": "MIT", + "dependencies": { + "@react-navigation/elements": "^2.2.6", + "color": "^4.2.3", + "react-native-drawer-layout": "^4.1.1", + "use-latest-callback": "^0.2.1" + }, + "peerDependencies": { + "@react-navigation/native": "^7.0.15", + "react": ">= 18.2.0", + "react-native": "*", + "react-native-gesture-handler": ">= 2.0.0", + "react-native-reanimated": ">= 2.0.0", + "react-native-safe-area-context": ">= 4.0.0", + "react-native-screens": ">= 4.0.0" + } + }, + "node_modules/@react-navigation/elements": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-2.2.6.tgz", + "integrity": "sha512-UPeaCcEDSDRaxjG+qEHbur6jmNW/f9QNCyPsUt6NMgPEdbB5Z8K8oSx2swIaiCnvUbs/K5G3MuWkqQxGj8QXXA==", + "license": "MIT", + "dependencies": { + "color": "^4.2.3" + }, + "peerDependencies": { + "@react-native-masked-view/masked-view": ">= 0.2.0", + "@react-navigation/native": "^7.0.15", + "react": ">= 18.2.0", + "react-native": "*", + "react-native-safe-area-context": ">= 4.0.0" + }, + "peerDependenciesMeta": { + "@react-native-masked-view/masked-view": { + "optional": true + } + } + }, + "node_modules/@react-navigation/native": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-7.0.15.tgz", + "integrity": "sha512-72PabJJ8VY3GM8i/DCutFW+ATED96ZV6NH+bW+ry1EL0ZFGHoie96H+KzTqktsrUbBw1rd9KXbEQhBQgo0N7iQ==", + "license": "MIT", + "dependencies": { + "@react-navigation/core": "^7.4.0", + "escape-string-regexp": "^4.0.0", + "fast-deep-equal": "^3.1.3", + "nanoid": "3.3.8", + "use-latest-callback": "^0.2.1" + }, + "peerDependencies": { + "react": ">= 18.2.0", + "react-native": "*" + } + }, + "node_modules/@react-navigation/routers": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-7.2.0.tgz", + "integrity": "sha512-lMyib39H4a//u+eiyt162U6TwCfI8zJbjl9ovjKtDddQ4/Vf7b8/OhyimnJH09N2CBfm4pv0gCV6Q0WnZcfaJg==", + "license": "MIT", + "dependencies": { + "nanoid": "3.3.8" + } + }, "node_modules/@segment/loosely-validate-event": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@segment/loosely-validate-event/-/loosely-validate-event-2.0.0.tgz", @@ -4963,6 +5078,12 @@ "@types/node": "*" } }, + "node_modules/@types/hammerjs": { + "version": "2.0.46", + "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.46.tgz", + "integrity": "sha512-ynRvcq6wvqexJ9brDMS4BnBLzmr0e14d6ZJTEShTBWKymQiHwlAyGu0ZPEFI2Fh1U53F7tN9ufClWM5KvqkKOw==", + "license": "MIT" + }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", @@ -5298,6 +5419,16 @@ "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", "license": "MIT" }, + "node_modules/async-storage": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/async-storage/-/async-storage-0.1.0.tgz", + "integrity": "sha512-29i3KfI7o9YNmqtR3ecY1KqOuM5/Goos3SHzIwvXNYgQMS4ggB+YQ38DC1FVY+Cc4SxiMLy9J4IRZHZ5q5gDpw==", + "license": "MPL", + "engines": { + "fennec": ">=27.0 <=30.0", + "firefox": ">=27.0" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -6115,6 +6246,19 @@ "node": ">=6" } }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -6133,6 +6277,16 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, "node_modules/colorette": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", @@ -6391,6 +6545,15 @@ "node": ">=0.10.0" } }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -7074,6 +7237,12 @@ "integrity": "sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==", "license": "Apache-2.0" }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, "node_modules/fast-glob": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", @@ -7181,6 +7350,15 @@ "node": ">=8" } }, + "node_modules/filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/finalhandler": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", @@ -7629,6 +7807,21 @@ "hermes-estree": "0.23.1" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, "node_modules/hosted-git-info": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", @@ -7959,6 +8152,15 @@ "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==", + "license": "MIT", + "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", @@ -9077,6 +9279,18 @@ "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", "license": "MIT" }, + "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==", + "license": "MIT", + "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", @@ -10596,6 +10810,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/query-string": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", + "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==", + "license": "MIT", + "dependencies": { + "decode-uri-component": "^0.2.2", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/queue": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", @@ -10708,6 +10940,19 @@ } } }, + "node_modules/react-freeze": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/react-freeze/-/react-freeze-1.0.4.tgz", + "integrity": "sha512-r4F0Sec0BLxWicc7HEyo2x3/2icUTrRmDjaaRyzzn+7aDyFZliszMDOgLVwSnQnYENOlL1o569Ze2HZefk8clA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=17.0.0" + } + }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -10775,6 +11020,87 @@ } } }, + "node_modules/react-native-drawer-layout": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/react-native-drawer-layout/-/react-native-drawer-layout-4.1.1.tgz", + "integrity": "sha512-ob6O3ph7PZ3A2FpdlsSxHuMpHDXREZPR8A6S3q0dSxV7i6d+8Z6CPCTbegfN2QZyizSow9NLrKyXP93tlqZ3dA==", + "license": "MIT", + "dependencies": { + "use-latest-callback": "^0.2.1" + }, + "peerDependencies": { + "react": ">= 18.2.0", + "react-native": "*", + "react-native-gesture-handler": ">= 2.0.0", + "react-native-reanimated": ">= 2.0.0" + } + }, + "node_modules/react-native-gesture-handler": { + "version": "2.20.2", + "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.20.2.tgz", + "integrity": "sha512-HqzFpFczV4qCnwKlvSAvpzEXisL+Z9fsR08YV5LfJDkzuArMhBu2sOoSPUF/K62PCoAb+ObGlTC83TKHfUd0vg==", + "license": "MIT", + "dependencies": { + "@egjs/hammerjs": "^2.0.17", + "hoist-non-react-statics": "^3.3.0", + "invariant": "^2.2.4", + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-native-reanimated": { + "version": "3.16.7", + "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.16.7.tgz", + "integrity": "sha512-qoUUQOwE1pHlmQ9cXTJ2MX9FQ9eHllopCLiWOkDkp6CER95ZWeXhJCP4cSm6AD4jigL5jHcZf/SkWrg8ttZUsw==", + "license": "MIT", + "dependencies": { + "@babel/plugin-transform-arrow-functions": "^7.0.0-0", + "@babel/plugin-transform-class-properties": "^7.0.0-0", + "@babel/plugin-transform-classes": "^7.0.0-0", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.0.0-0", + "@babel/plugin-transform-optional-chaining": "^7.0.0-0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0-0", + "@babel/plugin-transform-template-literals": "^7.0.0-0", + "@babel/plugin-transform-unicode-regex": "^7.0.0-0", + "@babel/preset-typescript": "^7.16.7", + "convert-source-map": "^2.0.0", + "invariant": "^2.2.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0", + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-native-safe-area-context": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.3.0.tgz", + "integrity": "sha512-glV9bwuozTjf/JDBIBm+ITnukHNaUT3nucgdeADwjtHsfEN3RL5UO6nq99vvdWv5j/O9yCZBvFncM1BBQ+UvpQ==", + "license": "MIT", + "peer": true, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-native-screens": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-4.9.1.tgz", + "integrity": "sha512-3pIOu1YXTDClQfkgk2t7rIr7unrV6bviaXRJsOq1APNHLeCPrJ6m5Gy3pW5Ty+XBm9jRAbMqhpjiXZIjesOR6A==", + "license": "MIT", + "peer": true, + "dependencies": { + "react-freeze": "^1.0.0", + "warn-once": "^0.1.0" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, "node_modules/react-native/node_modules/babel-plugin-syntax-hermes-parser": { "version": "0.23.1", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.23.1.tgz", @@ -11589,6 +11915,21 @@ "node": ">= 5.10.0" } }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "license": "MIT" + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -11717,6 +12058,15 @@ "node": "*" } }, + "node_modules/split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -11801,6 +12151,15 @@ "node": ">= 0.10.0" } }, + "node_modules/strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -12553,6 +12912,24 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/use-latest-callback": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.2.3.tgz", + "integrity": "sha512-7vI3fBuyRcP91pazVboc4qu+6ZqM8izPWX9k7cRnT8hbD5svslcknsh3S9BUhaK11OmgTV4oWZZVSeQAiV53SQ==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz", + "integrity": "sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -12611,6 +12988,13 @@ "makeerror": "1.0.12" } }, + "node_modules/warn-once": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/warn-once/-/warn-once-0.1.1.tgz", + "integrity": "sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q==", + "license": "MIT", + "peer": true + }, "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", diff --git a/package.json b/package.json index de59267..c8bf4ed 100644 --- a/package.json +++ b/package.json @@ -10,10 +10,16 @@ "web": "expo start --web" }, "dependencies": { + "@react-navigation/drawer": "^7.1.2", + "@react-navigation/native": "^7.0.15", + "async-storage": "^0.1.0", "expo": "~52.0.37", "expo-status-bar": "~2.0.1", "react": "18.3.1", - "react-native": "0.76.7" + "react-native": "0.76.7", + "react-native-gesture-handler": "~2.20.2", + "react-native-reanimated": "~3.16.1", + "@react-native-async-storage/async-storage": "1.23.1" }, "devDependencies": { "@babel/core": "^7.20.0", diff --git a/screens/Landing.js b/screens/Landing.js new file mode 100644 index 0000000..d838042 --- /dev/null +++ b/screens/Landing.js @@ -0,0 +1,41 @@ +import { View, Text, StyleSheet, TouchableOpacity } from "react-native"; +import { useSettings } from "../context/SettingsContext"; + +export default function LandingScreen({ onFinish }) { + const { settings } = useSettings(); + + return ( + + Welcome to TodoApp + Customize your experience + + + Get Started + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: "center", + alignItems: "center", + padding: 20, + }, + title: { + fontSize: 32, + color: "white", + marginBottom: 20, + }, + button: { + backgroundColor: "white", + padding: 15, + borderRadius: 25, + marginTop: 30, + }, + buttonText: { + color: "#5784BA", + fontSize: 18, + }, +}); diff --git a/screens/MainScreen.js b/screens/MainScreen.js new file mode 100644 index 0000000..36e75ac --- /dev/null +++ b/screens/MainScreen.js @@ -0,0 +1,111 @@ +import React, { useState, useEffect } from "react"; +import { + KeyboardAvoidingView, + Platform, + StyleSheet, + ScrollView, + TouchableOpacity, + Keyboard, +} from "react-native"; +import { useSettings } from "../context/SettingsContext"; +import AsyncStorage from "@react-native-async-storage/async-storage"; +import Task from "../components/Task"; + +export default function MainScreen() { + const [task, setTask] = useState(); + const [taskItems, setTaskItems] = useState([]); + const { settings } = useSettings(); + + // Add persistence logic here + useEffect(() => { + loadTasks(); + }, []); + + const loadTasks = async () => { + try { + const storedTasks = await AsyncStorage.getItem("@tasks"); + if (storedTasks) setTaskItems(JSON.parse(storedTasks)); + } catch (e) { + console.error("Failed to load tasks"); + } + }; + + const saveTasks = async (tasks) => { + try { + await AsyncStorage.setItem("@tasks", JSON.stringify(tasks)); + } catch (e) { + console.error("Failed to save tasks"); + } + }; + + const handleAddTask = () => { + Keyboard.dismiss(); + const newTasks = [...taskItems, task]; + setTaskItems(newTasks); + saveTasks(newTasks); + setTask(null); + }; + + const completeTask = (index) => { + const newTasks = taskItems.filter((_, i) => i !== index); + setTaskItems(newTasks); + saveTasks(newTasks); + }; + + return ( + + {/* Rest of your original App.js JSX here */} + {/* Keep all the ScrollView and KeyboardAvoidingView code */} + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: "#E8EAED", + }, + tasksWrapper: { + paddingTop: 80, + paddingHorizontal: 20, + }, + sectionTitle: { + fontSize: 24, + fontWeight: "bold", + }, + items: { + marginTop: 30, + }, + writeTaskWrapper: { + position: "absolute", + bottom: 60, + width: "100%", + flexDirection: "row", + alignItems: "center", + justifyContent: "space-around", + }, + input: { + paddingVertical: 15, + paddingHorizontal: 15, + backgroundColor: "#FFF", + borderRadius: 60, + borderColor: "#C0C0C0", + borderWidth: 1, + width: 250, + }, + addWrapper: { + width: 60, + height: 60, + backgroundColor: "#FFF", + borderRadius: 60, + justifyContent: "center", + alignItems: "center", + borderColor: "#C0C0C0", + borderWidth: 1, + }, +}); diff --git a/screens/Settings.js b/screens/Settings.js new file mode 100644 index 0000000..214dd81 --- /dev/null +++ b/screens/Settings.js @@ -0,0 +1,68 @@ +import { View, Text, Switch, StyleSheet } from "react-native"; +import { useSettings } from "../context/SettingsContext"; +import ColorPicker from "../components/ColorPicker"; + +export default function SettingsScreen() { + const { settings, saveSettings } = useSettings(); + + const handleColorChange = (color) => { + saveSettings({ ...settings, accentColor: color }); + }; + + return ( + + Settings + + + Dark Mode + + saveSettings({ + ...settings, + theme: val ? "dark" : "light", + }) + } + /> + + + + Accent Color + + + + + Enable Notifications + + saveSettings({ ...settings, notifications: val }) + } + /> + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + padding: 20, + }, + header: { + fontSize: 24, + marginBottom: 20, + }, + settingItem: { + flexDirection: "row", + justifyContent: "space-between", + alignItems: "center", + marginVertical: 15, + padding: 10, + backgroundColor: "#f5f5f5", + borderRadius: 10, + }, +});