Skip to content

Instantly share code, notes, and snippets.

@cba85
Created December 27, 2023 16:53
Show Gist options
  • Save cba85/d372c610936a4a41749a2539fe1933a5 to your computer and use it in GitHub Desktop.
Save cba85/d372c610936a4a41749a2539fe1933a5 to your computer and use it in GitHub Desktop.
Vue 3 TV Maze (with components) - IPI Toulouse - CDAN SOPRA
let Search = {
data() {
return {
q: "",
};
},
methods: {
async search() {
if (!this.q) {
this.$emit("updateError", "Veuillez entrer une série");
return;
}
this.$emit("updateError", "");
try {
const response = await fetch(
`https://api.tvmaze.com/search/shows?q=${this.q}`
);
const data = await response.json();
this.$emit("results", data);
this.q = "";
} catch (error) {
const e = "Vous n'êtes pas connecté à internet";
this.$emit("updateError", e);
console.error(e);
}
},
},
template: `<form @submit.prevent="search">
<input type="text" placeholder="Série..." autofocus v-model="q" />
<button type="submit">Recherche</button>
</form>`,
};
let Post = {
props: ["show"],
template: `
<div>
<h2>{{ show.show.name }}</h2>
<h3>
⭐️ {{ show.show.rating.average ? show.show.rating.average : "-" }}
<mark v-if="show.show.ended">Ended</mark>
</h3>
<p><strong>Genres :</strong> {{ show.show.genres.join(", ") }}</p>
<img
v-if="show.show.image"
:src="show.show.image.medium"
:alt="show.show.name"
/>
<div v-html="show.show.summary"></div>
<table>
<tbody>
<tr>
<th>Average runtime</th>
<td class="text-right">{{ show.show.averageRuntime }} min</td>
</tr>
<tr>
<th>Premiered</th>
<td class="text-right">{{ show.show.premiered }}</td>
</tr>
<tr>
<th>Ended</th>
<td class="text-right">{{ show.show.ended }}</td>
</tr>
<tr>
<th>Website</th>
<td class="text-right">
<a :href="show.show.officialSite">Official website</a>
</td>
</tr>
</tbody>
</table>
</div>`,
};
let Error = {
props: ["error"],
template: `<p style="color: red; font-weight: bold">😡 {{ error }}</p>`,
};
Vue.createApp({
components: { Search, Post, Error },
data() {
return {
error: "",
shows: [],
};
},
methods: {
updateError(error) {
this.error = error;
},
updateShows(data) {
this.shows = data;
},
},
}).mount("#app");
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>TV Maze</title>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/water.css@2/out/water.min.css"
/>
<style>
.text-right {
text-align: right;
}
</style>
<script src="https://unpkg.com/vue@3/dist/vue.global.js" defer></script>
<script src="app.js" defer></script>
</head>
<body>
<div id="app">
<h1>TV Maze</h1>
<error v-if="error" :error="error"></error>
<search
v-on:results="updateShows"
v-on:update-error="updateError"
></search>
<p v-if="!shows.length"><em>Aucun resultat.</em></p>
<post v-else v-for="show in shows" :show="show"></post>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment