fixed settings paging, calendar style,

This commit is contained in:
ivic00
2024-10-29 20:15:20 +01:00
parent 8ba6f7aecf
commit 74d82e2029
9 changed files with 1934 additions and 1729 deletions

View File

@ -23,9 +23,16 @@ import NavToDosIcon from "@/assets/svgs/NavToDosIcon";
import NavBrainDumpIcon from "@/assets/svgs/NavBrainDumpIcon";
import NavCalendarIcon from "@/assets/svgs/NavCalendarIcon";
import NavSettingsIcon from "@/assets/svgs/NavSettingsIcon";
import { useAtom } from "jotai";
import {
settingsPageIndex,
userSettingsView,
} from "@/components/pages/calendar/atoms";
export default function TabLayout() {
const { mutateAsync: signOut } = useSignOut();
const [pageIndex, setPageIndex] = useAtom(settingsPageIndex);
const [userView, setUserView] = useAtom(userSettingsView);
return (
<Drawer
@ -66,14 +73,22 @@ export default function TabLayout() {
title={"Calendar"}
color="rgb(7, 184, 199)"
bgColor={"rgb(231, 248, 250)"}
pressFunc={() => props.navigation.navigate("calendar")}
pressFunc={() => {
props.navigation.navigate("calendar");
setPageIndex(0);
setUserView(true);
}}
icon={<NavCalendarIcon />}
/>
<DrawerButton
color="#50be0c"
title={"Groceries"}
bgColor={"#eef9e7"}
pressFunc={() => props.navigation.navigate("grocery")}
pressFunc={() => {
props.navigation.navigate("grocery");
setPageIndex(0);
setUserView(true);
}}
icon={<NavGroceryIcon />}
/>
</View>
@ -95,21 +110,33 @@ export default function TabLayout() {
color="#8005eb"
title={"To Do's"}
bgColor={"#f3e6fd"}
pressFunc={() => props.navigation.navigate("todos")}
pressFunc={() => {
props.navigation.navigate("todos");
setPageIndex(0);
setUserView(true);
}}
icon={<NavToDosIcon />}
/>
<DrawerButton
color="#e0ca03"
title={"Brain Dump"}
bgColor={"#fffacb"}
pressFunc={() => props.navigation.navigate("brain_dump")}
pressFunc={() => {
props.navigation.navigate("brain_dump");
setPageIndex(0);
setUserView(true);
}}
icon={<NavBrainDumpIcon />}
/>
{/*<DrawerItem label="Logout" onPress={() => signOut()} />*/}
</View>
</View>
<Button
onPress={() => props.navigation.navigate("settings")}
onPress={() => {
props.navigation.navigate("settings");
setPageIndex(0);
setUserView(true);
}}
label={"Manage Settings"}
labelStyle={styles.label}
iconSource={() => (

View File

@ -1,11 +1,18 @@
import React, { memo } from "react";
import {Button, Picker, PickerModes, SegmentedControl, Text, View,} from "react-native-ui-lib";
import {
Button,
Picker,
PickerModes,
SegmentedControl,
Text,
View,
} from "react-native-ui-lib";
import { MaterialIcons } from "@expo/vector-icons";
import { modeMap, months } from "./constants";
import { StyleSheet } from "react-native";
import { useAtom } from "jotai";
import { modeAtom, selectedDateAtom } from "@/components/pages/calendar/atoms";
import {isSameDay} from "date-fns";
import { format, isSameDay } from "date-fns";
import { useAuthContext } from "@/contexts/AuthContext";
export const CalendarHeader = memo(() => {
@ -82,16 +89,14 @@ export const CalendarHeader = memo(() => {
borderWidth: 0.7,
borderColor: "#dadce0",
height: 30,
paddingHorizontal: 10
paddingHorizontal: 10,
}}
labelStyle={{
fontSize: 12,
color: "black",
fontFamily: "Manrope_500Medium",
}}
label={new Date().toLocaleDateString("en-US", {
timeZone: profileData?.timeZone || "",
})}
label={format(new Date(), "dd/MM/yyyy")}
onPress={() => {
setSelectedDate(new Date());
}}

View File

@ -39,7 +39,7 @@ export const EventCalendar: React.FC<EventCalendarProps> = React.memo(
const [isRendering, setIsRendering] = useState(true);
const [offsetMinutes, setOffsetMinutes] = useState(getTotalMinutes());
const todaysDate = new Date()
const todaysDate = new Date();
useEffect(() => {
if (events && mode) {
@ -107,7 +107,7 @@ export const EventCalendar: React.FC<EventCalendarProps> = React.memo(
}, [selectedDate, mode]);
const dateStyle = useMemo(() => {
if (mode === "week") return undefined
if (mode === "week") return undefined;
return isSameDate(todaysDate, selectedDate) && mode === "day"
? styles.dayHeader
: styles.otherDayHeader;
@ -205,8 +205,29 @@ export const EventCalendar: React.FC<EventCalendarProps> = React.memo(
headerContentStyle={memoizedHeaderContentStyle}
onSwipeEnd={handleSwipeEnd}
scrollOffsetMinutes={offsetMinutes}
theme={{
palette: {
nowIndicator: "#fd1575",
gray: {
"100": "#e8eaed",
"200": "#e8eaed",
"500": "#b7b7b7",
"800": "#919191",
},
},
typography: {
fontFamily: "PlusJakartaSans_500Medium",
sm: { fontFamily: "Manrope_600SemiBold", fontSize: 15 },
xl: {
fontFamily: "PlusJakartaSans_500Medium",
fontSize: 16,
},
moreLabel: {},
xs:{fontSize: 10}
},
}}
dayHeaderStyle={dateStyle}
dayHeaderHighlightColor={dayHeaderColor}
dayHeaderHighlightColor={"white"}
renderCustomDateForMonth={renderCustomDateForMonth}
showAdjacentMonths
/>

View File

@ -1,4 +1,4 @@
import { atom } from 'jotai';
import { atom } from "jotai";
import { CalendarEvent } from "@/components/pages/calendar/interfaces";
export const editVisibleAtom = atom<boolean>(false);
@ -7,3 +7,5 @@ export const isFamilyViewAtom = atom<boolean>(false);
export const modeAtom = atom<"week" | "month" | "day">("week");
export const selectedDateAtom = atom<Date>(new Date());
export const selectedNewEventDateAtom = atom<Date | undefined>(undefined);
export const settingsPageIndex = atom<number>(0);
export const userSettingsView = atom<boolean>(true);

View File

@ -16,9 +16,11 @@ import {UserProfile} from "@firebase/auth";
import { useFetchAndSaveGoogleEvents } from "@/hooks/useFetchAndSaveGoogleEvents";
import { useFetchAndSaveOutlookEvents } from "@/hooks/useFetchAndSaveOutlookEvents";
import { useFetchAndSaveAppleEvents } from "@/hooks/useFetchAndSaveAppleEvents";
import * as AppleAuthentication from 'expo-apple-authentication';
import * as AppleAuthentication from "expo-apple-authentication";
import ExpoLocalization from "expo-localization/src/ExpoLocalization";
import { colorMap } from "@/constants/colorMap";
import { useAtom } from "jotai";
import { settingsPageIndex } from "../calendar/atoms";
const googleConfig = {
androidClientId:
@ -43,17 +45,22 @@ const microsoftConfig = {
"email",
"offline_access",
"Calendars.ReadWrite",
"User.Read"
"User.Read",
],
authorizationEndpoint: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
authorizationEndpoint:
"https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
tokenEndpoint: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
};
const CalendarSettingsPage = (props: {
setSelectedPage: (page: number) => void;
}) => {
const CalendarSettingsPage = () => {
const { profileData } = useAuthContext();
const [firstDayOfWeek, setFirstDayOfWeek] = useState<string>(profileData?.firstDayOfWeek ?? ExpoLocalization.getCalendars()[0].firstWeekday === 1 ? "Mondays" : "Sundays");
const [pageIndex, setPageIndex] = useAtom(settingsPageIndex);
const [firstDayOfWeek, setFirstDayOfWeek] = useState<string>(
profileData?.firstDayOfWeek ??
ExpoLocalization.getCalendars()[0].firstWeekday === 1
? "Mondays"
: "Sundays"
);
const [selectedColor, setSelectedColor] = useState<string>(
profileData?.eventColor ?? colorMap.pink
@ -63,10 +70,14 @@ const CalendarSettingsPage = (props: {
);
const { mutateAsync: updateUserData } = useUpdateUserData();
const {mutateAsync: fetchAndSaveGoogleEvents, isLoading: isSyncingGoogle} = useFetchAndSaveGoogleEvents();
const {mutateAsync: fetchAndSaveOutlookEvents, isLoading: isSyncingOutlook} = useFetchAndSaveOutlookEvents();
const {mutateAsync: fetchAndSaveAppleEvents, isLoading: isSyncingApple} = useFetchAndSaveAppleEvents();
const { mutateAsync: fetchAndSaveGoogleEvents, isLoading: isSyncingGoogle } =
useFetchAndSaveGoogleEvents();
const {
mutateAsync: fetchAndSaveOutlookEvents,
isLoading: isSyncingOutlook,
} = useFetchAndSaveOutlookEvents();
const { mutateAsync: fetchAndSaveAppleEvents, isLoading: isSyncingApple } =
useFetchAndSaveAppleEvents();
WebBrowser.maybeCompleteAuthSession();
const [_, response, promptAsync] = Google.useAuthRequest(googleConfig);
@ -91,13 +102,18 @@ const CalendarSettingsPage = (props: {
const googleMail = userInfo.email;
let googleAccounts = profileData?.googleAccounts;
const updatedGoogleAccounts = googleAccounts ? {...googleAccounts, [googleMail]: accessToken} : {[googleMail]: accessToken};
const updatedGoogleAccounts = googleAccounts
? { ...googleAccounts, [googleMail]: accessToken }
: { [googleMail]: accessToken };
await updateUserData({
newUserData: { googleAccounts: updatedGoogleAccounts },
});
await fetchAndSaveGoogleEvents({token: accessToken, email: googleMail})
await fetchAndSaveGoogleEvents({
token: accessToken,
email: googleMail,
});
}
} catch (error) {
console.error("Error during Google sign-in:", error);
@ -160,11 +176,14 @@ const CalendarSettingsPage = (props: {
console.log("Access token received, fetching user info...");
// Fetch user info from Microsoft Graph API to get the email
const userInfoResponse = await fetch("https://graph.microsoft.com/v1.0/me", {
const userInfoResponse = await fetch(
"https://graph.microsoft.com/v1.0/me",
{
headers: {
Authorization: `Bearer ${tokenData.access_token}`,
},
});
}
);
const userInfo = await userInfoResponse.json();
console.log("User info received:", userInfo);
@ -175,14 +194,19 @@ const CalendarSettingsPage = (props: {
const outlookMail = userInfo.mail || userInfo.userPrincipalName;
let microsoftAccounts = profileData?.microsoftAccounts;
const updatedMicrosoftAccounts = microsoftAccounts ? {...microsoftAccounts, [outlookMail]: tokenData.access_token} : {[outlookMail]: tokenData.access_token};
const updatedMicrosoftAccounts = microsoftAccounts
? { ...microsoftAccounts, [outlookMail]: tokenData.access_token }
: { [outlookMail]: tokenData.access_token };
// Update user data with Microsoft token and email
await updateUserData({
newUserData: { microsoftAccounts: updatedMicrosoftAccounts },
});
await fetchAndSaveOutlookEvents(tokenData.access_token, outlookMail)
await fetchAndSaveOutlookEvents(
tokenData.access_token,
outlookMail
);
console.log("User data updated successfully.");
}
}
@ -220,7 +244,9 @@ const CalendarSettingsPage = (props: {
console.log("User data updated with Apple ID token.");
await fetchAndSaveAppleEvents({ token: appleToken, email: appleMail! });
} else {
console.warn("Apple authentication was not successful or email was hidden.");
console.warn(
"Apple authentication was not successful or email was hidden."
);
}
} catch (error) {
console.error("Error during Apple Sign-in:", error);
@ -260,8 +286,10 @@ const CalendarSettingsPage = (props: {
const handleChangeFirstDayOfWeek = (firstDayOfWeek: string) => {
setFirstDayOfWeek(firstDayOfWeek === "Sundays" ? "Mondays" : "Sundays");
debouncedUpdateFirstDayOfWeek(firstDayOfWeek === "Sundays" ? "Mondays" : "Sundays");
}
debouncedUpdateFirstDayOfWeek(
firstDayOfWeek === "Sundays" ? "Mondays" : "Sundays"
);
};
const handleChangeColor = (color: string) => {
setPreviousSelectedColor(selectedColor);
@ -269,7 +297,10 @@ const CalendarSettingsPage = (props: {
debouncedUpdateUserData(color);
};
const clearToken = async (provider: "google" | "outlook" | "apple", email: string) => {
const clearToken = async (
provider: "google" | "outlook" | "apple",
email: string
) => {
const newUserData: Partial<UserProfile> = {};
if (provider === "google") {
let googleAccounts = profileData?.googleAccounts;
@ -326,9 +357,8 @@ const CalendarSettingsPage = (props: {
return (
<ScrollView>
<View marginH-30 marginB-30>
<TouchableOpacity onPress={() => props.setSelectedPage(0)}>
<View row marginT-20 marginB-35 centerV>
<TouchableOpacity onPress={() => setPageIndex(0)}>
<View row marginT-20 marginB-20 marginL-20 centerV>
<Ionicons
name="chevron-back"
size={14}
@ -343,6 +373,7 @@ const CalendarSettingsPage = (props: {
</Text>
</View>
</TouchableOpacity>
<View marginH-30 marginB-30>
<Text style={styles.subTitle}>Calendar settings</Text>
<View style={styles.card}>
<Text style={styles.cardTitle} marginB-14>
@ -428,7 +459,7 @@ const CalendarSettingsPage = (props: {
label={"Connect Google"}
labelStyle={styles.addCalLbl}
labelProps={{
numberOfLines: 2
numberOfLines: 2,
}}
iconSource={() => (
<View marginR-15>
@ -439,15 +470,18 @@ const CalendarSettingsPage = (props: {
color="black"
text70BL
/>
{profileData?.googleAccounts ? Object.keys(profileData?.googleAccounts)?.map((googleMail) => {
{profileData?.googleAccounts
? Object.keys(profileData?.googleAccounts)?.map((googleMail) => {
const googleToken = profileData?.googleAccounts?.[googleMail];
return googleToken && <Button
return (
googleToken && (
<Button
key={googleMail}
onPress={() => clearToken("google", googleMail)}
label={`Disconnect ${googleMail}`}
labelStyle={styles.addCalLbl}
labelProps={{
numberOfLines: 2
numberOfLines: 2,
}}
iconSource={() => (
<View marginR-15>
@ -458,14 +492,17 @@ const CalendarSettingsPage = (props: {
color="black"
text70BL
/>
}) : null}
)
);
})
: null}
<Button
onPress={() => handleAppleSignIn()}
label={"Connect Apple"}
labelStyle={styles.addCalLbl}
labelProps={{
numberOfLines: 2
numberOfLines: 2,
}}
iconSource={() => (
<View marginR-15>
@ -476,15 +513,18 @@ const CalendarSettingsPage = (props: {
color="black"
text70BL
/>
{profileData?.appleAccounts ? Object.keys(profileData?.appleAccounts)?.map((appleEmail) => {
{profileData?.appleAccounts
? Object.keys(profileData?.appleAccounts)?.map((appleEmail) => {
const appleToken = profileData?.appleAccounts?.[appleEmail];
return appleToken && <Button
return (
appleToken && (
<Button
key={appleEmail}
onPress={() => clearToken("apple", appleEmail)}
label={`Disconnect ${appleEmail}`}
labelStyle={styles.addCalLbl}
labelProps={{
numberOfLines: 2
numberOfLines: 2,
}}
iconSource={() => (
<View marginR-15>
@ -495,14 +535,17 @@ const CalendarSettingsPage = (props: {
color="black"
text70BL
/>
}) : null}
)
);
})
: null}
<Button
onPress={() => handleMicrosoftSignIn()}
label={"Connect Outlook"}
labelStyle={styles.addCalLbl}
labelProps={{
numberOfLines: 2
numberOfLines: 2,
}}
iconSource={() => (
<View marginR-15>
@ -513,15 +556,20 @@ const CalendarSettingsPage = (props: {
color="black"
text70BL
/>
{profileData?.microsoftAccounts ? Object.keys(profileData?.microsoftAccounts)?.map((microsoftEmail) => {
const microsoftToken = profileData?.microsoftAccounts?.[microsoftEmail];
return microsoftToken && <Button
{profileData?.microsoftAccounts
? Object.keys(profileData?.microsoftAccounts)?.map(
(microsoftEmail) => {
const microsoftToken =
profileData?.microsoftAccounts?.[microsoftEmail];
return (
microsoftToken && (
<Button
key={microsoftEmail}
onPress={() => clearToken("outlook", microsoftEmail)}
label={`Disconnect ${microsoftEmail}`}
labelStyle={styles.addCalLbl}
labelProps={{
numberOfLines: 2
numberOfLines: 2,
}}
iconSource={() => (
<View marginR-15>
@ -532,9 +580,15 @@ const CalendarSettingsPage = (props: {
color="black"
text70BL
/>
}) : null}
)
);
}
)
: null}
{(isConnectedToGoogle || isConnectedToMicrosoft || isConnectedToApple) && (
{(isConnectedToGoogle ||
isConnectedToMicrosoft ||
isConnectedToApple) && (
<>
<Text style={styles.subTitle} marginT-30 marginB-20>
Connected Calendars
@ -542,16 +596,30 @@ const CalendarSettingsPage = (props: {
<View style={styles.noPaddingCard}>
<View style={{ marginTop: 20 }}>
{profileData?.googleAccounts && Object.keys(profileData?.googleAccounts)?.map((googleEmail) => {
const googleToken = profileData?.googleAccounts?.[googleEmail];
return googleToken && (
{profileData?.googleAccounts &&
Object.keys(profileData?.googleAccounts)?.map(
(googleEmail) => {
const googleToken =
profileData?.googleAccounts?.[googleEmail];
return (
googleToken && (
<TouchableOpacity
onPress={() => fetchAndSaveGoogleEvents({token: googleToken, email: googleEmail})}
onPress={() =>
fetchAndSaveGoogleEvents({
token: googleToken,
email: googleEmail,
})
}
>
<View row paddingR-20 center>
<Button
disabled={isSyncingGoogle}
onPress={() => fetchAndSaveGoogleEvents({token: googleToken, email: googleEmail})}
onPress={() =>
fetchAndSaveGoogleEvents({
token: googleToken,
email: googleEmail,
})
}
label={`Sync ${googleEmail}`}
labelStyle={styles.addCalLbl}
labelProps={{ numberOfLines: 3 }}
@ -568,28 +636,41 @@ const CalendarSettingsPage = (props: {
{isSyncingGoogle ? (
<ActivityIndicator />
) : (
<Ionicons name={"refresh"} size={20} color={"#000000"}/>
<Ionicons
name={"refresh"}
size={20}
color={"#000000"}
/>
)}
</View>
</TouchableOpacity>
)
})}
);
}
)}
{profileData?.appleAccounts && Object.keys(profileData?.appleAccounts)?.map((appleEmail) => {
{profileData?.appleAccounts &&
Object.keys(profileData?.appleAccounts)?.map((appleEmail) => {
const appleToken = profileData?.appleAccounts?.[appleEmail];
return appleToken && (
return (
appleToken && (
<TouchableOpacity
onPress={() => fetchAndSaveAppleEvents({
onPress={() =>
fetchAndSaveAppleEvents({
email: appleEmail,
token: appleToken
})}>
token: appleToken,
})
}
>
<View row paddingR-20 center>
<Button
disabled={isSyncingApple}
onPress={() => fetchAndSaveAppleEvents({
onPress={() =>
fetchAndSaveAppleEvents({
email: appleEmail,
token: appleToken
})}
token: appleToken,
})
}
label={`Sync ${appleEmail}`}
labelStyle={styles.addCalLbl}
labelProps={{ numberOfLines: 3 }}
@ -605,29 +686,42 @@ const CalendarSettingsPage = (props: {
{isSyncingApple ? (
<ActivityIndicator />
) : (
<Ionicons name={"refresh"} size={20} color={"#000000"}/>
<Ionicons
name={"refresh"}
size={20}
color={"#000000"}
/>
)}
</View>
</TouchableOpacity>
)
);
})}
{profileData?.microsoftAccounts && Object.keys(profileData?.microsoftAccounts)?.map((microsoftEmail) => {
const microsoftToken = profileData?.microsoftAccounts?.[microsoftEmail];
return microsoftToken && (
{profileData?.microsoftAccounts &&
Object.keys(profileData?.microsoftAccounts)?.map(
(microsoftEmail) => {
const microsoftToken =
profileData?.microsoftAccounts?.[microsoftEmail];
return (
microsoftToken && (
<TouchableOpacity
onPress={() => fetchAndSaveOutlookEvents({
onPress={() =>
fetchAndSaveOutlookEvents({
token: microsoftToken,
email: microsoftEmail
})}
email: microsoftEmail,
})
}
>
<View row paddingR-20 center>
<Button
disabled={isSyncingOutlook}
onPress={() => fetchAndSaveOutlookEvents({
onPress={() =>
fetchAndSaveOutlookEvents({
token: microsoftToken,
email: microsoftEmail
})}
email: microsoftEmail,
})
}
label={`Sync ${microsoftEmail}`}
labelStyle={styles.addCalLbl}
labelProps={{ numberOfLines: 3 }}
@ -643,12 +737,18 @@ const CalendarSettingsPage = (props: {
{isSyncingOutlook ? (
<ActivityIndicator />
) : (
<Ionicons name={"refresh"} size={20} color={"#000000"}/>
<Ionicons
name={"refresh"}
size={20}
color={"#000000"}
/>
)}
</View>
</TouchableOpacity>
)
})}
);
}
)}
</View>
</View>
</>
@ -701,7 +801,7 @@ const styles = StyleSheet.create({
width: "75%",
textAlign: "left",
lineHeight: 20,
overflow: "visible"
overflow: "visible",
},
subTitle: {
fontFamily: "Manrope_600SemiBold",

View File

@ -4,16 +4,16 @@ import { Ionicons } from "@expo/vector-icons";
import { ToDosContextProvider } from "@/contexts/ToDosContext";
import ToDosList from "../todos/ToDosList";
import { ScrollView } from "react-native-gesture-handler";
import { settingsPageIndex } from "../calendar/atoms";
import { useAtom } from "jotai";
const ChoreRewardSettings = () => {
const [pageIndex, setPageIndex] = useAtom(settingsPageIndex);
const ChoreRewardSettings = (props: {
setSelectedPage: (page: number) => void;
}) => {
return (
<ToDosContextProvider>
<View marginT-10 marginH-20>
<ScrollView>
<TouchableOpacity onPress={() => props.setSelectedPage(0)}>
<View row marginT-20 marginB-35 centerV>
<TouchableOpacity onPress={() => setPageIndex(0)}>
<View row marginT-20 marginB-20 marginL-20 centerV>
<Ionicons
name="chevron-back"
size={14}
@ -28,6 +28,8 @@ const ChoreRewardSettings = (props: {
</Text>
</View>
</TouchableOpacity>
<View marginH-20>
<ScrollView>
<Text text60R marginB-20>
Chore Reward Settings
</Text>

View File

@ -10,6 +10,8 @@ import CalendarIcon from "@/assets/svgs/CalendarIcon";
import PrivacyPolicyIcon from "@/assets/svgs/PrivacyPolicyIcon";
import ArrowRightIcon from "@/assets/svgs/ArrowRightIcon";
import { ProfileType, useAuthContext } from "@/contexts/AuthContext";
import { settingsPageIndex } from "../calendar/atoms";
import { useAtom } from "jotai";
const pageIndex = {
main: 0,
@ -20,13 +22,13 @@ const pageIndex = {
};
const SettingsPage = () => {
const {profileData} = useAuthContext()
const isntParent = profileData?.userType !== ProfileType.PARENT
const { profileData } = useAuthContext();
const [pageIndex, setPageIndex] = useAtom(settingsPageIndex);
const isntParent = profileData?.userType !== ProfileType.PARENT;
const [selectedPage, setSelectedPage] = useState<number>(0);
return (
<View flexG>
{selectedPage == 0 && (
{pageIndex == 0 && (
<View flexG centerH marginH-30 marginT-30>
<Button
disabled={isntParent}
@ -35,13 +37,18 @@ const SettingsPage = () => {
children={
<View row centerV width={"100%"}>
<ProfileIcon style={{ marginRight: 10 }} color="#07b9c8" />
<Text style={[styles.label, isntParent && styles.disabledText]}>
<Text
style={[
styles.label,
isntParent ? styles.disabledText : { color: "#07b9c8" },
]}
>
Manage My Profile
</Text>
<ArrowRightIcon style={{ marginLeft: "auto" }} />
</View>
}
onPress={() => setSelectedPage(pageIndex.user)}
onPress={() => setPageIndex(1)}
/>
<Button
disabled={isntParent}
@ -50,14 +57,19 @@ const SettingsPage = () => {
children={
<View row centerV width={"100%"}>
<CalendarIcon style={{ marginRight: 10 }} />
<Text style={[styles.label, isntParent && styles.disabledText]}>
<Text
style={[
styles.label,
isntParent ? styles.disabledText : { color: "#FD1775" },
]}
>
Calendar Settings
</Text>
<ArrowRightIcon style={{ marginLeft: "auto" }} />
</View>
}
onPress={() => {
setSelectedPage(pageIndex.calendar);
setPageIndex(2);
}}
/>
<Button
@ -72,13 +84,13 @@ const SettingsPage = () => {
color="#ff9900"
style={{ marginRight: 10 }}
/>
<Text style={[styles.label, isntParent && styles.disabledText]}>
<Text style={[styles.label, isntParent ? styles.disabledText : {color: "#ff9900"}]}>
To-Do Reward Settings
</Text>
<ArrowRightIcon style={{ marginLeft: "auto" }} />
</View>
}
onPress={() => setSelectedPage(pageIndex.chore)}
onPress={() => setPageIndex(3)}
/>
<Button
backgroundColor="white"
@ -86,24 +98,16 @@ const SettingsPage = () => {
children={
<View row centerV width={"100%"}>
<PrivacyPolicyIcon style={{ marginRight: 10 }} />
<Text style={styles.label}>
Cally Privacy Policy
</Text>
<Text style={[styles.label]} color={"#6C645B"}>Cally Privacy Policy</Text>
<ArrowRightIcon style={{ marginLeft: "auto" }} />
</View>
}
/>
</View>
)}
{selectedPage == pageIndex.calendar && (
<CalendarSettingsPage setSelectedPage={setSelectedPage}/>
)}
{selectedPage == pageIndex.chore && (
<ChoreRewardSettings setSelectedPage={setSelectedPage}/>
)}
{selectedPage == pageIndex.user && (
<UserSettings setSelectedPage={setSelectedPage}/>
)}
{pageIndex == 2 && <CalendarSettingsPage />}
{pageIndex == 3 && <ChoreRewardSettings />}
{pageIndex == 1 && <UserSettings />}
</View>
);
};
@ -123,6 +127,6 @@ const styles = StyleSheet.create({
textAlignVertical: "center",
},
disabledText: {
color: '#A9A9A9', // Example of a gray color for disabled text
color: "#A9A9A9", // Example of a gray color for disabled text
},
});

View File

@ -4,15 +4,30 @@ 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 { useAtom } from "jotai";
import { settingsPageIndex, userSettingsView } from "../calendar/atoms";
import { AuthContextProvider } from "@/contexts/AuthContext";
const UserSettings = (props: { setSelectedPage: (page: number) => void }) => {
const [selectedView, setSelectedView] = useState<boolean>(true);
const UserSettings = () => {
const [pageIndex, setPageIndex] = useAtom(settingsPageIndex);
const [userView, setUserView] = useAtom(userSettingsView);
return (
<AuthContextProvider>
<View flexG>
<ScrollView style={{ paddingBottom: 20, minHeight: "100%" }}>
<TouchableOpacity onPress={() => props.setSelectedPage(0)}>
<View row marginT-20 marginB-35 centerV>
<Ionicons name="chevron-back" size={14} color="#979797" style={{paddingBottom: 3}} />
<TouchableOpacity
onPress={() => {
setPageIndex(0);
setUserView(true);
}}
>
<View row marginT-20 marginB-20 marginL-20 centerV>
<Ionicons
name="chevron-back"
size={14}
color="#979797"
style={{ paddingBottom: 3 }}
/>
<Text
style={{ fontFamily: "Poppins_400Regular", fontSize: 14.71 }}
color="#979797"
@ -21,53 +36,54 @@ const UserSettings = (props: { setSelectedPage: (page: number) => void }) => {
</Text>
</View>
</TouchableOpacity>
<View marginH-20 flexG style={{ minHeight: "90%" }}>
<View marginH-26 flexG style={{ minHeight: "90%" }}>
<Text text60R marginB-25>
User Management
</Text>
<View style={styles.buttonSwitch} spread row>
<TouchableOpacity
onPress={() => setSelectedView(true)}
onPress={() => setUserView(true)}
centerV
centerH
style={selectedView == true ? styles.btnSelected : styles.btnNot}
style={userView == true ? styles.btnSelected : styles.btnNot}
>
<View>
<Text
style={styles.btnTxt}
color={selectedView ? "white" : "black"}
color={userView ? "white" : "black"}
>
My Profile
</Text>
</View>
</TouchableOpacity>
<TouchableOpacity
onPress={() => setSelectedView(false)}
onPress={() => setUserView(false)}
centerV
centerH
style={selectedView == false ? styles.btnSelected : styles.btnNot}
style={userView == false ? styles.btnSelected : styles.btnNot}
>
<View>
<Text
style={styles.btnTxt}
color={!selectedView ? "white" : "black"}
color={!userView ? "white" : "black"}
>
My Group
</Text>
</View>
</TouchableOpacity>
</View>
{selectedView && <MyProfile />}
{!selectedView && <MyGroup />}
{userView && <MyProfile />}
{!userView && <MyGroup />}
</View>
</ScrollView>
{!selectedView && (
{!userView && (
<View>
<Text>selview</Text>
</View>
)}
</View>
</AuthContextProvider>
);
};

View File

@ -15,10 +15,10 @@ import {
View,
} from "react-native-ui-lib";
import React, { useEffect, useRef, useState } from "react";
import {ScrollView, StyleSheet} from "react-native";
import { ImageBackground, ScrollView, StyleSheet } from "react-native";
import { PickerSingleValue } from "react-native-ui-lib/src/components/picker/types";
import { useCreateSubUser } from "@/hooks/firebase/useCreateSubUser";
import {ProfileType} from "@/contexts/AuthContext";
import { ProfileType, useAuthContext } from "@/contexts/AuthContext";
import { useGetFamilyMembers } from "@/hooks/firebase/useGetFamilyMembers";
import UserMenu from "@/components/pages/settings/user_settings_views/UserMenu";
import { uuidv4 } from "@firebase/util";
@ -43,10 +43,13 @@ const MyGroup = () => {
const lNameRef = useRef<TextFieldRef>(null);
const emailRef = useRef<TextFieldRef>(null);
const [showQRCodeDialog, setShowQRCodeDialog] = useState<string | boolean>(false);
const [showQRCodeDialog, setShowQRCodeDialog] = useState<string | boolean>(
false
);
const { mutateAsync: createSubUser, isLoading, isError } = useCreateSubUser();
const { data: familyMembers } = useGetFamilyMembers(true);
const { user } = useAuthContext();
const parents =
familyMembers?.filter((x) => x.userType === ProfileType.PARENT) ?? [];
@ -101,8 +104,7 @@ const MyGroup = () => {
setFirstName("");
setLastName("");
setEmail("");
}, [])
}, []);
// @ts-ignore
return (
@ -117,7 +119,7 @@ const MyGroup = () => {
{(!!parents.length || !!children.length) && (
<>
<Text style={styles.subTit} marginV-10>
<Text style={styles.subTit} marginB-10>
Family
</Text>
{[...parents, ...children]?.map((member, index) => (
@ -128,31 +130,37 @@ const MyGroup = () => {
style={styles.familyCard}
row
centerV
padding-10
paddingT-10
>
<Avatar
source={{uri: "https://via.placeholder.com/60"}}
size={40}
backgroundColor={Colors.grey60}
{member.pfp ? (
<ImageBackground
style={styles.pfp}
borderRadius={10.56}
source={{ uri: member.pfp || undefined }}
/>
<View marginL-10>
<Text text70M>
) : (
<View style={[styles.pfp, {backgroundColor: "#ea156d"}]} />
)}
<View row marginL-10 centerV>
<Text style={styles.name}>
{member.firstName} {member.lastName}
</Text>
<Text text90 grey40>
</View>
<View flexG />
<View row centerV gap-10>
<Text style={styles.userType}>
{member.userType === ProfileType.PARENT
? "Admin (You)"
? `Admin${
member.uid === user?.uid ? " (You)" : ""
}`
: "Child"}
</Text>
</View>
<View flex-1/>
<UserMenu
setShowQRCodeDialog={(val) => setShowQRCodeDialog(val)}
showQRCodeDialog={showQRCodeDialog === member?.uid}
userId={member?.uid!}
/>
</View>
</Card>
))}
</>
@ -160,7 +168,7 @@ const MyGroup = () => {
{!!caregivers.length && (
<>
<Text text70 marginB-10 marginT-15>
<Text style={styles.subTit} marginB-10 marginT-15>
Caregivers
</Text>
{caregivers?.map((member) => (
@ -312,9 +320,11 @@ const MyGroup = () => {
<Text style={{ fontFamily: "Manrope_500Medium", fontSize: 16 }}>
New User Information
</Text>
<TouchableOpacity onPress={() => {
setShowNewUserInfoDialog(false)
}}>
<TouchableOpacity
onPress={() => {
setShowNewUserInfoDialog(false);
}}
>
<CircledXIcon />
</TouchableOpacity>
</View>
@ -331,8 +341,7 @@ const MyGroup = () => {
style={{ borderRadius: 25 }}
center
/>
<TouchableOpacity onPress={() => {
}}>
<TouchableOpacity onPress={() => {}}>
<Text color="#50be0c" style={styles.jakarta13} marginL-15>
Upload User Profile Photo
</Text>
@ -349,21 +358,30 @@ const MyGroup = () => {
floatingPlaceholder
style={styles.inViewPicker}
trailingAccessory={
<View style={{
<View
style={{
justifyContent: "center",
alignItems: "center",
height: "100%",
marginTop: -38,
paddingRight: 15
}}>
<Ionicons name={"chevron-down"} style={{alignSelf: "center"}} size={20}
color={"#000000"}/>
paddingRight: 15,
}}
>
<Ionicons
name={"chevron-down"}
style={{ alignSelf: "center" }}
size={20}
color={"#000000"}
/>
</View>
}
>
<Picker.Item label="Child" value={ProfileType.CHILD} />
<Picker.Item label="Parent" value={ProfileType.PARENT} />
<Picker.Item label="Caregiver" value={ProfileType.CAREGIVER}/>
<Picker.Item
label="Caregiver"
value={ProfileType.CAREGIVER}
/>
<Picker.Item
label="Family Device"
value={ProfileType.FAMILY_DEVICE}
@ -387,7 +405,7 @@ const MyGroup = () => {
onChangeText={setFirstName}
style={styles.inputField}
onSubmitEditing={() => {
lNameRef.current?.focus()
lNameRef.current?.focus();
}}
blurOnSubmit={false}
returnKeyType="next"
@ -404,11 +422,10 @@ const MyGroup = () => {
onChangeText={setLastName}
style={styles.inputField}
onSubmitEditing={() => {
emailRef.current?.focus()
emailRef.current?.focus();
}}
blurOnSubmit={false}
returnKeyType="next"
/>
</>
)}
@ -470,8 +487,9 @@ const styles = StyleSheet.create({
marginVertical: 15,
backgroundColor: "white",
width: "100%",
borderRadius: 15,
padding: 20,
borderRadius: 12,
paddingHorizontal: 21,
paddingVertical: 20,
},
bottomButton: {
position: "absolute",
@ -556,6 +574,16 @@ const styles = StyleSheet.create({
fontFamily: "PlusJakartaSans_500Medium",
fontSize: 13,
},
pfp: { aspectRatio: 1, width: 37.03, borderRadius: 10.56 },
userType: {
fontFamily: "Manrope_500Medium",
fontSize: 12,
color: "#858585",
},
name: {
fontFamily: "Manrope_600SemiBold",
fontSize: 16,
},
});
export default MyGroup;