Merge branch '41-add-user-settings-modal-on-home-page' into 'main'
Resolve "Add user settings modal on home Page" Closes #41 See merge request thschleicher/interaktive-systeme!23
This commit is contained in:
commit
69f1dd0234
13 changed files with 367 additions and 48 deletions
|
|
@ -13,10 +13,6 @@ export default function Layout() {
|
||||||
// const backgroundColor: string = useThemeColor("backgroundColor");
|
// const backgroundColor: string = useThemeColor("backgroundColor");
|
||||||
// const tabBarColor: string = useThemeColor("tabBarColor");
|
// const tabBarColor: string = useThemeColor("tabBarColor");
|
||||||
const {authState} = useAuth()
|
const {authState} = useAuth()
|
||||||
useEffect(()=>{
|
|
||||||
console.log(authState, "in root Layout")
|
|
||||||
},[authState])
|
|
||||||
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
sceneContainer: {
|
sceneContainer: {
|
||||||
|
|
@ -53,7 +49,8 @@ export default function Layout() {
|
||||||
tabBarLabel: "Home",
|
tabBarLabel: "Home",
|
||||||
tabBarIcon: ({size, color}) => (
|
tabBarIcon: ({size, color}) => (
|
||||||
<FontAwesome name="home" size={size} color={color}/>),
|
<FontAwesome name="home" size={size} color={color}/>),
|
||||||
unmountOnBlur: true
|
unmountOnBlur: true,
|
||||||
|
href: "(tabs)/home/"
|
||||||
}
|
}
|
||||||
}/>
|
}/>
|
||||||
<Tabs.Screen name="stats/index" options={
|
<Tabs.Screen name="stats/index" options={
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,35 @@ import { Stack } from "expo-router";
|
||||||
|
|
||||||
import { View, Text } from 'react-native'
|
import { View, Text } from 'react-native'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { useThemeColor } from "../../../hooks/useThemeColor";
|
||||||
|
import { useTheme } from "../../contexts/ThemeContext";
|
||||||
|
|
||||||
|
|
||||||
export default function _Layout() {
|
export default function _Layout() {
|
||||||
|
const { colors } = useTheme();
|
||||||
return (
|
return (
|
||||||
<Stack>
|
<Stack
|
||||||
|
initialRouteName="index"
|
||||||
|
screenOptions={{
|
||||||
|
contentStyle: {
|
||||||
|
backgroundColor:colors.backgroundColor,
|
||||||
|
},
|
||||||
|
headerStyle: {
|
||||||
|
backgroundColor: colors.backgroundColor
|
||||||
|
},
|
||||||
|
headerTintColor: colors.primaryText
|
||||||
|
|
||||||
|
}}>
|
||||||
<Stack.Screen name="index" options={{
|
<Stack.Screen name="index" options={{
|
||||||
title: "test",
|
title: "test",
|
||||||
headerShown: false,
|
headerShown: false,
|
||||||
}}/>
|
}}/>
|
||||||
<Stack.Screen name="addItem"/>
|
<Stack.Screen name="addItem"/>
|
||||||
|
<Stack.Screen name="userSettings" options={{
|
||||||
|
animation: "slide_from_left",
|
||||||
|
title: "User Settings",
|
||||||
|
headerShown: false,
|
||||||
|
}}/>
|
||||||
</Stack>
|
</Stack>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -7,6 +7,7 @@ import useFetch from '../../../hooks/useFetch';
|
||||||
import { useThemeColor } from "../../../hooks/useThemeColor";
|
import { useThemeColor } from "../../../hooks/useThemeColor";
|
||||||
import { addExpense } from "../../../services/database";
|
import { addExpense } from "../../../services/database";
|
||||||
import { useAuth } from '../../contexts/AuthContext';
|
import { useAuth } from '../../contexts/AuthContext';
|
||||||
|
import { useRouter } from "expo-router";
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
|
|
||||||
|
|
@ -31,6 +32,7 @@ export default function Page() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
const {onLogout} = useAuth();
|
const {onLogout} = useAuth();
|
||||||
const [plusShow, setPlusShow] = useState(true);
|
const [plusShow, setPlusShow] = useState(true);
|
||||||
const prevOffset = useRef(0);
|
const prevOffset = useRef(0);
|
||||||
|
|
@ -73,7 +75,7 @@ export default function Page() {
|
||||||
data={data}
|
data={data}
|
||||||
ListHeaderComponent={
|
ListHeaderComponent={
|
||||||
<>
|
<>
|
||||||
<Welcome name="My Dude" image={profile} onPress={onLogout!}></Welcome>
|
<Welcome name="My Dude" image={profile} onPress={() => {router.push("/home/userSettings")}}></Welcome>
|
||||||
<SearchBar placeholder='Type to Search...'></SearchBar>
|
<SearchBar placeholder='Type to Search...'></SearchBar>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
110
app/(tabs)/home/userSettings.tsx
Normal file
110
app/(tabs)/home/userSettings.tsx
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
import { View, Text, StyleSheet, Image, Appearance } from 'react-native'
|
||||||
|
import React, { useState } from 'react'
|
||||||
|
import { useThemeColor } from '../../../hooks/useThemeColor'
|
||||||
|
import { SIZES } from '../../../constants/theme'
|
||||||
|
import { SafeAreaView } from 'react-native-safe-area-context'
|
||||||
|
import { ButtonSetting, ToggleSetting } from '../../../components'
|
||||||
|
import { useTheme } from '../../contexts/ThemeContext'
|
||||||
|
import { deleteExpenses } from '../../../services/database'
|
||||||
|
import { useAuth } from '../../contexts/AuthContext'
|
||||||
|
import { TouchableOpacity } from 'react-native-gesture-handler'
|
||||||
|
|
||||||
|
const generateStyles = (): void => {
|
||||||
|
styles.text = {
|
||||||
|
color: useThemeColor('primaryText')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function userSettings() {
|
||||||
|
const {onLogout} = useAuth();
|
||||||
|
const {theme, colors, isSystemTheme, applyTheme, applySystemTheme} = useTheme();
|
||||||
|
|
||||||
|
const backgroundColor = useThemeColor("backgroundColor");
|
||||||
|
styles.text = {...styles.text, color: useThemeColor("primaryText")}
|
||||||
|
|
||||||
|
const [systemTheme, setSystemTheme] = useState<boolean>(isSystemTheme!)
|
||||||
|
const [darkMode, setDarkMode] = useState<boolean>(theme === "dark" ? true : false)
|
||||||
|
|
||||||
|
const handleSystemTheme = () => {
|
||||||
|
const newTheme = darkMode ? "dark" : "light"
|
||||||
|
if(systemTheme){
|
||||||
|
applyTheme!(newTheme)
|
||||||
|
}else{
|
||||||
|
applySystemTheme!()
|
||||||
|
}
|
||||||
|
|
||||||
|
setSystemTheme(prev => !prev)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDarkMode = () => {
|
||||||
|
const newTheme = darkMode ? "light" : "dark"
|
||||||
|
|
||||||
|
setDarkMode(prev => !prev)
|
||||||
|
applyTheme!(newTheme);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={[styles.container, {backgroundColor: colors.backgroundColor}]}>
|
||||||
|
<View>
|
||||||
|
<View style={styles.header}>
|
||||||
|
<Image style={{height: 70, width: 70, borderRadius: 200}}source={require("../../../assets/images/profile.jpg")} height={60} width={20} resizeMode='cover'/>
|
||||||
|
<Text style={{fontSize: SIZES.xxLarge, color: colors.primaryText}}>My Profile</Text>
|
||||||
|
<View></View>
|
||||||
|
</View>
|
||||||
|
<View style={styles.settingsContainer}>
|
||||||
|
<ToggleSetting settingsTitle='Use System Theme' value={systemTheme} onChange={handleSystemTheme}/>
|
||||||
|
<ToggleSetting settingsTitle='Dark Mode' disabled={systemTheme} onChange={handleDarkMode} value={darkMode}/>
|
||||||
|
<ButtonSetting settingsTitle='Reset Expenses' onPress={() => {
|
||||||
|
deleteExpenses().then(() => {
|
||||||
|
console.log("Expenses Deleted!");
|
||||||
|
})}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
</View>
|
||||||
|
<View style={styles.bottomNavigation}>
|
||||||
|
<TouchableOpacity onPress={onLogout}>
|
||||||
|
<View style={[styles.button, {backgroundColor: colors.accentColor}]}>
|
||||||
|
<Text style={{fontSize: SIZES.large, color: colors.primaryText}}>Sign Out</Text>
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</SafeAreaView>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: "space-between"
|
||||||
|
},
|
||||||
|
|
||||||
|
header:{
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
margin: 10,
|
||||||
|
},
|
||||||
|
settingsContainer: {
|
||||||
|
marginHorizontal: 10
|
||||||
|
},
|
||||||
|
|
||||||
|
upperPart:{
|
||||||
|
flex: 1
|
||||||
|
},
|
||||||
|
|
||||||
|
bottomNavigation:{
|
||||||
|
marginBottom: 20,
|
||||||
|
alignItems:"center"
|
||||||
|
|
||||||
|
},
|
||||||
|
button:{
|
||||||
|
borderRadius: 80,
|
||||||
|
minHeight: 60,
|
||||||
|
justifyContent: "center",
|
||||||
|
paddingHorizontal: 20
|
||||||
|
},
|
||||||
|
text: {}
|
||||||
|
})
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import { Slot } from 'expo-router';
|
import { Slot } from 'expo-router';
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { initDatabase } from '../services/database';
|
import { addCategory, initDatabase } from '../services/database';
|
||||||
import { AuthProvider } from './contexts/AuthContext';
|
import { AuthProvider } from './contexts/AuthContext';
|
||||||
|
import { ThemeProvider } from './contexts/ThemeContext';
|
||||||
|
|
||||||
export default function _layout() {
|
export default function _layout() {
|
||||||
|
|
||||||
|
|
@ -9,10 +10,11 @@ export default function _layout() {
|
||||||
initDatabase();
|
initDatabase();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
console.log("layout called")
|
|
||||||
return (
|
return (
|
||||||
<AuthProvider>
|
<AuthProvider>
|
||||||
<Slot />
|
<ThemeProvider>
|
||||||
|
<Slot />
|
||||||
|
</ThemeProvider>
|
||||||
</AuthProvider>
|
</AuthProvider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -4,9 +4,10 @@ import * as SecureStore from 'expo-secure-store'
|
||||||
|
|
||||||
interface AuthProps {
|
interface AuthProps {
|
||||||
authState?: {email: string | null; authenticated: boolean | null; session: string | null};
|
authState?: {email: string | null; authenticated: boolean | null; session: string | null};
|
||||||
|
isLoading?: boolean | null;
|
||||||
onRegister?: (email: string, password: string) => Promise<any>;
|
onRegister?: (email: string, password: string) => Promise<any>;
|
||||||
onLogin?: (email: string, password: string) => Promise<any>
|
onLogin?: (email: string, password: string) => Promise<any>;
|
||||||
onLogout?: () => void
|
onLogout?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SESSION_KEY = 'my_session'
|
const SESSION_KEY = 'my_session'
|
||||||
|
|
@ -50,38 +51,31 @@ export const AuthProvider = ({children}: any) => {
|
||||||
email: string | null;
|
email: string | null;
|
||||||
authenticated: boolean | null;
|
authenticated: boolean | null;
|
||||||
session : string | null;
|
session : string | null;
|
||||||
isLoading: boolean;
|
|
||||||
}>({
|
}>({
|
||||||
email: null, authenticated: null, session: null, isLoading: false
|
email: null, authenticated: null, session: null
|
||||||
});
|
});
|
||||||
|
const [isLoading, setIsLoading] = useState(true)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadSession = async () => {
|
const loadSession = async () => {
|
||||||
setAuthState((prev) => {
|
setIsLoading(true)
|
||||||
return {
|
|
||||||
...prev,
|
|
||||||
isLoading: true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
const session = await getStorageItemAsync(SESSION_KEY)
|
const session = await getStorageItemAsync(SESSION_KEY)
|
||||||
const email = await getStorageItemAsync(USER_KEY)
|
const email = await getStorageItemAsync(USER_KEY)
|
||||||
|
|
||||||
if(session && email){
|
if(session !== null && email !== null){
|
||||||
setAuthState({
|
console.log("applied session", session, email)
|
||||||
email: email,
|
setAuthState( (prev) => {
|
||||||
authenticated: true,
|
return {
|
||||||
session: session,
|
email: email,
|
||||||
isLoading: false
|
authenticated: true,
|
||||||
|
session: session,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
setAuthState((prev) => {
|
|
||||||
return {
|
setIsLoading(false)
|
||||||
...prev,
|
|
||||||
isLoading: false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
loadSession()
|
loadSession()
|
||||||
},[])
|
},[])
|
||||||
|
|
@ -92,29 +86,23 @@ export const AuthProvider = ({children}: any) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const login = async (email: string, password: string) => {
|
const login = async (email: string, password: string) => {
|
||||||
|
setIsLoading(true)
|
||||||
//login functionality goes here
|
//login functionality goes here
|
||||||
console.log("login called")
|
console.log("login called")
|
||||||
setAuthState((prev) => {
|
|
||||||
return{
|
|
||||||
...prev,
|
|
||||||
isLoading: true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
setAuthState({
|
setAuthState({
|
||||||
email: email,
|
email: email,
|
||||||
authenticated: true,
|
authenticated: true,
|
||||||
session: "super duper session token das wir vlt mal brauchen",
|
session: "super duper session token das wir vlt mal brauchen"
|
||||||
isLoading: false
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
await setStorageItemAsync(SESSION_KEY, "super duper session token das wir vlt mal brauchen")
|
await setStorageItemAsync(SESSION_KEY, "super duper session token das wir vlt mal brauchen")
|
||||||
await setStorageItemAsync(USER_KEY, email)
|
await setStorageItemAsync(USER_KEY, email)
|
||||||
|
setIsLoading(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
const logout = async () => {
|
const logout = async () => {
|
||||||
|
setIsLoading(true)
|
||||||
await setStorageItemAsync(SESSION_KEY, null)
|
await setStorageItemAsync(SESSION_KEY, null)
|
||||||
await setStorageItemAsync(USER_KEY, null)
|
await setStorageItemAsync(USER_KEY, null)
|
||||||
|
|
||||||
|
|
@ -122,8 +110,9 @@ export const AuthProvider = ({children}: any) => {
|
||||||
email: null,
|
email: null,
|
||||||
authenticated: false,
|
authenticated: false,
|
||||||
session: null,
|
session: null,
|
||||||
isLoading: false
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setIsLoading(false)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -131,7 +120,8 @@ export const AuthProvider = ({children}: any) => {
|
||||||
onRegister: register,
|
onRegister: register,
|
||||||
onLogin: login,
|
onLogin: login,
|
||||||
onLogout: logout,
|
onLogout: logout,
|
||||||
authState
|
isLoading: isLoading,
|
||||||
|
authState: authState
|
||||||
}
|
}
|
||||||
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>
|
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>
|
||||||
}
|
}
|
||||||
97
app/contexts/ThemeContext.tsx
Normal file
97
app/contexts/ThemeContext.tsx
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
import {useContext, createContext, useState, useEffect} from "react"
|
||||||
|
import AsyncStorage from "@react-native-async-storage/async-storage"
|
||||||
|
import { useColorScheme } from "react-native";
|
||||||
|
import themeColors from "../../constants/colors";
|
||||||
|
|
||||||
|
|
||||||
|
interface ThemeProps {
|
||||||
|
isSystemTheme?: boolean
|
||||||
|
theme: "light" | "dark";
|
||||||
|
colors: typeof themeColors.light & typeof themeColors.dark;
|
||||||
|
applySystemTheme?: () => void;
|
||||||
|
applyTheme?: (theme: "light" | "dark") => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const THEME_KEY = "THEME"
|
||||||
|
const SYSTEM_THEME_KEY = "SYSTEM_THEME"
|
||||||
|
|
||||||
|
const ThemeContext = createContext<ThemeProps>({theme: "light", colors: themeColors.light})
|
||||||
|
|
||||||
|
export const useTheme = () => {
|
||||||
|
return useContext(ThemeContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ThemeProvider = ({children} : any) => {
|
||||||
|
const currentSystemTheme = useColorScheme()
|
||||||
|
const [isSystemTheme, setIsSystemTheme] = useState<boolean>(true);
|
||||||
|
const [theme, setTheme] = useState<"light" | "dark">("light");
|
||||||
|
const [colors, setColors] = useState<typeof themeColors.light & typeof themeColors.dark>(themeColors.light)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log("effect called")
|
||||||
|
const loadTheme = async () => {
|
||||||
|
try {
|
||||||
|
const is_system_theme = await AsyncStorage.getItem(SYSTEM_THEME_KEY)
|
||||||
|
const saved_theme = await AsyncStorage.getItem(THEME_KEY);
|
||||||
|
|
||||||
|
if(is_system_theme !== "false"){//We will use !== false bacause system theme should be used if unspecified
|
||||||
|
applySystemTheme();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(saved_theme === "light" || saved_theme === "dark"){
|
||||||
|
applyTheme(saved_theme);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loadTheme();
|
||||||
|
}, [currentSystemTheme])
|
||||||
|
|
||||||
|
|
||||||
|
const applySystemTheme = () => {
|
||||||
|
const storeSystemTheme = async () => {
|
||||||
|
console.log("applySystemTheme")
|
||||||
|
await AsyncStorage.setItem(SYSTEM_THEME_KEY, "true")
|
||||||
|
}
|
||||||
|
|
||||||
|
storeSystemTheme();
|
||||||
|
setIsSystemTheme(true)
|
||||||
|
applyThemeInternal(currentSystemTheme ?? "light")
|
||||||
|
}
|
||||||
|
|
||||||
|
const applyThemeInternal = (theme: "light" | "dark") => {
|
||||||
|
const storeTheme = async (theme: "light" | "dark") => {
|
||||||
|
await AsyncStorage.setItem(THEME_KEY, theme)
|
||||||
|
}
|
||||||
|
|
||||||
|
setTheme(theme);
|
||||||
|
storeTheme(theme);
|
||||||
|
setColors(themeColors[theme])
|
||||||
|
}
|
||||||
|
|
||||||
|
const applyTheme = (theme: "light" | "dark") => {
|
||||||
|
const unsetSytemTheme = async () => {
|
||||||
|
AsyncStorage.setItem(SYSTEM_THEME_KEY, "false");
|
||||||
|
}
|
||||||
|
unsetSytemTheme()
|
||||||
|
setIsSystemTheme(false);
|
||||||
|
applyThemeInternal(theme);
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = {
|
||||||
|
isSystemTheme: isSystemTheme,
|
||||||
|
applyTheme: applyTheme,
|
||||||
|
applySystemTheme: applySystemTheme,
|
||||||
|
theme: theme,
|
||||||
|
colors: colors,
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ThemeContext.Provider value={value}>
|
||||||
|
{children}
|
||||||
|
</ThemeContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -6,9 +6,8 @@ import { useAuth } from './contexts/AuthContext'
|
||||||
export default function index() {
|
export default function index() {
|
||||||
const {authState} = useAuth()
|
const {authState} = useAuth()
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Redirect href={authState?.authenticated ? "/home/" : "/login"}></Redirect>
|
<Redirect href={authState?.authenticated ? "/home/" : "/login"}></Redirect>
|
||||||
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
66
components/home/userSettings/Setting.tsx
Normal file
66
components/home/userSettings/Setting.tsx
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
import { View, Text, StyleSheet, Switch, SwitchProps, useColorScheme, TouchableOpacityProps, TouchableOpacity, ViewProps } from 'react-native'
|
||||||
|
import React from 'react'
|
||||||
|
import { SIZES } from '../../../constants/theme'
|
||||||
|
import { useThemeColor } from '../../../hooks/useThemeColor';
|
||||||
|
import { CustomCard } from "../../"
|
||||||
|
import { useTheme } from '../../../app/contexts/ThemeContext';
|
||||||
|
|
||||||
|
interface ToggleSettingProps extends SwitchProps {
|
||||||
|
settingsTitle: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ToggleSetting(props: ToggleSettingProps) {
|
||||||
|
const {settingsTitle, ...rest} = props;
|
||||||
|
const { colors } = useTheme()
|
||||||
|
|
||||||
|
return (
|
||||||
|
|
||||||
|
<View style={[{ backgroundColor: colors.containerColor}, styles.settingsTile]}>
|
||||||
|
<Text style={[styles.settingTitle, {color: rest.disabled ? colors.secondaryText: colors.primaryText }]}>
|
||||||
|
{settingsTitle}
|
||||||
|
</Text>
|
||||||
|
<Switch
|
||||||
|
{...rest}
|
||||||
|
thumbColor={rest.thumbColor === undefined ? colors.accentColor: rest.thumbColor}
|
||||||
|
trackColor={rest.trackColor === undefined ? {true: "#E88C3F", false: colors.elementDefaultColor}: rest.trackColor}
|
||||||
|
|
||||||
|
></Switch>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ButtonSettingProps extends TouchableOpacityProps {
|
||||||
|
settingsTitle: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ButtonSetting(props: ButtonSettingProps){
|
||||||
|
const {settingsTitle, ...rest} = props;
|
||||||
|
const { colors } = useTheme();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TouchableOpacity {...rest}>
|
||||||
|
<View style={[styles.settingsTile, {backgroundColor: colors.containerColor}]}>
|
||||||
|
<Text style={[styles.settingTitle, {color: colors.primaryText}]}>{settingsTitle}</Text>
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
settingTitle: {
|
||||||
|
fontSize: SIZES.large
|
||||||
|
},
|
||||||
|
settingsTile: {
|
||||||
|
width: "100%",
|
||||||
|
minHeight: 60,
|
||||||
|
paddingVertical: 5,
|
||||||
|
paddingHorizontal: 20,
|
||||||
|
borderRadius: 80,
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
marginBottom: 10
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
//home
|
//home
|
||||||
import ExpenseItem from "./home/expenseItem/expenseItem"
|
import ExpenseItem from "./home/expenseItem/expenseItem"
|
||||||
import Welcome from "./home/Welcome/Welcome"
|
import Welcome from "./home/Welcome/Welcome"
|
||||||
|
import { ToggleSetting, ButtonSetting } from "./home/userSettings/Setting"
|
||||||
|
|
||||||
//common
|
//common
|
||||||
import LoadingSymbol from "./common/loadingSymbol/loadingSymbol"
|
import LoadingSymbol from "./common/loadingSymbol/loadingSymbol"
|
||||||
import Plus from "./common/plus/plus"
|
import Plus from "./common/plus/plus"
|
||||||
import SearchBar from "./common/searchBar/SearchBar"
|
import SearchBar from "./common/searchBar/SearchBar"
|
||||||
|
import CustomCard from "./common/customCard/CustomCard"
|
||||||
|
|
||||||
|
|
||||||
//login
|
//login
|
||||||
|
|
@ -14,6 +16,8 @@ import Input from "./login/input"
|
||||||
export {
|
export {
|
||||||
ExpenseItem, Input,
|
ExpenseItem, Input,
|
||||||
LoadingSymbol, Plus,
|
LoadingSymbol, Plus,
|
||||||
SearchBar, Welcome
|
SearchBar, Welcome,
|
||||||
|
ToggleSetting, CustomCard,
|
||||||
|
ButtonSetting
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ export default {
|
||||||
tabIconSelected: "#EF6C00",
|
tabIconSelected: "#EF6C00",
|
||||||
|
|
||||||
backgroundColor: "#121212",
|
backgroundColor: "#121212",
|
||||||
containerColor: "#181818",
|
containerColor: "#1c1c1c",
|
||||||
elementDefaultColor: "#535353",
|
elementDefaultColor: "#535353",
|
||||||
elementSelectedColor: "#B3B3B3",
|
elementSelectedColor: "#B3B3B3",
|
||||||
accentColor: "#EF6C00",
|
accentColor: "#EF6C00",
|
||||||
|
|
|
||||||
31
package-lock.json
generated
31
package-lock.json
generated
|
|
@ -9,6 +9,7 @@
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@expo/vector-icons": "^13.0.0",
|
"@expo/vector-icons": "^13.0.0",
|
||||||
|
"@react-native-async-storage/async-storage": "1.18.2",
|
||||||
"@react-navigation/native": "^6.0.2",
|
"@react-navigation/native": "^6.0.2",
|
||||||
"expo": "~49.0.15",
|
"expo": "~49.0.15",
|
||||||
"expo-font": "~11.4.0",
|
"expo-font": "~11.4.0",
|
||||||
|
|
@ -4277,6 +4278,17 @@
|
||||||
"react": "^16.8 || ^17.0 || ^18.0"
|
"react": "^16.8 || ^17.0 || ^18.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@react-native-async-storage/async-storage": {
|
||||||
|
"version": "1.18.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.18.2.tgz",
|
||||||
|
"integrity": "sha512-dM8AfdoeIxlh+zqgr0o5+vCTPQ0Ru1mrPzONZMsr7ufp5h+6WgNxQNza7t0r5qQ6b04AJqTlBNixTWZxqP649Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"merge-options": "^3.0.4"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react-native": "^0.0.0-0 || 0.60 - 0.72 || 1000.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@react-native-community/cli": {
|
"node_modules/@react-native-community/cli": {
|
||||||
"version": "11.3.7",
|
"version": "11.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-11.3.7.tgz",
|
"resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-11.3.7.tgz",
|
||||||
|
|
@ -13452,6 +13464,25 @@
|
||||||
"resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz",
|
||||||
"integrity": "sha512-OcjA+jzjOYzKmKS6IQVALHLVz+rNTMPoJvCztFaZxwG14wtAW7VRZjwTQu06vKCYOxh4jVnik7ya0SXTB0W+xA=="
|
"integrity": "sha512-OcjA+jzjOYzKmKS6IQVALHLVz+rNTMPoJvCztFaZxwG14wtAW7VRZjwTQu06vKCYOxh4jVnik7ya0SXTB0W+xA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/merge-options": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz",
|
||||||
|
"integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"is-plain-obj": "^2.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/merge-options/node_modules/is-plain-obj": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/merge-stream": {
|
"node_modules/merge-stream": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@expo/vector-icons": "^13.0.0",
|
"@expo/vector-icons": "^13.0.0",
|
||||||
|
"@react-native-async-storage/async-storage": "1.18.2",
|
||||||
"@react-navigation/native": "^6.0.2",
|
"@react-navigation/native": "^6.0.2",
|
||||||
"expo": "~49.0.15",
|
"expo": "~49.0.15",
|
||||||
"expo-font": "~11.4.0",
|
"expo-font": "~11.4.0",
|
||||||
|
|
|
||||||
Reference in a new issue