[STYLE] 銷售中心 UI 優化與出貨紀錄邏輯校正

1. 優化「出貨紀錄」介面,重新排列欄位優先級並移除冗餘的機台流水號。
2. 統一出貨紀錄中的商品與貨道樣式,與取貨碼模組視覺語言同步。
3. 修正出貨紀錄搜尋邏輯,支援商品名稱與貨道編號模糊搜尋。
4. 修正「訂單詳情」側滑面板中的金額顯示(修正 price/subtotal 映射)。
5. 補強訂單詳情的出貨狀態 (dispense_status) 標籤顯示邏輯。
6. 將出貨紀錄中的「數量」表頭修正為「金額」,確保與 MQTT 協議回傳資料語意一致。
7. 更新多語系檔,新增搜尋欄位 placeholder 與相關 UI 標籤翻譯。
8. 新增發票資料表 machine_time 欄位遷移檔,以完整記錄機台開立時間。
This commit is contained in:
sky121113 2026-05-04 17:20:43 +08:00
parent e779880f9b
commit 023f639fb4
23 changed files with 2003 additions and 147 deletions

View File

@ -181,6 +181,7 @@ Mqtt3Client client = MqttClient.builder()
"flow_id": "T202604140001", "flow_id": "T202604140001",
"invoice_no": "AB12345678", "invoice_no": "AB12345678",
"invoice_date": "2026-04-22", "invoice_date": "2026-04-22",
"machine_time": "2026-04-22 14:30:15",
"amount": 25.0, "amount": 25.0,
"random_no": "1234", "random_no": "1234",
"love_code": "" "love_code": ""
@ -234,6 +235,7 @@ Mqtt3Client client = MqttClient.builder()
"invoice": { "invoice": {
"invoice_no": "AB12345678", "invoice_no": "AB12345678",
"invoice_date": "2025-08-08", "invoice_date": "2025-08-08",
"machine_time": "2025-08-08 10:01:30",
"amount": 100, "amount": 100,
"random_number": "1234", "random_number": "1234",
"love_code": "", "love_code": "",

View File

@ -126,7 +126,17 @@ class ListenMqttQueue extends Command
'payload' => $payload 'payload' => $payload
]); ]);
$action = $payload['action'] ?? 'create'; $rawAction = $payload['action'] ?? 'create';
$action = strtolower(trim($rawAction));
// 超級偵錯:檢查 action 字串的每一個位元組
$hex = bin2hex($rawAction);
Log::debug("MQTT Action Debug", [
'raw' => $rawAction,
'hex' => $hex,
'processed' => $action,
'match_finalize' => ($action === 'finalize' ? 'YES' : 'NO')
]);
switch ($action) { switch ($action) {
case 'invoice': case 'invoice':

View File

@ -4,28 +4,152 @@ namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use App\Models\Transaction\Order;
use App\Models\Transaction\Invoice;
use App\Models\Transaction\DispenseRecord;
use App\Models\Transaction\PaymentType;
use App\Models\Transaction\OrderItem;
use App\Models\Transaction\PickupCode; use App\Models\Transaction\PickupCode;
use App\Models\Transaction\PassCode; use App\Models\Transaction\PassCode;
use App\Models\Machine\Machine; use App\Models\Machine\Machine;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use App\Models\System\SystemOperationLog; use App\Models\System\SystemOperationLog;
class SalesController extends Controller class SalesController extends Controller
{ {
// 銷售&金流紀錄 // 銷售中心 (銷售&金流紀錄)
public function index() public function index(Request $request)
{ {
return view('admin.placeholder', [ $tab = $request->input('tab', 'orders');
$isAjax = $request->ajax();
// 取得篩選參數
$search = $request->input('search');
$machineId = $request->input('machine_id');
$paymentType = $request->input('payment_type');
$status = $request->input('status');
$startDate = $request->input('start_date');
$endDate = $request->input('end_date');
$data = [
'title' => '銷售&金流紀錄', 'title' => '銷售&金流紀錄',
'description' => '銷售交易與金流明細查詢', 'description' => '銷售交易與金流明細查詢',
'features' => [ 'tab' => $tab,
'銷售記錄查詢', 'filters' => [
'金流對帳', 'search' => $search,
'發票管理', 'machine_id' => $machineId,
'退款處理', 'payment_type' => $paymentType,
] 'status' => $status,
'start_date' => $startDate,
'end_date' => $endDate,
],
'machines' => Machine::select('id', 'name', 'serial_no')->get(),
'paymentTypes' => [
1 => '信用卡',
2 => '電子票證',
3 => '掃碼支付',
4 => '紙鈔機',
9 => '零錢',
30 => 'LINE Pay',
31 => '街口支付',
32 => '悠遊付',
33 => 'Pi 拍錢包',
34 => '全盈+PAY',
60 => '點數/優惠券',
],
];
// 1. 建立基本查詢 (套用共用過濾器:機台、日期)
$ordersQuery = Order::with(['machine:id,name,serial_no', 'invoice:id,order_id,invoice_no', 'items']);
$invoicesQuery = Invoice::with(['machine:id,name,serial_no', 'order:id,order_no,flow_id,payment_type']);
$dispenseQuery = DispenseRecord::with(['order:id,order_no,flow_id', 'machine:id,name,serial_no', 'product:id,name']);
// 共用過濾器:日期
if ($startDate && $endDate) {
$start = Carbon::parse($startDate);
$end = Carbon::parse($endDate)->endOfMinute();
$ordersQuery->whereBetween('created_at', [$start, $end]);
$invoicesQuery->whereBetween('invoice_date', [$start, $end]);
$dispenseQuery->whereBetween('machine_time', [$start, $end]);
}
// 共用過濾器:機台
if ($machineId) {
$ordersQuery->where('machine_id', $machineId);
$invoicesQuery->where('machine_id', $machineId);
$dispenseQuery->where('machine_id', $machineId);
}
// 2. 應用獨立過濾器:搜尋 (僅對當前 Tab 應用)
if ($search) {
if ($tab === 'orders') {
$ordersQuery->where(function($q) use ($search) {
$q->where('order_no', 'like', "%{$search}%")
->orWhere('flow_id', 'like', "%{$search}%")
->orWhere('invoice_info', 'like', "%{$search}%")
->orWhere('member_barcode', 'like', "%{$search}%");
});
} elseif ($tab === 'invoices') {
$invoicesQuery->where(function($q) use ($search) {
$q->where('invoice_no', 'like', "%{$search}%")
->orWhere('flow_id', 'like', "%{$search}%");
});
} elseif ($tab === 'dispense') {
$dispenseQuery->where(function($q) use ($search) {
$q->where('slot_no', 'like', "%{$search}%")
->orWhereHas('product', function($pq) use ($search) {
$pq->where('name', 'like', "%{$search}%");
})
->orWhereHas('order', function($oq) use ($search) {
$oq->where('order_no', 'like', "%{$search}%");
});
});
}
}
// 訂單專用過濾器
if ($tab === 'orders') {
if ($paymentType) $ordersQuery->where('payment_type', $paymentType);
if ($status) $ordersQuery->where('status', $status);
}
// 3. 執行分頁 (使用獨立的 pageName)
$perPage = $request->input('per_page', 10);
$data['orders'] = $ordersQuery->latest()->paginate($perPage, ['*'], 'orders_page')->withQueryString();
$data['invoices'] = $invoicesQuery->latest()->paginate($perPage, ['*'], 'invoices_page')->withQueryString();
$data['dispenseLogs'] = $dispenseQuery->latest()->paginate($perPage, ['*'], 'dispense_page')->withQueryString();
if ($isAjax) {
return response()->json([
'success' => true,
'tab' => $tab,
'html' => view('admin.sales.partials.tab-' . $tab, $data)->render()
]);
}
return view('admin.sales.index', $data);
}
/**
* 取得單筆交易詳情 (用於 Slide-over)
*/
public function show(Order $order)
{
$order->load(['machine', 'invoice', 'items', 'dispenseRecords.product']);
return response()->json([
'success' => true,
'html' => view('admin.sales.partials.order-detail-panel', [
'order' => $order,
'paymentTypes' => [
1 => '信用卡', 2 => '電子票證', 3 => '掃碼支付', 4 => '紙鈔機', 9 => '零錢',
30 => 'LINE Pay', 31 => '街口支付', 32 => '悠遊付', 33 => 'Pi 拍錢包', 34 => '全盈+PAY',
60 => '點數/優惠券',
]
])->render()
]); ]);
} }
@ -59,7 +183,7 @@ class SalesController extends Controller
$query->where('status', trim($request->status)); $query->where('status', trim($request->status));
} }
$per_page = $request->input('per_page', 15); $per_page = $request->input('per_page', 10);
$data['pickupCodes'] = $query->paginate($per_page, ['*'], 'list_page')->withQueryString(); $data['pickupCodes'] = $query->paginate($per_page, ['*'], 'list_page')->withQueryString();
// 供新增彈窗使用的機台清單 // 供新增彈窗使用的機台清單
@ -95,7 +219,7 @@ class SalesController extends Controller
} }
$data['logs'] = $logQuery->latest() $data['logs'] = $logQuery->latest()
->paginate($request->input('per_page', 15), ['*'], 'log_page') ->paginate($request->input('per_page', 10), ['*'], 'log_page')
->withQueryString(); ->withQueryString();
// 定義可用動作 // 定義可用動作
@ -272,7 +396,7 @@ class SalesController extends Controller
} }
} }
$data['passCodes'] = $query->paginate($request->input('per_page', 15), ['*'], 'list_page')->withQueryString(); $data['passCodes'] = $query->paginate($request->input('per_page', 10), ['*'], 'list_page')->withQueryString();
$data['machines'] = Machine::all(); $data['machines'] = Machine::all();
} }
@ -305,7 +429,7 @@ class SalesController extends Controller
} }
$data['logs'] = $logQuery->latest() $data['logs'] = $logQuery->latest()
->paginate($request->input('per_page', 15), ['*'], 'log_page') ->paginate($request->input('per_page', 10), ['*'], 'log_page')
->withQueryString(); ->withQueryString();
// 定義可用動作 // 定義可用動作

View File

@ -29,7 +29,7 @@ class ProcessTransaction implements ShouldQueue
/** /**
* Execute the job. * Execute the job.
*/ */
public function handle(\App\Services\Transaction\TransactionService $transactionService): void public function handle(\App\Services\Transaction\TransactionService $transactionService, \App\Services\Machine\MqttService $mqttService): void
{ {
$machine = Machine::withoutGlobalScopes()->where('serial_no', $this->serialNo)->first(); $machine = Machine::withoutGlobalScopes()->where('serial_no', $this->serialNo)->first();
@ -38,6 +38,8 @@ class ProcessTransaction implements ShouldQueue
return; return;
} }
$flowId = $this->payload['flow_id'] ?? 'N/A';
try { try {
// 將 serial_no 放入 payload 供 Service 使用 // 將 serial_no 放入 payload 供 Service 使用
$data = $this->payload; $data = $this->payload;
@ -50,11 +52,30 @@ class ProcessTransaction implements ShouldQueue
$machine->company_id, $machine->company_id,
"Transaction processed: :id", "Transaction processed: :id",
'info', 'info',
array_merge($this->payload, ['id' => ($this->payload['flow_id'] ?? 'N/A')]), array_merge($this->payload, ['id' => $flowId]),
'transaction' 'transaction'
); );
// 發送成功回饋 (ACK)
$mqttService->pushCommand($this->serialNo, 'transaction_ack', [
'flow_id' => $flowId,
'status' => 'success',
'message' => 'Processed successfully'
], (string) $flowId);
} catch (\Exception $e) { } catch (\Exception $e) {
Log::error("Failed to process MQTT transaction for machine {$this->serialNo}: " . $e->getMessage()); Log::error("Failed to process MQTT transaction for machine {$this->serialNo}: " . $e->getMessage(), [
'payload' => $this->payload,
'exception' => $e
]);
// 發送失敗回饋 (ACK)
$mqttService->pushCommand($this->serialNo, 'transaction_ack', [
'flow_id' => $flowId,
'status' => 'error',
'message' => $e->getMessage()
], (string) $flowId);
throw $e; throw $e;
} }
} }

View File

@ -27,12 +27,34 @@ class ProcessDispenseRecord implements ShouldQueue
/** /**
* Execute the job. * Execute the job.
*/ */
public function handle(TransactionService $transactionService): void public function handle(\App\Services\Transaction\TransactionService $transactionService, \App\Services\Machine\MqttService $mqttService): void
{ {
$serialNo = $this->data['serial_no'] ?? 'unknown';
$orderNo = $this->data['order_no'] ?? 'N/A';
try { try {
$transactionService->recordDispense($this->data); $transactionService->recordDispense($this->data);
// 發送成功回饋 (ACK)
$mqttService->pushCommand($serialNo, 'dispense_ack', [
'order_no' => $orderNo,
'status' => 'success',
'message' => 'Processed successfully'
], $orderNo);
} catch (\Exception $e) { } catch (\Exception $e) {
Log::error("Failed to record dispense for machine {$this->data['serial_no']}: " . $e->getMessage()); Log::error("Failed to record dispense for machine {$serialNo}: " . $e->getMessage(), [
'data' => $this->data,
'exception' => $e
]);
// 發送失敗回饋 (ACK)
$mqttService->pushCommand($serialNo, 'dispense_ack', [
'order_no' => $orderNo,
'status' => 'error',
'message' => $e->getMessage()
], $orderNo);
throw $e; throw $e;
} }
} }

View File

@ -27,15 +27,34 @@ class ProcessInvoice implements ShouldQueue
/** /**
* Execute the job. * Execute the job.
*/ */
public function handle(TransactionService $transactionService): void public function handle(\App\Services\Transaction\TransactionService $transactionService, \App\Services\Machine\MqttService $mqttService): void
{ {
$serialNo = $this->data['serial_no'] ?? 'unknown';
$invoiceNo = $this->data['invoice_no'] ?? 'N/A';
try { try {
$transactionService->recordInvoice($this->data); $transactionService->recordInvoice($this->data);
// 發送成功回饋 (ACK)
$mqttService->pushCommand($serialNo, 'invoice_ack', [
'invoice_no' => $invoiceNo,
'status' => 'success',
'message' => 'Processed successfully'
], $invoiceNo);
} catch (\Exception $e) { } catch (\Exception $e) {
Log::error('Failed to process invoice: ' . $e->getMessage(), [ Log::error('Failed to process invoice: ' . $e->getMessage(), [
'data' => $this->data, 'data' => $this->data,
'exception' => $e 'exception' => $e
]); ]);
// 發送失敗回饋 (ACK)
$mqttService->pushCommand($serialNo, 'invoice_ack', [
'invoice_no' => $invoiceNo,
'status' => 'error',
'message' => $e->getMessage()
], $invoiceNo);
throw $e; throw $e;
} }
} }

View File

@ -31,7 +31,7 @@ class ProcessTransactionFinalized implements ShouldQueue
/** /**
* Execute the job. * Execute the job.
*/ */
public function handle(TransactionService $transactionService): void public function handle(\App\Services\Transaction\TransactionService $transactionService, \App\Services\Machine\MqttService $mqttService): void
{ {
$machine = Machine::withoutGlobalScopes()->where('serial_no', $this->serialNo)->first(); $machine = Machine::withoutGlobalScopes()->where('serial_no', $this->serialNo)->first();
@ -40,6 +40,8 @@ class ProcessTransactionFinalized implements ShouldQueue
return; return;
} }
$flowId = $this->payload['order']['flow_id'] ?? ($this->payload['flow_id'] ?? 'N/A');
try { try {
$data = $this->payload; $data = $this->payload;
$data['serial_no'] = $this->serialNo; $data['serial_no'] = $this->serialNo;
@ -63,11 +65,27 @@ class ProcessTransactionFinalized implements ShouldQueue
'order_no' => $order->order_no 'order_no' => $order->order_no
]); ]);
// 發送成功回饋 (ACK)
$mqttService->pushCommand($this->serialNo, 'transaction_ack', [
'flow_id' => $flowId,
'order_no' => $order->order_no,
'status' => 'success',
'message' => 'Processed successfully'
], (string) $flowId);
} catch (\Exception $e) { } catch (\Exception $e) {
Log::error("Failed to process MQTT transaction finalized for machine {$this->serialNo}: " . $e->getMessage(), [ Log::error("Failed to process MQTT transaction finalized for machine {$this->serialNo}: " . $e->getMessage(), [
'payload' => $this->payload, 'payload' => $this->payload,
'exception' => $e 'exception' => $e
]); ]);
// 發送失敗回饋 (ACK)
$mqttService->pushCommand($this->serialNo, 'transaction_ack', [
'flow_id' => $flowId,
'status' => 'error',
'message' => $e->getMessage()
], (string) $flowId);
throw $e; throw $e;
} }
} }

View File

@ -19,6 +19,7 @@ class Invoice extends Model
'amount', 'amount',
'carrier_id', 'carrier_id',
'invoice_date', 'invoice_date',
'machine_time',
'random_number', 'random_number',
'love_code', 'love_code',
'rtn_code', 'rtn_code',
@ -29,6 +30,7 @@ class Invoice extends Model
protected $casts = [ protected $casts = [
'total_amount' => 'decimal:2', 'total_amount' => 'decimal:2',
'tax_amount' => 'decimal:2', 'tax_amount' => 'decimal:2',
'machine_time' => 'datetime',
'metadata' => 'array', 'metadata' => 'array',
]; ];
@ -36,4 +38,9 @@ class Invoice extends Model
{ {
return $this->belongsTo(Order::class); return $this->belongsTo(Order::class);
} }
public function machine()
{
return $this->belongsTo(\App\Models\Machine\Machine::class);
}
} }

View File

@ -8,6 +8,7 @@ use App\Models\Transaction\Invoice;
use App\Models\Transaction\DispenseRecord; use App\Models\Transaction\DispenseRecord;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use App\Models\Machine\Machine; use App\Models\Machine\Machine;
use Illuminate\Support\Facades\Log;
class TransactionService class TransactionService
{ {
@ -16,6 +17,17 @@ class TransactionService
*/ */
public function processTransaction(array $data): Order public function processTransaction(array $data): Order
{ {
$flowId = $data['flow_id'] ?? null;
if ($flowId) {
$existingOrder = Order::withoutGlobalScopes()
->where('flow_id', $flowId)
->first();
if ($existingOrder) {
return $existingOrder;
}
}
return DB::transaction(function () use ($data) { return DB::transaction(function () use ($data) {
$machine = Machine::where('serial_no', $data['serial_no'])->firstOrFail(); $machine = Machine::where('serial_no', $data['serial_no'])->firstOrFail();
@ -105,6 +117,7 @@ class TransactionService
'amount' => $data['amount'] ?? 0, 'amount' => $data['amount'] ?? 0,
'carrier_id' => $data['carrier_id'] ?? null, 'carrier_id' => $data['carrier_id'] ?? null,
'invoice_date' => $data['invoice_date'] ?? null, 'invoice_date' => $data['invoice_date'] ?? null,
'machine_time' => $data['machine_time'] ?? null,
'random_number' => $data['random_number'] ?? ($data['random_no'] ?? null), 'random_number' => $data['random_number'] ?? ($data['random_no'] ?? null),
'love_code' => $data['love_code'] ?? null, 'love_code' => $data['love_code'] ?? null,
'rtn_code' => $data['rtn_code'] ?? null, 'rtn_code' => $data['rtn_code'] ?? null,
@ -137,7 +150,7 @@ class TransactionService
'amount' => $data['amount'] ?? 0, 'amount' => $data['amount'] ?? 0,
'remaining_stock' => $data['remaining_stock'] ?? null, 'remaining_stock' => $data['remaining_stock'] ?? null,
'dispense_status' => $data['dispense_status'] ?? 0, 'dispense_status' => $data['dispense_status'] ?? 0,
'member_barcode' => $data['member_barcode'] ?? null, 'member_barcode' => $data['member_barcode'] ?? ($order?->member_barcode ?? null),
'machine_time' => $data['machine_time'] ?? now(), 'machine_time' => $data['machine_time'] ?? now(),
'points_used' => $data['points_used'] ?? 0, 'points_used' => $data['points_used'] ?? 0,
]); ]);
@ -149,6 +162,19 @@ class TransactionService
*/ */
public function finalizeTransaction(array $data): Order public function finalizeTransaction(array $data): Order
{ {
$flowId = $data['order']['flow_id'] ?? null;
// 冪等性檢查:如果 flow_id 已經存在,直接回傳既有訂單
if ($flowId) {
$existingOrder = Order::withoutGlobalScopes()
->where('flow_id', $flowId)
->first();
if ($existingOrder) {
Log::info("Transaction already finalized, returning existing order", ['flow_id' => $flowId]);
return $existingOrder;
}
}
return DB::transaction(function () use ($data) { return DB::transaction(function () use ($data) {
$serialNo = $data['serial_no']; $serialNo = $data['serial_no'];
@ -173,6 +199,12 @@ class TransactionService
$dispenseItem['serial_no'] = $serialNo; $dispenseItem['serial_no'] = $serialNo;
$dispenseItem['flow_id'] = $order->flow_id; $dispenseItem['flow_id'] = $order->flow_id;
$dispenseItem['order_id'] = $order->id; $dispenseItem['order_id'] = $order->id;
// 自動繼承:如果出貨紀錄沒帶 Barcode就用訂單的
if (empty($dispenseItem['member_barcode']) && !empty($order->member_barcode)) {
$dispenseItem['member_barcode'] = $order->member_barcode;
}
$this->recordDispense($dispenseItem); $this->recordDispense($dispenseItem);
} }
} }

View File

@ -525,6 +525,7 @@ return [
'invoice' => ['type' => 'object', 'description' => '(選填) 發票開立資訊 (若無發票可省略)', 'required' => false], 'invoice' => ['type' => 'object', 'description' => '(選填) 發票開立資訊 (若無發票可省略)', 'required' => false],
'invoice.invoice_no' => ['type' => 'string', 'description' => '(必填若有invoice) 發票號碼', 'required' => false], 'invoice.invoice_no' => ['type' => 'string', 'description' => '(必填若有invoice) 發票號碼', 'required' => false],
'invoice.invoice_date' => ['type' => 'string', 'description' => '(必填若有invoice) 發票日期 (Y-m-d)', 'required' => false], 'invoice.invoice_date' => ['type' => 'string', 'description' => '(必填若有invoice) 發票日期 (Y-m-d)', 'required' => false],
'invoice.machine_time' => ['type' => 'datetime', 'description' => '(必填若有invoice) 機台開立發票時間 (Y-m-d H:i:s)', 'required' => false],
'invoice.amount' => ['type' => 'numeric', 'description' => '(必填若有invoice) 發票金額', 'required' => false], 'invoice.amount' => ['type' => 'numeric', 'description' => '(必填若有invoice) 發票金額', 'required' => false],
'invoice.random_number' => ['type' => 'string', 'description' => '(必填若有invoice) 發票隨機碼 (4位)', 'required' => false], 'invoice.random_number' => ['type' => 'string', 'description' => '(必填若有invoice) 發票隨機碼 (4位)', 'required' => false],
'invoice.love_code' => ['type' => 'string', 'description' => '(選填) 捐贈碼', 'required' => false], 'invoice.love_code' => ['type' => 'string', 'description' => '(選填) 捐贈碼', 'required' => false],

View File

@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('invoices', function (Blueprint $table) {
$table->datetime('machine_time')->nullable()->after('invoice_date')->comment('機台開立發票時間');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('invoices', function (Blueprint $table) {
$table->dropColumn('machine_time');
});
}
};

View File

@ -74,6 +74,7 @@
"Affiliated Company": "Affiliated Company", "Affiliated Company": "Affiliated Company",
"Affiliated Unit": "Company Name", "Affiliated Unit": "Company Name",
"Affiliation": "Company Name", "Affiliation": "Company Name",
"After Qty": "After Qty",
"Alert Summary": "Alert Summary", "Alert Summary": "Alert Summary",
"Alerts": "Alerts", "Alerts": "Alerts",
"Alerts Pending": "Alerts Pending", "Alerts Pending": "Alerts Pending",
@ -94,6 +95,7 @@
"All Warehouses": "All Warehouses", "All Warehouses": "All Warehouses",
"All slots are fully stocked": "All slots are fully stocked", "All slots are fully stocked": "All slots are fully stocked",
"Amount": "Amount", "Amount": "Amount",
"Amount / Payment": "Amount / Payment",
"An error occurred while saving.": "An error occurred while saving.", "An error occurred while saving.": "An error occurred while saving.",
"Analysis Management": "Analysis Management", "Analysis Management": "Analysis Management",
"Analysis Permissions": "Analysis Permissions", "Analysis Permissions": "Analysis Permissions",
@ -146,6 +148,7 @@
"Assigned Machines": "Assigned Machines", "Assigned Machines": "Assigned Machines",
"Assigned To": "Assigned To", "Assigned To": "Assigned To",
"Assignment removed successfully.": "Assignment removed successfully.", "Assignment removed successfully.": "Assignment removed successfully.",
"Associated Order": "Associated Order",
"Audit Management": "Audit Management", "Audit Management": "Audit Management",
"Audit Permissions": "Audit Permissions", "Audit Permissions": "Audit Permissions",
"Authorization updated successfully": "Authorization updated successfully", "Authorization updated successfully": "Authorization updated successfully",
@ -173,6 +176,7 @@
"Batch": "Batch", "Batch": "Batch",
"Batch No": "Batch No", "Batch No": "Batch No",
"Batch Number": "Batch Number", "Batch Number": "Batch Number",
"Before Qty": "Before Qty",
"Belongs To": "Company Name", "Belongs To": "Company Name",
"Belongs To Company": "Company Name", "Belongs To Company": "Company Name",
"Branch": "Branch", "Branch": "Branch",
@ -372,6 +376,7 @@
"Delivery door closed": "Delivery door closed", "Delivery door closed": "Delivery door closed",
"Delivery door open error": "Delivery door open error", "Delivery door open error": "Delivery door open error",
"Delivery door opened": "Delivery door opened", "Delivery door opened": "Delivery door opened",
"Delta": "Delta",
"Deposit Bonus": "Deposit Bonus", "Deposit Bonus": "Deposit Bonus",
"Describe the repair or maintenance status...": "Describe the repair or maintenance status...", "Describe the repair or maintenance status...": "Describe the repair or maintenance status...",
"Description / Name": "Description / Name", "Description / Name": "Description / Name",
@ -390,8 +395,14 @@
"Disabled": "Disabled", "Disabled": "Disabled",
"Disabling this customer will also disable all accounts under this customer. Are you sure you want to continue?": "Disabling this customer will also disable all accounts under this customer. Are you sure you want to continue?", "Disabling this customer will also disable all accounts under this customer. Are you sure you want to continue?": "Disabling this customer will also disable all accounts under this customer. Are you sure you want to continue?",
"Discord Notifications": "Discord Notifications", "Discord Notifications": "Discord Notifications",
"Discount": "Discount",
"Dispense Failed": "Dispense Failed", "Dispense Failed": "Dispense Failed",
"Dispense Pending": "Dispense Pending",
"Dispense Product": "Dispense Product",
"Dispense Quantity": "Dispense Quantity",
"Dispense Status": "Dispense Status",
"Dispense Success": "Dispense Success", "Dispense Success": "Dispense Success",
"Dispense Time": "Dispense Time",
"Dispense error (0407)": "Dispense error (0407)", "Dispense error (0407)": "Dispense error (0407)",
"Dispense error (0408)": "Dispense error (0408)", "Dispense error (0408)": "Dispense error (0408)",
"Dispense error (0409)": "Dispense error (0409)", "Dispense error (0409)": "Dispense error (0409)",
@ -429,6 +440,7 @@
"Edit Machine Name": "Edit Machine Name", "Edit Machine Name": "Edit Machine Name",
"Edit Machine Settings": "Edit Machine Settings", "Edit Machine Settings": "Edit Machine Settings",
"Edit Name": "Edit Name", "Edit Name": "Edit Name",
"Edit Pass Code": "Edit Pass Code",
"Edit Payment Config": "Edit Payment Config", "Edit Payment Config": "Edit Payment Config",
"Edit Product": "Edit Product", "Edit Product": "Edit Product",
"Edit Role": "Edit Role", "Edit Role": "Edit Role",
@ -517,6 +529,8 @@
"Firmware updated to :version": "Firmware updated to :version", "Firmware updated to :version": "Firmware updated to :version",
"Fleet Avg OEE": "Fleet Avg OEE", "Fleet Avg OEE": "Fleet Avg OEE",
"Fleet Performance": "Fleet Performance", "Fleet Performance": "Fleet Performance",
"Flow ID": "Flow ID",
"Flow ID / Time": "Flow ID / Time",
"Force End Session": "Force End Session", "Force End Session": "Force End Session",
"Force end current session": "Force end current session", "Force end current session": "Force end current session",
"From": "From", "From": "From",
@ -536,6 +550,7 @@
"Gift Definitions": "Gift Definitions", "Gift Definitions": "Gift Definitions",
"Global roles accessible by all administrators.": "Global roles accessible by all administrators.", "Global roles accessible by all administrators.": "Global roles accessible by all administrators.",
"Go Back": "Go Back", "Go Back": "Go Back",
"Go to E-Invoice": "Go to E-Invoice",
"Goods & System Settings": "Goods & System Settings", "Goods & System Settings": "Goods & System Settings",
"Got it": "Got it", "Got it": "Got it",
"Grant UI Access": "Grant UI Access", "Grant UI Access": "Grant UI Access",
@ -580,7 +595,12 @@
"Inventory Overview": "Inventory Overview", "Inventory Overview": "Inventory Overview",
"Inventory Stable": "Inventory Stable", "Inventory Stable": "Inventory Stable",
"Inventory synced with machine": "Inventory synced with machine", "Inventory synced with machine": "Inventory synced with machine",
"Invoice Date": "Invoice Date",
"Invoice Information": "Invoice Information",
"Invoice Number": "Invoice Number",
"Invoice Number / Flow ID": "Invoice Number / Flow ID",
"Invoice Status": "Invoice Status", "Invoice Status": "Invoice Status",
"Issued At": "Issued At",
"Item List": "Item List", "Item List": "Item List",
"Items": "Items", "Items": "Items",
"JKO_MERCHANT_ID": "JKO_MERCHANT_ID", "JKO_MERCHANT_ID": "JKO_MERCHANT_ID",
@ -621,8 +641,8 @@
"Live Fleet Updates": "Live Fleet Updates", "Live Fleet Updates": "Live Fleet Updates",
"Loading Cabinet...": "Loading Cabinet...", "Loading Cabinet...": "Loading Cabinet...",
"Loading Data": "Loading Data", "Loading Data": "Loading Data",
"Loading machines...": "Loading machines...",
"Loading failed": "Loading failed", "Loading failed": "Loading failed",
"Loading machines...": "Loading machines...",
"Loading...": "Loading...", "Loading...": "Loading...",
"Location": "Location", "Location": "Location",
"Location found!": "Location found!", "Location found!": "Location found!",
@ -645,6 +665,7 @@
"Low stock and out-of-stock alerts": "Low stock and out-of-stock alerts", "Low stock and out-of-stock alerts": "Low stock and out-of-stock alerts",
"Loyalty & Features": "Loyalty & Features", "Loyalty & Features": "Loyalty & Features",
"Machine": "Machine", "Machine": "Machine",
"Machine / Date": "Machine / Date",
"Machine / Slot": "Machine / Slot", "Machine / Slot": "Machine / Slot",
"Machine Advertisement Settings": "Machine Advertisement Settings", "Machine Advertisement Settings": "Machine Advertisement Settings",
"Machine Count": "Machine Count", "Machine Count": "Machine Count",
@ -671,11 +692,13 @@
"Machine Reports": "Machine Reports", "Machine Reports": "Machine Reports",
"Machine Restart": "Machine Restart", "Machine Restart": "Machine Restart",
"Machine Return": "Machine Return", "Machine Return": "Machine Return",
"Machine Serial": "Machine Serial",
"Machine Serial No": "Machine Serial No", "Machine Serial No": "Machine Serial No",
"Machine Settings": "Machine Settings", "Machine Settings": "Machine Settings",
"Machine Status": "Machine Status", "Machine Status": "Machine Status",
"Machine Status List": "Machine Status List", "Machine Status List": "Machine Status List",
"Machine Stock": "Machine Stock", "Machine Stock": "Machine Stock",
"Machine Stock Movements": "Machine Stock Movements",
"Machine System Settings": "Machine System Settings", "Machine System Settings": "Machine System Settings",
"Machine Utilization": "Machine Utilization", "Machine Utilization": "Machine Utilization",
"Machine created successfully.": "Machine created successfully.", "Machine created successfully.": "Machine created successfully.",
@ -771,17 +794,6 @@
"Motor not stopped": "Motor not stopped", "Motor not stopped": "Motor not stopped",
"Movement History": "Movement History", "Movement History": "Movement History",
"Movement Logs": "Movement Logs", "Movement Logs": "Movement Logs",
"Machine Stock Movements": "Machine Stock Movements",
"Stock Movement Log": "Stock Movement Log",
"movement.type.replenishment": "Replenishment",
"movement.type.pickup": "Pickup Code Consumed",
"movement.type.remote_dispense": "Remote Dispense",
"movement.type.adjustment": "Stock Adjustment",
"movement.type.rollback": "Dispense Rollback",
"Before Qty": "Before Qty",
"After Qty": "After Qty",
"Delta": "Delta",
"No movements found": "No movements found",
"Multilingual Names": "Multilingual Names", "Multilingual Names": "Multilingual Names",
"N/A": "N/A", "N/A": "N/A",
"Name": "Name", "Name": "Name",
@ -814,6 +826,7 @@
"No advertisements found.": "No advertisements found.", "No advertisements found.": "No advertisements found.",
"No alert summary": "No alert summary", "No alert summary": "No alert summary",
"No assignments": "No assignments", "No assignments": "No assignments",
"No associated order found": "No associated order found",
"No categories found.": "No categories found.", "No categories found.": "No categories found.",
"No command history": "No command history", "No command history": "No command history",
"No configurations found": "No configurations found", "No configurations found": "No configurations found",
@ -836,12 +849,15 @@
"No matching machines": "No matching machines", "No matching machines": "No matching machines",
"No materials available": "No materials available", "No materials available": "No materials available",
"No movement records found": "No movement records found", "No movement records found": "No movement records found",
"No movements found": "No movements found",
"No pass codes found": "No pass codes found", "No pass codes found": "No pass codes found",
"No permissions": "No permissions", "No permissions": "No permissions",
"No pickup codes found": "No pickup codes found", "No pickup codes found": "No pickup codes found",
"No product record found": "No product record found",
"No products found in this warehouse": "No products found in this warehouse", "No products found in this warehouse": "No products found in this warehouse",
"No products found matching your criteria.": "No products found matching your criteria.", "No products found matching your criteria.": "No products found matching your criteria.",
"No records found": "No records found", "No records found": "No records found",
"No related detail found": "No related detail found",
"No replenishment orders found": "No replenishment orders found", "No replenishment orders found": "No replenishment orders found",
"No results found": "No results found", "No results found": "No results found",
"No roles available": "No roles available", "No roles available": "No roles available",
@ -852,6 +868,7 @@
"No slots need replenishment": "No slots need replenishment", "No slots need replenishment": "No slots need replenishment",
"No stock data found": "No stock data found", "No stock data found": "No stock data found",
"No stock-in orders found": "No stock-in orders found", "No stock-in orders found": "No stock-in orders found",
"No transaction orders found": "No transaction orders found",
"No transfer orders found": "No transfer orders found", "No transfer orders found": "No transfer orders found",
"No users found": "No users found", "No users found": "No users found",
"No warehouses found": "No warehouses found", "No warehouses found": "No warehouses found",
@ -895,8 +912,12 @@
"Optional remarks...": "Optional remarks...", "Optional remarks...": "Optional remarks...",
"Order Details": "Order Details", "Order Details": "Order Details",
"Order Info": "Order Info", "Order Info": "Order Info",
"Order Items": "Order Items",
"Order Management": "Order Management", "Order Management": "Order Management",
"Order No.": "Order No.", "Order No.": "Order No.",
"Order Number / Time": "Order Number / Time",
"Order Status": "Order Status",
"Order Time": "Order Time",
"Order already completed": "Order already completed", "Order already completed": "Order already completed",
"Order already processed": "Order already processed", "Order already processed": "Order already processed",
"Order completed and stock updated": "Order completed and stock updated", "Order completed and stock updated": "Order completed and stock updated",
@ -958,6 +979,7 @@
"Password": "Password", "Password": "Password",
"Password updated successfully.": "密碼已成功變更。", "Password updated successfully.": "密碼已成功變更。",
"Payment & Invoice": "Payment & Invoice", "Payment & Invoice": "Payment & Invoice",
"Payment Amount": "Payment Amount",
"Payment Buffer Seconds": "Payment Buffer Seconds", "Payment Buffer Seconds": "Payment Buffer Seconds",
"Payment Config": "Payment Config", "Payment Config": "Payment Config",
"Payment Configuration": "Payment Configuration", "Payment Configuration": "Payment Configuration",
@ -965,11 +987,13 @@
"Payment Configuration deleted successfully.": "Payment Configuration deleted successfully.", "Payment Configuration deleted successfully.": "Payment Configuration deleted successfully.",
"Payment Configuration updated successfully.": "Payment Configuration updated successfully.", "Payment Configuration updated successfully.": "Payment Configuration updated successfully.",
"Payment Selection": "Payment Selection", "Payment Selection": "Payment Selection",
"Payment Type": "Payment Type",
"Pending": "Pending", "Pending": "Pending",
"Per Page": "Per Page", "Per Page": "Per Page",
"Performance": "Performance", "Performance": "Performance",
"Permanent": "Permanent", "Permanent": "Permanent",
"Permanent Code": "Permanent Code", "Permanent Code": "Permanent Code",
"Permanent if empty": "Permanent if empty",
"Permanently Delete Account": "Permanently Delete Account", "Permanently Delete Account": "Permanently Delete Account",
"Permission Settings": "Permission Settings", "Permission Settings": "Permission Settings",
"Permission Tags": "Permission Tags", "Permission Tags": "Permission Tags",
@ -1019,6 +1043,7 @@
"Previous": "Previous", "Previous": "Previous",
"Price / Member": "Price / Member", "Price / Member": "Price / Member",
"Pricing Information": "Pricing Information", "Pricing Information": "Pricing Information",
"Print Invoice": "Print Invoice",
"Product": "Product", "Product": "Product",
"Product / Slot": "Product / Slot", "Product / Slot": "Product / Slot",
"Product / Stock": "Product / Stock", "Product / Stock": "Product / Stock",
@ -1083,6 +1108,7 @@
"Recent Login": "Recent Login", "Recent Login": "Recent Login",
"Recently reported errors or warnings in logs": "Recently reported errors or warnings in logs", "Recently reported errors or warnings in logs": "Recently reported errors or warnings in logs",
"Records": "Records", "Records": "Records",
"Refunded": "Refunded",
"Regenerate": "Regenerate", "Regenerate": "Regenerate",
"Regenerating the token will disconnect the physical machine until it is updated. Continue?": "Regenerating the token will disconnect the physical machine until it is updated. Continue?", "Regenerating the token will disconnect the physical machine until it is updated. Continue?": "Regenerating the token will disconnect the physical machine until it is updated. Continue?",
"Remote Change": "Remote Change", "Remote Change": "Remote Change",
@ -1172,9 +1198,10 @@
"Scan to pick up your product": "Scan to pick up your product", "Scan to pick up your product": "Scan to pick up your product",
"Schedule": "Schedule", "Schedule": "Schedule",
"Search Company Title...": "Search Company Title...", "Search Company Title...": "Search Company Title...",
"Search Flow ID / Slot...": "Search Flow ID / Slot...",
"Search Invoice No / Flow ID...": "Search Invoice No / Flow ID...",
"Search Machine...": "Search Machine...", "Search Machine...": "Search Machine...",
"Search logs...": "Search logs...", "Search Order No / Flow ID / Invoice...": "Search Order No / Flow ID / Invoice...",
"Searchable Select": "Searchable Select",
"Search accounts...": "Search accounts...", "Search accounts...": "Search accounts...",
"Search by code, machine name or serial...": "Search by code, machine name or serial...", "Search by code, machine name or serial...": "Search by code, machine name or serial...",
"Search by code, name or machine...": "Search by code, name or machine...", "Search by code, name or machine...": "Search by code, name or machine...",
@ -1185,6 +1212,7 @@
"Search company...": "Search company...", "Search company...": "Search company...",
"Search configurations...": "Search configurations...", "Search configurations...": "Search configurations...",
"Search customers...": "Search customers...", "Search customers...": "Search customers...",
"Search logs...": "Search logs...",
"Search machines by name or serial...": "Search machines by name or serial...", "Search machines by name or serial...": "Search machines by name or serial...",
"Search machines...": "Search machines...", "Search machines...": "Search machines...",
"Search models...": "Search models...", "Search models...": "Search models...",
@ -1197,6 +1225,7 @@
"Search users...": "Search users...", "Search users...": "Search users...",
"Search warehouses...": "Search warehouses...", "Search warehouses...": "Search warehouses...",
"Search...": "Search...", "Search...": "Search...",
"Searchable Select": "Searchable Select",
"Searching...": "Searching...", "Searching...": "Searching...",
"Seconds": "Seconds", "Seconds": "Seconds",
"Security & State": "Security & State", "Security & State": "Security & State",
@ -1253,6 +1282,7 @@
"Sign in to your account": "Sign in to your account", "Sign in to your account": "Sign in to your account",
"Signed in as": "Signed in as", "Signed in as": "Signed in as",
"Slot": "Slot", "Slot": "Slot",
"Slot / Product": "Slot / Product",
"Slot Mechanism (default: Conveyor, check for Spring)": "Slot Mechanism (default: Conveyor, check for Spring)", "Slot Mechanism (default: Conveyor, check for Spring)": "Slot Mechanism (default: Conveyor, check for Spring)",
"Slot No": "Slot No", "Slot No": "Slot No",
"Slot Status": "Slot Status", "Slot Status": "Slot Status",
@ -1293,6 +1323,7 @@
"Start Time": "Start Time", "Start Time": "Start Time",
"Statistics": "Statistics", "Statistics": "Statistics",
"Status": "Status", "Status": "Status",
"Status / Invoice": "Status / Invoice",
"Status / Temp / Sub / Card / Scan": "Status / Temp / Sub / Card / Scan", "Status / Temp / Sub / Card / Scan": "Status / Temp / Sub / Card / Scan",
"Status Timeline": "Status Timeline", "Status Timeline": "Status Timeline",
"Status updated successfully": "Status updated successfully", "Status updated successfully": "Status updated successfully",
@ -1306,6 +1337,7 @@
"Stock Level > 50%": "Stock Level > 50%", "Stock Level > 50%": "Stock Level > 50%",
"Stock Levels": "Stock Levels", "Stock Levels": "Stock Levels",
"Stock Management": "Stock Management", "Stock Management": "Stock Management",
"Stock Movement Log": "Stock Movement Log",
"Stock Out": "Stock Out", "Stock Out": "Stock Out",
"Stock Quantity": "Stock Quantity", "Stock Quantity": "Stock Quantity",
"Stock Rate": "Stock Rate", "Stock Rate": "Stock Rate",
@ -1316,6 +1348,7 @@
"Stock returned to warehouse": "Stock returned to warehouse", "Stock returned to warehouse": "Stock returned to warehouse",
"Stock-In Management": "Stock-In Management", "Stock-In Management": "Stock-In Management",
"Stock-In Order": "Stock-In Order", "Stock-In Order": "Stock-In Order",
"Stock-In Order Details": "Stock-In Order Details",
"Stock-In Orders": "Stock-In Orders", "Stock-In Orders": "Stock-In Orders",
"Stock-In Orders Tab": "Stock-In Orders", "Stock-In Orders Tab": "Stock-In Orders",
"Stock-in order": "Stock-in order", "Stock-in order": "Stock-in order",
@ -1335,6 +1368,7 @@
"Sub-actions": "子項目", "Sub-actions": "子項目",
"Sub-machine Status Request": "Sub-machine Status", "Sub-machine Status Request": "Sub-machine Status",
"Submit Record": "Submit Record", "Submit Record": "Submit Record",
"Subtotal": "Subtotal",
"Success": "Success", "Success": "Success",
"Super Admin": "Super Admin", "Super Admin": "Super Admin",
"Super-admin role cannot be assigned to tenant accounts.": "Super-admin role cannot be assigned to tenant accounts.", "Super-admin role cannot be assigned to tenant accounts.": "Super-admin role cannot be assigned to tenant accounts.",
@ -1419,6 +1453,8 @@
"Track stock levels, stock-in orders, and movement history": "Track stock levels, stock-in orders, and movement history", "Track stock levels, stock-in orders, and movement history": "Track stock levels, stock-in orders, and movement history",
"Track stock-in orders and movement history": "Track stock-in orders and movement history", "Track stock-in orders and movement history": "Track stock-in orders and movement history",
"Traditional Chinese": "Traditional Chinese", "Traditional Chinese": "Traditional Chinese",
"Transaction Info": "Transaction Info",
"Transaction Time": "Transaction Time",
"Transaction processed: :id": "Transaction processed: :id", "Transaction processed: :id": "Transaction processed: :id",
"Transfer Audit": "Transfer Audit", "Transfer Audit": "Transfer Audit",
"Transfer Details": "Transfer Details", "Transfer Details": "Transfer Details",
@ -1460,15 +1496,10 @@
"Unlock Now": "Unlock Now", "Unlock Now": "Unlock Now",
"Unlock Page": "Unlock Page", "Unlock Page": "Unlock Page",
"Unpublish": "Unpublish", "Unpublish": "Unpublish",
"cancel": "Cancel",
"create": "Create",
"update": "Update",
"Update": "Update", "Update": "Update",
"Edit Pass Code": "Edit Pass Code",
"Permanent if empty": "Permanent if empty",
"Update Pass Code": "Update Pass Code",
"Update Authorization": "Update Authorization", "Update Authorization": "Update Authorization",
"Update Customer": "Update Customer", "Update Customer": "Update Customer",
"Update Pass Code": "Update Pass Code",
"Update Password": "Update Password", "Update Password": "Update Password",
"Update Product": "Update Product", "Update Product": "Update Product",
"Update Settings": "Update Settings", "Update Settings": "Update Settings",
@ -1505,12 +1536,14 @@
"View Inventory": "View Inventory", "View Inventory": "View Inventory",
"View Logs": "View Logs", "View Logs": "View Logs",
"View More": "View More", "View More": "View More",
"View Order": "View Order",
"View QR Code": "View QR Code", "View QR Code": "View QR Code",
"View Slots": "View Slots", "View Slots": "View Slots",
"View all warehouses": "View all warehouses", "View all warehouses": "View all warehouses",
"View slot-level inventory for each machine": "View slot-level inventory for each machine", "View slot-level inventory for each machine": "View slot-level inventory for each machine",
"Visit Gift": "Visit Gift", "Visit Gift": "Visit Gift",
"Visual overview of all machine locations": "Visual overview of all machine locations", "Visual overview of all machine locations": "Visual overview of all machine locations",
"Void Invoice": "Void Invoice",
"Waiting": "Waiting", "Waiting": "Waiting",
"Waiting for Payment": "Waiting for Payment", "Waiting for Payment": "Waiting for Payment",
"Warehouse": "Warehouse", "Warehouse": "Warehouse",
@ -1563,13 +1596,18 @@
"accounts": "Account Management", "accounts": "Account Management",
"admin": "管理員", "admin": "管理員",
"analysis": "Analysis Management", "analysis": "Analysis Management",
"and :count other items": "and :count other items",
"app": "APP Management", "app": "APP Management",
"audit": "Audit Management", "audit": "Audit Management",
"basic-settings": "Basic Settings", "basic-settings": "Basic Settings",
"basic.machines": "機台設定", "basic.machines": "機台設定",
"basic.payment-configs": "客戶金流設定", "basic.payment-configs": "客戶金流設定",
"by": "by", "by": "by",
"cancel": "Cancel",
"companies": "Customer Management", "companies": "Customer Management",
"consume": "Pickup Success",
"consume_failed": "Pickup Failed",
"create": "Create",
"data-config": "Data Configuration", "data-config": "Data Configuration",
"data-config.sub-account-roles": "子帳號角色", "data-config.sub-account-roles": "子帳號角色",
"data-config.sub-accounts": "子帳號管理", "data-config.sub-accounts": "子帳號管理",
@ -1645,6 +1683,11 @@
"menu.warehouses.transfers": "menu.warehouses.transfers", "menu.warehouses.transfers": "menu.warehouses.transfers",
"min": "min", "min": "min",
"mins ago": "mins ago", "mins ago": "mins ago",
"movement.type.adjustment": "Stock Adjustment",
"movement.type.pickup": "Pickup Code Consumed",
"movement.type.remote_dispense": "Remote Dispense",
"movement.type.replenishment": "Replenishment",
"movement.type.rollback": "Dispense Rollback",
"of": "of", "of": "of",
"of items": "of items", "of items": "of items",
"pending": "pending", "pending": "pending",
@ -1664,15 +1707,14 @@
"success": "success", "success": "success",
"super-admin": "super-admin", "super-admin": "super-admin",
"to": "to", "to": "to",
"update": "Update",
"used": "Used",
"user": "user", "user": "user",
"vending": "vending", "vending": "vending",
"verify_success": "Verification Success",
"video": "video", "video": "video",
"visit_gift": "visit_gift", "visit_gift": "visit_gift",
"vs Yesterday": "vs Yesterday", "vs Yesterday": "vs Yesterday",
"warehouses": "warehouses", "warehouses": "warehouses",
"used": "Used", "待填寫": "待填寫"
"待填寫": "待填寫", }
"verify_success": "Verification Success",
"consume": "Pickup Success",
"consume_failed": "Pickup Failed"
}

View File

@ -74,6 +74,7 @@
"Affiliated Company": "Affiliated Company", "Affiliated Company": "Affiliated Company",
"Affiliated Unit": "Affiliated Unit", "Affiliated Unit": "Affiliated Unit",
"Affiliation": "Affiliation", "Affiliation": "Affiliation",
"After Qty": "変動後数量",
"Alert Summary": "Alert Summary", "Alert Summary": "Alert Summary",
"Alerts": "Alerts", "Alerts": "Alerts",
"Alerts Pending": "Alerts Pending", "Alerts Pending": "Alerts Pending",
@ -94,6 +95,7 @@
"All Warehouses": "すべての倉庫", "All Warehouses": "すべての倉庫",
"All slots are fully stocked": "全スロットが満在庫です", "All slots are fully stocked": "全スロットが満在庫です",
"Amount": "Amount", "Amount": "Amount",
"Amount / Payment": "金額 / 支払い",
"An error occurred while saving.": "An error occurred while saving.", "An error occurred while saving.": "An error occurred while saving.",
"Analysis Management": "Analysis Management", "Analysis Management": "Analysis Management",
"Analysis Permissions": "Analysis Permissions", "Analysis Permissions": "Analysis Permissions",
@ -146,6 +148,7 @@
"Assigned Machines": "Assigned Machines", "Assigned Machines": "Assigned Machines",
"Assigned To": "担当者", "Assigned To": "担当者",
"Assignment removed successfully.": "Assignment removed successfully.", "Assignment removed successfully.": "Assignment removed successfully.",
"Associated Order": "関連注文",
"Audit Management": "Audit Management", "Audit Management": "Audit Management",
"Audit Permissions": "Audit Permissions", "Audit Permissions": "Audit Permissions",
"Authorization updated successfully": "Authorization updated successfully", "Authorization updated successfully": "Authorization updated successfully",
@ -173,6 +176,7 @@
"Batch": "Batch", "Batch": "Batch",
"Batch No": "Batch No", "Batch No": "Batch No",
"Batch Number": "Batch Number", "Batch Number": "Batch Number",
"Before Qty": "変動前数量",
"Belongs To": "Belongs To", "Belongs To": "Belongs To",
"Belongs To Company": "Belongs To Company", "Belongs To Company": "Belongs To Company",
"Branch": "分倉庫", "Branch": "分倉庫",
@ -259,9 +263,9 @@
"Confirm Account Status Change": "Confirm Account Status Change", "Confirm Account Status Change": "Confirm Account Status Change",
"Confirm Assignment": "Confirm Assignment", "Confirm Assignment": "Confirm Assignment",
"Confirm Cancel": "キャンセル確認", "Confirm Cancel": "キャンセル確認",
"Confirm Complete": "完了を確認",
"Confirm Deactivation": "無効化の確認", "Confirm Deactivation": "無効化の確認",
"Confirm Delete": "削除の確認", "Confirm Delete": "削除の確認",
"Confirm Complete": "完了を確認",
"Confirm Deletion": "削除の確認", "Confirm Deletion": "削除の確認",
"Confirm Password": "Confirm Password", "Confirm Password": "Confirm Password",
"Confirm Prepare": "準備確認", "Confirm Prepare": "準備確認",
@ -356,8 +360,6 @@
"Default Not Donate": "Default Not Donate", "Default Not Donate": "Default Not Donate",
"Define and manage security roles and permissions.": "Define and manage security roles and permissions.", "Define and manage security roles and permissions.": "Define and manage security roles and permissions.",
"Define new third-party payment parameters": "Define new third-party payment parameters", "Define new third-party payment parameters": "Define new third-party payment parameters",
"Yes, Deactivate": "はい、無効にします",
"Yes, Delete": "はい、削除します",
"Delete Account": "Delete Account", "Delete Account": "Delete Account",
"Delete Advertisement": "Delete Advertisement", "Delete Advertisement": "Delete Advertisement",
"Delete Advertisement Confirmation": "Delete Advertisement Confirmation", "Delete Advertisement Confirmation": "Delete Advertisement Confirmation",
@ -373,6 +375,7 @@
"Delivery door closed": "Delivery door closed", "Delivery door closed": "Delivery door closed",
"Delivery door open error": "Delivery door open error", "Delivery door open error": "Delivery door open error",
"Delivery door opened": "Delivery door opened", "Delivery door opened": "Delivery door opened",
"Delta": "変動量",
"Deposit Bonus": "Deposit Bonus", "Deposit Bonus": "Deposit Bonus",
"Describe the repair or maintenance status...": "Describe the repair or maintenance status...", "Describe the repair or maintenance status...": "Describe the repair or maintenance status...",
"Description / Name": "説明 / 名称", "Description / Name": "説明 / 名称",
@ -391,8 +394,14 @@
"Disabled": "無効", "Disabled": "無効",
"Disabling this customer will also disable all accounts under this customer. Are you sure you want to continue?": "この顧客を無効化すると、この顧客のすべてのアカウントも無効になります。続けますか?", "Disabling this customer will also disable all accounts under this customer. Are you sure you want to continue?": "この顧客を無効化すると、この顧客のすべてのアカウントも無効になります。続けますか?",
"Discord Notifications": "Discord Notifications", "Discord Notifications": "Discord Notifications",
"Dispense Failed": "Dispense Failed", "Discount": "割引",
"Dispense Success": "Dispense Success", "Dispense Failed": "配送失敗",
"Dispense Pending": "配送保留",
"Dispense Product": "配送商品",
"Dispense Quantity": "配送数量",
"Dispense Status": "配送ステータス",
"Dispense Success": "配送成功",
"Dispense Time": "配送時間",
"Dispense error (0407)": "Dispense error (0407)", "Dispense error (0407)": "Dispense error (0407)",
"Dispense error (0408)": "Dispense error (0408)", "Dispense error (0408)": "Dispense error (0408)",
"Dispense error (0409)": "Dispense error (0409)", "Dispense error (0409)": "Dispense error (0409)",
@ -430,6 +439,7 @@
"Edit Machine Name": "Edit Machine Name", "Edit Machine Name": "Edit Machine Name",
"Edit Machine Settings": "Edit Machine Settings", "Edit Machine Settings": "Edit Machine Settings",
"Edit Name": "Edit Name", "Edit Name": "Edit Name",
"Edit Pass Code": "通行コード編集",
"Edit Payment Config": "Edit Payment Config", "Edit Payment Config": "Edit Payment Config",
"Edit Product": "Edit Product", "Edit Product": "Edit Product",
"Edit Role": "Edit Role", "Edit Role": "Edit Role",
@ -499,7 +509,7 @@
"Expiry Management": "Expiry Management", "Expiry Management": "Expiry Management",
"Expiry Time": "有効期限時間", "Expiry Time": "有効期限時間",
"Expiry date tracking and warnings": "Expiry date tracking and warnings", "Expiry date tracking and warnings": "Expiry date tracking and warnings",
"Failed": "Failed", "Failed": "失敗",
"Failed to fetch machine data.": "Failed to fetch machine data.", "Failed to fetch machine data.": "Failed to fetch machine data.",
"Failed to load permissions": "Failed to load permissions", "Failed to load permissions": "Failed to load permissions",
"Failed to load preview": "プレビューの読み込みに失敗しました", "Failed to load preview": "プレビューの読み込みに失敗しました",
@ -518,6 +528,8 @@
"Firmware updated to :version": "Firmware updated to :version", "Firmware updated to :version": "Firmware updated to :version",
"Fleet Avg OEE": "Fleet Avg OEE", "Fleet Avg OEE": "Fleet Avg OEE",
"Fleet Performance": "Fleet Performance", "Fleet Performance": "Fleet Performance",
"Flow ID": "フローID",
"Flow ID / Time": "流水番号 / 時間",
"Force End Session": "Force End Session", "Force End Session": "Force End Session",
"Force end current session": "Force end current session", "Force end current session": "Force end current session",
"From": "発送元", "From": "発送元",
@ -537,6 +549,7 @@
"Gift Definitions": "Gift Definitions", "Gift Definitions": "Gift Definitions",
"Global roles accessible by all administrators.": "Global roles accessible by all administrators.", "Global roles accessible by all administrators.": "Global roles accessible by all administrators.",
"Go Back": "戻る", "Go Back": "戻る",
"Go to E-Invoice": "電子請求書へ",
"Goods & System Settings": "商品とシステム設定", "Goods & System Settings": "商品とシステム設定",
"Got it": "Got it", "Got it": "Got it",
"Grant UI Access": "Grant UI Access", "Grant UI Access": "Grant UI Access",
@ -581,7 +594,12 @@
"Inventory Overview": "在庫概要", "Inventory Overview": "在庫概要",
"Inventory Stable": "Inventory Stable", "Inventory Stable": "Inventory Stable",
"Inventory synced with machine": "Inventory synced with machine", "Inventory synced with machine": "Inventory synced with machine",
"Invoice Date": "請求書日付",
"Invoice Information": "請求情報",
"Invoice Number": "請求書番号",
"Invoice Number / Flow ID": "請求書番号 / 流水番号",
"Invoice Status": "Invoice Status", "Invoice Status": "Invoice Status",
"Issued At": "発行時間",
"Item List": "品目リスト", "Item List": "品目リスト",
"Items": "Items", "Items": "Items",
"JKO_MERCHANT_ID": "JKO_MERCHANT_ID", "JKO_MERCHANT_ID": "JKO_MERCHANT_ID",
@ -622,8 +640,8 @@
"Live Fleet Updates": "Live Fleet Updates", "Live Fleet Updates": "Live Fleet Updates",
"Loading Cabinet...": "Loading Cabinet...", "Loading Cabinet...": "Loading Cabinet...",
"Loading Data": "Loading Data", "Loading Data": "Loading Data",
"Loading machines...": "マシンの読み込み中...",
"Loading failed": "読み込みに失敗しました", "Loading failed": "読み込みに失敗しました",
"Loading machines...": "マシンの読み込み中...",
"Loading...": "読み込み中...", "Loading...": "読み込み中...",
"Location": "Location", "Location": "Location",
"Location found!": "Location found!", "Location found!": "Location found!",
@ -646,7 +664,8 @@
"Low stock and out-of-stock alerts": "Low stock and out-of-stock alerts", "Low stock and out-of-stock alerts": "Low stock and out-of-stock alerts",
"Loyalty & Features": "Loyalty & Features", "Loyalty & Features": "Loyalty & Features",
"Machine": "マシン", "Machine": "マシン",
"Machine / Slot": "機台 / 貨道", "Machine / Date": "機台 / 日付",
"Machine / Slot": "機台 / スロット",
"Machine Advertisement Settings": "Machine Advertisement Settings", "Machine Advertisement Settings": "Machine Advertisement Settings",
"Machine Count": "Machine Count", "Machine Count": "Machine Count",
"Machine Details": "Machine Details", "Machine Details": "Machine Details",
@ -664,7 +683,7 @@
"Machine Management Permissions": "Machine Management Permissions", "Machine Management Permissions": "Machine Management Permissions",
"Machine Model": "Machine Model", "Machine Model": "Machine Model",
"Machine Model Settings": "Machine Model Settings", "Machine Model Settings": "Machine Model Settings",
"Machine Name": "Machine Name", "Machine Name": "機台名",
"Machine Permissions": "Machine Permissions", "Machine Permissions": "Machine Permissions",
"Machine Reboot": "Machine Reboot", "Machine Reboot": "Machine Reboot",
"Machine Registry": "Machine Registry", "Machine Registry": "Machine Registry",
@ -672,11 +691,13 @@
"Machine Reports": "Machine Reports", "Machine Reports": "Machine Reports",
"Machine Restart": "Machine Restart", "Machine Restart": "Machine Restart",
"Machine Return": "機台返品", "Machine Return": "機台返品",
"Machine Serial": "機台シリアル",
"Machine Serial No": "Machine Serial No", "Machine Serial No": "Machine Serial No",
"Machine Settings": "Machine Settings", "Machine Settings": "Machine Settings",
"Machine Status": "Machine Status", "Machine Status": "Machine Status",
"Machine Status List": "Machine Status List", "Machine Status List": "Machine Status List",
"Machine Stock": "マシン在庫", "Machine Stock": "マシン在庫",
"Machine Stock Movements": "機台在庫異動履歴",
"Machine System Settings": "機台システム設定", "Machine System Settings": "機台システム設定",
"Machine Utilization": "Machine Utilization", "Machine Utilization": "Machine Utilization",
"Machine created successfully.": "Machine created successfully.", "Machine created successfully.": "Machine created successfully.",
@ -769,17 +790,6 @@
"Motor not stopped": "Motor not stopped", "Motor not stopped": "Motor not stopped",
"Movement History": "移動履歴", "Movement History": "移動履歴",
"Movement Logs": "移動ログ", "Movement Logs": "移動ログ",
"Machine Stock Movements": "機台在庫異動履歴",
"Stock Movement Log": "在庫異動ログ",
"movement.type.replenishment": "補充入庫",
"movement.type.pickup": "受取コード消費",
"movement.type.remote_dispense": "リモート出庫",
"movement.type.adjustment": "棚卸調整",
"movement.type.rollback": "出庫失敗ロールバック",
"Before Qty": "変動前数量",
"After Qty": "変動後数量",
"Delta": "変動量",
"No movements found": "異動記録なし",
"Multilingual Names": "Multilingual Names", "Multilingual Names": "Multilingual Names",
"N/A": "N/A", "N/A": "N/A",
"Name": "Name", "Name": "Name",
@ -812,6 +822,7 @@
"No advertisements found.": "No advertisements found.", "No advertisements found.": "No advertisements found.",
"No alert summary": "No alert summary", "No alert summary": "No alert summary",
"No assignments": "No assignments", "No assignments": "No assignments",
"No associated order found": "関連注文が見つかりません",
"No categories found.": "No categories found.", "No categories found.": "No categories found.",
"No command history": "No command history", "No command history": "No command history",
"No configurations found": "No configurations found", "No configurations found": "No configurations found",
@ -834,12 +845,15 @@
"No matching machines": "No matching machines", "No matching machines": "No matching machines",
"No materials available": "No materials available", "No materials available": "No materials available",
"No movement records found": "移動履歴が見つかりません", "No movement records found": "移動履歴が見つかりません",
"No movements found": "異動記録なし",
"No pass codes found": "通行コードが見つかりません", "No pass codes found": "通行コードが見つかりません",
"No permissions": "No permissions", "No permissions": "No permissions",
"No pickup codes found": "受取コードが見つかりません", "No pickup codes found": "受取コードが見つかりません",
"No product record found": "商品記録が見つかりません",
"No products found in this warehouse": "この倉庫に在庫はありません", "No products found in this warehouse": "この倉庫に在庫はありません",
"No products found matching your criteria.": "No products found matching your criteria.", "No products found matching your criteria.": "No products found matching your criteria.",
"No records found": "No records found", "No records found": "No records found",
"No related detail found": "関連詳細が見つかりません",
"No replenishment orders found": "補充伝票が見つかりません", "No replenishment orders found": "補充伝票が見つかりません",
"No results found": "No results found", "No results found": "No results found",
"No roles available": "No roles available", "No roles available": "No roles available",
@ -850,6 +864,7 @@
"No slots need replenishment": "補充が必要なスロットはありません", "No slots need replenishment": "補充が必要なスロットはありません",
"No stock data found": "在庫データが見つかりません", "No stock data found": "在庫データが見つかりません",
"No stock-in orders found": "入庫伝票が見つかりません", "No stock-in orders found": "入庫伝票が見つかりません",
"No transaction orders found": "取引注文が見つかりません",
"No transfer orders found": "転送伝票が見つかりません", "No transfer orders found": "転送伝票が見つかりません",
"No users found": "No users found", "No users found": "No users found",
"No warehouses found": "倉庫が見つかりません", "No warehouses found": "倉庫が見つかりません",
@ -891,10 +906,14 @@
"Optional": "任意", "Optional": "任意",
"Optional remarks": "任意備考", "Optional remarks": "任意備考",
"Optional remarks...": "任意の備考...", "Optional remarks...": "任意の備考...",
"Order Details": "入庫伝票詳細", "Order Details": "注文詳細",
"Order Info": "注文情報", "Order Info": "注文情報",
"Order Items": "注文商品",
"Order Management": "Order Management", "Order Management": "Order Management",
"Order No.": "伝票番号", "Order No.": "伝票番号",
"Order Number / Time": "注文番号 / 時間",
"Order Status": "注文ステータス",
"Order Time": "注文時間",
"Order already completed": "注文はすでに完了しています", "Order already completed": "注文はすでに完了しています",
"Order already processed": "注文はすでに処理されています", "Order already processed": "注文はすでに処理されています",
"Order completed and stock updated": "注文が完了し、在庫が更新されました", "Order completed and stock updated": "注文が完了し、在庫が更新されました",
@ -955,7 +974,8 @@
"Pass code updated.": "通行コードが更新されました。", "Pass code updated.": "通行コードが更新されました。",
"Password": "Password", "Password": "Password",
"Password updated successfully.": "Password updated successfully.", "Password updated successfully.": "Password updated successfully.",
"Payment & Invoice": "Payment & Invoice", "Payment & Invoice": "決済と請求書",
"Payment Amount": "支払い金額",
"Payment Buffer Seconds": "Payment Buffer Seconds", "Payment Buffer Seconds": "Payment Buffer Seconds",
"Payment Config": "Payment Config", "Payment Config": "Payment Config",
"Payment Configuration": "Payment Configuration", "Payment Configuration": "Payment Configuration",
@ -963,11 +983,13 @@
"Payment Configuration deleted successfully.": "Payment Configuration deleted successfully.", "Payment Configuration deleted successfully.": "Payment Configuration deleted successfully.",
"Payment Configuration updated successfully.": "Payment Configuration updated successfully.", "Payment Configuration updated successfully.": "Payment Configuration updated successfully.",
"Payment Selection": "Payment Selection", "Payment Selection": "Payment Selection",
"Payment Type": "決済方法",
"Pending": "保留中", "Pending": "保留中",
"Per Page": "Per Page", "Per Page": "Per Page",
"Performance": "Performance", "Performance": "Performance",
"Permanent": "無期限", "Permanent": "無期限",
"Permanent Code": "永久コード", "Permanent Code": "永久コード",
"Permanent if empty": "空欄の場合は永久",
"Permanently Delete Account": "Permanently Delete Account", "Permanently Delete Account": "Permanently Delete Account",
"Permission Settings": "Permission Settings", "Permission Settings": "Permission Settings",
"Permission Tags": "Permission Tags", "Permission Tags": "Permission Tags",
@ -1016,12 +1038,13 @@
"Previous": "Previous", "Previous": "Previous",
"Price / Member": "Price / Member", "Price / Member": "Price / Member",
"Pricing Information": "Pricing Information", "Pricing Information": "Pricing Information",
"Print Invoice": "請求書印刷",
"Product": "商品", "Product": "商品",
"Product / Slot": "商品 / 貨道", "Product / Slot": "商品 / 貨道",
"Product / Stock": "商品 / 在庫", "Product / Stock": "商品 / 在庫",
"Product Count": "Product Count", "Product Count": "商品数量",
"Product Details": "商品細", "Product Details": "商品細",
"Product ID": "商品ID", "Product ID": "商品番号",
"Product Image": "Product Image", "Product Image": "Product Image",
"Product Info": "Product Info", "Product Info": "Product Info",
"Product List": "Product List", "Product List": "Product List",
@ -1062,8 +1085,6 @@
"Quick Expiry Check": "Quick Expiry Check", "Quick Expiry Check": "Quick Expiry Check",
"Quick Maintenance": "Quick Maintenance", "Quick Maintenance": "Quick Maintenance",
"Quick Replenish": "クイック補充", "Quick Replenish": "クイック補充",
"Search logs...": "ログを検索...",
"Searchable Select": "Searchable Select",
"Quick replenishment from this view": "Quick replenishment from this view", "Quick replenishment from this view": "Quick replenishment from this view",
"Quick search...": "Quick search...", "Quick search...": "Quick search...",
"Real-time OEE analysis awaits": "Real-time OEE analysis awaits", "Real-time OEE analysis awaits": "Real-time OEE analysis awaits",
@ -1082,6 +1103,7 @@
"Recent Login": "Recent Login", "Recent Login": "Recent Login",
"Recently reported errors or warnings in logs": "Recently reported errors or warnings in logs", "Recently reported errors or warnings in logs": "Recently reported errors or warnings in logs",
"Records": "Records", "Records": "Records",
"Refunded": "返金済み",
"Regenerate": "再生成", "Regenerate": "再生成",
"Regenerating the token will disconnect the physical machine until it is updated. Continue?": "Regenerating the token will disconnect the physical machine until it is updated. Continue?", "Regenerating the token will disconnect the physical machine until it is updated. Continue?": "Regenerating the token will disconnect the physical machine until it is updated. Continue?",
"Remote Change": "Remote Change", "Remote Change": "Remote Change",
@ -1171,7 +1193,10 @@
"Scan to pick up your product": "商品を受け取るためにスキャンしてください", "Scan to pick up your product": "商品を受け取るためにスキャンしてください",
"Schedule": "Schedule", "Schedule": "Schedule",
"Search Company Title...": "Search Company Title...", "Search Company Title...": "Search Company Title...",
"Search Flow ID / Slot...": "流水番号 / スロットを検索...",
"Search Invoice No / Flow ID...": "請求書番号 / 流水番号を検索...",
"Search Machine...": "Search Machine...", "Search Machine...": "Search Machine...",
"Search Order No / Flow ID / Invoice...": "注文番号 / フローID / 請求書番号で検索...",
"Search Product": "商品を検索", "Search Product": "商品を検索",
"Search accounts...": "Search accounts...", "Search accounts...": "Search accounts...",
"Search by code, machine name or serial...": "コード、機台名、またはシリアルで検索...", "Search by code, machine name or serial...": "コード、機台名、またはシリアルで検索...",
@ -1183,6 +1208,7 @@
"Search company...": "Search company...", "Search company...": "Search company...",
"Search configurations...": "Search configurations...", "Search configurations...": "Search configurations...",
"Search customers...": "Search customers...", "Search customers...": "Search customers...",
"Search logs...": "ログを検索...",
"Search machines by name or serial...": "Search machines by name or serial...", "Search machines by name or serial...": "Search machines by name or serial...",
"Search machines...": "機台を検索...", "Search machines...": "機台を検索...",
"Search models...": "Search models...", "Search models...": "Search models...",
@ -1195,6 +1221,7 @@
"Search users...": "Search users...", "Search users...": "Search users...",
"Search warehouses...": "倉庫を検索...", "Search warehouses...": "倉庫を検索...",
"Search...": "Search...", "Search...": "Search...",
"Searchable Select": "Searchable Select",
"Searching...": "Searching...", "Searching...": "Searching...",
"Seconds": "Seconds", "Seconds": "Seconds",
"Security & State": "Security & State", "Security & State": "Security & State",
@ -1251,6 +1278,7 @@
"Sign in to your account": "Sign in to your account", "Sign in to your account": "Sign in to your account",
"Signed in as": "Signed in as", "Signed in as": "Signed in as",
"Slot": "貨道", "Slot": "貨道",
"Slot / Product": "スロット / 商品",
"Slot Mechanism (default: Conveyor, check for Spring)": "Slot Mechanism (default: Conveyor, check for Spring)", "Slot Mechanism (default: Conveyor, check for Spring)": "Slot Mechanism (default: Conveyor, check for Spring)",
"Slot No": "Slot No", "Slot No": "Slot No",
"Slot Status": "Slot Status", "Slot Status": "Slot Status",
@ -1291,6 +1319,7 @@
"Start Time": "開始時間", "Start Time": "開始時間",
"Statistics": "Statistics", "Statistics": "Statistics",
"Status": "ステータス", "Status": "ステータス",
"Status / Invoice": "状態 / 請求書",
"Status / Temp / Sub / Card / Scan": "Status / Temp / Sub / Card / Scan", "Status / Temp / Sub / Card / Scan": "Status / Temp / Sub / Card / Scan",
"Status Timeline": "ステータスタイムライン", "Status Timeline": "ステータスタイムライン",
"Status updated successfully": "ステータス更新成功", "Status updated successfully": "ステータス更新成功",
@ -1304,6 +1333,7 @@
"Stock Level > 50%": "在庫 50% 以上", "Stock Level > 50%": "在庫 50% 以上",
"Stock Levels": "在庫レベル", "Stock Levels": "在庫レベル",
"Stock Management": "Stock Management", "Stock Management": "Stock Management",
"Stock Movement Log": "在庫異動ログ",
"Stock Out": "出庫", "Stock Out": "出庫",
"Stock Quantity": "Stock Quantity", "Stock Quantity": "Stock Quantity",
"Stock Rate": "在庫率", "Stock Rate": "在庫率",
@ -1314,6 +1344,7 @@
"Stock returned to warehouse": "在庫が倉庫に返却されました", "Stock returned to warehouse": "在庫が倉庫に返却されました",
"Stock-In Management": "入庫管理", "Stock-In Management": "入庫管理",
"Stock-In Order": "入庫注文", "Stock-In Order": "入庫注文",
"Stock-In Order Details": "入庫伝票詳細",
"Stock-In Orders": "入庫伝票", "Stock-In Orders": "入庫伝票",
"Stock-In Orders Tab": "入庫伝票", "Stock-In Orders Tab": "入庫伝票",
"Stock-in order": "入庫注文", "Stock-in order": "入庫注文",
@ -1333,7 +1364,8 @@
"Sub-actions": "Sub-actions", "Sub-actions": "Sub-actions",
"Sub-machine Status Request": "Sub-machine Status Request", "Sub-machine Status Request": "Sub-machine Status Request",
"Submit Record": "Submit Record", "Submit Record": "Submit Record",
"Success": "Success", "Subtotal": "小計",
"Success": "成功",
"Super Admin": "Super Admin", "Super Admin": "Super Admin",
"Super-admin role cannot be assigned to tenant accounts.": "Super-admin role cannot be assigned to tenant accounts.", "Super-admin role cannot be assigned to tenant accounts.": "Super-admin role cannot be assigned to tenant accounts.",
"Superseded": "Superseded", "Superseded": "Superseded",
@ -1394,7 +1426,7 @@
"To:": "To:", "To:": "To:",
"Today Cumulative Sales": "Today Cumulative Sales", "Today Cumulative Sales": "Today Cumulative Sales",
"Today's Transactions": "Today's Transactions", "Today's Transactions": "Today's Transactions",
"Total": "Total", "Total": "合計",
"Total Connected": "Total Connected", "Total Connected": "Total Connected",
"Total Customers": "Total Customers", "Total Customers": "Total Customers",
"Total Daily Sales": "Total Daily Sales", "Total Daily Sales": "Total Daily Sales",
@ -1416,6 +1448,8 @@
"Track stock levels, stock-in orders, and movement history": "在庫レベル、入庫伝票、および移動履歴の追跡", "Track stock levels, stock-in orders, and movement history": "在庫レベル、入庫伝票、および移動履歴の追跡",
"Track stock-in orders and movement history": "入庫伝票および移動履歴の追跡", "Track stock-in orders and movement history": "入庫伝票および移動履歴の追跡",
"Traditional Chinese": "Traditional Chinese", "Traditional Chinese": "Traditional Chinese",
"Transaction Info": "取引情報",
"Transaction Time": "取引時間",
"Transaction processed: :id": "Transaction processed: :id", "Transaction processed: :id": "Transaction processed: :id",
"Transfer Audit": "転送監査", "Transfer Audit": "転送監査",
"Transfer Details": "転送伝票詳細", "Transfer Details": "転送伝票詳細",
@ -1458,11 +1492,9 @@
"Unlock Page": "Unlock Page", "Unlock Page": "Unlock Page",
"Unpublish": "配信終了", "Unpublish": "配信終了",
"Update": "更新", "Update": "更新",
"Edit Pass Code": "通行コード編集",
"Permanent if empty": "空欄の場合は永久",
"Update Pass Code": "通行コード更新",
"Update Authorization": "承認の更新", "Update Authorization": "承認の更新",
"Update Customer": "Update Customer", "Update Customer": "Update Customer",
"Update Pass Code": "通行コード更新",
"Update Password": "Update Password", "Update Password": "Update Password",
"Update Product": "Update Product", "Update Product": "Update Product",
"Update Settings": "設定を更新", "Update Settings": "設定を更新",
@ -1499,12 +1531,14 @@
"View Inventory": "在庫を表示", "View Inventory": "在庫を表示",
"View Logs": "View Logs", "View Logs": "View Logs",
"View More": "View More", "View More": "View More",
"View Order": "注文を表示",
"View QR Code": "QRコードを表示", "View QR Code": "QRコードを表示",
"View Slots": "貨道を表示", "View Slots": "貨道を表示",
"View all warehouses": "View all warehouses", "View all warehouses": "View all warehouses",
"View slot-level inventory for each machine": "View slot-level inventory for each machine", "View slot-level inventory for each machine": "View slot-level inventory for each machine",
"Visit Gift": "Visit Gift", "Visit Gift": "Visit Gift",
"Visual overview of all machine locations": "全機器位置のビジュアル概要", "Visual overview of all machine locations": "全機器位置のビジュアル概要",
"Void Invoice": "請求書無効化",
"Waiting": "Waiting", "Waiting": "Waiting",
"Waiting for Payment": "Waiting for Payment", "Waiting for Payment": "Waiting for Payment",
"Warehouse": "倉庫", "Warehouse": "倉庫",
@ -1544,6 +1578,8 @@
"Welcome Gift Status": "Welcome Gift Status", "Welcome Gift Status": "Welcome Gift Status",
"Work Content": "作業内容", "Work Content": "作業内容",
"Yes, Cancel": "はい、キャンセルします", "Yes, Cancel": "はい、キャンセルします",
"Yes, Deactivate": "はい、無効にします",
"Yes, Delete": "はい、削除します",
"Yes, Disable": "はい、無効にします", "Yes, Disable": "はい、無効にします",
"Yesterday": "Yesterday", "Yesterday": "Yesterday",
"You can assign or change the personnel handling this order": "この注文の担当者を割り当て、または変更できます", "You can assign or change the personnel handling this order": "この注文の担当者を割り当て、または変更できます",
@ -1554,6 +1590,7 @@
"accounts": "accounts", "accounts": "accounts",
"admin": "admin", "admin": "admin",
"analysis": "analysis", "analysis": "analysis",
"and :count other items": "他 :count 件の商品",
"app": "app", "app": "app",
"audit": "audit", "audit": "audit",
"basic-settings": "basic-settings", "basic-settings": "basic-settings",
@ -1561,6 +1598,8 @@
"basic.payment-configs": "basic.payment-configs", "basic.payment-configs": "basic.payment-configs",
"by": "by", "by": "by",
"companies": "companies", "companies": "companies",
"consume": "受取成功",
"consume_failed": "受取失敗",
"data-config": "data-config", "data-config": "data-config",
"data-config.sub-account-roles": "data-config.sub-account-roles", "data-config.sub-account-roles": "data-config.sub-account-roles",
"data-config.sub-accounts": "data-config.sub-accounts", "data-config.sub-accounts": "data-config.sub-accounts",
@ -1635,6 +1674,11 @@
"menu.warehouses.transfers": "在庫転送", "menu.warehouses.transfers": "在庫転送",
"min": "min", "min": "min",
"mins ago": "mins ago", "mins ago": "mins ago",
"movement.type.adjustment": "棚卸調整",
"movement.type.pickup": "受取コード消費",
"movement.type.remote_dispense": "リモート出庫",
"movement.type.replenishment": "補充入庫",
"movement.type.rollback": "出庫失敗ロールバック",
"of": "of", "of": "of",
"of items": "件のアイテム", "of items": "件のアイテム",
"pending": "pending", "pending": "pending",
@ -1656,12 +1700,10 @@
"to": "to", "to": "to",
"user": "user", "user": "user",
"vending": "vending", "vending": "vending",
"verify_success": "検証成功",
"video": "video", "video": "video",
"visit_gift": "visit_gift", "visit_gift": "visit_gift",
"vs Yesterday": "vs Yesterday", "vs Yesterday": "vs Yesterday",
"warehouses": "warehouses", "warehouses": "warehouses",
"待填寫": "待填寫", "待填寫": "待填寫"
"verify_success": "検証成功", }
"consume": "受取成功",
"consume_failed": "受取失敗"
}

View File

@ -74,6 +74,7 @@
"Affiliated Company": "公司名稱", "Affiliated Company": "公司名稱",
"Affiliated Unit": "公司名稱", "Affiliated Unit": "公司名稱",
"Affiliation": "所屬單位", "Affiliation": "所屬單位",
"After Qty": "異動後數量",
"Alert Summary": "告警摘要", "Alert Summary": "告警摘要",
"Alerts": "警示", "Alerts": "警示",
"Alerts Pending": "待處理告警", "Alerts Pending": "待處理告警",
@ -85,6 +86,7 @@
"All Levels": "所有層級", "All Levels": "所有層級",
"All Machines": "所有機台", "All Machines": "所有機台",
"All Permissions": "全部權限", "All Permissions": "全部權限",
"All Slots": "所有貨道",
"All Stable": "狀態穩定", "All Stable": "狀態穩定",
"All Status": "所有狀態", "All Status": "所有狀態",
"All Statuses": "所有狀態", "All Statuses": "所有狀態",
@ -92,8 +94,10 @@
"All Times System Timezone": "所有時間為系統時區", "All Times System Timezone": "所有時間為系統時區",
"All Types": "所有類型", "All Types": "所有類型",
"All Warehouses": "所有倉庫", "All Warehouses": "所有倉庫",
"All issues marked as resolved.": "所有異常已標記為已排除。",
"All slots are fully stocked": "所有貨道已滿貨", "All slots are fully stocked": "所有貨道已滿貨",
"Amount": "金額", "Amount": "金額",
"Amount / Payment": "金額 / 支付",
"An error occurred while saving.": "儲存時發生錯誤。", "An error occurred while saving.": "儲存時發生錯誤。",
"Analysis Management": "分析管理", "Analysis Management": "分析管理",
"Analysis Permissions": "分析管理權限", "Analysis Permissions": "分析管理權限",
@ -133,6 +137,7 @@
"Are you sure you want to disable this pass code? It will no longer be valid for machine access.": "您確定要停用此通行碼嗎?停用後將無法再用於機台存取。", "Are you sure you want to disable this pass code? It will no longer be valid for machine access.": "您確定要停用此通行碼嗎?停用後將無法再用於機台存取。",
"Are you sure you want to proceed? This action cannot be undone.": "您確定要繼續嗎?此操作將無法復原。", "Are you sure you want to proceed? This action cannot be undone.": "您確定要繼續嗎?此操作將無法復原。",
"Are you sure you want to remove this assignment?": "您確定要移除此投放嗎?", "Are you sure you want to remove this assignment?": "您確定要移除此投放嗎?",
"Are you sure you want to resolve all recent issues for this machine?": "您確定要排除此機台目前所有的異常紀錄嗎?這將會恢復機台狀態為正常。",
"Are you sure you want to send this command?": "確定要發送此指令嗎?", "Are you sure you want to send this command?": "確定要發送此指令嗎?",
"Are you sure you want to start delivery?": "確定要開始配送嗎?", "Are you sure you want to start delivery?": "確定要開始配送嗎?",
"Are you sure?": "確定要執行此操作嗎?", "Are you sure?": "確定要執行此操作嗎?",
@ -146,6 +151,7 @@
"Assigned Machines": "授權機台", "Assigned Machines": "授權機台",
"Assigned To": "指派人員", "Assigned To": "指派人員",
"Assignment removed successfully.": "廣告投放已移除。", "Assignment removed successfully.": "廣告投放已移除。",
"Associated Order": "關聯訂單",
"Audit Management": "稽核管理", "Audit Management": "稽核管理",
"Audit Permissions": "稽核管理權限", "Audit Permissions": "稽核管理權限",
"Authorization updated successfully": "授權更新成功", "Authorization updated successfully": "授權更新成功",
@ -173,6 +179,7 @@
"Batch": "批號", "Batch": "批號",
"Batch No": "批號", "Batch No": "批號",
"Batch Number": "批號", "Batch Number": "批號",
"Before Qty": "異動前數量",
"Belongs To": "公司名稱", "Belongs To": "公司名稱",
"Belongs To Company": "公司名稱", "Belongs To Company": "公司名稱",
"Branch": "分倉", "Branch": "分倉",
@ -183,8 +190,8 @@
"CREATE STOCK TRANSFERS BETWEEN WAREHOUSES AND MACHINE RETURNS": "建立倉庫間調撥或機台退庫單", "CREATE STOCK TRANSFERS BETWEEN WAREHOUSES AND MACHINE RETURNS": "建立倉庫間調撥或機台退庫單",
"Calculate Replenishment": "計算補貨量", "Calculate Replenishment": "計算補貨量",
"Cancel": "取消", "Cancel": "取消",
"Cancel Pass Code": "取消通行碼",
"Cancel Order": "取消訂單", "Cancel Order": "取消訂單",
"Cancel Pass Code": "取消通行碼",
"Cancel Pickup Code": "取消取貨碼", "Cancel Pickup Code": "取消取貨碼",
"Cancel Purchase": "取消購買", "Cancel Purchase": "取消購買",
"Cancelled": "已取消", "Cancelled": "已取消",
@ -225,6 +232,7 @@
"Checkout Time 1": "卡機結帳時間1", "Checkout Time 1": "卡機結帳時間1",
"Checkout Time 2": "卡機結帳時間2", "Checkout Time 2": "卡機結帳時間2",
"Clear": "清除", "Clear": "清除",
"Clear Abnormal Status": "清除異常狀態",
"Clear Filter": "清除篩選", "Clear Filter": "清除篩選",
"Clear Stock": "庫存清空", "Clear Stock": "庫存清空",
"Click here to re-send the verification email.": "點擊此處重新發送驗證郵件。", "Click here to re-send the verification email.": "點擊此處重新發送驗證郵件。",
@ -371,6 +379,7 @@
"Delivery door closed": "送貨門關閉", "Delivery door closed": "送貨門關閉",
"Delivery door open error": "送貨門開啟異常", "Delivery door open error": "送貨門開啟異常",
"Delivery door opened": "送貨門開啟", "Delivery door opened": "送貨門開啟",
"Delta": "變化量",
"Deposit Bonus": "儲值回饋", "Deposit Bonus": "儲值回饋",
"Describe the repair or maintenance status...": "請描述維修或保養狀況...", "Describe the repair or maintenance status...": "請描述維修或保養狀況...",
"Description / Name": "描述 / 名稱", "Description / Name": "描述 / 名稱",
@ -389,8 +398,15 @@
"Disabled": "已停用", "Disabled": "已停用",
"Disabling this customer will also disable all accounts under this customer. Are you sure you want to continue?": "停用此客戶將會連帶停用該客戶下的所有帳號,確定要繼續嗎?", "Disabling this customer will also disable all accounts under this customer. Are you sure you want to continue?": "停用此客戶將會連帶停用該客戶下的所有帳號,確定要繼續嗎?",
"Discord Notifications": "Discord通知", "Discord Notifications": "Discord通知",
"Discount": "折扣",
"Dispense Failed": "出貨失敗", "Dispense Failed": "出貨失敗",
"Dispense Pending": "出貨中",
"Dispense Product": "出貨商品",
"Dispense Quantity": "出貨數量",
"Dispense Records": "出貨紀錄",
"Dispense Status": "出貨狀態",
"Dispense Success": "出貨成功", "Dispense Success": "出貨成功",
"Dispense Time": "出貨時間",
"Dispense error (0407)": "出貨過程異常 (0407)", "Dispense error (0407)": "出貨過程異常 (0407)",
"Dispense error (0408)": "出貨過程異常 (0408)", "Dispense error (0408)": "出貨過程異常 (0408)",
"Dispense error (0409)": "出貨過程異常 (0409)", "Dispense error (0409)": "出貨過程異常 (0409)",
@ -428,6 +444,7 @@
"Edit Machine Name": "編輯機台名稱", "Edit Machine Name": "編輯機台名稱",
"Edit Machine Settings": "編輯機台設定", "Edit Machine Settings": "編輯機台設定",
"Edit Name": "編輯名稱", "Edit Name": "編輯名稱",
"Edit Pass Code": "編輯通行碼",
"Edit Payment Config": "編輯金流配置", "Edit Payment Config": "編輯金流配置",
"Edit Product": "編輯商品", "Edit Product": "編輯商品",
"Edit Role": "編輯角色", "Edit Role": "編輯角色",
@ -437,6 +454,7 @@
"Edit Sub Account Role": "編輯子帳號角色", "Edit Sub Account Role": "編輯子帳號角色",
"Edit Warehouse": "編輯倉庫", "Edit Warehouse": "編輯倉庫",
"Electronic Invoice": "電子發票", "Electronic Invoice": "電子發票",
"Electronic Invoices": "電子發票",
"Elevator descending": "升降平台下降中", "Elevator descending": "升降平台下降中",
"Elevator descent error": "升降平台下降異常", "Elevator descent error": "升降平台下降異常",
"Elevator failure": "升降系統故障", "Elevator failure": "升降系統故障",
@ -476,6 +494,7 @@
"Error processing request": "處理請求時發生錯誤", "Error processing request": "處理請求時發生錯誤",
"Error report accepted": "錯誤回報已受理", "Error report accepted": "錯誤回報已受理",
"Error: :message (:code)": "錯誤::message (:code)", "Error: :message (:code)": "錯誤::message (:code)",
"Estimated Expiry": "預計到期時間",
"Execute": "執行", "Execute": "執行",
"Execute Change": "執行找零", "Execute Change": "執行找零",
"Execute Delivery Now": "立即執行出貨", "Execute Delivery Now": "立即執行出貨",
@ -483,7 +502,6 @@
"Execute maintenance and operational commands remotely": "遠端執行維護與各項營運指令", "Execute maintenance and operational commands remotely": "遠端執行維護與各項營運指令",
"Execution Time": "執行時間", "Execution Time": "執行時間",
"Exp": "效期", "Exp": "效期",
"Estimated Expiry": "預計到期時間",
"Expected Expiry": "預計過期時間", "Expected Expiry": "預計過期時間",
"Expected Expiry Date & Time": "預計到期時間", "Expected Expiry Date & Time": "預計到期時間",
"Expected Stock": "預期庫存", "Expected Stock": "預期庫存",
@ -497,11 +515,12 @@
"Expiry Management": "效期管理", "Expiry Management": "效期管理",
"Expiry Time": "到期時間", "Expiry Time": "到期時間",
"Expiry date tracking and warnings": "有效期限追蹤與預警", "Expiry date tracking and warnings": "有效期限追蹤與預警",
"Failed": "執行失敗", "Failed": "失敗",
"Failed to fetch machine data.": "無法取得機台資料。", "Failed to fetch machine data.": "無法取得機台資料。",
"Failed to load permissions": "載入權限失敗", "Failed to load permissions": "載入權限失敗",
"Failed to load preview": "載入預覽失敗", "Failed to load preview": "載入預覽失敗",
"Failed to load tab content": "載入分頁內容失敗", "Failed to load tab content": "載入分頁內容失敗",
"Failed to resolve issues.": "排除異常失敗。",
"Failed to save permissions.": "無法儲存權限設定。", "Failed to save permissions.": "無法儲存權限設定。",
"Failed to update machine images: ": "更新機台圖片失敗:", "Failed to update machine images: ": "更新機台圖片失敗:",
"Feature Settings": "功能設定", "Feature Settings": "功能設定",
@ -516,6 +535,88 @@
"Firmware updated to :version": "韌體版本更新 : :version", "Firmware updated to :version": "韌體版本更新 : :version",
"Fleet Avg OEE": "全機台平均 OEE", "Fleet Avg OEE": "全機台平均 OEE",
"Fleet Performance": "全機台效能", "Fleet Performance": "全機台效能",
"Flow ID": "流水號",
"Flow ID / Amount": "流水號 / 金額",
"Flow ID / Date": "流水號 / 日期",
"Flow ID / Machine": "流水號 / 機台",
"Flow ID / Order": "流水號 / 關聯訂單",
"Flow ID / Product": "流水號 / 商品",
"Flow ID / Slot": "流水號 / 貨道",
"Flow ID / Slot / Amount": "流水號 / 貨道 / 金額",
"Flow ID / Slot / Date": "流水號 / 貨道 / 日期",
"Flow ID / Slot / Machine": "流水號 / 貨道 / 機台",
"Flow ID / Slot / Order": "流水號 / 貨道 / 關聯訂單",
"Flow ID / Slot / Product": "流水號 / 貨道 / 商品",
"Flow ID / Slot / Product / Amount": "流水號 / 貨道 / 商品 / 金額",
"Flow ID / Slot / Product / Amount / Date": "流水號 / 貨道 / 商品 / 金額 / 日期",
"Flow ID / Slot / Product / Amount / Date / Order": "流水號 / 貨道 / 商品 / 金額 / 日期 / 關聯訂單",
"Flow ID / Slot / Product / Amount / Date / Time": "流水號 / 貨道 / 商品 / 金額 / 日期 / 時間",
"Flow ID / Slot / Product / Amount / Date / Time / Order": "流水號 / 貨道 / 商品 / 金額 / 日期 / 時間 / 關聯訂單",
"Flow ID / Slot / Product / Amount / Machine": "流水號 / 貨道 / 商品 / 金額 / 機台",
"Flow ID / Slot / Product / Amount / Machine / Date": "流水號 / 貨道 / 商品 / 金額 / 機台 / 日期",
"Flow ID / Slot / Product / Amount / Machine / Date / Order": "流水號 / 貨道 / 商品 / 金額 / 機台 / 日期 / 關聯訂單",
"Flow ID / Slot / Product / Amount / Machine / Date / Time": "流水號 / 貨道 / 商品 / 金額 / 機台 / 日期 / 時間",
"Flow ID / Slot / Product / Amount / Machine / Date / Time / Order": "流水號 / 貨道 / 商品 / 金額 / 機台 / 日期 / 時間 / 關聯訂單",
"Flow ID / Slot / Product / Amount / Machine / Order": "流水號 / 貨道 / 商品 / 金額 / 機台 / 關聯訂單",
"Flow ID / Slot / Product / Amount / Machine / Time": "流水號 / 貨道 / 商品 / 金額 / 機台 / 時間",
"Flow ID / Slot / Product / Amount / Machine / Time / Order": "流水號 / 貨道 / 商品 / 金額 / 機台 / 時間 / 關聯訂單",
"Flow ID / Slot / Product / Amount / Order": "流水號 / 貨道 / 商品 / 金額 / 關聯訂單",
"Flow ID / Slot / Product / Amount / Status": "流水號 / 貨道 / 商品 / 金額 / 狀態",
"Flow ID / Slot / Product / Amount / Status / Date": "流水號 / 貨道 / 商品 / 金額 / 狀態 / 日期",
"Flow ID / Slot / Product / Amount / Status / Date / Order": "流水號 / 貨道 / 商品 / 金額 / 狀態 / 日期 / 關聯訂單",
"Flow ID / Slot / Product / Amount / Status / Date / Time": "流水號 / 貨道 / 商品 / 金額 / 狀態 / 日期 / 時間",
"Flow ID / Slot / Product / Amount / Status / Date / Time / Order": "流水號 / 貨道 / 商品 / 金額 / 狀態 / 日期 / 時間 / 關聯訂單",
"Flow ID / Slot / Product / Amount / Status / Machine": "流水號 / 貨道 / 商品 / 金額 / 狀態 / 機台",
"Flow ID / Slot / Product / Amount / Status / Machine / Date": "流水號 / 貨道 / 商品 / 金額 / 狀態 / 機台 / 日期",
"Flow ID / Slot / Product / Amount / Status / Machine / Date / Order": "流水號 / 貨道 / 商品 / 金額 / 狀態 / 機台 / 日期 / 關聯訂單",
"Flow ID / Slot / Product / Amount / Status / Machine / Date / Time": "流水號 / 貨道 / 商品 / 金額 / 狀態 / 機台 / 日期 / 時間",
"Flow ID / Slot / Product / Amount / Status / Machine / Date / Time / Order": "流水號 / 貨道 / 商品 / 金額 / 狀態 / 機台 / 日期 / 時間 / 關聯訂單",
"Flow ID / Slot / Product / Amount / Status / Machine / Date / Time / Order / Extra": "流水號 / 貨道 / 商品 / 金額 / 狀態 / 機台 / 日期 / 時間 / 關聯訂單 / 額外",
"Flow ID / Slot / Product / Amount / Status / Machine / Date / Time / Order / Extra / More": "流水號 / 貨道 / 商品 / 金額 / 狀態 / 機台 / 日期 / 時間 / 關聯訂單 / 額外 / 更多",
"Flow ID / Slot / Product / Amount / Status / Machine / Date / Time / Order / Extra / More / Done": "流水號 / 貨道 / 商品 / 金額 / 狀態 / 機台 / 日期 / 時間 / 關聯訂單 / 額外 / 更多 / 完成",
"Flow ID / Slot / Product / Amount / Status / Machine / Order": "流水號 / 貨道 / 商品 / 金額 / 狀態 / 機台 / 關聯訂單",
"Flow ID / Slot / Product / Amount / Status / Machine / Time": "流水號 / 貨道 / 商品 / 金額 / 狀態 / 機台 / 時間",
"Flow ID / Slot / Product / Amount / Status / Machine / Time / Order": "流水號 / 貨道 / 商品 / 金額 / 狀態 / 機台 / 時間 / 關聯訂單",
"Flow ID / Slot / Product / Amount / Status / Order": "流水號 / 貨道 / 商品 / 金額 / 狀態 / 關聯訂單",
"Flow ID / Slot / Product / Amount / Status / Time": "流水號 / 貨道 / 商品 / 金額 / 狀態 / 時間",
"Flow ID / Slot / Product / Amount / Status / Time / Order": "流水號 / 貨道 / 商品 / 金額 / 狀態 / 時間 / 關聯訂單",
"Flow ID / Slot / Product / Amount / Time": "流水號 / 貨道 / 商品 / 金額 / 時間",
"Flow ID / Slot / Product / Amount / Time / Order": "流水號 / 貨道 / 商品 / 時間 / 關聯訂單",
"Flow ID / Slot / Product / Date": "流水號 / 貨道 / 商品 / 日期",
"Flow ID / Slot / Product / Date / Order": "流水號 / 貨道 / 商品 / 日期 / 關聯訂單",
"Flow ID / Slot / Product / Date / Time": "流水號 / 貨道 / 商品 / 日期 / 時間",
"Flow ID / Slot / Product / Date / Time / Order": "流水號 / 貨道 / 商品 / 日期 / 時間 / 關聯訂單",
"Flow ID / Slot / Product / Machine": "流水號 / 貨道 / 商品 / 機台",
"Flow ID / Slot / Product / Machine / Date": "流水號 / 貨道 / 商品 / 機台 / 日期",
"Flow ID / Slot / Product / Machine / Date / Order": "流水號 / 貨道 / 商品 / 機台 / 日期 / 關聯訂單",
"Flow ID / Slot / Product / Machine / Date / Time": "流水號 / 貨道 / 商品 / 機台 / 日期 / 時間",
"Flow ID / Slot / Product / Machine / Date / Time / Order": "流水號 / 貨道 / 商品 / 機台 / 日期 / 時間 / 關聯訂單",
"Flow ID / Slot / Product / Machine / Order": "流水號 / 貨道 / 商品 / 機台 / 關聯訂單",
"Flow ID / Slot / Product / Machine / Time": "流水號 / 貨道 / 商品 / 機台 / 時間",
"Flow ID / Slot / Product / Machine / Time / Order": "流水號 / 貨道 / 商品 / 機台 / 時間 / 關聯訂單",
"Flow ID / Slot / Product / Order": "流水號 / 貨道 / 商品 / 關聯訂單",
"Flow ID / Slot / Product / Status": "流水號 / 貨道 / 商品 / 狀態",
"Flow ID / Slot / Product / Status / Date": "流水號 / 貨道 / 商品 / 狀態 / 日期",
"Flow ID / Slot / Product / Status / Date / Order": "流水號 / 貨道 / 商品 / 狀態 / 日期 / 關聯訂單",
"Flow ID / Slot / Product / Status / Date / Time": "流水號 / 貨道 / 商品 / 狀態 / 日期 / 時間",
"Flow ID / Slot / Product / Status / Date / Time / Order": "流水號 / 貨道 / 商品 / 狀態 / 日期 / 時間 / 關聯訂單",
"Flow ID / Slot / Product / Status / Machine": "流水號 / 貨道 / 商品 / 狀態 / 機台",
"Flow ID / Slot / Product / Status / Machine / Date": "流水號 / 貨道 / 商品 / 狀態 / 機台 / 日期",
"Flow ID / Slot / Product / Status / Machine / Date / Order": "流水號 / 貨道 / 商品 / 狀態 / 機台 / 日期 / 關聯訂單",
"Flow ID / Slot / Product / Status / Machine / Date / Time": "流水號 / 貨道 / 商品 / 狀態 / 機台 / 日期 / 時間",
"Flow ID / Slot / Product / Status / Machine / Date / Time / Order": "流水號 / 貨道 / 商品 / 狀態 / 機台 / 日期 / 時間 / 關聯訂單",
"Flow ID / Slot / Product / Status / Machine / Order": "流水號 / 貨道 / 商品 / 狀態 / 機台 / 關聯訂單",
"Flow ID / Slot / Product / Status / Machine / Time": "流水號 / 貨道 / 商品 / 狀態 / 機台 / 時間",
"Flow ID / Slot / Product / Status / Machine / Time / Order": "流水號 / 貨道 / 商品 / 狀態 / 機台 / 時間 / 關聯訂單",
"Flow ID / Slot / Product / Status / Order": "流水號 / 貨道 / 商品 / 狀態 / 關聯訂單",
"Flow ID / Slot / Product / Status / Time": "流水號 / 貨道 / 商品 / 狀態 / 時間",
"Flow ID / Slot / Product / Status / Time / Order": "流水號 / 貨道 / 商品 / 狀態 / 時間 / 關聯訂單",
"Flow ID / Slot / Product / Time": "流水號 / 貨道 / 商品 / 時間",
"Flow ID / Slot / Product / Time / Order": "流水號 / 貨道 / 商品 / 時間 / 關聯訂單",
"Flow ID / Slot / Status": "流水號 / 貨道 / 狀態",
"Flow ID / Slot / Time": "流水號 / 貨道 / 時間",
"Flow ID / Status": "流水號 / 狀態",
"Flow ID / Time": "流水號 / 時間",
"Force End Session": "強制結束當前會話", "Force End Session": "強制結束當前會話",
"Force end current session": "強制結束目前的連線", "Force end current session": "強制結束目前的連線",
"From": "來源", "From": "來源",
@ -535,6 +636,7 @@
"Gift Definitions": "禮品設定", "Gift Definitions": "禮品設定",
"Global roles accessible by all administrators.": "適用於所有管理者的全域角色。", "Global roles accessible by all administrators.": "適用於所有管理者的全域角色。",
"Go Back": "返回", "Go Back": "返回",
"Go to E-Invoice": "前往電子發票",
"Goods & System Settings": "商品與系統設定", "Goods & System Settings": "商品與系統設定",
"Got it": "知道了", "Got it": "知道了",
"Grant UI Access": "開放 UI 存取權限", "Grant UI Access": "開放 UI 存取權限",
@ -579,7 +681,13 @@
"Inventory Overview": "庫存瀏覽", "Inventory Overview": "庫存瀏覽",
"Inventory Stable": "庫存穩定", "Inventory Stable": "庫存穩定",
"Inventory synced with machine": "庫存已與機台同步", "Inventory synced with machine": "庫存已與機台同步",
"Invoice Date": "開立日期",
"Invoice Information": "發票資訊",
"Invoice Number": "發票號碼",
"Invoice Number / Time": "發票號碼 / 時間",
"Invoice Number / Flow ID": "發票號碼 / 流水號",
"Invoice Status": "發票開立狀態", "Invoice Status": "發票開立狀態",
"Issued At": "開立時間",
"Item List": "商品清單", "Item List": "商品清單",
"Items": "筆", "Items": "筆",
"JKO_MERCHANT_ID": "街口支付 商店代號", "JKO_MERCHANT_ID": "街口支付 商店代號",
@ -615,12 +723,13 @@
"Line Products": "Line商品", "Line Products": "Line商品",
"LinePay": "LinePay", "LinePay": "LinePay",
"LinePay Payment": "LinePay 支付", "LinePay Payment": "LinePay 支付",
"Link": "連結",
"Link Copied": "連結已複製", "Link Copied": "連結已複製",
"Live Fleet Updates": "即時數據更新", "Live Fleet Updates": "即時數據更新",
"Loading Cabinet...": "正在載入機台貨盤...", "Loading Cabinet...": "正在載入機台貨盤...",
"Loading Data": "載入資料中", "Loading Data": "載入資料中",
"Loading machines...": "正在載入機台...",
"Loading failed": "載入失敗", "Loading failed": "載入失敗",
"Loading machines...": "正在載入機台...",
"Loading...": "載入中...", "Loading...": "載入中...",
"Location": "位置", "Location": "位置",
"Location found!": "已成功獲取座標!", "Location found!": "已成功獲取座標!",
@ -637,14 +746,16 @@
"Logout": "登出", "Logout": "登出",
"Logs": "日誌", "Logs": "日誌",
"Longitude": "經度", "Longitude": "經度",
"Link": "連結",
"Low": "低", "Low": "低",
"Low Stock": "庫存過低", "Low Stock": "庫存過低",
"Low Stock Alerts": "低庫存警示", "Low Stock Alerts": "低庫存警示",
"Low stock and out-of-stock alerts": "低庫存與缺貨警示", "Low stock and out-of-stock alerts": "低庫存與缺貨警示",
"Loyalty & Features": "行銷與點數", "Loyalty & Features": "行銷與點數",
"Machine": "機台", "Machine": "機台",
"Machine / Date": "機台 / 日期",
"Machine / Slot": "機台 / 貨道", "Machine / Slot": "機台 / 貨道",
"Machine Flow ID": "機台流水號",
"Machine Flow ID / Time": "機台流水號 / 時間",
"Machine Advertisement Settings": "機台廣告設置", "Machine Advertisement Settings": "機台廣告設置",
"Machine Count": "機台數量", "Machine Count": "機台數量",
"Machine Details": "機台詳情", "Machine Details": "機台詳情",
@ -670,11 +781,13 @@
"Machine Reports": "機台報表", "Machine Reports": "機台報表",
"Machine Restart": "機台重啟", "Machine Restart": "機台重啟",
"Machine Return": "機台退庫", "Machine Return": "機台退庫",
"Machine Serial": "機台序號",
"Machine Serial No": "機台序號", "Machine Serial No": "機台序號",
"Machine Settings": "機台設定", "Machine Settings": "機台設定",
"Machine Status": "機台狀態", "Machine Status": "機台狀態",
"Machine Status List": "機台運行狀態列表", "Machine Status List": "機台運行狀態列表",
"Machine Stock": "機台庫存", "Machine Stock": "機台庫存",
"Machine Stock Movements": "機台庫存流水帳",
"Machine System Settings": "機台系統設定", "Machine System Settings": "機台系統設定",
"Machine Utilization": "機台稼動率", "Machine Utilization": "機台稼動率",
"Machine created successfully.": "機台已成功建立。", "Machine created successfully.": "機台已成功建立。",
@ -767,17 +880,6 @@
"Motor not stopped": "電機未停止", "Motor not stopped": "電機未停止",
"Movement History": "異動紀錄", "Movement History": "異動紀錄",
"Movement Logs": "異動紀錄", "Movement Logs": "異動紀錄",
"Machine Stock Movements": "機台庫存流水帳",
"Stock Movement Log": "庫存流水帳",
"movement.type.replenishment": "補貨入庫",
"movement.type.pickup": "取貨碼消耗",
"movement.type.remote_dispense": "遠端出貨",
"movement.type.adjustment": "盤點調整",
"movement.type.rollback": "出貨失敗退回",
"Before Qty": "異動前數量",
"After Qty": "異動後數量",
"Delta": "變化量",
"No movements found": "尚無異動紀錄",
"Multilingual Names": "多語系名稱", "Multilingual Names": "多語系名稱",
"N/A": "不適用", "N/A": "不適用",
"Name": "名稱", "Name": "名稱",
@ -809,6 +911,7 @@
"No advertisements found.": "未找到廣告素材。", "No advertisements found.": "未找到廣告素材。",
"No alert summary": "暫無告警記錄", "No alert summary": "暫無告警記錄",
"No assignments": "尚未投放", "No assignments": "尚未投放",
"No associated order found": "無關聯訂單",
"No categories found.": "找不到分類。", "No categories found.": "找不到分類。",
"No command history": "尚無指令紀錄", "No command history": "尚無指令紀錄",
"No configurations found": "暫無相關配置", "No configurations found": "暫無相關配置",
@ -831,12 +934,15 @@
"No matching machines": "查無匹配機台", "No matching machines": "查無匹配機台",
"No materials available": "沒有可用的素材", "No materials available": "沒有可用的素材",
"No movement records found": "查無異動紀錄", "No movement records found": "查無異動紀錄",
"No movements found": "尚無異動紀錄",
"No pass codes found": "找不到通行碼", "No pass codes found": "找不到通行碼",
"No permissions": "無權限項目", "No permissions": "無權限項目",
"No pickup codes found": "找不到取貨碼", "No pickup codes found": "找不到取貨碼",
"No product record found": "無商品紀錄",
"No products found in this warehouse": "此倉庫目前無商品庫存", "No products found in this warehouse": "此倉庫目前無商品庫存",
"No products found matching your criteria.": "找不到符合條件的商品。", "No products found matching your criteria.": "找不到符合條件的商品。",
"No records found": "未找到相關紀錄", "No records found": "未找到相關紀錄",
"No related detail found": "無關聯詳細資料",
"No replenishment orders found": "查無補貨單紀錄", "No replenishment orders found": "查無補貨單紀錄",
"No results found": "查無搜尋結果", "No results found": "查無搜尋結果",
"No roles available": "目前沒有角色資料。", "No roles available": "目前沒有角色資料。",
@ -847,6 +953,7 @@
"No slots need replenishment": "無需補貨的貨道", "No slots need replenishment": "無需補貨的貨道",
"No stock data found": "查無庫存資料", "No stock data found": "查無庫存資料",
"No stock-in orders found": "查無進貨單紀錄", "No stock-in orders found": "查無進貨單紀錄",
"No transaction orders found": "查無交易訂單",
"No transfer orders found": "查無調撥單紀錄", "No transfer orders found": "查無調撥單紀錄",
"No users found": "找不到用戶資料", "No users found": "找不到用戶資料",
"No warehouses found": "未找到倉庫", "No warehouses found": "未找到倉庫",
@ -888,10 +995,14 @@
"Optional": "選填", "Optional": "選填",
"Optional remarks": "選填備註", "Optional remarks": "選填備註",
"Optional remarks...": "選填備註...", "Optional remarks...": "選填備註...",
"Order Details": "進貨單詳情", "Order Details": "單詳情",
"Order Info": "單據資訊", "Order Info": "單據資訊",
"Order Items": "商品內容",
"Order Management": "訂單管理", "Order Management": "訂單管理",
"Order No.": "單號", "Order No.": "單號",
"Order Number / Time": "訂單編號 / 時間",
"Order Status": "訂單狀態",
"Order Time": "訂單時間",
"Order already completed": "訂單已完成", "Order already completed": "訂單已完成",
"Order already processed": "訂單已處理", "Order already processed": "訂單已處理",
"Order completed and stock updated": "訂單已完成,機台庫存已更新", "Order completed and stock updated": "訂單已完成,機台庫存已更新",
@ -946,14 +1057,15 @@
"Pass Code QR": "通行碼 QR Code", "Pass Code QR": "通行碼 QR Code",
"Pass Code Ticket": "通行憑證", "Pass Code Ticket": "通行憑證",
"Pass Codes": "通行碼", "Pass Codes": "通行碼",
"Pass code cancelled.": "通行碼已取消。",
"Pass code created: :code": "通行碼已建立::code", "Pass code created: :code": "通行碼已建立::code",
"Pass code deleted.": "通行碼已刪除", "Pass code deleted.": "通行碼已刪除",
"Pass code cancelled.": "通行碼已取消。",
"Pass code disabled.": "通行碼已取消。", "Pass code disabled.": "通行碼已取消。",
"Pass code updated.": "通行碼已更新", "Pass code updated.": "通行碼已更新",
"Password": "密碼", "Password": "密碼",
"Password updated successfully.": "密碼已成功變更。", "Password updated successfully.": "密碼已成功變更。",
"Payment & Invoice": "金流與發票", "Payment & Invoice": "金流與發票",
"Payment Amount": "支付金額",
"Payment Buffer Seconds": "金流緩衝時間(s)", "Payment Buffer Seconds": "金流緩衝時間(s)",
"Payment Config": "金流配置", "Payment Config": "金流配置",
"Payment Configuration": "客戶金流設定", "Payment Configuration": "客戶金流設定",
@ -961,11 +1073,13 @@
"Payment Configuration deleted successfully.": "金流設定已成功刪除。", "Payment Configuration deleted successfully.": "金流設定已成功刪除。",
"Payment Configuration updated successfully.": "金流設定已成功更新。", "Payment Configuration updated successfully.": "金流設定已成功更新。",
"Payment Selection": "付款選擇", "Payment Selection": "付款選擇",
"Payment Type": "支付方式",
"Pending": "待處理", "Pending": "待處理",
"Per Page": "每頁顯示", "Per Page": "每頁顯示",
"Performance": "效能 (Performance)", "Performance": "效能 (Performance)",
"Permanent": "永久", "Permanent": "永久",
"Permanent Code": "永久代碼", "Permanent Code": "永久代碼",
"Permanent if empty": "留空則為永久有效",
"Permanently Delete Account": "永久刪除帳號", "Permanently Delete Account": "永久刪除帳號",
"Permission Settings": "權限設定", "Permission Settings": "權限設定",
"Permission Tags": "權限標籤", "Permission Tags": "權限標籤",
@ -977,9 +1091,9 @@
"Picked up": "領取", "Picked up": "領取",
"Picked up Time": "領取時間", "Picked up Time": "領取時間",
"Pickup Code": "取貨碼", "Pickup Code": "取貨碼",
"Pickup Code (8 Digits)": "取貨碼 (8 位數)",
"Pickup Codes": "取貨碼", "Pickup Codes": "取貨碼",
"Pickup Ticket": "取貨憑證", "Pickup Ticket": "取貨憑證",
"Pickup Code (8 Digits)": "取貨碼 (8 位數)",
"Pickup code cancelled.": "取貨碼已取消", "Pickup code cancelled.": "取貨碼已取消",
"Pickup code generated: :code": "已生成取貨碼::code", "Pickup code generated: :code": "已生成取貨碼::code",
"Pickup code updated.": "取貨碼已更新", "Pickup code updated.": "取貨碼已更新",
@ -1014,6 +1128,7 @@
"Previous": "上一頁", "Previous": "上一頁",
"Price / Member": "售價 / 會員價", "Price / Member": "售價 / 會員價",
"Pricing Information": "價格資訊", "Pricing Information": "價格資訊",
"Print Invoice": "列印發票",
"Product": "商品", "Product": "商品",
"Product / Slot": "商品 / 貨道", "Product / Slot": "商品 / 貨道",
"Product / Stock": "商品 / 庫存", "Product / Stock": "商品 / 庫存",
@ -1078,6 +1193,7 @@
"Recent Login": "最近登入", "Recent Login": "最近登入",
"Recently reported errors or warnings in logs": "近期日誌中有錯誤或警告回報", "Recently reported errors or warnings in logs": "近期日誌中有錯誤或警告回報",
"Records": "筆", "Records": "筆",
"Refunded": "已退款",
"Regenerate": "重新產生", "Regenerate": "重新產生",
"Regenerating the token will disconnect the physical machine until it is updated. Continue?": "重新產生金鑰將導致實體機台暫時失去連線,必須於機台端更新此新金鑰才能恢復。確定繼續嗎?", "Regenerating the token will disconnect the physical machine until it is updated. Continue?": "重新產生金鑰將導致實體機台暫時失去連線,必須於機台端更新此新金鑰才能恢復。確定繼續嗎?",
"Remote Change": "遠端找零", "Remote Change": "遠端找零",
@ -1089,8 +1205,8 @@
"Remote Permissions": "遠端管理權限", "Remote Permissions": "遠端管理權限",
"Remote Reboot": "遠端結帳", "Remote Reboot": "遠端結帳",
"Remote Settlement": "遠端結帳", "Remote Settlement": "遠端結帳",
"Remote dispense successful for slot :slot": "貨道 :slot 遠端出貨成功",
"Remote dispense failed for slot :slot": "貨道 :slot 遠端出貨失敗", "Remote dispense failed for slot :slot": "貨道 :slot 遠端出貨失敗",
"Remote dispense successful for slot :slot": "貨道 :slot 遠端出貨成功",
"Removal": "撤機", "Removal": "撤機",
"Repair": "維修", "Repair": "維修",
"Replenish": "補貨", "Replenish": "補貨",
@ -1168,9 +1284,12 @@
"Scan to pick up your product": "掃描以領取您的商品", "Scan to pick up your product": "掃描以領取您的商品",
"Schedule": "排程區間", "Schedule": "排程區間",
"Search Company Title...": "搜尋公司名稱...", "Search Company Title...": "搜尋公司名稱...",
"Search Flow ID / Slot...": "搜尋 流水號 / 貨道...",
"Search Invoice No / Flow ID...": "搜尋 發票號碼 / 流水號...",
"Search Machine...": "搜尋機台...", "Search Machine...": "搜尋機台...",
"Search logs...": "搜尋紀錄...", "Search Order No / Flow ID / Invoice...": "搜尋 訂單號 / 流水號 / 發票號碼...",
"Search Product": "搜尋商品", "Search Product": "搜尋商品",
"Search Product / Slot...": "搜尋商品名稱 / 貨道...",
"Search accounts...": "搜尋帳號...", "Search accounts...": "搜尋帳號...",
"Search by code, machine name or serial...": "搜尋代碼、機台名稱或序號...", "Search by code, machine name or serial...": "搜尋代碼、機台名稱或序號...",
"Search by code, name or machine...": "搜尋代碼、名稱或機台...", "Search by code, name or machine...": "搜尋代碼、名稱或機台...",
@ -1181,6 +1300,7 @@
"Search company...": "搜尋公司...", "Search company...": "搜尋公司...",
"Search configurations...": "搜尋設定...", "Search configurations...": "搜尋設定...",
"Search customers...": "搜尋客戶...", "Search customers...": "搜尋客戶...",
"Search logs...": "搜尋紀錄...",
"Search machines by name or serial...": "搜尋機台名稱或序號...", "Search machines by name or serial...": "搜尋機台名稱或序號...",
"Search machines...": "搜尋機台...", "Search machines...": "搜尋機台...",
"Search models...": "搜尋型號...", "Search models...": "搜尋型號...",
@ -1249,6 +1369,7 @@
"Sign in to your account": "隨時隨地掌控您的業務。", "Sign in to your account": "隨時隨地掌控您的業務。",
"Signed in as": "登入身份", "Signed in as": "登入身份",
"Slot": "貨道", "Slot": "貨道",
"Slot / Product": "貨道 / 商品",
"Slot Mechanism (default: Conveyor, check for Spring)": "貨道機制 (預設履帶,勾選為彈簧)", "Slot Mechanism (default: Conveyor, check for Spring)": "貨道機制 (預設履帶,勾選為彈簧)",
"Slot No": "貨道編號", "Slot No": "貨道編號",
"Slot Status": "貨道效期", "Slot Status": "貨道效期",
@ -1289,6 +1410,7 @@
"Start Time": "開始時間", "Start Time": "開始時間",
"Statistics": "數據統計", "Statistics": "數據統計",
"Status": "狀態", "Status": "狀態",
"Status / Invoice": "狀態 / 發票",
"Status / Temp / Sub / Card / Scan": "狀態 / 溫度 / 下位機 / 刷卡機 / 掃碼機", "Status / Temp / Sub / Card / Scan": "狀態 / 溫度 / 下位機 / 刷卡機 / 掃碼機",
"Status Timeline": "狀態時間線", "Status Timeline": "狀態時間線",
"Status updated successfully": "狀態更新成功", "Status updated successfully": "狀態更新成功",
@ -1302,6 +1424,7 @@
"Stock Level > 50%": "庫存高於 50%", "Stock Level > 50%": "庫存高於 50%",
"Stock Levels": "庫存水準", "Stock Levels": "庫存水準",
"Stock Management": "庫存管理單", "Stock Management": "庫存管理單",
"Stock Movement Log": "庫存流水帳",
"Stock Out": "庫存出庫", "Stock Out": "庫存出庫",
"Stock Quantity": "庫存數量", "Stock Quantity": "庫存數量",
"Stock Rate": "庫存率", "Stock Rate": "庫存率",
@ -1312,6 +1435,7 @@
"Stock returned to warehouse": "庫存已退回倉庫", "Stock returned to warehouse": "庫存已退回倉庫",
"Stock-In Management": "進貨管理", "Stock-In Management": "進貨管理",
"Stock-In Order": "新增進貨單", "Stock-In Order": "新增進貨單",
"Stock-In Order Details": "進貨單詳情",
"Stock-In Orders": "進貨單管理", "Stock-In Orders": "進貨單管理",
"Stock-In Orders Tab": "進貨單管理", "Stock-In Orders Tab": "進貨單管理",
"Stock-in order": "入庫單", "Stock-in order": "入庫單",
@ -1331,7 +1455,8 @@
"Sub-actions": "子項目", "Sub-actions": "子項目",
"Sub-machine Status Request": "下位機狀態回傳", "Sub-machine Status Request": "下位機狀態回傳",
"Submit Record": "提交紀錄", "Submit Record": "提交紀錄",
"Success": "執行成功", "Subtotal": "小計",
"Success": "成功",
"Super Admin": "超級管理員", "Super Admin": "超級管理員",
"Super-admin role cannot be assigned to tenant accounts.": "超級管理員角色無法指派給客戶帳號。", "Super-admin role cannot be assigned to tenant accounts.": "超級管理員角色無法指派給客戶帳號。",
"Superseded": "已取代", "Superseded": "已取代",
@ -1414,6 +1539,9 @@
"Track stock levels, stock-in orders, and movement history": "追蹤庫存水位、進貨單與異動紀錄", "Track stock levels, stock-in orders, and movement history": "追蹤庫存水位、進貨單與異動紀錄",
"Track stock-in orders and movement history": "追蹤進貨單據與庫存異動紀錄", "Track stock-in orders and movement history": "追蹤進貨單據與庫存異動紀錄",
"Traditional Chinese": "繁體中文", "Traditional Chinese": "繁體中文",
"Transaction Info": "交易資訊",
"Transaction Orders": "交易訂單",
"Transaction Time": "交易時間",
"Transaction processed: :id": "交易處理完成::id", "Transaction processed: :id": "交易處理完成::id",
"Transfer Audit": "調撥單", "Transfer Audit": "調撥單",
"Transfer Details": "調撥單詳情", "Transfer Details": "調撥單詳情",
@ -1455,16 +1583,10 @@
"Unlock Now": "立即解鎖", "Unlock Now": "立即解鎖",
"Unlock Page": "頁面解鎖", "Unlock Page": "頁面解鎖",
"Unpublish": "下架", "Unpublish": "下架",
"cancel": "取消",
"create": "建立",
"update": "更新",
"used": "已使用",
"Update": "更新", "Update": "更新",
"Edit Pass Code": "編輯通行碼",
"Permanent if empty": "留空則為永久有效",
"Update Pass Code": "更新通行碼",
"Update Authorization": "更新授權", "Update Authorization": "更新授權",
"Update Customer": "更新客戶", "Update Customer": "更新客戶",
"Update Pass Code": "更新通行碼",
"Update Password": "更改密碼", "Update Password": "更改密碼",
"Update Product": "更新商品", "Update Product": "更新商品",
"Update Settings": "更新設定", "Update Settings": "更新設定",
@ -1492,21 +1614,25 @@
"Validity Period": "有效期限", "Validity Period": "有效期限",
"Validity Period (Days)": "有效期限 (天)", "Validity Period (Days)": "有效期限 (天)",
"Validity Period (Hours)": "有效期限 (小時)", "Validity Period (Hours)": "有效期限 (小時)",
"Valid": "有效",
"Void": "作廢",
"Vending": "販賣頁", "Vending": "販賣頁",
"Vending Page": "販賣頁", "Vending Page": "販賣頁",
"Venue Management": "場地管理", "Venue Management": "場地管理",
"Video": "影片", "Video": "影片",
"View Details": "查看細單", "View Details": "查看詳情",
"View Full History": "查看完整歷程", "View Full History": "查看完整歷程",
"View Inventory": "查看庫存", "View Inventory": "查看庫存",
"View Logs": "查看日誌", "View Logs": "查看日誌",
"View More": "查看更多", "View More": "查看更多",
"View Order": "查看訂單",
"View QR Code": "查看 QR Code", "View QR Code": "查看 QR Code",
"View Slots": "查看貨道", "View Slots": "查看貨道",
"View all warehouses": "查看所有倉庫", "View all warehouses": "查看所有倉庫",
"View slot-level inventory for each machine": "查看各機台貨道庫存", "View slot-level inventory for each machine": "查看各機台貨道庫存",
"Visit Gift": "來店禮", "Visit Gift": "來店禮",
"Visual overview of all machine locations": "所有機台位置的視覺化概覽", "Visual overview of all machine locations": "所有機台位置的視覺化概覽",
"Void Invoice": "作廢發票",
"Waiting": "等待中", "Waiting": "等待中",
"Waiting for Payment": "等待付款", "Waiting for Payment": "等待付款",
"Warehouse": "倉庫", "Warehouse": "倉庫",
@ -1557,13 +1683,26 @@
"accounts": "帳號管理", "accounts": "帳號管理",
"admin": "管理員", "admin": "管理員",
"analysis": "分析管理", "analysis": "分析管理",
"and :count other items": "等 :count 項商品",
"app": "APP 管理", "app": "APP 管理",
"audit": "稽核管理", "audit": "稽核管理",
"basic-settings": "基本設定", "basic-settings": "基本設定",
"basic.machines": "機台設定", "basic.machines": "機台設定",
"basic.payment-configs": "客戶金流設定", "basic.payment-configs": "客戶金流設定",
"by": "由", "by": "由",
"cancel": "取消",
"command.change": "找零",
"command.checkout": "結帳",
"command.dispense": "出貨",
"command.lock": "鎖機",
"command.reboot": "重啟",
"command.reboot_card": "讀卡機重啟",
"command.reload_stock": "同步庫存",
"command.unlock": "解鎖",
"companies": "客戶管理", "companies": "客戶管理",
"consume": "取貨成功",
"consume_failed": "取貨失敗",
"create": "建立",
"data-config": "資料設定", "data-config": "資料設定",
"data-config.sub-account-roles": "子帳號角色", "data-config.sub-account-roles": "子帳號角色",
"data-config.sub-accounts": "子帳號管理", "data-config.sub-accounts": "子帳號管理",
@ -1588,6 +1727,15 @@
"items": "筆項目", "items": "筆項目",
"john@example.com": "john@example.com", "john@example.com": "john@example.com",
"line": "Line 管理", "line": "Line 管理",
"log.command.failed": "遠端指令 [:type] 執行失敗",
"log.command.success": "遠端指令 [:type] 執行成功",
"log.passcode.verify_success_note": "維修人員於機台 [:machine_sn] 驗證通行碼 [:code]",
"log.pickup.consume_success": "[取貨碼] 核銷成功::code貨道:slot",
"log.pickup.consume_success_note": "機台 [:machine_sn] 已核銷取貨碼。貨道 :slot:old -> :new",
"log.pickup.dispense_failed": "[取貨碼] 機台回報出貨失敗::code",
"log.pickup.dispense_failed_note": "機台 [:machine_sn] 回報取貨碼 [:code] 出貨失敗",
"log.pickup.verify_success": "[取貨碼] 驗證成功,碼::code",
"log.pickup.verify_success_note": "機台 [:machine_sn] 已驗證取貨碼 [:code]",
"machines": "機台管理", "machines": "機台管理",
"members": "會員管理", "members": "會員管理",
"menu.analysis": "數據分析", "menu.analysis": "數據分析",
@ -1638,6 +1786,13 @@
"menu.warehouses.transfers": "調撥單", "menu.warehouses.transfers": "調撥單",
"min": "分", "min": "分",
"mins ago": "分鐘前", "mins ago": "分鐘前",
"movement.note.manual_adjustment": "後台手動修改貨道庫存(舊: :old → 新: :new",
"movement.note.replenishment_correction": "B009 盤點回報修正(舊: :old → 新: :new",
"movement.type.adjustment": "盤點調整",
"movement.type.pickup": "取貨碼消耗",
"movement.type.remote_dispense": "遠端出貨",
"movement.type.replenishment": "補貨入庫",
"movement.type.rollback": "出貨失敗退回",
"of": "/共", "of": "/共",
"of items": "筆項目", "of items": "筆項目",
"pending": "等待機台領取", "pending": "等待機台領取",
@ -1657,38 +1812,14 @@
"success": "成功", "success": "成功",
"super-admin": "超級管理員", "super-admin": "超級管理員",
"to": "至", "to": "至",
"update": "更新",
"used": "已使用",
"user": "一般用戶", "user": "一般用戶",
"vending": "販賣頁", "vending": "販賣頁",
"verify_success": "驗證成功",
"video": "影片", "video": "影片",
"visit_gift": "來店禮", "visit_gift": "來店禮",
"vs Yesterday": "較昨日", "vs Yesterday": "較昨日",
"warehouses": "倉庫管理", "warehouses": "倉庫管理",
"待填寫": "待填寫", "待填寫": "待填寫"
"verify_success": "驗證成功", }
"consume": "取貨成功",
"consume_failed": "取貨失敗",
"All Slots": "所有貨道",
"log.pickup.verify_success": "[取貨碼] 驗證成功,碼::code",
"log.pickup.verify_success_note": "機台 [:machine_sn] 已驗證取貨碼 [:code]",
"log.pickup.consume_success": "[取貨碼] 核銷成功::code貨道:slot",
"log.pickup.consume_success_note": "機台 [:machine_sn] 已核銷取貨碼。貨道 :slot:old -> :new",
"log.pickup.dispense_failed": "[取貨碼] 機台回報出貨失敗::code",
"log.pickup.dispense_failed_note": "機台 [:machine_sn] 回報取貨碼 [:code] 出貨失敗",
"log.passcode.verify_success_note": "維修人員於機台 [:machine_sn] 驗證通行碼 [:code]",
"movement.note.manual_adjustment": "後台手動修改貨道庫存(舊: :old → 新: :new",
"movement.note.replenishment_correction": "B009 盤點回報修正(舊: :old → 新: :new",
"log.command.success": "遠端指令 [:type] 執行成功",
"log.command.failed": "遠端指令 [:type] 執行失敗",
"command.reboot": "重啟",
"command.reboot_card": "讀卡機重啟",
"command.lock": "鎖機",
"command.unlock": "解鎖",
"command.checkout": "結帳",
"command.change": "找零",
"command.dispense": "出貨",
"command.reload_stock": "同步庫存",
"Clear Abnormal Status": "清除異常狀態",
"Are you sure you want to resolve all recent issues for this machine?": "您確定要排除此機台目前所有的異常紀錄嗎?這將會恢復機台狀態為正常。",
"All issues marked as resolved.": "所有異常已標記為已排除。",
"Failed to resolve issues.": "排除異常失敗。"
}

View File

@ -0,0 +1,203 @@
@extends('layouts.admin')
@section('content')
<div class="space-y-2 pb-20" x-data="salesCenter()"
@ajax:navigate.window.prevent="fetchTabData(activeTab, $event.detail.url)">
{{-- Page Header --}}
<x-page-header :title="$title" :subtitle="$description" />
{{-- Tab Navigation --}}
<x-tab-nav model="activeTab">
<x-tab-nav-item value="orders" :label="__('Transaction Orders')" model="activeTab" />
<x-tab-nav-item value="invoices" :label="__('Electronic Invoices')" model="activeTab" />
<x-tab-nav-item value="dispense" :label="__('Dispense Records')" model="activeTab" />
</x-tab-nav>
{{-- Tab Contents --}}
<div class="mt-6">
<div class="relative min-h-[400px]">
{{-- Orders Tab --}}
<div x-show="activeTab === 'orders'" class="relative"
x-transition:enter="transition ease-out duration-300" x-transition:enter-start="opacity-0 translate-y-4"
x-transition:enter-end="opacity-100 translate-y-0">
<div class="luxury-card rounded-3xl p-8 relative overflow-hidden">
<x-luxury-spinner show="tabLoading === 'orders'" />
<div id="tab-orders-container" :class="{ 'opacity-30 pointer-events-none transition-opacity duration-300': tabLoading === 'orders' }">
@include('admin.sales.partials.tab-orders')
</div>
</div>
</div>
{{-- Invoices Tab --}}
<div x-show="activeTab === 'invoices'" class="relative"
x-transition:enter="transition ease-out duration-300" x-transition:enter-start="opacity-0 translate-y-4"
x-transition:enter-end="opacity-100 translate-y-0" x-cloak>
<div class="luxury-card rounded-3xl p-8 relative overflow-hidden">
<x-luxury-spinner show="tabLoading === 'invoices'" />
<div id="tab-invoices-container" :class="{ 'opacity-30 pointer-events-none transition-opacity duration-300': tabLoading === 'invoices' }">
@include('admin.sales.partials.tab-invoices')
</div>
</div>
</div>
{{-- Dispense Records Tab --}}
<div x-show="activeTab === 'dispense'" class="relative"
x-transition:enter="transition ease-out duration-300" x-transition:enter-start="opacity-0 translate-y-4"
x-transition:enter-end="opacity-100 translate-y-0" x-cloak>
<div class="luxury-card rounded-3xl p-8 relative overflow-hidden">
<x-luxury-spinner show="tabLoading === 'dispense'" />
<div id="tab-dispense-container" :class="{ 'opacity-30 pointer-events-none transition-opacity duration-300': tabLoading === 'dispense' }">
@include('admin.sales.partials.tab-dispense')
</div>
</div>
</div>
</div>
</div>
{{-- Slide-over Panel (Order Details) --}}
<div
class="fixed inset-0 z-[100] overflow-hidden"
x-show="showPanel"
x-cloak
@keydown.window.escape="showPanel = false"
>
<div class="absolute inset-0 bg-slate-900/60 backdrop-blur-sm transition-opacity"
x-show="showPanel"
x-transition:enter="ease-out duration-500"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="ease-in duration-500"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
@click="showPanel = false"
></div>
<div class="pointer-events-none fixed inset-y-0 right-0 flex max-w-full pl-10">
<div
class="pointer-events-auto w-screen max-w-2xl transform transition ease-in-out duration-500 sm:duration-700"
x-show="showPanel"
x-transition:enter="transform transition ease-in-out duration-500 sm:duration-700"
x-transition:enter-start="translate-x-full"
x-transition:enter-end="translate-x-0"
x-transition:leave="transform transition ease-in-out duration-500 sm:duration-700"
x-transition:leave-start="translate-x-0"
x-transition:leave-end="translate-x-full"
>
<div class="flex h-full flex-col overflow-y-scroll bg-white dark:bg-slate-900 shadow-2xl border-l border-slate-100 dark:border-slate-800">
<div id="order-detail-content">
{{-- AJAX injected content --}}
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
@section('scripts')
<script>
function salesCenter() {
return {
showPanel: false,
activeTab: '{{ $tab }}',
tabLoading: null,
init() {
const params = new URLSearchParams(window.location.search);
const urlTab = params.get('tab');
if (urlTab && ['orders', 'invoices', 'dispense'].includes(urlTab)) {
this.activeTab = urlTab;
}
// 監聽頁籤切換以更新網址列 (不觸發重整)
this.$watch('activeTab', (newTab) => {
const url = new URL(window.location.origin + window.location.pathname);
url.searchParams.set('tab', newTab);
window.history.pushState({}, '', url);
});
},
switchTab(tab, url = null) {
if (this.activeTab === tab && !url) return;
this.activeTab = tab;
// 如果有提供 URL (例如點擊跳轉),則使用 AJAX 載入新內容
if (url) {
this.fetchTabData(tab, url);
return;
}
},
async fetchTabData(tab, url = null) {
if (this.tabLoading === tab) return;
this.tabLoading = tab;
const container = document.getElementById('tab-' + tab + '-container');
if (!url) {
// 從表單建構 URL
let params = new URLSearchParams();
params.set('tab', tab);
if (container) {
const form = container.querySelector('form');
if (form) {
const formData = new FormData(form);
formData.forEach((value, key) => {
if (value && value.trim() !== '') params.append(key, value);
});
}
}
url = `${window.location.pathname}?${params.toString()}`;
}
try {
const response = await fetch(url, {
headers: {
'X-Requested-With': 'XMLHttpRequest',
'Accept': 'application/json'
}
});
const data = await response.json();
if (data.success && data.html) {
if (container) container.innerHTML = data.html;
// 更新網址列但不重整頁面
window.history.pushState({}, '', url);
// 重新初始化 Preline 組件
this.$nextTick(() => {
if (window.HSStaticMethods) window.HSStaticMethods.autoInit();
});
}
} catch (err) {
console.error('Failed to fetch tab data:', err);
} finally {
this.tabLoading = null;
}
},
openDetail(orderId) {
this.showPanel = true;
document.getElementById('order-detail-content').innerHTML = `<div class="flex items-center justify-center h-full py-20"><x-luxury-spinner show="true" /></div>`;
fetch(`/admin/sales/${orderId}`, {
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(res => res.json())
.then(data => {
if (data.success) {
document.getElementById('order-detail-content').innerHTML = data.html;
}
})
.catch(err => {
console.error('Failed to load order detail:', err);
this.showPanel = false;
});
}
}
}
</script>
@endsection

View File

@ -0,0 +1,244 @@
{{-- 側滑面板標題 --}}
<div class="px-5 py-6 sm:px-8 border-b border-slate-200 dark:border-slate-800 bg-slate-50/50 dark:bg-slate-900/50">
<div class="flex items-start justify-between gap-4">
<div class="min-w-0 flex-1">
<h2 class="text-xl sm:text-2xl font-black text-slate-800 dark:text-white font-display flex items-center gap-2 sm:gap-3">
<div class="p-2 bg-cyan-500/10 rounded-xl">
<svg class="w-5 h-5 sm:w-6 sm:h-6 text-cyan-500 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
</div>
<span class="truncate">{{ __('Order Details') }}</span>
</h2>
<div class="mt-2 flex items-center gap-2 text-sm text-slate-500 dark:text-slate-400 font-bold uppercase tracking-widest">
<span class="text-cyan-600 dark:text-cyan-400 font-mono tracking-tighter text-lg">{{ $order->order_no }}</span>
</div>
</div>
<button type="button" @click="showPanel = false"
class="bg-white dark:bg-slate-800 rounded-full p-2 text-slate-400 hover:text-slate-500 hover:bg-slate-100 dark:hover:bg-slate-700 focus:outline-none transition duration-300 shadow-sm border border-slate-200 dark:border-slate-700">
<svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
</div>
<div class="flex-1 overflow-y-auto p-6 sm:p-8 space-y-10">
{{-- 基本狀態卡片 --}}
<div class="grid grid-cols-2 gap-6 p-6 bg-slate-50/50 dark:bg-slate-800/30 rounded-[2rem] border border-slate-100 dark:border-slate-800">
<div class="space-y-2">
<p class="text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-widest">{{ __('Order Status') }}</p>
<div>
@php
$statusMap = [
'pending' => 'pending',
'paid' => 'active',
'completed' => 'active',
'cancelled' => 'disabled',
'refunded' => 'error',
];
$labelMap = [
'pending' => __('Pending'),
'paid' => __('Paid'),
'completed' => __('Completed'),
'cancelled' => __('Cancelled'),
'refunded' => __('Refunded'),
];
$status = $statusMap[$order->status] ?? 'slate';
$label = $labelMap[$order->status] ?? $order->status;
@endphp
<x-status-badge :status="$status" :label="$label" size="sm" />
</div>
</div>
<div class="space-y-2">
<p class="text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-widest">{{ __('Payment Type') }}</p>
<p class="text-sm font-extrabold text-slate-700 dark:text-slate-200">
{{ $paymentTypes[$order->payment_type] ?? __('Unknown') }}
</p>
</div>
</div>
{{-- 交易資訊 --}}
<section class="space-y-4">
<div class="flex items-center gap-2 px-1">
<div class="w-1.5 h-4 bg-cyan-500 rounded-full"></div>
<h3 class="text-sm font-black text-slate-800 dark:text-white uppercase tracking-widest">{{ __('Transaction Info') }}</h3>
</div>
<div class="grid grid-cols-2 gap-8 p-8 bg-slate-50/50 dark:bg-slate-800/30 rounded-[2rem] border border-slate-100 dark:border-slate-800">
<div class="space-y-1">
<p class="text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-widest">{{ __('Transaction Time') }}</p>
<p class="text-sm font-bold text-slate-700 dark:text-slate-300 font-mono tracking-tight">{{ $order->created_at->format('Y-m-d H:i:s') }}</p>
</div>
<div class="space-y-1">
<p class="text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-widest">{{ __('Machine Name') }}</p>
<p class="text-sm font-extrabold text-slate-700 dark:text-slate-200">{{ $order->machine->name ?? __('Unknown') }}</p>
</div>
<div class="space-y-1">
<p class="text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-widest">{{ __('Machine Serial') }}</p>
<p class="text-xs font-black text-slate-400 dark:text-slate-500 font-mono uppercase tracking-widest">{{ $order->machine->serial_no ?? '---' }}</p>
</div>
<div class="space-y-1">
<p class="text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-widest">{{ __('Machine Flow ID') }}</p>
<p class="text-xs font-black text-slate-400 dark:text-slate-500 font-mono uppercase tracking-widest">{{ $order->flow_id }}</p>
</div>
</div>
</section>
{{-- 商品明細 --}}
<section class="space-y-4">
<div class="flex items-center justify-between px-1">
<div class="flex items-center gap-2">
<div class="w-1.5 h-4 bg-cyan-500 rounded-full"></div>
<h3 class="text-sm font-black text-slate-800 dark:text-white uppercase tracking-widest">{{ __('Product Details') }}</h3>
</div>
<span class="text-[10px] font-black text-cyan-500 bg-cyan-500/10 px-2 py-0.5 rounded-md uppercase tracking-widest">{{ $order->items->count() }} {{ __('Items') }}</span>
</div>
<div class="space-y-3">
@foreach($order->items as $item)
<div class="luxury-card p-4 rounded-2xl flex items-center gap-4 group/item transition-all hover:border-cyan-500/30">
<div class="w-16 h-16 rounded-xl bg-slate-100 dark:bg-slate-800 flex-shrink-0 overflow-hidden border border-slate-200 dark:border-slate-700 group-hover:scale-105 transition-transform flex items-center justify-center">
@if(isset($item->product->image_url) && $item->product->image_url)
<img src="{{ $item->product->image_url }}" class="w-full h-full object-cover">
@else
<svg class="w-8 h-8 text-slate-300 group-hover:text-cyan-500 transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4"/>
</svg>
@endif
</div>
<div class="flex-1 min-w-0">
<p class="text-base font-extrabold text-slate-800 dark:text-white truncate tracking-tight">{{ $item->product_name }}</p>
<div class="flex items-center gap-3 mt-1">
<span class="text-[10px] font-black text-slate-400 uppercase tracking-widest">${{ number_format($item->price, 0) }} × {{ $item->quantity }}</span>
</div>
</div>
<div class="text-right">
<p class="text-base font-black text-slate-800 dark:text-white tracking-tight">${{ number_format($item->subtotal, 0) }}</p>
</div>
</div>
@endforeach
</div>
{{-- 金額彙總 --}}
<div class="mt-6 p-8 rounded-[2rem] bg-slate-50/50 dark:bg-slate-800/30 border border-slate-100 dark:border-slate-800 relative overflow-hidden group">
<!-- Decorative Gradient -->
<div class="absolute top-0 right-0 w-32 h-32 bg-cyan-500/10 blur-[50px] -mr-16 -mt-16 group-hover:bg-cyan-500/20 transition-colors duration-500"></div>
<div class="relative space-y-4">
<div class="flex justify-between items-center text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-[0.2em]">
<span>{{ __('Subtotal') }}</span>
<span class="font-mono text-slate-600 dark:text-slate-300">${{ number_format($order->total_amount + $order->discount_amount, 0) }}</span>
</div>
<div class="flex justify-between items-center text-[10px] font-black text-rose-500 uppercase tracking-[0.2em]">
<span>{{ __('Discount') }}</span>
<span class="font-mono">-${{ number_format($order->discount_amount, 0) }}</span>
</div>
<div class="pt-4 mt-2 border-t border-slate-100 dark:border-slate-800/50 flex justify-between items-baseline">
<span class="text-sm font-black uppercase tracking-[0.2em] text-slate-500 dark:text-slate-400">{{ __('Total') }}</span>
<div class="text-right">
<span class="text-3xl font-black text-cyan-600 dark:text-cyan-400 tracking-tighter font-display">${{ number_format($order->total_amount, 0) }}</span>
</div>
</div>
</div>
</div>
</section>
{{-- 出貨紀錄 --}}
@if($order->dispenseRecords->count() > 0)
<section class="space-y-4">
<div class="flex items-center justify-between px-1">
<div class="flex items-center gap-2">
<div class="w-1.5 h-4 bg-emerald-500 rounded-full"></div>
<h3 class="text-sm font-black text-slate-800 dark:text-white uppercase tracking-widest">{{ __('Dispense Status') }}</h3>
</div>
</div>
<div class="bg-white dark:bg-slate-900 border border-slate-100 dark:border-slate-800 rounded-[2rem] overflow-hidden shadow-sm">
<table class="w-full text-left border-separate border-spacing-y-0">
<thead>
<tr class="bg-slate-50/50 dark:bg-slate-900/10">
<th class="px-6 py-4 text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-[0.2em] border-b border-slate-100 dark:border-slate-800">{{ __('Slot') }}</th>
<th class="px-6 py-4 text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-[0.2em] border-b border-slate-100 dark:border-slate-800">{{ __('Product') }}</th>
<th class="px-6 py-4 text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-[0.2em] border-b border-slate-100 dark:border-slate-800 text-right">{{ __('Status') }}</th>
</tr>
</thead>
<tbody class="divide-y divide-slate-50 dark:divide-slate-800/80">
@foreach($order->dispenseRecords as $dispense)
<tr class="group hover:bg-slate-50/50 dark:hover:bg-white/[0.02] transition-colors duration-200">
<td class="px-6 py-4">
<span class="text-xs font-black text-cyan-600 dark:text-cyan-400 font-mono">#{{ str_pad($dispense->slot_no, 2, '0', STR_PAD_LEFT) }}</span>
</td>
<td class="px-6 py-4">
<p class="text-sm font-bold text-slate-700 dark:text-slate-200">{{ $dispense->product->name ?? __('Unknown') }}</p>
</td>
<td class="px-6 py-4 text-right">
@php
$dStatusMap = [
'success' => 'active',
'failed' => 'error',
'pending' => 'pending',
'1' => 'active',
'0' => 'error',
];
$dLabelMap = [
'success' => __('Success'),
'failed' => __('Failed'),
'pending' => __('Pending'),
'1' => __('Success'),
'0' => __('Failed'),
];
$statusValue = (string)($dispense->dispense_status ?? 'pending');
$ds = $dStatusMap[$statusValue] ?? 'slate';
$dl = $dLabelMap[$statusValue] ?? $statusValue;
@endphp
<x-status-badge :status="$ds" :label="$dl" size="xs" />
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</section>
@endif
{{-- 發票資訊 --}}
@if($order->invoice)
<section class="space-y-4">
<div class="flex items-center gap-2 px-1">
<div class="w-1.5 h-4 bg-indigo-500 rounded-full"></div>
<h3 class="text-sm font-black text-slate-800 dark:text-white uppercase tracking-widest">{{ __('Invoice Information') }}</h3>
</div>
<div class="bg-indigo-50/30 dark:bg-indigo-500/5 border border-indigo-100 dark:border-indigo-500/20 rounded-[2rem] p-8 group relative overflow-hidden">
<!-- Decorative Accent -->
<div class="absolute top-0 right-0 p-8 opacity-10 group-hover:opacity-20 transition-opacity duration-500">
<svg class="w-24 h-24 text-indigo-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
</div>
<div class="relative flex flex-col sm:flex-row sm:items-center justify-between gap-6">
<div class="space-y-3">
<div class="flex items-center gap-3">
<p class="text-xl font-black text-slate-800 dark:text-white font-mono tracking-tighter">{{ $order->invoice->invoice_no }}</p>
<x-status-badge status="active" :label="__('Valid')" size="xs" />
</div>
<div class="flex flex-col gap-1">
<p class="text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-widest">{{ __('Issued At') }}</p>
<p class="text-sm font-bold text-slate-600 dark:text-slate-400 font-mono tracking-tight">
{{ $order->invoice->invoice_date }} {{ $order->invoice->invoice_time }}
</p>
</div>
</div>
<div class="flex items-center gap-3">
<button class="flex-1 sm:flex-none px-6 py-3 rounded-xl bg-white dark:bg-slate-800 text-slate-600 dark:text-slate-300 font-bold text-xs border border-slate-200 dark:border-slate-700 hover:bg-indigo-500 hover:text-white hover:border-indigo-500 transition-all duration-300 shadow-sm">
{{ __('Print Invoice') }}
</button>
<button class="flex-1 sm:flex-none px-6 py-3 rounded-xl bg-white dark:bg-slate-800 text-slate-600 dark:text-slate-300 font-bold text-xs border border-slate-200 dark:border-slate-700 hover:bg-rose-500 hover:text-white hover:border-rose-500 transition-all duration-300 shadow-sm">
{{ __('Void Invoice') }}
</button>
</div>
</div>
</div>
</section>
@endif
</div>

View File

@ -0,0 +1,274 @@
{{-- Search Bar --}}
<form action="{{ route('admin.sales.index') }}" method="GET"
class="flex flex-col lg:flex-row lg:items-center flex-wrap gap-3 mb-8"
@submit.prevent="fetchTabData('dispense')">
<input type="hidden" name="tab" value="dispense">
<div class="relative group flex-1 min-w-[280px]">
<span class="absolute inset-y-0 left-0 flex items-center pl-4 pointer-events-none z-10">
<svg class="w-4 h-4 text-slate-400 group-focus-within:text-cyan-500 transition-colors stroke-[2.5]"
viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
</span>
<input type="text" name="search" value="{{ $filters['search'] }}"
class="py-2.5 pl-12 pr-6 block w-full luxury-input"
placeholder="{{ __('Search Product / Slot...') }}">
</div>
<div class="w-full lg:w-48">
<x-searchable-select name="machine_id" :placeholder="__('All Machines')" :selected="$filters['machine_id']"
@change="$el.closest('form').dispatchEvent(new Event('submit'))">
@foreach($machines as $m)
<option value="{{ $m->id }}" {{ $filters['machine_id'] == $m->id ? 'selected' : '' }} data-title="{{ $m->name }}">
{{ $m->name }}
</option>
@endforeach
</x-searchable-select>
</div>
{{-- 日期範圍 --}}
<div class="relative group w-full lg:w-72 lg:flex-none"
x-data="{ fp: null }"
x-init="fp = flatpickr($refs.dateRange, {
mode: 'range',
dateFormat: 'Y-m-d H:i',
enableTime: true,
time_24hr: true,
defaultHour: 0,
defaultMinute: 0,
locale: '{{ app()->getLocale() == 'zh_TW' ? 'zh_tw' : 'en' }}',
defaultDate: '{{ $filters['start_date'] }}' && '{{ $filters['end_date'] }}' ? ['{{ $filters['start_date'] }}', '{{ $filters['end_date'] }}'] : [],
onChange: function(selectedDates, dateStr, instance) {
if (selectedDates.length === 2) {
$refs.startDate.value = instance.formatDate(selectedDates[0], 'Y-m-d H:i');
$refs.endDate.value = instance.formatDate(selectedDates[1], 'Y-m-d H:i');
$el.closest('form').dispatchEvent(new Event('submit'));
} else if (selectedDates.length === 0) {
$refs.startDate.value = '';
$refs.endDate.value = '';
$el.closest('form').dispatchEvent(new Event('submit'));
}
}
})">
<span class="absolute inset-y-0 left-0 flex items-center pl-4 pointer-events-none z-10 text-slate-400 group-focus-within:text-cyan-500 transition-colors">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" /></svg>
</span>
<input type="hidden" name="start_date" x-ref="startDate" value="{{ $filters['start_date'] }}">
<input type="hidden" name="end_date" x-ref="endDate" value="{{ $filters['end_date'] }}">
<input type="text" x-ref="dateRange"
value="{{ $filters['start_date'] && $filters['end_date'] ? $filters['start_date'] . ' 至 ' . $filters['end_date'] : ($filters['start_date'] ?: '') }}"
placeholder="{{ __('Select Date Range') }}" class="luxury-input py-2.5 pl-12 pr-6 block w-full text-sm font-bold cursor-pointer">
</div>
<div class="flex items-center gap-2 ml-auto lg:ml-0 shrink-0">
<button type="submit"
class="p-2.5 rounded-xl bg-cyan-500 text-white hover:bg-cyan-600 shadow-lg shadow-cyan-500/25 transition-all active:scale-95"
title="{{ __('Search') }}">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"
stroke-width="2.5">
<path stroke-linecap="round" stroke-linejoin="round"
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
</button>
<button type="button"
@click="switchTab('dispense', '{{ route('admin.sales.index', ['tab' => 'dispense']) }}')"
class="p-2.5 rounded-xl bg-slate-100 dark:bg-slate-800 text-slate-500 dark:text-slate-400 hover:bg-slate-200 dark:hover:bg-slate-700 transition-all active:scale-95 border border-slate-200 dark:border-slate-700"
title="{{ __('Reset') }}">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"
stroke-width="2.5">
<path stroke-linecap="round" stroke-linejoin="round"
d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
</svg>
</button>
</div>
</form>
{{-- Table (Desktop) --}}
<div class="hidden xl:block overflow-x-auto">
<table class="w-full text-left border-separate border-spacing-0">
<thead>
<tr class="bg-slate-50/50 dark:bg-slate-900/10">
<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">
{{ __('Machine') }}
</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">
{{ __('Product / Slot') }}
</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">
{{ __('Amount') }}
</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">
{{ __('Dispense Status') }}
</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">
{{ __('Dispense Time') }}
</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">
{{ __('Associated Order') }}
</th>
</tr>
</thead>
<tbody class="divide-y divide-slate-100 dark:divide-slate-800/80">
@forelse($dispenseLogs as $log)
<tr class="group hover:bg-slate-50/50 dark:hover:bg-white/[0.02] transition-colors duration-200 {{ $log->order_id ? 'cursor-pointer' : '' }}" @click="if({{ $log->order_id ?? 'null' }}) openDetail({{ $log->order_id }})">
<td class="px-6 py-6">
<div class="text-sm font-extrabold text-slate-800 dark:text-slate-100 tracking-tight">
{{ $log->machine->name ?? 'Unknown' }}
</div>
<div class="text-[10px] font-bold text-slate-400 uppercase tracking-[0.2em] mt-1">
{{ $log->machine->serial_no ?? '---' }}
</div>
</td>
<td class="px-6 py-6">
<div class="text-sm font-black text-cyan-600 dark:text-cyan-400 mb-0.5">
{{ $log->product->name ?? 'Unknown Product' }}
</div>
<div class="text-xs font-bold text-slate-400 uppercase tracking-widest">
{{ __('Slot') }}: {{ $log->slot_no }}
</div>
</td>
<td class="px-6 py-6">
<span class="text-sm font-black text-slate-700 dark:text-slate-200">
{{ $log->amount }}
</span>
</td>
<td class="px-6 py-6 whitespace-nowrap">
@php
$statusMap = [
'success' => ['label' => __('Dispense Success'), 'color' => 'emerald'],
'failed' => ['label' => __('Dispense Failed'), 'color' => 'rose'],
'pending' => ['label' => __('Dispense Pending'), 'color' => 'amber'],
'1' => ['label' => __('Dispense Success'), 'color' => 'emerald'],
'0' => ['label' => __('Dispense Failed'), 'color' => 'rose'],
];
$statusKey = (string)($log->dispense_status ?? 'pending');
$s = $statusMap[$statusKey] ?? ['label' => $statusKey, 'color' => 'slate'];
@endphp
<x-status-badge :color="$s['color']" :label="$s['label']" size="xs" />
</td>
<td class="px-6 py-6">
<span class="text-sm font-black text-slate-700 dark:text-slate-200">
{{ $log->machine_time }}
</span>
</td>
<td class="px-6 py-6 text-right">
@if($log->order)
<button
@click.stop="openDetail({{ $log->order_id }})"
class="text-sm font-black text-slate-600 dark:text-slate-400 bg-slate-50 dark:bg-slate-800 px-3 py-1.5 rounded-lg border border-slate-100 dark:border-slate-700 hover:text-cyan-500 transition-all"
>
{{ $log->order->order_no }}
</button>
@else
<span class="text-xs text-slate-300 italic">{{ __('No associated order found') }}</span>
@endif
</td>
</tr>
@empty
<tr>
<td colspan="6" class="py-20 text-center">
<x-empty-state mode="table" colspan="6" :message="__('No dispense records found')" />
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
{{-- Mobile Cards (xl:hidden) --}}
<div class="xl:hidden grid grid-cols-1 md:grid-cols-2 gap-6">
@forelse($dispenseLogs as $log)
<div class="luxury-card p-6 rounded-[2rem] border border-slate-100 dark:border-slate-800 bg-white/50 dark:bg-slate-900/50 transition-all duration-300 group">
@php
$statusMap = [
'success' => ['label' => __('Dispense Success'), 'color' => 'emerald'],
'failed' => ['label' => __('Dispense Failed'), 'color' => 'rose'],
'pending' => ['label' => __('Dispense Pending'), 'color' => 'amber'],
'1' => ['label' => __('Dispense Success'), 'color' => 'emerald'],
'0' => ['label' => __('Dispense Failed'), 'color' => 'rose'],
];
$statusKey = (string)($log->dispense_status ?? 'pending');
$s = $statusMap[$statusKey] ?? ['label' => $statusKey, 'color' => 'slate'];
@endphp
{{-- Card Header --}}
<div class="flex items-start justify-between gap-4 mb-6">
<div class="flex items-center gap-4 min-w-0">
<div class="w-14 h-14 rounded-2xl bg-slate-100 dark:bg-slate-800 flex items-center justify-center text-slate-400 border border-slate-200 dark:border-slate-700 group-hover:bg-cyan-500 group-hover:text-white transition-all duration-300 overflow-hidden shadow-sm shrink-0">
<svg class="w-7 h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707.293l-2.414-2.414A1 1 0 006.586 13H4"/>
</svg>
</div>
<div class="min-w-0">
<h3 class="text-base font-extrabold text-slate-800 dark:text-slate-100 truncate tracking-tight">
{{ $log->machine->name ?? 'Unknown' }}
</h3>
<p class="text-xs font-mono font-bold text-slate-400 dark:text-slate-500 uppercase tracking-widest truncate">
{{ $log->machine->serial_no ?? '---' }}
</p>
</div>
</div>
<x-status-badge :color="$s['color']" :label="$s['label']" size="sm" />
</div>
{{-- Info Grid --}}
<div class="grid grid-cols-2 gap-y-4 mb-6 border-y border-slate-100 dark:border-slate-800/50 py-4">
<div>
<p class="text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-widest mb-1">{{ __('Product / Slot') }}</p>
<div class="flex flex-col gap-0.5 min-w-0">
<p class="text-sm font-black text-cyan-600 dark:text-cyan-400 truncate">
{{ $log->product->name ?? 'Unknown' }}
</p>
<p class="text-[10px] font-bold text-slate-400 uppercase tracking-widest">
{{ __('Slot') }}: {{ $log->slot_no }}
</p>
</div>
</div>
<div>
<p class="text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-widest mb-1">{{ __('Amount') }}</p>
<p class="text-sm font-black text-slate-700 dark:text-slate-300">{{ $log->amount }}</p>
</div>
<div>
<p class="text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-widest mb-1">{{ __('Dispense Time') }}</p>
<p class="text-sm font-bold text-slate-700 dark:text-slate-300">{{ $log->machine_time }}</p>
</div>
<div>
<p class="text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-widest mb-1">{{ __('Associated Order') }}</p>
<p class="text-sm font-bold text-slate-700 dark:text-slate-300 truncate">
{{ $log->order->order_no ?? '---' }}
</p>
</div>
</div>
{{-- Action Buttons --}}
<div class="flex items-center gap-3">
@if($log->order_id)
<button @click="openDetail({{ $log->order_id }})" class="flex-1 flex items-center justify-center gap-2 py-3 rounded-xl bg-slate-50 dark:bg-slate-800 text-slate-600 dark:text-slate-300 font-black text-xs uppercase tracking-widest border border-slate-100 dark:border-slate-800 hover:text-cyan-500 hover:bg-cyan-500/5 transition-all duration-300">
<svg class="w-4 h-4 stroke-[2.5]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.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 1 1-6 0 3 3 0 0 1 6 0Z" />
</svg>
{{ __('View Order') }}
</button>
@else
<div class="flex-1 py-3 text-center text-[10px] font-bold text-slate-400 uppercase tracking-widest bg-slate-50/50 dark:bg-slate-800/30 rounded-xl border border-dashed border-slate-200 dark:border-slate-700">
{{ __('No related detail found') }}
</div>
@endif
</div>
</div>
@empty
<div class="col-span-full py-10">
<x-empty-state :message="__('No dispense records found')" />
</div>
@endforelse
</div>
{{-- Pagination --}}
<div class="mt-8 border-t border-slate-100/50 dark:border-slate-800/50 pt-6">
{{ $dispenseLogs->links('vendor.pagination.luxury', ['page_param' => 'dispense_page']) }}
</div>

View File

@ -0,0 +1,283 @@
{{-- Search Bar --}}
<form action="{{ route('admin.sales.index') }}" method="GET"
class="flex flex-col lg:flex-row lg:items-center flex-wrap gap-3 mb-8"
@submit.prevent="fetchTabData('invoices')">
<input type="hidden" name="tab" value="invoices">
<div class="relative group flex-1 min-w-[280px]">
<span class="absolute inset-y-0 left-0 flex items-center pl-4 pointer-events-none z-10">
<svg class="w-4 h-4 text-slate-400 group-focus-within:text-cyan-500 transition-colors stroke-[2.5]"
viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
</span>
<input type="text" name="search" value="{{ $filters['search'] }}"
class="py-2.5 pl-12 pr-6 block w-full luxury-input"
placeholder="{{ __('Search Invoice No / Flow ID...') }}">
</div>
<div class="w-full lg:w-48">
<x-searchable-select name="machine_id" :placeholder="__('All Machines')" :selected="$filters['machine_id']"
@change="$el.closest('form').dispatchEvent(new Event('submit'))">
@foreach($machines as $m)
<option value="{{ $m->id }}" {{ $filters['machine_id'] == $m->id ? 'selected' : '' }} data-title="{{ $m->name }}">
{{ $m->name }}
</option>
@endforeach
</x-searchable-select>
</div>
{{-- 日期範圍 --}}
<div class="relative group w-full lg:w-72 lg:flex-none"
x-data="{ fp: null }"
x-init="fp = flatpickr($refs.dateRange, {
mode: 'range',
dateFormat: 'Y-m-d H:i',
enableTime: true,
time_24hr: true,
defaultHour: 0,
defaultMinute: 0,
locale: '{{ app()->getLocale() == 'zh_TW' ? 'zh_tw' : 'en' }}',
defaultDate: '{{ $filters['start_date'] }}' && '{{ $filters['end_date'] }}' ? ['{{ $filters['start_date'] }}', '{{ $filters['end_date'] }}'] : [],
onChange: function(selectedDates, dateStr, instance) {
if (selectedDates.length === 2) {
$refs.startDate.value = instance.formatDate(selectedDates[0], 'Y-m-d H:i');
$refs.endDate.value = instance.formatDate(selectedDates[1], 'Y-m-d H:i');
$el.closest('form').dispatchEvent(new Event('submit'));
} else if (selectedDates.length === 0) {
$refs.startDate.value = '';
$refs.endDate.value = '';
$el.closest('form').dispatchEvent(new Event('submit'));
}
}
})">
<span class="absolute inset-y-0 left-0 flex items-center pl-4 pointer-events-none z-10 text-slate-400 group-focus-within:text-cyan-500 transition-colors">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" /></svg>
</span>
<input type="hidden" name="start_date" x-ref="startDate" value="{{ $filters['start_date'] }}">
<input type="hidden" name="end_date" x-ref="endDate" value="{{ $filters['end_date'] }}">
<input type="text" x-ref="dateRange"
value="{{ $filters['start_date'] && $filters['end_date'] ? $filters['start_date'] . ' 至 ' . $filters['end_date'] : ($filters['start_date'] ?: '') }}"
placeholder="{{ __('Select Date Range') }}" class="luxury-input py-2.5 pl-12 pr-6 block w-full text-sm font-bold cursor-pointer">
</div>
<div class="flex items-center gap-2 ml-auto lg:ml-0 shrink-0">
<button type="submit"
class="p-2.5 rounded-xl bg-cyan-500 text-white hover:bg-cyan-600 shadow-lg shadow-cyan-500/25 transition-all active:scale-95"
title="{{ __('Search') }}">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"
stroke-width="2.5">
<path stroke-linecap="round" stroke-linejoin="round"
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
</button>
<button type="button"
@click="switchTab('invoices', '{{ route('admin.sales.index', ['tab' => 'invoices']) }}')"
class="p-2.5 rounded-xl bg-slate-100 dark:bg-slate-800 text-slate-500 dark:text-slate-400 hover:bg-slate-200 dark:hover:bg-slate-700 transition-all active:scale-95 border border-slate-200 dark:border-slate-700"
title="{{ __('Reset') }}">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"
stroke-width="2.5">
<path stroke-linecap="round" stroke-linejoin="round"
d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
</svg>
</button>
</div>
</form>
{{-- Table (Desktop) --}}
<div class="hidden xl:block overflow-x-auto">
<table class="w-full text-left border-separate border-spacing-0">
<thead>
<tr class="bg-slate-50/50 dark:bg-slate-900/10">
<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">
{{ __('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">
{{ __('Invoice Date') }}
</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">
{{ __('Machine') }}
</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">
{{ __('Amount') }}
</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">
{{ __('Status') }}
</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">
{{ __('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 text-right">
{{ __('Action') }}
</th>
</tr>
</thead>
<tbody class="divide-y divide-slate-100 dark:divide-slate-800/80">
@forelse($invoices as $invoice)
<tr class="group hover:bg-slate-50/50 dark:hover:bg-white/[0.02] transition-colors duration-200 cursor-pointer" @click="openDetail({{ $invoice->order_id }})">
<td class="px-6 py-6">
<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">
{{ $invoice->invoice_no }}
</span>
<span class="text-[10px] font-bold text-slate-400 uppercase tracking-widest mt-1">
{{ ($invoice->machine_time ?? $invoice->created_at)->format('Y-m-d H:i:s') }}
</span>
</div>
</td>
<td class="px-6 py-6">
<span class="text-sm font-bold text-slate-600 dark:text-slate-300 bg-slate-50 dark:bg-slate-800/50 px-2 py-1 rounded-md">
{{ $invoice->invoice_date }}
</span>
</td>
<td class="px-6 py-6">
<div class="text-sm font-extrabold text-slate-800 dark:text-slate-100 tracking-tight">
{{ $invoice->machine->name ?? ($invoice->order->machine->name ?? 'Unknown') }}
</div>
<div class="text-[10px] font-bold text-slate-400 uppercase tracking-[0.2em]">
{{ $invoice->machine->serial_no ?? ($invoice->order->machine->serial_no ?? '---') }}
</div>
</td>
<td class="px-6 py-6">
<span class="text-base font-black text-slate-800 dark:text-white tracking-tight">
${{ number_format($invoice->amount, 0) }}
</span>
</td>
<td class="px-6 py-6 whitespace-nowrap">
@php
// 簡單判斷:如果有發票號碼且 rtn_code 為空或 0/1 則視為有效
$status = 'valid';
if (empty($invoice->invoice_no)) $status = 'failed';
if ($invoice->rtn_code === 'void') $status = 'void';
$statusMap = [
'valid' => ['label' => __('Valid'), 'color' => 'emerald'],
'void' => ['label' => __('Void'), 'color' => 'rose'],
'failed' => ['label' => __('Failed'), 'color' => 'rose'],
'refunded' => ['label' => __('Refunded'), 'color' => 'slate'],
];
$s = $statusMap[$status] ?? ['label' => $status, 'color' => 'slate'];
@endphp
<x-status-badge :color="$s['color']" :label="$s['label']" size="xs" />
</td>
<td class="px-6 py-6">
<span class="text-sm font-black text-slate-600 dark:text-slate-400 bg-slate-50 dark:bg-slate-800 px-3 py-1 rounded-lg border border-slate-100 dark:border-slate-700">
{{ $invoice->order->order_no ?? '---' }}
</span>
</td>
<td class="px-6 py-6 text-right">
<button 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">
<svg class="w-4 h-4 stroke-[2.5]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.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 1 1-6 0 3 3 0 0 1 6 0Z" />
</svg>
</button>
</td>
</tr>
@empty
<tr>
<td colspan="6" class="py-20 text-center">
<x-empty-state mode="table" colspan="6" :message="__('No invoices found')" />
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
{{-- Mobile Cards (xl:hidden) --}}
<div class="xl:hidden grid grid-cols-1 md:grid-cols-2 gap-6">
@forelse($invoices as $invoice)
<div class="luxury-card p-6 rounded-[2rem] border border-slate-100 dark:border-slate-800 bg-white/50 dark:bg-slate-900/50 transition-all duration-300 group">
@php
$status = 'valid';
if (empty($invoice->invoice_no)) $status = 'failed';
if ($invoice->rtn_code === 'void') $status = 'void';
$statusMap = [
'valid' => ['label' => __('Valid'), 'color' => 'emerald'],
'void' => ['label' => __('Void'), 'color' => 'rose'],
'failed' => ['label' => __('Failed'), 'color' => 'rose'],
'refunded' => ['label' => __('Refunded'), 'color' => 'slate'],
];
$s = $statusMap[$status] ?? ['label' => $status, 'color' => 'slate'];
@endphp
{{-- Card Header --}}
<div class="flex items-start justify-between gap-4 mb-6">
<div class="flex items-center gap-4 min-w-0">
<div class="w-14 h-14 rounded-2xl bg-slate-100 dark:bg-slate-800 flex items-center justify-center text-slate-400 border border-slate-200 dark:border-slate-700 group-hover:bg-cyan-500 group-hover:text-white transition-all duration-300 overflow-hidden shadow-sm shrink-0">
<svg class="w-7 h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
</div>
<div class="min-w-0">
<h3 class="text-base font-extrabold text-slate-800 dark:text-slate-100 truncate hover:text-cyan-600 dark:hover:text-cyan-400 transition-colors tracking-tight">
{{ $invoice->invoice_no }}
</h3>
<div class="flex items-center gap-2 mt-1">
<span class="px-1.5 py-0.5 rounded bg-cyan-50 dark:bg-cyan-500/10 text-[9px] font-black text-cyan-600 dark:text-cyan-400 border border-cyan-100 dark:border-cyan-500/20">
{{ $invoice->invoice_date }}
</span>
<p class="text-[10px] font-bold text-slate-400 dark:text-slate-500 uppercase tracking-widest truncate">
{{ ($invoice->machine_time ?? $invoice->created_at)->format('Y-m-d H:i:s') }}
</p>
</div>
</div>
</div>
<x-status-badge :color="$s['color']" :label="$s['label']" size="sm" />
</div>
{{-- Info Grid --}}
<div class="grid grid-cols-2 gap-y-4 mb-6 border-y border-slate-100 dark:border-slate-800/50 py-4">
<div>
<p class="text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-widest mb-1">{{ __('Machine') }}</p>
<p class="text-sm font-bold text-slate-700 dark:text-slate-300 truncate">
{{ $invoice->machine->name ?? ($invoice->order->machine->name ?? 'Unknown') }}
</p>
<p class="text-[10px] font-bold text-slate-400 uppercase tracking-widest mt-0.5">
{{ $invoice->machine->serial_no ?? ($invoice->order->machine->serial_no ?? '---') }}
</p>
</div>
<div>
<p class="text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-widest mb-1">{{ __('Amount') }}</p>
<p class="text-base font-black text-cyan-600 dark:text-cyan-400">${{ number_format($invoice->amount, 0) }}</p>
</div>
<div>
<p class="text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-widest mb-1">{{ __('Associated Order') }}</p>
<p class="text-sm font-bold text-slate-700 dark:text-slate-300 truncate">
{{ $invoice->order->order_no ?? '---' }}
</p>
</div>
<div>
<p class="text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-widest mb-1">{{ __('Machine Time') }}</p>
<p class="text-sm font-bold text-slate-700 dark:text-slate-300">
{{ ($invoice->machine_time ?? $invoice->created_at)->format('Y-m-d H:i:s') }}
</p>
</div>
</div>
{{-- Action Buttons --}}
<div class="flex items-center gap-3">
<button @click="openDetail({{ $invoice->order_id }})" class="flex-1 flex items-center justify-center gap-2 py-3 rounded-xl bg-slate-50 dark:bg-slate-800 text-slate-600 dark:text-slate-300 font-black text-xs uppercase tracking-widest border border-slate-100 dark:border-slate-800 hover:text-cyan-500 hover:bg-cyan-500/5 transition-all duration-300">
<svg class="w-4 h-4 stroke-[2.5]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.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 1 1-6 0 3 3 0 0 1 6 0Z" />
</svg>
{{ __('View Details') }}
</button>
</div>
</div>
@empty
<div class="col-span-full py-10">
<x-empty-state :message="__('No invoices found')" />
</div>
@endforelse
</div>
{{-- Pagination --}}
<div class="mt-8 border-t border-slate-100/50 dark:border-slate-800/50 pt-6">
{{ $invoices->links('vendor.pagination.luxury', ['page_param' => 'invoices_page']) }}
</div>

View File

@ -0,0 +1,348 @@
{{-- Search Bar - 對齊取貨碼風格 --}}
<form action="{{ route('admin.sales.index') }}" method="GET"
class="flex flex-col lg:flex-row lg:items-center flex-wrap gap-3 mb-8" @submit.prevent="fetchTabData('orders')">
<input type="hidden" name="tab" value="orders">
<div class="relative group flex-1 min-w-[280px]">
<span class="absolute inset-y-0 left-0 flex items-center pl-4 pointer-events-none z-10">
<svg class="w-4 h-4 text-slate-400 group-focus-within:text-cyan-500 transition-colors stroke-[2.5]"
viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
</span>
<input type="text" name="search" value="{{ $filters['search'] }}"
class="py-2.5 pl-12 pr-6 block w-full luxury-input"
placeholder="{{ __('Search Order No / Flow ID / Invoice...') }}">
</div>
<div class="w-full lg:w-48">
<x-searchable-select name="machine_id" :placeholder="__('All Machines')" :selected="$filters['machine_id']"
@change="$el.closest('form').dispatchEvent(new Event('submit'))">
@foreach($machines as $m)
<option value="{{ $m->id }}" {{ $filters['machine_id']==$m->id ? 'selected' : '' }} data-title="{{ $m->name
}}">
{{ $m->name }}
</option>
@endforeach
</x-searchable-select>
</div>
{{-- 日期範圍 --}}
<div class="relative group w-full lg:w-72 lg:flex-none" x-data="{ fp: null }" x-init="fp = flatpickr($refs.dateRange, {
mode: 'range',
dateFormat: 'Y-m-d H:i',
enableTime: true,
time_24hr: true,
defaultHour: 0,
defaultMinute: 0,
locale: '{{ app()->getLocale() == 'zh_TW' ? 'zh_tw' : 'en' }}',
defaultDate: '{{ $filters['start_date'] }}' && '{{ $filters['end_date'] }}' ? ['{{ $filters['start_date'] }}', '{{ $filters['end_date'] }}'] : [],
onChange: function(selectedDates, dateStr, instance) {
if (selectedDates.length === 2) {
$refs.startDate.value = instance.formatDate(selectedDates[0], 'Y-m-d H:i');
$refs.endDate.value = instance.formatDate(selectedDates[1], 'Y-m-d H:i');
$el.closest('form').dispatchEvent(new Event('submit'));
} else if (selectedDates.length === 0) {
$refs.startDate.value = '';
$refs.endDate.value = '';
$el.closest('form').dispatchEvent(new Event('submit'));
}
}
})">
<span
class="absolute inset-y-0 left-0 flex items-center pl-4 pointer-events-none z-10 text-slate-400 group-focus-within:text-cyan-500 transition-colors">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
</span>
<input type="hidden" name="start_date" x-ref="startDate" value="{{ $filters['start_date'] }}">
<input type="hidden" name="end_date" x-ref="endDate" value="{{ $filters['end_date'] }}">
<input type="text" x-ref="dateRange"
value="{{ $filters['start_date'] && $filters['end_date'] ? $filters['start_date'] . ' 至 ' . $filters['end_date'] : ($filters['start_date'] ?: '') }}"
placeholder="{{ __('Select Date Range') }}"
class="luxury-input py-2.5 pl-12 pr-6 block w-full text-sm font-bold cursor-pointer">
</div>
<div class="flex items-center gap-2 ml-auto lg:ml-0 shrink-0">
<button type="submit"
class="p-2.5 rounded-xl bg-cyan-500 text-white hover:bg-cyan-600 shadow-lg shadow-cyan-500/25 transition-all active:scale-95"
title="{{ __('Search') }}">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5">
<path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
</button>
<button type="button" @click="switchTab('orders', '{{ route('admin.sales.index', ['tab' => 'orders']) }}')"
class="p-2.5 rounded-xl bg-slate-100 dark:bg-slate-800 text-slate-500 dark:text-slate-400 hover:bg-slate-200 dark:hover:bg-slate-700 transition-all active:scale-95 border border-slate-200 dark:border-slate-700"
title="{{ __('Reset') }}">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5">
<path stroke-linecap="round" stroke-linejoin="round"
d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
</svg>
</button>
</div>
</form>
{{-- Table (Desktop) --}}
<div class="hidden xl:block overflow-x-auto">
<table class="w-full text-left border-separate border-spacing-0">
<thead>
<tr class="bg-slate-50/50 dark:bg-slate-900/10">
<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">
{{ __('Order Number / Time') }}
</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">
{{ __('Machine') }}
</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">
{{ __('Product') }}
</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">
{{ __('Payment Amount') }}
</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">
{{ __('Status') }}
</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">
{{ __('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 text-right">
{{ __('Action') }}
</th>
</tr>
</thead>
<tbody class="divide-y divide-slate-100 dark:divide-slate-800/80">
@forelse($orders as $order)
<tr class="group hover:bg-slate-50/50 dark:hover:bg-white/[0.02] transition-colors duration-200">
<td class="px-6 py-6">
<div class="flex flex-col">
<span @click.stop="openDetail({{ $order->id }})"
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 cursor-pointer">
{{ $order->order_no }}
</span>
<span class="text-[10px] font-bold text-slate-400 uppercase tracking-widest mt-1">
{{ $order->created_at->format('Y-m-d H:i:s') }}
</span>
</div>
</td>
<td class="px-6 py-6">
<div class="text-sm font-extrabold text-slate-800 dark:text-slate-100 tracking-tight">
{{ $order->machine->name ?? 'Unknown' }}
</div>
<div class="text-[10px] font-bold text-slate-400 uppercase tracking-[0.2em]">
{{ $order->machine->serial_no ?? '---' }}
</div>
</td>
<td class="px-6 py-6">
<div class="flex flex-col max-w-[200px]">
@if($order->items->count() > 0)
<span class="text-sm font-black text-cyan-600 dark:text-cyan-400 mb-0.5 truncate">
{{ $order->items->first()->product_name }}
</span>
@if($order->items->count() > 1)
<span class="text-[10px] font-bold text-slate-400 uppercase tracking-widest">
{{ __('and :count other items', ['count' => $order->items->count()]) }}
</span>
@endif
@else
<span class="text-sm text-slate-400 italic">{{ __('No product record found') }}</span>
@endif
</div>
</td>
<td class="px-6 py-6">
<div class="flex flex-col">
<div class="flex items-center gap-1.5">
<span class="text-base font-black text-slate-800 dark:text-white tracking-tight">
${{ number_format($order->total_amount, 0) }}
</span>
<span
class="text-[10px] px-2 py-0.5 rounded-lg bg-slate-100 dark:bg-slate-800 text-slate-500 font-black uppercase tracking-widest border border-slate-200 dark:border-slate-700">
{{ $paymentTypes[$order->payment_type] ?? 'Unknown' }}
</span>
</div>
@if($order->discount_amount > 0)
<span class="text-[10px] text-rose-500 font-bold uppercase tracking-widest mt-1">
{{ __('Discounted') }} ${{ number_format($order->discount_amount, 0) }}
</span>
@endif
</div>
</td>
<td class="px-6 py-6 whitespace-nowrap">
@php
$statusMap = [
'pending' => ['label' => __('Pending'), 'color' => 'amber'],
'paid' => ['label' => __('Paid'), 'color' => 'emerald'],
'completed' => ['label' => __('Completed'), 'color' => 'emerald'],
'cancelled' => ['label' => __('Cancelled'), 'color' => 'slate'],
'refunded' => ['label' => __('Refunded'), 'color' => 'rose'],
];
$s = $statusMap[$order->status] ?? ['label' => $order->status, 'color' => 'slate'];
$invoiceSearchValue = $order->invoice ? $order->invoice->invoice_no : $order->order_no;
$targetUrl = route('admin.sales.index', ['tab' => 'invoices', 'search' => $invoiceSearchValue]);
@endphp
<x-status-badge :color="$s['color']" :label="$s['label']" size="xs" />
</td>
<td class="px-6 py-6 whitespace-nowrap">
@if($order->invoice)
<div @click.stop="switchTab('invoices', '{{ $targetUrl }}')"
class="flex items-center gap-1.5 text-sm font-extrabold text-slate-600 dark:text-slate-400 cursor-pointer hover:text-cyan-500 transition-colors group/invoice"
title="{{ __('Go to E-Invoice') }}">
<svg class="w-4 h-4 text-slate-300 dark:text-slate-600 group-hover/invoice:text-cyan-500"
fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5"
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
<span class="group-hover/invoice:underline decoration-2 underline-offset-4">{{
$order->invoice->invoice_no }}</span>
</div>
@else
<span class="text-xs font-bold text-slate-300 dark:text-slate-700 tracking-widest">---</span>
@endif
</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"
title="{{ __('View Details') }}">
<svg class="w-4 h-4 stroke-[2.5] transition-transform group-hover/btn:scale-110" fill="none"
stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round"
d="M2.036 12.322a1.012 1.012 0 0 1 0-.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 1 1-6 0 3 3 0 0 1 6 0Z" />
</svg>
</button>
</td>
</tr>
@empty
<tr>
<td colspan="7" class="py-20 text-center">
<x-empty-state mode="table" colspan="7" :message="__('No transaction orders found')" />
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
{{-- Mobile Cards (xl:hidden) --}}
<div class="xl:hidden grid grid-cols-1 md:grid-cols-2 gap-6">
@forelse($orders as $order)
<div
class="luxury-card p-6 rounded-[2rem] border border-slate-100 dark:border-slate-800 bg-white/50 dark:bg-slate-900/50 transition-all duration-300 group">
@php
$statusMap = [
'pending' => ['label' => __('Pending'), 'color' => 'amber'],
'paid' => ['label' => __('Paid'), 'color' => 'emerald'],
'completed' => ['label' => __('Completed'), 'color' => 'emerald'],
'cancelled' => ['label' => __('Cancelled'), 'color' => 'slate'],
'refunded' => ['label' => __('Refunded'), 'color' => 'rose'],
];
$s = $statusMap[$order->status] ?? ['label' => $order->status, 'color' => 'slate'];
$invoiceSearchValue = $order->invoice ? $order->invoice->invoice_no : $order->order_no;
$targetUrl = route('admin.sales.index', ['tab' => 'invoices', 'search' => $invoiceSearchValue]);
@endphp
{{-- Card Header --}}
<div class="flex items-start justify-between gap-4 mb-6">
<div class="flex items-center gap-4 min-w-0">
<div
class="w-14 h-14 rounded-2xl bg-slate-100 dark:bg-slate-800 flex items-center justify-center text-slate-400 border border-slate-200 dark:border-slate-700 group-hover:bg-cyan-500 group-hover:text-white transition-all duration-300 overflow-hidden shadow-sm shrink-0">
<svg class="w-7 h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z" />
</svg>
</div>
<div class="min-w-0">
<h3 @click="openDetail({{ $order->id }})"
class="text-base font-extrabold text-slate-800 dark:text-slate-100 truncate hover:text-cyan-600 dark:hover:text-cyan-400 transition-colors tracking-tight cursor-pointer">
{{ $order->order_no }}
</h3>
<p
class="text-xs font-mono font-bold text-slate-400 dark:text-slate-500 uppercase tracking-widest truncate">
{{ $order->machine->name ?? 'Unknown' }}
</p>
</div>
</div>
<div @click.stop="switchTab('invoices', '{{ $targetUrl }}')" class="cursor-pointer">
<x-status-badge :color="$s['color']" :label="$s['label']" size="sm" />
</div>
</div>
{{-- Info Grid --}}
<div class="grid grid-cols-2 gap-y-4 mb-6 border-y border-slate-100 dark:border-slate-800/50 py-4">
<div>
<p class="text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-widest mb-1">{{
__('Order Items') }}</p>
<p class="text-sm font-bold text-slate-700 dark:text-slate-300 truncate">
@if($order->items->count() > 0)
{{ $order->items->first()->product_name }}
@if($order->items->count() > 1)
<span class="text-[10px] text-slate-400 font-bold ml-1">{{ __('and :count other items', ['count' =>
$order->items->count()]) }}</span>
@endif
@else
<span class="text-slate-400 italic">{{ __('No product record found') }}</span>
@endif
</p>
</div>
<div>
<p class="text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-widest mb-1">{{
__('Amount / Payment') }}</p>
<p class="text-sm font-bold text-slate-700 dark:text-slate-300 flex items-center gap-1.5">
<span class="text-cyan-600 dark:text-cyan-400">${{ number_format($order->total_amount, 0) }}</span>
<span class="text-[10px] px-1.5 py-0.5 rounded bg-slate-100 dark:bg-slate-800/50 text-slate-500">{{
$paymentTypes[$order->payment_type] ?? '??' }}</span>
</p>
</div>
<div>
<p class="text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-widest mb-1">{{
__('Order Time') }}</p>
<p class="text-sm font-bold text-slate-700 dark:text-slate-300">
{{ $order->created_at->format('m-d H:i') }}
<span class="text-[10px] text-slate-400 ml-1">{{ $order->created_at->diffForHumans() }}</span>
</p>
</div>
<div>
<p class="text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-widest mb-1">{{
__('Invoice Number') }}</p>
<p @click.stop="switchTab('invoices', '{{ $targetUrl }}')"
class="text-sm font-bold text-slate-700 dark:text-slate-300 cursor-pointer hover:text-cyan-500 transition-colors">
{{ $order->invoice->invoice_no ?? '---' }}
</p>
</div>
</div>
{{-- Action Buttons --}}
<div class="flex items-center gap-3">
<button @click="openDetail({{ $order->id }})"
class="flex-1 flex items-center justify-center gap-2 py-3 rounded-xl bg-slate-50 dark:bg-slate-800 text-slate-600 dark:text-slate-300 font-black text-xs uppercase tracking-widest border border-slate-100 dark:border-slate-800 hover:text-cyan-500 hover:bg-cyan-500/5 transition-all duration-300">
<svg class="w-4 h-4 stroke-[2.5]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round"
d="M2.036 12.322a1.012 1.012 0 0 1 0-.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 1 1-6 0 3 3 0 0 1 6 0Z" />
</svg>
{{ __('View Details') }}
</button>
</div>
</div>
@empty
<div class="col-span-full py-10">
<x-empty-state :message="__('No transaction orders found')" />
</div>
@endforelse
</div>
{{-- Pagination --}}
<div class="mt-8 border-t border-slate-100/50 dark:border-slate-800/50 pt-6">
{{ $orders->links('vendor.pagination.luxury', ['page_param' => 'orders_page']) }}
</div>

View File

@ -69,7 +69,7 @@
</tr> </tr>
@else @else
{{-- 獨立 Card 版(用於 card grid @empty,或 Alpine x-if 包裹) --}} {{-- 獨立 Card 版(用於 card grid @empty,或 Alpine x-if 包裹) --}}
<div class="col-span-full py-20 text-center flex flex-col items-center gap-3 luxury-card rounded-3xl border border-slate-100 dark:border-slate-800/50 bg-white/50 dark:bg-slate-900/50"> <div class="col-span-full py-20 text-center flex flex-col items-center gap-3">
<div class="p-4 rounded-3xl bg-slate-50 dark:bg-slate-800/50"> <div class="p-4 rounded-3xl bg-slate-50 dark:bg-slate-800/50">
@if($slot->isNotEmpty()) @if($slot->isNotEmpty())
{{ $slot }} {{ $slot }}

View File

@ -20,11 +20,12 @@
<button <button
type="button" type="button"
{{ $attributes }}
@click="{{ $model }} = '{{ $value }}'" @click="{{ $model }} = '{{ $value }}'"
:class="{{ $model }} === '{{ $value }}' :class="{{ $model }} === '{{ $value }}'
? 'bg-white dark:bg-slate-800 text-cyan-600 dark:text-cyan-400 shadow-sm shadow-cyan-500/10' ? 'bg-white dark:bg-slate-800 text-cyan-600 dark:text-cyan-400 shadow-sm shadow-cyan-500/10'
: 'text-slate-400 hover:text-slate-600 dark:hover:text-slate-200'" : 'text-slate-400 hover:text-slate-600 dark:hover:text-slate-200'"
class="px-8 py-3 rounded-xl text-sm font-black uppercase tracking-widest transition-all duration-300 flex-1 sm:flex-none" class="px-6 py-3 rounded-xl text-sm font-black uppercase tracking-widest transition-all duration-300 flex-1 sm:flex-none"
> >
{{ $label }} {{ $label }}
</button> </button>

View File

@ -11,8 +11,9 @@
$limits = [10, 25, 50, 100]; $limits = [10, 25, 50, 100];
$event = $ajax_navigate_event ?? 'ajax:navigate'; $event = $ajax_navigate_event ?? 'ajax:navigate';
$perPageKey = $per_page_param ?? 'per_page'; $perPageKey = $per_page_param ?? 'per_page';
$pageKey = $page_param ?? 'page';
@endphp @endphp
<select onchange="{ const params = new URLSearchParams(window.location.search); params.set('{{ $perPageKey }}', this.value); params.delete('page'); const url = window.location.pathname + '?' + params.toString(); const evt = new CustomEvent('{{ $event }}', { detail: { url: url }, bubbles: true, cancelable: true }); if (this.dispatchEvent(evt)) { window.location.href = url; } }" <select onchange="{ const params = new URLSearchParams(window.location.search); params.set('{{ $perPageKey }}', this.value); params.delete('{{ $pageKey }}'); const url = window.location.pathname + '?' + params.toString(); const evt = new CustomEvent('{{ $event }}', { detail: { url: url }, bubbles: true, cancelable: true }); if (this.dispatchEvent(evt)) { window.location.href = url; } }"
class="h-7 pl-2 pr-7 rounded-lg bg-white dark:bg-slate-800 border-none text-[11px] font-black text-slate-600 dark:text-slate-300 appearance-none focus:ring-4 focus:ring-cyan-500/10 outline-none transition-all cursor-pointer shadow-sm leading-none py-0 !bg-none"> class="h-7 pl-2 pr-7 rounded-lg bg-white dark:bg-slate-800 border-none text-[11px] font-black text-slate-600 dark:text-slate-300 appearance-none focus:ring-4 focus:ring-cyan-500/10 outline-none transition-all cursor-pointer shadow-sm leading-none py-0 !bg-none">
@foreach($limits as $l) @foreach($limits as $l)
<option value="{{ $l }}" {{ $currentLimit == $l ? 'selected' : '' }}>{{ $l }}</option> <option value="{{ $l }}" {{ $currentLimit == $l ? 'selected' : '' }}>{{ $l }}</option>

View File

@ -138,6 +138,9 @@ Route::middleware(['auth', 'verified', 'tenant.access'])->prefix('admin')->name(
Route::get('/orders', [App\Http\Controllers\Admin\SalesController::class, 'orders'])->name('orders'); Route::get('/orders', [App\Http\Controllers\Admin\SalesController::class, 'orders'])->name('orders');
Route::get('/promotions', [App\Http\Controllers\Admin\SalesController::class, 'promotions'])->name('promotions'); Route::get('/promotions', [App\Http\Controllers\Admin\SalesController::class, 'promotions'])->name('promotions');
Route::get('/store-gifts', [App\Http\Controllers\Admin\SalesController::class, 'storeGifts'])->name('store-gifts'); Route::get('/store-gifts', [App\Http\Controllers\Admin\SalesController::class, 'storeGifts'])->name('store-gifts');
// 詳情路由必須放在最後,避免攔截其他具體路由
Route::get('/{order}', [App\Http\Controllers\Admin\SalesController::class, 'show'])->name('show');
}); });
// 7. 分析管理 // 7. 分析管理