diff --git a/babel.config.js b/babel.config.js
index 5f0e9ee..50f2163 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -4,8 +4,6 @@ function config( api ) {
presets: [
'babel-preset-expo',
'@babel/preset-typescript',
- '@babel/preset-env',
- '@babel/preset-react',
],
}
}
diff --git a/components/Todo.tsx b/components/Todo.tsx
deleted file mode 100644
index 3d0fd79..0000000
--- a/components/Todo.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-// src/components/TodoComponent.tsx
-import React, { useState } from 'react';
-import { View, Text, TextInput, Button, FlatList, StyleSheet, Dimensions } from 'react-native';
-import { useDispatch, useSelector } from 'react-redux';
-import { RootState } from '../store/store';
-import { addTodo, toggleTodo, deleteTodo } from '../src/utils/_todoSlice';
-
-const TodoComponent: React.FC = () => {
- return (
- Test
- );
-};
-
-// @todo: add to shared styles export.
-const yellow = '#ffcc00';
-const white = '#fff'
-const styles = StyleSheet.create({
- background: {
- backgroundColor: white,
- }
-});
-
-export default TodoComponent;
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index d7f945b..3d9cfaa 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -36,6 +36,7 @@
"@babel/core": "^7.20.0",
"@babel/preset-typescript": "^7.24.7",
"@testing-library/jest-native": "^5.4.3",
+ "@testing-library/react": "^16.0.1",
"@testing-library/react-native": "^12.6.1",
"@types/jest": "^29.5.12",
"@types/react": "~18.2.45",
@@ -7437,6 +7438,158 @@
"react": "^18 || ^19"
}
},
+ "node_modules/@testing-library/dom": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz",
+ "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/runtime": "^7.12.5",
+ "@types/aria-query": "^5.0.1",
+ "aria-query": "5.3.0",
+ "chalk": "^4.1.0",
+ "dom-accessibility-api": "^0.5.9",
+ "lz-string": "^1.5.0",
+ "pretty-format": "^27.0.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@testing-library/dom/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@testing-library/dom/node_modules/aria-query": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
+ "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "dequal": "^2.0.3"
+ }
+ },
+ "node_modules/@testing-library/dom/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/@testing-library/dom/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/@testing-library/dom/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@testing-library/dom/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@testing-library/dom/node_modules/pretty-format": {
+ "version": "27.5.1",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
+ "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^17.0.1"
+ },
+ "engines": {
+ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
+ }
+ },
+ "node_modules/@testing-library/dom/node_modules/pretty-format/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@testing-library/dom/node_modules/react-is": {
+ "version": "17.0.2",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
+ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@testing-library/dom/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/@testing-library/jest-native": {
"version": "5.4.3",
"resolved": "https://registry.npmjs.org/@testing-library/jest-native/-/jest-native-5.4.3.tgz",
@@ -7567,6 +7720,34 @@
"node": ">=8"
}
},
+ "node_modules/@testing-library/react": {
+ "version": "16.0.1",
+ "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.0.1.tgz",
+ "integrity": "sha512-dSmwJVtJXmku+iocRhWOUFbrERC76TX2Mnf0ATODz8brzAZrMBbzLwQixlBSanZxR6LddK3eiwpSFZgDET1URg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.12.5"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@testing-library/dom": "^10.0.0",
+ "@types/react": "^18.0.0",
+ "@types/react-dom": "^18.0.0",
+ "react": "^18.0.0",
+ "react-dom": "^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@testing-library/react-native": {
"version": "12.6.1",
"resolved": "https://registry.npmjs.org/@testing-library/react-native/-/react-native-12.6.1.tgz",
@@ -7635,6 +7816,14 @@
"node": ">= 10"
}
},
+ "node_modules/@types/aria-query": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",
+ "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/@types/babel__core": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
@@ -10702,6 +10891,17 @@
"node": ">= 0.8"
}
},
+ "node_modules/dequal": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
+ "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/destroy": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
@@ -11165,6 +11365,14 @@
"node": ">=6.0.0"
}
},
+ "node_modules/dom-accessibility-api": {
+ "version": "0.5.16",
+ "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",
+ "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/domexception": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz",
@@ -18327,6 +18535,17 @@
"yallist": "^3.0.2"
}
},
+ "node_modules/lz-string": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz",
+ "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "bin": {
+ "lz-string": "bin/bin.js"
+ }
+ },
"node_modules/make-dir": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
@@ -23240,6 +23459,32 @@
}
}
},
+ "node_modules/react-dom": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
+ "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.2"
+ },
+ "peerDependencies": {
+ "react": "^18.3.1"
+ }
+ },
+ "node_modules/react-dom/node_modules/scheduler": {
+ "version": "0.23.2",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
+ "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
"node_modules/react-freeze": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/react-freeze/-/react-freeze-1.0.4.tgz",
diff --git a/package.json b/package.json
index 1c64e65..cc572c9 100644
--- a/package.json
+++ b/package.json
@@ -41,6 +41,7 @@
"@babel/core": "^7.20.0",
"@babel/preset-typescript": "^7.24.7",
"@testing-library/jest-native": "^5.4.3",
+ "@testing-library/react": "^16.0.1",
"@testing-library/react-native": "^12.6.1",
"@types/jest": "^29.5.12",
"@types/react": "~18.2.45",
diff --git a/src/components/AppStack.tsx b/src/components/AppStack.tsx
index 34c4400..d704114 100644
--- a/src/components/AppStack.tsx
+++ b/src/components/AppStack.tsx
@@ -1,11 +1,12 @@
-import MainScreen from '../screens/Main';
-import SettingsScreen from '../screens/Settings';
-import { createStackNavigator } from '@react-navigation/stack';
-import { RootStackParamList } from '../../App';
+import { createStackNavigator } from '@react-navigation/stack'
+import MainScreen from '../screens/Main'
+import SettingsScreen from '../screens/Settings'
+import { RootStackParamList } from '../types/todos'
+import ListScreen from '../screens/Lists'
-const Stack = createStackNavigator();
+const Stack = createStackNavigator()
-const AppStack = () => {
+function AppStack() {
return (
{
name="Settings"
component={SettingsScreen}
/>
+
)
}
-export default AppStack;
\ No newline at end of file
+export default AppStack
diff --git a/src/components/AuthStack.tsx b/src/components/AuthStack.tsx
index bb68ea3..ca0082e 100644
--- a/src/components/AuthStack.tsx
+++ b/src/components/AuthStack.tsx
@@ -1,12 +1,12 @@
-import LogInScreen from '../screens/LogIn';
-import SignUpScreen from '../screens/SignUp';
-import SplashScreen from '../screens/Splash';
-import { createStackNavigator } from '@react-navigation/stack';
-import { RootStackParamList } from '../../App';
+import { createStackNavigator } from '@react-navigation/stack'
+import LogInScreen from '../screens/LogIn'
+import SignUpScreen from '../screens/SignUp'
+import SplashScreen from '../screens/Splash'
+import { RootStackParamList } from '../types/todos'
-const Stack = createStackNavigator();
+const Stack = createStackNavigator()
-const AuthStack = () => {
+function AuthStack() {
return (
{
)
}
-export default AuthStack;
\ No newline at end of file
+export default AuthStack
diff --git a/src/components/Button.tsx b/src/components/Button.tsx
index 19a5b63..9c104f4 100644
--- a/src/components/Button.tsx
+++ b/src/components/Button.tsx
@@ -1,56 +1,112 @@
-import React from 'react';
-import { Text, StyleSheet, Pressable } from 'react-native';
+import React, { useContext } from 'react'
+import { Text, StyleSheet, Pressable } from 'react-native'
+import { ThemeContext } from '../providers/ThemeProvider'
+import themeStyles from '../lib/themeConfig'
-export default function Button(props) {
- const { onPress, title = 'Press Me!', type = 'button' } = props;
+export default function Button( props ) {
+ const { onPress, title = 'Press Me!', type = 'button' } = props
+ const { theme } = useContext( ThemeContext )
return (
-
- {title}
+
+ {title}
- );
+ )
}
-const red = 'rgba(238,113,113,1)';
-const styles = StyleSheet.create({
- button: {
+// @todo: consolidate these into themeConfig.
+const styles = StyleSheet.create( {
+ back: {
alignItems: 'center',
+ borderRadius: 4,
+ elevation: 3,
justifyContent: 'center',
- paddingVertical: 10,
- paddingHorizontal: 20,
+ marginBottom: 8,
+ },
+ backDark: {
+ alignItems: 'center',
borderRadius: 4,
elevation: 3,
+ justifyContent: 'center',
+ marginBottom: 8,
+ },
+ remove: {
+ fontSize: 12,
+ backgroundColor: '#fff',
+ paddingVertical: 2,
+ paddingHorizontal: 4,
+ borderRadius: 4,
+ marginLeft: 'auto',
+ },
+ removeDark: {
+ fontSize: 12,
+ backgroundColor: 'rgba(19, 12, 84, 1)',
+ paddingVertical: 2,
+ paddingHorizontal: 4,
+ borderRadius: 4,
+ marginLeft: 'auto',
+ },
+ button: {
+ alignItems: 'center',
backgroundColor: 'white',
+ borderRadius: 4,
+ elevation: 3,
+ justifyContent: 'center',
marginBottom: 10,
+ paddingHorizontal: 20,
+ paddingVertical: 10,
},
- back: {
+ buttonDark: {
alignItems: 'center',
- justifyContent: 'center',
+ backgroundColor: 'rgba(19, 12, 84, 1)',
borderRadius: 4,
- position: 'absolute',
- bottom: 30,
- left: 30,
elevation: 3,
- marginBottom: 8,
+ justifyContent: 'center',
+ marginBottom: 10,
+ paddingHorizontal: 20,
+ paddingVertical: 10,
},
secondary: {
+ alignItems: 'center',
backgroundColor: 'transparent',
- padding: 0,
elevation: 3,
+ padding: 0,
+ marginBottom: 10,
+ },
+ secondaryDark: {
alignItems: 'center',
+ backgroundColor: 'transparent',
+ elevation: 3,
+ padding: 0,
+ marginBottom: 10,
},
tertiary: {
+ alignItems: 'center',
backgroundColor: 'transparent',
- padding: 0,
elevation: 3,
+ marginBottom: 10,
+ marginTop: 10,
+ padding: 0,
+ },
+ tertiaryDark: {
alignItems: 'center',
+ backgroundColor: 'transparent',
+ elevation: 3,
marginBottom: 10,
marginTop: 10,
+ padding: 0,
},
text: {
+ color: themeStyles.text.light,
fontSize: 14,
+ letterSpacing: 0.25,
lineHeight: 21,
+ textTransform: 'uppercase',
+ },
+ textDark: {
+ color: themeStyles.text.dark,
+ fontSize: 14,
letterSpacing: 0.25,
- color: red,
+ lineHeight: 21,
textTransform: 'uppercase',
},
-});
+} )
diff --git a/src/components/Todo.tsx b/src/components/Todo.tsx
deleted file mode 100644
index 37f7d27..0000000
--- a/src/components/Todo.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-// src/components/TodoComponent.tsx
-import React, { useState } from 'react';
-import { View, Text, TextInput, Button, FlatList, StyleSheet, Dimensions } from 'react-native';
-import { useDispatch, useSelector } from 'react-redux';
-import { RootState } from '../store/store';
-import { addTodo, toggleTodo, deleteTodo } from '../utils/_todoSlice';
-
-const TodoComponent: React.FC = () => {
- return (
- Test
- );
-};
-
-// @todo: add to shared styles export.
-const yellow = '#ffcc00';
-const white = '#fff'
-const styles = StyleSheet.create({
- background: {
- backgroundColor: white,
- }
-});
-
-export default TodoComponent;
\ No newline at end of file
diff --git a/src/components/Todos.tsx b/src/components/Todos.tsx
new file mode 100644
index 0000000..2b39b43
--- /dev/null
+++ b/src/components/Todos.tsx
@@ -0,0 +1,95 @@
+import React, { useContext, useEffect } from 'react'
+import {
+ View, Text, TextInput, FlatList, StyleSheet, ViewStyle,
+} from 'react-native'
+import { useNavigation } from '@react-navigation/native'
+import { useSelector, useDispatch } from 'react-redux'
+import Button from './Button'
+import useAuth from '../hooks/useAuth'
+import { RootState } from '../redux/store'
+import { TodoList } from '../types/todos'
+import { addList, fetchLists } from '../redux/thunks/todoThunk'
+import themeStyles from '../lib/themeConfig'
+import { ThemeContext } from '../providers/ThemeProvider'
+
+function Todos(): React.ReactElement {
+ const [ newListTitle, setNewListTitle ] = React.useState( '' )
+
+ const { theme } = useContext( ThemeContext )
+ const { user } = useAuth()
+ const navigation = useNavigation()
+
+ const dispatch = useDispatch()
+
+ const lists = useSelector( ( state: RootState ) => state.todos.lists )
+
+ /**
+ * Adds a new list.
+ */
+ const handleAddList = async () => {
+ if ( !newListTitle.trim() ) {
+ return
+ }
+
+ const listId = Date.now().toString()
+ const newList: TodoList = {
+ id: listId,
+ name: newListTitle,
+ user_id: user?.id || null,
+ }
+
+ // @ts-expect-error @todo: resolve ts error.
+ await dispatch( addList( newList ) )
+ setNewListTitle( '' )
+ // @ts-expect-error @todo: resolve ts error.
+ navigation.navigate( 'List', { listId } )
+ }
+
+ /**
+ * Fetch lists after dispatch to refresh.
+ */
+ useEffect( () => {
+ // Fetch lists from Supabase and update Redux store
+ // @ts-expect-error @todo: resolve ts error.
+ dispatch( fetchLists() )
+ }, [dispatch] )
+
+ return (
+
+ T◩DY
+
+ item.id}
+ renderItem={( { item } ) => (
+
+ )
+}
+
+const styles = StyleSheet.create( {
+ container: {
+ flex: 1,
+ padding: 16,
+ },
+ input: themeStyles.input.light as ViewStyle,
+ inputDark: themeStyles.input.dark as ViewStyle,
+ title: themeStyles.title.light as ViewStyle,
+ titleDark: themeStyles.title.dark as ViewStyle,
+} )
+
+export default Todos
diff --git a/src/hooks/useAuth.test.tsx b/src/hooks/useAuth.test.temp
similarity index 100%
rename from src/hooks/useAuth.test.tsx
rename to src/hooks/useAuth.test.temp
diff --git a/src/lib/supabaseClient.ts b/src/lib/supabaseClient.ts
index 225b28e..d11dae2 100644
--- a/src/lib/supabaseClient.ts
+++ b/src/lib/supabaseClient.ts
@@ -4,6 +4,8 @@ import Constants from 'expo-constants'
import { AppState } from 'react-native'
const supabaseUrl = 'https://uybhrwvodlxtcfgfzezq.supabase.co'
+
+// @ts-expect-error @todo: expoConfig not being recognized in definition.
const { SUPABASE_KEY } = Constants.expoConfig.extra
const supabase = createClient( supabaseUrl, SUPABASE_KEY, {
diff --git a/src/lib/themeConfig.ts b/src/lib/themeConfig.ts
index 3080e21..550d817 100644
--- a/src/lib/themeConfig.ts
+++ b/src/lib/themeConfig.ts
@@ -1,6 +1,61 @@
+const darkBlue = 'rgba(19, 12, 84, 1)'
+const white = '#fff'
+const red = 'rgba(238,113,113,1)'
+
+const inputShared = {
+ alignSelf: 'stretch',
+ borderRadius: 4,
+ borderStyle: 'solid',
+ borderWidth: 1,
+ fontSize: 16,
+ marginBottom: 10,
+ marginLeft: 20,
+ marginRight: 20,
+ padding: 8,
+}
+
export default {
backgroundColor: {
dark: [ 'rgba(19, 12, 183,0.5)', 'rgba(82, 229, 231,0.5)' ],
light: [ 'rgba(238,113,113,0.5)', 'rgba(246,215,148,0.5)' ],
},
+ color: {
+ white: {
+ light: white,
+ dark: darkBlue,
+ },
+ },
+ input: {
+ light: {
+ ...inputShared,
+ backgroundColor: white,
+ textColor: red,
+ },
+ dark: {
+ ...inputShared,
+ backgroundColor: darkBlue,
+ textColor: white,
+ },
+ },
+ text: {
+ light: red,
+ dark: white,
+ },
+ container: {
+ alignItems: 'center',
+ flex: 1,
+ justifyContent: 'center',
+ },
+ title: {
+ light: {
+ color: white,
+ fontSize: 48,
+ marginBottom: 20,
+ },
+ dark: {
+ color: darkBlue,
+ fontSize: 48,
+ marginBottom: 20,
+ },
+ },
}
diff --git a/src/providers/ThemeProvider.tsx b/src/providers/ThemeProvider.tsx
index bebd8ea..65ada5d 100644
--- a/src/providers/ThemeProvider.tsx
+++ b/src/providers/ThemeProvider.tsx
@@ -7,7 +7,7 @@ import React, {
} from 'react'
import AsyncStorage from '@react-native-async-storage/async-storage'
-enum Theme {
+export enum Theme {
LIGHT = 'light',
DARK = 'dark',
}
diff --git a/src/screens/Lists.tsx b/src/screens/Lists.tsx
new file mode 100644
index 0000000..0e3e63c
--- /dev/null
+++ b/src/screens/Lists.tsx
@@ -0,0 +1,217 @@
+import React, { ReactElement, useContext } from 'react'
+import {
+ View, Text, TextInput, FlatList, StyleSheet,
+ ViewStyle,
+} from 'react-native'
+import { useSelector, useDispatch } from 'react-redux'
+import { RouteProp, useNavigation, useFocusEffect } from '@react-navigation/native'
+import { LinearGradient } from 'expo-linear-gradient'
+import { SafeAreaView } from 'react-native-safe-area-context'
+import Button from '../components/Button'
+import { RootStackParamList } from '../types/todos'
+import useThemeColors from '../hooks/useThemeColors'
+import {
+ addTodo, removeList, removeTodo, toggleTodoStatus, fetchTodosByListId,
+} from '../redux/thunks/todoThunk'
+import { RootState } from '../redux/store'
+import themeStyles from '../lib/themeConfig'
+import { Theme, ThemeContext } from '../providers/ThemeProvider'
+
+interface Props {
+ route: RouteProp;
+}
+
+function ListScreen( { route }: Props ): ReactElement {
+ const navigation = useNavigation()
+ const { theme } = useContext( ThemeContext )
+
+ const { listId } = route.params
+
+ const dispatch = useDispatch()
+
+ const lists = useSelector( ( state: RootState ) => state.todos.lists )
+ const list = lists.find( ( l ) => l.id === listId )
+
+ // @ts-expect-error @todo: need to pull this directly from store.
+ const todos = list?.todos || []
+
+ const [ newTodoText, setNewTodoText ] = React.useState( '' )
+
+ const themeColors = useThemeColors()
+
+ // Fetch todos for the selected list on component mount or when listId changes
+ useFocusEffect(
+ React.useCallback( () => {
+ if ( listId ) {
+ // @ts-expect-error @todo: fix ts error.
+ dispatch( fetchTodosByListId( listId ) )
+ }
+ }, [ dispatch, listId ] ),
+ )
+
+ if ( !list ) return null
+
+ /**
+ * Handle removing a list entirely.
+ */
+ const handleRemoveList = ( lstId: string ) => {
+ // @ts-expect-error @todo: fix ts error.
+ dispatch( removeList( lstId ) )
+ navigation.goBack() // Navigate back after removing the list
+ }
+
+ /**
+ * Add todo.
+ */
+ const handleAddTodo = () => {
+ if ( !newTodoText.trim() ) return
+
+ dispatch(
+ // @ts-expect-error @todo: defined shape.
+ addTodo( {
+ listId,
+ // @ts-expect-error @todo: define shape.
+ todo: {
+ id: Date.now().toString(),
+ text: newTodoText,
+ status: 'incomplete',
+ },
+ } ),
+ )
+
+ setNewTodoText( '' )
+ }
+
+ /**
+ * Remove a todo item.
+ */
+ const handleRemoveTodo = ( todoId: string ) => {
+ // @ts-expect-error @todo: define type.
+ dispatch( removeTodo( {
+ listId,
+ todoId,
+ } ) )
+ }
+
+ /**
+ * Toggle type status.
+ */
+ const handleToggleTodoStatus = ( todoId: string ) => {
+ // @ts-expect-error @todo: define type.
+ dispatch( toggleTodoStatus( {
+ listId,
+ todoId,
+ } ) )
+ }
+
+ return (
+
+
+ {list.name}
+
+ {todos.length ? (
+ item.id}
+ renderItem={( { item } ) => (
+
+ handleToggleTodoStatus( item.id )}
+ >
+ {item.text}
+
+ handleRemoveTodo( item.id )}
+ title="Remove"
+ type="remove"
+ />
+
+ )}
+ />
+ ) : null}
+
+ navigation.goBack()}
+ title="Go Back"
+ type="secondary"
+ />
+
+
+
+ handleRemoveList( list.id )}
+ type="secondary"
+ />
+
+
+ )
+}
+
+const styles = StyleSheet.create( {
+ container: {
+ flex: 1,
+ padding: 16,
+ },
+ input: themeStyles.input.light as ViewStyle,
+ inputDark: themeStyles.input.dark as ViewStyle,
+ title: themeStyles.title.light as ViewStyle,
+ titleDark: themeStyles.title.dark as ViewStyle,
+ list: {
+ marginTop: 20,
+ },
+ horizontal: {
+ flexDirection: 'row',
+ marginBottom: 15,
+ backgroundColor: 'rgba(255, 255, 255, 0.2)',
+ padding: 4,
+ borderRadius: 4,
+ alignItems: 'center',
+ },
+ todo: {
+ fontSize: 16,
+ flex: 1,
+ },
+ todoDark: {
+ fontSize: 16,
+ flex: 1,
+ },
+ todoComplete: {
+ textDecorationLine: 'line-through',
+ fontSize: 16,
+ color: 'gray',
+ },
+ todoCompleteDark: {
+ textDecorationLine: 'line-through',
+ fontSize: 16,
+ color: 'gray',
+ },
+ todoPartiallyComplete: {
+ fontSize: 16,
+ color: 'rgb(252, 7, 11)',
+ },
+ todoPartiallyCompleteDark: {
+ fontSize: 16,
+ color: 'rgb(174, 7, 169)',
+ },
+} )
+
+const getNextStatus = ( currentStatus: 'incomplete' | 'partially-complete' | 'complete', theme: Theme ) => {
+ switch ( currentStatus ) {
+ case 'partially-complete':
+ return theme === 'light' ? styles.todoPartiallyComplete : styles.todoPartiallyCompleteDark
+ case 'complete':
+ return theme === 'light' ? styles.todoComplete : styles.todoCompleteDark
+ default:
+ return theme === 'light' ? styles.todo : styles.todoDark
+ }
+}
+
+export default ListScreen
diff --git a/src/screens/LogIn.tsx b/src/screens/LogIn.tsx
index d30ee3c..fc07bdc 100644
--- a/src/screens/LogIn.tsx
+++ b/src/screens/LogIn.tsx
@@ -1,98 +1,93 @@
-import Button from '../components/Button';
-import { LinearGradient } from 'expo-linear-gradient';
-import { RootStackParamList } from '../../App';
-import { SafeAreaView } from 'react-native-safe-area-context';
-import { StackNavigationProp } from '@react-navigation/stack';
-import { StyleSheet, Text, TextInput } from 'react-native';
-import { useAuth } from '../providers/AuthProvider';
-import { useState } from 'react';
-import useThemeColors from '../hooks/useThemeColors';
+import { LinearGradient } from 'expo-linear-gradient'
+import { SafeAreaView } from 'react-native-safe-area-context'
+import { StackNavigationProp } from '@react-navigation/stack'
+import {
+ StyleSheet, Text, TextInput, ViewStyle,
+} from 'react-native'
+import { useState, ReactElement, useContext } from 'react'
+import { RootStackParamList } from '../types/todos'
+import useThemeColors from '../hooks/useThemeColors'
+import useAuth from '../hooks/useAuth'
+import Button from '../components/Button'
+import themeStyles from '../lib/themeConfig'
+import { ThemeContext } from '../providers/ThemeProvider'
-type LogInScreenNavigationProp = StackNavigationProp;
+type LogInScreenNavigationProp = StackNavigationProp<
+ RootStackParamList,
+ 'SignUp'
+>
interface LogInScreenProps {
- navigation: LogInScreenNavigationProp;
+ navigation: LogInScreenNavigationProp
}
-const LogInScreen: React.FC = ({ navigation }) => {
- const [email, setEmail] = useState('');
- const [password, setPassword] = useState('');
+/**
+ * Login screen.
+ *
+ * @todo: need more feedback on errors.
+ */
+function LogInScreen( { navigation } ): ReactElement {
+ const [ email, setEmail ] = useState( '' )
+ const [ password, setPassword ] = useState( '' )
+ const { theme } = useContext( ThemeContext )
const themeColors = useThemeColors()
- const { loading, signInWithEmail } = useAuth();
+ const { loading, signInWithEmail } = useAuth()
- return (
-
-
- Log In!
- {
- setEmail(text);
- }}
- value={email}
- keyboardType="email-address"
- autoCapitalize="none"
- textContentType="emailAddress"
- style={styles.input}
- />
- setPassword(text)}
- value={password}
- secureTextEntry={true}
- autoCapitalize="none"
- textContentType="password"
- style={styles.input}
- />
- signInWithEmail(email, password)}
- title={loading ? 'Signing In...' : 'Sign In'}
- />
- navigation.goBack()}
- title="Go Back"
- type="secondary"
- />
-
-
- );
+ return (
+
+
+ Log In!
+ {
+ setEmail( text )
+ }}
+ value={email}
+ keyboardType="email-address"
+ autoCapitalize="none"
+ textContentType="emailAddress"
+ style={styles.input}
+ />
+ setPassword( text )}
+ value={password}
+ secureTextEntry
+ autoCapitalize="none"
+ textContentType="password"
+ style={styles.input}
+ />
+ signInWithEmail( email, password )}
+ title={loading ? 'Signing In...' : 'Sign In'}
+ />
+ navigation.goBack()}
+ title="Go Back"
+ type="secondary"
+ />
+
+
+ )
}
-export default LogInScreen;
+export default LogInScreen
-// @todo: add to shared styles export.
-const yellow = '#ffcc00';
-const white = '#fff';
-const red = 'rgba(238,113,113,0.5)';
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- alignItems: 'center',
- justifyContent: 'center',
- },
- input: {
- borderRadius: 4,
- borderColor: red,
- borderWidth: 1,
- borderStyle: 'solid',
- backgroundColor: white,
- marginBottom: 10,
- padding: 8,
- alignSelf: 'stretch',
- marginLeft: 20,
- marginRight: 20,
- fontSize: 16,
- },
- logo: {
- color: white,
- fontSize: 48,
- marginBottom: 15,
- },
-});
+const styles = StyleSheet.create( {
+ container: {
+ alignItems: 'center',
+ flex: 1,
+ justifyContent: 'center',
+ },
+ input: themeStyles.input.light as ViewStyle,
+ inputDark: themeStyles.input.dark as ViewStyle,
+ title: themeStyles.title.light as ViewStyle,
+ titleDark: themeStyles.title.dark as ViewStyle,
+} )
diff --git a/src/screens/Main.tsx b/src/screens/Main.tsx
index 8778940..a1717a7 100644
--- a/src/screens/Main.tsx
+++ b/src/screens/Main.tsx
@@ -1,20 +1,20 @@
-import React from 'react';
-import { StyleSheet, View, Text } from 'react-native';
-import { StackNavigationProp } from '@react-navigation/stack';
-import { RootStackParamList } from '../../App';
-import Todo from '../components/Todo'
-import { SafeAreaView } from 'react-native-safe-area-context';
-import { LinearGradient } from 'expo-linear-gradient';
-import Button from '../components/Button';
-import useThemeColors from '../hooks/useThemeColors';
+import React, { ReactElement } from 'react'
+import { LinearGradient } from 'expo-linear-gradient'
+import { SafeAreaView } from 'react-native-safe-area-context'
+import { StackNavigationProp } from '@react-navigation/stack'
+import { StyleSheet } from 'react-native'
+import { RootStackParamList } from '../types/todos'
+import useThemeColors from '../hooks/useThemeColors'
+import Todos from '../components/Todos'
+import Button from '../components/Button'
-type MainScreenNavigationProp = StackNavigationProp;
+type MainScreenNavigationProp = StackNavigationProp
interface MainScreenProps {
- navigation: MainScreenNavigationProp;
+ navigation: MainScreenNavigationProp
}
-const MainScreen: React.FC = ({ navigation }) => {
+function MainScreen( { navigation } ): ReactElement {
const themeColors = useThemeColors()
return (
= ({ navigation }) => {
}}
>
-
+
navigation.navigate('Settings')}
+ onPress={() => navigation.navigate( 'Settings' )}
type="back"
/>
- );
+ )
}
-export default MainScreen;
+export default MainScreen
-// @todo: add to shared styles export.
-const yellow = 'rgba(246,215,148,0.5)';
-const styles = StyleSheet.create({
+const styles = StyleSheet.create( {
container: {
flex: 1,
- }
-});
+ },
+} )
diff --git a/src/screens/Settings.tsx b/src/screens/Settings.tsx
index 01c7fe8..172e6cb 100644
--- a/src/screens/Settings.tsx
+++ b/src/screens/Settings.tsx
@@ -1,31 +1,34 @@
-import Button from '../components/Button';
-import React, { useContext} from 'react';
-import { LinearGradient } from 'expo-linear-gradient';
-import { RootStackParamList } from '../../App';
-import { SafeAreaView } from 'react-native-safe-area-context';
-import { StackNavigationProp } from '@react-navigation/stack';
-import { StyleSheet, View, Text } from 'react-native';
-import { useAuth } from '../providers/AuthProvider';
-import ThemeContext from '../providers/ThemeProvider';
-import useThemeColors from '../hooks/useThemeColors';
+import React, { ReactElement, useContext } from 'react'
+import { LinearGradient } from 'expo-linear-gradient'
+import { SafeAreaView } from 'react-native-safe-area-context'
+import { StackNavigationProp } from '@react-navigation/stack'
+import { StyleSheet, Text, ViewStyle } from 'react-native'
+import Button from '../components/Button'
+import themeStyles from '../lib/themeConfig'
+import useAuth from '../hooks/useAuth'
+import useThemeColors from '../hooks/useThemeColors'
+import { RootStackParamList } from '../types/todos'
+import { Theme, ThemeContext } from '../providers/ThemeProvider'
-type SettingsScreenNavigationProp = StackNavigationProp;
+type SettingsScreenNavigationProp = StackNavigationProp<
+ RootStackParamList,
+ 'Settings'
+>
interface SettingsScreenProps {
- navigation: SettingsScreenNavigationProp;
+ navigation: SettingsScreenNavigationProp
}
-const SettingsScreen: React.FC = ({ navigation }) => {
-
- const { signOut } = useAuth();
+function SettingsScreen( { navigation } ): ReactElement {
+ const { signOut } = useAuth()
const themeColors = useThemeColors()
- const {theme, toggleTheme} = useContext(ThemeContext);
+ const { theme, toggleTheme } = useContext( ThemeContext )
const handleToggleTheme = () => {
- const newTheme = theme === 'light' ? 'dark' : 'light';
- toggleTheme(newTheme);
- };
+ const newTheme = theme === Theme.LIGHT ? Theme.DARK : Theme.LIGHT
+ toggleTheme( newTheme )
+ }
return (
= ({ navigation }) => {
}}
>
- Settings
- {
- signOut()
- toggleTheme('light')
- }}
- />
-
- navigation.navigate('Main')}
- type="secondary"
- />
+ Settings
+ {
+ signOut()
+ toggleTheme( Theme.LIGHT )
+ }}
+ />
+
+ navigation.navigate( 'Main' )}
+ type="secondary"
+ />
- );
+ )
}
-export default SettingsScreen;
+export default SettingsScreen
-// @todo: add to shared styles export.
-const yellow = '#ffcc00';
-const white = '#fff';
-const styles = StyleSheet.create({
+const styles = StyleSheet.create( {
container: {
flex: 1,
- padding: 20,
- },
- logo: {
- color: white,
- fontSize: 48,
- marginBottom: 25,
+ padding: 16,
},
-});
\ No newline at end of file
+ title: themeStyles.title.light as ViewStyle,
+ titleDark: themeStyles.title.dark as ViewStyle,
+} )
diff --git a/src/screens/SignUp.tsx b/src/screens/SignUp.tsx
index 6dfdeaf..dd1471d 100644
--- a/src/screens/SignUp.tsx
+++ b/src/screens/SignUp.tsx
@@ -1,120 +1,124 @@
+import { LinearGradient } from 'expo-linear-gradient'
+import {
+ ReactElement, useContext, useEffect, useState,
+} from 'react'
+import { SafeAreaView } from 'react-native-safe-area-context'
+import { StackNavigationProp } from '@react-navigation/stack'
import { StatusBar } from 'expo-status-bar'
-import Button from '../components/Button';
-import { StyleSheet, Text, TextInput } from 'react-native';
-import { StackNavigationProp } from '@react-navigation/stack';
-import { RootStackParamList } from '../../App';
-import { SafeAreaView } from 'react-native-safe-area-context';
-import { LinearGradient } from 'expo-linear-gradient';
-import { useEffect, useState } from 'react';
-import { useAuth } from '../providers/AuthProvider';
-import useThemeColors from '../hooks/useThemeColors';
+import {
+ StyleSheet, Text, TextInput, ViewStyle,
+} from 'react-native'
+import { RootStackParamList } from '../types/todos'
+import useThemeColors from '../hooks/useThemeColors'
+import useAuth from '../hooks/useAuth'
+import Button from '../components/Button'
+import themeStyles from '../lib/themeConfig'
+import { ThemeContext } from '../providers/ThemeProvider'
-type SignUpScreenNavigationProp = StackNavigationProp;
+type SignUpScreenNavigationProp = StackNavigationProp<
+ RootStackParamList,
+ 'SignUp'
+>
interface SignUpScreenProps {
- navigation: SignUpScreenNavigationProp;
+ navigation: SignUpScreenNavigationProp
}
-const SignUpScreen: React.FC = ({ navigation }) => {
- const [email, setEmail] = useState('');
- const [password, setPassword] = useState('');
- const [retypePassword, setRetypePassword] = useState('');
- const [name, setName] = useState('');
-
+function SignUpScreen( { navigation } ): ReactElement {
+ const [ email, setEmail ] = useState( '' )
+ const [ password, setPassword ] = useState( '' )
+ const [ retypePassword, setRetypePassword ] = useState( '' )
+ const [ name, setName ] = useState( '' )
+ /**
+ * Providers.
+ */
+ const { theme } = useContext( ThemeContext )
const themeColors = useThemeColors()
- const { error, session, user, signUpNewUser } = useAuth();
+ const {
+ error, session, user, signUpNewUser,
+ } = useAuth()
- useEffect(() => {
- if (user && user.aud === 'authenticated' && ! session ) {
- navigation.navigate('LogIn');
- }
- }, [user]);
+ /**
+ * Redirect the user after creation.
+ */
+ useEffect( () => {
+ if ( user && user.aud === 'authenticated' && !session ) {
+ navigation.navigate( 'LogIn' )
+ }
+ }, [ user, session, navigation ] )
- return (
-
-
- Registration!
- {
- setEmail(text);
- }}
- value={email}
- keyboardType="email-address"
- autoCapitalize="none"
- textContentType="emailAddress"
- style={styles.input}
- />
- setName(text)}
- value={name}
- autoCapitalize="none"
- textContentType="name"
- style={styles.input}
- />
- setPassword(text)}
- value={password}
- secureTextEntry={true}
- autoCapitalize="none"
- textContentType="password"
- style={styles.input}
- />
- setRetypePassword(text)}
- value={retypePassword}
- secureTextEntry={true}
- autoCapitalize="none"
- textContentType="password"
- style={styles.input}
- />
- {error ? {error.toString()} : null}
- signUpNewUser(email, name, password)}
- title="Register"
- />
-
-
-
- );
+ return (
+
+
+ Registration!
+ {
+ setEmail( text )
+ }}
+ value={email}
+ keyboardType="email-address"
+ autoCapitalize="none"
+ textContentType="emailAddress"
+ style={styles.input}
+ />
+ setName( text )}
+ value={name}
+ autoCapitalize="none"
+ textContentType="name"
+ style={styles.input}
+ />
+ setPassword( text )}
+ value={password}
+ secureTextEntry
+ autoCapitalize="none"
+ textContentType="password"
+ style={styles.input}
+ />
+ setRetypePassword( text )}
+ value={retypePassword}
+ secureTextEntry
+ autoCapitalize="none"
+ textContentType="password"
+ style={styles.input}
+ />
+ {error ? {error.toString()} : null}
+ signUpNewUser( email, name, password )}
+ title="Register"
+ />
+ navigation.goBack()}
+ title="Go Back"
+ type="secondary"
+ />
+
+
+
+ )
}
-export default SignUpScreen;
+export default SignUpScreen
-// @todo: add to shared styles export.
-const yellow = '#ffcc00';
-const white = '#fff';
-const red = 'rgba(238,113,113,0.5)';
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- alignItems: 'center',
- justifyContent: 'center',
- },
- input: {
- borderRadius: 4,
- borderColor: red,
- borderWidth: 1,
- borderStyle: 'solid',
- backgroundColor: white,
- marginBottom: 10,
- padding: 8,
- alignSelf: 'stretch',
- marginLeft: 20,
- marginRight: 20,
- fontSize: 16,
- },
- logo: {
- color: white,
- fontSize: 48,
- marginBottom: 15,
- },
-});
+const styles = StyleSheet.create( {
+ container: {
+ alignItems: 'center',
+ flex: 1,
+ justifyContent: 'center',
+ },
+ input: themeStyles.input.light as ViewStyle,
+ inputDark: themeStyles.input.dark as ViewStyle,
+ title: themeStyles.title.light as ViewStyle,
+ titleDark: themeStyles.title.dark as ViewStyle,
+} )
diff --git a/src/screens/Splash.tsx b/src/screens/Splash.tsx
index acb9493..a7784b3 100644
--- a/src/screens/Splash.tsx
+++ b/src/screens/Splash.tsx
@@ -1,58 +1,66 @@
-import { StatusBar } from 'expo-status-bar';
-import { StyleSheet, Text, View } from 'react-native';
-import Button from '../components/Button';
-import { StackNavigationProp } from '@react-navigation/stack';
-import { RootStackParamList } from '../../App';
-import { SafeAreaView } from 'react-native-safe-area-context';
-import { LinearGradient } from 'expo-linear-gradient';
-import useThemeColors from '../hooks/useThemeColors';
+import { StatusBar } from 'expo-status-bar'
+import { StyleSheet, Text, View } from 'react-native'
+import { StackNavigationProp } from '@react-navigation/stack'
+import { SafeAreaView } from 'react-native-safe-area-context'
+import { LinearGradient } from 'expo-linear-gradient'
+import { ReactElement, useContext } from 'react'
+import { RootStackParamList } from '../types/todos'
+import Button from '../components/Button'
+import useThemeColors from '../hooks/useThemeColors'
+import themeStyles from '../lib/themeConfig'
+import { ThemeContext } from '../providers/ThemeProvider'
-type SplashScreenNavigationProp = StackNavigationProp;
+type SplashScreenNavigationProp = StackNavigationProp<
+ RootStackParamList,
+ 'Splash'
+>
interface SplashScreenProps {
- navigation: SplashScreenNavigationProp;
+ navigation: SplashScreenNavigationProp
}
-const SplashScreen: React.FC = ({ navigation }) => {
+function SplashScreen( { navigation } ): ReactElement {
const themeColors = useThemeColors()
- return (
-
-
- T◩DY
-
- navigation.navigate('SignUp')}
- />
- navigation.navigate('LogIn')}
- type="secondary"
- />
-
-
-
-
- );
+ const { theme } = useContext( ThemeContext )
+ return (
+
+
+ T◩DY
+
+ navigation.navigate( 'SignUp' )}
+ />
+ navigation.navigate( 'LogIn' )}
+ type="secondary"
+ />
+
+
+
+
+ )
}
-export default SplashScreen;
+export default SplashScreen
-// @todo: add to shared styles export.
-const yellow = '#ffcc00';
-const white = '#fff';
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- alignItems: 'center',
- justifyContent: 'center',
- },
- logo: {
- color: white,
- fontSize: 48,
- },
-});
+const styles = StyleSheet.create( {
+ container: {
+ alignItems: 'center',
+ flex: 1,
+ justifyContent: 'center',
+ },
+ title: {
+ color: themeStyles.color.white.light,
+ fontSize: 48,
+ },
+ titleDark: {
+ color: themeStyles.color.white.dark,
+ fontSize: 48,
+ },
+} )
diff --git a/tsconfig.jest.json b/tsconfig.jest.json
deleted file mode 100644
index 2b06029..0000000
--- a/tsconfig.jest.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "compilerOptions": {
- "jsx": "react",
- "module": "commonjs",
- "target": "es6",
- "strict": true,
- "esModuleInterop": true,
- "skipLibCheck": true,
- "forceConsistentCasingInFileNames": true,
- "types": ["jest", "node"]
- }
-}