Align CMS title fallbacks and mutation error handling.

Add blog post untitled helper, use product title helper in order views, and surface API validation messages on product save/delete.
This commit is contained in:
2026-09-16 16:20:52 +02:00
parent 09ad236cb9
commit 0cd7158f7d
5 changed files with 18 additions and 7 deletions
+3 -2
View File
@@ -15,7 +15,7 @@
target="_blank"
rel="noopener"
>
{{ row.productTitle }}
{{ getProductTitle(row.productTitle) }}
</router-link>
</template>
</el-table-column>
@@ -113,6 +113,7 @@ import type { OrderExtended } from '@/types/order/OrderExtended';
import { DeliveryMode } from '@/types/product/DeliveryMode';
import { formatDeliveryMode } from '@/utils/product/formatDeliveryMode';
import { formatFiatPrice } from '@/utils/formatFiatPrice';
import { getProductTitle } from '@/utils/product/getProductTitle';
import { resolveAxiosErrorMessage } from '@/utils/resolveAxiosErrorMessage';
const props = defineProps({
@@ -143,7 +144,7 @@ const openAutoDelivery = (line: OrderLine): void => {
const markAsFulfilled = async (line: OrderLine): Promise<void> => {
try {
await ElMessageBox.confirm(
`Mark "${line.productTitle}" (${line.variantTitle}) as fulfilled? This cannot be undone.`,
`Mark "${getProductTitle(line.productTitle)}" (${line.variantTitle}) as fulfilled? This cannot be undone.`,
'Mark as fulfilled',
{
type: 'warning',
@@ -70,6 +70,7 @@ import type { OrderLine } from '@/types/order/OrderLine';
import type { OrderLineAutoFulfillmentItem } from '@/types/order/OrderLineAutoFulfillmentItem';
import type { OrderLineAutoFulfillmentItemAttachment } from '@/types/order/OrderLineAutoFulfillmentItemAttachment';
import { formatFileSize } from '@/utils/formatFileSize';
import { getProductTitle } from '@/utils/product/getProductTitle';
const props = defineProps({
modelValue: {
@@ -99,7 +100,7 @@ const lineSummary = computed((): string => {
return '';
}
return `${line.productTitle} · ${line.variantTitle}`;
return `${getProductTitle(line.productTitle)} · ${line.variantTitle}`;
});
const downloadAttachment = async (
+1
View File
@@ -0,0 +1 @@
export const UNTITLED_BLOG_POST_TITLE = '(untitled)';
+3
View File
@@ -0,0 +1,3 @@
import { UNTITLED_BLOG_POST_TITLE } from '@/consts/untitledBlogPostTitle';
export const getBlogPostTitle = (title: string | undefined | null): string => title || UNTITLED_BLOG_POST_TITLE;
+9 -4
View File
@@ -131,6 +131,7 @@ import { useCategoriesStore } from '@/stores/categories';
import { useProductsStore } from '@/stores/products';
import type { ProductVariantExtended } from '@/types/product/ProductVariantExtended';
import { formatFiatPrice } from '@/utils/formatFiatPrice';
import { resolveAxiosErrorMessage } from '@/utils/resolveAxiosErrorMessage';
import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus';
import { storeToRefs } from 'pinia';
import { computed, onBeforeMount, reactive, ref } from 'vue';
@@ -241,8 +242,10 @@ const submitProduct = async (): Promise<void> => {
});
ElMessage.success('Product saved');
} catch {
ElMessage.error('Could not save product');
} catch (e) {
const message = resolveAxiosErrorMessage(e, 'Could not save product');
ElMessage.error(message);
} finally {
productSaving.value = false;
}
@@ -288,8 +291,10 @@ const confirmDeleteProduct = async (): Promise<void> => {
await productsStore.deleteProduct(pid);
ElMessage.success('Product deleted');
router.push({ name: ROUTE_NAMES.Products });
} catch {
ElMessage.error('Could not delete product');
} catch (e) {
const message = resolveAxiosErrorMessage(e, 'Could not delete product');
ElMessage.error(message);
} finally {
deleteSaving.value = false;
}