diff --git a/react-native-to-do-app/.gitignore b/react-native-to-do-app/.gitignore
new file mode 100644
index 0000000..a260560
--- /dev/null
+++ b/react-native-to-do-app/.gitignore
@@ -0,0 +1,40 @@
+# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files
+
+# dependencies
+node_modules/
+
+# Expo
+.expo/
+dist/
+web-build/
+
+# Native
+*.orig.*
+*.jks
+*.p8
+*.p12
+*.key
+*.mobileprovision
+
+# Metro
+.metro-health-check*
+
+# debug
+npm-debug.*
+yarn-debug.*
+yarn-error.*
+
+# macOS
+.DS_Store
+*.pem
+
+# local env files
+.env*.local
+
+# typescript
+*.tsbuildinfo
+
+.env
+
+/android
+/ios
\ No newline at end of file
diff --git a/react-native-to-do-app/App.js b/react-native-to-do-app/App.js
new file mode 100644
index 0000000..d8cf87f
--- /dev/null
+++ b/react-native-to-do-app/App.js
@@ -0,0 +1,29 @@
+import { PaperProvider } from "react-native-paper";
+import { NavigationContainer } from "@react-navigation/native";
+import { createStackNavigator } from "@react-navigation/stack";
+import Cover from "./screens/Cover";
+import Home from "./screens/Home";
+import AddTaskModal from "./components/AddTaskModal";
+import { GestureHandlerRootView } from "react-native-gesture-handler";
+import Categories from './screens/Categories';
+
+export default function App() {
+ const Stack = createStackNavigator();
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/react-native-to-do-app/README.md b/react-native-to-do-app/README.md
new file mode 100644
index 0000000..bf89e75
--- /dev/null
+++ b/react-native-to-do-app/README.md
@@ -0,0 +1,27 @@
+# To Do App
+A simple To Do application built with React Native and Expo for iOS. The app uses [SQLite Cloud](https://sqlitecloud.io/) as a database.
+
+## Features
+- Add Tasks: Create new tasks with titles and optional tags.
+- Edit Task Status: Update task status when completed.
+- Delete Tasks: Remove tasks from your list.
+- Dropdown Menu: Select categories for tasks from a predefined list.
+
+## Set Up
+After you've cloned the repo create a `.env` file and add your SQLite Cloud connection string. Make sure your connection string includes the name of your database before the api key. If the database name isn't included, you'll get an error when you run the application.
+```bash
+DB_CONNECTON_STRING=""
+```
+
+## Installation
+```bash
+npm install
+npm start
+```
+This command will start expo.
+
+## Usage
+Running on Mobile:
+
+Open the Expo Go app on your mobile device.
+Scan the QR code displayed in the terminal.
diff --git a/react-native-to-do-app/app.json b/react-native-to-do-app/app.json
new file mode 100644
index 0000000..e0cccee
--- /dev/null
+++ b/react-native-to-do-app/app.json
@@ -0,0 +1,33 @@
+{
+ "expo": {
+ "name": "mobile-to-do-app",
+ "slug": "mobile-to-do-app",
+ "version": "1.0.0",
+ "orientation": "portrait",
+ "icon": "./assets/icon.png",
+ "userInterfaceStyle": "light",
+ "splash": {
+ "image": "./assets/splash.png",
+ "resizeMode": "contain",
+ "backgroundColor": "#ffffff"
+ },
+ "ios": {
+ "supportsTablet": true
+ },
+ "android": {
+ "adaptiveIcon": {
+ "foregroundImage": "./assets/adaptive-icon.png",
+ "backgroundColor": "#ffffff"
+ }
+ },
+ "web": {
+ "favicon": "./assets/favicon.png"
+ },
+ "extra": {
+ "eas": {
+ "projectId": "faffd54b-fc15-4368-987a-a73b08640cfd"
+ }
+ },
+ "owner": "unatarajan"
+ }
+}
diff --git a/react-native-to-do-app/assets/adaptive-icon.png b/react-native-to-do-app/assets/adaptive-icon.png
new file mode 100644
index 0000000..03d6f6b
Binary files /dev/null and b/react-native-to-do-app/assets/adaptive-icon.png differ
diff --git a/react-native-to-do-app/assets/favicon.png b/react-native-to-do-app/assets/favicon.png
new file mode 100644
index 0000000..e75f697
Binary files /dev/null and b/react-native-to-do-app/assets/favicon.png differ
diff --git a/react-native-to-do-app/assets/icon.png b/react-native-to-do-app/assets/icon.png
new file mode 100644
index 0000000..a0b1526
Binary files /dev/null and b/react-native-to-do-app/assets/icon.png differ
diff --git a/react-native-to-do-app/assets/splash.png b/react-native-to-do-app/assets/splash.png
new file mode 100644
index 0000000..0e89705
Binary files /dev/null and b/react-native-to-do-app/assets/splash.png differ
diff --git a/react-native-to-do-app/babel.config.js b/react-native-to-do-app/babel.config.js
new file mode 100644
index 0000000..00d8949
--- /dev/null
+++ b/react-native-to-do-app/babel.config.js
@@ -0,0 +1,16 @@
+module.exports = function (api) {
+ api.cache(false);
+ return {
+ presets: ["babel-preset-expo"],
+ plugins: [
+ "react-native-paper/babel",
+ [
+ "module:react-native-dotenv",
+ {
+ moduleName: "@env",
+ path: ".env",
+ },
+ ],
+ ],
+ };
+};
diff --git a/react-native-to-do-app/components/AddTaskModal.js b/react-native-to-do-app/components/AddTaskModal.js
new file mode 100644
index 0000000..5195205
--- /dev/null
+++ b/react-native-to-do-app/components/AddTaskModal.js
@@ -0,0 +1,125 @@
+import React, { useState, useEffect } from "react";
+import { View, StyleSheet, Alert, Platform } from "react-native";
+import { TextInput, Button, Modal } from "react-native-paper";
+import DropdownMenu from "./DropdownMenu";
+import db from "../db/dbConnection";
+
+export default AddTaskModal = ({
+ modalVisible,
+ addTaskTag,
+ setModalVisible,
+}) => {
+ const [taskTitle, setTaskTitle] = useState("");
+ const [tagsList, setTagsList] = useState([]);
+ const [selectedTag, setSelectedTag] = useState({});
+
+ const closeModal = () => {
+ setModalVisible(false);
+ };
+
+ const handleAddTask = () => {
+ if (taskTitle.trim()) {
+ addTaskTag({ title: taskTitle.trim(), isCompleted: false }, selectedTag);
+ setTaskTitle("");
+ setSelectedTag({});
+ closeModal();
+ } else {
+ Alert.alert("Please add a new task.");
+ }
+ };
+
+ const getTags = async () => {
+ try {
+ const tags = await db.sql("SELECT * FROM tags");
+ setTagsList(tags);
+ } catch (error) {
+ console.error("Error getting tags", error);
+ }
+ };
+
+ useEffect(() => {
+ getTags();
+ }, []);
+
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ modalContainer: {
+ flex: 1,
+ backgroundColor: "white",
+ padding: 10,
+ },
+ newTaskBox: {
+ flexDirection: "row",
+ alignItems: "center",
+ justifyContent: "center",
+ borderWidth: 1,
+ borderColor: "lightgray",
+ backgroundColor: "#f0f5fd",
+ marginBottom: 10,
+ },
+ textInput: {
+ width: "100%",
+ backgroundColor: "transparent",
+ height: 50,
+ },
+ textInputContent: {
+ backgroundColor: "transparennt",
+ borderWidth: 0,
+ paddingLeft: 10,
+ },
+ button: {
+ height: 50,
+ width: 50,
+ justifyContent: "center",
+ alignItems: "center",
+ },
+ closeButton: {
+ alignItems: "flex-start",
+ bottom: 180,
+ left: -10,
+ zIndex: 1,
+ },
+ addTaskButton: {
+ backgroundColor: "#b2cae9",
+ marginTop: 10,
+ },
+});
diff --git a/react-native-to-do-app/components/DropdownMenu.js b/react-native-to-do-app/components/DropdownMenu.js
new file mode 100644
index 0000000..a0b3eab
--- /dev/null
+++ b/react-native-to-do-app/components/DropdownMenu.js
@@ -0,0 +1,67 @@
+import React from "react";
+import { View, StyleSheet } from "react-native";
+import RNPickerSelect from "react-native-picker-select";
+
+export default DropdownMenu = ({ tagsList, selectedTag, setSelectedTag }) => {
+ const TAGS = tagsList.map((tag) => {
+ return { label: tag.name, value: tag.name };
+ });
+
+ const getTagId = (value) => {
+ const tagId = tagsList.filter((tag) => {
+ return tag.name === value;
+ });
+ return tagId[0]?.id;
+ };
+
+ return (
+
+
+ setSelectedTag({ id: getTagId(value), name: value })
+ }
+ placeholder={{ label: "Select a category", value: null }}
+ value={selectedTag}
+ style={pickerSelectStyles}
+ />
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ borderColor: "lightgray",
+ borderWidth: 1,
+ borderRadius: 5,
+ backgroundColor: "#f0f5fd",
+ marginBottom: 10,
+ },
+});
+
+const pickerSelectStyles = StyleSheet.create({
+ inputIOS: {
+ height: 50,
+ fontSize: 16,
+ paddingVertical: 12,
+ paddingHorizontal: 10,
+ borderWidth: 1,
+ borderColor: "lightgray",
+ borderRadius: 4,
+ color: "black",
+ backgroundColor: "#f0f5fd",
+ paddingRight: 30,
+ },
+ inputAndroid: {
+ height: 50,
+ fontSize: 16,
+ paddingHorizontal: 10,
+ paddingVertical: 8,
+ borderWidth: 1,
+ borderColor: "lightgray",
+ borderRadius: 4,
+ color: "black",
+ backgroundColor: "#f0f5fd",
+ paddingRight: 30,
+ },
+});
diff --git a/react-native-to-do-app/components/TaskRow.js b/react-native-to-do-app/components/TaskRow.js
new file mode 100644
index 0000000..3891b70
--- /dev/null
+++ b/react-native-to-do-app/components/TaskRow.js
@@ -0,0 +1,134 @@
+import React, { useState, useRef } from "react";
+import {
+ View,
+ Text,
+ StyleSheet,
+ TouchableOpacity,
+ Platform,
+} from "react-native";
+import Icon from "react-native-vector-icons/FontAwesome";
+import { Swipeable } from "react-native-gesture-handler";
+
+export default TaskRow = ({ task, updateTask, handleDelete }) => {
+ const { id, title, isCompleted, tag_id, tag_name } = task;
+ const [checked, setChecked] = useState(isCompleted);
+ const swipableRef = useRef(null);
+
+ const handleIconPress = () => {
+ const newCompletedStatus = checked === 1 ? 0 : 1;
+ setChecked(newCompletedStatus);
+ updateTask(newCompletedStatus, id);
+ };
+
+ const renderLeftActions = () => {
+ return (
+ {
+ handleDelete(id);
+ if (swipableRef.current) {
+ swipableRef.current.close();
+ }
+ }}
+ >
+ Delete
+
+ );
+ };
+
+ return Platform.OS === "web" ? (
+
+
+ {checked === 0 ? (
+ {title}
+ ) : (
+ {title}
+ )}
+ {tag_name}
+
+
+
+
+
+ handleDelete(id)}
+ style={styles.webDeleteButton}
+ >
+
+
+
+
+ ) : (
+
+
+
+ {checked === 0 ? (
+ {title}
+ ) : (
+ {title}
+ )}
+ {tag_name}
+
+
+
+
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ taskRow: {
+ flexDirection: "row",
+ justifyContent: "space-between",
+ fontSize: 16,
+ padding: 10,
+ },
+ deleteButton: {
+ backgroundColor: "#6BA2EA",
+ padding: 10,
+ alignItems: "center",
+ justifyContent: "center",
+ },
+ dottedBox: {
+ borderWidth: 1,
+ borderColor: "lightgray",
+ borderStyle: "dashed",
+ },
+ deleteButtonText: {
+ color: "white",
+ },
+ text: {
+ fontSize: 16,
+ },
+ strikethroughText: {
+ textDecorationLine: "line-through",
+ textDecorationColor: "#6BA2EA",
+ fontSize: 16,
+ },
+ tag: {
+ color: "gray",
+ fontSize: 12,
+ marginTop: 5,
+ },
+ taskAndTag: {
+ flexDirection: "column",
+ },
+ webDeleteButton: {
+ marginLeft: 15,
+ },
+ actions: {
+ flexDirection: "row",
+ justifyContent: "center",
+ alignItems: "center"
+ }
+});
diff --git a/react-native-to-do-app/db/dbConnection.js b/react-native-to-do-app/db/dbConnection.js
new file mode 100644
index 0000000..af118bc
--- /dev/null
+++ b/react-native-to-do-app/db/dbConnection.js
@@ -0,0 +1,8 @@
+import { DB_CONNECTION_STRING } from "@env";
+import { Database } from "@sqlitecloud/drivers";
+
+export default db = new Database({
+ connectionstring: DB_CONNECTION_STRING,
+ usewebsocket: true,
+ });
+
diff --git a/react-native-to-do-app/hooks/useCategories.js b/react-native-to-do-app/hooks/useCategories.js
new file mode 100644
index 0000000..f0bda15
--- /dev/null
+++ b/react-native-to-do-app/hooks/useCategories.js
@@ -0,0 +1,78 @@
+import React, { useState, useEffect } from "react";
+import db from "../db/dbConnection";
+
+const useCategories = () => {
+ const [moreCategories, setMoreCategories] = useState(["Work", "Personal"]);
+
+ const getCategories = async () => {
+ try {
+ const tags = await db.sql("SELECT * FROM tags");
+ const filteredTags = tags.filter((tag) => {
+ return tag["name"] !== "Work" && tag["name"] !== "Personal";
+ });
+ setMoreCategories((prevCategories) => [
+ ...prevCategories,
+ ...filteredTags.map((tag) => tag.name),
+ ]);
+ } catch (error) {
+ console.error("Error getting tags/categories", error);
+ }
+ };
+
+ const addCategory = async (newCategory) => {
+ try {
+ await db.sql(
+ "INSERT INTO tags (name) VALUES (?) RETURNING *",
+ newCategory
+ );
+ setMoreCategories((prevCategories) => [...prevCategories, newCategory]);
+ } catch (error) {
+ console.error("Error adding category", error);
+ }
+ };
+
+ const initializeTables = async () => {
+ try {
+ const createTasksTable = await db.sql(
+ "CREATE TABLE IF NOT EXISTS tasks (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, isCompleted INT NOT NULL);"
+ );
+
+ const createTagsTable = await db.sql(
+ "CREATE TABLE IF NOT EXISTS tags (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, UNIQUE(name));"
+ );
+
+ const createTagsTasksTable = await db.sql(
+ "CREATE TABLE IF NOT EXISTS tasks_tags (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, task_id INTEGER NOT NULL, tag_id INTEGER NOT NULL, FOREIGN KEY (task_id) REFERENCES tasks(id), FOREIGN KEY (tag_id) REFERENCES tags(id));"
+ );
+
+ if (
+ createTagsTable === "OK" &&
+ createTagsTable === "OK" &&
+ createTagsTasksTable === "OK"
+ ) {
+ console.log("Successfully created tables");
+
+ await db.sql("INSERT OR IGNORE INTO tags (name) VALUES (?)", "Work");
+ await db.sql(
+ "INSERT OR IGNORE INTO tags (name) VALUES (?)",
+ "Personal"
+ );
+ getCategories();
+ }
+ } catch (error) {
+ console.error("Error creating tables", error);
+ }
+ };
+
+ useEffect(() => {
+ initializeTables();
+ }, []);
+
+ return {
+ moreCategories,
+ addCategory,
+ getCategories,
+ };
+};
+
+export default useCategories;
diff --git a/react-native-to-do-app/hooks/useTasks.js b/react-native-to-do-app/hooks/useTasks.js
new file mode 100644
index 0000000..534747e
--- /dev/null
+++ b/react-native-to-do-app/hooks/useTasks.js
@@ -0,0 +1,100 @@
+import React, { useState, useEffect, useCallback } from "react";
+import db from "../db/dbConnection";
+
+const useTasks = (tag = null) => {
+ const [taskList, setTaskList] = useState([]);
+
+ const getTasks = useCallback(async () => {
+ try {
+ let result;
+ if (tag) {
+ result = await db.sql(
+ `
+ SELECT tasks.*, tags.id AS tag_id, tags.name AS tag_name
+ FROM tasks
+ JOIN tasks_tags ON tasks.id = tasks_tags.task_id
+ JOIN tags ON tags.id = tasks_tags.tag_id
+ WHERE tag_name=?`,
+ tag
+ );
+ setTaskList(result);
+ } else {
+ result = await db.sql`
+ SELECT tasks.*, tags.id AS tag_id, tags.name AS tag_name
+ FROM tasks
+ JOIN tasks_tags ON tasks.id = tasks_tags.task_id
+ JOIN tags ON tags.id = tasks_tags.tag_id`;
+ setTaskList(result);
+ }
+ } catch (error) {
+ console.error("Error getting tasks", error);
+ }
+ }, [tag, taskList]);
+
+ const updateTask = async (completedStatus, taskId) => {
+ try {
+ const task = await db.sql(
+ "UPDATE tasks SET isCompleted=? WHERE id=? RETURNING *",
+ completedStatus,
+ taskId
+ );
+ getTasks();
+ } catch (error) {
+ console.error("Error updating tasks", error);
+ }
+ };
+
+ const addTaskTag = async (newTask, tag) => {
+ try {
+ if (tag.id) {
+ const addNewTask = await db.sql(
+ "INSERT INTO tasks (title, isCompleted) VALUES (?, ?) RETURNING *",
+ newTask.title,
+ newTask.isCompleted
+ );
+ addNewTask[0].tag_id = tag.id;
+ addNewTask[0].tag_name = tag.name;
+ setTaskList([...taskList, addNewTask[0]]);
+ await db.sql(
+ "INSERT INTO tasks_tags (task_id, tag_id) VALUES (?, ?)",
+ addNewTask[0].id,
+ tag.id
+ );
+ } else {
+ const addNewTaskNoTag = await db.sql(
+ "INSERT INTO tasks (title, isCompleted) VALUES (?, ?) RETURNING *",
+ newTask.title,
+ newTask.isCompleted
+ );
+ setTaskList([...taskList, addNewTaskNoTag[0]]);
+ }
+ } catch (error) {
+ console.error("Error adding task to database", error);
+ }
+ };
+
+ const deleteTask = async (taskId) => {
+ try {
+ await db.sql("DELETE FROM tasks_tags WHERE task_id=?", taskId);
+ const result = await db.sql("DELETE FROM tasks WHERE id=?", taskId);
+ console.log(`deleted ${result[0].TOTAL_CHANGES} task`);
+ getTasks();
+ } catch (error) {
+ console.error("Error deleting task", error);
+ }
+ };
+
+ useEffect(() => {
+ getTasks();
+ }, [getTasks]);
+
+ return {
+ taskList,
+ updateTask,
+ addTaskTag,
+ deleteTask,
+ refreshTasks: getTasks,
+ };
+};
+
+export default useTasks;
diff --git a/react-native-to-do-app/package.json b/react-native-to-do-app/package.json
new file mode 100644
index 0000000..46890e3
--- /dev/null
+++ b/react-native-to-do-app/package.json
@@ -0,0 +1,41 @@
+{
+ "name": "mobile-to-do-app",
+ "version": "1.0.0",
+ "main": "expo/AppEntry.js",
+ "scripts": {
+ "start": "expo start",
+ "android": "expo start --android",
+ "ios": "expo start --ios",
+ "web": "expo start --web"
+ },
+ "dependencies": {
+ "@expo/metro-runtime": "~3.2.1",
+ "@react-native-community/masked-view": "^0.1.11",
+ "@react-navigation/native": "^6.1.18",
+ "@react-navigation/stack": "^6.4.1",
+ "@sqlitecloud/drivers": "^1.0.193",
+ "expo": "~51.0.25",
+ "expo-status-bar": "~1.12.1",
+ "react": "18.2.0",
+ "react-dom": "18.2.0",
+ "react-native": "0.74.5",
+ "react-native-gesture-handler": "~2.16.1",
+ "react-native-paper": "^5.12.5",
+ "react-native-picker-select": "^9.3.1",
+ "react-native-reanimated": "~3.10.1",
+ "react-native-safe-area-context": "4.10.5",
+ "react-native-screens": "3.31.1",
+ "react-native-vector-icons": "^10.1.0",
+ "react-native-walkthrough-tooltip": "^1.6.0",
+ "react-native-web": "~0.19.10"
+ },
+ "devDependencies": {
+ "@babel/core": "^7.20.0",
+ "react-native-dotenv": "^3.4.11"
+ },
+ "resolutions": {
+ "@babel/core": "^7.20.2",
+ "babel-loader": "^8.3.0"
+ },
+ "private": true
+}
diff --git a/react-native-to-do-app/screens/Categories.js b/react-native-to-do-app/screens/Categories.js
new file mode 100644
index 0000000..e032c44
--- /dev/null
+++ b/react-native-to-do-app/screens/Categories.js
@@ -0,0 +1,219 @@
+import React, { useState, useEffect } from "react";
+import { ScrollView, StyleSheet, View } from "react-native";
+import {
+ Avatar,
+ Card,
+ Text,
+ Modal,
+ Portal,
+ Button,
+ TextInput,
+} from "react-native-paper";
+import useCategories from "../hooks/useCategories";
+
+const Categories = ({ navigation }) => {
+ const today = new Date();
+ const days = [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday",
+ ];
+ const dayIndex = today.getDay();
+ const monthDate = today.toLocaleDateString("en-US", {
+ month: "long",
+ day: "numeric",
+ });
+
+ const {moreCategories, addCategory} = useCategories();
+
+ const [newCategory, setNewCategory] = useState("");
+ const [visible, setVisible] = React.useState(false);
+
+ const showModal = () => setVisible(true);
+ const hideModal = () => setVisible(false);
+
+ function handleAddCategory() {
+ if (newCategory) {
+ addCategory(newCategory);
+ }
+ setNewCategory("");
+ hideModal();
+ }
+
+ return (
+ <>
+
+
+ setNewCategory(newCategory)}
+ keyboardType="default"
+ activeUnderlineColor="#6ba2ea"
+ underlineColor="none"
+ activeOutlineColor="#fff"
+ outlineColor="none"
+ />
+
+
+
+
+
+ {days[dayIndex]}
+
+
+ {monthDate}
+
+
+ navigation.navigate("Tasks")}
+ mode="contained"
+ >
+ (
+
+ )}
+ />
+
+
+ Inbox
+
+
+
+ {moreCategories.map((category, index) => (
+ navigation.navigate("Tasks", {category})}
+ mode="contained"
+ >
+ (
+
+ )}
+ />
+
+
+ {category}
+
+
+ ))}
+
+
+ (
+
+ )}
+ />
+
+
+ {" "}
+
+
+
+
+ >
+ );
+};
+
+Categories.title = "Categories";
+
+const styles = StyleSheet.create({
+ container: {
+ backgroundColor: "#fff",
+ },
+ content: {
+ padding: 10,
+ },
+ cardRow: {
+ flexDirection: "row",
+ flexWrap: "wrap",
+ justifyContent: "space-between",
+ },
+ card: {
+ backgroundColor: "#cfe2f8",
+ margin: 5,
+ width: "47%",
+ },
+ addCard: {
+ backgroundColor: "#fff",
+ margin: 5,
+ borderWidth: 1,
+ borderStyle: "dashed",
+ borderColor: "#6BA2EA",
+ width: "47%",
+ },
+ icon: {
+ backgroundColor: "#cfe2f8",
+ color: "#6b7280",
+ },
+ addIcon: {
+ backgroundColor: "#fff",
+ color: "#6BA2EA",
+ },
+ text: {
+ color: "#6b7280",
+ padding: 15,
+ },
+ button: {
+ borderRadius: "none",
+ backgroundColor: "#b2cae9",
+ color: "#000",
+ },
+ textInput: {
+ backgroundColor: "#f0f5fd",
+ },
+});
+
+export default Categories;
diff --git a/react-native-to-do-app/screens/Cover.js b/react-native-to-do-app/screens/Cover.js
new file mode 100644
index 0000000..ff1abef
--- /dev/null
+++ b/react-native-to-do-app/screens/Cover.js
@@ -0,0 +1,44 @@
+import React from 'react';
+import { StatusBar } from 'expo-status-bar';
+import { View, Text, StyleSheet } from 'react-native';
+import { Button } from 'react-native-paper';
+
+export default Cover = ({ navigation }) => {
+ return (
+
+ Organize Your
+ Tasks with SQLite
+ Designed for Happiness, Not Just Productivity.
+ Enjoy a Stress-free Way to Manage Your Day.
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: '#fff',
+ alignItems: 'flex-start',
+ justifyContent: 'center',
+ paddingLeft: 15,
+ },
+ heading: {
+ fontWeight: 'bold',
+ fontSize: 40,
+ marginBottom: 5,
+ },
+ button: {
+ position: 'absolute',
+ bottom: 70,
+ right: 20,
+ },
+});
diff --git a/react-native-to-do-app/screens/Home.js b/react-native-to-do-app/screens/Home.js
new file mode 100644
index 0000000..342c1f3
--- /dev/null
+++ b/react-native-to-do-app/screens/Home.js
@@ -0,0 +1,107 @@
+import React, { useState, useEffect } from "react";
+import {
+ View,
+ Text,
+ StyleSheet,
+ FlatList,
+ Alert,
+ Platform,
+} from "react-native";
+import { Button } from "react-native-paper";
+import Icon from "react-native-vector-icons/FontAwesome";
+import TaskRow from "../components/TaskRow";
+import AddTaskModal from "../components/AddTaskModal";
+import useTasks from "../hooks/useTasks"
+
+export default Home = ({ route }) => {
+ const [modalVisible, setModalVisible] = useState(false);
+
+ const tag = route.params?.category;
+
+ const {taskList, updateTask, addTaskTag, deleteTask} = useTasks(tag)
+
+ const today = new Date();
+ const options = { year: "numeric", month: "long", day: "numeric" };
+ const formattedDate = today.toLocaleDateString("en-US", options);
+
+ const handleDelete = (taskId) => {
+ console.log(taskId);
+ if (Platform.OS === "web") {
+ const confirmDelete = window.confirm(
+ "Are you sure you want to delete this task?"
+ );
+ if (confirmDelete) {
+ deleteTask(taskId);
+ }
+ } else {
+ Alert.alert(
+ "Confirm Delete",
+ "Are you sure you want to delete this task?",
+ [
+ {
+ text: "Cancel",
+ style: "cancel",
+ },
+ {
+ text: "Delete",
+ onPress: () => deleteTask(taskId),
+ style: "destructive",
+ },
+ ]
+ );
+ }
+ };
+
+ return (
+
+ {formattedDate}
+ index}
+ renderItem={({ item }) => (
+
+ )}
+ />
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: "white",
+ padding: 20,
+ },
+ date: {
+ color: "gray",
+ marginTop: 50,
+ fontSize: 16,
+ },
+ button: {
+ backgroundColor: "#6BA2EA",
+ position: "absolute",
+ bottom: 70,
+ right: 20,
+ },
+ taskList: {
+ paddingTop: 40,
+ },
+});