fix: style

This commit is contained in:
2026-04-02 11:42:12 +02:00
parent 7e8e9897e1
commit 9513feba37
2 changed files with 58 additions and 125 deletions

View File

@@ -1,10 +1,14 @@
<template> <template>
<component :is="Default || 'div'"> <component :is="Default || 'div'">
<p class="cursor-pointer" @click="backFromProduct()">Back to products</p> <div class="flex items-center gap-2 mb-4">
<div class="container my-10 mx-auto "> <UIcon name="line-md:arrow-left" class="text-(--accent-blue-light) dark:text-(--accent-blue-dark)" />
<p class="cursor-pointer text-(--accent-blue-light) dark:text-(--accent-blue-dark)" @click="backFromProduct()">
Back to products</p>
</div>
<div class="container mx-auto ">
<div <div
class=" gap-4 mb-6 bg-(--second-light) dark:bg-(--main-dark) border border-(--border-light) dark:border-(--border-dark) p-4 rounded-md"> class=" gap-4 mb-6 bg-(--second-light) dark:bg-(--main-dark) border border-(--border-light) dark:border-(--border-dark) p-4 rounded-md">
<div v-if="!isShowProductView" class="flex items-end justify-between"> <div v-if="!isShowProductView" class="flex items-center justify-between">
<div class="flex items-center gap-3" v-if="!isTranslations"> <div class="flex items-center gap-3" v-if="!isTranslations">
<p class="text-red-500 text-md whitespace-nowrap">Translate from Polish to</p> <p class="text-red-500 text-md whitespace-nowrap">Translate from Polish to</p>
<USelect v-model="toLangId" :items="availableLangs" value-key="id" label-key="name" <USelect v-model="toLangId" :items="availableLangs" value-key="id" label-key="name"
@@ -21,7 +25,7 @@
</USelect> </USelect>
</div> </div>
<div class="flex gap-3 items-end justify-end"> <div class="flex gap-3">
<UButton @click="() => { <UButton @click="() => {
fetchForLanguage(toLangId) fetchForLanguage(toLangId)
isShowProductView = true isShowProductView = true
@@ -34,7 +38,7 @@
class="text-white bg-(--accent-blue-light) dark:bg-(--accent-blue-dark) px-12!"> class="text-white bg-(--accent-blue-light) dark:bg-(--accent-blue-dark) px-12!">
Translate Translate
</UButton> </UButton>
<div v-else class="flex gap-3 items-end justify-end"> <div v-else class="flex gap-3">
<UButton @click="() => { <UButton @click="() => {
toLangId = settingStore.shopDefaultLanguage toLangId = settingStore.shopDefaultLanguage
isTranslations = false isTranslations = false
@@ -50,7 +54,8 @@
</div> </div>
<div v-else> <div v-else>
<UButton @click="isShowProductView = false" color="primary" <UButton @click="isShowProductView = false" color="primary"
class="text-white bg-(--accent-blue-light) dark:bg-(--accent-blue-dark) px-12!"> class="text-white bg-(--accent-blue-light) dark:bg-(--accent-blue-dark) gap-2">
<UIcon name="line-md:arrow-left" class="" />
Back Back
</UButton> </UButton>
</div> </div>
@@ -162,7 +167,6 @@ import Default from '@/layouts/default.vue';
import { langs } from '@/router/langs'; import { langs } from '@/router/langs';
import { useProductStore } from '@/stores/product'; import { useProductStore } from '@/stores/product';
import { useSettingsStore } from '@/stores/settings'; import { useSettingsStore } from '@/stores/settings';
import { watch } from 'vue';
import { onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue';
import { computed } from 'vue'; import { computed } from 'vue';
import { useRoute, useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
@@ -226,6 +230,8 @@ const translateToSelectedLanguage = async () => {
const fetchForLanguage = async (langId: number | null) => { const fetchForLanguage = async (langId: number | null) => {
if (productID.value) { if (productID.value) {
await productStore.getProductDescription(langId, productID.value) await productStore.getProductDescription(langId, productID.value)
removeInlineStylesFromAll(productStore.productDescription)
removePStyles(productStore.productDescription)
} }
} }
@@ -237,6 +243,7 @@ onMounted(async () => {
} }
}) })
// text edit // text edit
const enableEdit = () => { const enableEdit = () => {
if (usageRef.value) { if (usageRef.value) {
@@ -290,4 +297,48 @@ const cancelDescriptionEdit = () => {
} }
descriptionEdit.disableEdit() descriptionEdit.disableEdit()
} }
function removeInlineStylesFromAll(product) {
if (!product) return
const removeStyles = (html: string) => {
if (!html) return ''
const div = document.createElement('div')
div.innerHTML = html
div.querySelectorAll('*').forEach(el => {
const bg = el.style.background || el.style.backgroundColor
if (bg) {
el.style.background = ''
el.style.backgroundColor = ''
}
})
div.querySelectorAll('p').forEach(p => {
if (p.querySelector('img')) {
p.style.display = 'flex'
p.style.gap = '20px'
p.style.padding = '30px 0'
}
})
div.querySelectorAll('table').forEach(table => {
table.querySelectorAll('tbody').forEach(tbody => {
tbody.style.setProperty('background-color', 'white', 'important')
tbody.querySelectorAll('tr').forEach(tr => {
tr.querySelectorAll('td').forEach(td => {
td.style.setProperty('padding', '10px', 'important')
td.querySelectorAll('p').forEach(p => {
p.style.setProperty('display', 'flex', 'important')
p.style.setProperty('padding', '0px', 'important')
p.style.setProperty('align-items', 'start', 'important')
})
})
})
})
})
return div.innerHTML
}
product.description = removeStyles(product.description)
product.description_short = removeStyles(product.description_short)
product.usage = removeStyles(product.usage)
}
</script> </script>

View File

@@ -89,7 +89,6 @@ export const useProductStore = defineStore('product', () => {
available_now: stripHtml(productDescription.value?.available_now || ''), available_now: stripHtml(productDescription.value?.available_now || ''),
available_later: stripHtml(productDescription.value?.available_later || ''), available_later: stripHtml(productDescription.value?.available_later || ''),
usage: stripHtml(productDescription.value?.usage || ''), usage: stripHtml(productDescription.value?.usage || ''),
// delivery_in_stock: stripHtml(productDescription.value?.delivery_in_stock || '')
}) })
} }
) )
@@ -109,120 +108,3 @@ export const useProductStore = defineStore('product', () => {
} }
}) })
// import { defineStore } from 'pinia'
// import { ref } from 'vue'
// import { useFetchJson } from '@/composable/useFetchJson'
// import type { ProductDescription } from '@/types/product'
// import { useSettingsStore } from './settings'
// export interface Product {
// id: number
// image: string
// name: string
// code: string
// inStock: boolean
// priceFrom: number
// priceTo: number
// count: number
// description?: string
// howToUse?: string
// productDetails?: string
// }
// export interface ProductResponse {
// items: Product[]
// items_count: number
// }
// export const useProductStore = defineStore('product', () => {
// const productDescription = ref()
// const currentProduct = ref<Product | null>(null)
// const loading = ref(false)
// const error = ref<string | null>(null)
// async function getProductDescription(langId = 1, productID: number) {
// loading.value = true
// error.value = null
// try {
// const response = await useFetchJson<ProductDescription>(
// `/api/v1/restricted/product-translation/get-product-description?productID=${productID}&productLangID=${langId}`
// )
// productDescription.value = response.items
// console.log(productDescription, 'dfsfsdf');
// } catch (e: unknown) {
// error.value = e instanceof Error ? e.message : 'Failed to load product description'
// } finally {
// loading.value = false
// }
// }
// function stripHtml(html: string) {
// const div = document.createElement('div')
// div.innerHTML = html
// return div.textContent || div.innerText || ''
// }
// async function saveProductDescription(productID?: number, langId?: number) {
// const id = productID || 1
// const lang = langId || 1
// try {
// const data = await useFetchJson(
// `/api/v1/restricted/product-translation/save-product-description?productID=${id}&productLangID=${lang}`,
// {
// method: 'POST',
// headers: {
// 'Content-Type': 'application/json'
// },
// body: JSON.stringify({
// name: stripHtml(productDescription.value?.name || ''),
// description: stripHtml(productDescription.value?.description || ''),
// description_short: stripHtml(productDescription.value?.description_short || ''),
// meta_title: stripHtml(productDescription.value?.meta_title || ''),
// meta_description: stripHtml(productDescription.value?.meta_description || ''),
// available_now: stripHtml(productDescription.value?.available_now || ''),
// available_later: stripHtml(productDescription.value?.available_later || ''),
// usage: stripHtml(productDescription.value?.usage || '')
// })
// }
// )
// return data
// } catch (e) {
// console.error(e)
// }
// }
// const defaultLangId = ref(1)
// async function translateProductDescription(productID: number, fromLangId: number, defaultLangId: number, model: string = 'OpenAI') {
// loading.value = true
// error.value = null
// try {
// const response = await useFetchJson<ProductDescription>(`/api/v1/restricted/product-translation/translate-product-description?productID=${productID}&productFromLangID=${fromLangId}&productToLangID=${defaultLangId}&model=${model}`)
// productDescription.value = response.items
// return response.items
// } catch (e: any) {
// error.value = e?.message || 'Failed to translate product description'
// console.error('Failed to translate product description:', e)
// } finally {
// loading.value = false
// }
// }
// function clearCurrentProduct() {
// currentProduct.value = null
// }
// return {
// productDescription,
// currentProduct,
// loading,
// error,
// getProductDescription,
// clearCurrentProduct,
// saveProductDescription,
// translateProductDescription,
// }
// })