diff --git a/app/src/main/java/com/mob/utsmyanmar/AGENTS.md b/app/src/main/java/com/mob/utsmyanmar/AGENTS.md index 16439bf..94ec56a 100644 --- a/app/src/main/java/com/mob/utsmyanmar/AGENTS.md +++ b/app/src/main/java/com/mob/utsmyanmar/AGENTS.md @@ -37,4 +37,7 @@ Pick the edge-case-correct option when two stdlib approaches are the same size, Mark intentional simplifications with a ponytail: comment. If the shortcut has a known ceiling (global lock, O(n²) scan, naive heuristic), the comment names the ceiling and the upgrade path. Not lazy about: understanding the problem (read it fully and trace the real flow before picking a rung, a small diff you don't understand is just laziness dressed up as efficiency), input validation at trust boundaries, error handling that prevents data loss, security, accessibility, the calibration real hardware needs (the platform is never the spec ideal, a clock drifts, a sensor reads off), anything explicitly requested. Lazy code without its check is unfinished: non-trivial logic leaves ONE runnable check behind, the smallest thing that fails if the logic breaks (an assert-based demo/self-check or one small test file; no frameworks, no fixtures). Trivial one-liners need no test. -(Yes, this file also applies to agents working on the ponytail repo itself. Especially to them.) \ No newline at end of file +(Yes, this file also applies to agents working on the ponytail repo itself. Especially to them.) + +### Don't Do This +- don't run ./grdlew \ No newline at end of file diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/print_receipt/PrintReceiptScreen.kt b/app/src/main/java/com/mob/utsmyanmar/ui/print_receipt/PrintReceiptScreen.kt index 02e99c7..0d93508 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/print_receipt/PrintReceiptScreen.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/print_receipt/PrintReceiptScreen.kt @@ -3,6 +3,7 @@ package com.mob.utsmyanmar.ui.print_receipt import androidx.compose.animation.core.Animatable import androidx.compose.animation.core.FastOutSlowInEasing import androidx.compose.animation.core.tween +import androidx.compose.foundation.Canvas import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.layout.Arrangement @@ -32,18 +33,24 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.PathEffect +import androidx.compose.ui.graphics.StrokeCap import androidx.compose.ui.graphics.graphicsLayer -import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.mob.utsmyanmar.ui.components.appbar.AppBar import com.mob.utsmyanmar.ui.history_functions.displayTransactionStatus import com.mob.utsmyanmar.ui.history_functions.displayTransactionTitle +import com.mob.utsmyanmar.ui.preview.P2Preview +import com.mob.utsmyanmar.ui.preview.P3Preview import com.mob.utsmyanmar.ui.theme.Color +import com.mob.utsmyanmar.ui.theme.MOBPOSTheme import com.mob.utsmyanmar.ui.transaction_result.TransactionResultState import com.mob.utsmyanmar.ui.transaction_result.TransactionResultViewModel import com.mob.utsmyanmar.viewmodel.SharedViewModel +import com.utsmyanmar.paylibs.model.PayDetail import com.utsmyanmar.paylibs.utils.POSUtil import com.utsmyanmar.paylibs.utils.PrintStatus import kotlinx.coroutines.launch @@ -59,9 +66,32 @@ fun PrintReceiptScreen( sharedViewModel: SharedViewModel, onPrint: () -> Unit, onDone: () -> Unit, - onPrintFinished : () -> Unit, + onPrintFinished: () -> Unit, ) { val state by transactionResultViewModel.state.collectAsStateWithLifecycle() + val isReprint = sharedViewModel.isReprint.value ?: false + + PrintReceiptContent( + state = state, + isReprint = isReprint, + onPrint = onPrint, + onDone = onDone, + onPrintFinished = onPrintFinished, + onSetPrintStatus = { sharedViewModel.setPrintStatus(it) }, + onResetReprint = { sharedViewModel.isReprint.value = false }, + ) +} + +@Composable +fun PrintReceiptContent( + state: TransactionResultState, + isReprint: Boolean, + onPrint: () -> Unit, + onDone: () -> Unit, + onPrintFinished: () -> Unit, + onSetPrintStatus: (PrintStatus) -> Unit, + onResetReprint: () -> Unit +) { val scope = rememberCoroutineScope() val receiptOffsetY = remember { Animatable(0f) } val merchant_copy_autoprint = true @@ -82,14 +112,11 @@ fun PrintReceiptScreen( ) } - fun isReprintMode() = sharedViewModel.isReprint.value == true - fun doPrint(copy: ReceiptCopy, onFinished: (printFinished: ReceiptCopy) -> Unit) { - val reprint = isReprintMode() - val actualCopy = if (reprint && copy == ReceiptCopy.MERCHANT) ReceiptCopy.CUSTOMER else copy + val actualCopy = if (isReprint && copy == ReceiptCopy.MERCHANT) ReceiptCopy.CUSTOMER else copy currentCopy = actualCopy - sharedViewModel.setPrintStatus( + onSetPrintStatus( if (actualCopy == ReceiptCopy.MERCHANT) PrintStatus.FIRST_PRINT else @@ -100,7 +127,7 @@ fun PrintReceiptScreen( isPrinting = true animatePrint() isPrinting = false - val upcomingCopy = if (reprint) ReceiptCopy.CUSTOMER + val upcomingCopy = if (isReprint) ReceiptCopy.CUSTOMER else if (actualCopy == ReceiptCopy.MERCHANT) ReceiptCopy.CUSTOMER else ReceiptCopy.CUSTOMER @@ -112,14 +139,13 @@ fun PrintReceiptScreen( } LaunchedEffect(Unit) { - val reprint = isReprintMode() - if (reprint) { + if (isReprint) { currentCopy = ReceiptCopy.CUSTOMER nextCopy = ReceiptCopy.CUSTOMER } - sharedViewModel.isReprint.value = false + onResetReprint() when { - merchant_copy_autoprint && !reprint -> doPrint(ReceiptCopy.MERCHANT) { } + merchant_copy_autoprint && !isReprint -> doPrint(ReceiptCopy.MERCHANT) { } customer_copy_autoprint -> doPrint(ReceiptCopy.CUSTOMER) { } } } @@ -209,6 +235,7 @@ fun ReceiptPreview( copyLabel: String, modifier: Modifier = Modifier ) { + val isPreview = LocalInspectionMode.current Column( modifier = modifier .fillMaxWidth() @@ -246,7 +273,7 @@ fun ReceiptPreview( ReceiptRow("Amount", POSUtil.getInstance().getDecimalAmountSeparatorFormat(state.payDetail?.amount?:0)) ReceiptRow("Card Type", state.payDetail?.accountType.toString()) ReceiptRow("Card No", state.payDetail?.cardNo.toString()) - ReceiptRow("Status", state.payDetail?.let(::displayTransactionStatus).orEmpty()) + ReceiptRow("Status", if (isPreview) "SUCCESS" else state.payDetail?.let(::displayTransactionStatus).orEmpty()) ReceiptRow("Date", state.payDetail?.transDate.toString() ) ReceiptRow("Time", state.payDetail?.transTime.toString()) ReceiptRow("Ref No", state.payDetail?.referNo.toString()) @@ -292,25 +319,62 @@ fun ReceiptRow( @Composable fun ReceiptDivider() { - Text( + Canvas( modifier = Modifier .fillMaxWidth() - .padding(vertical = 10.dp), - text = "--------------------------------", - color = Color.Gray - ) + .padding(vertical = 10.dp) + .height(2.dp) + ) { + // Convert dp to pixels so it scales perfectly on all screen sizes + val dotRadius = 1.5.dp.toPx() + val dotSpacing = 6.dp.toPx() + + val totalWidth = size.width + var currentX = 0f + + // Loop across the width of the screen and draw individual circles + while (currentX < totalWidth) { + drawCircle( + color = Color.Gray, + radius = dotRadius, + center = Offset(x = currentX, y = size.height / 2) + ) + // Move X forward by the size of the dot + the space we want + currentX += (dotRadius * 2) + dotSpacing + } + } } -@Preview(showBackground = true, showSystemUi = true) +@P2Preview +@P3Preview @Composable -fun PreviewPrintReceiptScreen() { - MaterialTheme { - PrintReceiptScreen( - sharedViewModel = hiltViewModel(), - transactionResultViewModel = hiltViewModel(), +private fun PrintReceiptScreenPreview() { + val samplePayDetail = PayDetail().apply { + merchantName = "Sample Merchant" + terminalNo = "12345678" + voucherNo = "000001" + amount = 100000 + cardNo = "1234********5678" + transDate = "2023-10-27" + transTime = "10:30:00" + referNo = "123456789012" + transType = "SALE" + tradeAnswerCode = "00" + } + + val sampleState = TransactionResultState( + payDetail = samplePayDetail + ) + + MOBPOSTheme { + PrintReceiptContent( + state = sampleState, + isReprint = false, onPrint = {}, onDone = {}, - onPrintFinished = {} + onPrintFinished = {}, + onSetPrintStatus = {}, + onResetReprint = {} ) } }