changes
This commit is contained in:
@@ -97,11 +97,8 @@ async function removeCart(cartId) {
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
.tabs a {
|
.tabs a {
|
||||||
background-color: hsl(from var(--bulma-tabs-boxed-link-hover-background-color) h s calc(l + 1));
|
background-color: hsl(from var(--bulma-tabs-boxed-link-hover-background-color) h s calc(l + 1));
|
||||||
--bulma-tabs-link-padding: 0.4em 1em 0.4em 0.5em;
|
|
||||||
&.new {
|
|
||||||
--bulma-tabs-link-padding: 0.4em 0.5em 0.4em 0.5em;
|
--bulma-tabs-link-padding: 0.4em 0.5em 0.4em 0.5em;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.tabs a:hover {
|
.tabs a:hover {
|
||||||
background-color: hsl(from var(--bulma-tabs-boxed-link-hover-background-color) h s calc(l - 2));
|
background-color: hsl(from var(--bulma-tabs-boxed-link-hover-background-color) h s calc(l - 2));
|
||||||
@@ -117,13 +114,13 @@ async function removeCart(cartId) {
|
|||||||
|
|
||||||
.close {
|
.close {
|
||||||
display: none;
|
display: none;
|
||||||
background-color: var(--bulma-white-ter);
|
background-color: transparent;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
li:hover .close {
|
li:hover .close {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
.close:hover {
|
.close:hover {
|
||||||
background-color: var(--bulma-grey-lighter);
|
background-color: hsl(0, 0%, 0%, 0.1);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,49 +1,38 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { without } from "es-toolkit";
|
|
||||||
import Address from "~/components/pos/Address.vue";
|
import Address from "~/components/pos/Address.vue";
|
||||||
import CartItem from "~/components/pos/CartItem.vue";
|
import CartItem from "~/components/pos/CartItem.vue";
|
||||||
import CartTabs from "~/components/pos/CartTabs.vue";
|
import CartTabs from "~/components/pos/CartTabs.vue";
|
||||||
|
import useActiveCart from "~/components/pos/composables/useActiveCart";
|
||||||
|
import useCartData from "~/components/pos/composables/useCartData";
|
||||||
|
import useCustomer from "~/components/pos/composables/useCustomer";
|
||||||
|
import useOrderInfo from "~/components/pos/composables/useOrderInfo";
|
||||||
import SearchBox from "~/components/SearchBox.vue";
|
import SearchBox from "~/components/SearchBox.vue";
|
||||||
|
|
||||||
const store = useStore();
|
const store = useStore();
|
||||||
const { $findapi, $getapi, $getdata, $patchapi, $numtoString } = useNuxtApp();
|
const { $numtoString } = useNuxtApp();
|
||||||
const carts = ref([]);
|
|
||||||
const cartItems = ref([]);
|
|
||||||
const customers = ref([]);
|
|
||||||
const activeCartId = ref();
|
|
||||||
const activeCart = computed(() => carts.value.find((c) => c.id === activeCartId.value));
|
|
||||||
const activeCartItems = computed(() => cartItems.value.filter((ci) => ci.cart === activeCartId.value));
|
|
||||||
const isUpdating = ref(false);
|
|
||||||
|
|
||||||
async function getCarts() {
|
const { carts, cartItems, customers, getCarts, isPending } = useCartData();
|
||||||
const apis = $findapi(["Cart", "Cart_Item", "customer"]);
|
|
||||||
const [cartsRes, cartItemsRes, customersRes] = await $getapi(apis);
|
|
||||||
|
|
||||||
carts.value = cartsRes.data.rows || [];
|
const { activeCartId, activeCart, activeCartItems, customerIdsWithNoCart, subtotal } = useActiveCart({
|
||||||
cartItems.value = cartItemsRes.data.rows || [];
|
carts,
|
||||||
customers.value = customersRes.data.rows || [];
|
cartItems,
|
||||||
}
|
customers,
|
||||||
|
|
||||||
const customerIdsWithNoCart = computed(() => {
|
|
||||||
const cusIds = customers.value.map((c) => c.id);
|
|
||||||
const cusIdsWithCart = carts.value.filter((c) => c.customer).map((c) => c.customer);
|
|
||||||
const cusIdsWithNoCart = without(cusIds, ...cusIdsWithCart);
|
|
||||||
return cusIdsWithNoCart;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(async () => {
|
const { addresses, getAddresses, isChangingCus, changeCustomer } = useCustomer({ activeCart, getCarts });
|
||||||
await getCarts();
|
|
||||||
activeCartId.value = carts.value[0].id;
|
const { orderInfo, isOrderValid } = useOrderInfo({
|
||||||
|
activeCartId,
|
||||||
|
activeCart,
|
||||||
|
activeCartItems,
|
||||||
|
addresses,
|
||||||
|
getAddresses,
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(activeCartId, () => {
|
const showModal = ref();
|
||||||
orderInfo.value.deliveryMethod = null;
|
|
||||||
orderInfo.value.paymentMethod = null;
|
|
||||||
});
|
|
||||||
|
|
||||||
const showProductSelectionModal = ref();
|
|
||||||
function openProductSelectionModal() {
|
function openProductSelectionModal() {
|
||||||
showProductSelectionModal.value = {
|
showModal.value = {
|
||||||
component: "pos/ProductSelection",
|
component: "pos/ProductSelection",
|
||||||
title: "Chọn sản phẩm",
|
title: "Chọn sản phẩm",
|
||||||
width: "85%",
|
width: "85%",
|
||||||
@@ -51,70 +40,8 @@ function openProductSelectionModal() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const orderInfo = ref({
|
|
||||||
address: null,
|
|
||||||
deliveryMethod: null,
|
|
||||||
paymentMethod: null,
|
|
||||||
});
|
|
||||||
const addresses = ref([]);
|
|
||||||
const subtotal = computed(() => {
|
|
||||||
return activeCartItems.value?.reduce((prev, curr) => prev + curr.imei__variant__price, 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
async function getAddresses() {
|
|
||||||
addresses.value = await $getdata("Customer_Address", {
|
|
||||||
filter: { customer: activeCart.value.customer },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
watch(activeCart, async (newVal, oldVal) => {
|
|
||||||
// set order info
|
|
||||||
if (newVal.customer) {
|
|
||||||
await getAddresses();
|
|
||||||
if (!oldVal || !oldVal.customer || oldVal.customer !== newVal.customer) {
|
|
||||||
const defaultAddress = addresses.value.find((add) => add.is_default);
|
|
||||||
orderInfo.value.address = defaultAddress;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
addresses.value = null;
|
|
||||||
orderInfo.value.address = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const isChangingCus = ref(false);
|
|
||||||
async function changeCustomer(cusId) {
|
|
||||||
isChangingCus.value = true;
|
|
||||||
const updatedCart = await $patchapi("Cart", {
|
|
||||||
id: activeCartId.value,
|
|
||||||
customer: cusId,
|
|
||||||
});
|
|
||||||
await getCarts();
|
|
||||||
isChangingCus.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => orderInfo.value.deliveryMethod,
|
|
||||||
(newVal) => {
|
|
||||||
if (newVal?.code === "HOME_DELIVERY") {
|
|
||||||
const defaultAddress = addresses.value.find((add) => add.is_default);
|
|
||||||
orderInfo.value.address = defaultAddress;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const isOrderValid = computed(() => {
|
|
||||||
if (activeCartItems.value?.length === 0) return false;
|
|
||||||
if (!activeCart.value?.customer) return false;
|
|
||||||
if (!orderInfo.value.deliveryMethod) return false;
|
|
||||||
if (!orderInfo.value.paymentMethod) return false;
|
|
||||||
if (orderInfo.value.deliveryMethod.code === "HOME_DELIVERY" && !orderInfo.value.address) return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
const showConfirmModal = ref();
|
|
||||||
function openConfirmModal() {
|
function openConfirmModal() {
|
||||||
showConfirmModal.value = {
|
showModal.value = {
|
||||||
component: "pos/ConfirmOrder",
|
component: "pos/ConfirmOrder",
|
||||||
title: "Xác nhận đơn hàng",
|
title: "Xác nhận đơn hàng",
|
||||||
width: "60%",
|
width: "60%",
|
||||||
@@ -163,7 +90,7 @@ provide("pos", {
|
|||||||
</span>
|
</span>
|
||||||
<span>Giỏ hàng</span>
|
<span>Giỏ hàng</span>
|
||||||
<span
|
<span
|
||||||
v-if="isUpdating"
|
v-if="isPending"
|
||||||
class="icon"
|
class="icon"
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
@@ -385,14 +312,9 @@ provide("pos", {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Modal
|
<Modal
|
||||||
v-if="showProductSelectionModal"
|
v-if="showModal"
|
||||||
v-bind="showProductSelectionModal"
|
v-bind="showModal"
|
||||||
@close="showProductSelectionModal = undefined"
|
@close="showModal = undefined"
|
||||||
/>
|
|
||||||
<Modal
|
|
||||||
v-if="showConfirmModal"
|
|
||||||
v-bind="showConfirmModal"
|
|
||||||
@close="showConfirmModal = undefined"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
31
app/components/pos/composables/useActiveCart.js
Normal file
31
app/components/pos/composables/useActiveCart.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { without } from "es-toolkit";
|
||||||
|
|
||||||
|
export default function useActiveCart({ carts, cartItems, customers }) {
|
||||||
|
const activeCartId = ref();
|
||||||
|
|
||||||
|
const activeCart = computed(() => carts.value.find((c) => c.id === activeCartId.value));
|
||||||
|
const activeCartItems = computed(() => cartItems.value.filter((ci) => ci.cart === activeCartId.value));
|
||||||
|
|
||||||
|
watch(
|
||||||
|
carts,
|
||||||
|
(newVal) => {
|
||||||
|
if (!activeCartId.value && newVal.length) {
|
||||||
|
activeCartId.value = newVal[0].id;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
const customerIdsWithNoCart = computed(() => {
|
||||||
|
const cusIds = customers.value.map((c) => c.id);
|
||||||
|
const cusIdsWithCart = carts.value.filter((c) => c.customer).map((c) => c.customer);
|
||||||
|
const cusIdsWithNoCart = without(cusIds, ...cusIdsWithCart);
|
||||||
|
return cusIdsWithNoCart;
|
||||||
|
});
|
||||||
|
|
||||||
|
const subtotal = computed(() => {
|
||||||
|
return activeCartItems.value?.reduce((prev, curr) => prev + curr.imei__variant__price, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
return { activeCartId, activeCart, activeCartItems, customerIdsWithNoCart, subtotal };
|
||||||
|
}
|
||||||
22
app/components/pos/composables/useCartData.js
Normal file
22
app/components/pos/composables/useCartData.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
export default function useCartData() {
|
||||||
|
const { $findapi, $getapi } = useNuxtApp();
|
||||||
|
const carts = ref([]);
|
||||||
|
const cartItems = ref([]);
|
||||||
|
const customers = ref([]);
|
||||||
|
const isPending = ref(false);
|
||||||
|
|
||||||
|
async function getCarts() {
|
||||||
|
isPending.value = true;
|
||||||
|
const apis = $findapi(["Cart", "Cart_Item", "customer"]);
|
||||||
|
const [cartsRes, cartItemsRes, customersRes] = await $getapi(apis);
|
||||||
|
isPending.value = false;
|
||||||
|
|
||||||
|
carts.value = cartsRes.data.rows || [];
|
||||||
|
cartItems.value = cartItemsRes.data.rows || [];
|
||||||
|
customers.value = customersRes.data.rows || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(getCarts);
|
||||||
|
|
||||||
|
return { carts, cartItems, customers, getCarts, isPending };
|
||||||
|
}
|
||||||
23
app/components/pos/composables/useCustomer.js
Normal file
23
app/components/pos/composables/useCustomer.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
export default function useCustomer({ activeCart, getCarts }) {
|
||||||
|
const { $getdata, $patchapi } = useNuxtApp();
|
||||||
|
|
||||||
|
const addresses = ref([]);
|
||||||
|
async function getAddresses() {
|
||||||
|
addresses.value = await $getdata("Customer_Address", {
|
||||||
|
filter: { customer: activeCart.value.customer },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const isChangingCus = ref(false);
|
||||||
|
async function changeCustomer(cusId) {
|
||||||
|
isChangingCus.value = true;
|
||||||
|
const updatedCart = await $patchapi("Cart", {
|
||||||
|
id: activeCart.value.id,
|
||||||
|
customer: cusId,
|
||||||
|
});
|
||||||
|
await getCarts();
|
||||||
|
isChangingCus.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { addresses, getAddresses, isChangingCus, changeCustomer };
|
||||||
|
}
|
||||||
49
app/components/pos/composables/useOrderInfo.js
Normal file
49
app/components/pos/composables/useOrderInfo.js
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
export default function useOrderInfo({ activeCartId, activeCart, activeCartItems, addresses, getAddresses }) {
|
||||||
|
const orderInfo = ref({
|
||||||
|
address: null,
|
||||||
|
deliveryMethod: null,
|
||||||
|
paymentMethod: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(activeCartId, () => {
|
||||||
|
// reset fields when tab is switched
|
||||||
|
orderInfo.value.deliveryMethod = null;
|
||||||
|
orderInfo.value.paymentMethod = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(activeCart, async (newVal, oldVal) => {
|
||||||
|
// set order info
|
||||||
|
if (newVal?.customer) {
|
||||||
|
await getAddresses();
|
||||||
|
if (!oldVal || !oldVal.customer || oldVal.customer !== newVal.customer) {
|
||||||
|
const defaultAddress = addresses.value.find((add) => add.is_default);
|
||||||
|
orderInfo.value.address = defaultAddress;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
addresses.value = null;
|
||||||
|
orderInfo.value.address = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => orderInfo.value.deliveryMethod,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal?.code === "HOME_DELIVERY") {
|
||||||
|
const defaultAddress = addresses.value.find((add) => add.is_default);
|
||||||
|
orderInfo.value.address = defaultAddress;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const isOrderValid = computed(() => {
|
||||||
|
if (activeCartItems.value?.length === 0) return false;
|
||||||
|
if (!activeCart.value?.customer) return false;
|
||||||
|
if (!orderInfo.value.deliveryMethod) return false;
|
||||||
|
if (!orderInfo.value.paymentMethod) return false;
|
||||||
|
if (orderInfo.value.deliveryMethod.code === "HOME_DELIVERY" && !orderInfo.value.address) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
return { orderInfo, isOrderValid };
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user