Merge branch 'dev'

# Conflicts:
#	app/(auth)/calendar/index.tsx
This commit is contained in:
Milan Paunovic
2024-11-26 21:01:10 +01:00
8 changed files with 600 additions and 435 deletions

View File

@ -22,7 +22,32 @@ export default function Screen() {
}
}, [resyncAllCalendars]);
const refreshControl = (
return (
<View style={{ flex: 1 }}>
<View style={{ flex: 1, zIndex: 0 }}>
{Device.deviceType === DeviceType.TABLET ? (
<TabletCalendarPage />
) : (
<CalendarPage />
)}
</View>
<ScrollView
style={{
position: "absolute",
top: 0,
left: isTablet ? "15%" : 0,
height: isTablet ? "9%" : "4%",
width: isTablet ? "62%" : "100%",
zIndex: 50,
backgroundColor: "transparent",
}}
contentContainerStyle={{
flex: 1,
justifyContent: "center",
paddingRight: 200,
}}
refreshControl={
<RefreshControl
colors={[
colorMap.pink,
@ -32,23 +57,23 @@ export default function Screen() {
colorMap.teal,
]}
tintColor={colorMap.pink}
progressBackgroundColor="white"
refreshing={isSyncing}
progressBackgroundColor={"white"}
refreshing={refreshing || isSyncing}
onRefresh={onRefresh}
style={{
position: "absolute",
left: "50%", // Position at screen center
transform: [
// Offset by half its own width
{ translateX: -20 }, // Assuming the refresh control is ~40px wide
],
}}
/>
);
return (
<ScrollView
style={{flex: 1, height: "100%",}}
contentContainerStyle={{flex: 1, height: "100%"}}
refreshControl={refreshControl}
}
bounces={true}
showsVerticalScrollIndicator={false}
>
<View style={{flex: 1}}>
{isTablet ? <TabletCalendarPage/> : <CalendarPage/>}
pointerEvents={refreshing || isSyncing ? "auto" : "none"}
/>
</View>
</ScrollView>
);
}

View File

@ -27,7 +27,7 @@ export default function Screen() {
<View style={{flex: 1, padding: 21, paddingBottom: 45, paddingTop: "20%", alignItems: "center"}}>
<View gap-13 width={"100%"} marginB-20>
{householdName && <Text style={{fontSize: 25, fontFamily: 'Manrope_600SemiBold'}}>
You Joined {householdName}
You Joined The {householdName} Household
</Text>}
<Text style={{fontSize: 40, fontFamily: 'Manrope_600SemiBold'}}>
Let's get started!

View File

@ -55,7 +55,7 @@ const SettingsPage = () => {
isntParent ? styles.disabledText : { color: "#07b9c8" },
]}
>
Manage My Profile
User Profiles & Settings
</Text>
<ArrowRightIcon style={{ marginLeft: "auto" }} />
</View>

View File

@ -34,6 +34,7 @@ import KeyboardManager, {
import { ScrollView } from "react-native-gesture-handler";
import { useUploadProfilePicture } from "@/hooks/useUploadProfilePicture";
import UserOptions from "./UserOptions";
import { colorMap } from "@/constants/colorMap";
type MyGroupProps = {
onNewUserClick: boolean;
@ -181,7 +182,7 @@ const MyGroup: React.FC<MyGroupProps> = ({
/>
) : (
<View
style={[styles.pfp, { backgroundColor: "#ea156d" }]}
style={[styles.pfp, { backgroundColor: member.eventColor || colorMap.pink }]}
/>
)}
<View row marginL-10 centerV>

View File

@ -109,7 +109,7 @@ const MyProfile = () => {
useEffect(() => {
setHouseholdName(hhName);
}, [hhName])
}, [hhName]);
const pickImage = async () => {
const permissionResult =
@ -262,40 +262,6 @@ const MyProfile = () => {
/>
</View>
</View>
<View style={styles.card}>
<Text style={styles.subTit}>Settings</Text>
<Text style={styles.jakarta12}>Time Zone</Text>
<View style={styles.viewPicker}>
<Picker
value={timeZone}
onChange={(item) => setTimeZone(item as string)}
showSearch
floatingPlaceholder
style={styles.inViewPicker}
trailingAccessory={
<View
style={{
justifyContent: "center",
alignItems: "center",
height: "100%",
marginTop: -38,
paddingRight: 15,
}}
>
<Ionicons
name={"chevron-down"}
style={{ alignSelf: "center" }}
size={20}
color={"#000000"}
/>
</View>
}
>
{timeZoneItems}
</Picker>
</View>
</View>
<View style={styles.card}>
<Text style={styles.cardTitle} marginB-14>
Color Preference
@ -337,15 +303,92 @@ const MyProfile = () => {
</View>
</TouchableOpacity>
</View>
<View row spread marginT-10>
<TouchableOpacity onPress={() => handleChangeColor(colorMap.navy)}>
<View style={styles.colorBox} backgroundColor={colorMap.navy}>
{selectedColor == colorMap.navy && (
<AntDesign name="check" size={30} color="white" />
)}
</View>
<Button
size="large"
backgroundColor="#ff1637"
label="Delete Profile"
style={{ marginTop: 10 }}
labelStyle={{ fontFamily: "PlusJakartaSans_500Medium", fontSize: 15 }}
onPress={handleShowDeleteDialog}
</TouchableOpacity>
<TouchableOpacity onPress={() => handleChangeColor(colorMap.red)}>
<View style={styles.colorBox} backgroundColor={colorMap.red}>
{selectedColor == colorMap.red && (
<AntDesign name="check" size={30} color="white" />
)}
</View>
</TouchableOpacity>
<TouchableOpacity onPress={() => handleChangeColor(colorMap.gray)}>
<View style={styles.colorBox} backgroundColor={colorMap.gray}>
{selectedColor == colorMap.gray && (
<AntDesign name="check" size={30} color="white" />
)}
</View>
</TouchableOpacity>
<TouchableOpacity onPress={() => handleChangeColor(colorMap.yellow)}>
<View style={styles.colorBox} backgroundColor={colorMap.yellow}>
{selectedColor == colorMap.yellow && (
<AntDesign name="check" size={30} color="white" />
)}
</View>
</TouchableOpacity>
<TouchableOpacity onPress={() => handleChangeColor(colorMap.sky)}>
<View style={styles.colorBox} backgroundColor={colorMap.sky}>
{selectedColor == colorMap.sky && (
<AntDesign name="check" size={30} color="white" />
)}
</View>
</TouchableOpacity>
</View>
</View>
<View style={styles.card}>
<Text style={styles.subTit}>Settings</Text>
<Text style={styles.jakarta12}>Time Zone</Text>
<View style={styles.viewPicker}>
<Picker
value={timeZone}
onChange={(item) => setTimeZone(item as string)}
showSearch
floatingPlaceholder
style={styles.inViewPicker}
trailingAccessory={
<View
style={{
justifyContent: "center",
alignItems: "center",
height: "100%",
marginTop: -38,
paddingRight: 15,
}}
>
<Ionicons
name={"chevron-down"}
style={{ alignSelf: "center" }}
size={20}
color={"#000000"}
/>
</View>
}
>
{timeZoneItems}
</Picker>
</View>
</View>
<TouchableOpacity
onPress={handleShowDeleteDialog}
style={{ marginTop: 10, alignSelf: "center" }}
>
<Text
style={{
color: "#ff1637",
fontFamily: "PlusJakartaSans_500Medium",
fontSize: 15,
}}
>
Delete Profile
</Text>
</TouchableOpacity>
<DeleteProfileDialogs
onFirstYes={() => {
setShowDeleteDialog(false);

View File

@ -1,6 +1,20 @@
import {Button, Colors, Dialog, Image, Picker, Text, TextField, View} from "react-native-ui-lib";
import {
Button,
Colors,
Dialog,
Image,
Picker,
Text,
TextField,
View,
} from "react-native-ui-lib";
import { UserProfile } from "@/hooks/firebase/types/profileTypes";
import {Dimensions, ScrollView, StyleSheet, TouchableOpacity} from "react-native";
import {
Dimensions,
ScrollView,
StyleSheet,
TouchableOpacity,
} from "react-native";
import { colorMap } from "@/constants/colorMap";
import Ionicons from "@expo/vector-icons/Ionicons";
import { AntDesign } from "@expo/vector-icons";
@ -14,10 +28,10 @@ import {PanningDirectionsEnum} from "react-native-ui-lib/src/incubator/panView";
import { useUpdateSubUser } from "@/hooks/firebase/useUpdateSubUser";
type Props = {
open: boolean,
handleClose: Function,
profileData: UserProfile
}
open: boolean;
handleClose: Function;
profileData: UserProfile;
};
const UpdateUserDialog = ({ open, handleClose, profileData }: Props) => {
const [timeZone, setTimeZone] = useState<string>(
profileData?.timeZone! ?? Localization.getCalendars()[0].timeZone
@ -39,7 +53,15 @@ const UpdateUserDialog = ({open, handleClose, profileData} : Props) => {
const { mutateAsync: changeProfilePicture } = useChangeProfilePicture();
const handleUpdateUserData = async () => {
await updateSubUser({ userProfile: {...profileData, firstName, lastName, timeZone, eventColor: selectedColor } });
await updateSubUser({
userProfile: {
...profileData,
firstName,
lastName,
timeZone,
eventColor: selectedColor,
},
});
handleClose();
};
@ -93,10 +115,10 @@ const UpdateUserDialog = ({open, handleClose, profileData} : Props) => {
alignSelf: "stretch",
padding: 0,
paddingTop: 4,
margin: 0
margin: 0,
}}
>
<ScrollView style={{ flex: 1, display: 'flex' }}>
<ScrollView style={{ flex: 1, display: "flex" }}>
<View style={styles.dialogContent}>
<View>
<Text style={styles.title}>Update Profile</Text>
@ -208,40 +230,50 @@ const UpdateUserDialog = ({open, handleClose, profileData} : Props) => {
</Picker>
</View>
</View>
<View paddingH-15 marginT-15 style={{ display: 'flex', flexGrow: 1}}>
<View paddingH-15 marginT-15 style={{ display: "flex", flexGrow: 1 }}>
<Text style={styles.cardTitle} marginB-14>
Color Preference
</Text>
<View row spread>
<TouchableOpacity onPress={() => handleChangeColor(colorMap.pink)}>
<TouchableOpacity
onPress={() => handleChangeColor(colorMap.pink)}
>
<View style={styles.colorBox} backgroundColor={colorMap.pink}>
{selectedColor == colorMap.pink && (
<AntDesign name="check" size={30} color="white" />
)}
</View>
</TouchableOpacity>
<TouchableOpacity onPress={() => handleChangeColor(colorMap.orange)}>
<TouchableOpacity
onPress={() => handleChangeColor(colorMap.orange)}
>
<View style={styles.colorBox} backgroundColor={colorMap.orange}>
{selectedColor == colorMap.orange && (
<AntDesign name="check" size={30} color="white" />
)}
</View>
</TouchableOpacity>
<TouchableOpacity onPress={() => handleChangeColor(colorMap.green)}>
<TouchableOpacity
onPress={() => handleChangeColor(colorMap.green)}
>
<View style={styles.colorBox} backgroundColor={colorMap.green}>
{selectedColor == colorMap.green && (
<AntDesign name="check" size={30} color="white" />
)}
</View>
</TouchableOpacity>
<TouchableOpacity onPress={() => handleChangeColor(colorMap.teal)}>
<TouchableOpacity
onPress={() => handleChangeColor(colorMap.teal)}
>
<View style={styles.colorBox} backgroundColor={colorMap.teal}>
{selectedColor == colorMap.teal && (
<AntDesign name="check" size={30} color="white" />
)}
</View>
</TouchableOpacity>
<TouchableOpacity onPress={() => handleChangeColor(colorMap.purple)}>
<TouchableOpacity
onPress={() => handleChangeColor(colorMap.purple)}
>
<View style={styles.colorBox} backgroundColor={colorMap.purple}>
{selectedColor == colorMap.purple && (
<AntDesign name="check" size={30} color="white" />
@ -249,14 +281,61 @@ const UpdateUserDialog = ({open, handleClose, profileData} : Props) => {
</View>
</TouchableOpacity>
</View>
<View row spread marginT-10>
<TouchableOpacity
onPress={() => handleChangeColor(colorMap.navy)}
>
<View style={styles.colorBox} backgroundColor={colorMap.navy}>
{selectedColor == colorMap.navy && (
<AntDesign name="check" size={30} color="white" />
)}
</View>
</TouchableOpacity>
<TouchableOpacity onPress={() => handleChangeColor(colorMap.red)}>
<View style={styles.colorBox} backgroundColor={colorMap.red}>
{selectedColor == colorMap.red && (
<AntDesign name="check" size={30} color="white" />
)}
</View>
</TouchableOpacity>
<TouchableOpacity
onPress={() => handleChangeColor(colorMap.gray)}
>
<View style={styles.colorBox} backgroundColor={colorMap.gray}>
{selectedColor == colorMap.gray && (
<AntDesign name="check" size={30} color="white" />
)}
</View>
</TouchableOpacity>
<TouchableOpacity
onPress={() => handleChangeColor(colorMap.yellow)}
>
<View style={styles.colorBox} backgroundColor={colorMap.yellow}>
{selectedColor == colorMap.yellow && (
<AntDesign name="check" size={30} color="white" />
)}
</View>
</TouchableOpacity>
<TouchableOpacity onPress={() => handleChangeColor(colorMap.sky)}>
<View style={styles.colorBox} backgroundColor={colorMap.sky}>
{selectedColor == colorMap.sky && (
<AntDesign name="check" size={30} color="white" />
)}
</View>
</TouchableOpacity>
</View>
</View>
<View row center style={{
display: 'flex',
</View>
<View
row
center
style={{
display: "flex",
gap: 10,
alignItems: "flex-end",
marginTop: 50
}}>
marginTop: 10,
}}
>
<Button
style={{
backgroundColor: profileData.eventColor ?? colorMap.pink,
@ -276,7 +355,7 @@ const UpdateUserDialog = ({open, handleClose, profileData} : Props) => {
</View>
</ScrollView>
</Dialog>
)
);
};
const timeZoneItems = Object.keys(tz.zones)
@ -294,7 +373,7 @@ const styles = StyleSheet.create({
paddingHorizontal: 10,
paddingTop: 10,
paddingBottom: 10,
flexGrow: 1
flexGrow: 1,
},
cardTitle: {
fontFamily: "Manrope_500Medium",
@ -342,7 +421,7 @@ const styles = StyleSheet.create({
},
title: {
fontFamily: "Manrope_500Medium",
fontSize: 20
fontSize: 20,
},
label: {
fontFamily: "PlusJakartaSans_500Medium",

View File

@ -11,7 +11,7 @@ import { PanningDirectionsEnum } from "react-native-ui-lib/src/components/pannin
import Ionicons from "@expo/vector-icons/Ionicons";
import { UserProfile } from "@/hooks/firebase/types/profileTypes";
import { StyleSheet } from "react-native";
import { ProfileType } from "@/contexts/AuthContext";
import { ProfileType, useAuthContext } from "@/contexts/AuthContext";
const UserMenu = ({
user,
@ -22,10 +22,24 @@ const UserMenu = ({
showQRCodeDialog: boolean;
setShowQRCodeDialog: (value: string | boolean) => void;
}) => {
const {user: currentUser} = useAuthContext();
const handleShowQRCode = () => {
setShowQRCodeDialog(user.uid!);
};
const getQRCodeText = () => {
if (user.userType === ProfileType.FAMILY_DEVICE) {
return "Open Cally on the family device and scan the code to link it to your family group";
}
if (currentUser?.uid === user.uid) {
return "To connect another device to your profile, open the Cally app on that device and scan this QR code.";
}
return `To connect ${user.firstName}'s device to your Family Group, open the Cally app on their device and scan the QR code.`;
};
return (
<>
<TouchableOpacity onPress={handleShowQRCode}>
@ -45,9 +59,7 @@ const UserMenu = ({
marginB-25
style={{ fontSize: 18, fontFamily: "Manrope_500Medium" }}
>
{user.userType !== ProfileType.FAMILY_DEVICE
? `Open Cally on ${user.firstName}'s device and scan the code to link it to your family group`
: "Open Cally on the family device and scan the code to link it to your family group"}
{getQRCodeText()}
</Text>
<QRCode value={user.uid!} size={150} />
<Button

View File

@ -4,4 +4,9 @@ export const colorMap = {
green: "#46a80a",
teal: "#05a8b6",
purple: "#7305d4",
navy: '#002e42',
red: '#ff1637',
gray: '#607d8b',
yellow: '#ffc107',
sky: '#2196f3'
};