diff --git a/apps/backend/prisma/migrations/20260614000000_add_product_translation/migration.sql b/apps/backend/prisma/migrations/20260614000000_add_product_translation/migration.sql new file mode 100644 index 0000000..ddd8c8d --- /dev/null +++ b/apps/backend/prisma/migrations/20260614000000_add_product_translation/migration.sql @@ -0,0 +1,19 @@ +-- CreateTable +CREATE TABLE "ProductTranslation" ( + "id" SERIAL NOT NULL, + "productId" INTEGER NOT NULL, + "langCode" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "details" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "ProductTranslation_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "ProductTranslation_productId_langCode_key" ON "ProductTranslation"("productId", "langCode"); + +-- AddForeignKey +ALTER TABLE "ProductTranslation" ADD CONSTRAINT "ProductTranslation_productId_fkey" FOREIGN KEY ("productId") REFERENCES "Product"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/apps/spa/src/pages/ProductDetailPage.tsx b/apps/spa/src/pages/ProductDetailPage.tsx index d7ca45b..0130cd0 100644 --- a/apps/spa/src/pages/ProductDetailPage.tsx +++ b/apps/spa/src/pages/ProductDetailPage.tsx @@ -7,9 +7,17 @@ import ProductCard from '../components/ProductCard' import ProductReviews from '../components/ProductReviews' import ProductImageGallery from '../components/ProductImageGallery' import DynamicPageRenderer from '../components/DynamicPageRenderer' -import { API_BASE, getCategoryImage, formatPrice, type Category, type Product, type PageSection } from '../types' +import { API_BASE, getCategoryImage, formatPrice, type Category, type Product, type PageSection, type TranslatableString } from '../types' import { useCartStore } from '../store/cartStore' +/** แปลง TranslatableString (string | Record) เป็น string ตาม locale */ +function resolveTranslatable(value: TranslatableString | null | undefined, lang: string): string { + if (!value) return '' + if (typeof value === 'string') return value + // Record: ลอง lang เต็ม → ลอง prefix 2 ตัว → fallback 'th'/'en' + return value[lang] ?? value[lang.slice(0, 2)] ?? value['th'] ?? value['en'] ?? Object.values(value)[0] ?? '' +} + export default function ProductDetailPage() { const { id } = useParams<{ id: string }>() @@ -176,8 +184,8 @@ export default function ProductDetailPage() {

- {product.description && ( -

{product.description}

+ {resolveTranslatable(product.description, i18n.language) && ( +

{resolveTranslatable(product.description, i18n.language)}

)} {/* Price */} @@ -250,12 +258,12 @@ export default function ProductDetailPage() { {/* Full Details Section */} - {product.details && ( + {resolveTranslatable(product.details, i18n.language) && (

Product Details

)}