added focus, ui changes

This commit is contained in:
ivic00
2024-10-17 19:57:41 +02:00
parent e4eb67fba7
commit d2b46ad977
14 changed files with 729 additions and 476 deletions

View File

@ -0,0 +1,19 @@
import * as React from "react"
import Svg, { SvgProps, Path } from "react-native-svg"
const ArrowRightIcon = (props: SvgProps) => (
<Svg
width={9}
height={15}
viewBox="0 0 9 15"
fill="none"
{...props}
>
<Path
stroke="#ACACAC"
strokeLinecap="round"
strokeWidth={2}
d="M1.272 1.803 7.16 7.69a.16.16 0 0 1 0 .226l-5.887 5.887"
/>
</Svg>
)
export default ArrowRightIcon

View File

@ -0,0 +1,22 @@
import * as React from "react";
import Svg, { SvgProps, Path } from "react-native-svg";
const CircledXIcon = (props: SvgProps) => (
<Svg
width={props.width || 22}
height={props.height || 21}
viewBox="0 0 22 21"
fill="none"
{...props}
>
<Path
stroke={props.color || "#BBB"}
d="M11 20.5c5.523 0 10-4.477 10-10S16.523.5 11 .5 1 4.977 1 10.5s4.477 10 10 10Z"
/>
<Path
stroke={props.color || "#BBB"}
strokeLinecap="round"
d="m13.75 7.75-5.5 5.5m0-5.5 5.5 5.5"
/>
</Svg>
);
export default CircledXIcon;

17
assets/svgs/EmailIcon.tsx Normal file
View File

@ -0,0 +1,17 @@
import * as React from "react"
import Svg, { SvgProps, Path } from "react-native-svg"
const EmailIcon = (props: SvgProps) => (
<Svg
width={props.width || 20}
height={props.height || 16}
viewBox="0 0 20 16"
fill="none"
{...props}
>
<Path
fill={props.color || "#fff"}
d="M19.948 2.385a2.767 2.767 0 0 0-.76-1.422A2.768 2.768 0 0 0 17.225.15H2.774A2.772 2.772 0 0 0 0 2.925v10.15c0 .389.083.763.23 1.101a2.719 2.719 0 0 0 .774 1.035c.48.398 1.1.638 1.77.638h14.452a2.755 2.755 0 0 0 1.961-.813c.245-.245.447-.537.586-.86v-.002c.147-.338.227-.71.227-1.1V2.925c0-.182-.018-.363-.052-.539ZM1.817 1.967a1.34 1.34 0 0 1 .957-.397h14.452a1.335 1.335 0 0 1 1.079.54l-7.575 6.6a1.11 1.11 0 0 1-1.46 0L1.698 2.107c.034-.048.075-.095.119-.139Zm-.398 11.107V3.575l5.482 4.782-5.479 4.777c-.003-.018-.003-.039-.003-.06Zm15.807 1.355H2.774c-.245 0-.475-.064-.67-.178l5.78-5.037.54.47a2.406 2.406 0 0 0 3.155 0l.54-.47 5.778 5.037a1.338 1.338 0 0 1-.671.178Zm1.355-1.354c0 .02 0 .04-.003.059L13.1 8.36l5.48-4.782v9.497Z"
/>
</Svg>
)
export default EmailIcon

20
assets/svgs/QRIcon.tsx Normal file
View File

@ -0,0 +1,20 @@
import * as React from "react"
import Svg, { SvgProps, Path } from "react-native-svg"
const QRIcon = (props: SvgProps) => (
<Svg
width={props.width || 19}
height={props.height || 20}
viewBox="0 0 19 20"
fill="none"
{...props}
>
<Path
stroke={props.color || "#fff"}
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={1.764}
d="M5.086 10.441h4.41v4.41m-7.93-4.41h-.008m4.418 4.41h-.008m3.536 3.528h-.008m7.946-7.938h-.008m-15.876 4.41H2.88m9.702-4.41h1.764M1.557 18.38h4.41M9.497 1.621v5.292m4.939 11.466h1.587c.494 0 .741 0 .93-.096.166-.085.3-.22.385-.386.097-.188.097-.435.097-.93V15.38c0-.494 0-.74-.097-.93a.882.882 0 0 0-.385-.385c-.189-.096-.436-.096-.93-.096h-1.587c-.494 0-.741 0-.93.096a.881.881 0 0 0-.385.386c-.096.188-.096.435-.096.93v1.587c0 .494 0 .74.096.93.084.166.22.3.385.385.189.096.436.096.93.096Zm0-11.466h1.587c.494 0 .741 0 .93-.096.166-.085.3-.22.385-.385.097-.19.097-.436.097-.93V3.914c0-.494 0-.74-.097-.93a.882.882 0 0 0-.385-.385c-.189-.096-.436-.096-.93-.096h-1.587c-.494 0-.741 0-.93.096a.881.881 0 0 0-.385.386c-.096.188-.096.435-.096.93v1.587c0 .494 0 .74.096.93.084.165.22.3.385.385.189.096.436.096.93.096Zm-11.466 0h1.587c.494 0 .741 0 .93-.096.166-.085.3-.22.385-.385.097-.19.097-.436.097-.93V3.914c0-.494 0-.74-.097-.93a.882.882 0 0 0-.385-.385c-.189-.096-.436-.096-.93-.096H2.97c-.494 0-.741 0-.93.096a.882.882 0 0 0-.385.386c-.096.188-.096.435-.096.93v1.587c0 .494 0 .74.096.93.084.165.22.3.385.385.189.096.436.096.93.096Z"
/>
</Svg>
)
export default QRIcon

View File

@ -1,17 +1,24 @@
import { View, Text, Button, TextField } from "react-native-ui-lib";
import React, { useEffect, useState } from "react";
import {
View,
Text,
Button,
TextField,
TextFieldRef,
TouchableOpacity,
} from "react-native-ui-lib";
import React, { useEffect, useState, useRef } from "react";
import { Dialog } from "react-native-ui-lib";
import { PanningDirectionsEnum } from "react-native-ui-lib/src/incubator/panView";
import CloseXIcon from "@/assets/svgs/CloseXIcon";
import { Dimensions, StyleSheet } from "react-native";
import { Dimensions, Keyboard, StyleSheet } from "react-native";
import DropModalIcon from "@/assets/svgs/DropModalIcon";
import MenuIcon from "@/assets/svgs/MenuIcon";
import { useBrainDumpContext } from "@/contexts/DumpContext";
interface IAddBrainDumpProps {
isVisible: boolean;
setIsVisible: (value: boolean) => void;
}
const AddBrainDump = ({
addBrainDumpProps,
}: {
@ -20,7 +27,10 @@ const AddBrainDump = ({
const { addBrainDump } = useBrainDumpContext();
const [dumpTitle, setDumpTitle] = useState<string>("");
const [dumpDesc, setDumpDesc] = useState<string>("");
const { width, height } = Dimensions.get("screen");
const { width } = Dimensions.get("screen");
// Refs for the two TextFields
const descriptionRef = useRef<TextFieldRef>(null);
useEffect(() => {
setDumpDesc("");
@ -34,14 +44,7 @@ const AddBrainDump = ({
width={width}
panDirection={PanningDirectionsEnum.DOWN}
onDismiss={() => addBrainDumpProps.setIsVisible(false)}
containerStyle={{
borderTopRightRadius: 15,
borderTopLeftRadius: 15,
backgroundColor: "white",
padding: 0,
paddingTop: 3,
margin: 0,
}}
containerStyle={styles.dialogContainer}
visible={addBrainDumpProps.isVisible}
>
<View row spread style={styles.topBtns} marginB-20>
@ -53,16 +56,15 @@ const AddBrainDump = ({
addBrainDumpProps.setIsVisible(false);
}}
/>
<DropModalIcon
style={{ marginTop: 15 }}
onPress={() => addBrainDumpProps.setIsVisible(false)}
/>
<TouchableOpacity onPress={() => addBrainDumpProps.setIsVisible(false)}>
<DropModalIcon style={{ marginTop: 15 }} />
</TouchableOpacity>
<Button
color="#05a8b6"
label="Save"
style={styles.topBtn}
onPress={() => {
addBrainDump({ id: 99, title: dumpTitle, description: dumpDesc });
addBrainDump({ id: 99, title: dumpTitle.trimEnd().trimStart(), description: dumpDesc.trimEnd().trimStart() });
addBrainDumpProps.setIsVisible(false);
}}
/>
@ -70,20 +72,37 @@ const AddBrainDump = ({
<View marginH-20>
<TextField
value={dumpTitle}
autoFocus
placeholder="Set Title"
text60R
onChangeText={(text) => {
setDumpTitle(text);
}}
onSubmitEditing={() => {
// Move focus to the description field
descriptionRef.current?.focus();
}}
style={styles.title}
blurOnSubmit={false} // Keep the keyboard open when moving focus
returnKeyType="next"
/>
<View height={2} backgroundColor="#b3b3b3" width={"100%"} marginB-20 />
<TextField
ref={descriptionRef}
value={dumpDesc}
placeholder="Write Description"
text70
onChangeText={(text) => {
setDumpDesc(text);
}}
style={styles.description}
multiline
numberOfLines={4}
maxLength={255}
onEndEditing={() => {
descriptionRef.current?.blur();
}}
returnKeyType="done"
/>
</View>
</Dialog>
@ -91,11 +110,28 @@ const AddBrainDump = ({
};
const styles = StyleSheet.create({
dialogContainer: {
borderTopRightRadius: 15,
borderTopLeftRadius: 15,
backgroundColor: "white",
padding: 0,
paddingTop: 3,
margin: 0,
},
topBtns: {},
topBtn: {
backgroundColor: "white",
color: "#05a8b6",
},
title: {
fontSize: 22,
fontFamily: "Manrope_500Medium",
},
description: {
fontFamily: "Manrope_400Regular",
fontSize: 14,
textAlignVertical: 'top'
},
});
export default AddBrainDump;

View File

@ -98,19 +98,18 @@ const MoveBrainDump = (props: {
<TextField
textAlignVertical="top"
multiline
autoFocus
fieldStyle={{
width: "94%",
}}
style={{
fontFamily: "Manrope_400Regular",
fontSize: 14,
}}
style={styles.description}
placeholder="Add description"
numberOfLines={3}
value={description}
onChangeText={(value) => {
setDescription(value);
}}
returnKeyType="default"
/>
</View>
<View style={styles.divider} />
@ -192,6 +191,10 @@ const styles = StyleSheet.create({
fontSize: 22,
fontFamily: "Manrope_500Medium",
},
description:{
fontFamily: "Manrope_400Regular",
fontSize: 14,
}
});
export default MoveBrainDump;

View File

@ -225,6 +225,7 @@ export const ManuallyAddEventModal = ({
<TextField
placeholder="Add event title"
value={title}
autoFocus
onChangeText={(text) => {
setTitle(text);
}}
@ -232,6 +233,7 @@ export const ManuallyAddEventModal = ({
style={{ fontFamily: "Manrope_500Medium", fontSize: 22 }}
paddingT-15
paddingL-30
returnKeyType="next"
/>
<View style={styles.divider} marginT-8 />
<View marginL-30 centerV>

View File

@ -23,7 +23,7 @@ const CategoryDropdown = (props: {
padding: 10,
}}
>
<Text>{category}</Text>
<Text style={{fontFamily: "Manrope_400Regular"}}>{category}</Text>
</View>
</TouchableOpacity>
))}

View File

@ -1,7 +1,8 @@
import {Text, View} from "react-native";
import React, {useEffect, useRef} from "react";
import React, {useEffect, useRef, useState} from "react";
import {TextField, TextFieldRef} from "react-native-ui-lib";
import {GroceryCategory, useGroceryContext,} from "@/contexts/GroceryContext";
import CategoryDropdown from "./CategoryDropdown";
interface IEditGrocery {
id?: string;
@ -17,6 +18,7 @@ interface IEditGrocery {
const EditGroceryItem = ({editGrocery}: { editGrocery: IEditGrocery }) => {
const {fuzzyMatchGroceryCategory} = useGroceryContext();
const inputRef = useRef<TextFieldRef>(null);
const [category, setCategory] = useState<GroceryCategory>(GroceryCategory.None);
useEffect(() => {
if (editGrocery.setCategory)

View File

@ -1,10 +1,11 @@
import React, { useState } from "react";
import React, { useRef, useState } from "react";
import {
Button,
ButtonSize,
Checkbox,
Text,
TextField,
TextFieldRef,
TouchableOpacity,
View,
} from "react-native-ui-lib";
@ -13,7 +14,13 @@ import { ProfileType } from "@/contexts/AuthContext";
import { StyleSheet } from "react-native";
import { AntDesign } from "@expo/vector-icons";
const SignUpPage = ({setTab}: { setTab: React.Dispatch<React.SetStateAction<"register" | "login" | "reset-password">> }) => {
const SignUpPage = ({
setTab,
}: {
setTab: React.Dispatch<
React.SetStateAction<"register" | "login" | "reset-password">
>;
}) => {
const [email, setEmail] = useState<string>("");
const [firstName, setFirstName] = useState<string>("");
const [lastName, setLastName] = useState<string>("");
@ -24,6 +31,10 @@ const SignUpPage = ({setTab}: { setTab: React.Dispatch<React.SetStateAction<"re
const [acceptTerms, setAcceptTerms] = useState<boolean>(false);
const { mutateAsync: signUp } = useSignUp();
const lnameRef = useRef<TextFieldRef>(null);
const emailRef = useRef<TextFieldRef>(null);
const passwordRef = useRef<TextFieldRef>(null);
const handleSignUp = async () => {
await signUp({ email, password, firstName, lastName });
};
@ -36,24 +47,34 @@ const SignUpPage = ({setTab}: { setTab: React.Dispatch<React.SetStateAction<"re
<Text center>Please enter your details.</Text>
<TextField
marginT-60
autoFocus
placeholder="First name"
value={firstName}
onChangeText={setFirstName}
style={styles.textfield}
onSubmitEditing={() => {lnameRef.current?.focus()}}
blurOnSubmit={false}
/>
<TextField
ref={lnameRef}
placeholder="Last name"
value={lastName}
onChangeText={setLastName}
style={styles.textfield}
onSubmitEditing={() => {emailRef.current?.focus()}}
blurOnSubmit={false}
/>
<TextField
ref={emailRef}
placeholder="Email"
value={email}
onChangeText={setEmail}
style={styles.textfield}
onSubmitEditing={() => {passwordRef.current?.focus()}}
blurOnSubmit={false}
/>
<TextField
ref={passwordRef}
placeholder="Password"
value={password}
onChangeText={setPassword}

View File

@ -9,6 +9,7 @@ import { AuthContextProvider } from "@/contexts/AuthContext";
import ProfileIcon from "@/assets/svgs/ProfileIcon";
import CalendarIcon from "@/assets/svgs/CalendarIcon";
import PrivacyPolicyIcon from "@/assets/svgs/PrivacyPolicyIcon";
import ArrowRightIcon from "@/assets/svgs/ArrowRightIcon";
const pageIndex = {
main: 0,
@ -20,71 +21,83 @@ const pageIndex = {
const SettingsPage = () => {
const [selectedPage, setSelectedPage] = useState<number>(0);
return (
<View flexG>
{selectedPage == 0 && (
<View flexG centerH marginH-30 marginT-30>
<Button
backgroundColor="white"
style={styles.mainBtn}
label="Manage My Profile"
labelStyle={styles.label}
color="#07b8c7"
iconSource={() => (
<ProfileIcon style={{marginRight: 10}} color="#07b9c8" />
)}
onPress={() => setSelectedPage(pageIndex.user)}
/>
<Button
backgroundColor="white"
style={styles.mainBtn}
label="Calendar Settings"
labelStyle={styles.label}
color="#fd1775"
iconSource={() => (
<CalendarIcon style={{marginRight: 10}}/>
)}
onPress={() => {
setSelectedPage(pageIndex.calendar);
}}
/>
<Button
backgroundColor="white"
style={styles.mainBtn}
label="To-Do Reward Settings"
labelStyle={styles.label}
color="#ff9900"
iconSource={() => (
<View flexG>
{selectedPage == 0 && (
<View flexG centerH marginH-30 marginT-30>
<Button
backgroundColor="white"
style={styles.mainBtn}
children={
<View row centerV width={"100%"}>
<ProfileIcon style={{ marginRight: 10 }} color="#07b9c8" />
<Text style={styles.label} color="#07b8c7">
Manage My Profile
</Text>
<ArrowRightIcon style={{ marginLeft: "auto" }} />
</View>
}
onPress={() => setSelectedPage(pageIndex.user)}
/>
<Button
backgroundColor="white"
style={styles.mainBtn}
children={
<View row centerV width={"100%"}>
<CalendarIcon style={{ marginRight: 10 }} />
<Text style={styles.label} color="#fd1775">
Calendar Settings
</Text>
<ArrowRightIcon style={{ marginLeft: "auto" }} />
</View>
}
onPress={() => {
setSelectedPage(pageIndex.calendar);
}}
/>
<Button
backgroundColor="white"
style={styles.mainBtn}
children={
<View row centerV width={"100%"}>
<Octicons
name="gear"
size={24}
color="#ff9900"
style={{ marginRight: 10 }}
/>
)}
onPress={() => setSelectedPage(pageIndex.chore)}
/>
<Button
backgroundColor="white"
style={styles.mainBtn}
label="Cally Privacy Policy"
labelStyle={styles.label}
iconSource={() => (
<PrivacyPolicyIcon 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>
<Text style={styles.label} color="#ff9900">
To-Do Reward Settings
</Text>
<ArrowRightIcon style={{ marginLeft: "auto" }} />
</View>
}
onPress={() => setSelectedPage(pageIndex.chore)}
/>
<Button
backgroundColor="white"
style={styles.mainBtn}
children={
<View row centerV width={"100%"}>
<PrivacyPolicyIcon style={{ marginRight: 10 }} />
<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} />
)}
</View>
);
};
@ -92,14 +105,14 @@ export default SettingsPage;
const styles = StyleSheet.create({
mainBtn: {
width: "100%",
width: 311,
justifyContent: "flex-start",
marginBottom: 20,
height: 60,
height: 57.61,
},
label:{
label: {
fontFamily: "Poppins_400Regular",
fontSize: 14.71,
textAlignVertical: 'center'
}
textAlignVertical: "center",
},
});

View File

@ -1,392 +1,505 @@
import {
Avatar,
Button,
Card,
Colors,
Dialog,
FloatingButton,
PanningProvider,
Picker,
Text,
TextField,
TouchableOpacity,
View,
Avatar,
Button,
Card,
Colors,
Dialog,
FloatingButton,
PanningProvider,
Picker,
Text,
TextField,
TextFieldRef,
TouchableOpacity,
View,
} from "react-native-ui-lib";
import React, {useState} from "react";
import {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 {useGetFamilyMembers} from "@/hooks/firebase/useGetFamilyMembers";
import React, { useEffect, useRef, useState } from "react";
import { Dimensions, 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 { useGetFamilyMembers } from "@/hooks/firebase/useGetFamilyMembers";
import UserMenu from "@/components/pages/settings/user_settings_views/UserMenu";
import {uuidv4} from "@firebase/util";
import { uuidv4 } from "@firebase/util";
import QRIcon from "@/assets/svgs/QRIcon";
import EmailIcon from "@/assets/svgs/EmailIcon";
import CircledXIcon from "@/assets/svgs/CircledXIcon";
import ProfileIcon from "@/assets/svgs/ProfileIcon";
import NavToDosIcon from "@/assets/svgs/NavToDosIcon";
const MyGroup = () => {
const [showAddUserDialog, setShowAddUserDialog] = useState(false);
const [showNewUserInfoDialog, setShowNewUserInfoDialog] = useState(false);
const [selectedStatus, setSelectedStatus] = useState<
string | PickerSingleValue
>(ProfileType.CHILD);
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const [email, setEmail] = useState("");
const [showAddUserDialog, setShowAddUserDialog] = useState(false);
const [showNewUserInfoDialog, setShowNewUserInfoDialog] = useState(false);
const [selectedStatus, setSelectedStatus] = useState<
string | PickerSingleValue
>(ProfileType.CHILD);
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const [email, setEmail] = useState("");
const [showQRCodeDialog, setShowQRCodeDialog] = useState("");
const lNameRef = useRef<TextFieldRef>(null);
const emailRef = useRef<TextFieldRef>(null);
const {mutateAsync: createSubUser, isLoading, isError} = useCreateSubUser();
const {data: familyMembers} = useGetFamilyMembers(true);
const [showQRCodeDialog, setShowQRCodeDialog] = useState("");
const parents =
familyMembers?.filter((x) => x.userType === ProfileType.PARENT) ?? [];
const children =
familyMembers?.filter((x) => x.userType === ProfileType.CHILD) ?? [];
const caregivers =
familyMembers?.filter((x) => x.userType === ProfileType.CAREGIVER) ?? [];
const familyDevices =
familyMembers?.filter((x) => x.userType === ProfileType.FAMILY_DEVICE) ?? [];
const { mutateAsync: createSubUser, isLoading, isError } = useCreateSubUser();
const { data: familyMembers } = useGetFamilyMembers(true);
const handleCreateSubUser = async () => {
if (!firstName || (selectedStatus !== ProfileType.FAMILY_DEVICE && !lastName)) {
console.error("First name and last name are required");
return;
}
const parents =
familyMembers?.filter((x) => x.userType === ProfileType.PARENT) ?? [];
const children =
familyMembers?.filter((x) => x.userType === ProfileType.CHILD) ?? [];
const caregivers =
familyMembers?.filter((x) => x.userType === ProfileType.CAREGIVER) ?? [];
const familyDevices =
familyMembers?.filter((x) => x.userType === ProfileType.FAMILY_DEVICE) ??
[];
if (selectedStatus !== ProfileType.FAMILY_DEVICE && !email) {
console.error("Email is required for non-family device users");
return;
}
const handleCreateSubUser = async () => {
if (
!firstName ||
(selectedStatus !== ProfileType.FAMILY_DEVICE && !lastName)
) {
console.error("First name and last name are required");
return;
}
if (email && !email.includes("@")) {
console.error("Invalid email address");
return;
}
if (selectedStatus !== ProfileType.FAMILY_DEVICE && !email) {
console.error("Email is required for non-family device users");
return;
}
const res = await createSubUser({
firstName,
lastName: selectedStatus === ProfileType.FAMILY_DEVICE ? "" : lastName,
email: email || `placeholder_${uuidv4().split("-")[0]}@family.device`,
password: uuidv4(),
userType: selectedStatus as ProfileType,
});
console.log(res)
if (email && !email.includes("@")) {
console.error("Invalid email address");
return;
}
if (!isError) {
setShowNewUserInfoDialog(false);
const res = await createSubUser({
firstName,
lastName: selectedStatus === ProfileType.FAMILY_DEVICE ? "" : lastName,
email: email || `placeholder_${uuidv4().split("-")[0]}@family.device`,
password: uuidv4(),
userType: selectedStatus as ProfileType,
});
console.log(res);
if(res?.data?.userId) {
setTimeout(() => {
setShowQRCodeDialog(res.data.userId)
}, 500)
}
}
if (!isError) {
setShowNewUserInfoDialog(false);
if (res?.data?.userId) {
setTimeout(() => {
setShowQRCodeDialog(res.data.userId);
}, 500);
}
}
};
};
useEffect(() => {
setFirstName("");
setLastName("");
setEmail("");
}, [])
return (
<View style={{flex: 1}}>
<View>
<ScrollView style={styles.card}>
{!parents.length && !children.length && !caregivers.length && (
<Text text70 marginV-10>
{isLoading ? "Loading...." : "No user devices added"}
</Text>
)}
return (
<View style={{ flex: 1, minHeight: 500 }}>
<View>
<ScrollView style={styles.card}>
{!parents.length && !children.length && !caregivers.length && (
<Text text70 marginV-10>
{isLoading ? "Loading...." : "No user devices added"}
</Text>
)}
{(!!parents.length || !!children.length) && (
<>
<Text style={styles.subTit} marginV-10>
Family
</Text>
{[...parents, ...children]?.map((member, index) => (
<Card
enableShadow={false}
elevation={0}
key={`${member.firstName}_${member.lastName}_${index}`}
style={styles.familyCard}
row
centerV
padding-10
>
<Avatar
source={{uri: "https://via.placeholder.com/60"}}
size={40}
backgroundColor={Colors.grey60}
/>
<View marginL-10>
<Text text70M>
{member.firstName} {member.lastName}
</Text>
<Text text90 grey40>
{member.userType === ProfileType.PARENT
? "Admin (You)"
: "Child"}
</Text>
</View>
<View flex-1/>
<UserMenu setShowQRCodeDialog={(val) => setShowQRCodeDialog("")} showQRCodeDialog={showQRCodeDialog === member?.uid} userId={member?.uid!}/>
</Card>
))}
</>
)}
{!!caregivers.length && (
<>
<Text text70 marginB-10 marginT-15>
Caregivers
</Text>
{caregivers?.map((member) => (
<Card
enableShadow={false}
elevation={0}
key={`${member.firstName}_${member.lastName}`}
style={styles.familyCard}
row
centerV
padding-10
>
<Avatar
source={{uri: "https://via.placeholder.com/60"}}
size={40}
backgroundColor={Colors.grey60}
/>
<View marginL-10>
<Text text70M>
{member.firstName} {member.lastName}
</Text>
<Text text90 grey40>
Caregiver
</Text>
</View>
<UserMenu setShowQRCodeDialog={(val) => setShowQRCodeDialog("")} showQRCodeDialog={showQRCodeDialog === member?.uid} userId={member?.uid!}/>
</Card>
))}
</>
)}
{!!familyDevices.length && (
<>
<Text text70 marginB-10 marginT-15>
Family Devices
</Text>
{familyDevices?.map((member, index) => (
<Card
enableShadow={false}
elevation={0}
key={`${member.firstName}_${member.lastName}_${index}`}
style={styles.familyCard}
row
centerV
padding-10
>
<Avatar
source={{uri: "https://via.placeholder.com/60"}}
size={40}
backgroundColor={Colors.grey60}
/>
<View marginL-10>
<Text text70M>
{member.firstName}
</Text>
<Text text90 grey40>
Family Device
</Text>
</View>
<UserMenu setShowQRCodeDialog={(val) => setShowQRCodeDialog("")} showQRCodeDialog={showQRCodeDialog === member?.uid} userId={member?.uid!}/>
</Card>
))}
</>
)}
</ScrollView>
</View>
<FloatingButton
fullWidth
hideBackgroundOverlay
visible
button={{
label: "+ Add a user device",
onPress: () => setShowAddUserDialog(true),
}}
/>
<Dialog
visible={showAddUserDialog}
onDismiss={() => setShowAddUserDialog(false)}
panDirection={PanningProvider.Directions.DOWN}
>
<Card padding-25 gap-10>
<Text>Add a new user device</Text>
<Button backgroundColor={"#FD1775"}>
<Text white>Show a QR Code</Text>
</Button>
<Button
backgroundColor={"#05A8B6"}
onPress={() => {
setShowAddUserDialog(false);
setTimeout(() => {
setShowNewUserInfoDialog(true);
}, 500);
}}
>
<Text white>Enter email address</Text>
</Button>
<TouchableOpacity onPress={() => setShowAddUserDialog(false)} center>
<Text>Return to user settings</Text>
</TouchableOpacity>
</Card>
</Dialog>
<Dialog
panDirection={PanningProvider.Directions.DOWN}
visible={showNewUserInfoDialog}
onDismiss={() => setShowNewUserInfoDialog(false)}
>
<Card padding-25 style={styles.dialogCard}>
<View row spread>
<Text text60M>New User Information</Text>
<TouchableOpacity onPress={() => setShowAddUserDialog(false)}>
<Text>X</Text>
</TouchableOpacity>
</View>
<View row centerV gap-20 marginV-20>
<Avatar
imageStyle={{borderRadius: 10}}
containerStyle={{borderRadius: 10}}
size={60}
backgroundColor={Colors.grey60}
/>
<TouchableOpacity onPress={() => {
}}>
<Text style={{color: Colors.green10}}>
Upload User Profile Photo
</Text>
</TouchableOpacity>
</View>
<Text style={styles.label}>Member Status</Text>
<Picker
editable={!isLoading}
value={selectedStatus}
//@ts-ignore
onChange={(item) => setSelectedStatus(item)}
style={styles.picker}
showSearch
floatingPlaceholder
>
<Picker.Item label="Child" value={ProfileType.CHILD}/>
<Picker.Item label="Parent" value={ProfileType.PARENT}/>
<Picker.Item label="Caregiver" value={ProfileType.CAREGIVER}/>
<Picker.Item label="Family Device" value={ProfileType.FAMILY_DEVICE}/>
</Picker>
<Text style={styles.label}>
{selectedStatus === ProfileType.FAMILY_DEVICE ? "Device Name" : "First Name"}
{(!!parents.length || !!children.length) && (
<>
<Text style={styles.subTit} marginV-10>
Family
</Text>
{[...parents, ...children]?.map((member, index) => (
<Card
enableShadow={false}
elevation={0}
key={`${member.firstName}_${member.lastName}_${index}`}
style={styles.familyCard}
row
centerV
padding-10
>
<Avatar
source={{ uri: "https://via.placeholder.com/60" }}
size={40}
backgroundColor={Colors.grey60}
/>
<View marginL-10>
<Text text70M>
{member.firstName} {member.lastName}
</Text>
<TextField
editable={!isLoading}
placeholder={selectedStatus === ProfileType.FAMILY_DEVICE ? "Device name" : "First name"}
value={firstName}
onChangeText={setFirstName}
style={styles.inputField}
/>
<Text text90 grey40>
{member.userType === ProfileType.PARENT
? "Admin (You)"
: "Child"}
</Text>
</View>
{selectedStatus !== ProfileType.FAMILY_DEVICE && (
<>
<Text style={styles.label}>Last Name</Text>
<TextField
editable={!isLoading}
placeholder="Last name"
value={lastName}
onChangeText={setLastName}
style={styles.inputField}
/>
</>
)}
<View flex-1 />
{selectedStatus !== ProfileType.FAMILY_DEVICE && (
<>
<Text style={styles.label}>Email Address (Optional)</Text>
<TextField
editable={!isLoading}
placeholder="Email address"
value={email}
onChangeText={setEmail}
keyboardType="email-address"
autoCapitalize="none"
style={styles.inputField}
/>
</>
)}
<Button
disabled={!firstName || (selectedStatus !== ProfileType.FAMILY_DEVICE && !lastName) || isLoading}
label={isLoading ? "Adding..." : "Add group member"}
backgroundColor="#FD1775"
style={{marginTop: 20}}
onPress={handleCreateSubUser}
/>
<UserMenu
setShowQRCodeDialog={(val) => setShowQRCodeDialog("")}
showQRCodeDialog={showQRCodeDialog === member?.uid}
userId={member?.uid!}
/>
</Card>
</Dialog>
</View>
);
))}
</>
)}
{!!caregivers.length && (
<>
<Text text70 marginB-10 marginT-15>
Caregivers
</Text>
{caregivers?.map((member) => (
<Card
enableShadow={false}
elevation={0}
key={`${member.firstName}_${member.lastName}`}
style={styles.familyCard}
row
centerV
padding-10
>
<Avatar
source={{ uri: "https://via.placeholder.com/60" }}
size={40}
backgroundColor={Colors.grey60}
/>
<View marginL-10>
<Text text70M>
{member.firstName} {member.lastName}
</Text>
<Text text90 grey40>
Caregiver
</Text>
</View>
<UserMenu
setShowQRCodeDialog={(val) => setShowQRCodeDialog("")}
showQRCodeDialog={showQRCodeDialog === member?.uid}
userId={member?.uid!}
/>
</Card>
))}
</>
)}
{!!familyDevices.length && (
<>
<Text text70 marginB-10 marginT-15>
Family Devices
</Text>
{familyDevices?.map((member, index) => (
<Card
enableShadow={false}
elevation={0}
key={`${member.firstName}_${member.lastName}_${index}`}
style={styles.familyCard}
row
centerV
padding-10
>
<Avatar
source={{ uri: "https://via.placeholder.com/60" }}
size={40}
backgroundColor={Colors.grey60}
/>
<View marginL-10>
<Text text70M>{member.firstName}</Text>
<Text text90 grey40>
Family Device
</Text>
</View>
<UserMenu
setShowQRCodeDialog={(val) => setShowQRCodeDialog("")}
showQRCodeDialog={showQRCodeDialog === member?.uid}
userId={member?.uid!}
/>
</Card>
))}
</>
)}
</ScrollView>
</View>
<FloatingButton
fullWidth
hideBackgroundOverlay
visible
button={{
label: "+ Add a user device",
onPress: () => setShowAddUserDialog(true),
style: styles.bottomButton,
}}
/>
<Dialog
visible={showAddUserDialog}
onDismiss={() => setShowAddUserDialog(false)}
panDirection={PanningProvider.Directions.DOWN}
>
<Card
paddingH-25
paddingT-40
paddingB-20
gap-10
centerH
borderRadius={20}
>
<Text style={styles.dialogTitle} marginB-35>
Add a new user device
</Text>
<Button backgroundColor={"#FD1775"} style={styles.dialogBtn}>
<QRIcon />
<Text style={styles.dialogBtnLbl} marginL-7>
Show a QR Code
</Text>
</Button>
<Button
style={styles.dialogBtn}
backgroundColor={"#05A8B6"}
onPress={() => {
setShowAddUserDialog(false);
setTimeout(() => {
setShowNewUserInfoDialog(true);
}, 500);
}}
>
<EmailIcon />
<Text style={styles.dialogBtnLbl} marginL-7>
Enter email address
</Text>
</Button>
<TouchableOpacity
onPress={() => setShowAddUserDialog(false)}
center
marginT-30
>
<Text style={styles.dialogBackBtn}>Return to user settings</Text>
</TouchableOpacity>
</Card>
</Dialog>
<Dialog
panDirection={PanningProvider.Directions.DOWN}
visible={showNewUserInfoDialog}
onDismiss={() => setShowNewUserInfoDialog(false)}
>
<Card padding-25 style={styles.dialogCard}>
<View row spread>
<Text style={{ fontFamily: "Manrope_500Medium", fontSize: 16 }}>
New User Information
</Text>
<TouchableOpacity onPress={() => {setShowNewUserInfoDialog(false)}}>
<CircledXIcon />
</TouchableOpacity>
</View>
<View style={styles.divider} spread />
<View row centerV gap-20 marginV-20>
<View
height={65.54}
width={65.54}
children={
<ProfileIcon color={"#d6d6d6"} width={37} height={37} />
}
backgroundColor={Colors.grey60}
style={{ borderRadius: 25 }}
center
/>
<TouchableOpacity onPress={() => {}}>
<Text color="#50be0c" style={styles.jakarta13} marginL-15>
Upload User Profile Photo
</Text>
</TouchableOpacity>
</View>
<Text style={styles.jakarta12}>Member Status</Text>
<Picker
editable={!isLoading}
value={selectedStatus}
//@ts-ignore
onChange={(item) => setSelectedStatus(item)}
style={styles.picker}
showSearch
floatingPlaceholder
>
<Picker.Item label="Child" value={ProfileType.CHILD} />
<Picker.Item label="Parent" value={ProfileType.PARENT} />
<Picker.Item label="Caregiver" value={ProfileType.CAREGIVER} />
<Picker.Item
label="Family Device"
value={ProfileType.FAMILY_DEVICE}
/>
</Picker>
<Text style={styles.jakarta12}>
{selectedStatus === ProfileType.FAMILY_DEVICE
? "Device Name"
: "First Name"}
</Text>
<TextField
editable={!isLoading}
placeholder={
selectedStatus === ProfileType.FAMILY_DEVICE
? "Device name"
: "First name"
}
value={firstName}
onChangeText={setFirstName}
style={styles.inputField}
onSubmitEditing={() => {lNameRef.current?.focus()}}
blurOnSubmit={false}
/>
{selectedStatus !== ProfileType.FAMILY_DEVICE && (
<>
<Text style={styles.jakarta12}>Last Name</Text>
<TextField
ref={lNameRef}
editable={!isLoading}
placeholder="Last name"
value={lastName}
onChangeText={setLastName}
style={styles.inputField}
onSubmitEditing={() => {emailRef.current?.focus()}}
blurOnSubmit={false}
/>
</>
)}
{selectedStatus !== ProfileType.FAMILY_DEVICE && (
<>
<Text style={styles.jakarta12}>Email Address (Optional)</Text>
<TextField
ref={emailRef}
editable={!isLoading}
placeholder="Email address"
value={email}
onChangeText={setEmail}
keyboardType="email-address"
autoCapitalize="none"
style={styles.inputField}
/>
</>
)}
<Button
disabled={
!firstName ||
(selectedStatus !== ProfileType.FAMILY_DEVICE && !lastName) ||
isLoading
}
label={isLoading ? "Adding..." : "Add group member"}
backgroundColor="#fd1775"
labelStyle={{
fontFamily: "PlusJakartaSans_500Medium",
fontSize: 15,
marginLeft: 7,
}}
style={{ marginTop: 20, backgroundColor: "#fd1775" }}
iconSource={() => <NavToDosIcon width={22} color={"white"} />}
onPress={handleCreateSubUser}
/>
</Card>
</Dialog>
</View>
);
};
const styles = StyleSheet.create({
card: {
marginVertical: 15,
backgroundColor: "white",
width: "100%",
borderRadius: 15,
padding: 20,
},
familyCard: {
marginBottom: 10,
borderRadius: 10,
backgroundColor: Colors.white,
width: "100%",
},
inputField: {
borderRadius: 50,
paddingVertical: 12,
paddingHorizontal: 16,
backgroundColor: Colors.grey80,
marginBottom: 16,
borderColor: Colors.grey50,
borderWidth: 1,
height: 40,
},
picker: {
borderRadius: 50,
paddingVertical: 12,
paddingHorizontal: 16,
backgroundColor: Colors.grey80,
marginBottom: 16,
borderColor: Colors.grey50,
borderWidth: 1,
marginTop: -20,
height: 40,
},
label: {
marginBottom: 5,
fontSize: 12,
color: Colors.grey40,
},
dialogCard: {
borderRadius: 10,
gap: 10,
},
subTit: {
fontFamily: "Manrope_500Medium",
fontSize: 15,
},
dialogBtn: {
height: 47,
width: 279,
},
dialogTitle: { fontFamily: "Manrope_600SemiBold", fontSize: 22 },
dialogBackBtn: {
fontFamily: "PlusJakartaSans_500Medium",
fontSize: 15,
color: "#a7a7a7",
},
card: {
marginVertical: 15,
backgroundColor: "white",
width: "100%",
borderRadius: 15,
padding: 20,
},
bottomButton: {
position: "absolute",
bottom: 80,
width: "100%",
},
familyCard: {
marginBottom: 10,
borderRadius: 10,
backgroundColor: Colors.white,
width: "100%",
},
inputField: {
fontFamily: "PlusJakartaSans_500Medium",
fontSize: 13,
color: "#565656",
borderRadius: 50,
paddingVertical: 12,
paddingHorizontal: 16,
backgroundColor: Colors.grey80,
marginBottom: 16,
borderColor: Colors.grey50,
borderWidth: 1,
height: 40,
},
picker: {
borderRadius: 50,
paddingVertical: 12,
paddingHorizontal: 16,
backgroundColor: Colors.grey80,
marginBottom: 16,
borderColor: Colors.grey50,
borderWidth: 1,
marginTop: -20,
height: 40,
},
label: {
marginBottom: 5,
fontSize: 12,
color: Colors.grey40,
},
dialogCard: {
borderRadius: 10,
gap: 10,
},
subTit: {
fontFamily: "Manrope_500Medium",
fontSize: 15,
},
dialogBtnLbl: {
fontFamily: "PlusJakartaSans_500Medium",
fontSize: 15,
color: "white",
},
divider: { height: 0.7, backgroundColor: "#e6e6e6", width: "100%" },
jakarta12: {
fontFamily: "PlusJakartaSans_500Medium",
fontSize: 12,
color: "#a1a1a1",
},
jakarta13: {
fontFamily: "PlusJakartaSans_500Medium",
fontSize: 13,
},
});
export default MyGroup;

View File

@ -30,7 +30,7 @@ const UserMenu = ({
customContent={
<View height={18}>
<ListItem onPress={handleShowQRCode}>
<Text>Show Login QR Code</Text>
<Text style={{fontFamily: "Manrope_500Medium"}}>Show Login QR Code</Text>
</ListItem>
</View>
}

View File

@ -1,5 +1,5 @@
import { View, Text, Button, Switch } from "react-native-ui-lib";
import React, { useState } from "react";
import React, { useRef, useState } from "react";
import PointsSlider from "@/components/shared/PointsSlider";
import { repeatOptions, useToDosContext } from "@/contexts/ToDosContext";
import { Feather, AntDesign, Ionicons } from "@expo/vector-icons";
@ -14,6 +14,7 @@ import { PanningDirectionsEnum } from "react-native-ui-lib/src/incubator/panView
import { Dimensions, StyleSheet } from "react-native";
import DropModalIcon from "@/assets/svgs/DropModalIcon";
import { IToDo } from "@/hooks/firebase/types/todoData";
import AssigneesDisplay from "@/components/shared/AssigneesDisplay";
interface IAddChoreDialog {
isVisible: boolean;
@ -111,6 +112,7 @@ const AddChoreDialog = (addChoreDialogProps: IAddChoreDialog) => {
</View>
<TextField
placeholder="Add a To Do"
autoFocus
value={todo?.title}
onChangeText={(text) => {
setTodo((oldValue: IToDo) => ({ ...oldValue, title: text }));
@ -197,25 +199,8 @@ const AddChoreDialog = (addChoreDialogProps: IAddChoreDialog) => {
label="Assign"
/>
</View>
<View row marginH-13 marginT-13>
<View
marginL-30
style={{
aspectRatio: 1,
width: 50,
backgroundColor: "red",
borderRadius: 50,
}}
/>
<View
marginL-30
style={{
aspectRatio: 1,
width: 50,
backgroundColor: "red",
borderRadius: 50,
}}
/>
<View row marginL-27 marginT-0>
<AssigneesDisplay />
</View>
<View row centerV style={styles.rotateSwitch}>
<Text text80>Take Turns</Text>