feat [front]: api in composables
This commit is contained in:
parent
b6c6514ad5
commit
64787d914c
3 changed files with 121 additions and 4 deletions
|
@ -1,4 +1,102 @@
|
||||||
/* TODO function to access TMDB
|
import { NuxtApp } from "nuxt3/dist/app/nuxt"
|
||||||
- https://github.com/sindresorhus/camelcase-keys/issues/60 to manage keys' case
|
import { useLoadingStore } from "~/stores/loadingStore"
|
||||||
- https://v3.nuxtjs.org/docs/usage/data-fetching/
|
|
||||||
* */
|
type MyHeaders = { [key: string]: string }
|
||||||
|
|
||||||
|
const makeLoadingKey = (path: string) => {
|
||||||
|
// camel-case the path : auth/login -> authLogin
|
||||||
|
if (path.endsWith("/")) {
|
||||||
|
path = path.slice(0, -1)
|
||||||
|
}
|
||||||
|
if (path.startsWith("/")) {
|
||||||
|
path = path.slice(1)
|
||||||
|
}
|
||||||
|
let words = path.split("/")
|
||||||
|
words = words.filter((word) => !/^\d+$/.test(word))
|
||||||
|
for (const [ix, word] of Object.entries(words.slice(1))) {
|
||||||
|
words[parseInt(ix) + 1] = word[0].toUpperCase() + word.slice(1)
|
||||||
|
}
|
||||||
|
return words.join("")
|
||||||
|
}
|
||||||
|
|
||||||
|
const getCsrfCookie = (ctx: NuxtApp) => {
|
||||||
|
let cookie = ""
|
||||||
|
if (ctx?.ssrContext?.req.headers.cookie) {
|
||||||
|
cookie = ctx?.ssrContext.req.headers.cookie
|
||||||
|
} else if (process.client) {
|
||||||
|
cookie = document.cookie
|
||||||
|
}
|
||||||
|
if (!cookie) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const csfrRow = cookie.split("; ").find((row) => row.startsWith("csrftoken="))
|
||||||
|
if (!csfrRow) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return csfrRow.split("=")[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
const getHeaders = (ctx: NuxtApp, includeCsrf = false): MyHeaders => {
|
||||||
|
const headers: MyHeaders = useRequestHeaders(["cookie"])
|
||||||
|
if (includeCsrf) {
|
||||||
|
const csfrToken = getCsrfCookie(ctx)
|
||||||
|
if (csfrToken) {
|
||||||
|
headers["X-CSRFTOKEN"] = csfrToken
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return headers
|
||||||
|
}
|
||||||
|
|
||||||
|
let host
|
||||||
|
// local
|
||||||
|
if (process.env.NODE_ENV !== "production") {
|
||||||
|
host = "http://localhost:8000"
|
||||||
|
} else {
|
||||||
|
// production server
|
||||||
|
if (process.server) {
|
||||||
|
// server-side rendering
|
||||||
|
host = "http://localhost:8064"
|
||||||
|
} else {
|
||||||
|
host = "https://cineclub.ens.fr" //use env params ?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const baseUrl = `${host}/api/`
|
||||||
|
|
||||||
|
export async function apiRequest<Type>(
|
||||||
|
method: string,
|
||||||
|
path: string,
|
||||||
|
payload,
|
||||||
|
params = {}
|
||||||
|
) {
|
||||||
|
const loadingStore = useLoadingStore()
|
||||||
|
|
||||||
|
const key = makeLoadingKey(path)
|
||||||
|
loadingStore.markLoading(key)
|
||||||
|
const { data, error } = await useAsyncData<Type>(key, (ctx) =>
|
||||||
|
$fetch(baseUrl + path, {
|
||||||
|
method: method,
|
||||||
|
body: payload,
|
||||||
|
credentials: "include",
|
||||||
|
headers: getHeaders(ctx, true),
|
||||||
|
params: params,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
if (error.value) {
|
||||||
|
loadingStore.markError(key)
|
||||||
|
} else {
|
||||||
|
loadingStore.markDone(key)
|
||||||
|
}
|
||||||
|
return { data, error }
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function apiGet<Type>(path: string, params = {}) {
|
||||||
|
return apiRequest<Type>("GET", path, undefined, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function apiPost<Type>(path: string, payload = {}, params = {}) {
|
||||||
|
return apiRequest<Type>("POST", path, payload, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function apiPatch<Type>(path: string, payload = {}, params = {}) {
|
||||||
|
return apiRequest<Type>("PATCH", path, payload, params)
|
||||||
|
}
|
||||||
|
|
|
@ -164,12 +164,17 @@ definePageMeta({
|
||||||
|
|
||||||
const foundFilms = ref()
|
const foundFilms = ref()
|
||||||
const film = reactive<Film>({})
|
const film = reactive<Film>({})
|
||||||
|
const { $api } = useNuxtApp()
|
||||||
|
|
||||||
// https://developers.themoviedb.org/3/getting-started/images
|
// https://developers.themoviedb.org/3/getting-started/images
|
||||||
const image = computed(() => (index: number) => {
|
const image = computed(() => (index: number) => {
|
||||||
return `https://image.tmdb.org/t/p/w500${foundFilms.value?.results[index].poster_path}`
|
return `https://image.tmdb.org/t/p/w500${foundFilms.value?.results[index].poster_path}`
|
||||||
})
|
})
|
||||||
|
|
||||||
|
async function post() {
|
||||||
|
return await $api.post("films/", film)
|
||||||
|
}
|
||||||
|
|
||||||
async function findFilm() {
|
async function findFilm() {
|
||||||
foundFilms.value = await $fetch("https://api.themoviedb.org/3/search/movie", {
|
foundFilms.value = await $fetch("https://api.themoviedb.org/3/search/movie", {
|
||||||
params: {
|
params: {
|
||||||
|
|
14
front/plugins/api.ts
Normal file
14
front/plugins/api.ts
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import * as api from "~/composables/api"
|
||||||
|
|
||||||
|
export default defineNuxtPlugin(() => {
|
||||||
|
return {
|
||||||
|
provide: {
|
||||||
|
api: {
|
||||||
|
request: api.apiRequest,
|
||||||
|
get: api.apiGet,
|
||||||
|
post: api.apiPost,
|
||||||
|
patch: api.apiPost,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
Loading…
Reference in a new issue