mirror of
https://github.com/urosran/cally.git
synced 2025-07-09 22:57:16 +00:00
added birthday input
This commit is contained in:
@ -3,6 +3,7 @@ import {
|
||||
Button,
|
||||
Card,
|
||||
Colors,
|
||||
DateTimePicker,
|
||||
Dialog,
|
||||
Image,
|
||||
KeyboardAwareScrollView,
|
||||
@ -53,6 +54,11 @@ const MyGroup: React.FC<MyGroupProps> = ({
|
||||
const [firstName, setFirstName] = useState("");
|
||||
const [lastName, setLastName] = useState("");
|
||||
const [email, setEmail] = useState("");
|
||||
const [birthday, setBirthday] = useState<Date>(() => {
|
||||
const date = new Date();
|
||||
date.setFullYear(date.getFullYear() - 3);
|
||||
return date;
|
||||
});
|
||||
|
||||
const { profileData } = useAuthContext();
|
||||
|
||||
@ -66,7 +72,8 @@ const MyGroup: React.FC<MyGroupProps> = ({
|
||||
);
|
||||
|
||||
const { mutateAsync: createSubUser, isLoading, isError } = useCreateSubUser();
|
||||
const { data: familyMembers, refetch: refetchFamilyMembers } = useGetFamilyMembers(true);
|
||||
const { data: familyMembers, refetch: refetchFamilyMembers } =
|
||||
useGetFamilyMembers(true);
|
||||
const { user } = useAuthContext();
|
||||
const {
|
||||
pickImage,
|
||||
@ -77,9 +84,9 @@ const MyGroup: React.FC<MyGroupProps> = ({
|
||||
} = useUploadProfilePicture(newUserId);
|
||||
|
||||
useFocusEffect(
|
||||
useCallback(() => {
|
||||
refetchFamilyMembers();
|
||||
}, [refetchFamilyMembers])
|
||||
useCallback(() => {
|
||||
refetchFamilyMembers();
|
||||
}, [refetchFamilyMembers])
|
||||
);
|
||||
|
||||
const parents =
|
||||
@ -115,6 +122,7 @@ const MyGroup: React.FC<MyGroupProps> = ({
|
||||
firstName,
|
||||
lastName: selectedStatus === ProfileType.FAMILY_DEVICE ? "" : lastName,
|
||||
email: email || `placeholder_${uuidv4().split("-")[0]}@family.device`,
|
||||
birthday: birthday,
|
||||
password: uuidv4(),
|
||||
userType: selectedStatus as ProfileType,
|
||||
});
|
||||
@ -146,8 +154,24 @@ const MyGroup: React.FC<MyGroupProps> = ({
|
||||
setFirstName("");
|
||||
setLastName("");
|
||||
setEmail("");
|
||||
|
||||
const date = new Date();
|
||||
date.setFullYear(date.getFullYear() - 3);
|
||||
setBirthday(date);
|
||||
}, []);
|
||||
|
||||
const getMaxDate = () => {
|
||||
const date = new Date();
|
||||
date.setFullYear(date.getFullYear() - 3); // Minimum age: 3 years
|
||||
return date;
|
||||
};
|
||||
|
||||
const getMinDate = () => {
|
||||
const date = new Date();
|
||||
date.setFullYear(date.getFullYear() - 18); // Maximum age: 18 years
|
||||
return date;
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
return (
|
||||
<View marginB-70>
|
||||
@ -524,6 +548,24 @@ const MyGroup: React.FC<MyGroupProps> = ({
|
||||
blurOnSubmit={false}
|
||||
returnKeyType="next"
|
||||
/>
|
||||
<Text style={styles.jakarta12}>Birthday</Text>
|
||||
<DateTimePicker
|
||||
editable={!isLoading}
|
||||
mode="date"
|
||||
minimumDate={getMinDate()}
|
||||
maximumDate={getMaxDate()}
|
||||
style={[styles.inputField, { paddingVertical: 0 }]}
|
||||
value={birthday}
|
||||
onChange={(date) => {
|
||||
if (date) {
|
||||
const validDate = new Date(date);
|
||||
if (!isNaN(validDate.getTime())) {
|
||||
setBirthday(validDate);
|
||||
console.log("Selected birthday:", validDate);
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import * as ImagePicker from "expo-image-picker";
|
||||
import {
|
||||
Button,
|
||||
Colors,
|
||||
DateTimePicker,
|
||||
Image,
|
||||
Picker,
|
||||
Text,
|
||||
@ -52,6 +53,16 @@ const MyProfile = () => {
|
||||
const [previousSelectedColor, setPreviousSelectedColor] = useState<string>(
|
||||
profileData?.eventColor ?? colorMap.pink
|
||||
);
|
||||
const [birthday, setBirthday] = useState<Date>(() => {
|
||||
if (profileData?.birthday) {
|
||||
if (profileData.birthday.toDate) {
|
||||
return profileData.birthday.toDate();
|
||||
}
|
||||
const date = new Date(profileData.birthday);
|
||||
return isNaN(date.getTime()) ? new Date() : date;
|
||||
}
|
||||
return new Date();
|
||||
});
|
||||
|
||||
const [showDeleteDialog, setShowDeleteDialog] = useState<boolean>(false);
|
||||
|
||||
@ -98,11 +109,11 @@ const MyProfile = () => {
|
||||
useEffect(() => {
|
||||
if (familyMembers) {
|
||||
const colors = familyMembers
|
||||
.filter(member => member?.eventColor && member.uid !== user?.uid)
|
||||
.map(member => member.eventColor!);
|
||||
.filter((member) => member?.eventColor && member.uid !== user?.uid)
|
||||
.map((member) => member.eventColor!);
|
||||
setTakenColors(colors);
|
||||
}
|
||||
}, [familyMembers]);
|
||||
}, [familyMembers]);
|
||||
|
||||
useEffect(() => {
|
||||
if (profileData) {
|
||||
@ -111,6 +122,16 @@ const MyProfile = () => {
|
||||
setTimeZone(
|
||||
profileData.timeZone || Localization.getCalendars()[0].timeZone!
|
||||
);
|
||||
if (profileData?.birthday) {
|
||||
if (profileData.birthday.toDate) {
|
||||
setBirthday(profileData.birthday.toDate());
|
||||
} else {
|
||||
const date = new Date(profileData.birthday);
|
||||
if (!isNaN(date.getTime())) {
|
||||
setBirthday(date);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [profileData]);
|
||||
|
||||
@ -267,6 +288,27 @@ const MyProfile = () => {
|
||||
setLastName(value);
|
||||
}}
|
||||
/>
|
||||
<Text text80 marginT-10 marginB-7 style={styles.label}>
|
||||
Birthday
|
||||
</Text>
|
||||
<DateTimePicker
|
||||
style={styles.txtBox}
|
||||
mode="date"
|
||||
value={birthday}
|
||||
onChange={(date) => {
|
||||
if (date) {
|
||||
const validDate = new Date(date);
|
||||
if (!isNaN(validDate.getTime())) {
|
||||
setBirthday(validDate);
|
||||
updateUserData({
|
||||
newUserData: {
|
||||
birthday: validDate,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Text text80 marginT-10 marginB-7 style={styles.label}>
|
||||
Email address
|
||||
</Text>
|
||||
@ -284,36 +326,83 @@ const MyProfile = () => {
|
||||
Color Preference
|
||||
</Text>
|
||||
<View row spread>
|
||||
<TouchableOpacity onPress={() => handleChangeColor(colorMap.pink)} disabled={takenColors.includes(colorMap.pink)}>
|
||||
<View style={[styles.colorBox, {opacity: takenColors.includes(colorMap.pink) ? 0.1 : 1}]} backgroundColor={colorMap.pink}>
|
||||
<TouchableOpacity
|
||||
onPress={() => handleChangeColor(colorMap.pink)}
|
||||
disabled={takenColors.includes(colorMap.pink)}
|
||||
>
|
||||
<View
|
||||
style={[
|
||||
styles.colorBox,
|
||||
{ opacity: takenColors.includes(colorMap.pink) ? 0.1 : 1 },
|
||||
]}
|
||||
backgroundColor={colorMap.pink}
|
||||
>
|
||||
{selectedColor == colorMap.pink && (
|
||||
<AntDesign name="check" size={30} color="white" />
|
||||
)}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity onPress={() => handleChangeColor(colorMap.lightPink)} disabled={takenColors.includes(colorMap.lightPink)}>
|
||||
<View style={[styles.colorBox, {opacity: takenColors.includes(colorMap.lightPink) ? 0.1 : 1}]} backgroundColor={colorMap.lightPink}>
|
||||
<TouchableOpacity
|
||||
onPress={() => handleChangeColor(colorMap.lightPink)}
|
||||
disabled={takenColors.includes(colorMap.lightPink)}
|
||||
>
|
||||
<View
|
||||
style={[
|
||||
styles.colorBox,
|
||||
{ opacity: takenColors.includes(colorMap.lightPink) ? 0.1 : 1 },
|
||||
]}
|
||||
backgroundColor={colorMap.lightPink}
|
||||
>
|
||||
{selectedColor == colorMap.lightPink && (
|
||||
<AntDesign name="check" size={30} color="black" />
|
||||
)}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity onPress={() => handleChangeColor(colorMap.orange)} disabled={takenColors.includes(colorMap.orange)}>
|
||||
<View style={[styles.colorBox, {opacity: takenColors.includes(colorMap.orange) ? 0.1 : 1}]} backgroundColor={colorMap.orange}>
|
||||
<TouchableOpacity
|
||||
onPress={() => handleChangeColor(colorMap.orange)}
|
||||
disabled={takenColors.includes(colorMap.orange)}
|
||||
>
|
||||
<View
|
||||
style={[
|
||||
styles.colorBox,
|
||||
{ opacity: takenColors.includes(colorMap.orange) ? 0.1 : 1 },
|
||||
]}
|
||||
backgroundColor={colorMap.orange}
|
||||
>
|
||||
{selectedColor == colorMap.orange && (
|
||||
<AntDesign name="check" size={30} color="white" />
|
||||
)}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity onPress={() => handleChangeColor(colorMap.lightOrange)} disabled={takenColors.includes(colorMap.lightOrange)}>
|
||||
<View style={[styles.colorBox, {opacity: takenColors.includes(colorMap.lightOrange) ? 0.1 : 1}]} backgroundColor={colorMap.lightOrange}>
|
||||
<TouchableOpacity
|
||||
onPress={() => handleChangeColor(colorMap.lightOrange)}
|
||||
disabled={takenColors.includes(colorMap.lightOrange)}
|
||||
>
|
||||
<View
|
||||
style={[
|
||||
styles.colorBox,
|
||||
{
|
||||
opacity: takenColors.includes(colorMap.lightOrange) ? 0.1 : 1,
|
||||
},
|
||||
]}
|
||||
backgroundColor={colorMap.lightOrange}
|
||||
>
|
||||
{selectedColor == colorMap.lightOrange && (
|
||||
<AntDesign name="check" size={30} color="black" />
|
||||
)}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity onPress={() => handleChangeColor(colorMap.green)}disabled={takenColors.includes(colorMap.green)}>
|
||||
<View style={[styles.colorBox, {opacity: takenColors.includes(colorMap.green) ? 0.1 : 1}]} backgroundColor={colorMap.green}>
|
||||
<TouchableOpacity
|
||||
onPress={() => handleChangeColor(colorMap.green)}
|
||||
disabled={takenColors.includes(colorMap.green)}
|
||||
>
|
||||
<View
|
||||
style={[
|
||||
styles.colorBox,
|
||||
{ opacity: takenColors.includes(colorMap.green) ? 0.1 : 1 },
|
||||
]}
|
||||
backgroundColor={colorMap.green}
|
||||
>
|
||||
{selectedColor == colorMap.green && (
|
||||
<AntDesign name="check" size={30} color="white" />
|
||||
)}
|
||||
@ -321,36 +410,85 @@ const MyProfile = () => {
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View row spread marginT-10>
|
||||
<TouchableOpacity onPress={() => handleChangeColor(colorMap.lightGreen)} disabled={takenColors.includes(colorMap.lightGreen)}>
|
||||
<View style={[styles.colorBox, {opacity: takenColors.includes(colorMap.lightGreen) ? 0.1 : 1}]} backgroundColor={colorMap.lightGreen}>
|
||||
<TouchableOpacity
|
||||
onPress={() => handleChangeColor(colorMap.lightGreen)}
|
||||
disabled={takenColors.includes(colorMap.lightGreen)}
|
||||
>
|
||||
<View
|
||||
style={[
|
||||
styles.colorBox,
|
||||
{
|
||||
opacity: takenColors.includes(colorMap.lightGreen) ? 0.1 : 1,
|
||||
},
|
||||
]}
|
||||
backgroundColor={colorMap.lightGreen}
|
||||
>
|
||||
{selectedColor == colorMap.lightGreen && (
|
||||
<AntDesign name="check" size={30} color="black" />
|
||||
)}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity onPress={() => handleChangeColor(colorMap.teal)} disabled={takenColors.includes(colorMap.teal)}>
|
||||
<View style={[styles.colorBox, {opacity: takenColors.includes(colorMap.teal) ? 0.1 : 1}]} backgroundColor={colorMap.teal}>
|
||||
<TouchableOpacity
|
||||
onPress={() => handleChangeColor(colorMap.teal)}
|
||||
disabled={takenColors.includes(colorMap.teal)}
|
||||
>
|
||||
<View
|
||||
style={[
|
||||
styles.colorBox,
|
||||
{ opacity: takenColors.includes(colorMap.teal) ? 0.1 : 1 },
|
||||
]}
|
||||
backgroundColor={colorMap.teal}
|
||||
>
|
||||
{selectedColor == colorMap.teal && (
|
||||
<AntDesign name="check" size={30} color="white" />
|
||||
)}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity onPress={() => handleChangeColor(colorMap.lightTeal)} disabled={takenColors.includes(colorMap.lightTeal)}>
|
||||
<View style={[styles.colorBox, {opacity: takenColors.includes(colorMap.lightTeal) ? 0.1 : 1}]} backgroundColor={colorMap.lightTeal}>
|
||||
<TouchableOpacity
|
||||
onPress={() => handleChangeColor(colorMap.lightTeal)}
|
||||
disabled={takenColors.includes(colorMap.lightTeal)}
|
||||
>
|
||||
<View
|
||||
style={[
|
||||
styles.colorBox,
|
||||
{ opacity: takenColors.includes(colorMap.lightTeal) ? 0.1 : 1 },
|
||||
]}
|
||||
backgroundColor={colorMap.lightTeal}
|
||||
>
|
||||
{selectedColor == colorMap.lightTeal && (
|
||||
<AntDesign name="check" size={30} color="black" />
|
||||
)}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity onPress={() => handleChangeColor(colorMap.purple)} disabled={takenColors.includes(colorMap.purple)}>
|
||||
<View style={[styles.colorBox, {opacity: takenColors.includes(colorMap.purple) ? 0.1 : 1}]} backgroundColor={colorMap.purple}>
|
||||
<TouchableOpacity
|
||||
onPress={() => handleChangeColor(colorMap.purple)}
|
||||
disabled={takenColors.includes(colorMap.purple)}
|
||||
>
|
||||
<View
|
||||
style={[
|
||||
styles.colorBox,
|
||||
{ opacity: takenColors.includes(colorMap.purple) ? 0.1 : 1 },
|
||||
]}
|
||||
backgroundColor={colorMap.purple}
|
||||
>
|
||||
{selectedColor == colorMap.purple && (
|
||||
<AntDesign name="check" size={30} color="white" />
|
||||
)}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity onPress={() => handleChangeColor(colorMap.lightPurple)} disabled={takenColors.includes(colorMap.lightPurple)}>
|
||||
<View style={[styles.colorBox, {opacity: takenColors.includes(colorMap.lightPurple) ? 0.1 : 1}]} backgroundColor={colorMap.lightPurple}>
|
||||
<TouchableOpacity
|
||||
onPress={() => handleChangeColor(colorMap.lightPurple)}
|
||||
disabled={takenColors.includes(colorMap.lightPurple)}
|
||||
>
|
||||
<View
|
||||
style={[
|
||||
styles.colorBox,
|
||||
{
|
||||
opacity: takenColors.includes(colorMap.lightPurple) ? 0.1 : 1,
|
||||
},
|
||||
]}
|
||||
backgroundColor={colorMap.lightPurple}
|
||||
>
|
||||
{selectedColor == colorMap.lightPurple && (
|
||||
<AntDesign name="check" size={30} color="black" />
|
||||
)}
|
||||
|
Reference in New Issue
Block a user