Small fixes

This commit is contained in:
Milan Paunovic
2024-10-31 21:28:23 +01:00
parent fda1287011
commit ca5df87f3d
5 changed files with 244 additions and 195 deletions

View File

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

View File

@ -1,11 +1,11 @@
import React, { useEffect, useState } from "react"; import React, {useEffect, useRef, useState} from "react";
import { import {
Button, Button,
Dialog, Dialog,
View, View,
Text, Text,
TextField, TextField,
TouchableOpacity, TouchableOpacity, TextFieldRef,
} from "react-native-ui-lib"; } from "react-native-ui-lib";
import { Dimensions, StyleSheet } from "react-native"; import { Dimensions, StyleSheet } from "react-native";
import { PanningDirectionsEnum } from "react-native-ui-lib/src/incubator/panView"; import { PanningDirectionsEnum } from "react-native-ui-lib/src/incubator/panView";
@ -30,6 +30,7 @@ const MoveBrainDump = (props: {
props.item.description props.item.description
); );
const [modalVisible, setModalVisible] = useState<boolean>(false); const [modalVisible, setModalVisible] = useState<boolean>(false);
const descriptionRef = useRef<TextFieldRef>(null)
const { width } = Dimensions.get("screen"); const { width } = Dimensions.get("screen");
@ -37,6 +38,14 @@ const MoveBrainDump = (props: {
updateBrainDumpItem(props.item.id, { description: description }); updateBrainDumpItem(props.item.id, { description: description });
}, [description]); }, [description]);
useEffect(() => {
if (props.isVisible) {
setTimeout(() => {
descriptionRef?.current?.focus()
}, 500)
}
}, [props.isVisible]);
const showConfirmationDialog = () => { const showConfirmationDialog = () => {
setModalVisible(true); setModalVisible(true);
}; };
@ -112,7 +121,6 @@ const MoveBrainDump = (props: {
<TextField <TextField
textAlignVertical="top" textAlignVertical="top"
multiline multiline
autoFocus
fieldStyle={{ fieldStyle={{
width: "94%", width: "94%",
}} }}
@ -123,6 +131,7 @@ const MoveBrainDump = (props: {
onChangeText={(value) => { onChangeText={(value) => {
setDescription(value); setDescription(value);
}} }}
ref={descriptionRef}
returnKeyType="default" returnKeyType="default"
/> />
</View> </View>

View File

@ -1,7 +1,16 @@
import {Button, ButtonSize, Dialog, Text, TextField, TextFieldRef, View,} from "react-native-ui-lib"; import {
Button,
ButtonSize, Colors,
Dialog,
KeyboardAwareScrollView, LoaderScreen, Modal,
Text,
TextField,
TextFieldRef,
View,
} from "react-native-ui-lib";
import React, {useRef, useState} from "react"; import React, {useRef, useState} from "react";
import {useSignIn} from "@/hooks/firebase/useSignIn"; import {useSignIn} from "@/hooks/firebase/useSignIn";
import {StyleSheet} from "react-native"; import {KeyboardAvoidingView, Platform, StyleSheet} from "react-native";
import Toast from "react-native-toast-message"; import Toast from "react-native-toast-message";
import {useLoginWithQrCode} from "@/hooks/firebase/useLoginWithQrCode"; import {useLoginWithQrCode} from "@/hooks/firebase/useLoginWithQrCode";
import {Camera, CameraView} from "expo-camera"; import {Camera, CameraView} from "expo-camera";
@ -19,8 +28,10 @@ const SignInPage = ({
const [showCameraDialog, setShowCameraDialog] = useState<boolean>(false); const [showCameraDialog, setShowCameraDialog] = useState<boolean>(false);
const passwordRef = useRef<TextFieldRef>(null); const passwordRef = useRef<TextFieldRef>(null);
const {mutateAsync: signIn, error, isError} = useSignIn(); const {mutateAsync: signIn, error, isError, isLoading: isSigninIn} = useSignIn();
const {mutateAsync: signInWithQrCode} = useLoginWithQrCode(); const {mutateAsync: signInWithQrCode, isLoading: isQRCodeLoggingIn} = useLoginWithQrCode();
const isLoading = isSigninIn || isQRCodeLoggingIn
const handleSignIn = async () => { const handleSignIn = async () => {
await signIn({email, password}); await signIn({email, password});
@ -64,8 +75,13 @@ const SignInPage = ({
}; };
return ( return (
<View padding-10 centerV height={"100%"}> <View padding-10 centerV height={"100%%"} style={{justifyContent: "center"}}>
<TextField <KeyboardAvoidingView
contentContainerStyle={{ justifyContent:"center"}}
keyboardVerticalOffset={50}
behavior={Platform.OS === "ios" ? "padding" : "height"}
>
<TextField
placeholder="Email" placeholder="Email"
keyboardType={"email-address"} keyboardType={"email-address"}
returnKeyType={"next"} returnKeyType={"next"}
@ -73,6 +89,8 @@ const SignInPage = ({
defaultValue={email} defaultValue={email}
onChangeText={setEmail} onChangeText={setEmail}
style={styles.textfield} style={styles.textfield}
autoComplete={"email"}
autoCorrect={false}
onSubmitEditing={() => { onSubmitEditing={() => {
// Move focus to the description field // Move focus to the description field
passwordRef.current?.focus(); passwordRef.current?.focus();
@ -99,62 +117,64 @@ const SignInPage = ({
style={{marginBottom: 20, height: 50}} style={{marginBottom: 20, height: 50}}
backgroundColor="#fd1775" backgroundColor="#fd1775"
/> />
<Button
label="Log in with a QR Code"
labelStyle={{
fontFamily: "PlusJakartaSans_600SemiBold",
fontSize: 16,
}}
onPress={() => {
getCameraPermissions(() => setShowCameraDialog(true));
}}
style={{marginBottom: 20, height: 50}}
backgroundColor="#fd1775"
/>
{isError && (
<Text center style={{marginBottom: 20}}>{`${
error?.toString()?.split("]")?.[1]
}`}</Text>
)}
<View row centerH marginB-5 gap-5>
<Text style={styles.jakartaLight}>Don't have an account?</Text>
<Button <Button
onPress={() => setTab("register")} label="Log in with a QR Code"
label="Sign Up" labelStyle={{
labelStyle={[ fontFamily: "PlusJakartaSans_600SemiBold",
styles.jakartaMedium, fontSize: 16,
{textDecorationLine: "none", color: "#fd1575"}, }}
]} onPress={() => {
link getCameraPermissions(() => setShowCameraDialog(true));
size={ButtonSize.xSmall} }}
padding-0 style={{marginBottom: 20, height: 50}}
margin-0 backgroundColor="#fd1775"
text70
left
color="#fd1775"
/> />
</View>
<View row centerH marginB-5 gap-5> {isError && (
<Text text70>Forgot your password?</Text> <Text center style={{marginBottom: 20}}>{`${
<Button error?.toString()?.split("]")?.[1]
onPress={() => setTab("reset-password")} }`}</Text>
label="Reset password" )}
labelStyle={[
styles.jakartaMedium, <View row centerH marginB-5 gap-5>
{textDecorationLine: "none", color: "#fd1575"}, <Text style={styles.jakartaLight}>Don't have an account?</Text>
]} <Button
link onPress={() => setTab("register")}
size={ButtonSize.xSmall} label="Sign Up"
padding-0 labelStyle={[
margin-0 styles.jakartaMedium,
text70 {textDecorationLine: "none", color: "#fd1575"},
left ]}
avoidInnerPadding link
color="#fd1775" size={ButtonSize.xSmall}
/> padding-0
</View> margin-0
text70
left
color="#fd1775"
/>
</View>
<View row centerH marginB-5 gap-5>
<Text text70>Forgot your password?</Text>
<Button
onPress={() => setTab("reset-password")}
label="Reset password"
labelStyle={[
styles.jakartaMedium,
{textDecorationLine: "none", color: "#fd1575"},
]}
link
size={ButtonSize.xSmall}
padding-0
margin-0
text70
left
avoidInnerPadding
color="#fd1775"
/>
</View>
</KeyboardAvoidingView>
{/* Camera Dialog */} {/* Camera Dialog */}
<Dialog <Dialog
@ -185,6 +205,12 @@ const SignInPage = ({
style={{margin: 10, marginBottom: 30}} style={{margin: 10, marginBottom: 30}}
/> />
</Dialog> </Dialog>
{isLoading && (
<LoaderScreen overlay message={"Signing in..."} backgroundColor={Colors.white} color={Colors.grey40}/>
)}
</View> </View>
); );
}; };

View File

@ -55,6 +55,12 @@ const SignUpPage = ({
lnameRef.current?.focus(); lnameRef.current?.focus();
}} }}
blurOnSubmit={false} blurOnSubmit={false}
accessibilityLabel="First name input"
accessibilityHint="Enter your first name"
accessible
returnKeyType="next"
textContentType="givenName"
importantForAccessibility="yes"
/> />
<TextField <TextField
ref={lnameRef} ref={lnameRef}
@ -66,17 +72,27 @@ const SignUpPage = ({
emailRef.current?.focus(); emailRef.current?.focus();
}} }}
blurOnSubmit={false} blurOnSubmit={false}
accessibilityLabel="Last name input"
accessibilityHint="Enter your last name"
accessible
returnKeyType="next"
textContentType="familyName"
importantForAccessibility="yes"
/> />
<TextField <TextField
ref={emailRef}
placeholder="Email" placeholder="Email"
value={email} keyboardType={"email-address"}
returnKeyType={"next"}
textContentType={"emailAddress"}
defaultValue={email}
onChangeText={setEmail} onChangeText={setEmail}
style={styles.textfield} style={styles.textfield}
autoComplete={"email"}
autoCorrect={false}
ref={emailRef}
onSubmitEditing={() => { onSubmitEditing={() => {
passwordRef.current?.focus(); passwordRef.current?.focus();
}} }}
blurOnSubmit={false}
/> />
<View <View
centerV centerV

View File

@ -22,7 +22,7 @@ const AddChore = () => {
> >
<View style={styles.buttonContainer}> <View style={styles.buttonContainer}>
<Button <Button
marginH-20 marginB-30
size={ButtonSize.large} size={ButtonSize.large}
style={styles.button} style={styles.button}
onPress={() => setIsVisible(!isVisible)} onPress={() => setIsVisible(!isVisible)}