diff --git a/bo/src/composable/useConteditable.ts b/bo/src/composable/useConteditable.ts new file mode 100644 index 0000000..2a7803f --- /dev/null +++ b/bo/src/composable/useConteditable.ts @@ -0,0 +1,37 @@ +import { ref, type Ref } from 'vue' +import DOMPurify from 'dompurify' +import { useProductStore } from '@/stores/product' + +export function useEditable() { + const isEditing = ref(false) + const productStore = useProductStore() + + const removeAttribute = (editableRef: HTMLElement | null) => { + if (!editableRef) return + isEditing.value = true + Array.from(editableRef.children).forEach(item => { + item.setAttribute('contenteditable', 'true') + console.log('lllllll') + }) + } + + const setAttribute = async (editableRef: HTMLElement | null): Promise => { + if (!editableRef) return + Array.from(editableRef.children).forEach(item => { + item.setAttribute('contenteditable', 'false') + }) + isEditing.value = false + + const html = editableRef.innerHTML + const cleanHtml = DOMPurify.sanitize(html) + await productStore.saveProductDescription(cleanHtml) + + return cleanHtml + } + + return { + isEditing, + removeAttribute, + setAttribute + } +} \ No newline at end of file diff --git a/bo/src/stores/product.ts b/bo/src/stores/product.ts index 7dec3d7..5b23bd3 100644 --- a/bo/src/stores/product.ts +++ b/bo/src/stores/product.ts @@ -49,9 +49,7 @@ export const useProductStore = defineStore('product', () => { currentProduct.value = null try { - const data = await useFetchJson<{ items: Product }>(`/api/v1/restricted/product-description?id=${id}`, { - method: 'GET', - }) + const data = await useFetchJson<{ items: Product }>(`/api/v1/restricted/product-description?id=${id}`) const response = (data as any).items || data currentProduct.value = response.items?.[0] || response @@ -63,6 +61,34 @@ export const useProductStore = defineStore('product', () => { } } + + async function saveProductDescription(description: string) { + try { + const data = await useFetchJson( + `/api/v1/restricted/product-description/save-product-description?productID=1&productShopID=1&productLangID=1`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + description: description, + description_short: "

Test short

", + meta_description: "This is a test", + meta_title: "...", + name: "...", + available_now: "Test", + available_later: "...", + usage: "

test

" + }) + } + ) + return data + } catch (e) { + console.error(e) + } + } + // Clear current product function clearCurrentProduct() { currentProduct.value = null @@ -76,5 +102,6 @@ export const useProductStore = defineStore('product', () => { getProductDescription, fetchProductById, clearCurrentProduct, + saveProductDescription } }) diff --git a/bo/src/views/customer/ProductDetailView.vue b/bo/src/views/customer/ProductDetailView.vue index e7b52ee..4b5254a 100644 --- a/bo/src/views/customer/ProductDetailView.vue +++ b/bo/src/views/customer/ProductDetailView.vue @@ -1,34 +1,36 @@ @@ -39,4 +41,5 @@ const create = () => { gap: 70px; margin: 20px 0 20px 0; } + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 06db83f..340bbe2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,7 @@ "dependencies": { "@nuxt/ui": "^4.5.1", "chart.js": "^4.5.1", + "dompurify": "^3.3.3", "vue-chartjs": "^5.3.3" } }, @@ -1960,6 +1961,13 @@ "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", "license": "MIT" }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT", + "optional": true + }, "node_modules/@types/web-bluetooth": { "version": "0.0.21", "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", @@ -2441,6 +2449,15 @@ "node": ">=8" } }, + "node_modules/dompurify": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.3.tgz", + "integrity": "sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, "node_modules/dotenv": { "version": "17.3.1", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz", diff --git a/package.json b/package.json index 95e04f5..bc75906 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "dependencies": { "@nuxt/ui": "^4.5.1", "chart.js": "^4.5.1", + "dompurify": "^3.3.3", "vue-chartjs": "^5.3.3" } } diff --git a/tmp/main b/tmp/main index 361c013..a844282 100755 Binary files a/tmp/main and b/tmp/main differ