Sfoglia il codice sorgente

Added formik and yup validation

new-app
Lazar Kostic 3 anni fa
parent
commit
0b36df499a

+ 11
- 11
components/InputField.jsx Vedi File

@@ -16,35 +16,35 @@ const InputField = ({
filedButtonLabel,
fieldButtonFunction,
onChangeText,
text
text,
name,
handleBlur
}) => {
return (
<View style={styles.textField}>
{icon}
{inputType === "password" ? (
<TextInput
name={name}
placeholder={label}
placeholderTextColor="#C6C6C6"
keyboardType={keyboardType}
style={styles.textInput}
secureTextEntry={true}
value={text}
onChangeText={inputText => {
if (onChangeText) {
onChangeText(inputText);
}
}}
onChangeText={onChangeText}
onBlur={handleBlur}
/>
) : (
<TextInput
name={name}
placeholder={label}
placeholderTextColor="#C6C6C6"
keyboardType={keyboardType}
style={styles.textInput}
value={text}
onChangeText={inputText => {
if (onChangeText) {
onChangeText(inputText);
}
}}
onChangeText={onChangeText}
onBlur={handleBlur}
/>
)}
<TouchableOpacity onPress={fieldButtonFunction}>

+ 7
- 2
context/AuthContext.js Vedi File

@@ -2,6 +2,7 @@ import AsyncStorage from "@react-native-async-storage/async-storage";
import * as Google from "expo-auth-session/providers/google";
import React, { createContext, useEffect, useState } from "react";
import { googleApi, loginApi, registerApi } from "../service/user";
import {revokeAsync} from 'expo-auth-session'

export const AuthContext = createContext();

@@ -59,7 +60,7 @@ export const AuthProvider = ({ children }) => {
};

const googleAuth = () => {
promptAsync({ useProxy: false, showInRecents: true });
promptAsync({ useProxy: true, showInRecents: true });
};

const register = (username, email, password, callback) => {
@@ -81,11 +82,15 @@ export const AuthProvider = ({ children }) => {
});
};

const logout = () => {
const logout = async () => {
setIsLoading(true);
AsyncStorage.removeItem("userInfo");
setUserInfo({});
setIsLoading(false);

if (userInfo.user.provider === 'google') {
await revokeAsync({token: response.authentication.accessToken}, {revocationEndpoint: 'https://oauth2.googleapis.com/revoke'})
}
};

const isLoggedIn = async () => {

+ 3
- 2
package.json Vedi File

@@ -9,7 +9,6 @@
"dependencies": {
"@react-native-async-storage/async-storage": "~1.17.3",
"@react-native-community/datetimepicker": "6.5.2",
"@react-native-google-signin/google-signin": "^8.2.2",
"@react-native-masked-view/masked-view": "0.2.8",
"@react-navigation/bottom-tabs": "^6.4.3",
"@react-navigation/drawer": "^6.5.5",
@@ -20,8 +19,10 @@
"expo": "~47.0.8",
"expo-auth-session": "~3.7.3",
"expo-random": "~13.0.0",
"expo-splash-screen": "~0.17.5",
"expo-status-bar": "~1.4.2",
"expo-web-browser": "~12.0.0",
"formik": "^2.2.9",
"react": "18.1.0",
"react-dom": "18.1.0",
"react-native": "0.70.5",
@@ -40,7 +41,7 @@
"react-redux": "^8.0.5",
"redux-batched-actions": "^0.5.0",
"redux-thunk": "^2.4.2",
"expo-splash-screen": "~0.17.5"
"yup": "^0.32.11"
},
"devDependencies": {
"@babel/core": "^7.19.3"

+ 6
- 0
schemas/loginSchema.js Vedi File

@@ -0,0 +1,6 @@
import * as Yup from "yup";

export const loginSchema = Yup.object().shape({
email: Yup.string().required('Email/Username is required'),
password: Yup.string().required("Password is required"),
});

+ 11
- 0
schemas/registerSchema.js Vedi File

@@ -0,0 +1,11 @@
import * as Yup from "yup";

export const registerSchema = Yup.object().shape({
username: Yup.string().required("Username is required."),
email: Yup.string().required('Email is required'),
password: Yup.string().required("Password is required"),
confirmPassword: Yup.string().oneOf(
[Yup.ref("password"), null],
"Passwords must match"
).required('Confirmation password is required'),
});

+ 12
- 0
screens/HomeScreen.jsx Vedi File

@@ -16,6 +16,10 @@ const HomeScreen = ({navigation}) => {
<ImageBackground source={require('../assets/images/diligent-purple.png')} style={styles.imageBackground} imageStyle={{borderRadius:25}} />
</TouchableOpacity>
</View>
<View style={styles.search}>
<Feather name='search' size={20} color='#C6C6C6' style={{marginRight: 5}} />
<TextInput placeholder='Search' placeholderTextColor='#C6C6C6' />
</View>
</ScrollView>
</SafeAreaView>
)
@@ -30,6 +34,14 @@ const styles = StyleSheet.create({
imageBackground: {
width: 35,
height: 35
},
search: {
flexDirection: 'row',
borderColor: '#C6C6C6',
borderWidth: 1,
borderRadius: 8,
paddingHorizontal: 10,
paddingVertical: 8
}
})


+ 66
- 47
screens/LoginScreen.jsx Vedi File

@@ -1,4 +1,4 @@
import React, {useState, useContext} from "react";
import React, { useState, useContext } from "react";
import {
SafeAreaView,
View,
@@ -19,20 +19,19 @@ import InputField from "../components/InputField";
import { globalStyles } from "../styles/global";
import { AuthContext } from "../context/AuthContext";
import Loader from "../components/Loader";
import { Formik } from "formik";
import { loginSchema } from "../schemas/loginSchema";

const LoginScreen = ({ navigation }) => {
const [email, setEmail] = useState(null);
const [password, setPassword] = useState(null);
const [error, setError] = useState(null);

const { isLoading, login, googleAuth } = useContext(AuthContext);

const {isLoading, login, googleAuth} = useContext(AuthContext);

const handleLogin = () => {
login(email, password, function(result) {
const handleLogin = (values) => {
login(values.email, values.password, function (result) {
setError(result.error.message);
});
}
};

return (
<SafeAreaView style={globalStyles.safeArea}>
@@ -41,46 +40,66 @@ const LoginScreen = ({ navigation }) => {
<View style={{ alignItems: "center" }}>
<LoginSVG height={300} width={300} />
</View>
<Text style={globalStyles.boldText}>Sign In</Text>
<InputField
label={"Email"}
keyboardType="email-address"
onChangeText={text => {
setEmail(text);
}}
text={email}
icon={
<MaterialIcons
name="alternate-email"
size={20}
color="#666"
style={{ marginRight: 5 }}
/>
}
/>
<InputField
label={"Password"}
filedButtonLabel={"Forgot?"}
fieldButtonFunction={() => {}}
inputType="password"
text={password}
onChangeText={text => {
setPassword(text);
<Formik
initialValues={{
email: "",
password: "",
}}
icon={
<Ionicons
name="ios-lock-closed-outline"
size={20}
color="#666"
style={{ marginRight: 5 }}
/>
}
/>
{error && <Text style={styles.errorMessage}>{error}</Text>}
<CustomButton label={"Login"} onPress={handleLogin} />
validationSchema={loginSchema}
onSubmit={handleLogin}
validateOnChange={false}
validateOnBlur={false}
>
{({ handleChange, handleBlur, handleSubmit, values, isValid, errors }) => (
<>
<Text style={globalStyles.boldText}>Sign In</Text>
<InputField
name="email"
label={"Email"}
keyboardType="email-address"
onChangeText={handleChange('email')}
text={values.email}
handleBlur={handleBlur('email')}
icon={
<MaterialIcons
name="alternate-email"
size={20}
color="#666"
style={{ marginRight: 5 }}
/>
}
/>
{errors.email && <Text style={styles.errorMessage}>{errors.email}</Text>}
<InputField
name="password"
label={"Password"}
filedButtonLabel={"Forgot?"}
fieldButtonFunction={() => {}}
inputType="password"
handleBlur={handleBlur('password')}
text={values.password}
onChangeText={handleChange('password')}
icon={
<Ionicons
name="ios-lock-closed-outline"
size={20}
color="#666"
style={{ marginRight: 5 }}
/>
}
/>
{errors.password && <Text style={styles.errorMessage}>{errors.password}</Text>}
{error && <Text style={styles.errorMessage}>{error}</Text>}
<CustomButton label={"Login"} onPress={handleSubmit} />
</>
)}
</Formik>
<Text style={globalStyles.regularCenteredText}>Or login with ...</Text>
<View style={styles.providersContainer}>
<TouchableOpacity onPress={googleAuth} style={globalStyles.iconButton}>
<TouchableOpacity
onPress={googleAuth}
style={globalStyles.iconButton}
>
<GoogleSVG height={24} width={24} />
</TouchableOpacity>
<TouchableOpacity onPress={() => {}} style={globalStyles.iconButton}>
@@ -125,8 +144,8 @@ const styles = StyleSheet.create({
},
errorMessage: {
marginBottom: 30,
color: 'red'
}
color: "red",
},
});

export default LoginScreen;

+ 125
- 88
screens/RegisterScreen.jsx Vedi File

@@ -10,7 +10,7 @@ import {
Platform,
} from "react-native";

import DateTimePicker from "@react-native-community/datetimepicker";
// import DateTimePicker from "@react-native-community/datetimepicker";
import InputField from "../components/InputField";

import MaterialIcons from "@expo/vector-icons/MaterialIcons";
@@ -24,43 +24,35 @@ import TwitterSVG from "../assets/images/twitter.svg";
import CustomButton from "../components/Buttons/CustomButton";
import { globalStyles } from "../styles/global";
import { AuthContext } from "../context/AuthContext";
import Spinner from "react-native-loading-spinner-overlay/lib";
import Loader from "../components/Loader";
import { Formik } from "formik";
import { registerSchema } from "../schemas/registerSchema";

const RegisterScreen = ({ navigation }) => {
const { isLoading, register } = useContext(AuthContext);
const { isLoading, register, googleAuth } = useContext(AuthContext);

const [date, setDate] = useState(new Date());
const [open, setOpen] = useState(false);
const [dateOfBirthLabel, setDateOfBirthLabel] = useState("Date of Birth");

const [username, setUsername] = useState(null);
const [email, setEmail] = useState(null);
const [password, setPassword] = useState(null);
const [confirmPassword, setConfirmPassword] = useState(null);
// const [dateOfBirthLabel, setDateOfBirthLabel] = useState("Date of Birth");
const [error, setError] = useState(null);

const onChange = (event, selectedDate) => {
const currentDate = selectedDate || date;
setDate(currentDate);
let tempDate = new Date(currentDate);
let fDate =
tempDate.getDate() +
"/" +
(tempDate.getMonth() + 1) +
"/" +
tempDate.getFullYear();
setDateOfBirthLabel(fDate);
setOpen(false);
};

const handleSignup = () => {
if (password !== confirmPassword) {
setError("Passwords must match");
return;
}
// BIRTHDAY DATETIME PICKER
// const onChange = (event, selectedDate) => {
// const currentDate = selectedDate || date;
// setDate(currentDate);
// let tempDate = new Date(currentDate);
// let fDate =
// tempDate.getDate() +
// "/" +
// (tempDate.getMonth() + 1) +
// "/" +
// tempDate.getFullYear();
// setDateOfBirthLabel(fDate);
// setOpen(false);
// };

register(username, email, password, function (result) {
const handleSignup = (values) => {
register(values.username, values.email, values.password, function (result) {
setError(result.error.message);
});
};
@@ -77,7 +69,10 @@ const RegisterScreen = ({ navigation }) => {
</View>
<Text style={globalStyles.boldText}>Sign Up</Text>
<View style={styles.providersContainer}>
<TouchableOpacity onPress={() => {}} style={globalStyles.iconButton}>
<TouchableOpacity
onPress={googleAuth}
style={globalStyles.iconButton}
>
<GoogleSVG height={24} width={24} />
</TouchableOpacity>
<TouchableOpacity onPress={() => {}} style={globalStyles.iconButton}>
@@ -90,70 +85,112 @@ const RegisterScreen = ({ navigation }) => {
<Text style={globalStyles.regularCenteredText}>
Or, sign up with email...
</Text>
<InputField
text={username}
onChangeText={(text) => setUsername(text)}
label={"Full Name"}
icon={
<Ionicons
name="person-outline"
size={20}
color="#666"
style={{ marginRight: 5 }}
/>
}
/>
<InputField
text={email}
onChangeText={(text) => setEmail(text)}
label={"Email"}
icon={
<MaterialIcons
name="alternate-email"
size={20}
color="#666"
style={{ marginRight: 5 }}
/>
}
keyboardType="email-address"
/>
<InputField
text={password}
onChangeText={(text) => setPassword(text)}
label={"Password"}
icon={
<Ionicons
name="ios-lock-closed-outline"
size={20}
color="#666"
style={{ marginRight: 5 }}
/>
}
inputType="password"
/>
<InputField
text={confirmPassword}
onChangeText={(text) => setConfirmPassword(text)}
label={"Confirm Password"}
icon={
<Ionicons
name="ios-lock-closed-outline"
size={20}
color="#666"
style={{ marginRight: 5 }}
/>
}
inputType="password"
/>
{/* <View style={styles.dateOfBirthContainer}>
<Formik
initialValues={{
username: "",
email: "",
password: "",
confirmPassword: "",
}}
validationSchema={registerSchema}
onSubmit={handleSignup}
validateOnChange={false}
validateOnBlur={false}
>
{({
handleChange,
handleBlur,
handleSubmit,
values,
isValid,
errors,
}) => (
<>
<InputField
name={"username"}
text={values.username}
onChangeText={handleChange("username")}
label={"Username"}
handleBlur={handleBlur("username")}
icon={
<Ionicons
name="person-outline"
size={20}
color="#666"
style={{ marginRight: 5 }}
/>
}
/>
{errors.username && (
<Text style={styles.errorMessage}>{errors.username}</Text>
)}
<InputField
name={"email"}
text={values.email}
onChangeText={handleChange("email")}
label={"Email"}
handleBlur={handleBlur("email")}
icon={
<MaterialIcons
name="alternate-email"
size={20}
color="#666"
style={{ marginRight: 5 }}
/>
}
keyboardType="email-address"
/>
{errors.email && (
<Text style={styles.errorMessage}>{errors.email}</Text>
)}
<InputField
name={"password"}
text={values.password}
onChangeText={handleChange("password")}
label={"Password"}
handleBlur={handleBlur("password")}
icon={
<Ionicons
name="ios-lock-closed-outline"
size={20}
color="#666"
style={{ marginRight: 5 }}
/>
}
inputType="password"
/>
{errors.password && (
<Text style={styles.errorMessage}>{errors.password}</Text>
)}
<InputField
name={"confirmPassword"}
text={values.confirmPassword}
onChangeText={handleChange("confirmPassword")}
label={"Confirm Password"}
handleBlur={handleBlur("confirmPassword")}
icon={
<Ionicons
name="ios-lock-closed-outline"
size={20}
color="#666"
style={{ marginRight: 5 }}
/>
}
inputType="password"
/>
{errors.confirmPassword && <Text style={styles.errorMessage}>{errors.confirmPassword}</Text>}
{/* <View style={styles.dateOfBirthContainer}>
<Ionicons name='calendar-outline' size={20} color="#666" style={{marginRight: 5}} />
<TouchableOpacity onPress={() => setOpen(true)}>
<Text style={styles.dateOfBirthLabel}>{dateOfBirthLabel}</Text>
{open && <DateTimePicker testID='dateTimePicker' value={date} mode="date" display='spinner' onChange={onChange} textColor="#000" />}
</TouchableOpacity>
</View> */}
{error && <Text style={styles.errorMessage}>{error}</Text>}
<CustomButton label={"Sign Up"} onPress={handleSignup} />
{error && <Text style={styles.errorMessage}>{error}</Text>}
<CustomButton label={"Sign Up"} onPress={handleSubmit} />
</>
)}
</Formik>
<View style={styles.alreadyRegistered}>
<Text style={globalStyles.regularText}>Already Registered? </Text>
<TouchableOpacity onPress={() => navigation.goBack()}>

+ 19
- 19
service/asyncStorage.js Vedi File

@@ -1,26 +1,26 @@
import AsyncStorage from "@react-native-async-storage/async-storage";

export const storeData = async (key, value) => {
try {
await AsyncStorage.setItem(key, value);
} catch (e) {
console.log(e);
}
try {
await AsyncStorage.setItem(key, value);
} catch (e) {
// error reading value
}
};

export const getData = async (key) => {
try {
const value = await AsyncStorage.getItem(key);
return value;
} catch(e) {
// error reading value
}
export const getData = async (key) => {
try {
const value = await AsyncStorage.getItem(key);
return value;
} catch (e) {
// error reading value
}
};

export const removeData = async (key) => {
try {
await AsyncStorage.removeItem(key);
} catch(e) {
// error reading value
}
}
export const removeData = async (key) => {
try {
await AsyncStorage.removeItem(key);
} catch (e) {
// error reading value
}
};

+ 3
- 2
service/user.js Vedi File

@@ -1,7 +1,8 @@
import { API_ENDPOINT } from "./endpointDef";
import apiEndpoints from "./apiEndpoints";

export const loginApi = async (payload) => {
const result = await fetch(API_ENDPOINT + 'api/auth/local', {
const result = await fetch(`${API_ENDPOINT}${apiEndpoints.login}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
@@ -29,7 +30,7 @@ export const registerApi = async (payload) => {
};

export const googleApi = async (accessToken) => {
const result = await fetch('https://9dae-178-220-74-194.eu.ngrok.io/' + `api/auth/google/callback?access_token=${accessToken}`);
const result = await fetch('http://localhost:1337/' + `api/auth/google/callback?access_token=${accessToken}`);

const res = await result.json();


+ 72
- 6
yarn.lock Vedi File

@@ -1017,7 +1017,7 @@
pirates "^4.0.5"
source-map-support "^0.5.16"

"@babel/runtime@^7.0.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.14.0", "@babel/runtime@^7.18.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
"@babel/runtime@^7.0.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.14.0", "@babel/runtime@^7.15.4", "@babel/runtime@^7.18.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
version "7.20.6"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.6.tgz#facf4879bfed9b5326326273a64220f099b0fce3"
integrity sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA==
@@ -1730,11 +1730,6 @@
dependencies:
invariant "^2.2.4"

"@react-native-google-signin/google-signin@^8.2.2":
version "8.2.2"
resolved "https://registry.yarnpkg.com/@react-native-google-signin/google-signin/-/google-signin-8.2.2.tgz#c8420fea36f05dfb067eb1fc301d42f442440a65"
integrity sha512-y56SDxupkN4nvIsmvnq11OqDMLJKTihbwT4dUtnPZ+FCOO4uX62zCpCyXub5o7/N12Ei8KCHC2umd8OHpMdRFg==

"@react-native-masked-view/masked-view@0.2.8":
version "0.2.8"
resolved "https://registry.yarnpkg.com/@react-native-masked-view/masked-view/-/masked-view-0.2.8.tgz#34405a4361882dae7c81b1b771fe9f5fbd545a97"
@@ -1999,6 +1994,11 @@
dependencies:
"@types/istanbul-lib-report" "*"

"@types/lodash@^4.14.175":
version "4.14.191"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.191.tgz#09511e7f7cba275acd8b419ddac8da9a6a79e2fa"
integrity sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==

"@types/node@*":
version "18.11.11"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.11.tgz#1d455ac0211549a8409d3cdb371cd55cc971e8dc"
@@ -3132,6 +3132,11 @@ deep-extend@^0.6.0:
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==

deepmerge@^2.1.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170"
integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==

deepmerge@^3.2.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-3.3.0.tgz#d3c47fd6f3a93d517b14426b0628a17b0125f5f7"
@@ -3803,6 +3808,19 @@ form-data@^4.0.0:
combined-stream "^1.0.8"
mime-types "^2.1.12"

formik@^2.2.9:
version "2.2.9"
resolved "https://registry.yarnpkg.com/formik/-/formik-2.2.9.tgz#8594ba9c5e2e5cf1f42c5704128e119fc46232d0"
integrity sha512-LQLcISMmf1r5at4/gyJigGn0gOwFbeEAlji+N9InZF6LIMXnFNkO42sCI8Jt84YZggpD4cPWObAZaxpEFtSzNA==
dependencies:
deepmerge "^2.1.1"
hoist-non-react-statics "^3.3.0"
lodash "^4.17.21"
lodash-es "^4.17.21"
react-fast-compare "^2.0.1"
tiny-warning "^1.0.2"
tslib "^1.10.0"

fragment-cache@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19"
@@ -4742,6 +4760,11 @@ locate-path@^6.0.0:
dependencies:
p-locate "^5.0.0"

lodash-es@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==

lodash.debounce@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
@@ -5331,6 +5354,11 @@ mz@^2.7.0:
object-assign "^4.0.1"
thenify-all "^1.0.0"

nanoclone@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/nanoclone/-/nanoclone-0.2.1.tgz#dd4090f8f1a110d26bb32c49ed2f5b9235209ed4"
integrity sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==

nanoid@^3.1.23:
version "3.3.4"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
@@ -5879,6 +5907,11 @@ prop-types@^15.5.10, prop-types@^15.7.2:
object-assign "^4.1.1"
react-is "^16.13.1"

property-expr@^2.0.4:
version "2.0.5"
resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.5.tgz#278bdb15308ae16af3e3b9640024524f4dc02cb4"
integrity sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==

proxy-from-env@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
@@ -5984,6 +6017,11 @@ react-dom@18.1.0:
loose-envify "^1.1.0"
scheduler "^0.22.0"

react-fast-compare@^2.0.1:
version "2.0.4"
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==

react-freeze@^1.0.0:
version "1.0.3"
resolved "https://registry.yarnpkg.com/react-freeze/-/react-freeze-1.0.3.tgz#5e3ca90e682fed1d73a7cb50c2c7402b3e85618d"
@@ -7077,6 +7115,11 @@ through@2:
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==

tiny-warning@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==

tmp@^0.0.33:
version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
@@ -7136,6 +7179,11 @@ toidentifier@1.0.1:
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==

toposort@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330"
integrity sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==

tr46@~0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
@@ -7151,6 +7199,11 @@ ts-interface-checker@^0.1.9:
resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699"
integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==

tslib@^1.10.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==

tslib@^2.0.1, tslib@^2.1.0, tslib@^2.4.0:
version "2.4.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e"
@@ -7599,3 +7652,16 @@ yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==

yup@^0.32.11:
version "0.32.11"
resolved "https://registry.yarnpkg.com/yup/-/yup-0.32.11.tgz#d67fb83eefa4698607982e63f7ca4c5ed3cf18c5"
integrity sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==
dependencies:
"@babel/runtime" "^7.15.4"
"@types/lodash" "^4.14.175"
lodash "^4.17.21"
lodash-es "^4.17.21"
nanoclone "^0.2.1"
property-expr "^2.0.4"
toposort "^2.0.2"

Loading…
Annulla
Salva