diff --git a/app/src/main/java/com/unibuy/smartdevice/DialogAbstract.java b/app/src/main/java/com/unibuy/smartdevice/DialogAbstract.java index 5eab9c8..e270acb 100644 --- a/app/src/main/java/com/unibuy/smartdevice/DialogAbstract.java +++ b/app/src/main/java/com/unibuy/smartdevice/DialogAbstract.java @@ -88,6 +88,7 @@ public abstract class DialogAbstract extends AlertDialog { // 設定對話框寬度為螢幕的 90% Window window = getWindow(); if (window != null) { + window.setBackgroundDrawable(new android.graphics.drawable.ColorDrawable(android.graphics.Color.TRANSPARENT)); WindowManager.LayoutParams layoutParams = window.getAttributes(); // layoutParams.width = (int) (getContext().getResources().getDisplayMetrics().widthPixels * 0.9); @@ -97,8 +98,8 @@ public abstract class DialogAbstract extends AlertDialog { // 設定高度為包裹內容(可調整為 MATCH_PARENT) layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; - // 設定對話框貼齊底部 - layoutParams.gravity = Gravity.BOTTOM; + // 設定對話框居中顯示 + layoutParams.gravity = Gravity.CENTER; window.setAttributes(layoutParams); getSrcHandlerMain().start(getClass().getSimpleName(), FontendActivity.Option.HIDE_SALE_OVERLAY.getOption(), "hide sale overlay"); diff --git a/app/src/main/java/com/unibuy/smartdevice/ui/devs/vmc/RecyclerVmcBuyListAdpter.java b/app/src/main/java/com/unibuy/smartdevice/ui/devs/vmc/RecyclerVmcBuyListAdpter.java index 1f22414..52f9823 100644 --- a/app/src/main/java/com/unibuy/smartdevice/ui/devs/vmc/RecyclerVmcBuyListAdpter.java +++ b/app/src/main/java/com/unibuy/smartdevice/ui/devs/vmc/RecyclerVmcBuyListAdpter.java @@ -91,22 +91,18 @@ public class RecyclerVmcBuyListAdpter extends RecyclerView.Adapter 0 ? machinePrice : sellingPrice; - if (price > 0) { - holder.binding.textPrice.setVisibility(View.VISIBLE); - holder.binding.textPrice.setText("NT$ " + price); - } else { - holder.binding.textPrice.setVisibility(View.GONE); - } + holder.binding.textPrice.setVisibility(View.VISIBLE); + holder.binding.textPrice.setText("NT$ " + price); // 綁定庫存數量顯示 - holder.binding.textStock.setText("庫存: " + count); + holder.binding.textStock.setText("庫存" + count); holder.binding.mask.setVisibility(View.GONE); holder.binding.textMask.setText(""); if (count <= 0) { holder.binding.mask.setVisibility(View.VISIBLE); - holder.binding.textMask.setText("補貨中");// 已經售完 + holder.binding.textMask.setText("售完"); } if (isLock) { diff --git a/app/src/main/java/com/unibuy/smartdevice/ui/dialog/CheckoutAccessCodeDialog.java b/app/src/main/java/com/unibuy/smartdevice/ui/dialog/CheckoutAccessCodeDialog.java index 6244a70..dd613b0 100644 --- a/app/src/main/java/com/unibuy/smartdevice/ui/dialog/CheckoutAccessCodeDialog.java +++ b/app/src/main/java/com/unibuy/smartdevice/ui/dialog/CheckoutAccessCodeDialog.java @@ -144,6 +144,18 @@ public class CheckoutAccessCodeDialog extends DialogAbstract { openBarcode = true; httpAPI = new HttpAPI(getHandlerMain()); + setInputMode(true); + + binding.btnModeKeypad.setOnClickListener(v -> { + setInputMode(true); + if (closeDialogCountdown != null) closeDialogCountdown.setCountdown(40); + }); + + binding.btnModeScan.setOnClickListener(v -> { + setInputMode(false); + if (closeDialogCountdown != null) closeDialogCountdown.setCountdown(40); + }); + binding.buttonFinish.setOnClickListener(v -> changeOk()); binding.buttonCancel.setOnClickListener(v -> changeBuy()); @@ -297,6 +309,14 @@ public class CheckoutAccessCodeDialog extends DialogAbstract { } } + private void setInputMode(boolean isKeyboard) { + binding.btnModeKeypad.setSelected(isKeyboard); + binding.btnModeScan.setSelected(!isKeyboard); + + binding.linearNumpad.setVisibility(isKeyboard ? android.view.View.VISIBLE : android.view.View.GONE); + binding.imageViewScanHint.setVisibility(isKeyboard ? android.view.View.GONE : android.view.View.VISIBLE); + } + public int getTotalPrice() { int totalPrice = 0; if (MyApp.getInstance().getBuyList().size() == 0) return totalPrice; diff --git a/app/src/main/java/com/unibuy/smartdevice/ui/dialog/CheckoutFreeGiftCodeDialog.java b/app/src/main/java/com/unibuy/smartdevice/ui/dialog/CheckoutFreeGiftCodeDialog.java index 94aa446..7b753eb 100644 --- a/app/src/main/java/com/unibuy/smartdevice/ui/dialog/CheckoutFreeGiftCodeDialog.java +++ b/app/src/main/java/com/unibuy/smartdevice/ui/dialog/CheckoutFreeGiftCodeDialog.java @@ -137,6 +137,18 @@ public class CheckoutFreeGiftCodeDialog extends DialogAbstract { openBarcode = true; httpAPI = new HttpAPI(getHandlerMain()); + setInputMode(true); + + binding.btnModeKeypad.setOnClickListener(v -> { + setInputMode(true); + if (closeDialogCountdown != null) closeDialogCountdown.setCountdown(40); + }); + + binding.btnModeScan.setOnClickListener(v -> { + setInputMode(false); + if (closeDialogCountdown != null) closeDialogCountdown.setCountdown(40); + }); + binding.buttonFinish.setOnClickListener(v -> changeOk()); binding.buttonCancel.setOnClickListener(v -> changeBuy()); @@ -287,6 +299,14 @@ public class CheckoutFreeGiftCodeDialog extends DialogAbstract { } } + private void setInputMode(boolean isKeyboard) { + binding.btnModeKeypad.setSelected(isKeyboard); + binding.btnModeScan.setSelected(!isKeyboard); + + binding.linearNumpad.setVisibility(isKeyboard ? android.view.View.VISIBLE : android.view.View.GONE); + binding.imageViewScanHint.setVisibility(isKeyboard ? android.view.View.GONE : android.view.View.VISIBLE); + } + public int getTotalPrice() { int totalPrice = 0; if (MyApp.getInstance().getBuyList().size() == 0) return totalPrice; diff --git a/app/src/main/java/com/unibuy/smartdevice/ui/dialog/FontendPickupCodeDialog.java b/app/src/main/java/com/unibuy/smartdevice/ui/dialog/FontendPickupCodeDialog.java index c0ae77f..c26631e 100644 --- a/app/src/main/java/com/unibuy/smartdevice/ui/dialog/FontendPickupCodeDialog.java +++ b/app/src/main/java/com/unibuy/smartdevice/ui/dialog/FontendPickupCodeDialog.java @@ -180,6 +180,18 @@ public class FontendPickupCodeDialog extends DialogAbstract { MyApp.getInstance().initialReportData(); + setInputMode(true); + + binding.btnModeKeypad.setOnClickListener(v -> { + setInputMode(true); + if (closeDialogCountdown != null) closeDialogCountdown.setCountdown(40); + }); + + binding.btnModeScan.setOnClickListener(v -> { + setInputMode(false); + if (closeDialogCountdown != null) closeDialogCountdown.setCountdown(40); + }); + isChangeDispatch = true; openBarcode = true; httpAPI = new HttpAPI(getHandlerMain()); @@ -295,6 +307,14 @@ public class FontendPickupCodeDialog extends DialogAbstract { } } + private void setInputMode(boolean isKeyboard) { + binding.btnModeKeypad.setSelected(isKeyboard); + binding.btnModeScan.setSelected(!isKeyboard); + + binding.linearNumpad.setVisibility(isKeyboard ? android.view.View.VISIBLE : android.view.View.GONE); + binding.imageViewScanHint.setVisibility(isKeyboard ? android.view.View.GONE : android.view.View.VISIBLE); + } + public class ReadBarCodeOnScheduler extends HandlerMainScheduler { public ReadBarCodeOnScheduler(HandlerMain handlerMain) { super(handlerMain); @@ -471,7 +491,7 @@ public class FontendPickupCodeDialog extends DialogAbstract { } public void setButtonCancelText(long countdown) { - binding.buttonCancel.setText(getContext().getString(R.string.return_to)+"("+countdown+")");//返回 + binding.buttonCancel.setText("取消 " + countdown + "秒"); } public void setStatusText(String message) { diff --git a/app/src/main/java/com/unibuy/smartdevice/ui/dialog/InvoiceTypeDialog.java b/app/src/main/java/com/unibuy/smartdevice/ui/dialog/InvoiceTypeDialog.java index 4ce7f3f..df1194f 100644 --- a/app/src/main/java/com/unibuy/smartdevice/ui/dialog/InvoiceTypeDialog.java +++ b/app/src/main/java/com/unibuy/smartdevice/ui/dialog/InvoiceTypeDialog.java @@ -90,6 +90,13 @@ public class InvoiceTypeDialog extends DialogAbstract { binding = DialogInvoiceTypeBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); + android.view.Window window = getWindow(); + if (window != null) { + android.view.WindowManager.LayoutParams layoutParams = window.getAttributes(); + layoutParams.gravity = android.view.Gravity.CENTER; + window.setAttributes(layoutParams); + } + // 選擇:輸入載具(手機條碼) binding.cardVehicle.setOnClickListener(v -> { closeDialogCountdown.shutdown(); @@ -139,7 +146,7 @@ public class InvoiceTypeDialog extends DialogAbstract { } public void setButtonCancelText(long countdown) { - binding.buttonCancel.setText("返回支付方式(" + countdown + ")"); + binding.buttonCancel.setText("返回" + countdown + "秒"); } public static class CloseDialogOnThreadHandler extends HandlerMainCountdown { diff --git a/app/src/main/java/com/unibuy/v2/adapter/CartOperationAdapter.kt b/app/src/main/java/com/unibuy/v2/adapter/CartOperationAdapter.kt index 877c3e6..67dfb16 100644 --- a/app/src/main/java/com/unibuy/v2/adapter/CartOperationAdapter.kt +++ b/app/src/main/java/com/unibuy/v2/adapter/CartOperationAdapter.kt @@ -1,6 +1,8 @@ package com.unibuy.v2.adapter +import android.graphics.PorterDuff import android.widget.ImageView +import androidx.core.content.ContextCompat import com.chad.library.adapter.base.BaseQuickAdapter import com.chad.library.adapter.base.viewholder.BaseViewHolder import com.unibuy.smartdevice.R @@ -12,6 +14,11 @@ import com.unibuy.v2.UnibuyHelper /** * 購物車品項清單 Adapter(自 Luzui v2 移植)。 * 依賴 BaseRecyclerViewAdapterHelper 的 BaseQuickAdapter。 + * + * Disabled 按鈕規則: + * - buttonMinus:當 cartSelectedCount == 1 時 disabled(最低 1 件,不允許繼續減少) + * - buttonPlus :當 cartSelectedCount >= slot.count(庫存上限)或全車總件數 >= 8 時 disabled + * Disabled 外觀:背景換 bg_quantity_button_disabled、圖示染灰(#ADADAD)、clickable = false。 */ class CartOperationAdapter(layoutResId: Int, data: MutableList) : BaseQuickAdapter(layoutResId, data) { @@ -22,19 +29,65 @@ class CartOperationAdapter(layoutResId: Int, data: MutableList) : override fun convert(holder: BaseViewHolder, item: SlotStructure) { val result = UnibuyHelper.getCartViewModel().createResult(item) + val ctx = holder.itemView.context - // 多國語商品名稱(統一由 ProductStructure 處理,英/日未翻譯自動 fallback 中文) - val name = item.product.getLocalizedName(holder.itemView.context) + // 多國語商品名稱(統一由 ProductStructure 處理:i18n map → zh_TW → 舊 _en/_jp → 中文主值) + val name = item.product.getLocalizedName(ctx) holder.setText(R.id.textProductName, name) .setText(R.id.totalPriceTextView, "NT$ ${result.currentItemPrice}") + .setText(R.id.textStock, String.format("庫存%02d件", item.count)) .setText(R.id.textQuantity, "${result.currentItemCount}") .setText(R.id.textPrice, "NT$ ${item.product.realPrice}") + + // ── 商品圖片 ──────────────────────────────────────────────────── val imageProductPicture = holder.getView(R.id.image_product) try { ImageGlide(imageProductPicture.context).fileload(item.product.productImg, imageProductPicture) } catch (e: LogsEmptyException) { e.printStackTrace() } + + // ── 按鈕 Disabled 狀態判斷 ────────────────────────────────────── + val buttonMinus = holder.getView(R.id.buttonMinus) + val buttonPlus = holder.getView(R.id.buttonPlus) + + val isAtMinCount = item.cartSelectedCount <= 1 + val isAtStockLimit = item.cartSelectedCount >= item.count + val isCartFull = UnibuyHelper.getCartViewModel().hasMinimumCartItems() + val isPlusDisabled = isAtStockLimit || isCartFull + + // ── 減少按鈕 ──────────────────────────────────────────────────── + applyButtonState(buttonMinus, disabled = isAtMinCount, ctx) + + // ── 增加按鈕 ──────────────────────────────────────────────────── + applyButtonState(buttonPlus, disabled = isPlusDisabled, ctx) + } + + /** + * 套用啟用 / 停用外觀到 ImageView 按鈕。 + * + * @param button 目標按鈕 + * @param disabled true = 停用(light_gray 背景 + 灰色圖示 + 不可點擊) + * @param ctx Context(取色用) + */ + private fun applyButtonState(button: ImageView, disabled: Boolean, ctx: android.content.Context) { + if (disabled) { + button.setBackgroundResource(R.drawable.bg_quantity_button_disabled) + // setBackgroundResource 會重置 stateListAnimator,需立刻清除以防止陰影跳動 + button.stateListAnimator = null + button.setColorFilter( + ContextCompat.getColor(ctx, R.color.gray), + PorterDuff.Mode.SRC_IN + ) + button.isClickable = false + } else { + button.setBackgroundResource(R.drawable.bg_quantity_outline_button) + // setBackgroundResource 會重置 stateListAnimator,需立刻清除以防止陰影跳動 + button.stateListAnimator = null + button.clearColorFilter() + button.isClickable = true + } } } + diff --git a/app/src/main/java/com/unibuy/v2/ui/ShoppingCartFragment.java b/app/src/main/java/com/unibuy/v2/ui/ShoppingCartFragment.java index fe88b9f..d90c6ad 100644 --- a/app/src/main/java/com/unibuy/v2/ui/ShoppingCartFragment.java +++ b/app/src/main/java/com/unibuy/v2/ui/ShoppingCartFragment.java @@ -200,6 +200,12 @@ public class ShoppingCartFragment extends FragmentAbstract { allCartItems = UnibuyHelper.INSTANCE.getCartViewModel().getAllCartItems(); binding.totalItemsTextView.setText(getString(R.string.total_items_format, allCartItems.getTotalCount())); binding.totalAmountTextView.setText(getString(R.string.total_amount_format, allCartItems.getTotalPrice())); + + if (UnibuyHelper.INSTANCE.getCartViewModel().hasMinimumCartItems()) { + binding.maxItemsWarningTextView.setVisibility(View.VISIBLE); + } else { + binding.maxItemsWarningTextView.setVisibility(View.GONE); + } } /** 清空購物車並切回 VMC 商品列表。 */ diff --git a/app/src/main/res/color/color_input_mode_bg.xml b/app/src/main/res/color/color_input_mode_bg.xml new file mode 100644 index 0000000..b65f4e8 --- /dev/null +++ b/app/src/main/res/color/color_input_mode_bg.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/color/color_input_mode_text.xml b/app/src/main/res/color/color_input_mode_text.xml new file mode 100644 index 0000000..55d3170 --- /dev/null +++ b/app/src/main/res/color/color_input_mode_text.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/bg_input_outline.xml b/app/src/main/res/drawable/bg_input_outline.xml new file mode 100644 index 0000000..12c5355 --- /dev/null +++ b/app/src/main/res/drawable/bg_input_outline.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/app/src/main/res/drawable/bg_quantity_button_disabled.xml b/app/src/main/res/drawable/bg_quantity_button_disabled.xml new file mode 100644 index 0000000..a51aaee --- /dev/null +++ b/app/src/main/res/drawable/bg_quantity_button_disabled.xml @@ -0,0 +1,8 @@ + + + + + + + diff --git a/app/src/main/res/drawable/bg_quantity_outline_button.xml b/app/src/main/res/drawable/bg_quantity_outline_button.xml index e6e9c1c..a805788 100644 --- a/app/src/main/res/drawable/bg_quantity_outline_button.xml +++ b/app/src/main/res/drawable/bg_quantity_outline_button.xml @@ -1,12 +1,16 @@ - - - - - - - - + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/bg_rounded_card_surface.xml b/app/src/main/res/drawable/bg_rounded_card_surface.xml new file mode 100644 index 0000000..0a5b02a --- /dev/null +++ b/app/src/main/res/drawable/bg_rounded_card_surface.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/bg_rounded_light_gray.xml b/app/src/main/res/drawable/bg_rounded_light_gray.xml new file mode 100644 index 0000000..5b68829 --- /dev/null +++ b/app/src/main/res/drawable/bg_rounded_light_gray.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/app/src/main/res/drawable/bg_rounded_primary.xml b/app/src/main/res/drawable/bg_rounded_primary.xml new file mode 100644 index 0000000..5a9aefb --- /dev/null +++ b/app/src/main/res/drawable/bg_rounded_primary.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/app/src/main/res/drawable/bg_rounded_surface.xml b/app/src/main/res/drawable/bg_rounded_surface.xml new file mode 100644 index 0000000..19f9c30 --- /dev/null +++ b/app/src/main/res/drawable/bg_rounded_surface.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/bg_segmented_container.xml b/app/src/main/res/drawable/bg_segmented_container.xml new file mode 100644 index 0000000..c424ff0 --- /dev/null +++ b/app/src/main/res/drawable/bg_segmented_container.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/src/main/res/drawable/bg_waste_outline_button.xml b/app/src/main/res/drawable/bg_waste_outline_button.xml index 2de6c1b..45c5635 100644 --- a/app/src/main/res/drawable/bg_waste_outline_button.xml +++ b/app/src/main/res/drawable/bg_waste_outline_button.xml @@ -1,12 +1,16 @@ - - - - - - - - + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/keyboard_alt_24.xml b/app/src/main/res/drawable/keyboard_alt_24.xml new file mode 100644 index 0000000..e1426ba --- /dev/null +++ b/app/src/main/res/drawable/keyboard_alt_24.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/keyboard_backspace_24.xml b/app/src/main/res/drawable/keyboard_backspace_24.xml new file mode 100644 index 0000000..c9953b3 --- /dev/null +++ b/app/src/main/res/drawable/keyboard_backspace_24.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/qr_code_scanner_24.xml b/app/src/main/res/drawable/qr_code_scanner_24.xml new file mode 100644 index 0000000..29d28d1 --- /dev/null +++ b/app/src/main/res/drawable/qr_code_scanner_24.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/layout/dialog_access_code.xml b/app/src/main/res/layout/dialog_access_code.xml index 1e96a05..829892b 100644 --- a/app/src/main/res/layout/dialog_access_code.xml +++ b/app/src/main/res/layout/dialog_access_code.xml @@ -6,12 +6,12 @@ android:layout_height="match_parent" android:background="@color/transparent"> - + + + + + + + - + + android:orientation="vertical"> + + + + + + + @@ -245,56 +205,43 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" + android:clipChildren="false" + android:clipToPadding="false" android:orientation="horizontal"> + + style="@style/Widget.App.KeypadButton" + android:layout_marginEnd="12dp" + app:icon="@drawable/close_24" /> + + + style="@style/Widget.App.KeypadButton" + app:icon="@drawable/keyboard_backspace_24" /> + + + + @@ -303,15 +250,25 @@ android:layout_height="80dp" android:layout_marginTop="16dp" android:gravity="center" + android:clipChildren="false" + android:clipToPadding="false" android:orientation="horizontal"> - + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_free_gift_code.xml b/app/src/main/res/layout/dialog_free_gift_code.xml index 44a68a3..16eb7a9 100644 --- a/app/src/main/res/layout/dialog_free_gift_code.xml +++ b/app/src/main/res/layout/dialog_free_gift_code.xml @@ -3,192 +3,298 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:background="@color/light_gray"> + android:layout_height="match_parent" + android:background="@color/transparent"> - - - - - - - + android:clipChildren="false" + android:clipToPadding="false" + android:orientation="vertical" + android:paddingTop="32dp" + android:paddingBottom="24dp"> + + - - + android:text="@string/enter_gift_or_scan_qrcode" + android:textColor="@color/primary" + android:textSize="24sp" + android:textStyle="bold" /> + android:clipChildren="false" + android:clipToPadding="false" + android:paddingBottom="20dp" + android:orientation="vertical"> -