From d863bf25fce1e3b1ce3dcfbec5cbb71933575697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathilde=20H=C3=A9tru?= Date: Fri, 13 Feb 2026 13:25:13 +0100 Subject: [PATCH 01/14] feat: supabase + api + pinia --- app/assets/css/main.css | 11 +- app/components/SearchItem.vue | 92 +++++++++++- app/pages/[id].vue | 14 ++ app/stores/entites.store.ts | 134 ++++++++++++++++++ app/types/database.types.ts | 18 +++ nuxt.config.ts | 7 + package-lock.json | 231 ++++++++++++++++++++++++++++++- package.json | 2 + server/api/entites/[id].get.ts | 24 ++++ server/api/entites/index.get.ts | 27 ++++ server/api/entites/search.get.ts | 25 ++++ tailwind.config.ts | 31 +++-- 12 files changed, 593 insertions(+), 23 deletions(-) create mode 100644 app/pages/[id].vue create mode 100644 app/stores/entites.store.ts create mode 100644 app/types/database.types.ts create mode 100644 server/api/entites/[id].get.ts create mode 100644 server/api/entites/index.get.ts create mode 100644 server/api/entites/search.get.ts diff --git a/app/assets/css/main.css b/app/assets/css/main.css index 253a174..8993501 100644 --- a/app/assets/css/main.css +++ b/app/assets/css/main.css @@ -13,10 +13,13 @@ body { @layer base { :root { /* Couleurs */ - --primary: 59 130 246; - --secondary: 139 92 246; - --accent: 236 72 153; - --depth: #dadada; + --ui-primary: var(--color-indigo-900); + --ui-secondary: var(--color-indigo-400); + --depth: var(--color-slate-200); + --ui-success: var(--color-indigo-900); + --ui-info: var(--ui-color-teal-500); + --ui-warning: var(--ui-color-rose-500); + --ui-error: var(--ui-color-red-700); /* Spacing */ --spacing-sm: 0.5rem; diff --git a/app/components/SearchItem.vue b/app/components/SearchItem.vue index 13d02b2..5d47794 100644 --- a/app/components/SearchItem.vue +++ b/app/components/SearchItem.vue @@ -1,7 +1,91 @@ + + - - diff --git a/app/pages/[id].vue b/app/pages/[id].vue new file mode 100644 index 0000000..6184e8e --- /dev/null +++ b/app/pages/[id].vue @@ -0,0 +1,14 @@ + + + diff --git a/app/stores/entites.store.ts b/app/stores/entites.store.ts new file mode 100644 index 0000000..a2c4f85 --- /dev/null +++ b/app/stores/entites.store.ts @@ -0,0 +1,134 @@ +import { defineStore } from 'pinia' +import { ref, computed } from 'vue' +import type { Entite } from '~/types/database.types' + +export const useEntitesStore = defineStore('entites', () => { + const entites = ref([]) + const typeFilter = ref<'tous' | 'personnage' | 'lieu' | 'creature'>('tous') + const searchValue = ref('') + const loading = ref(false) + const error = ref(null) + + //TODO rework types and error types + const loadEntites = async () => { + loading.value = true + error.value = null + + try { + const data = await $fetch('/api/entites', { + params: typeFilter.value !== 'tous' ? { type: typeFilter.value } : {}, + }) + + entites.value = data || [] + //@ts-except-error + } catch (e) { + const err = e as Error + error.value = err.message + } finally { + loading.value = false + } + } + + // Récupérer une entité par ID + const getEntiteById = async (id: string) => { + try { + return await $fetch(`/api/entites/${id}`) + } catch (e) { + const err = e as Error + error.value = err.message + throw error + } + } + + // Rechercher + const searchEntites = async (terme: string) => { + if (!terme) { + await loadEntites() + return + } + + loading.value = true + error.value = null + + try { + entites.value = await $fetch('/api/entites/search', { + params: { q: terme }, + }) + } catch (e) { + const err = e as Error + error.value = err.message + } finally { + loading.value = false + } + } + + // Entités filtrées par recherche locale + const entitesFilter = computed(() => { + if (!searchValue.value) return entites.value + + return entites.value.filter((e) => + e.nom.toLowerCase().includes(searchValue.value.toLowerCase()) + ) + }) + + // // Ajouter une entité + // const ajouterEntite = async (entite: Partial) => { + // try { + // const nouvelleEntite = await $fetch('/api/entites', { + // method: 'POST', + // body: entite + // }) + + // await loadEntites() // Recharger la liste + // return nouvelleEntite + // } catch (e: any) { + // error.value = e.message + // throw e + // } + // } + + // // Mettre à jour + // const mettreAJourEntite = async (id: string, updates: Partial) => { + // try { + // const entiteMaj = await $fetch(`/api/entites/${id}`, { + // method: 'PATCH', + // body: updates + // }) + + // await loadEntites() // Recharger la liste + // return entiteMaj + // } catch (e: any) { + // error.value = e.message + // throw e + // } + // } + + // // Supprimer + // const supprimerEntite = async (id: string) => { + // try { + // await $fetch(`/api/entites/${id}`, { + // method: 'DELETE' + // }) + + // await loadEntites() // Recharger la liste + // } catch (e: any) { + // error.value = e.message + // throw e + // } + // } + + return { + entites, + typeFilter, + searchValue, + loading, + error, + entitesFilter, + loadEntites, + getEntiteById, + searchEntites, + // ajouterEntite, + // mettreAJourEntite, + // supprimerEntite + } +}) diff --git a/app/types/database.types.ts b/app/types/database.types.ts new file mode 100644 index 0000000..42347fc --- /dev/null +++ b/app/types/database.types.ts @@ -0,0 +1,18 @@ +export type EntiteType = 'personnage' | 'lieu' | 'creature' + +export type Entite = { + id: string + created_at: string + nom: string + type: EntiteType + description?: string + image_url?: string + tags?: string[] + espece?: string + vivant?: boolean + dangereux?: boolean + hostile?: boolean + tome?: string + relations?: string[] + lieu_id?: string +} diff --git a/nuxt.config.ts b/nuxt.config.ts index 98c35a5..509f9d5 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -10,6 +10,8 @@ export default defineNuxtConfig({ 'nuxt-security', '@nuxt/ui', '@nuxt/fonts', + '@nuxtjs/supabase', + '@pinia/nuxt', ], vite: { server: { @@ -41,6 +43,11 @@ export default defineNuxtConfig({ branch: 'content', }, }, + supabase: { + redirect: false, + url: process.env.SUPABASE_URL, + key: process.env.SUPABASE_KEY, + }, app: { head: { script: diff --git a/package-lock.json b/package-lock.json index bf20ff7..352d6ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,8 @@ "@nuxt/fonts": "^0.13.0", "@nuxt/image": "^2.0.0", "@nuxt/ui": "^4.4.0", + "@nuxtjs/supabase": "^2.0.3", + "@pinia/nuxt": "^0.11.3", "better-sqlite3": "^12.6.2", "nuxt": "^4.3.0", "nuxt-security": "^2.5.1", @@ -4016,6 +4018,18 @@ "vfile": "^6.0.3" } }, + "node_modules/@nuxtjs/supabase": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@nuxtjs/supabase/-/supabase-2.0.3.tgz", + "integrity": "sha512-zfhuOqhbQUijMd5rXS9qzzuVqBMU00gcJyvxFuTBXdS9TAk/gboQZxxX7EQp6eAi5asvtJNM+mwBKqzQwtZi7g==", + "license": "MIT", + "dependencies": { + "@supabase/ssr": "^0.8.0", + "@supabase/supabase-js": "^2.86.0", + "defu": "^6.1.4", + "pathe": "^2.0.3" + } + }, "node_modules/@oxc-minify/binding-android-arm-eabi": { "version": "0.110.0", "resolved": "https://registry.npmjs.org/@oxc-minify/binding-android-arm-eabi/-/binding-android-arm-eabi-0.110.0.tgz", @@ -5306,6 +5320,21 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/@pinia/nuxt": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/@pinia/nuxt/-/nuxt-0.11.3.tgz", + "integrity": "sha512-7WVNHpWx4qAEzOlnyrRC88kYrwnlR/PrThWT0XI1dSNyUAXu/KBv9oR37uCgYkZroqP5jn8DfzbkNF3BtKvE9w==", + "license": "MIT", + "dependencies": { + "@nuxt/kit": "^4.2.0" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "pinia": "^3.0.4" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -6028,6 +6057,98 @@ "eslint": ">=9.0.0" } }, + "node_modules/@supabase/auth-js": { + "version": "2.95.3", + "resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.95.3.tgz", + "integrity": "sha512-vD2YoS8E2iKIX0F7EwXTmqhUpaNsmbU6X2R0/NdFcs02oEfnHyNP/3M716f3wVJ2E5XHGiTFXki6lRckhJ0Thg==", + "license": "MIT", + "dependencies": { + "tslib": "2.8.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@supabase/functions-js": { + "version": "2.95.3", + "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.95.3.tgz", + "integrity": "sha512-uTuOAKzs9R/IovW1krO0ZbUHSJnsnyJElTXIRhjJTqymIVGcHzkAYnBCJqd7468Fs/Foz1BQ7Dv6DCl05lr7ig==", + "license": "MIT", + "dependencies": { + "tslib": "2.8.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@supabase/postgrest-js": { + "version": "2.95.3", + "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-2.95.3.tgz", + "integrity": "sha512-LTrRBqU1gOovxRm1vRXPItSMPBmEFqrfTqdPTRtzOILV4jPSueFz6pES5hpb4LRlkFwCPRmv3nQJ5N625V2Xrg==", + "license": "MIT", + "dependencies": { + "tslib": "2.8.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@supabase/realtime-js": { + "version": "2.95.3", + "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.95.3.tgz", + "integrity": "sha512-D7EAtfU3w6BEUxDACjowWNJo/ZRo7sDIuhuOGKHIm9FHieGeoJV5R6GKTLtga/5l/6fDr2u+WcW/m8I9SYmaIw==", + "license": "MIT", + "dependencies": { + "@types/phoenix": "^1.6.6", + "@types/ws": "^8.18.1", + "tslib": "2.8.1", + "ws": "^8.18.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@supabase/ssr": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@supabase/ssr/-/ssr-0.8.0.tgz", + "integrity": "sha512-/PKk8kNFSs8QvvJ2vOww1mF5/c5W8y42duYtXvkOSe+yZKRgTTZywYG2l41pjhNomqESZCpZtXuWmYjFRMV+dw==", + "license": "MIT", + "dependencies": { + "cookie": "^1.0.2" + }, + "peerDependencies": { + "@supabase/supabase-js": "^2.76.1" + } + }, + "node_modules/@supabase/storage-js": { + "version": "2.95.3", + "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.95.3.tgz", + "integrity": "sha512-4GxkJiXI3HHWjxpC3sDx1BVrV87O0hfX+wvJdqGv67KeCu+g44SPnII8y0LL/Wr677jB7tpjAxKdtVWf+xhc9A==", + "license": "MIT", + "dependencies": { + "iceberg-js": "^0.8.1", + "tslib": "2.8.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@supabase/supabase-js": { + "version": "2.95.3", + "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.95.3.tgz", + "integrity": "sha512-Fukw1cUTQ6xdLiHDJhKKPu6svEPaCEDvThqCne3OaQyZvuq2qjhJAd91kJu3PXLG18aooCgYBaB6qQz35hhABg==", + "license": "MIT", + "dependencies": { + "@supabase/auth-js": "2.95.3", + "@supabase/functions-js": "2.95.3", + "@supabase/postgrest-js": "2.95.3", + "@supabase/realtime-js": "2.95.3", + "@supabase/storage-js": "2.95.3" + }, + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/@swc/helpers": { "version": "0.5.18", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.18.tgz", @@ -7046,7 +7167,6 @@ "version": "25.0.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.10.tgz", "integrity": "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg==", - "devOptional": true, "license": "MIT", "dependencies": { "undici-types": "~7.16.0" @@ -7058,6 +7178,12 @@ "integrity": "sha512-LriObC2+KYZD3FzCrgWGv/qufdUy4eXrxcLgQMfYXgPbLIecKIsVBaQgUPmxSSLcjmYbDTQbMgr6qr6l/eb7Bg==", "license": "MIT" }, + "node_modules/@types/phoenix": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.7.tgz", + "integrity": "sha512-oN9ive//QSBkf19rfDv45M7eZPi0eEXylht2OLEXicu5b4KoQ1OzXIw+xDSGWxSxe1JmepRR/ZH283vsu518/Q==", + "license": "MIT" + }, "node_modules/@types/resolve": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", @@ -7076,6 +7202,15 @@ "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", "license": "MIT" }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.53.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.53.1.tgz", @@ -9448,6 +9583,19 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "license": "MIT" }, + "node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/cookie-es": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-2.0.0.tgz", @@ -12944,6 +13092,15 @@ "url": "https://github.com/sponsors/typicode" } }, + "node_modules/iceberg-js": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/iceberg-js/-/iceberg-js-0.8.1.tgz", + "integrity": "sha512-1dhVQZXhcHje7798IVM+xoo/1ZdVfzOMIc8/rgVSijRK38EDqOJoGula9N/8ZI5RD8QTxNQtK/Gozpr+qUqRRA==", + "license": "MIT", + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -15750,9 +15907,9 @@ } }, "node_modules/nanotar": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/nanotar/-/nanotar-0.2.0.tgz", - "integrity": "sha512-9ca1h0Xjvo9bEkE4UOxgAzLV0jHKe6LMaxo37ND2DAhhAtd0j8pR1Wxz+/goMrZO8AEZTWCmyaOsFI/W5AdpCQ==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/nanotar/-/nanotar-0.2.1.tgz", + "integrity": "sha512-MUrzzDUcIOPbv7ubhDV/L4CIfVTATd9XhDE2ixFeCrM5yp9AlzUpn91JrnN0HD6hksdxvz9IW9aKANz0Bta0GA==", "license": "MIT" }, "node_modules/napi-build-utils": { @@ -16838,6 +16995,71 @@ "node": ">=6" } }, + "node_modules/pinia": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.4.tgz", + "integrity": "sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@vue/devtools-api": "^7.7.7" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "typescript": ">=4.5.0", + "vue": "^3.5.11" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/pinia/node_modules/@vue/devtools-api": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.9.tgz", + "integrity": "sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g==", + "license": "MIT", + "peer": true, + "dependencies": { + "@vue/devtools-kit": "^7.7.9" + } + }, + "node_modules/pinia/node_modules/@vue/devtools-kit": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.9.tgz", + "integrity": "sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@vue/devtools-shared": "^7.7.9", + "birpc": "^2.3.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/pinia/node_modules/@vue/devtools-shared": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.9.tgz", + "integrity": "sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA==", + "license": "MIT", + "peer": true, + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/pinia/node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "license": "MIT", + "peer": true + }, "node_modules/pkg-types": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", @@ -19795,7 +20017,6 @@ "version": "7.16.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "devOptional": true, "license": "MIT" }, "node_modules/unenv": { diff --git a/package.json b/package.json index 8763ed7..e819c36 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,8 @@ "@nuxt/fonts": "^0.13.0", "@nuxt/image": "^2.0.0", "@nuxt/ui": "^4.4.0", + "@nuxtjs/supabase": "^2.0.3", + "@pinia/nuxt": "^0.11.3", "better-sqlite3": "^12.6.2", "nuxt": "^4.3.0", "nuxt-security": "^2.5.1", diff --git a/server/api/entites/[id].get.ts b/server/api/entites/[id].get.ts new file mode 100644 index 0000000..a9e0237 --- /dev/null +++ b/server/api/entites/[id].get.ts @@ -0,0 +1,24 @@ +import { serverSupabaseClient } from '#supabase/server' + +export default defineEventHandler(async (event) => { + const supabase = await serverSupabaseClient(event) + const id = getRouterParam(event, 'id') + + if (!id) { + throw createError({ + statusCode: 400, + message: 'ID manquant', + }) + } + + const { data, error } = await supabase.from('entites').select('*').eq('id', id).single() + + if (error) { + throw createError({ + statusCode: 404, + message: 'Entité non trouvée', + }) + } + + return data +}) diff --git a/server/api/entites/index.get.ts b/server/api/entites/index.get.ts new file mode 100644 index 0000000..2daa976 --- /dev/null +++ b/server/api/entites/index.get.ts @@ -0,0 +1,27 @@ +import { serverSupabaseClient } from '#supabase/server' + +export default defineEventHandler(async (event) => { + const supabase = await serverSupabaseClient(event) + + // Récupérer les paramètres de query (?type=personnage) + const query = getQuery(event) + const type = query.type as string | undefined + + let supabaseQuery = supabase.from('entites').select('*').order('created_at', { ascending: false }) + + // Filtrer par type si fourni + if (type && type !== 'tous') { + supabaseQuery = supabaseQuery.eq('type', type) + } + + const { data, error } = await supabaseQuery + + if (error) { + throw createError({ + statusCode: 500, + message: error.message, + }) + } + + return data +}) diff --git a/server/api/entites/search.get.ts b/server/api/entites/search.get.ts new file mode 100644 index 0000000..36f71de --- /dev/null +++ b/server/api/entites/search.get.ts @@ -0,0 +1,25 @@ +import { serverSupabaseClient } from '#supabase/server' + +export default defineEventHandler(async (event) => { + const supabase = await serverSupabaseClient(event) + const query = getQuery(event) + const searchTerm = query.q as string + + if (!searchTerm) { + throw createError({ + statusCode: 400, + message: 'Terme de recherche manquant', + }) + } + + const { data, error } = await supabase.from('entites').select('*').ilike('nom', `%${searchTerm}%`) + + if (error) { + throw createError({ + statusCode: 500, + message: error.message, + }) + } + + return data +}) diff --git a/tailwind.config.ts b/tailwind.config.ts index 514adcc..6d66a74 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -4,18 +4,29 @@ export default >{ theme: { extend: { colors: { - primary: 'rgb(var(--primary) / )', - secondary: 'rgb(var(--secondary) / )', - accent: 'rgb(var(--accent) / )', + primary: { + 50: '#f5f3ff', + 100: '#ede9fe', + 200: '#ddd6fe', + 300: '#c4b5fd', + 400: '#a78bfa', + 500: '#624e88', // Votre couleur principale + 600: '#7c3aed', + 700: '#6d28d9', + 800: '#5b21b6', + 900: '#4c1d95', + 950: '#2e1065', + }, + secondary: { + 500: '#7b7bf7', + }, + accent: { + 500: '#ff7444', + }, }, fontFamily: { - main: ['var(--font-main)'], - heading: ['var(--font-heading)'], - }, - spacing: { - sm: 'var(--spacing-sm)', - md: 'var(--spacing-md)', - lg: 'var(--spacing-lg)', + main: ['Montserrat', 'sans-serif'], + heading: ['Birthstone Bounce', 'sans-serif'], }, }, }, From 9ea97abd09bdd60d65cf725ecb781a9a0b9d8caa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathilde=20H=C3=A9tru?= Date: Fri, 13 Feb 2026 13:26:07 +0100 Subject: [PATCH 02/14] fix: type Entite --- app/stores/entites.store.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/stores/entites.store.ts b/app/stores/entites.store.ts index a2c4f85..4873797 100644 --- a/app/stores/entites.store.ts +++ b/app/stores/entites.store.ts @@ -51,7 +51,7 @@ export const useEntitesStore = defineStore('entites', () => { error.value = null try { - entites.value = await $fetch('/api/entites/search', { + entites.value = await $fetch('/api/entites/search', { params: { q: terme }, }) } catch (e) { From 37f51df1a0ff346ac16e7c206902d0123806aef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathilde=20H=C3=A9tru?= Date: Fri, 13 Feb 2026 13:26:53 +0100 Subject: [PATCH 03/14] fix: types --- app/stores/entites.store.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/stores/entites.store.ts b/app/stores/entites.store.ts index 4873797..aad2ef7 100644 --- a/app/stores/entites.store.ts +++ b/app/stores/entites.store.ts @@ -20,7 +20,6 @@ export const useEntitesStore = defineStore('entites', () => { }) entites.value = data || [] - //@ts-except-error } catch (e) { const err = e as Error error.value = err.message @@ -29,10 +28,9 @@ export const useEntitesStore = defineStore('entites', () => { } } - // Récupérer une entité par ID const getEntiteById = async (id: string) => { try { - return await $fetch(`/api/entites/${id}`) + return await $fetch(`/api/entites/${id}`) } catch (e) { const err = e as Error error.value = err.message @@ -40,7 +38,6 @@ export const useEntitesStore = defineStore('entites', () => { } } - // Rechercher const searchEntites = async (terme: string) => { if (!terme) { await loadEntites() @@ -62,7 +59,6 @@ export const useEntitesStore = defineStore('entites', () => { } } - // Entités filtrées par recherche locale const entitesFilter = computed(() => { if (!searchValue.value) return entites.value From 6512cd73ffbe7a174c60eace91f5e84a2c37c57c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathilde=20H=C3=A9tru?= Date: Fri, 13 Feb 2026 13:47:07 +0100 Subject: [PATCH 04/14] fix: prettier --- app/components/SearchItem.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/app/components/SearchItem.vue b/app/components/SearchItem.vue index 5d47794..acd0208 100644 --- a/app/components/SearchItem.vue +++ b/app/components/SearchItem.vue @@ -59,7 +59,6 @@ -
Date: Fri, 13 Feb 2026 18:08:08 +0100 Subject: [PATCH 05/14] fix: loading + error --- app/components/SearchItem.vue | 67 ++++++++++++++++++++++++++------- app/stores/entites.store.ts | 37 ++++++++++-------- eslint.config.mjs | 12 ++++++ server/api/entites/index.get.ts | 3 +- 4 files changed, 88 insertions(+), 31 deletions(-) diff --git a/app/components/SearchItem.vue b/app/components/SearchItem.vue index acd0208..f6fe393 100644 --- a/app/components/SearchItem.vue +++ b/app/components/SearchItem.vue @@ -1,8 +1,10 @@