Skip to content

Commit

Permalink
Merge pull request #92 from HE-Arc/sp-89-convert-api-request-to-use-a…
Browse files Browse the repository at this point in the history
…piclient

Sp 89 convert api request to use apiclient
  • Loading branch information
Krucksy authored Apr 9, 2024
2 parents 97cd1a5 + d35be41 commit bf7e6cc
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 281 deletions.
121 changes: 117 additions & 4 deletions frontend/src/api_client.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,128 @@ axios.defaults.baseURL = API_SERVER;
axios.defaults.withCredentials = true;

export default
class APIClient {
class APIClient {
/**
* Get all the categories with current IQ in each category
* (keys are category id)
* @returns
* @returns {Array} {category_id: {category_name: String, user_iq: Number}}
*/
static async getCategories()
{
static async getCategories() {
const response = await axios.get(`/api/category/iq/`);
return response.data;
}

/**
* Get a new question for a given category
* @param {Number} category_id
* @returns {String} question text
*/
static async getNewQuestion(category_id) {
const response = await axios.get(`/api/question/${category_id}/new`);
return response.data.text;
}

/**
* Get if the user has already asked for options
* @returns {Boolean} true if options have been asked, false otherwise
*/
static async getIfOptionsAsked() {
const response = await axios.get(`/api/question/options_asked`);
return !!response.data.options_asked;
}

/**
* Get the options for the current question
* @returns {Object} {"id_option": "text_option"}
*/
static async getOptions() {
const response = await axios.get(`/api/question/options`);
return response.data.options;
}

/**
* Return the image for a given category id
* @param {Number} category_id
* @returns {String} base64 image {data:image/jpeg;base64, ...}
*/
static async getImageCategory(category_id) {
const arrayBufferToBase64 = (buffer) => {
let binary = '';
const bytes = new Uint8Array(buffer);
const len = bytes.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return btoa(binary);
}

const response = await axios.get(`/api/category/${category_id}/image/`,
{
responseType: 'arraybuffer'
});
return 'data:image/jpeg;base64,' + arrayBufferToBase64(response.data);
}

/**
* Get the global leaderboard. It's the best players average IQ in all categories
* @returns {Array} [{user_id: Number, user_name: String, user_score: Number}]
*/
static async getGlobalLeaderboard()
{
const response = await axios.get(`/api/rank/global_leaderboard/`);
return response.data;
}
/**
* Get the global leaderboard specific to a category. It's the players with the best IQ in this category id
* @returns {Array} [{user_id: Number, user_name: String, user_score: Number}]
*/
static async getCategoryLeaderboard(category_id)
{
const response = await axios.get(`/api/rank/${category_id}/leaderboard/`);
return response.data;
}

/**
* Get the global user rank based on average IQ in all categories of the connected player
* @returns {Object} {user_rank: Number, user_score: Number}
*/
static async getGlobalUserRank()
{
const response = await axios.get(`/api/rank/global_user/`);
return response.data;
}

/**
* Get the user rank specific to a category.
* @returns {Object} {user_rank: Number, user_score: Number}
*/
static async getCategoryUserRank(category_id)
{
const response = await axios.get(`/api/rank/${category_id}/user/`);
return response.data;
}

/**
* Post the answer to the question as a text
* @param {String} answer_text
* @returns {Object} {user_is_correct: Boolean, right_answer: String, answer_sent: String}
*/
static async postAnswerText(answer_text) {
const response = await axios.post(`/api/question/answer_text/`, {
answer: answer_text,
});
return response.data;
}

/**
* Post the answer to the question as an options
* @param {String} option_id
* @returns {Object} {user_is_correct: Boolean, right_answer: String, answer_sent: String}
*/
static async postAnswerOption(option_id) {
const response = await axios.post(`/api/question/answer_option/`, {
answer: option_id,
});
return response.data;
}
}
19 changes: 6 additions & 13 deletions frontend/src/components/AnswerForm.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup>
import axios from 'axios';
import APIClient from '@/api_client';
import { defineEmits, onMounted, ref, defineProps, watch } from 'vue';
// variables specific to this component
Expand All @@ -20,27 +20,20 @@ const props = defineProps({
})
const submitAnswerText = async () => {
const response = await axios.post(`/api/question/answer_text/`, {
answer: answer_text.value,
});
response_to_answer.value = response.data;
response_to_answer.value = await APIClient.postAnswerText(answer_text.value);
answer_sent.value = true;
}
const submitAnswerOption = async (key) => {
const response = await axios.post(`/api/question/answer_option/`, {
answer: key,
});
response_to_answer.value = response.data;
const submitAnswerOption = async (id) => {
response_to_answer.value = await APIClient.postAnswerOption(id);
answer_sent.value = true;
}
const fetchOptions = async () => {
show_text_form.value = false;
const response = await axios.get(`/api/question/options/`, {
});
options.value = response.data.options;
options.value = await APIClient.getOptions();
}
const newQuestion = () => {
answer_sent.value = false;
show_text_form.value = true;
Expand Down
26 changes: 5 additions & 21 deletions frontend/src/components/CategoryItem.vue
Original file line number Diff line number Diff line change
@@ -1,37 +1,21 @@
<script setup>
import axios from 'axios';
import APIClient from '@/api_client';
import { onMounted, ref } from 'vue';
const API_SERVER = import.meta.env.VITE_API_SERVER;
const imageUrl = ref('');
const fetchImage = async () => {
const response = await axios.get(`${API_SERVER}/api/category/${props.id}/image/`, { responseType: 'arraybuffer' });
imageUrl.value = 'data:image/jpeg;base64,' + arrayBufferToBase64(response.data);
}
const arrayBufferToBase64 = (buffer) => {
let binary = '';
const bytes = new Uint8Array(buffer);
const len = bytes.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return btoa(binary);
}
const imageData = ref('');
const props = defineProps({
id: Number,
category: Object
})
onMounted(() => {
fetchImage();
onMounted(async () => {
imageData.value = await APIClient.getImageCategory(props.id);
});
</script>

<template>
<RouterLink class="link" :to="{ name: 'Quiz', params: { id_category: id } }">
<div class="category-item" :style="{ backgroundImage: 'url(' + imageUrl + ')' }">
<div class="category-item" :style="{ backgroundImage: 'url(' + imageData + ')' }">
<div class="opacity-filter">
<h2 class="name">{{ category.category_name }}</h2>
<p class="iq">{{ category.user_iq }}</p>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/CustomInput.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup>
import { ref, computed } from 'vue';
import { computed } from 'vue';
const props = defineProps({
label: {
Expand Down
44 changes: 0 additions & 44 deletions frontend/src/components/HelloWorld.vue

This file was deleted.

28 changes: 10 additions & 18 deletions frontend/src/components/LeaderBoard.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup>
import axios from 'axios';
import APIClient from '@/api_client';
import { defineProps, onMounted, ref } from 'vue';
const props = defineProps({
Expand All @@ -13,26 +13,18 @@ const props = defineProps({
const leaderboard = ref([]);
const user_rank = ref(null);
const fetchLeaderboard = async () => {
// is the global leaderboard
let url_rank_leaderboard = `/api/rank/global_leaderboard/`;
let url_rank_user = `/api/rank/global_user/`;
onMounted(async () => {
if (props.id_category !== undefined) {
// is a category leaderboard
url_rank_leaderboard = `/api/rank/${props.id_category}/leaderboard/`;
url_rank_user = `/api/rank/${props.id_category}/user/`;
leaderboard.value = await APIClient.getCategoryLeaderboard(props.id_category);
user_rank.value = await APIClient.getCategoryUserRank(props.id_category);
}
else
{
// is the global leaderboard
leaderboard.value = await APIClient.getGlobalLeaderboard();
user_rank.value = await APIClient.getGlobalUserRank();
}
const response_leaderboard = await axios.get(url_rank_leaderboard);
leaderboard.value = response_leaderboard.data;
const response_user = await axios.get(url_rank_user);
user_rank.value = response_user.data;
}
onMounted(() => {
fetchLeaderboard();
});
</script>
Expand Down
Loading

0 comments on commit bf7e6cc

Please sign in to comment.