mirror of
https://github.com/urosran/cally.git
synced 2025-07-10 07:07:16 +00:00
user settings, points slider
This commit is contained in:
@ -1,12 +1,15 @@
|
||||
import SettingsPage from "@/components/pages/settings/SettingsPage";
|
||||
import { AuthContextProvider } from "@/contexts/AuthContext";
|
||||
import { SettingsContextProvider } from "@/contexts/SettingsContext";
|
||||
import React from "react";
|
||||
import { View } from "react-native-ui-lib";
|
||||
|
||||
export default function Screen() {
|
||||
return (
|
||||
<SettingsContextProvider>
|
||||
<SettingsPage />
|
||||
</SettingsContextProvider>
|
||||
<AuthContextProvider>
|
||||
<SettingsContextProvider>
|
||||
<SettingsPage />
|
||||
</SettingsContextProvider>
|
||||
</AuthContextProvider>
|
||||
);
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ const SignUpPage = (props: { unsetRegister: () => any }) => {
|
||||
const { mutateAsync: signUp } = useSignUp();
|
||||
|
||||
const handleSignUp = async () => {
|
||||
await signUp({ email, password });
|
||||
await signUp({ email, password, firstName, lastName });
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -5,6 +5,7 @@ import { Entypo, Ionicons, Octicons } from "@expo/vector-icons";
|
||||
import CalendarSettingsPage from "./CalendarSettingsPage";
|
||||
import ChoreRewardSettings from "./ChoreRewardSettings";
|
||||
import UserSettings from "./UserSettings";
|
||||
import { AuthContextProvider } from "@/contexts/AuthContext";
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
mainBtn: {
|
||||
@ -24,74 +25,82 @@ const pageIndex = {
|
||||
const SettingsPage = () => {
|
||||
const [selectedPage, setSelectedPage] = useState<number>(0);
|
||||
return (
|
||||
<View>
|
||||
{selectedPage == 0 && (
|
||||
<View centerH marginH-30 marginT-30>
|
||||
<Button
|
||||
backgroundColor="white"
|
||||
style={styles.mainBtn}
|
||||
label="Manage my profile"
|
||||
color="#07b8c7"
|
||||
iconSource={() => (
|
||||
<Ionicons
|
||||
name="person-circle-sharp"
|
||||
size={24}
|
||||
color="#07b8c7"
|
||||
style={{ marginRight: 10 }}
|
||||
/>
|
||||
)}
|
||||
onPress={() => setSelectedPage(pageIndex.user)}
|
||||
/>
|
||||
<Button
|
||||
backgroundColor="white"
|
||||
style={styles.mainBtn}
|
||||
label="Calendar settings"
|
||||
color="#fd1775"
|
||||
iconSource={() => (
|
||||
<Ionicons
|
||||
name="home-outline"
|
||||
size={24}
|
||||
color="#fd1775"
|
||||
style={{ marginRight: 10 }}
|
||||
/>
|
||||
)}
|
||||
onPress={() => {setSelectedPage(pageIndex.calendar)}}
|
||||
/>
|
||||
<Button
|
||||
backgroundColor="white"
|
||||
style={styles.mainBtn}
|
||||
label="Chore reward settings"
|
||||
color="#ff9900"
|
||||
iconSource={() => (
|
||||
<Octicons
|
||||
name="gear"
|
||||
size={24}
|
||||
color="#ff9900"
|
||||
style={{ marginRight: 10 }}
|
||||
/>
|
||||
)}
|
||||
onPress={() => setSelectedPage(pageIndex.chore)}
|
||||
/>
|
||||
<Button
|
||||
backgroundColor="white"
|
||||
style={styles.mainBtn}
|
||||
label="Kaly privacy policy"
|
||||
iconSource={() => (
|
||||
<Entypo
|
||||
name="text-document"
|
||||
size={24}
|
||||
color="#6c645b"
|
||||
style={{ marginRight: 10 }}
|
||||
/>
|
||||
)}
|
||||
color="#6c645b"
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
{selectedPage == pageIndex.calendar && <CalendarSettingsPage setSelectedPage={setSelectedPage} />}
|
||||
{selectedPage == pageIndex.chore && <ChoreRewardSettings setSelectedPage={setSelectedPage} />}
|
||||
{selectedPage == pageIndex.user && <UserSettings setSelectedPage={setSelectedPage} />}
|
||||
</View>
|
||||
<View>
|
||||
{selectedPage == 0 && (
|
||||
<View centerH marginH-30 marginT-30>
|
||||
<Button
|
||||
backgroundColor="white"
|
||||
style={styles.mainBtn}
|
||||
label="Manage my profile"
|
||||
color="#07b8c7"
|
||||
iconSource={() => (
|
||||
<Ionicons
|
||||
name="person-circle-sharp"
|
||||
size={24}
|
||||
color="#07b8c7"
|
||||
style={{ marginRight: 10 }}
|
||||
/>
|
||||
)}
|
||||
onPress={() => setSelectedPage(pageIndex.user)}
|
||||
/>
|
||||
<Button
|
||||
backgroundColor="white"
|
||||
style={styles.mainBtn}
|
||||
label="Calendar settings"
|
||||
color="#fd1775"
|
||||
iconSource={() => (
|
||||
<Ionicons
|
||||
name="home-outline"
|
||||
size={24}
|
||||
color="#fd1775"
|
||||
style={{ marginRight: 10 }}
|
||||
/>
|
||||
)}
|
||||
onPress={() => {
|
||||
setSelectedPage(pageIndex.calendar);
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
backgroundColor="white"
|
||||
style={styles.mainBtn}
|
||||
label="Chore reward settings"
|
||||
color="#ff9900"
|
||||
iconSource={() => (
|
||||
<Octicons
|
||||
name="gear"
|
||||
size={24}
|
||||
color="#ff9900"
|
||||
style={{ marginRight: 10 }}
|
||||
/>
|
||||
)}
|
||||
onPress={() => setSelectedPage(pageIndex.chore)}
|
||||
/>
|
||||
<Button
|
||||
backgroundColor="white"
|
||||
style={styles.mainBtn}
|
||||
label="Kaly privacy policy"
|
||||
iconSource={() => (
|
||||
<Entypo
|
||||
name="text-document"
|
||||
size={24}
|
||||
color="#6c645b"
|
||||
style={{ marginRight: 10 }}
|
||||
/>
|
||||
)}
|
||||
color="#6c645b"
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
{selectedPage == pageIndex.calendar && (
|
||||
<CalendarSettingsPage setSelectedPage={setSelectedPage} />
|
||||
)}
|
||||
{selectedPage == pageIndex.chore && (
|
||||
<ChoreRewardSettings setSelectedPage={setSelectedPage} />
|
||||
)}
|
||||
{selectedPage == pageIndex.user && (
|
||||
<UserSettings setSelectedPage={setSelectedPage} />
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -4,6 +4,7 @@ import { Ionicons } from "@expo/vector-icons";
|
||||
import { ScrollView, StyleSheet } from "react-native";
|
||||
import MyProfile from "./user_settings_views/MyProfile";
|
||||
import MyGroup from "./user_settings_views/MyGroup";
|
||||
import { useAuthContext } from "@/contexts/AuthContext";
|
||||
|
||||
const UserSettings = (props: { setSelectedPage: (page: number) => void }) => {
|
||||
const [selectedView, setSelectedView] = useState<boolean>(true);
|
||||
|
@ -1,8 +1,19 @@
|
||||
import { View, Text, TextField } from "react-native-ui-lib";
|
||||
import React from "react";
|
||||
import React, { useState } from "react";
|
||||
import { StyleSheet } from "react-native";
|
||||
import { ScrollView } from "react-native-gesture-handler";
|
||||
import { useAuthContext } from "@/contexts/AuthContext";
|
||||
import { useSettingsContext } from "@/contexts/SettingsContext";
|
||||
import { useUpdateUserData } from "@/hooks/firebase/useUpdateUserData";
|
||||
const MyProfile = () => {
|
||||
const { user, profileData } = useAuthContext();
|
||||
|
||||
const [lastName, setLastName] = useState<string>(profileData?.lastName || "");
|
||||
const [firstName, setFirstName] = useState<string>(
|
||||
profileData?.firstName || ""
|
||||
);
|
||||
|
||||
const { mutateAsync: updateUserData } = useUpdateUserData();
|
||||
return (
|
||||
<View>
|
||||
<View style={styles.card}>
|
||||
@ -18,15 +29,38 @@ const MyProfile = () => {
|
||||
<Text text80 marginT-10 marginB-7 color="#a1a1a1">
|
||||
First name
|
||||
</Text>
|
||||
<TextField text70 placeholder="First name" style={styles.txtBox} />
|
||||
<TextField
|
||||
text70
|
||||
placeholder="First name"
|
||||
style={styles.txtBox}
|
||||
value={firstName}
|
||||
onChangeText={async (value) => {
|
||||
setFirstName(value);
|
||||
await updateUserData({ newUserData: { firstName: value } });
|
||||
}}
|
||||
/>
|
||||
<Text text80 marginT-10 marginB-7 color="#a1a1a1">
|
||||
Last name
|
||||
</Text>
|
||||
<TextField text70 placeholder="Last name" style={styles.txtBox} />
|
||||
<TextField
|
||||
text70
|
||||
placeholder="Last name"
|
||||
style={styles.txtBox}
|
||||
value={lastName}
|
||||
onChangeText={async (value) => {
|
||||
setLastName(value);
|
||||
await updateUserData({ newUserData: { lastName: value } });
|
||||
}}
|
||||
/>
|
||||
<Text text80 marginT-10 marginB-7 color="#a1a1a1">
|
||||
Email address
|
||||
</Text>
|
||||
<TextField text70 placeholder="Email address" style={styles.txtBox} />
|
||||
<TextField
|
||||
text70
|
||||
placeholder="Email address"
|
||||
value={user?.email?.toString()}
|
||||
style={styles.txtBox}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@ -35,7 +69,7 @@ const MyProfile = () => {
|
||||
<Text text80 marginT-20 marginB-7 color="#a1a1a1">
|
||||
Time Zone
|
||||
</Text>
|
||||
<TextField text70 placeholder="Email address" style={styles.txtBox} />
|
||||
<TextField text70 placeholder="Time Zone" style={styles.txtBox} />
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
|
@ -20,6 +20,7 @@ import LinearGradient from "react-native-linear-gradient";
|
||||
import { PanningDirectionsEnum } from "react-native-ui-lib/src/components/panningViews/panningProvider";
|
||||
import { repeatOptions, useToDosContext } from "@/contexts/ToDosContext";
|
||||
import { setDate } from "date-fns";
|
||||
import PointsSlider from "@/components/shared/PointsSlider";
|
||||
|
||||
const AddChore = () => {
|
||||
const { addToDo, toDos } = useToDosContext();
|
||||
@ -232,36 +233,11 @@ const AddChore = () => {
|
||||
Reward Points
|
||||
</Text>
|
||||
</View>
|
||||
<View marginH-30 row spread>
|
||||
<View width={"80%"}>
|
||||
<Slider
|
||||
value={points}
|
||||
onValueChange={(value) => setPoints(value)}
|
||||
minimumValue={0}
|
||||
step={10}
|
||||
maximumValue={100}
|
||||
/>
|
||||
<View row spread>
|
||||
<Text>0</Text>
|
||||
<Text>50</Text>
|
||||
<Text>100</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View style={{ marginLeft: "auto" }}>
|
||||
<TextField
|
||||
value={points.toString()}
|
||||
onChangeText={(text) => {
|
||||
handleChange(text);
|
||||
}}
|
||||
containerStyle={{
|
||||
borderWidth: 1,
|
||||
borderColor: "#d9d9d9",
|
||||
width: 45,
|
||||
borderRadius: 5,
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<PointsSlider
|
||||
points={points}
|
||||
setPoints={setPoints}
|
||||
handleChange={handleChange}
|
||||
/>
|
||||
</Dialog>
|
||||
</LinearGradient>
|
||||
);
|
||||
|
43
components/shared/PointsSlider.tsx
Normal file
43
components/shared/PointsSlider.tsx
Normal file
@ -0,0 +1,43 @@
|
||||
import { View, Text, Slider, TextField } from "react-native-ui-lib";
|
||||
import React from "react";
|
||||
|
||||
const PointsSlider = (props: {
|
||||
points: number;
|
||||
setPoints(value: number): void;
|
||||
handleChange(value: string): void;
|
||||
}) => {
|
||||
return (
|
||||
<View marginH-30 row spread>
|
||||
<View width={"80%"}>
|
||||
<Slider
|
||||
value={props.points}
|
||||
onValueChange={(value) => props.setPoints(value)}
|
||||
minimumValue={0}
|
||||
step={10}
|
||||
maximumValue={100}
|
||||
/>
|
||||
<View row spread>
|
||||
<Text>0</Text>
|
||||
<Text>50</Text>
|
||||
<Text>100</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View style={{ marginLeft: "auto" }}>
|
||||
<TextField
|
||||
value={props.points.toString()}
|
||||
onChangeText={(text) => {
|
||||
props.handleChange(text);
|
||||
}}
|
||||
containerStyle={{
|
||||
borderWidth: 1,
|
||||
borderColor: "#d9d9d9",
|
||||
width: 45,
|
||||
borderRadius: 5,
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default PointsSlider;
|
@ -1,4 +1,5 @@
|
||||
import { createContext, FC, ReactNode, useContext, useState } from "react";
|
||||
import { useAuthContext } from "./AuthContext";
|
||||
|
||||
export const colorMap = {
|
||||
pink: "#ea156c",
|
||||
@ -8,8 +9,16 @@ export const colorMap = {
|
||||
purple: "#7305d4",
|
||||
};
|
||||
|
||||
interface IUserDetails {
|
||||
email: string | undefined;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
}
|
||||
|
||||
interface ISettingsContext {
|
||||
calendarColor: string;
|
||||
userDetails: IUserDetails;
|
||||
editUserDetails: (details: Partial<IUserDetails>) => void;
|
||||
setCalendarColor: (color: string) => void;
|
||||
}
|
||||
|
||||
@ -18,10 +27,24 @@ const SettingsContext = createContext<ISettingsContext>(undefined!);
|
||||
export const SettingsContextProvider: FC<{ children: ReactNode }> = ({
|
||||
children,
|
||||
}) => {
|
||||
const { user } = useAuthContext();
|
||||
const [userDetails, setUserDetails] = useState<IUserDetails>({
|
||||
email: user?.email?.toString(),
|
||||
firstName: "",
|
||||
lastName: "",
|
||||
});
|
||||
const [calendarColor, setCalendarColor] = useState<string>(colorMap.pink);
|
||||
|
||||
const editUserDetails = (details: Partial<IUserDetails>) => {
|
||||
setUserDetails((prevDetails) => ({
|
||||
...prevDetails,
|
||||
...details,
|
||||
}));
|
||||
};
|
||||
return (
|
||||
<SettingsContext.Provider value={{ calendarColor, setCalendarColor }}>
|
||||
<SettingsContext.Provider
|
||||
value={{ calendarColor, setCalendarColor, userDetails, editUserDetails }}
|
||||
>
|
||||
{children}
|
||||
</SettingsContext.Provider>
|
||||
);
|
||||
|
@ -13,7 +13,7 @@ service cloud.firestore {
|
||||
// all client requests to your Firestore database will be denied until you Update
|
||||
// your rules
|
||||
match /{document=**} {
|
||||
allow read, write: if request.time < timestamp.date(2024, 9, 5);
|
||||
allow read, write;
|
||||
}
|
||||
}
|
||||
}
|
@ -7,7 +7,8 @@ export interface User {
|
||||
|
||||
export interface UserProfile {
|
||||
userType: ProfileType;
|
||||
name: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
childrenIds?: string[];
|
||||
birthday?: Date;
|
||||
parentId?: string;
|
||||
|
@ -8,9 +8,9 @@ export const useSignUp = () => {
|
||||
|
||||
return useMutation({
|
||||
mutationKey: ["signUp"],
|
||||
mutationFn: async ({email, password}: { email: string, password: string }) => {
|
||||
mutationFn: async ({email, password, firstName, lastName}: { email: string, password: string, firstName: string, lastName: string }) => {
|
||||
const res = await auth().createUserWithEmailAndPassword(email, password);
|
||||
await updateUserData({newUserData: {userType: ProfileType.PARENT}, customUser: res.user});
|
||||
await updateUserData({newUserData: {userType: ProfileType.PARENT, firstName: firstName, lastName: lastName}, customUser: res.user});
|
||||
}
|
||||
});
|
||||
}
|
@ -17,7 +17,7 @@ export const useUpdateUserData = () => {
|
||||
await firestore()
|
||||
.collection("Profiles")
|
||||
.doc(user.uid)
|
||||
.set(newUserData);
|
||||
.update(newUserData);
|
||||
|
||||
const profileData = await firestore().collection("Profiles").doc(user?.uid!).get()
|
||||
setProfileData(profileData.data() as UserProfile)
|
||||
|
Reference in New Issue
Block a user