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"