[PROMOTE] dev → demo:交易訂單與發票列表備註欄位晉升驗收
1. [FEAT] 交易訂單與電子發票列表新增可編輯備註欄位(ae4c9fb) - 新增 x-remark-cell 共用元件,列表內嵌備註編輯(AJAX PATCH + toast,不重整)。 - 交易訂單列表(桌面+手機)新增備註欄,接 order.remark。 - 電子發票列表(桌面+手機)新增備註欄,接 invoice.remark。 - 列表與訂單詳情面板共用同一 remark 欄位。 - 新增三語系 key「Add Remark」並對齊排序。 備註:本次無 migration 變更(remark 欄位已於前次晉升建立)。
This commit is contained in:
commit
f8a56f2b4e
@ -63,6 +63,7 @@
|
||||
"Add Pass Code": "Add Pass Code",
|
||||
"Add Pickup Code": "Add Pickup Code",
|
||||
"Add Product": "Add Product",
|
||||
"Add Remark": "Add Remark",
|
||||
"Add Role": "Add Role",
|
||||
"Add Staff Card": "Add Staff Card",
|
||||
"Add Warehouse": "Add Warehouse",
|
||||
|
||||
@ -63,6 +63,7 @@
|
||||
"Add Pass Code": "パスコード追加",
|
||||
"Add Pickup Code": "受取コード追加",
|
||||
"Add Product": "商品追加",
|
||||
"Add Remark": "備考を追加",
|
||||
"Add Role": "ロール追加",
|
||||
"Add Staff Card": "スタッフカード追加",
|
||||
"Add Warehouse": "倉庫追加",
|
||||
|
||||
@ -63,6 +63,7 @@
|
||||
"Add Pass Code": "新增通行碼",
|
||||
"Add Pickup Code": "新增取貨碼",
|
||||
"Add Product": "新增商品",
|
||||
"Add Remark": "新增備註",
|
||||
"Add Role": "新增角色",
|
||||
"Add Staff Card": "新增員工識別卡",
|
||||
"Add Warehouse": "新增倉庫",
|
||||
|
||||
@ -175,6 +175,10 @@
|
||||
class="px-6 py-4 text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-[0.15em] border-b border-slate-100 dark:border-slate-800">
|
||||
{{ __('Associated Order') }}
|
||||
</th>
|
||||
<th
|
||||
class="px-6 py-4 text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-[0.15em] border-b border-slate-100 dark:border-slate-800">
|
||||
{{ __('Remark') }}
|
||||
</th>
|
||||
<th
|
||||
class="px-6 py-4 text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-[0.15em] border-b border-slate-100 dark:border-slate-800 text-right">
|
||||
{{ __('Action') }}
|
||||
@ -235,6 +239,9 @@
|
||||
{{ $invoice->order->order_no ?? '---' }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-6 py-6">
|
||||
<x-remark-cell :url="route('admin.sales.invoices.remark', $invoice)" :value="$invoice->remark" />
|
||||
</td>
|
||||
<td class="px-6 py-6 text-right" @click.stop>
|
||||
<div class="flex items-center justify-end gap-1.5">
|
||||
@if(in_array($st, ['pending', 'failed']))
|
||||
@ -275,8 +282,8 @@
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="6" class="py-20 text-center">
|
||||
<x-empty-state mode="table" colspan="6" :message="__('No invoices found')" />
|
||||
<td colspan="8" class="py-20 text-center">
|
||||
<x-empty-state mode="table" colspan="8" :message="__('No invoices found')" />
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
@ -364,6 +371,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Remark --}}
|
||||
<div class="mb-6">
|
||||
<p class="text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-widest mb-1">{{ __('Remark') }}</p>
|
||||
<x-remark-cell :url="route('admin.sales.invoices.remark', $invoice)" :value="$invoice->remark" />
|
||||
</div>
|
||||
|
||||
{{-- Action Buttons --}}
|
||||
<div class="flex flex-col gap-3">
|
||||
<button @click="openDetail({{ $invoice->order_id }})"
|
||||
|
||||
@ -179,6 +179,10 @@
|
||||
class="px-6 py-4 text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-[0.15em] border-b border-slate-100 dark:border-slate-800">
|
||||
{{ __('Invoice Number') }}
|
||||
</th>
|
||||
<th
|
||||
class="px-6 py-4 text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-[0.15em] border-b border-slate-100 dark:border-slate-800">
|
||||
{{ __('Remark') }}
|
||||
</th>
|
||||
<th
|
||||
class="px-6 py-4 text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-[0.15em] border-b border-slate-100 dark:border-slate-800 text-right">
|
||||
{{ __('Action') }}
|
||||
@ -308,6 +312,9 @@
|
||||
<span class="text-xs font-bold text-slate-300 dark:text-slate-700 tracking-widest">---</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="px-6 py-6">
|
||||
<x-remark-cell :url="route('admin.sales.orders.remark', $order)" :value="$order->remark" />
|
||||
</td>
|
||||
<td class="px-6 py-6 text-right">
|
||||
<button @click.stop="openDetail({{ $order->id }})"
|
||||
class="p-2.5 rounded-xl text-slate-400 hover:text-cyan-500 hover:bg-cyan-500/5 dark:hover:bg-cyan-500/10 border border-transparent hover:border-cyan-500/20 transition-all group/btn"
|
||||
@ -324,8 +331,8 @@
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="8" class="py-20 text-center">
|
||||
<x-empty-state mode="table" colspan="8" :message="__('No transaction orders found')" />
|
||||
<td colspan="9" class="py-20 text-center">
|
||||
<x-empty-state mode="table" colspan="9" :message="__('No transaction orders found')" />
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
@ -456,6 +463,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Remark --}}
|
||||
<div class="mb-6">
|
||||
<p class="text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-widest mb-1">{{ __('Remark') }}</p>
|
||||
<x-remark-cell :url="route('admin.sales.orders.remark', $order)" :value="$order->remark" />
|
||||
</div>
|
||||
|
||||
{{-- Action Buttons --}}
|
||||
<div class="flex items-center gap-3">
|
||||
<button @click="openDetail({{ $order->id }})"
|
||||
|
||||
50
resources/views/components/remark-cell.blade.php
Normal file
50
resources/views/components/remark-cell.blade.php
Normal file
@ -0,0 +1,50 @@
|
||||
@props([
|
||||
'url', // PATCH 端點(更新 remark)
|
||||
'value' => null, // 目前備註內容
|
||||
])
|
||||
|
||||
{{-- 列表內嵌備註編輯:點擊文字進入編輯,fetch 儲存後 toast。@click.stop 避免觸發整列的開啟詳情。 --}}
|
||||
<div @click.stop class="min-w-[150px] max-w-[220px]"
|
||||
x-data="{
|
||||
editing: false,
|
||||
saving: false,
|
||||
value: @js($value ?? ''),
|
||||
original: @js($value ?? ''),
|
||||
cancel() { this.value = this.original; this.editing = false; },
|
||||
save() {
|
||||
this.saving = true;
|
||||
fetch(@js($url), {
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', 'X-CSRF-TOKEN': @js(csrf_token()), 'X-Requested-With': 'XMLHttpRequest' },
|
||||
body: JSON.stringify({ remark: this.value })
|
||||
}).then(r => { if (!r.ok) throw 0; return r.json(); })
|
||||
.then(d => { this.original = this.value; this.editing = false; window.showToast?.((d && d.message) || @js(__('Remark updated')), 'success'); })
|
||||
.catch(() => window.showToast?.(@js(__('Operation failed')), 'error'))
|
||||
.finally(() => this.saving = false);
|
||||
}
|
||||
}">
|
||||
<template x-if="!editing">
|
||||
<button type="button" @click="editing = true" class="group/rm flex items-start gap-1.5 text-left w-full">
|
||||
<span class="text-sm font-bold whitespace-pre-wrap break-words line-clamp-2"
|
||||
:class="value ? 'text-slate-600 dark:text-slate-300' : 'text-slate-300 dark:text-slate-600'"
|
||||
x-text="value || @js(__('Add Remark'))"></span>
|
||||
<svg class="w-3.5 h-3.5 shrink-0 mt-0.5 text-slate-300 dark:text-slate-600 opacity-0 group-hover/rm:opacity-100 transition-opacity"
|
||||
fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931z" />
|
||||
</svg>
|
||||
</button>
|
||||
</template>
|
||||
<template x-if="editing">
|
||||
<div class="space-y-2">
|
||||
<textarea x-model="value" rows="2" maxlength="1000"
|
||||
placeholder="{{ __('Enter remark (optional)') }}"
|
||||
class="luxury-input w-full text-xs py-2 px-3 resize-none"></textarea>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<button type="button" @click="save()" :disabled="saving"
|
||||
class="px-3 py-1.5 rounded-lg bg-cyan-500 hover:bg-cyan-600 text-white font-black text-[10px] uppercase tracking-widest disabled:opacity-60">{{ __('Save') }}</button>
|
||||
<button type="button" @click="cancel()" :disabled="saving"
|
||||
class="px-3 py-1.5 rounded-lg bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-300 font-black text-[10px] uppercase tracking-widest disabled:opacity-60">{{ __('Cancel') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
Loading…
Reference in New Issue
Block a user