...
 
Commits (3)
404.html,1592344325625,daa499dd96d8229e73235345702ba32f0793f0c8e5c0d30e40e37a5872be57aa
favicon.ico,1591654795111,d5451f0f0f0bcbcd433bbdf4f6e7e5d89d8ecce2650649e969ccb5e5cd499ab2
index.html,1592344427653,f63bfb4ed658ca7db0a59fad2c3d39e7889cd713f7eb09b1fe7bdd9f9c40f5a1
{
"projects": {
"default": "marvel-comic-app"
}
}
{
"hosting": {
"public": "public",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Page Not Found</title>
<style media="screen">
body { background: #ECEFF1; color: rgba(0,0,0,0.87); font-family: Roboto, Helvetica, Arial, sans-serif; margin: 0; padding: 0; }
#message { background: white; max-width: 360px; margin: 100px auto 16px; padding: 32px 24px 16px; border-radius: 3px; }
#message h3 { color: #888; font-weight: normal; font-size: 16px; margin: 16px 0 12px; }
#message h2 { color: #ffa100; font-weight: bold; font-size: 16px; margin: 0 0 8px; }
#message h1 { font-size: 22px; font-weight: 300; color: rgba(0,0,0,0.6); margin: 0 0 16px;}
#message p { line-height: 140%; margin: 16px 0 24px; font-size: 14px; }
#message a { display: block; text-align: center; background: #039be5; text-transform: uppercase; text-decoration: none; color: white; padding: 16px; border-radius: 4px; }
#message, #message a { box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24); }
#load { color: rgba(0,0,0,0.4); text-align: center; font-size: 13px; }
@media (max-width: 600px) {
body, #message { margin-top: 0; background: white; box-shadow: none; }
body { border-top: 16px solid #ffa100; }
}
</style>
</head>
<body>
<div id="message">
<h2>404</h2>
<h1>Page Not Found</h1>
<p>The specified file was not found on this website. Please check the URL for mistakes and try again.</p>
<h3>Why am I seeing this?</h3>
<p>This page was generated by the Firebase Command-Line Interface. To modify it, edit the <code>404.html</code> file in your project's configured <code>public</code> directory.</p>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css">
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css">
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
......@@ -12,17 +12,18 @@ export default new Vuetify({
theme: {
themes: {
light: {
primary: colors.blue.lighten3,
primary: '#2196F3',
secondary: colors.grey.darken4,
accent: colors.lightBlue,
accent: colors.shades.white,
error: colors.red.lighten1,
success: '#4CAF50',
info: '#2196F3',
warning: '#FB8C00',
},
dark: {
primary: colors.blue.lighten3,
primary: '#2196F3',
secondary: colors.shades.white,
accent: colors.grey.darken4,
},
},
},
......
......@@ -2,6 +2,8 @@ import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import ComicItem from '../views/ComicItem'
import MemoryGame from '../views/memory-game'
import Series from '../views/Series';
Vue.use(VueRouter)
......@@ -11,16 +13,21 @@ Vue.use(VueRouter)
name: 'Comics',
component: Home
},
{
path: '/comic',
name: 'Comics',
component: Home
},
{
path: '/comic/:id',
name: 'Comics',
component: ComicItem
}
{
path: '/comic/:id',
name: 'Comics',
component: ComicItem
},
{
path: '/memory-game',
name: 'Juego de memoria',
component: MemoryGame
},
{
path: '/series',
name: 'Series',
component: Series
},
]
const router = new VueRouter({
......
......@@ -14,13 +14,26 @@
<v-img v-bind:src="image" />
</v-col>
<v-col>
<div>{{description}}</div>
<div><span v-html="description"></span></div>
<v-spacer></v-spacer>
<h2 class="primary--text">{{parseCurrency(realPrice)}}</h2>
<div>Precio en Uruguay</div>
<v-spacer></v-spacer>
<h2 v-if="saleability" class="primary--text">{{parseCurrency(realPriceGoogle)}}</h2>
<h2 v-else class="primary--text">No se encuentra a la venta.</h2>
<v-btn v-if="hasGoogleLink" color="primary" class="text--accent" @click="navigateToGoogleBooks">
<v-icon>mdi-cart-outline</v-icon>
<div>Ir a Google Books</div>
</v-btn>
<h3 style="margin-top: 30px;">Personajes</h3>
<v-row style="padding: 20px;">
<v-avatar v-for="character in charactersInComic" :key="character.id">
<img
v-bind:src="getCharacterImage(character)"
alt="John"
>
</v-avatar>
</v-row>
</v-col>
</v-row>
</div>
......@@ -36,6 +49,7 @@ export default {
itemMarvel: null,
itemGoogle: null,
saleInfo: null,
charactersInComic: [],
overlay: false
};
},
......@@ -85,6 +99,9 @@ export default {
},
realPrice() {
return this.itemMarvel?.prices[0]?.price ?? 0;
},
hasGoogleLink() {
return this.itemGoogle?.infoLink;
}
},
methods: {
......@@ -93,6 +110,27 @@ export default {
style: "currency",
currency: "USD"
}).format(amount);
},
navigateToGoogleBooks() {
window.open(this.itemGoogle.infoLink, '_blank');
},
getCharacters() {
const apiKey = `apikey=29e762cfece8ff211a8d6eabfe17e3b9&ts=1591744565283&hash=7e89e736ebd0edff9b8aa0ee35706106`;
const characterList = this.itemMarvel.characters.items;
for (const item of characterList) {
axios.get(`${item.resourceURI}?${apiKey}`).then(response => {
this.charactersInComic = this.charactersInComic.concat(response.data.data.results);
console.log(this.charactersInComic);
})
}
},
getCharacterImage(character) {
return character.thumbnail?.path
? `${character.thumbnail.path}/portrait_incredible.jpg`
: "";
}
},
created() {
......@@ -108,6 +146,7 @@ export default {
.then(response => {
// JSON responses are automatically parsed.
this.itemMarvel = response.data.data.results[0];
this.getCharacters();
})
.catch(e => {
this.errors.push(e);
......@@ -124,8 +163,8 @@ export default {
.get(`${baseUrlGoogle}?q=isbn:${idGoogle}`)
.then(response => {
// JSON responses are automatically parsed.
this.itemGoogle = response.data.data.items[0].volumeInfo;
this.saleInfo = response.data.data.items[0].saleInfo;
this.itemGoogle = response.data.items[0].volumeInfo;
this.saleInfo = response.data.items[0].saleInfo;
})
.catch(e => {
this.errors.push(e);
......@@ -134,6 +173,7 @@ export default {
this.overlay = false;
});
}
};
</script>
......@@ -144,10 +184,10 @@ export default {
}
.dark-back {
background-color: rgba(255, 255, 255, 0.25);
background-color: rgba(255, 255, 255, 0.10);
}
.light-back {
background-color: rgba(0, 0, 0, 0.25);
background-color: rgba(0, 0, 0, 0.10);
}
</style>
<template>
<div>
<v-overlay :value="overlay">
<v-progress-circular indeterminate color="primary" size="64"></v-progress-circular>
</v-overlay>
<v-row>
<v-col>
<AutocompleteSearch v-on:updateComics="changeData($event)"></AutocompleteSearch>
</v-col>
</v-row>
<v-row>
<v-col
v-for="comic in comicList"
:key="comic.id"
md="2"
sm="3"
xs="6"
>
<SuperheroCard v-bind:comic="comic"/>
</v-col>
</v-row>
<v-row v-if="paginationLenght > 1">
<div class="text-center">
<v-pagination
v-model="page"
:length="paginationLenght"
></v-pagination>
</div>
</v-row>
</div>
</template>
<script>
import SuperheroCard from '@/components/Superhero-card.vue';
import axios from 'axios';
import AutocompleteSearch from "../components/autocomplete-search";
export default {
name: 'Series',
components: {
AutocompleteSearch,
SuperheroCard
},
data() {
return {
comicList: null,
totalNumber: 0,
paginationSize: 40,
page: this.$route.query?.page ? parseInt(this.$route.query.page) : 1,
overlay: false
}
},
computed: {
paginationLenght() {
return Math.ceil(this.totalNumber / this.paginationSize);
}
},
methods: {
changeData(character) {
this.overlay = true;
const baseUrl = 'https://gateway.marvel.com/v1/public/comics';
const filter = 'orderBy=-modified&noVariants=true';
const maxResults = `limit=${this.paginationSize}`;
const startIndex = `offset=${this.paginationSize * (this.page - 1)}`;
const apiKey = `apikey=29e762cfece8ff211a8d6eabfe17e3b9&ts=1591744565283&hash=7e89e736ebd0edff9b8aa0ee35706106`;
let characterFilter = character?.length > 0 ? `characters=${character.join(',')}` : '';
axios.get(`${baseUrl}?${filter}&${maxResults}&${startIndex}&${apiKey}&${characterFilter}`)
.then(response => {
this.comicList = response.data.data.results;
this.totalNumber = response.data.data.total;
this.overlay = false;
})
}
},
created() {
this.changeData();
},
watch: {
page: function(val) {
this.$router.push({ path: '', query: { page: val }});
this.changeData();
}
}
}
</script>
<template>
<div>
<v-overlay :value="overlay">
<v-progress-circular indeterminate color="primary" size="64"></v-progress-circular>
</v-overlay>
<v-row>
<v-col
cols="12"
v-for="character in characterList"
:key="character.id"
md="2"
sm="3"
xs="6"
>
<div class="card-item" @click="flipImage(character)">
<v-img :src="superheroImage(character)" height="250"></v-img>
</div>
</v-col>
</v-row>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'Memory-game',
data() {
return {
characterList: null,
totalNumber: 6,
overlay: false,
selectedItems: [],
successItems: []
}
},
methods: {
changeData() {
this.overlay = true;
const baseUrl = 'https://gateway.marvel.com/v1/public/characters';
const apiKey = `apikey=29e762cfece8ff211a8d6eabfe17e3b9&ts=1591744565283&hash=7e89e736ebd0edff9b8aa0ee35706106`;
const limit = `limit=${this.totalNumber}&orderBy=-modified`;
axios.get(`${baseUrl}?${apiKey}&${limit}`)
.then((response) => {
this.makeCharacterList(response.data.data.results);
this.overlay = false;
});
},
makeCharacterList(data) {
this.characterList = data;
this.characterList = this.characterList.concat(data);
let index = 0;
this.characterList.map(data => {
data.isSelected = false;
data.index = index;
index++;
});
this.shuffle(this.characterList);
},
shuffle(array) {
let currentIndex = array.length, temporaryValue, randomIndex;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
},
flipImage(character) {
const foundIndex = this.selectedItems.length > 0 ? this.selectedItems.findIndex(item => item.index === character.index) : -1;
if (foundIndex === -1) {
this.selectedItems.push(character);
if (this.selectedItems.length >= 2) {
if (this.selectedItems[0].id === this.selectedItems[1].id) {
console.log('biennn');
this.successItems = this.successItems.concat(this.selectedItems);
}
this.selectedItems = [];
}
} else {
this.selectedItems.splice(foundIndex, 1);
character.isSelected = !character.isSelected;
}
},
superheroImage(superhero) {
return `${superhero.thumbnail?.path}/portrait_incredible.jpg`;
}
},
created() {
this.changeData();
}
}
</script>
<style lang="scss">
.card-item {
cursor: pointer;
}
</style>