diff --git a/App.js b/App.js index 266a292..ddeee2b 100644 --- a/App.js +++ b/App.js @@ -1,6 +1,7 @@ import React from "react"; -import { Text, View, StyleSheet, StatusBar } from "react-native"; +import { Text, View, StyleSheet } from "react-native"; import { NativeRouter, Route, Routes } from "react-router-native"; +import { StatusBar } from "expo-status-bar"; import AppLoading from "expo-app-loading"; import { useFonts, @@ -13,6 +14,9 @@ import HomeCategoria from "./components/HomeCategoria/HomeCategoria"; import AddCard from "./components/AddCard/AddCard"; import ConfirmDelete from "./components/ConfirmDelete/ConfirmDelete"; import AddCategoria from "./components/AddCategoria/AddCategoria"; +import { SafeAreaView } from "react-native-safe-area-context"; +import * as NavigationBar from "expo-navigation-bar"; +import PlayCards from "./components/PlayCards/PlayCards"; export default function App() { let [fontsLoaded] = useFonts({ @@ -20,24 +24,36 @@ export default function App() { Epilogue_500Medium, Epilogue_700Bold, }); + + NavigationBar.setBackgroundColorAsync("#111"); + NavigationBar.setButtonStyleAsync("light"); + if (!fontsLoaded) { return ; } else { return ( - - - } /> - } /> - } /> - - } /> - - } - /> - - + + + + } /> + } /> + } /> + + } /> + + } + /> + + } + /> + + + ); } } diff --git a/app.json b/app.json index 2b5a01d..2ceb42b 100644 --- a/app.json +++ b/app.json @@ -28,6 +28,10 @@ }, "web": { "favicon": "./assets/favicon.png" + }, + "androidStatusBar": { + "backgroundColor": "#1a1a1a", + "translucent": false } } } diff --git a/assets/icons/check-solid.svg b/assets/icons/check-solid.svg new file mode 100644 index 0000000..1ff6404 --- /dev/null +++ b/assets/icons/check-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/chevron-left-solid.svg b/assets/icons/chevron-left-solid.svg new file mode 100644 index 0000000..7043552 --- /dev/null +++ b/assets/icons/chevron-left-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/pen-solid.svg b/assets/icons/pen-solid.svg index 93fe758..493c739 100644 --- a/assets/icons/pen-solid.svg +++ b/assets/icons/pen-solid.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/repeat-solid.svg b/assets/icons/repeat-solid.svg new file mode 100644 index 0000000..1f506d9 --- /dev/null +++ b/assets/icons/repeat-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/rotate-right-solid.svg b/assets/icons/rotate-right-solid.svg new file mode 100644 index 0000000..d1a6b8a --- /dev/null +++ b/assets/icons/rotate-right-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/xmark-solid.svg b/assets/icons/xmark-solid.svg new file mode 100644 index 0000000..86b827a --- /dev/null +++ b/assets/icons/xmark-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/BtnCategorias/BtnCategorias.jsx b/components/BtnCategorias/BtnCategorias.jsx index 1a291e7..fc3a27c 100644 --- a/components/BtnCategorias/BtnCategorias.jsx +++ b/components/BtnCategorias/BtnCategorias.jsx @@ -2,17 +2,16 @@ import React from 'react'; 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 BackIcon from '../../assets/icons/chevron-left-solid.svg' import { Link } from 'react-router-native' const BtnCategorias = (props) => { return ( - + - {/**/} - Voltar + ); diff --git a/components/BtnCategorias/BtnCategorias.styles.js b/components/BtnCategorias/BtnCategorias.styles.js index f3e30d1..a41141c 100644 --- a/components/BtnCategorias/BtnCategorias.styles.js +++ b/components/BtnCategorias/BtnCategorias.styles.js @@ -7,8 +7,6 @@ export const styles = StyleSheet.create({ display: "flex", flexDirection: "row", padding: 10, - paddingLeft: 20, - paddingRight: 20, alignItems: "center", justifyContent: "center", borderRadius: 50, diff --git a/components/BtnPlay/BtnPlay.jsx b/components/BtnPlay/BtnPlay.jsx index 9e8c02d..a44cf6f 100644 --- a/components/BtnPlay/BtnPlay.jsx +++ b/components/BtnPlay/BtnPlay.jsx @@ -6,10 +6,10 @@ import Play from '../../assets/icons/play-solid.svg' import { Link } from 'react-router-native' -const BtnCategorias = (props) => { +const BtnPlay = (props) => { return ( - + @@ -17,4 +17,4 @@ const BtnCategorias = (props) => { ); } -export default BtnCategorias; +export default BtnPlay; diff --git a/components/Card/Card.jsx b/components/Card/Card.jsx index f0647e3..509d77f 100644 --- a/components/Card/Card.jsx +++ b/components/Card/Card.jsx @@ -7,7 +7,7 @@ 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 TurnCardIcon from '../../assets/icons/repeat-solid.svg' import TrashIcon from '../../assets/icons/trash-solid.svg' import CardsDB from '../../services/sqlite/Card' import DetalhesDB from '../../services/sqlite/Detalhes' @@ -19,7 +19,6 @@ class Card extends React.Component { 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, @@ -88,7 +87,7 @@ class Card extends React.Component { {card.titulo} {card.resposta} - {(card.detalhes.length > 0) ? Detalhes : null} + {(card.detalhes.length > 0) ? Detalhes : null} { - 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 Card; diff --git a/components/Card/Verso.styles.js b/components/Card/Verso.styles.js index ca1e1de..9b7c17b 100644 --- a/components/Card/Verso.styles.js +++ b/components/Card/Verso.styles.js @@ -136,7 +136,7 @@ export const verso_styles = StyleSheet.create({ }, categoryItem: { - marginTop: 10, + marginBottom: 10, borderRadius: 10, width: "100%", }, diff --git a/components/CardList/CardList.jsx b/components/CardList/CardList.jsx index c509686..a716b81 100644 --- a/components/CardList/CardList.jsx +++ b/components/CardList/CardList.jsx @@ -10,9 +10,8 @@ import CardsDB from '../../services/sqlite/Card' class CardList extends React.Component { state = { - cards: 0, + cards: null, categoriaId: this.props.categoriaId, - categoriaNome: this.props.categoriaNome, cor: this.props.cor, } @@ -20,6 +19,14 @@ class CardList extends React.Component { this.getCards(this.state.categoriaId); } + componentDidUpdate(prevProps) { + if(this.props.categoriaId != prevProps.categoriaId){ + this.getCards(this.state.categoriaId); + } + + } + + getCards = (categoriaId) => { console.log(categoriaId) CardsDB.allCardsCategory(categoriaId).then(res => { @@ -31,12 +38,16 @@ class CardList extends React.Component { render(){ const renderCard = ({item}) => { return ( - + ); } - if (this.state.cards != 0 && Object.keys(this.state.cards).length <= 0){ + if (this.state.cards != null && Object.keys(this.state.cards).length <= 0){ return( - Crie um novo card. + + Clique no + + + para adicionar um card + ); } diff --git a/components/CardList/CardList.styles.js b/components/CardList/CardList.styles.js index 29c39ec..95a247f 100644 --- a/components/CardList/CardList.styles.js +++ b/components/CardList/CardList.styles.js @@ -7,11 +7,33 @@ export const styles = StyleSheet.create({ paddingRight: 20 - vw(3), }, - semCategoriasMensagem: { - marginTop: 10, - color: "#f2f2f2", + msgCriar: { + backgroundColor: "#2b2b2b", + display: "flex", + flexDirection: "column", + alignItems: "center", + width: vw(60), + marginLeft: vh(10), + marginTop: vh(18), + borderRadius: 20, + }, + + exampleAddBtn: { + color: "#2b2b2b", textAlign: "center", fontFamily: "Epilogue_500Medium", - fontSize: 20, + fontSize: 40, + backgroundColor: "#1a1a1a", + width: 60, + paddingBottom: 10, + borderRadius: 50, + }, + + semCategoriasMensagem: { + margin: 10, + color: "#1a1a1a", + textAlign: "center", + fontFamily: "Epilogue_700Bold", + fontSize: 25, }, }); diff --git a/components/Categoria/Categoria.jsx b/components/Categoria/Categoria.jsx index c08a0a8..ba94da6 100644 --- a/components/Categoria/Categoria.jsx +++ b/components/Categoria/Categoria.jsx @@ -4,16 +4,25 @@ import { styles } from './Categoria.styles'; //import { CategoriasWrapper } from './Categorias.styles'; import CardsIcon from '../../assets/icons/cards.svg' import { Link } from 'react-router-native' +import TrashIcon from '../../assets/icons/trash-solid.svg' +import EditIcon from '../../assets/icons/pen-solid.svg' const Categoria = (props) => { color = "#" + props.cor.split("-")[0] - let [editMode, setEditMode] = useState(false) + const [editMode, setEditMode] = useState(false) const menuEditMode = () => { if (editMode){ return( - Deletar + + + + + + + + ) } else { return( @@ -26,7 +35,7 @@ const Categoria = (props) => { } return( - editMode ? setEditMode(false) : setEditMode(true)}> + editMode ? setEditMode(false) : setEditMode(true)}> {props.nome} {menuEditMode()} diff --git a/components/Categoria/Categoria.styles.js b/components/Categoria/Categoria.styles.js index 32f8a1c..8f8cf7f 100644 --- a/components/Categoria/Categoria.styles.js +++ b/components/Categoria/Categoria.styles.js @@ -3,11 +3,11 @@ import { vw, vh, vmin, vmax } from "react-native-expo-viewport-units"; export const styles = StyleSheet.create({ nome: { - marginTop: 10, color: "#f2f2f2", - textAlign: "center", + textAlign: "left", fontFamily: "Epilogue_500Medium", - fontSize: 20, + fontSize: 18, + width: vw(53), }, categoria: { display: "flex", @@ -21,6 +21,27 @@ export const styles = StyleSheet.create({ borderLeftWidth: 10, }, + edit_buttons: { + display: "flex", + flexDirection: "row", + justifyContent: "space-between", + alignItems: "center", + borderRadius: 8, + }, + + trash_button: { + backgroundColor: "#c0392b", + padding: 10, + borderRadius: 50, + }, + + edit_button: { + backgroundColor: "#16a085", + padding: 10, + marginRight: 15, + borderRadius: 50, + }, + textQuantCards: { color: "#f2f2f2", fontFamily: "Epilogue_500Medium", diff --git a/components/CategoriasList/CategoriasList.jsx b/components/CategoriasList/CategoriasList.jsx index fcee010..abf6cd2 100644 --- a/components/CategoriasList/CategoriasList.jsx +++ b/components/CategoriasList/CategoriasList.jsx @@ -17,6 +17,12 @@ class CategoriasList extends React.Component { this.getCategorias(); } + componentDidUpdate(prevState){ + if (this.state.categorias !== prevState.categorias) { + this.getCategorias(); + } + } + getCategorias = () => { CategoriaDB.allCategorias().then(res => { this.setState({ @@ -46,7 +52,11 @@ class CategoriasList extends React.Component { ); }else{ return( - Crie uma nova categoria + + Clique no + + + para adicionar uma categoria + ); } } diff --git a/components/CategoriasList/CategoriasList.styles.js b/components/CategoriasList/CategoriasList.styles.js index f766b8e..ce89952 100644 --- a/components/CategoriasList/CategoriasList.styles.js +++ b/components/CategoriasList/CategoriasList.styles.js @@ -11,11 +11,33 @@ export const styles = StyleSheet.create({ height: vh(65), }, - semCategoriasMensagem: { - marginTop: 10, - color: "#f2f2f2", + msgCriar: { + backgroundColor: "#2b2b2b", + display: "flex", + flexDirection: "column", + alignItems: "center", + width: vw(60), + marginLeft: vh(10), + marginTop: vh(18), + borderRadius: 20, + }, + + exampleAddBtn: { + color: "#2b2b2b", textAlign: "center", fontFamily: "Epilogue_500Medium", - fontSize: 20, + fontSize: 40, + backgroundColor: "#1a1a1a", + width: 60, + paddingBottom: 10, + borderRadius: 50, + }, + + semCategoriasMensagem: { + margin: 10, + color: "#1a1a1a", + textAlign: "center", + fontFamily: "Epilogue_700Bold", + fontSize: 25, }, }); diff --git a/components/ConfirmDelete/ConfirmDelete.jsx b/components/ConfirmDelete/ConfirmDelete.jsx index d6f04bc..bd193ae 100644 --- a/components/ConfirmDelete/ConfirmDelete.jsx +++ b/components/ConfirmDelete/ConfirmDelete.jsx @@ -5,6 +5,7 @@ import { styles } from './ConfirmDelete.styles'; import DetalhesDB from '../../services/sqlite/Detalhes' import CategoriaDB from '../../services/sqlite/Categoria' import CardsDB from '../../services/sqlite/Card' +import PlayDB from '../../services/sqlite/PlayDB' import { Link, useParams } from 'react-router-native' function withParams(Component) { @@ -30,6 +31,7 @@ class ConfirmDelete extends React.Component { this.setState({ categoria: res, }); + console.log(res) if(this.state.who == "Card"){ this.getCard(this.state.id) } @@ -50,9 +52,9 @@ class ConfirmDelete extends React.Component { return( - Deseja realmente excluir {(who == "Card") ? `o card "${card.titulo}"?` : `a categoria "${categoria.nome}"?`} + Deseja realmente excluir {(who == "Card") ? `o card "${card.titulo}"?` : `o deck "${categoria.nome}"? (Também excluirá todos os cards dele!)`} - (who == "Card") ? deleteCard(id) : null}> + (who == "Card") ? deleteCard(id) : deleteCategoria(categoriaId)}> Sim @@ -72,14 +74,35 @@ function deleteCard(cardId){ //delete CardsDB.removeCard(cardId) .then( id => { - console.log('Card deleted with id: '+ id) + console.log('Cards deleted: '+ id) deleteDetalhes(cardId) + deletePlays(cardId, 0) }) .catch( err => console.log(err) ) } +function deleteCategoria(categoriaId) { + CardsDB.allCardsCategory(categoriaId).then(res => { + deleteOnlyCategoria(categoriaId) + for (let card of res){ + deleteCard(card.id) + } + + deletePlays(categoriaId, 1) + }); +} + +function deleteOnlyCategoria(categoriaId){ + //create + CategoriaDB.removeCategoria(categoriaId) + .then( id => { + console.log('Categorias deleted : '+ id) + }) + .catch( err => console.log(err) ) +} + function deleteDetalhes(cardId){ //delete @@ -92,4 +115,24 @@ function deleteDetalhes(cardId){ } +function deletePlays(id, by){ + if(by == 0){ + //delete + PlayDB.removePlaysCard(id) + .then( cardId => { + console.log('Plays deleted with cardId: '+ id) + }) + .catch( err => console.log(err) ) + + }else{ + //delete + PlayDB.removePlaysCategoria(id) + .then( cardId => { + console.log('Plays deleted with categoriaId: '+ id) + }) + .catch( err => console.log(err) ) + + } +} + export default withParams(ConfirmDelete); diff --git a/components/HomeCategoria/HomeCategoria.jsx b/components/HomeCategoria/HomeCategoria.jsx index 724dfd7..d82977b 100644 --- a/components/HomeCategoria/HomeCategoria.jsx +++ b/components/HomeCategoria/HomeCategoria.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import { View, Text } from 'react-native'; +import { View, Text, ScrollView } from 'react-native'; import { styles } from './HomeCategoria.styles'; import BtnAddCard from '../BtnAdd/BtnAddCard'; import BtnPlay from '../BtnPlay/BtnPlay'; @@ -38,14 +38,14 @@ class HomeCategoria extends React.Component { if (this.state.categoria.id != undefined) { return ( - {this.state.categoria.nome} + {this.state.categoria.nome} - + - + ); }else{ diff --git a/components/HomeCategoria/HomeCategoria.styles.js b/components/HomeCategoria/HomeCategoria.styles.js index 02b7f66..a8b211a 100644 --- a/components/HomeCategoria/HomeCategoria.styles.js +++ b/components/HomeCategoria/HomeCategoria.styles.js @@ -1,30 +1,37 @@ -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({ - home: { - flex: 1, - backgroundColor: '#1a1a1a', - width: '100%', - height: '100%', - }, + home: { + flex: 1, + backgroundColor: "#1a1a1a", + width: "100%", + height: "100%", + }, - categoryText: { - color: '#f2f2f2', - marginLeft: 20, - marginTop: 20, - fontFamily: 'Epilogue_500Medium', - fontSize: 40, - }, + categoryText: { + color: "#f2f2f2", + marginLeft: 20, + marginTop: 20, + fontFamily: "Epilogue_500Medium", + fontSize: 30, + }, - searchIcon: { - position: 'absolute', - top: 30, - right: 30, - }, + scrollView: { + position: "absolute", + top: 0, + left: 0, + right: 90, + }, - cardList: { - height: '100%', - marginTop: '5%', - } - }); + searchIcon: { + position: "absolute", + top: 30, + right: 30, + }, + + cardList: { + height: "100%", + marginTop: vh(13), + }, +}); diff --git a/components/PlayCards/CardPlay.jsx b/components/PlayCards/CardPlay.jsx new file mode 100644 index 0000000..4db3a13 --- /dev/null +++ b/components/PlayCards/CardPlay.jsx @@ -0,0 +1,102 @@ +import React, { useState } from 'react'; +import { View, Text, ScrollView, TouchableOpacity, FlatList } from 'react-native'; +import { styles } from './PlayCards.styles'; +import { verso_styles } from './Verso.styles'; +//import { CardWrapper } from './Card.styles'; +import { LinearGradient } from 'expo-linear-gradient'; +import TurnCardIcon from '../../assets/icons/arrows-rotate-solid.svg' +import DetalhesDB from '../../services/sqlite/Detalhes' + +class CardPlay extends React.Component { + + state = { + detalhes: [], + id: this.props.id, + categoriaId: this.props.categoriaId, + cor: this.props.cor, + titulo: this.props.titulo, + resposta: this.props.resposta, + isTurned: false + } + + componentDidMount() { + console.log("Montou") + 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)} + + this.setState({ + isTurned: this.state.isTurned ? false : true, + })}> + + + + + + ); + + function frente(card){ + return( + + + {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}> + + + ); + } + } +} + +function getColors(colorStr){ + var initialColor = colorStr.split("-")[0] + var finalColor = colorStr.split("-")[1] + return ["#" + initialColor, "#" + finalColor] + +} + +export default CardPlay; diff --git a/components/PlayCards/PlayCards.jsx b/components/PlayCards/PlayCards.jsx new file mode 100644 index 0000000..78fd0d9 --- /dev/null +++ b/components/PlayCards/PlayCards.jsx @@ -0,0 +1,179 @@ +import React, { useState } from 'react'; +import { View, Text, ScrollView, TouchableOpacity, FlatList } from 'react-native'; +import { styles } from './PlayCards.styles'; +import { verso_styles } from './Verso.styles'; +//import { CardWrapper } from './Card.styles'; +import { LinearGradient } from 'expo-linear-gradient'; +import TrashIcon from '../../assets/icons/trash-solid.svg' +import PlayDB from '../../services/sqlite/PlayDB' +import CardDB from '../../services/sqlite/Card' +import CategoriaDB from '../../services/sqlite/Categoria' +import { Link, useParams } from 'react-router-native'; +import CheckIcon from '../../assets/icons/check-solid.svg' +import XMarkIcon from '../../assets/icons/xmark-solid.svg' +import BackIcon from '../../assets/icons/chevron-left-solid.svg' +import TurnCardIcon from '../../assets/icons/repeat-solid.svg' +import ResetIcon from '../../assets/icons/rotate-right-solid.svg' +import DetalhesDB from '../../services/sqlite/Detalhes' + +function withParams(Component) { + return props => ; +} + +class PlayCards extends React.Component { + + state = { + categoriaId: this.props.params.categoriaId, + clicked: false, + card: 0, + categoria: 0, + isTurned: false, + detalhes: [] + } + + componentDidMount() { + this.createPlay(); + } + + componentDidUpdate(){ + if(this.state.clicked){ + console.log("click") + this.setState({clicked: false}) + this.createPlay(); + } + } + + createPlay = () => { + PlayDB.createPlay(this.state.categoriaId).then(idPlay => { + PlayDB.selectNextCard(this.state.categoriaId).then(nextCard => { + CardDB.findCard(nextCard.cardId).then(playCard => { + this.setState({ + card: playCard + }); + CategoriaDB.findCategoria(this.state.categoriaId).then(categoriaObj => { + this.setState({ + categoria: categoriaObj + }); + DetalhesDB.allDetalhesCard(nextCard.cardId).then(detalhes => { + this.setState({ + detalhes: detalhes, + }); + }); + }) + }) + }); + }); + } + + render (){ + + const renderDetalhe = ({item}) => { + return ( + + {item.titulo} + {item.resposta} + + ); +} + + if (this.state.categoria != 0 && this.state.card != 0 && !this.state.clicked){ + return( + + {resetaPlay(this.state.categoriaId); this.setState({clicked: true})}} style={[styles.btn_layout, styles.btn_reset]}> + + + + + + {this.state.categoria.nome} + + + + {this.state.isTurned ? verso(this.state.card, this.state.detalhes): frente(this.state.card)} + + this.setState({ + isTurned: this.state.isTurned ? false : true, + })}> + + + + + {updatePlay(this.state.card.id, 2,this.state.categoriaId); this.setState({clicked: true})}} style={[styles.btn_layout, styles.btn_right]}> + + + {updatePlay(this.state.card.id, 1, this.state.categoriaId);this.setState({clicked: true})}} style={[styles.btn_layout, styles.btn_left]}> + + + + ); + + }else{ + return( + + Opaaa + + Cancelar + + + ); + } + + function frente(card){ + return( + + + {card.titulo} + + + ) + } + + function verso(card, detalhes){ + return( + // Constrói a visualização do card + + {card.titulo} + {card.resposta} + {(detalhes.length > 0) ? Detalhes : null} + item.id} + contentContainerStyle={styles.cardList}> + + + ); + } + + + } +} + + +function updatePlay(cardId, status, categoriaId) { + //update + PlayDB.updatePlay(cardId, categoriaId, status) + .then( updated => console.log('Updated plays: '+ updated) ) + .catch( err => console.log(err)) +} + +function resetaPlay(categoriaId) { + //update + PlayDB.resetaPlay(categoriaId) + .then( updated => console.log('Updated plays: '+ updated) ) + .catch( err => console.log(err)) +} + +function getColors(colorStr){ + var initialColor = colorStr.split("-")[0] + var finalColor = colorStr.split("-")[1] + return ["#" + initialColor, "#" + finalColor] + +} + + +export default withParams(PlayCards); diff --git a/components/PlayCards/PlayCards.styles.js b/components/PlayCards/PlayCards.styles.js new file mode 100644 index 0000000..e688434 --- /dev/null +++ b/components/PlayCards/PlayCards.styles.js @@ -0,0 +1,123 @@ +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", + }, + + scrollViewTitle: { + position: "absolute", + top: 20, + left: 20, + right: 80, + //bottom: vh(98), + }, + + nomeCategoria: { + color: "#f2f2f2", + textAlign: "center", + fontFamily: "Epilogue_500Medium", + fontSize: 30, + width: "100%", + }, + + cardBody: { + flex: 1, + width: vw(100) - 40, + height: vh(10), + borderRadius: 40, + padding: 20, + marginLeft: vw(3), + marginRight: vw(3), + marginTop: vh(5), + marginBottom: 50, + display: "flex", + flexDirection: "column", + alignItems: "center", + }, + + scrollView: { + marginTop: "5%", + height: "82%", + }, + + cardTitulo: { + marginTop: 40, + color: "#f2f2f2", + textAlign: "center", + fontFamily: "Epilogue_500Medium", + fontSize: 30, + }, + + dica: { + marginTop: 20, + textAlign: "center", + color: "#f2f2f2", + fontFamily: "Epilogue_500Medium", + fontSize: 18, + }, + + menu_footer: { + height: vh(10), + width: "100%", + position: "absolute", + backgroundColor: "#1a1a1a", + bottom: 0, + }, + + 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_right: { + position: "absolute", + right: vw(15), + bottom: 20, + backgroundColor: "#16a085", + }, + + btn_reset: { + position: "absolute", + right: 20, + top: 20, + backgroundColor: "#f2f2f2", + padding: 10, + }, + + btn_left: { + position: "absolute", + left: vw(15), + bottom: 20, + backgroundColor: "#c0392b", + }, + + btn_back: { + position: "absolute", + left: vw(50) - 25, + bottom: 30, + backgroundColor: "#f2f2f2", + padding: 10, + }, + + btn_layout: { + padding: 15, + borderRadius: 50, + }, +}); diff --git a/components/PlayCards/Verso.styles.js b/components/PlayCards/Verso.styles.js new file mode 100644 index 0000000..9b7c17b --- /dev/null +++ b/components/PlayCards/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: { + marginBottom: 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/package.json b/package.json index e1b53a3..ce707a8 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "expo-app-loading": "~1.3.0", "expo-font": "~10.0.4", "expo-linear-gradient": "~11.0.1", + "expo-navigation-bar": "~1.1.1", "expo-splash-screen": "~0.14.1", "expo-sqlite": "~10.1.0", "expo-status-bar": "~1.2.0", diff --git a/services/sqlite/Categoria.js b/services/sqlite/Categoria.js index c6c3969..b13bf3f 100644 --- a/services/sqlite/Categoria.js +++ b/services/sqlite/Categoria.js @@ -138,8 +138,8 @@ const removeCategoria = (id) => { db.transaction((tx) => { //comando SQL modificável tx.executeSql( - "DELETE FROM categoria WHERE id=?; DELETE FROM cards WHERE categoriaId=?", - [id, id], + "DELETE FROM categorias WHERE id=?;", + [id], //----------------------- (_, { rowsAffected }) => { resolve(rowsAffected); diff --git a/services/sqlite/Play.js b/services/sqlite/Play.js deleted file mode 100644 index 02c9621..0000000 --- a/services/sqlite/Play.js +++ /dev/null @@ -1,14 +0,0 @@ -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/PlayDB.js b/services/sqlite/PlayDB.js new file mode 100644 index 0000000..3456d52 --- /dev/null +++ b/services/sqlite/PlayDB.js @@ -0,0 +1,250 @@ +import db from "./SQLiteDatabase"; +import CardDB from "./Card"; +/* +- cardId +- categoryId +- status +*/ + +// STATUS = 0 -> Card não visto +// STATUS = 1 -> Card foi respondido como ERRADO na ultima vez visto +// STATUS = 2 -> Card foi respondido como CERTO na ultima vez visto +// ESPAÇO = Quantidade de jogadas desde a ultima vez visto + +/** + * INICIALIZAÇÃO DA TABELA + * - Executa sempre, mas só cria a tabela caso não exista (primeira execução) + */ +db.transaction((tx) => { + tx.executeSql( + // "CREATE TABLE play ( id INTEGER PRIMARY KEY AUTOINCREMENT, cardId INTEGER, categoriaId INTEGER, status INTEGER, espaco INTEGER, UNIQUE(cardId))" + "CREATE TABLE play ( id INTEGER PRIMARY KEY AUTOINCREMENT, cardId INTEGER, categoriaId INTEGER, status INTEGER, views INTEGER, erros INTEGER, espaco INTEGER, UNIQUE(cardId))" + ); +}); + +/** + * 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 createPlay = (categoriaId) => { + return new Promise((resolve, reject) => { + // puxando todos os cards da categoria + CardDB.allCardsCategory(categoriaId).then((res) => { + db.transaction((tx) => { + // setando nova jogada para cada card que não foi setado + for (let obj of res) { + tx.executeSql( + "INSERT OR IGNORE INTO play (cardId, categoriaid, status, views, erros, espaco) VALUES (?, ?, 0, 0, 0, 1);", + [obj.id, obj.categoriaId], + //----------------------- + (_, { rowsAffected, insertId }) => { + if (rowsAffected > 0) resolve(insertId); + else resolve("Card existe"); // insert falhou + }, + (_, error) => resolve(rowsAffected) // 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 updatePlay = (cardId, categoriaId, status) => { + return new Promise((resolve, reject) => { + if (status == 2) { + db.transaction((tx) => { + //comando SQL modificável + tx.executeSql( + "UPDATE play SET status = 2, views = views + 1 WHERE cardid = ?;", + [cardId], + //----------------------- + (_, { rowsAffected }) => { + if (rowsAffected > 0) resolve(rowsAffected); + else reject("Error updating obj: id=" + id); // nenhum registro alterado + }, + (_, error) => reject(error) // erro interno em tx.executeSql + ); + }); + } else { + db.transaction((tx) => { + //comando SQL modificável + tx.executeSql( + "UPDATE play SET status = 1, views = views + 1, erros = erros + 1, espaco = espaco + 1 WHERE cardid = ?;", + [cardId], + //----------------------- + (_, { rowsAffected }) => { + if (rowsAffected > 0) resolve(rowsAffected); + else reject("Error updating obj: id=" + id); // nenhum registro alterado + }, + (_, error) => reject(error) // erro interno em tx.executeSql + ); + }); + } + + db.transaction((tx) => { + //comando SQL modificável + tx.executeSql( + "UPDATE play SET espaco = 1 WHERE cardid = ?", + [cardId], + //----------------------- + (_, { rowsAffected }) => { + if (rowsAffected > 0) resolve(rowsAffected); + else reject("Error updating obj: id=" + id); // nenhum registro alterado + }, + (_, error) => reject(error) // erro interno em tx.executeSql + ); + }); + + db.transaction((tx) => { + //comando SQL modificável + tx.executeSql( + "UPDATE play SET espaco = espaco + 1 WHERE cardid != ? AND categoriaid = ?;", + [cardId, categoriaId], + //----------------------- + (_, { rowsAffected }) => { + if (rowsAffected > 0) resolve(rowsAffected); + else reject("Error updating obj: id=" + id); // nenhum registro alterado + }, + (_, 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 resetaPlay = (categoriaId) => { + return new Promise((resolve, reject) => { + db.transaction((tx) => { + //comando SQL modificável + tx.executeSql( + "UPDATE play SET status = 0, views = 0, erros = 0, espaco = 1 WHERE categoriaId = ?;", + [categoriaId], + //----------------------- + (_, { rowsAffected }) => { + if (rowsAffected > 0) resolve(rowsAffected); + else reject("Error updating obj: id=" + categoriaId); // nenhum registro alterado + }, + (_, error) => reject(error) // erro interno em tx.executeSql + ); + }); + }); +}; + +const verificaJogadasNaoIniciadas = (id) => { + return new Promise((resolve, reject) => { + db.transaction((tx) => { + //comando SQL modificável + tx.executeSql( + "SELECT COUNT(VIEWS) as nao_iniciados FROM play WHERE views = 0 AND categoriaId = ?;", + [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 + ); + }); + }); +}; + +const removePlaysCard = (id) => { + return new Promise((resolve, reject) => { + db.transaction((tx) => { + //comando SQL modificável + tx.executeSql( + "DELETE FROM play WHERE cardId=?;", + [id], + //----------------------- + (_, { rowsAffected }) => { + resolve(rowsAffected); + }, + (_, error) => reject(error) // erro interno em tx.executeSql + ); + }); + }); +}; + +const removePlaysCategoria = (id) => { + return new Promise((resolve, reject) => { + db.transaction((tx) => { + //comando SQL modificável + tx.executeSql( + "DELETE FROM play WHERE categoriaId=?;", + [id], + //----------------------- + (_, { rowsAffected }) => { + resolve(rowsAffected); + }, + (_, error) => reject(error) // erro interno em tx.executeSql + ); + }); + }); +}; + +const selectNextCard = (id) => { + return new Promise((resolve, reject) => { + verificaJogadasNaoIniciadas(id).then((res) => { + if (res.nao_iniciados > 0) { + db.transaction((tx) => { + //comando SQL modificável + tx.executeSql( + "SELECT cardId FROM play WHERE views = 0 AND categoriaId = ? ORDER BY cardId LIMIT 1;", + [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 + ); + }); + } else { + db.transaction((tx) => { + //comando SQL modificável + tx.executeSql( + "SELECT cardid, status, erros, views, espaco, ((((erros * 1.00) / views) + 1) * (espaco * 1.00)) as peso FROM play WHERE categoriaId = ? ORDER BY peso DESC;", + [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 + ); + }); + } + }); + }); +}; + +// Atualizar Status + +// Finalizar jogo + +// Selecionar proxima carta + +export default { + createPlay, + resetaPlay, + updatePlay, + removePlaysCard, + removePlaysCategoria, + selectNextCard, +}; diff --git a/yarn.lock b/yarn.lock index 3eb8db7..8ca88cc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3016,6 +3016,15 @@ expo-modules-core@0.6.4: compare-versions "^3.4.0" invariant "^2.2.4" +expo-navigation-bar@~1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/expo-navigation-bar/-/expo-navigation-bar-1.1.2.tgz#1caddf41b3fd7652796db933ffe59a1ab0ed658c" + integrity sha512-6TEmFArrCazRKrhQrWho1sBEXiFBP+7MIcAeZ5wEB+QEb7ZkYmC+JKFfZl3oz9VWD7nnhgcLRgFE9XL0n74Fow== + dependencies: + "@expo/config-plugins" "^4.0.2" + "@react-native/normalize-color" "^2.0.0" + debug "^4.3.2" + expo-splash-screen@~0.14.0, expo-splash-screen@~0.14.1: version "0.14.2" resolved "https://registry.yarnpkg.com/expo-splash-screen/-/expo-splash-screen-0.14.2.tgz#2598d6980e71ecd8b7467ca821fb9dbfb80f355b"