[Update] Cetak barcode
This commit is contained in:
parent
e54a021b98
commit
e1639109c8
@ -69,32 +69,7 @@
|
|||||||
class="fixed inset-0 bg-black/75 flex items-center justify-center p-4 z-50 backdrop-blur-sm">
|
class="fixed inset-0 bg-black/75 flex items-center justify-center p-4 z-50 backdrop-blur-sm">
|
||||||
<div
|
<div
|
||||||
class="bg-white rounded-xl shadow-lg max-w-sm w-full p-6 relative transform transition-all duration-300 scale-95 opacity-0 animate-fadeIn">
|
class="bg-white rounded-xl shadow-lg max-w-sm w-full p-6 relative transform transition-all duration-300 scale-95 opacity-0 animate-fadeIn">
|
||||||
<!-- QR Code -->
|
<PrintBarcode :code="selectedItem?.kode_item" :item="selectedItem?.produk" />
|
||||||
<div class="flex justify-center mb-4">
|
|
||||||
<div class="p-2 border border-C rounded-lg">
|
|
||||||
<img :src="qrCodeUrl" alt="QR Code" class="w-36 h-36" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Info Produk -->
|
|
||||||
<div class="text-center text-D font-bold text-lg mb-1">
|
|
||||||
{{ selectedItem?.kode_item }}
|
|
||||||
</div>
|
|
||||||
<div class="text-center text-gray-700 font-medium mb-1">
|
|
||||||
{{ selectedItem?.produk?.nama }}
|
|
||||||
</div>
|
|
||||||
<div class="text-center text-gray-500 text-sm mb-4">
|
|
||||||
{{ selectedItem?.produk?.kategori }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Tombol Cetak -->
|
|
||||||
<div class="flex justify-center gap-2 mb-4">
|
|
||||||
<button @click="printQR" class="bg-D text-A px-4 py-2 rounded hover:bg-D/80 transition"
|
|
||||||
title="Cetak menggunakan printer browser">
|
|
||||||
<i class="fas fa-print mr-2"></i>
|
|
||||||
Print
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Dropdown pilih nampan -->
|
<!-- Dropdown pilih nampan -->
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
@ -173,6 +148,7 @@
|
|||||||
import { ref, computed, onMounted } from "vue";
|
import { ref, computed, onMounted } from "vue";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import ConfirmDeleteModal from './ConfirmDeleteModal.vue';
|
import ConfirmDeleteModal from './ConfirmDeleteModal.vue';
|
||||||
|
import PrintBarcode from './PrintBarcode.vue';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
search: {
|
search: {
|
||||||
@ -203,15 +179,6 @@ const confirmModalMessage = ref("");
|
|||||||
const confirmText = ref("Ya, Konfirmasi");
|
const confirmText = ref("Ya, Konfirmasi");
|
||||||
const cancelText = ref("Batal");
|
const cancelText = ref("Batal");
|
||||||
|
|
||||||
// QR Code generator
|
|
||||||
const qrCodeUrl = computed(() => {
|
|
||||||
if (selectedItem.value) {
|
|
||||||
const data = selectedItem.value.kode_item;
|
|
||||||
return `https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=${encodeURIComponent(data)}`;
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
});
|
|
||||||
|
|
||||||
// Computed untuk statistik
|
// Computed untuk statistik
|
||||||
const totalWeight = computed(() => {
|
const totalWeight = computed(() => {
|
||||||
const total = filteredItems.value.reduce((sum, item) => {
|
const total = filteredItems.value.reduce((sum, item) => {
|
||||||
@ -252,13 +219,6 @@ const confirmDelete = async () => {
|
|||||||
await axios.delete(`/api/item/${selectedItem.value.id}`, {
|
await axios.delete(`/api/item/${selectedItem.value.id}`, {
|
||||||
headers: { Authorization: `Bearer ${localStorage.getItem("token")}` },
|
headers: { Authorization: `Bearer ${localStorage.getItem("token")}` },
|
||||||
});
|
});
|
||||||
|
|
||||||
// Tampilkan alert sukses
|
|
||||||
alert.value = { success: `Item ${selectedItem.value.kode_item} berhasil dihapus.` };
|
|
||||||
|
|
||||||
// Refresh data
|
|
||||||
await refreshData();
|
|
||||||
|
|
||||||
// Tutup modal & popup
|
// Tutup modal & popup
|
||||||
showDeleteConfirm.value = false;
|
showDeleteConfirm.value = false;
|
||||||
closePopup();
|
closePopup();
|
||||||
@ -330,106 +290,6 @@ const handleConfirmAction = async () => {
|
|||||||
closeConfirmModal();
|
closeConfirmModal();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Print QR menggunakan browser
|
|
||||||
const printQR = () => {
|
|
||||||
if (qrCodeUrl.value && selectedItem.value) {
|
|
||||||
const printWindow = window.open('', '_blank');
|
|
||||||
const itemCode = selectedItem.value.kode_item;
|
|
||||||
|
|
||||||
printWindow.document.write(`
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Print QR Code - ${itemCode}</title>
|
|
||||||
<style>
|
|
||||||
@page {
|
|
||||||
size: 38mm 25mm;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
* {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
font-family: Arial, sans-serif;
|
|
||||||
width: 38mm;
|
|
||||||
height: 25mm;
|
|
||||||
padding: 2mm;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.qr-container {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.qr-img {
|
|
||||||
width: 18mm;
|
|
||||||
height: 18mm;
|
|
||||||
margin-bottom: 1mm;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-code {
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 8pt;
|
|
||||||
margin-bottom: 0.5mm;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
max-width: 34mm;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-name {
|
|
||||||
font-size: 6pt;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
max-width: 34mm;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-weight {
|
|
||||||
font-size: 6pt;
|
|
||||||
color: #666;
|
|
||||||
margin-top: 0.5mm;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media print {
|
|
||||||
body {
|
|
||||||
-webkit-print-color-adjust: exact;
|
|
||||||
print-color-adjust: exact;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="qr-container">
|
|
||||||
<img id="qr-img" class="qr-img" src="${qrCodeUrl.value}" alt="QR Code" />
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
`);
|
|
||||||
|
|
||||||
printWindow.document.close();
|
|
||||||
|
|
||||||
const img = printWindow.document.getElementById("qr-img");
|
|
||||||
img.onload = () => {
|
|
||||||
printWindow.focus();
|
|
||||||
printWindow.print();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleImageError = (event) => {
|
const handleImageError = (event) => {
|
||||||
event.target.style.display = 'none';
|
event.target.style.display = 'none';
|
||||||
};
|
};
|
||||||
|
|||||||
@ -35,9 +35,7 @@
|
|||||||
|
|
||||||
<!-- QR Code -->
|
<!-- QR Code -->
|
||||||
<div class="flex justify-center mb-4">
|
<div class="flex justify-center mb-4">
|
||||||
<div class="p-2 border border-gray-300 rounded-lg">
|
<PrintBarcode :code="createdItem?.kode_item" :item="product"/>
|
||||||
<img :src="qrCodeUrl" alt="QR Code" class="w-36 h-36" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Item Info -->
|
<!-- Item Info -->
|
||||||
@ -53,10 +51,6 @@
|
|||||||
class="flex-1 px-6 py-2 bg-gray-400 hover:bg-gray-500 text-white rounded-lg transition-colors">
|
class="flex-1 px-6 py-2 bg-gray-400 hover:bg-gray-500 text-white rounded-lg transition-colors">
|
||||||
Selesai
|
Selesai
|
||||||
</button>
|
</button>
|
||||||
<button @click="printQR"
|
|
||||||
class="flex-1 px-6 py-2 bg-C hover:bg-B text-D rounded-lg transition-colors">
|
|
||||||
<i class="fas fa-print mr-1"></i>Print
|
|
||||||
</button>
|
|
||||||
<button @click="addNewItem"
|
<button @click="addNewItem"
|
||||||
class="flex-1 px-6 py-2 bg-C hover:bg-B text-D rounded-lg transition-colors">
|
class="flex-1 px-6 py-2 bg-C hover:bg-B text-D rounded-lg transition-colors">
|
||||||
Buat Lagi
|
Buat Lagi
|
||||||
@ -69,10 +63,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import Modal from './Modal.vue';
|
import Modal from './Modal.vue';
|
||||||
import InputSelect from './InputSelect.vue';
|
import InputSelect from './InputSelect.vue';
|
||||||
|
import PrintBarcode from './PrintBarcode.vue';
|
||||||
|
|
||||||
// Props
|
// Props
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -99,15 +94,7 @@ const success = ref(false);
|
|||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const createdItem = ref(null);
|
const createdItem = ref(null);
|
||||||
|
|
||||||
// QR Code generator - berdasarkan logika dari brankas list
|
// QR Code rendering/printing moved to PrintBarcode component
|
||||||
const qrCodeUrl = computed(() => {
|
|
||||||
if (createdItem.value && props.product) {
|
|
||||||
const kode_item = createdItem.value.kode_item;
|
|
||||||
const data = kode_item;
|
|
||||||
return `https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=${encodeURIComponent(data)}`;
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
@ -174,105 +161,6 @@ const addNewItem = () => {
|
|||||||
createdItem.value = null;
|
createdItem.value = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fungsi print berdasarkan logika dari brankas list
|
|
||||||
const printQR = () => {
|
|
||||||
if (qrCodeUrl.value && createdItem.value && props.product) {
|
|
||||||
const printWindow = window.open('', '_blank');
|
|
||||||
const itemCode = createdItem.value.kode_item;
|
|
||||||
|
|
||||||
printWindow.document.write(`
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Print QR Code - ${itemCode}</title>
|
|
||||||
<style>
|
|
||||||
@page {
|
|
||||||
size: 38mm 25mm;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
* {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
font-family: Arial, sans-serif;
|
|
||||||
width: 38mm;
|
|
||||||
height: 25mm;
|
|
||||||
padding: 2mm;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.qr-container {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.qr-img {
|
|
||||||
width: 18mm;
|
|
||||||
height: 18mm;
|
|
||||||
margin-bottom: 1mm;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-code {
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 8pt;
|
|
||||||
margin-bottom: 0.5mm;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
max-width: 34mm;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-name {
|
|
||||||
font-size: 6pt;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
max-width: 34mm;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-weight {
|
|
||||||
font-size: 6pt;
|
|
||||||
color: #666;
|
|
||||||
margin-top: 0.5mm;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media print {
|
|
||||||
body {
|
|
||||||
-webkit-print-color-adjust: exact;
|
|
||||||
print-color-adjust: exact;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="qr-container">
|
|
||||||
<img id="qr-img" class="qr-img" src="${qrCodeUrl.value}" alt="QR Code" />
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
`);
|
|
||||||
|
|
||||||
printWindow.document.close();
|
|
||||||
|
|
||||||
const img = printWindow.document.getElementById("qr-img");
|
|
||||||
img.onload = () => {
|
|
||||||
printWindow.focus();
|
|
||||||
printWindow.print();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
// Reset state
|
// Reset state
|
||||||
|
|||||||
@ -55,7 +55,7 @@ const sizeClass = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const handleOverlayClick = () => {
|
const handleOverlayClick = () => {
|
||||||
if (clickOutside.value) {
|
if (props.clickOutside.value) {
|
||||||
emit('close')
|
emit('close')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
141
resources/js/components/PrintBarcode.vue
Normal file
141
resources/js/components/PrintBarcode.vue
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
<template>
|
||||||
|
<div class="text-center">
|
||||||
|
<div class="p-2 border rounded-lg inline-block">
|
||||||
|
<img :src="barcodeUrl" alt="Barcode" class="w-36 h-12" id="barcode-img" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="item.nama" class="mt-2 text-sm text-gray-700 font-medium">
|
||||||
|
{{ item.nama }}
|
||||||
|
(<span v-if="item.berat" class="mt-1 text-xs text-gray-500">{{ item.berat }} g</span>)
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex justify-center mt-3">
|
||||||
|
<button @click="printBarcode" class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-400 transition">
|
||||||
|
<i class="fas fa-print mr-2"></i>Cetak
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
code: { type: String, required: true },
|
||||||
|
item: { type: Object, required: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
const barcodeUrl = computed(() => {
|
||||||
|
if (!props.code) return '';
|
||||||
|
// Using bwip-js API for Code128 barcode
|
||||||
|
return `https://bwipjs-api.metafloor.com/?bcid=code128&text=${encodeURIComponent(props.code)}&scale=2`;
|
||||||
|
});
|
||||||
|
|
||||||
|
const printBarcode = () => {
|
||||||
|
if (!barcodeUrl.value || !props.code) return;
|
||||||
|
|
||||||
|
const printWindow = window.open('', '_blank');
|
||||||
|
const kode = props.code || 'N/A';
|
||||||
|
const nama = props.item.nama || 'N/A';
|
||||||
|
const berat = props.item.berat ? `(${props.item.berat} g)` : '';
|
||||||
|
|
||||||
|
printWindow.document.write(`
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Print Barcode - ${kode}</title>
|
||||||
|
<style>
|
||||||
|
@page {
|
||||||
|
size: 38mm 25mm;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
width: 38mm;
|
||||||
|
height: 25mm;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
display: flex;
|
||||||
|
width: 38mm;
|
||||||
|
height: 25mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.barcode-container {
|
||||||
|
width: 19mm;
|
||||||
|
height: 25mm;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.barcode-img {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
transform-origin: center;
|
||||||
|
max-height: 19mm;
|
||||||
|
max-width: 23mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.details-container {
|
||||||
|
width: 19mm;
|
||||||
|
height: 25mm;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-name {
|
||||||
|
display: block;
|
||||||
|
width: 23mm;
|
||||||
|
transform: rotate(270deg);
|
||||||
|
transform-origin: center;
|
||||||
|
font-size: 6pt;
|
||||||
|
line-height: 1.1;
|
||||||
|
text-align: left;
|
||||||
|
white-space: normal;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="label">
|
||||||
|
<div class="barcode-container">
|
||||||
|
<img id="barcode-img" class="barcode-img"
|
||||||
|
src="${barcodeUrl.value}" alt="Barcode" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="details-container">
|
||||||
|
<div class="item-name">${nama} ${berat}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`);
|
||||||
|
|
||||||
|
printWindow.document.close();
|
||||||
|
|
||||||
|
const img = printWindow.document.getElementById('barcode-img');
|
||||||
|
if (img) {
|
||||||
|
img.onload = () => {
|
||||||
|
printWindow.focus();
|
||||||
|
printWindow.print();
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// Fallback
|
||||||
|
printWindow.focus();
|
||||||
|
printWindow.print();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@ -86,24 +86,7 @@
|
|||||||
<!-- Pop-up pindah item -->
|
<!-- Pop-up pindah item -->
|
||||||
<div v-if="isPopupVisible" class="fixed inset-0 bg-black/50 flex items-center justify-center p-4 z-50">
|
<div v-if="isPopupVisible" class="fixed inset-0 bg-black/50 flex items-center justify-center p-4 z-50">
|
||||||
<div class="bg-white rounded-xl shadow-lg max-w-sm w-full p-6 relative">
|
<div class="bg-white rounded-xl shadow-lg max-w-sm w-full p-6 relative">
|
||||||
<div class="flex justify-center mb-2">
|
<PrintBarcode :code="selectedItem.kode_item" :item="selectedItem.produk" />
|
||||||
<div class="p-2 border rounded-lg">
|
|
||||||
<img :src="qrCodeUrl" alt="QR Code" class="w-36 h-36" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="text-center text-D font-bold text-lg">
|
|
||||||
{{ selectedItem.kode_item }}
|
|
||||||
</div>
|
|
||||||
<div class="text-center text-gray-700 font-medium mb-3">
|
|
||||||
{{ selectedItem.produk.nama }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex justify-center mb-4">
|
|
||||||
<button @click="printQR" class="bg-D text-A px-4 py-2 rounded hover:bg-D/80 transition">
|
|
||||||
<i class="fas fa-print mr-2"></i>Cetak
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Dropdown -->
|
<!-- Dropdown -->
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
@ -148,6 +131,7 @@ import { ref, onMounted, computed } from "vue";
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import InputSelect from "./InputSelect.vue";
|
import InputSelect from "./InputSelect.vue";
|
||||||
import ConfirmDeleteModal from './ConfirmDeleteModal.vue';
|
import ConfirmDeleteModal from './ConfirmDeleteModal.vue';
|
||||||
|
import PrintBarcode from './PrintBarcode.vue';
|
||||||
|
|
||||||
const isAdmin = localStorage.getItem("role") === "owner";
|
const isAdmin = localStorage.getItem("role") === "owner";
|
||||||
|
|
||||||
@ -167,113 +151,6 @@ const selectedItem = ref(null);
|
|||||||
const selectedTrayId = ref("");
|
const selectedTrayId = ref("");
|
||||||
const showDeleteConfirm = ref(false);
|
const showDeleteConfirm = ref(false);
|
||||||
|
|
||||||
// QR Code generator
|
|
||||||
const qrCodeUrl = computed(() => {
|
|
||||||
if (selectedItem.value) {
|
|
||||||
const data = selectedItem.value.kode_item;
|
|
||||||
return `https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=${encodeURIComponent(data)}`;
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
});
|
|
||||||
|
|
||||||
const printQR = () => {
|
|
||||||
if (qrCodeUrl.value && selectedItem.value) {
|
|
||||||
const printWindow = window.open('', '_blank');
|
|
||||||
const itemCode = selectedItem.value.kode_item;
|
|
||||||
|
|
||||||
printWindow.document.write(`
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Print QR Code - ${itemCode}</title>
|
|
||||||
<style>
|
|
||||||
@page {
|
|
||||||
size: 38mm 25mm;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
* {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
font-family: Arial, sans-serif;
|
|
||||||
width: 38mm;
|
|
||||||
height: 25mm;
|
|
||||||
padding: 2mm;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.qr-container {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.qr-img {
|
|
||||||
width: 18mm;
|
|
||||||
height: 18mm;
|
|
||||||
margin-bottom: 1mm;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-code {
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 8pt;
|
|
||||||
margin-bottom: 0.5mm;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
max-width: 34mm;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-name {
|
|
||||||
font-size: 6pt;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
max-width: 34mm;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-weight {
|
|
||||||
font-size: 6pt;
|
|
||||||
color: #666;
|
|
||||||
margin-top: 0.5mm;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media print {
|
|
||||||
body {
|
|
||||||
-webkit-print-color-adjust: exact;
|
|
||||||
print-color-adjust: exact;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="qr-container">
|
|
||||||
<img id="qr-img" class="qr-img" src="${qrCodeUrl.value}" alt="QR Code" />
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
`);
|
|
||||||
|
|
||||||
printWindow.document.close();
|
|
||||||
|
|
||||||
const img = printWindow.document.getElementById("qr-img");
|
|
||||||
img.onload = () => {
|
|
||||||
printWindow.focus();
|
|
||||||
printWindow.print();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const confirmDelete = async () => {
|
const confirmDelete = async () => {
|
||||||
if (!selectedItem.value) return;
|
if (!selectedItem.value) return;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user