[FIX] 修復商品多語系儲存與讀取錯誤、新增自動語系名稱顯示、補強商品規格欄位及密碼顯示切換功能
All checks were successful
star-cloud-deploy-demo / deploy-demo (push) Successful in 47s

This commit is contained in:
2026-03-30 17:11:15 +08:00
parent 9bbfaa39e6
commit d14eda7d69
9 changed files with 167 additions and 40 deletions

View File

@@ -484,8 +484,20 @@
<div class="space-y-2">
<label class="text-xs font-black text-slate-500 uppercase tracking-widest pl-1">{{
__('Password') }}</label>
<input type="password" name="admin_password" class="luxury-input w-full"
placeholder="{{ __('Min 8 characters') }}">
<div x-data="{ show: false }" class="relative items-center">
<input :type="show ? 'text' : 'password'" name="admin_password" class="luxury-input w-full pr-12"
placeholder="{{ __('Min 8 characters') }}">
<button type="button" @click="show = !show"
class="absolute inset-y-0 end-0 flex items-center z-20 px-4 cursor-pointer text-slate-400 hover:text-cyan-500 transition-colors">
<svg x-show="!show" class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5">
<path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z" />
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
<svg x-show="show" x-cloak class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5">
<path stroke-linecap="round" stroke-linejoin="round" d="M3.98 8.223A10.477 10.477 0 001.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.45 10.45 0 0112 4.5c4.756 0 8.773 3.162 10.065 7.498a10.523 10.523 0 01-4.293 5.774M6.228 6.228L3 3m3.228 3.228l3.65 3.65m7.894 7.894L21 21m-3.228-3.228l-3.65-3.65m0 0a3 3 0 10-4.243-4.243m4.242 4.242L9.88 9.88" />
</svg>
</button>
</div>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">

View File

@@ -366,9 +366,21 @@ $roleSelectConfig = [
<span class="text-rose-500">*</span>
</template>
</label>
<input type="password" name="password" :required="!editing"
class="luxury-input @error('password') border-rose-500 @enderror"
placeholder="••••••••">
<div x-data="{ show: false }" class="relative items-center">
<input :type="show ? 'text' : 'password'" name="password" :required="!editing"
class="luxury-input w-full pr-12 @error('password') border-rose-500 @enderror"
placeholder="••••••••">
<button type="button" @click="show = !show"
class="absolute inset-y-0 end-0 flex items-center z-20 px-4 cursor-pointer text-slate-400 hover:text-cyan-500 transition-colors">
<svg x-show="!show" class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5">
<path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z" />
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
<svg x-show="show" x-cloak class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5">
<path stroke-linecap="round" stroke-linejoin="round" d="M3.98 8.223A10.477 10.477 0 001.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.45 10.45 0 0112 4.5c4.756 0 8.773 3.162 10.065 7.498a10.523 10.523 0 01-4.293 5.774M6.228 6.228L3 3m3.228 3.228l3.65 3.65m7.894 7.894L21 21m-3.228-3.228l-3.65-3.65m0 0a3 3 0 10-4.243-4.243m4.242 4.242L9.88 9.88" />
</svg>
</button>
</div>
</div>
<div class="flex justify-end gap-x-4 pt-8">

View File

@@ -4,7 +4,7 @@
@php
$names = [];
foreach(['zh_TW', 'en', 'ja'] as $locale) {
$names[$locale] = $product->translations->where('locale', $locale)->first()?->text ?? '';
$names[$locale] = $product->translations->where('locale', $locale)->first()?->value ?? '';
}
// If zh_TW translation is empty, fallback to product->name
if (empty($names['zh_TW'])) {

View File

@@ -90,7 +90,7 @@ $roleSelectConfig = [
@endif
</div>
<div class="flex flex-col">
<span class="text-base font-extrabold text-slate-800 dark:text-slate-100 group-hover:text-cyan-600 dark:group-hover:text-cyan-400 transition-colors">{{ $product->name }}</span>
<span class="text-base font-extrabold text-slate-800 dark:text-slate-100 group-hover:text-cyan-600 dark:group-hover:text-cyan-400 transition-colors">{{ $product->localized_name }}</span>
<div class="flex items-center gap-2 mt-0.5">
@php
$catName = $product->category->name ?? __('Uncategorized');
@@ -236,7 +236,7 @@ $roleSelectConfig = [
<div class="px-6 py-3 border-b border-slate-100 dark:border-slate-800 flex items-center justify-between sticky top-0 bg-white/80 dark:bg-slate-900/80 backdrop-blur-md z-20">
<div>
<h2 class="text-xl font-black text-slate-800 dark:text-white">{{ __('Product Details') }}</h2>
<p class="text-[11px] font-bold text-slate-400 uppercase tracking-[0.2em] mt-1" x-text="selectedProduct?.name + ' (' + getCategoryName(selectedProduct?.category_id) + ')'"></p>
<p class="text-[11px] font-bold text-slate-400 uppercase tracking-[0.2em] mt-1" x-text="(selectedProduct?.localized_name || selectedProduct?.name) + ' (' + getCategoryName(selectedProduct?.category_id) + ')'"></p>
</div>
<button @click="isDetailOpen = false"
class="p-2 rounded-xl hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors">
@@ -281,6 +281,10 @@ $roleSelectConfig = [
<span class="text-xs font-bold text-slate-400 uppercase tracking-widest block mb-1.5">{{ __('Barcode') }}</span>
<div class="text-[15px] font-mono font-bold text-slate-700 dark:text-slate-200" x-text="selectedProduct?.barcode || '-'"></div>
</div>
<div class="bg-slate-50 dark:bg-slate-800/40 p-5 rounded-2xl border border-slate-100 dark:border-slate-800/80 group hover:border-cyan-500/30 transition-colors">
<span class="text-xs font-bold text-slate-400 uppercase tracking-widest block mb-1.5">{{ __('Specification') }}</span>
<div class="text-[15px] font-bold text-slate-700 dark:text-slate-200" x-text="selectedProduct?.spec || '-'"></div>
</div>
<template x-if="selectedProduct?.metadata?.material_code">
<div class="bg-slate-50 dark:bg-slate-800/40 p-5 rounded-2xl border border-slate-100 dark:border-slate-800/80 group hover:border-cyan-500/30 transition-colors">
<span class="text-xs font-bold text-slate-400 uppercase tracking-widest block mb-1.5">{{ __('Material Code') }}</span>
@@ -387,7 +391,7 @@ $roleSelectConfig = [
<img :src="selectedProduct?.image_url" class="max-w-full max-h-full rounded-[2.5rem] shadow-2xl border border-white/10 animate-luxury-in">
<div class="absolute bottom-[-4rem] left-1/2 -translate-x-1/2 text-white/60 text-sm font-bold tracking-widest uppercase animate-luxury-in" style="animation-delay: 200ms">
<span x-text="selectedProduct?.name"></span>
<span x-text="selectedProduct?.localized_name || selectedProduct?.name"></span>
</div>
</div>
</div>