diff --git a/App.js b/App.js index 83d0f59..9c49dc7 100644 --- a/App.js +++ b/App.js @@ -1,7 +1,6 @@ -import React, { useState, useEffect } from "react"; -import Home from "./components/Home/Home"; - +import React from "react"; import { Text, View, StyleSheet, StatusBar } from "react-native"; +import { NativeRouter, Route, Routes } from "react-router-native"; import AppLoading from "expo-app-loading"; import { useFonts, @@ -9,11 +8,10 @@ import { Epilogue_500Medium, Epilogue_700Bold, } from "@expo-google-fonts/epilogue"; -import { SafeAreaView } from "react-native-safe-area-context"; -import { NavigationContainer } from "@react-navigation/native"; -import { createNativeStackNavigator } from "@react-navigation/native-stack"; - -const Stack = createNativeStackNavigator(); +import Home from "./components/Home/Home"; +import HomeCategoria from "./components/HomeCategoria/HomeCategoria"; +import AddCard from "./components/AddCard/AddCard"; +import ConfirmDelete from "./components/ConfirmDelete/ConfirmDelete"; export default function App() { let [fontsLoaded] = useFonts({ @@ -21,25 +19,28 @@ export default function App() { Epilogue_500Medium, Epilogue_700Bold, }); - if (!fontsLoaded) { return ; } else { return ( - - + + ); } } diff --git a/app.json b/app.json index 9c8354f..2b5a01d 100644 --- a/app.json +++ b/app.json @@ -1,7 +1,7 @@ { "expo": { "name": "Study Cards", - "slug": "Study Cards", + "slug": "study-cards", "version": "1.0.0", "orientation": "portrait", "icon": "./assets/icon.png", diff --git a/assets/icons/arrows-rotate-solid.svg b/assets/icons/arrows-rotate-solid.svg new file mode 100644 index 0000000..b6e4dcf --- /dev/null +++ b/assets/icons/arrows-rotate-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/play-solid.svg b/assets/icons/play-solid.svg new file mode 100644 index 0000000..eed74b4 --- /dev/null +++ b/assets/icons/play-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/trash-solid.svg b/assets/icons/trash-solid.svg new file mode 100644 index 0000000..ddc0dff --- /dev/null +++ b/assets/icons/trash-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/AddCard/AddCard.jsx b/components/AddCard/AddCard.jsx new file mode 100644 index 0000000..3ac3f18 --- /dev/null +++ b/components/AddCard/AddCard.jsx @@ -0,0 +1,262 @@ +import React, { useState, useEffect } from 'react'; +import { View, Text, ScrollView, FlatList, TextInput, Button, TouchableOpacity } from 'react-native'; +import { styles } from './AddCard.styles'; +import { useParams } from 'react-router-native'; +import { LinearGradient } from 'expo-linear-gradient'; +import CategoriasIcon from '../../assets/icons/categorias.svg' +import { Link } from 'react-router-native'; +import { vw, vh, vmin, vmax } from "react-native-expo-viewport-units"; +import CardsDB from '../../services/sqlite/Card' +import DetalhesDB from '../../services/sqlite/Detalhes' + +const AddCard = () => { + // Recebe os parametros vindos do router + const { categoriaId, cor, nome } = useParams() + + // Cria os states para atualizar enquanto o usuário modifica + const [titulo, setTitulo] = useState('') + const [resposta, setResposta] = useState('') + const [tituloDetalhe, setTituloDetalhe] = useState('') + const [respostaDetalhe, setRespostaDetalhe] = useState('') + const [detalheVisibility, setDetalheVisibility] = useState(false) + const [adicionarVisibility, setAdicionarVisibility] = useState(true) + const [idDetalhe, setIdDetalhe] = useState(0) + const [detalhes, setDetalhes] = useState([]) + const [detalheSelected, setDetalheSelected] = useState(-1) + + // Pega as cores para formar o fundo gradiente + const gradientColors = getColors(cor) + + const geraFlatList = () => { + console.log(detalhes.length) + if(detalhes.length != 0) { + console.log(detalhes[idDetalhe-1]) + return( + + Detalhes + item.id} + contentContainerStyle={styles.cardList}> + + + ); + } + } + + function setaDetalhes(){ + if (detalheVisibility){ + return( + + + setTituloDetalhe(novoTitulo)} + /> + escondeDetalhe()}> + x + + + setRespostaDetalhe(novaResposta)} + /> + + ) + } + } + + function setaButtonAdicionar(){ + if(adicionarVisibility && detalheSelected == -1 && !detalheVisibility){ + return( + exibeDetalhe()}> + Adicionar Detalhe + + ) + } + } + + function exibeSalvarDetalhe(){ + if (detalheVisibility){ + return ( + salvarDetalhe()}> + Salvar Detalhe + + ); + } + + } + + function exibeDetalhe(){ + setAdicionarVisibility(false) + setDetalheVisibility(true) + } + + function escondeDetalhe(){ + setAdicionarVisibility(true) + setDetalheVisibility(false) + setTituloDetalhe('') + setRespostaDetalhe('') + } + + function salvarDetalhe() { + var novo_detalhe = { + id: idDetalhe, + titulo: tituloDetalhe, + resposta: respostaDetalhe + } + setDetalhes(detalhes.concat([novo_detalhe])) + setIdDetalhe(novo_detalhe.id + 1) + setTituloDetalhe('') + setRespostaDetalhe('') + setAdicionarVisibility(true) + setDetalheVisibility(false) + } + + function deletarDetalhe(){ + var indexDetalhe = detalhes.findIndex(detalhe => detalhe.id == detalheSelected); + setDetalhes(detalhes.filter((_, i) => i !== indexDetalhe)); + setDetalheSelected(-1) + } + + function showMenuDetalhe(){ + if (detalheSelected != -1){ + return ( + deletarDetalhe()}> + Deletar + + ); + } + } + + const renderDetalhe = ({item}) => { + id = item.id + var isSelected = false + + if (detalheSelected == item.id){ + isSelected = true + } + + function selecionaDetalhe(){ + if (detalheSelected == item.id){ + setDetalheSelected(-1) + }else{ + setDetalheSelected(item.id) + } + } + return ( + selecionaDetalhe()}> + {item.titulo} + {item.resposta} + + ); + } + + return ( + + // Constrói a visualização do card + + + Novo Card + + + {nome} + + + + + + + setTitulo(novoTitulo)} + /> + setResposta(novaResposta)} + /> + + {geraFlatList()} + {setaDetalhes()} + + + + {exibeSalvarDetalhe()} + {setaButtonAdicionar()} + {showMenuDetalhe()} + + + + insertCard(titulo, resposta, categoriaId, detalhes)}> + Salvar + + + Cancelar + + + + ) +} + +/** Transforma as cores em HEXADECIMAL para construir o gradiente */ +function getColors(colorStr){ + var initialColor = colorStr.split("-")[0] + var finalColor = colorStr.split("-")[1] + return ["#" + initialColor, "#" + finalColor] + +} + +function insertCard(titulo, resposta, categoriaId, detalhes){ + // Adiciona Card + var novoCard = { + titulo: titulo, + resposta: resposta, + categoriaId: categoriaId + } + + //create + CardsDB.createCard(novoCard) + .then( id => { + console.log('Card created with id: '+ id) + insertDetalhes(detalhes, id) + }) + .catch( err => console.log(err) ) + + +} + +function insertDetalhes(detalhes, cardId){ + // Adiciona Detalhes + for(let detalhe of detalhes){ + + var novoDetalhe = { + cardId: cardId, + titulo: detalhe.titulo, + resposta: detalhe.resposta + } + + //create + DetalhesDB.createDetalhe(novoDetalhe) + .then( id => console.log('Detalhe created with id: '+ id) ) + .catch( err => console.log(err) ) +} +} + +export default AddCard \ No newline at end of file diff --git a/components/AddCard/AddCard.styles.js b/components/AddCard/AddCard.styles.js new file mode 100644 index 0000000..3f8e31f --- /dev/null +++ b/components/AddCard/AddCard.styles.js @@ -0,0 +1,177 @@ +import { StyleSheet } from "react-native"; +import { vw, vh, vmin, vmax } from "react-native-expo-viewport-units"; + +export const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: "#1a1a1a", + width: "100%", + height: "100%", + alignItems: "center", + }, + + header_detalhe: { + marginTop: 20, + display: "flex", + flexDirection: "row", + alignItems: "center", + justifyContent: "space-between", + }, + + close_detalhe: { + backgroundColor: "#c0392b", + padding: 4, + paddingTop: 0, + width: 32, + borderRadius: 50, + }, + + cardTituloDetalhe: { + width: vw(70), + color: "#f2f2f2", + textAlign: "left", + fontFamily: "Epilogue_700Bold", + fontSize: 17, + //borderBottomWidth: 2, + //borderBottomColor: "#f2f2f2", + }, + + btn_card: { + position: "absolute", + bottom: 20, + backgroundColor: "#1a1a1a", + borderRadius: 50, + textAlign: "center", + padding: 12, + }, + + menu_footer: { + height: vh(10), + width: "100%", + }, + + btn_text: { + color: "#f2f2f2", + fontFamily: "Epilogue_500Medium", + fontSize: 20, + width: vw(36), + textAlign: "center", + }, + + btn_card_text: { + color: "#f2f2f2", + fontFamily: "Epilogue_500Medium", + fontSize: 20, + textAlign: "center", + width: vw(70), + }, + + btn_card_text_x: { + color: "#f2f2f2", + fontFamily: "Epilogue_500Medium", + fontSize: 20, + textAlign: "center", + }, + + btn_right: { + position: "absolute", + right: 20, + bottom: 20, + }, + + btn_left: { + position: "absolute", + left: 20, + bottom: 20, + backgroundColor: "#c0392b", + }, + + btn_layout: { + backgroundColor: "#16a085", + padding: 10, + borderRadius: 50, + }, + + header: { + width: "100%", + }, + + titulo: { + color: "#f2f2f2", + marginLeft: 20, + marginTop: 20, + fontFamily: "Epilogue_500Medium", + fontSize: 40, + }, + + categoria: { + display: "flex", + flexDirection: "row", + alignItems: "center", + marginLeft: 20, + marginTop: 10, + }, + + categoryText: { + color: "#f2f2f2", + marginLeft: 10, + fontFamily: "Epilogue_500Medium", + fontSize: 23, + }, + + categoryItem: { + marginTop: 10, + borderRadius: 10, + width: "100%", + }, + + cardBody: { + flex: 1, + width: vw(90), + height: vh(70), + borderRadius: 40, + padding: 20, + marginLeft: vw(3), + marginRight: vw(3), + display: "flex", + flexDirection: "column", + alignItems: "center", + }, + + scrollView: { + marginTop: "5%", + marginBottom: 70, + }, + + cardTitulo: { + marginTop: 10, + width: vw(70), + color: "#f2f2f2", + textAlign: "left", + fontFamily: "Epilogue_700Bold", + fontSize: 25, + //backgroundColor: "#1a1a1a80", + borderRadius: 8, + //borderWidth: 1, + //borderColor: "#f2f2f2", + }, + + cardResposta: { + marginTop: 10, + width: vw(70), + color: "#f2f2f2", + textAlign: "left", + fontFamily: "Epilogue_500Medium", + fontSize: 17, + backgroundColor: "#1a1a1a60", + borderRadius: 8, + //borderWidth: 1, + // borderColor: "#f2f2f2", + padding: 8, + }, + + elevation: { + elevation: 15, + shadowColor: "#121212", + }, +}); diff --git a/components/AddCategoria/AddCategoria.jsx b/components/AddCategoria/AddCategoria.jsx new file mode 100644 index 0000000..064587d --- /dev/null +++ b/components/AddCategoria/AddCategoria.jsx @@ -0,0 +1,245 @@ +import React, { useState, useEffect } from 'react'; +import { View, Text, ScrollView, FlatList, TextInput, Button, TouchableOpacity } from 'react-native'; +import { styles } from './AddCategoria.styles'; +import { useParams } from 'react-router-native'; +import { LinearGradient } from 'expo-linear-gradient'; +import CategoriasIcon from '../../assets/icons/categorias.svg' +import { Link } from 'react-router-native'; +import { vw, vh, vmin, vmax } from "react-native-expo-viewport-units"; +import CardsDB from '../../services/sqlite/Card' +import DetalhesDB from '../../services/sqlite/Detalhes' + +const AddCategoria = () => { + // Recebe os parametros vindos do router + const { categoriaId, cor, nome } = useParams() + + // Cria os states para atualizar enquanto o usuário modifica + const [titulo, setTitulo] = useState('') + const [resposta, setResposta] = useState('') + const [tituloDetalhe, setTituloDetalhe] = useState('') + const [respostaDetalhe, setRespostaDetalhe] = useState('') + const [detalheVisibility, setDetalheVisibility] = useState(false) + const [adicionarVisibility, setAdicionarVisibility] = useState(true) + const [idDetalhe, setIdDetalhe] = useState(0) + const [detalhes, setDetalhes] = useState([]) + const [detalheSelected, setDetalheSelected] = useState(-1) + + // Pega as cores para formar o fundo gradiente + const gradientColors = getColors(cor) + + const geraFlatList = () => { + console.log(detalhes.length) + if(detalhes.length != 0) { + console.log(detalhes[idDetalhe-1]) + return( + + Detalhes + item.id} + contentContainerStyle={styles.cardList}> + + + ); + } + } + + function setaDetalhes(){ + if (detalheVisibility){ + return( + + + setTituloDetalhe(novoTitulo)} + /> + escondeDetalhe()}> + x + + + setRespostaDetalhe(novaResposta)} + /> + + ) + } + } + + function setaButtonAdicionar(){ + if(adicionarVisibility && detalheSelected == -1 && !detalheVisibility){ + return( + exibeDetalhe()}> + Adicionar Detalhe + + ) + } + } + + function exibeSalvarDetalhe(){ + if (detalheVisibility){ + return ( + salvarDetalhe()}> + Salvar Detalhe + + ); + } + + } + + function exibeDetalhe(){ + setAdicionarVisibility(false) + setDetalheVisibility(true) + } + + function escondeDetalhe(){ + setAdicionarVisibility(true) + setDetalheVisibility(false) + setTituloDetalhe('') + setRespostaDetalhe('') + } + + function salvarDetalhe() { + var novo_detalhe = { + id: idDetalhe, + titulo: tituloDetalhe, + resposta: respostaDetalhe + } + setDetalhes(detalhes.concat([novo_detalhe])) + setIdDetalhe(novo_detalhe.id + 1) + setTituloDetalhe('') + setRespostaDetalhe('') + setAdicionarVisibility(true) + setDetalheVisibility(false) + } + + function deletarDetalhe(){ + var indexDetalhe = detalhes.findIndex(detalhe => detalhe.id == detalheSelected); + setDetalhes(detalhes.filter((_, i) => i !== indexDetalhe)); + setDetalheSelected(-1) + } + + function showMenuDetalhe(){ + if (detalheSelected != -1){ + return ( + deletarDetalhe()}> + Deletar + + ); + } + } + + const renderDetalhe = ({item}) => { + id = item.id + var isSelected = false + + if (detalheSelected == item.id){ + isSelected = true + } + + function selecionaDetalhe(){ + if (detalheSelected == item.id){ + setDetalheSelected(-1) + }else{ + setDetalheSelected(item.id) + } + } + return ( + selecionaDetalhe()}> + {item.titulo} + {item.resposta} + + ); + } + + return ( + + // Constrói a visualização do card + + + Novo Card + + + {nome} + + + + + + + setTitulo(novoTitulo)} + /> + setResposta(novaResposta)} + /> + + {geraFlatList()} + {setaDetalhes()} + + + + {exibeSalvarDetalhe()} + {setaButtonAdicionar()} + {showMenuDetalhe()} + + + + insertCard(titulo, resposta, categoriaId, detalhes)}> + Salvar + + + Cancelar + + + + ) +} + +/** Transforma as cores em HEXADECIMAL para construir o gradiente */ +function getColors(colorStr){ + var initialColor = colorStr.split("-")[0] + var finalColor = colorStr.split("-")[1] + return ["#" + initialColor, "#" + finalColor] + +} + +function insertCard(titulo, resposta, categoriaId, detalhes){ + // Adiciona Card + var novoCard = { + titulo: titulo, + resposta: resposta, + categoriaId: categoriaId + } + + //create + CardsDB.createCard(novoCard) + .then( id => { + console.log('Card created with id: '+ id) + insertDetalhes(detalhes, id) + }) + .catch( err => console.log(err) ) + + +} + +export default AddCategoria \ No newline at end of file diff --git a/components/AddCategoria/AddCategoria.styles.js b/components/AddCategoria/AddCategoria.styles.js new file mode 100644 index 0000000..3f8e31f --- /dev/null +++ b/components/AddCategoria/AddCategoria.styles.js @@ -0,0 +1,177 @@ +import { StyleSheet } from "react-native"; +import { vw, vh, vmin, vmax } from "react-native-expo-viewport-units"; + +export const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: "#1a1a1a", + width: "100%", + height: "100%", + alignItems: "center", + }, + + header_detalhe: { + marginTop: 20, + display: "flex", + flexDirection: "row", + alignItems: "center", + justifyContent: "space-between", + }, + + close_detalhe: { + backgroundColor: "#c0392b", + padding: 4, + paddingTop: 0, + width: 32, + borderRadius: 50, + }, + + cardTituloDetalhe: { + width: vw(70), + color: "#f2f2f2", + textAlign: "left", + fontFamily: "Epilogue_700Bold", + fontSize: 17, + //borderBottomWidth: 2, + //borderBottomColor: "#f2f2f2", + }, + + btn_card: { + position: "absolute", + bottom: 20, + backgroundColor: "#1a1a1a", + borderRadius: 50, + textAlign: "center", + padding: 12, + }, + + menu_footer: { + height: vh(10), + width: "100%", + }, + + btn_text: { + color: "#f2f2f2", + fontFamily: "Epilogue_500Medium", + fontSize: 20, + width: vw(36), + textAlign: "center", + }, + + btn_card_text: { + color: "#f2f2f2", + fontFamily: "Epilogue_500Medium", + fontSize: 20, + textAlign: "center", + width: vw(70), + }, + + btn_card_text_x: { + color: "#f2f2f2", + fontFamily: "Epilogue_500Medium", + fontSize: 20, + textAlign: "center", + }, + + btn_right: { + position: "absolute", + right: 20, + bottom: 20, + }, + + btn_left: { + position: "absolute", + left: 20, + bottom: 20, + backgroundColor: "#c0392b", + }, + + btn_layout: { + backgroundColor: "#16a085", + padding: 10, + borderRadius: 50, + }, + + header: { + width: "100%", + }, + + titulo: { + color: "#f2f2f2", + marginLeft: 20, + marginTop: 20, + fontFamily: "Epilogue_500Medium", + fontSize: 40, + }, + + categoria: { + display: "flex", + flexDirection: "row", + alignItems: "center", + marginLeft: 20, + marginTop: 10, + }, + + categoryText: { + color: "#f2f2f2", + marginLeft: 10, + fontFamily: "Epilogue_500Medium", + fontSize: 23, + }, + + categoryItem: { + marginTop: 10, + borderRadius: 10, + width: "100%", + }, + + cardBody: { + flex: 1, + width: vw(90), + height: vh(70), + borderRadius: 40, + padding: 20, + marginLeft: vw(3), + marginRight: vw(3), + display: "flex", + flexDirection: "column", + alignItems: "center", + }, + + scrollView: { + marginTop: "5%", + marginBottom: 70, + }, + + cardTitulo: { + marginTop: 10, + width: vw(70), + color: "#f2f2f2", + textAlign: "left", + fontFamily: "Epilogue_700Bold", + fontSize: 25, + //backgroundColor: "#1a1a1a80", + borderRadius: 8, + //borderWidth: 1, + //borderColor: "#f2f2f2", + }, + + cardResposta: { + marginTop: 10, + width: vw(70), + color: "#f2f2f2", + textAlign: "left", + fontFamily: "Epilogue_500Medium", + fontSize: 17, + backgroundColor: "#1a1a1a60", + borderRadius: 8, + //borderWidth: 1, + // borderColor: "#f2f2f2", + padding: 8, + }, + + elevation: { + elevation: 15, + shadowColor: "#121212", + }, +}); diff --git a/components/BtnAdd/BtnAdd.jsx b/components/BtnAdd/BtnAdd.jsx deleted file mode 100644 index 0611842..0000000 --- a/components/BtnAdd/BtnAdd.jsx +++ /dev/null @@ -1,14 +0,0 @@ -import React from 'react'; -import { View, Text, TouchableOpacity } from 'react-native'; -import { styles } from './BtnAdd.styles'; -//import { BtnAddWrapper } from './BtnAdd.styles'; - -const BtnAdd = (props) => { - return ( - - + - - ); -} - -export default BtnAdd; diff --git a/components/BtnAdd/BtnAdd.styles.js b/components/BtnAdd/BtnAdd.styles.js index a7f4326..0dd2916 100644 --- a/components/BtnAdd/BtnAdd.styles.js +++ b/components/BtnAdd/BtnAdd.styles.js @@ -1,20 +1,37 @@ -import { StyleSheet } from 'react-native'; +import { StyleSheet } from "react-native"; export const styles = StyleSheet.create({ - button: { - backgroundColor: '#f2f2f2', - alignItems:'center', - justifyContent:'center', - width:90, - height:90, - borderRadius:50, - position: 'absolute', - bottom: 20, - right: 20, - }, + button: { + backgroundColor: "#f2f2f2", + alignItems: "center", + justifyContent: "center", + width: 65, + height: 65, + borderRadius: 50, + position: "absolute", + bottom: 20, + right: 125, + }, - plus: { - fontSize: 50, - color: '#1A1A1A', - }, - }); + button_categoria: { + backgroundColor: "#f2f2f2", + alignItems: "center", + justifyContent: "center", + width: 90, + height: 90, + borderRadius: 50, + position: "absolute", + bottom: 20, + right: 20, + }, + + plus: { + fontSize: 40, + color: "#1A1A1A", + }, + + plus_categoria: { + fontSize: 55, + color: "#1A1A1A", + }, +}); diff --git a/components/BtnAdd/BtnAddCard.jsx b/components/BtnAdd/BtnAddCard.jsx new file mode 100644 index 0000000..fdda527 --- /dev/null +++ b/components/BtnAdd/BtnAddCard.jsx @@ -0,0 +1,16 @@ +import React from 'react'; +import { View, Text, TouchableOpacity } from 'react-native'; +import { styles } from './BtnAdd.styles'; +//import { BtnAddWrapper } from './BtnAdd.styles'; +import { Link } from 'react-router-native'; + +const BtnAddCard = (props) => { + + return ( + + + + + ); +} + +export default BtnAddCard; diff --git a/components/BtnAdd/BtnAddCategoria.jsx b/components/BtnAdd/BtnAddCategoria.jsx new file mode 100644 index 0000000..4a4be27 --- /dev/null +++ b/components/BtnAdd/BtnAddCategoria.jsx @@ -0,0 +1,15 @@ +import React from 'react'; +import { View, Text, TouchableOpacity } from 'react-native'; +import { styles } from './BtnAdd.styles'; +//import { BtnAddWrapper } from './BtnAdd.styles'; +import { Link } from 'react-router-native'; + +const BtnAddCategoria = (props) => { + return ( + + + + + ); +} + +export default BtnAddCategoria; diff --git a/components/BtnCategorias/BtnCategorias.jsx b/components/BtnCategorias/BtnCategorias.jsx index 39bdaf9..1a291e7 100644 --- a/components/BtnCategorias/BtnCategorias.jsx +++ b/components/BtnCategorias/BtnCategorias.jsx @@ -3,15 +3,18 @@ import { View, Text, TouchableOpacity } from 'react-native'; import { styles } from './BtnCategorias.styles'; //import { BtnCategoriasWrapper } from './BtnCategorias.styles'; import CategoriasIcon from '../../assets/icons/categorias.svg' +import { Link } from 'react-router-native' const BtnCategorias = (props) => { return ( - - - Categorias - + + + {/**/} + Voltar + + ); } diff --git a/components/BtnCategorias/BtnCategorias.styles.js b/components/BtnCategorias/BtnCategorias.styles.js index 70c0227..f3e30d1 100644 --- a/components/BtnCategorias/BtnCategorias.styles.js +++ b/components/BtnCategorias/BtnCategorias.styles.js @@ -1,26 +1,32 @@ -import { StyleSheet } from 'react-native'; -import { vw, vh, vmin, vmax } from 'react-native-expo-viewport-units'; +import { StyleSheet } from "react-native"; +import { vw, vh, vmin, vmax } from "react-native-expo-viewport-units"; export const styles = StyleSheet.create({ - button: { - backgroundColor: '#f2f2f2', - display: 'flex', - flexDirection: 'row', - padding: 10, - paddingLeft: 20, - paddingRight: 20, - alignItems:'center', - justifyContent:'center', - borderRadius:50, - position: 'absolute', - bottom: 20, - left: 20, - }, + button: { + backgroundColor: "#f2f2f2", + display: "flex", + flexDirection: "row", + padding: 10, + paddingLeft: 20, + paddingRight: 20, + alignItems: "center", + justifyContent: "center", + borderRadius: 50, + position: "absolute", + bottom: 20, + left: 20, + }, - text: { - marginLeft: 10, - fontSize: 20, - color: '#1A1A1A', - fontFamily: 'Epilogue_700Bold', - }, -}); \ No newline at end of file + view: { + display: "flex", + flexDirection: "row", + alignItems: "center", + justifyContent: "center", + }, + + text: { + fontSize: 20, + color: "#1A1A1A", + fontFamily: "Epilogue_700Bold", + }, +}); diff --git a/components/BtnPlay/BtnPlay.jsx b/components/BtnPlay/BtnPlay.jsx new file mode 100644 index 0000000..9e8c02d --- /dev/null +++ b/components/BtnPlay/BtnPlay.jsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { View, Text, TouchableOpacity } from 'react-native'; +import { styles } from './BtnPlay.styles'; +//import { BtnCategoriasWrapper } from './BtnCategorias.styles'; +import Play from '../../assets/icons/play-solid.svg' +import { Link } from 'react-router-native' + + +const BtnCategorias = (props) => { + + return ( + + + + + + ); +} + +export default BtnCategorias; diff --git a/components/BtnPlay/BtnPlay.styles.js b/components/BtnPlay/BtnPlay.styles.js new file mode 100644 index 0000000..010a555 --- /dev/null +++ b/components/BtnPlay/BtnPlay.styles.js @@ -0,0 +1,31 @@ +import { StyleSheet } from "react-native"; +import { vw, vh, vmin, vmax } from "react-native-expo-viewport-units"; + +export const styles = StyleSheet.create({ + button: { + backgroundColor: "#f2f2f2", + display: "flex", + flexDirection: "row", + + padding: 28, + alignItems: "center", + justifyContent: "center", + borderRadius: 50, + position: "absolute", + bottom: 20, + right: 20, + }, + + view: { + display: "flex", + flexDirection: "row", + alignItems: "center", + justifyContent: "center", + }, + + text: { + fontSize: 20, + color: "#1A1A1A", + fontFamily: "Epilogue_700Bold", + }, +}); diff --git a/components/Card/Card.jsx b/components/Card/Card.jsx index e135a29..95f8536 100644 --- a/components/Card/Card.jsx +++ b/components/Card/Card.jsx @@ -1,53 +1,105 @@ import React, { useState } from 'react'; -import { View, Text, ScrollView } from 'react-native'; +import { View, Text, ScrollView, TouchableOpacity, FlatList } from 'react-native'; import { styles } from './Card.styles'; +import { verso_styles } from './Verso.styles'; //import { CardWrapper } from './Card.styles'; import { LinearGradient } from 'expo-linear-gradient'; import LampIconOn from '../../assets/icons/lamp-on.svg'; import LampIconOff from '../../assets/icons/lamp-off.svg'; import StarIcon from '../../assets/icons/star.svg'; +import TurnCardIcon from '../../assets/icons/arrows-rotate-solid.svg' +import TrashIcon from '../../assets/icons/trash-solid.svg' +import CardsDB from '../../services/sqlite/Card' +import DetalhesDB from '../../services/sqlite/Detalhes' +import { Link } from 'react-router-native'; -const Card = (props) => { - const gradientColors = getColors(props.cor) - const [showDica, setShowDica] = useState(false) +class Card extends React.Component { - function getLampIcon(showDica){ - if(showDica == true){ - return ( - - setShowDica(false)} /> - - ); - - }else { - return ( - - setShowDica(true)} /> - - ); - } + state = { + detalhes: [], + id: this.props.id, + categoriaId: this.props.categoriaId, + categoriaNome: this.props.categoriaNome, + cor: this.props.cor, + titulo: this.props.titulo, + resposta: this.props.resposta, + isTurned: false + } + + componentDidMount() { + this.getDetalhes(); } + getDetalhes = () => { + DetalhesDB.allDetalhesCard(this.state.id).then(res => { + this.setState({ + detalhes: res, + }); + }); + } + + render (){ + const gradientColors = getColors(this.state.cor) + const renderDetalhe = ({item}) => { + return ( + + {item.titulo} + {item.resposta} + + ); +} return ( - - + + + + + {this.state.isTurned ? verso(this.state): frente(this.state)} + {console.log(`/confirm-delete/Card/${this.state.categoriaId}/${this.state.categoriaNome}/${this.state.cor}/${this.state.titulo}/${this.state.id}`)} + + + + + this.setState({ + isTurned: this.state.isTurned ? false : true, + })}> + + + + + + ); + + function frente(card){ + return( - - {props.titulo} - {returnDica(showDica, styles, props.dica)} + + {card.titulo} + + + ) + } + + function verso(card){ + return( + // Constrói a visualização do card + + {card.titulo} + {card.resposta} + {(card.detalhes.length > 0) ? Detalhes : null} + item.id} + contentContainerStyle={styles.cardList}> + - - {getLampIcon(showDica)} - - - - - -); + ); + } + } } function getColors(colorStr){ @@ -57,30 +109,29 @@ function getColors(colorStr){ } -function getLampIcon(showDica){ - if(showDica == true){ - return ( - - ); - - }else { - return ( - - ); - } +function deleteCard(cardId){ + + //delete + CardsDB.removeCard(cardId) + .then( id => { + console.log('Card deleted with id: '+ id) + deleteDetalhes(cardId) + }) + .catch( err => console.log(err) ) + + } -function returnDica(showDica, styles, dica) { - if(showDica == true){ - return ( - - {dica} - ); - }else{ - return ( - - ); - } +function deleteDetalhes(cardId){ + + //delete + DetalhesDB.removeDetalhe(cardId) + .then( cardId => { + console.log('Detalhes deleted with cardId: '+ cardId) + }) + .catch( err => console.log(err) ) + + } export default Card; diff --git a/components/Card/Card.styles.js b/components/Card/Card.styles.js index a331d08..56ac845 100644 --- a/components/Card/Card.styles.js +++ b/components/Card/Card.styles.js @@ -5,7 +5,7 @@ export const styles = StyleSheet.create({ cardBody: { flex: 1, width: vw(80), - height: vh(65), + height: vh(68), borderRadius: 40, padding: 20, marginLeft: vw(3), diff --git a/components/Card/Verso.styles.js b/components/Card/Verso.styles.js new file mode 100644 index 0000000..ca1e1de --- /dev/null +++ b/components/Card/Verso.styles.js @@ -0,0 +1,193 @@ +import { StyleSheet } from "react-native"; +import { vw, vh, vmin, vmax } from "react-native-expo-viewport-units"; + +export const verso_styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: "#1a1a1a", + width: "100%", + height: "100%", + alignItems: "center", + }, + + verse_button: { + position: "absolute", + right: 23, + bottom: 23, + }, + + trash_button: { + position: "absolute", + left: 23, + //top: 0, + bottom: 23, + backgroundColor: "#c0392b", + padding: 15, + borderRadius: 50, + }, + + header_detalhe: { + marginTop: 20, + display: "flex", + flexDirection: "row", + alignItems: "center", + justifyContent: "space-between", + }, + + close_detalhe: { + backgroundColor: "#c0392b", + padding: 4, + paddingTop: 0, + width: 32, + borderRadius: 50, + }, + + cardTituloDetalhe: { + width: vw(70), + color: "#f2f2f2", + textAlign: "left", + fontFamily: "Epilogue_700Bold", + fontSize: 17, + //borderBottomWidth: 2, + //borderBottomColor: "#f2f2f2", + }, + + btn_card: { + position: "absolute", + bottom: 20, + backgroundColor: "#1a1a1a", + borderRadius: 50, + textAlign: "center", + padding: 12, + }, + + menu_footer: { + height: vh(10), + width: "100%", + }, + + btn_text: { + color: "#f2f2f2", + fontFamily: "Epilogue_500Medium", + fontSize: 20, + width: vw(36), + textAlign: "center", + }, + + btn_card_text: { + color: "#f2f2f2", + fontFamily: "Epilogue_500Medium", + fontSize: 20, + textAlign: "center", + width: vw(70), + }, + + btn_card_text_x: { + color: "#f2f2f2", + fontFamily: "Epilogue_500Medium", + fontSize: 20, + textAlign: "center", + }, + + btn_right: { + position: "absolute", + right: 20, + bottom: 20, + }, + + btn_left: { + position: "absolute", + left: 20, + bottom: 20, + backgroundColor: "#c0392b", + }, + + btn_layout: { + backgroundColor: "#16a085", + padding: 10, + borderRadius: 50, + }, + + header: { + width: "100%", + }, + + titulo: { + color: "#f2f2f2", + marginLeft: 20, + marginTop: 20, + fontFamily: "Epilogue_500Medium", + fontSize: 40, + }, + + categoria: { + display: "flex", + flexDirection: "row", + alignItems: "center", + marginLeft: 20, + marginTop: 10, + }, + + categoryText: { + color: "#f2f2f2", + marginLeft: 10, + fontFamily: "Epilogue_500Medium", + fontSize: 23, + }, + + categoryItem: { + marginTop: 10, + borderRadius: 10, + width: "100%", + }, + + cardBody: { + flex: 1, + width: vw(90), + height: vh(70), + borderRadius: 40, + padding: 20, + marginLeft: vw(3), + marginRight: vw(3), + display: "flex", + flexDirection: "column", + alignItems: "center", + }, + + scrollView: { + marginTop: "5%", + marginBottom: 70, + }, + + cardTitulo: { + marginTop: 10, + width: vw(70), + color: "#f2f2f2", + textAlign: "left", + fontFamily: "Epilogue_700Bold", + fontSize: 25, + //backgroundColor: "#1a1a1a80", + borderRadius: 8, + //borderWidth: 1, + //borderColor: "#f2f2f2", + }, + + cardResposta: { + marginTop: 10, + width: vw(70), + color: "#f2f2f2", + textAlign: "left", + fontFamily: "Epilogue_500Medium", + fontSize: 17, + backgroundColor: "#1a1a1a60", + borderRadius: 8, + //borderWidth: 1, + // borderColor: "#f2f2f2", + padding: 8, + }, + + elevation: { + elevation: 15, + shadowColor: "#121212", + }, +}); diff --git a/components/CardList/CardList.jsx b/components/CardList/CardList.jsx index a61cbcb..35828c0 100644 --- a/components/CardList/CardList.jsx +++ b/components/CardList/CardList.jsx @@ -5,66 +5,44 @@ import { styles } from './CardList.styles'; import * as cards from '../test/cards.json'; import * as favoritos from '../test/favoritos.json'; import Card from '../Card/Card'; - -const CardList = (props) => { - - const renderCard = ({item}) => { - - return ( - - ); +import CardsDB from '../../services/sqlite/Card' + +class CardList extends React.Component { + + state = { + categoriaId: this.props.categoriaId, + categoriaNome: this.props.categoriaNome, + cor: this.props.cor, } - return ( - item.cardId} - contentContainerStyle={styles.cardList}> - - ); -} - -function getCardsByCategoryId(categoryId) { - var cardsObj = []; - - if(categoryId == "a"){ - for(var i=0; i < (Object.keys(cards).length - 1) ; i++){ - cardsObj.push(cards[i]); - } - }else if(categoryId == "f"){ - let favoritosIds = getFavoritosCardIds() - - var array = ["pal1", "pal2", "pal3"] - for(var pos in favoritosIds){ - - for(var i=0; i < (Object.keys(cards).length - 1); i++){ - - if(cards[i].cardId == favoritosIds[pos]){ - console.log(cards[i].titulo) - cardsObj.push(cards[i]) - } - } - } - - }else{ - for(var i=0; i < (Object.keys(cards).length - 1); i++){ - if(cards[i].categoriaId == categoryId){ - cardsObj.push(cards[i]) - } - } + componentDidMount() { + this.getCards(); } - return cardsObj -} - -function getFavoritosCardIds(){ - var favoritosIds = [] - for(var i=0; i < (Object.keys(favoritos).length - 1); i++){ - favoritosIds.push(favoritos[i].cardId) + getCards = () => { + CardsDB.allCardsCategory(this.state.categoriaId).then(res => { + this.setState({ + cards: res, + }); + }); + } + render(){ + const renderCard = ({item}) => { + return ( + + ); + } + return ( + item.id} + contentContainerStyle={styles.cardList}> + + ); } - return favoritosIds } export default CardList; diff --git a/components/Categoria/Categoria.jsx b/components/Categoria/Categoria.jsx new file mode 100644 index 0000000..7ab81cf --- /dev/null +++ b/components/Categoria/Categoria.jsx @@ -0,0 +1,22 @@ +import React from 'react'; +import { View, Text, ScrollView, FlatList } from 'react-native'; +import { styles } from './Categoria.styles'; +//import { CategoriasWrapper } from './Categorias.styles'; +import CardsIcon from '../../assets/icons/cards.svg' + +const Categoria = (props) => { + color = "#" + props.cor.split("-")[0] + return( + + {props.nome} + + + {props.quantCards} + + + ); + +} + +export default Categoria; diff --git a/components/Categoria/Categoria.styles.js b/components/Categoria/Categoria.styles.js new file mode 100644 index 0000000..32f8a1c --- /dev/null +++ b/components/Categoria/Categoria.styles.js @@ -0,0 +1,36 @@ +import { StyleSheet } from "react-native"; +import { vw, vh, vmin, vmax } from "react-native-expo-viewport-units"; + +export const styles = StyleSheet.create({ + nome: { + marginTop: 10, + color: "#f2f2f2", + textAlign: "center", + fontFamily: "Epilogue_500Medium", + fontSize: 20, + }, + categoria: { + display: "flex", + flexDirection: "row", + justifyContent: "space-between", + padding: 20, + alignItems: "center", + backgroundColor: "#111", + borderRadius: 8, + marginBottom: 15, + borderLeftWidth: 10, + }, + + textQuantCards: { + color: "#f2f2f2", + fontFamily: "Epilogue_500Medium", + fontSize: 20, + marginLeft: 5, + }, + + quantCards: { + display: "flex", + flexDirection: "row", + alignItems: "center", + }, +}); diff --git a/components/Categorias/Categorias.jsx b/components/Categorias/Categorias.jsx deleted file mode 100644 index 0e6488b..0000000 --- a/components/Categorias/Categorias.jsx +++ /dev/null @@ -1,77 +0,0 @@ -import React, { PureComponent } from 'react'; -import { View, Text } from 'react-native'; -import { connect } from 'react-redux'; -import PropTypes from 'prop-types'; -import * as styles from './Categorias.styles'; -//import { CategoriasWrapper } from './Categorias.styles'; - -class Categorias extends PureComponent { - constructor(props) { - super(props); - - this.state = { - hasError: false, - }; - } - - componentWillMount = () => { - console.log('Categorias will mount'); - } - - componentDidMount = () => { - console.log('Categorias mounted'); - } - - componentWillReceiveProps = (nextProps) => { - console.log('Categorias will receive props', nextProps); - } - - componentWillUpdate = (nextProps, nextState) => { - console.log('Categorias will update', nextProps, nextState); - } - - - componentDidUpdate = () => { - console.log('Categorias did update'); - } - - componentWillUnmount = () => { - console.log('Categorias will unmount'); - } - - render () { - if (this.state.hasError) { - return ( - - Something went wrong. - - ); - } - return ( - - Test content - - ); - } -} - -Categorias.propTypes = { - // bla: PropTypes.string, -}; - -Categorias.defaultProps = { - // bla: 'test', -}; - -const mapStateToProps = state => ({ - // blabla: state.blabla, -}); - -const mapDispatchToProps = dispatch => ({ - // fnBlaBla: () => dispatch(action.name()), -}); - -export default connect( - mapStateToProps, - mapDispatchToProps, -)(Categorias); diff --git a/components/Categorias/Categorias.styles.js b/components/Categorias/Categorias.styles.js deleted file mode 100644 index 80a725e..0000000 --- a/components/Categorias/Categorias.styles.js +++ /dev/null @@ -1,5 +0,0 @@ -import styled from 'styled-components/native'; - -export const CategoriasWrapper = styled.View` - flex: 1 -`; diff --git a/components/Categorias/index.js b/components/Categorias/index.js deleted file mode 100644 index fb8fb14..0000000 --- a/components/Categorias/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import Categorias from './Categorias'; - -export default Categorias; diff --git a/components/CategoriasList/CategoriasList.jsx b/components/CategoriasList/CategoriasList.jsx index 8f50cf3..91d9b8d 100644 --- a/components/CategoriasList/CategoriasList.jsx +++ b/components/CategoriasList/CategoriasList.jsx @@ -1,64 +1,54 @@ -import React, { PureComponent } from 'react'; -import { View, Text } from 'react-native'; -import PropTypes from 'prop-types'; -import * as styles from './CategoriasList.styles'; -//import { CategoriasListWrapper } from './CategoriasList.styles'; +import React from 'react'; +import { View, Text, ScrollView, FlatList, TouchableOpacity } from 'react-native'; +import { styles } from './CategoriasList.styles'; +//import { CardListWrapper } from './CardList.styles'; +import Categoria from '../Categoria/Categoria'; +import CategoriaDB from '../../services/sqlite/Categoria' +import CardDB from '../../services/sqlite/Card' +import { Link } from 'react-router-native' -class CategoriasList extends PureComponent { - constructor(props) { - super(props); +class CategoriasList extends React.Component { - this.state = { - hasError: false, - }; + state = { + categorias: [], } - componentWillMount = () => { - console.log('CategoriasList will mount'); + componentDidMount() { + this.getCategorias(); } - componentDidMount = () => { - console.log('CategoriasList mounted'); + getCategorias = () => { + CategoriaDB.allCategorias().then(res => { + this.setState({ + categorias: res, + }); + }); } - componentWillReceiveProps = (nextProps) => { - console.log('CategoriasList will receive props', nextProps); - } - - componentWillUpdate = (nextProps, nextState) => { - console.log('CategoriasList will update', nextProps, nextState); - } - - componentDidUpdate = () => { - console.log('CategoriasList did update'); - } - - componentWillUnmount = () => { - console.log('CategoriasList will unmount'); - } - - render () { - if (this.state.hasError) { + render() { + const renderCategoria = ({item}) => { return ( - - Something went wrong. - + console.log(item.nome)}> + + ); } + if (Object.keys(this.state.categorias).length > 0){ return ( - - Test content - - ); - } + item.id} + contentContainerStyle={styles.categoriasList}> + + + ); +}else{ + return( + Crie uma nova categoria + ); + } + } } -CategoriasList.propTypes = { - // bla: PropTypes.string, -}; - -CategoriasList.defaultProps = { - // bla: 'test', -}; - export default CategoriasList; diff --git a/components/CategoriasList/CategoriasList.styles.js b/components/CategoriasList/CategoriasList.styles.js index 329bd39..0113bcf 100644 --- a/components/CategoriasList/CategoriasList.styles.js +++ b/components/CategoriasList/CategoriasList.styles.js @@ -1,5 +1,17 @@ -import styled from 'styled-components/native'; +import { StyleSheet } from "react-native"; +import { vw, vh, vmin, vmax } from "react-native-expo-viewport-units"; -export const CategoriasListWrapper = styled.View` - flex: 1 -`; +export const styles = StyleSheet.create({ + categoriasList: { + paddingLeft: 20 - vw(3), + paddingRight: 20 - vw(3), + }, + + semCategoriasMensagem: { + marginTop: 10, + color: "#f2f2f2", + textAlign: "center", + fontFamily: "Epilogue_500Medium", + fontSize: 20, + }, +}); diff --git a/components/ConfirmDelete/ConfirmDelete.jsx b/components/ConfirmDelete/ConfirmDelete.jsx new file mode 100644 index 0000000..bd9a29b --- /dev/null +++ b/components/ConfirmDelete/ConfirmDelete.jsx @@ -0,0 +1,58 @@ +import React from 'react'; +import { View, Text, TouchableOpacity } from 'react-native'; +import { styles } from './ConfirmDelete.styles'; +//import { BtnAddWrapper } from './BtnAdd.styles'; +import { useParams, Link } from 'react-router-native'; +import CardsDB from '../../services/sqlite/Card' +import DetalhesDB from '../../services/sqlite/Detalhes' + +const ConfirmDelete = (props) => { + + const { who, categoriaId, categoriaNome, cor, nome, id } = useParams() + console.log(props) + "/home-categoria/:id/:cor/:nome" + return( + + + Deseja realmente excluir {(who == "Card") ? `o card "${nome}"?` : `a categoria "${nome}"?`} + + (who == "Card") ? deleteCard(id) : null}> + Sim + + + Não, voltar + + + + + ); +} + + + +function deleteCard(cardId){ + + //delete + CardsDB.removeCard(cardId) + .then( id => { + console.log('Card deleted with id: '+ id) + deleteDetalhes(cardId) + }) + .catch( err => console.log(err) ) + + +} + +function deleteDetalhes(cardId){ + + //delete + DetalhesDB.removeDetalhe(cardId) + .then( cardId => { + console.log('Detalhes deleted with cardId: '+ cardId) + }) + .catch( err => console.log(err) ) + + +} + +export default ConfirmDelete; diff --git a/components/ConfirmDelete/ConfirmDelete.styles.js b/components/ConfirmDelete/ConfirmDelete.styles.js new file mode 100644 index 0000000..ef62c25 --- /dev/null +++ b/components/ConfirmDelete/ConfirmDelete.styles.js @@ -0,0 +1,58 @@ +import { StyleSheet } from "react-native"; +import { vw, vh, vmin, vmax } from "react-native-expo-viewport-units"; + +export const styles = StyleSheet.create({ + backgroud: { + flex: 1, + backgroundColor: "#1a1a1a", + width: "100%", + height: "100%", + justifyContent: "center", + }, + + modal: { + backgroundColor: "#2a2a2a", + padding: 20, + margin: 20, + borderRadius: 38, + }, + + btn_container: { + display: "flex", + flexDirection: "row", + justifyContent: "space-between", + }, + + categoryText: { + color: "#f2f2f2", + fontFamily: "Epilogue_500Medium", + fontSize: 25, + marginBottom: 40, + }, + + plus: { + fontSize: 50, + color: "#1A1A1A", + }, + + btn_text: { + color: "#f2f2f2", + fontFamily: "Epilogue_700Bold", + fontSize: 17, + width: vw(32), + textAlign: "center", + }, + + btn_right: { + backgroundColor: "#16a085", + }, + + btn_left: { + backgroundColor: "#c0392b", + }, + + btn_layout: { + padding: 10, + borderRadius: 50, + }, +}); diff --git a/components/Home/Home.jsx b/components/Home/Home.jsx index 48fdba6..943b739 100644 --- a/components/Home/Home.jsx +++ b/components/Home/Home.jsx @@ -1,43 +1,25 @@ import React from 'react'; import { View, Text } from 'react-native'; import { styles } from './Home.styles'; -import BtnAdd from '../BtnAdd/BtnAdd'; +import BtnAddCategoria from '../BtnAdd/BtnAddCategoria'; import BtnCategorias from '../BtnCategorias/BtnCategorias'; import BtnFavoritos from '../BtnFavoritos/BtnFavoritos'; -import CardList from '../CardList/CardList'; +import CategoriasList from '../CategoriasList/CategoriasList'; import SearchIcon from '../../assets/icons/search.svg' import * as categorias from '../test/categorias.json'; const Home = (props) => { - var categoryName = getCategoryName(props.route.params.categoryId) return ( - {categoryName} + Decks - + - - + ); } -function getCategoryName(categoryId){ - // puxar os dados da categoria no BD - if(categoryId == "a"){ - return "Todos" - }else if(categoryId == "f"){ - return "Favoritos" - }else{ - for(var i=0; i < Object.keys(categorias).length; i++){ - if(categorias[i].categoriaId == categoryId){ - console.log(categorias[i].nome) - return categorias[i].nome - } - } - } -} - export default Home; \ No newline at end of file diff --git a/components/HomeCategoria/HomeCategoria.jsx b/components/HomeCategoria/HomeCategoria.jsx new file mode 100644 index 0000000..b5922a1 --- /dev/null +++ b/components/HomeCategoria/HomeCategoria.jsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { View, Text } from 'react-native'; +import { styles } from './HomeCategoria.styles'; +import BtnAddCard from '../BtnAdd/BtnAddCard'; +import BtnPlay from '../BtnPlay/BtnPlay'; +import BtnCategorias from '../BtnCategorias/BtnCategorias'; +import BtnFavoritos from '../BtnFavoritos/BtnFavoritos'; +import CardList from '../CardList/CardList'; +import SearchIcon from '../../assets/icons/search.svg' +import { useParams, Link } from 'react-router-native' +import * as categorias from '../test/categorias.json'; + +const HomeCategoria = (props) => { + const { id, cor, nome } = useParams() + return ( + + {nome} + + + + + + + + + ); +} + +export default HomeCategoria; \ No newline at end of file diff --git a/components/HomeCategoria/HomeCategoria.styles.js b/components/HomeCategoria/HomeCategoria.styles.js new file mode 100644 index 0000000..02b7f66 --- /dev/null +++ b/components/HomeCategoria/HomeCategoria.styles.js @@ -0,0 +1,30 @@ +import { StyleSheet } from 'react-native'; +import { vw, vh, vmin, vmax } from 'react-native-expo-viewport-units'; + +export const styles = StyleSheet.create({ + home: { + flex: 1, + backgroundColor: '#1a1a1a', + width: '100%', + height: '100%', + }, + + categoryText: { + color: '#f2f2f2', + marginLeft: 20, + marginTop: 20, + fontFamily: 'Epilogue_500Medium', + fontSize: 40, + }, + + searchIcon: { + position: 'absolute', + top: 30, + right: 30, + }, + + cardList: { + height: '100%', + marginTop: '5%', + } + }); diff --git a/package.json b/package.json index 872b9c0..e1b53a3 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "expo-font": "~10.0.4", "expo-linear-gradient": "~11.0.1", "expo-splash-screen": "~0.14.1", + "expo-sqlite": "~10.1.0", "expo-status-bar": "~1.2.0", "react": "17.0.1", "react-dom": "17.0.1", @@ -27,7 +28,7 @@ "react-native-screens": "~3.10.1", "react-native-svg": "12.1.1", "react-native-web": "0.17.1", - "react-router-native": "^6.2.1", + "react-router-native": "^6.3.0", "rn-faded-scrollview": "^1.0.12", "styled-components": "^5.3.3" }, diff --git a/services/sqlite/Card.js b/services/sqlite/Card.js new file mode 100644 index 0000000..bf82301 --- /dev/null +++ b/services/sqlite/Card.js @@ -0,0 +1,182 @@ +/* +- id +- titulo +- resposta +- categoriaId + */ + +import db from "./SQLiteDatabase"; + +/** + * INICIALIZAÇÃO DA TABELA + * - Executa sempre, mas só cria a tabela caso não exista (primeira execução) + */ +db.transaction((tx) => { + //<<<<<<<<<<<<<<<<<<<<<<<< USE ISSO APENAS DURANTE OS TESTES!!! >>>>>>>>>>>>>>>>>>>>>>> + //tx.executeSql("DROP TABLE cars;"); + //<<<<<<<<<<<<<<<<<<<<<<<< USE ISSO APENAS DURANTE OS TESTES!!! >>>>>>>>>>>>>>>>>>>>>>> + + tx.executeSql( + "CREATE TABLE IF NOT EXISTS cards (id INTEGER PRIMARY KEY AUTOINCREMENT, titulo TEXT, resposta TEXT, categoriaId INT);" + ); +}); + +/** + * CRIAÇÃO DE UM NOVO REGISTRO + * - Recebe um objeto; + * - Retorna uma Promise: + * - O resultado da Promise é o ID do registro (criado por AUTOINCREMENT) + * - Pode retornar erro (reject) caso exista erro no SQL ou nos parâmetros. + */ +const createCard = (obj) => { + return new Promise((resolve, reject) => { + db.transaction((tx) => { + //comando SQL modificável + tx.executeSql( + "INSERT INTO cards (titulo, resposta, categoriaId) values (?, ?, ?);", + [obj.titulo, obj.resposta, obj.categoriaId], + //----------------------- + (_, { rowsAffected, insertId }) => { + if (rowsAffected > 0) resolve(insertId); + else reject("Error inserting obj: " + JSON.stringify(obj)); // insert falhou + }, + (_, error) => reject(error) // erro interno em tx.executeSql + ); + }); + }); +}; + +/** + * ATUALIZA UM REGISTRO JÁ EXISTENTE + * - Recebe o ID do registro e um OBJETO com valores atualizados; + * - Retorna uma Promise: + * - O resultado da Promise é a quantidade de registros atualizados; + * - Pode retornar erro (reject) caso o ID não exista ou então caso ocorra erro no SQL. + */ +const updateCard = (id, obj) => { + return new Promise((resolve, reject) => { + db.transaction((tx) => { + //comando SQL modificável + tx.executeSql( + "UPDATE cars SET titulo=?, resposta=? WHERE id=?;", + [obj.titulo, obj.resposta, id], + //----------------------- + (_, { rowsAffected }) => { + if (rowsAffected > 0) resolve(rowsAffected); + else reject("Error updating obj: id=" + id); // nenhum registro alterado + }, + (_, error) => reject(error) // erro interno em tx.executeSql + ); + }); + }); +}; + +/** + * BUSCA UM REGISTRO POR MEIO DO ID + * - Recebe o ID do registro; + * - Retorna uma Promise: + * - O resultado da Promise é o objeto (caso exista); + * - Pode retornar erro (reject) caso o ID não exista ou então caso ocorra erro no SQL. + */ +const findCard = (id) => { + return new Promise((resolve, reject) => { + db.transaction((tx) => { + //comando SQL modificável + tx.executeSql( + "SELECT * FROM cards WHERE id=?;", + [id], + //----------------------- + (_, { rows }) => { + if (rows.length > 0) resolve(rows._array[0]); + else reject("Obj not found: id=" + id); // nenhum registro encontrado + }, + (_, error) => reject(error) // erro interno em tx.executeSql + ); + }); + }); +}; + +/** + * BUSCA UM REGISTRO POR MEIO DO TITULO (brand) + * - Recebe a marca do carro; + * - Retorna uma Promise: + * - O resultado da Promise é um array com os objetos encontrados; + * - Pode retornar erro (reject) caso o ID não exista ou então caso ocorra erro no SQL; + * - Pode retornar um array vazio caso nenhum objeto seja encontrado. + */ +const findCardByTitulo = (brand) => { + return new Promise((resolve, reject) => { + db.transaction((tx) => { + //comando SQL modificável + tx.executeSql( + "SELECT * FROM cards WHERE titulo LIKE %?%;", + [brand], + //----------------------- + (_, { rows }) => { + if (rows.length > 0) resolve(rows._array); + else reject("Obj not found: titulo=" + brand); // nenhum registro encontrado + }, + (_, error) => reject(error) // erro interno em tx.executeSql + ); + }); + }); +}; + +/** + * BUSCA TODOS OS REGISTROS DE UMA DETERMINADA TABELA + * - Não recebe parâmetros; + * - Retorna uma Promise: + * - O resultado da Promise é uma lista (Array) de objetos; + * - Pode retornar erro (reject) caso o ID não exista ou então caso ocorra erro no SQL; + * - Pode retornar um array vazio caso não existam registros. + */ +const allCardsCategory = (categoriaId) => { + return new Promise((resolve, reject) => { + db.transaction((tx) => { + //comando SQL modificável + tx.executeSql( + "SELECT * FROM cards WHERE categoriaId=?;", + [categoriaId], + //----------------------- + (_, { rows }) => { + if (rows.length > 0) resolve(rows._array); + else reject("Obj not found: categoriaId=" + categoriaId); // nenhum registro encontrado + }, + (_, error) => reject(error) // erro interno em tx.executeSql + ); + }); + }); +}; + +/** + * REMOVE UM REGISTRO POR MEIO DO ID + * - Recebe o ID do registro; + * - Retorna uma Promise: + * - O resultado da Promise a quantidade de registros removidos (zero indica que nada foi removido); + * - Pode retornar erro (reject) caso o ID não exista ou então caso ocorra erro no SQL. + */ +const removeCard = (id) => { + return new Promise((resolve, reject) => { + db.transaction((tx) => { + //comando SQL modificável + tx.executeSql( + "DELETE FROM cards WHERE id=?;", + [id], + //----------------------- + (_, { rowsAffected }) => { + resolve(rowsAffected); + }, + (_, error) => reject(error) // erro interno em tx.executeSql + ); + }); + }); +}; + +export default { + createCard, + updateCard, + findCard, + findCardByTitulo, + allCardsCategory, + removeCard, +}; diff --git a/services/sqlite/Categoria.js b/services/sqlite/Categoria.js new file mode 100644 index 0000000..c6c3969 --- /dev/null +++ b/services/sqlite/Categoria.js @@ -0,0 +1,159 @@ +/* +-id +-cor +-nome + */ + +// Criar tabela + +// Criar categoria + +// Excluir categoria + +// Atualizar categoria + +import db from "./SQLiteDatabase"; + +/** + * INICIALIZAÇÃO DA TABELA + * - Executa sempre, mas só cria a tabela caso não exista (primeira execução) + */ +db.transaction((tx) => { + //<<<<<<<<<<<<<<<<<<<<<<<< USE ISSO APENAS DURANTE OS TESTES!!! >>>>>>>>>>>>>>>>>>>>>>> + //tx.executeSql("DROP TABLE cars;"); + //<<<<<<<<<<<<<<<<<<<<<<<< USE ISSO APENAS DURANTE OS TESTES!!! >>>>>>>>>>>>>>>>>>>>>>> + + tx.executeSql( + "CREATE TABLE IF NOT EXISTS categorias (id INTEGER PRIMARY KEY AUTOINCREMENT, cor TEXT, nome TEXT);" + ); +}); + +/** + * CRIAÇÃO DE UM NOVO REGISTRO + * - Recebe um objeto; + * - Retorna uma Promise: + * - O resultado da Promise é o ID do registro (criado por AUTOINCREMENT) + * - Pode retornar erro (reject) caso exista erro no SQL ou nos parâmetros. + */ +const createCategoria = (obj) => { + return new Promise((resolve, reject) => { + db.transaction((tx) => { + //comando SQL modificável + tx.executeSql( + "INSERT INTO categorias (cor, nome) values (?, ?);", + [obj.cor, obj.nome], + //----------------------- + (_, { rowsAffected, insertId }) => { + if (rowsAffected > 0) resolve(insertId); + else reject("Error inserting obj: " + JSON.stringify(obj)); // insert falhou + }, + (_, error) => reject(error) // erro interno em tx.executeSql + ); + }); + }); +}; + +/** + * ATUALIZA UM REGISTRO JÁ EXISTENTE + * - Recebe o ID do registro e um OBJETO com valores atualizados; + * - Retorna uma Promise: + * - O resultado da Promise é a quantidade de registros atualizados; + * - Pode retornar erro (reject) caso o ID não exista ou então caso ocorra erro no SQL. + */ +const updateCategoria = (id, obj) => { + return new Promise((resolve, reject) => { + db.transaction((tx) => { + //comando SQL modificável + tx.executeSql( + "UPDATE categorias SET cor=?, nome=? WHERE id=?;", + [obj.cor, obj.nome, id], + //----------------------- + (_, { rowsAffected }) => { + if (rowsAffected > 0) resolve(rowsAffected); + else reject("Error updating obj: id=" + id); // nenhum registro alterado + }, + (_, error) => reject(error) // erro interno em tx.executeSql + ); + }); + }); +}; + +/** + * BUSCA UM REGISTRO POR MEIO DO ID + * - Recebe o ID do registro; + * - Retorna uma Promise: + * - O resultado da Promise é o objeto (caso exista); + * - Pode retornar erro (reject) caso o ID não exista ou então caso ocorra erro no SQL. + */ +const findCategoria = (id) => { + return new Promise((resolve, reject) => { + db.transaction((tx) => { + //comando SQL modificável + tx.executeSql( + "SELECT * FROM categorias WHERE id=?;", + [id], + //----------------------- + (_, { rows }) => { + if (rows.length > 0) resolve(rows._array[0]); + else reject("Obj not found: id=" + id); // nenhum registro encontrado + }, + (_, error) => reject(error) // erro interno em tx.executeSql + ); + }); + }); +}; + +/** + * BUSCA TODOS OS REGISTROS DE UMA DETERMINADA TABELA + * - Não recebe parâmetros; + * - Retorna uma Promise: + * - O resultado da Promise é uma lista (Array) de objetos; + * - Pode retornar erro (reject) caso o ID não exista ou então caso ocorra erro no SQL; + * - Pode retornar um array vazio caso não existam registros. + */ +const allCategorias = () => { + return new Promise((resolve, reject) => { + db.transaction((tx) => { + //comando SQL modificável + tx.executeSql( + "SELECT cat.*, COUNT(c.id) as quantCards FROM categorias as cat LEFT JOIN cards as c ON cat.id = c.categoriaId GROUP BY cat.id;", + [], + //----------------------- + (_, { rows }) => resolve(rows._array), + (_, error) => reject(error) // erro interno em tx.executeSql + ); + }); + }); +}; + +/** + * REMOVE UM REGISTRO POR MEIO DO ID + * - Recebe o ID do registro; + * - Retorna uma Promise: + * - O resultado da Promise a quantidade de registros removidos (zero indica que nada foi removido); + * - Pode retornar erro (reject) caso o ID não exista ou então caso ocorra erro no SQL. + */ +const removeCategoria = (id) => { + return new Promise((resolve, reject) => { + db.transaction((tx) => { + //comando SQL modificável + tx.executeSql( + "DELETE FROM categoria WHERE id=?; DELETE FROM cards WHERE categoriaId=?", + [id, id], + //----------------------- + (_, { rowsAffected }) => { + resolve(rowsAffected); + }, + (_, error) => reject(error) // erro interno em tx.executeSql + ); + }); + }); +}; + +export default { + createCategoria, + updateCategoria, + findCategoria, + allCategorias, + removeCategoria, +}; diff --git a/services/sqlite/Detalhes.js b/services/sqlite/Detalhes.js new file mode 100644 index 0000000..a0bdc36 --- /dev/null +++ b/services/sqlite/Detalhes.js @@ -0,0 +1,170 @@ +/* +-id +-cardId +-titulo +-resposta + */ + +// Criar tabela + +// Criar detalhe + +// Excluir detalhe + +// Atualizar detalhe + +/* +- id +- titulo +- resposta +- categoriaId + */ + +import db from "./SQLiteDatabase"; + +/** + * INICIALIZAÇÃO DA TABELA + * - Executa sempre, mas só cria a tabela caso não exista (primeira execução) + */ +db.transaction((tx) => { + //<<<<<<<<<<<<<<<<<<<<<<<< USE ISSO APENAS DURANTE OS TESTES!!! >>>>>>>>>>>>>>>>>>>>>>> + //tx.executeSql("DROP TABLE cars;"); + //<<<<<<<<<<<<<<<<<<<<<<<< USE ISSO APENAS DURANTE OS TESTES!!! >>>>>>>>>>>>>>>>>>>>>>> + + tx.executeSql( + "CREATE TABLE IF NOT EXISTS detalhes (id INTEGER PRIMARY KEY AUTOINCREMENT, titulo TEXT, resposta TEXT, cardId INT);" + ); +}); + +/** + * CRIAÇÃO DE UM NOVO REGISTRO + * - Recebe um objeto; + * - Retorna uma Promise: + * - O resultado da Promise é o ID do registro (criado por AUTOINCREMENT) + * - Pode retornar erro (reject) caso exista erro no SQL ou nos parâmetros. + */ +const createDetalhe = (obj) => { + return new Promise((resolve, reject) => { + db.transaction((tx) => { + //comando SQL modificável + tx.executeSql( + "INSERT INTO detalhes (titulo, resposta, cardId) values (?, ?, ?);", + [obj.titulo, obj.resposta, obj.cardId], + //----------------------- + (_, { rowsAffected, insertId }) => { + if (rowsAffected > 0) resolve(insertId); + else reject("Error inserting obj: " + JSON.stringify(obj)); // insert falhou + }, + (_, error) => reject(error) // erro interno em tx.executeSql + ); + }); + }); +}; + +/** + * ATUALIZA UM REGISTRO JÁ EXISTENTE + * - Recebe o ID do registro e um OBJETO com valores atualizados; + * - Retorna uma Promise: + * - O resultado da Promise é a quantidade de registros atualizados; + * - Pode retornar erro (reject) caso o ID não exista ou então caso ocorra erro no SQL. + */ +const updateDetalhe = (id, obj) => { + return new Promise((resolve, reject) => { + db.transaction((tx) => { + //comando SQL modificável + tx.executeSql( + "UPDATE detalhes SET titulo=?, resposta=? WHERE id=?;", + [obj.titulo, obj.resposta, id], + //----------------------- + (_, { rowsAffected }) => { + if (rowsAffected > 0) resolve(rowsAffected); + else reject("Error updating obj: id=" + id); // nenhum registro alterado + }, + (_, error) => reject(error) // erro interno em tx.executeSql + ); + }); + }); +}; + +/** + * BUSCA UM REGISTRO POR MEIO DO ID + * - Recebe o ID do registro; + * - Retorna uma Promise: + * - O resultado da Promise é o objeto (caso exista); + * - Pode retornar erro (reject) caso o ID não exista ou então caso ocorra erro no SQL. + */ +const findDetalhe = (id) => { + return new Promise((resolve, reject) => { + db.transaction((tx) => { + //comando SQL modificável + tx.executeSql( + "SELECT * FROM detalhes WHERE id=?;", + [id], + //----------------------- + (_, { rows }) => { + if (rows.length > 0) resolve(rows._array[0]); + else reject("Obj not found: id=" + id); // nenhum registro encontrado + }, + (_, error) => reject(error) // erro interno em tx.executeSql + ); + }); + }); +}; + +/** + * BUSCA TODOS OS REGISTROS DE UMA DETERMINADA TABELA + * - Não recebe parâmetros; + * - Retorna uma Promise: + * - O resultado da Promise é uma lista (Array) de objetos; + * - Pode retornar erro (reject) caso o ID não exista ou então caso ocorra erro no SQL; + * - Pode retornar um array vazio caso não existam registros. + */ +const allDetalhesCard = (cardId) => { + return new Promise((resolve, reject) => { + db.transaction((tx) => { + //comando SQL modificável + tx.executeSql( + "SELECT * FROM detalhes WHERE cardId=?;", + [cardId], + //----------------------- + (_, { rows }) => { + if (rows.length > 0) resolve(rows._array); + else resolve([]); // nenhum registro encontrado + }, + (_, error) => reject(error) // erro interno em tx.executeSql + ); + }); + }); +}; + +/** + * REMOVE UM REGISTRO POR MEIO DO ID + * - Recebe o ID do registro; + * - Retorna uma Promise: + * - O resultado da Promise a quantidade de registros removidos (zero indica que nada foi removido); + * - Pode retornar erro (reject) caso o ID não exista ou então caso ocorra erro no SQL. + */ +const removeDetalhe = (cardId) => { + return new Promise((resolve, reject) => { + db.transaction((tx) => { + //comando SQL modificável + tx.executeSql( + "DELETE FROM detalhes WHERE cardId=?;", + [cardId], + //----------------------- + (_, { rowsAffected }) => { + resolve(rowsAffected); + }, + (_, error) => reject(error) // erro interno em tx.executeSql + ); + }); + }); +}; + +export default { + createDetalhe, + updateDetalhe, + findDetalhe, + allDetalhesCard, + removeDetalhe, +}; diff --git a/services/sqlite/Play.js b/services/sqlite/Play.js new file mode 100644 index 0000000..02c9621 --- /dev/null +++ b/services/sqlite/Play.js @@ -0,0 +1,14 @@ +import db from "./SQLiteDatabse"; +/* +- cardId +- categoryId +- status + */ + +// Setar cards e criar resultado geral + +// Atualizar Status + +// Finalizar jogo + +// Selecionar proxima carta diff --git a/services/sqlite/ResultadoGeral.js b/services/sqlite/ResultadoGeral.js new file mode 100644 index 0000000..e4aba8b --- /dev/null +++ b/services/sqlite/ResultadoGeral.js @@ -0,0 +1,15 @@ +import db from "./SQLiteDatabse"; +/* +- status (ativo ou concluido) +- data +- numAcertos +- numErros +- nCards +- categoriaId +- rel_erro_jogadas (num_erros / numAcertos + numErros) +- performance (numAcertos / nCards) + */ + +// criar resultado + +// atualizar resultado diff --git a/services/sqlite/SQLiteDatabase.js b/services/sqlite/SQLiteDatabase.js new file mode 100644 index 0000000..9a146aa --- /dev/null +++ b/services/sqlite/SQLiteDatabase.js @@ -0,0 +1,7 @@ +// Inicializa o banco de dados + +import * as SQLite from "expo-sqlite"; + +const db = SQLite.openDatabase("db.db"); + +export default db; diff --git a/yarn.lock b/yarn.lock index 677000e..3eb8db7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1363,6 +1363,17 @@ lodash.pick "^4.4.0" lodash.template "^4.5.0" +"@expo/websql@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@expo/websql/-/websql-1.0.1.tgz#fff0cf9c1baa1f70f9e1d658b7c39a420d9b10a9" + integrity sha1-//DPnBuqH3D54dZYt8OaQg2bEKk= + dependencies: + argsarray "^0.0.1" + immediate "^3.2.2" + noop-fn "^1.0.0" + pouchdb-collections "^1.0.1" + tiny-queue "^0.2.1" + "@hapi/hoek@^9.0.0": version "9.2.1" resolved "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz" @@ -1878,6 +1889,11 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +argsarray@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/argsarray/-/argsarray-0.0.1.tgz#6e7207b4ecdb39b0af88303fa5ae22bda8df61cb" + integrity sha1-bnIHtOzbObCviDA/pa4ivajfYcs= + arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz" @@ -3008,6 +3024,13 @@ expo-splash-screen@~0.14.0, expo-splash-screen@~0.14.1: "@expo/configure-splash-screen" "^0.6.0" "@expo/prebuild-config" "^3.0.15" +expo-sqlite@~10.1.0: + version "10.1.1" + resolved "https://registry.yarnpkg.com/expo-sqlite/-/expo-sqlite-10.1.1.tgz#282bcb20cd04e3eb68e6480630d8176c3dcb49a9" + integrity sha512-yxVa+sDWhfuvYN1MJkQZK74ND3mEOyVm6o2bRoecP6MDZW6c7NXS7Q7kP157b80h8meHukIfkhd48NAe1peenA== + dependencies: + "@expo/websql" "^1.0.1" + expo-status-bar@~1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-1.2.0.tgz" @@ -3480,6 +3503,11 @@ image-size@^0.6.0: resolved "https://registry.npmjs.org/image-size/-/image-size-0.6.3.tgz" integrity sha512-47xSUiQioGaB96nqtp5/q55m0aBQSQdyIloMOc/x+QVTDZLNmXE892IIDrJ0hM1A5vcNUDD5tDffkSP5lCaIIA== +immediate@^3.2.2: + version "3.3.0" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" + integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q== + import-fresh@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz" @@ -4572,6 +4600,11 @@ node-stream-zip@^1.9.1: resolved "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.15.0.tgz" integrity sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw== +noop-fn@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/noop-fn/-/noop-fn-1.0.0.tgz#5f33d47f13d2150df93e0cb036699e982f78ffbf" + integrity sha1-XzPUfxPSFQ35PgywNmmemC94/78= + normalize-css-color@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/normalize-css-color/-/normalize-css-color-1.0.2.tgz" @@ -4907,6 +4940,11 @@ postcss-value-parser@^4.0.2: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== +pouchdb-collections@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/pouchdb-collections/-/pouchdb-collections-1.0.1.tgz#fe63a17da977611abef7cb8026cb1a9553fd8359" + integrity sha1-/mOhfal3YRq+98uAJssalVP9g1k= + pretty-format@^26.5.2, pretty-format@^26.6.2: version "26.6.2" resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz" @@ -5123,19 +5161,19 @@ react-refresh@^0.4.0: resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.4.3.tgz" integrity sha512-Hwln1VNuGl/6bVwnd0Xdn1e84gT/8T9aYNL+HAKDArLCS7LWjwr7StE30IEYbIkx0Vi3vs+coQxe+SQDbGbbpA== -react-router-native@^6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/react-router-native/-/react-router-native-6.2.1.tgz#64b979c07e433c9ced30551fb5232f4f3e839b90" - integrity sha512-MJ7n51d7UZTEXLKC2YUWL8waYTouIvyloUUIlNqERlkEFoDFH9CUuqaAmmGM6LbrphzqhR2XQDK2SgCF8lVvzg== +react-router-native@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/react-router-native/-/react-router-native-6.3.0.tgz#d8a14006cba4522fef335879997b7d7477d28748" + integrity sha512-Y+UuU6Typnz1eGWfYf2UYmh1qItbrNBK5kr3p7ZsamsLIxCKSoYo2YJyz9JOgRiv1nOFsCoSkpQJPYLAz68hlQ== dependencies: "@ungap/url-search-params" "^0.1.4" history "^5.2.0" - react-router "6.2.1" + react-router "6.3.0" -react-router@6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.2.1.tgz#be2a97a6006ce1d9123c28934e604faef51448a3" - integrity sha512-2fG0udBtxou9lXtK97eJeET2ki5//UWfQSl1rlJ7quwe6jrktK9FCCc8dQb5QY6jAv3jua8bBQRhhDOM/kVRsg== +react-router@6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.3.0.tgz#3970cc64b4cb4eae0c1ea5203a80334fdd175557" + integrity sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ== dependencies: history "^5.2.0" @@ -5867,6 +5905,11 @@ through2@^2.0.1: readable-stream "~2.3.6" xtend "~4.0.1" +tiny-queue@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/tiny-queue/-/tiny-queue-0.2.1.tgz#25a67f2c6e253b2ca941977b5ef7442ef97a6046" + integrity sha1-JaZ/LG4lOyypQZd7XvdELvl6YEY= + tmpl@1.0.5: version "1.0.5" resolved "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz"