- Esporta Lista Carrello (Totale)

- Sconto Applicato
This commit is contained in:
Surya Paolo
2025-06-09 09:48:34 +02:00
parent 664975b1fd
commit 56d1870bc1
17 changed files with 1325 additions and 327 deletions

View File

@@ -47,7 +47,198 @@
.qta{
font-size: 1.15rem;
font-weight: bold;
border-radius: 12px;
padding: 8px;
}
.autori{
font-style: italic;
}
.elimina-btn{
width: 36px;
height: 36px;
border: none;
border-radius: 12px;
background: linear-gradient(135deg, #ff3860, #e61e4d); /*negative gradient */
color: white;
font-size: 1.2rem;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
}
.quantity-btn {
width: 36px;
height: 36px;
border: none;
border-radius: 12px;
background: linear-gradient(135deg, #34c759, #2ecc71); /*positive gradient */
&[data-gradiente="negative"] {
background: linear-gradient(135deg, #ff3860, #e61e4d); /*negative gradient */
}
color: white;
font-size: 1.2rem;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
}
.quantity-btn:hover:not(:disabled) {
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(102, 126, 234, 0.4);
}
.quantity-btn:active {
transform: translateY(0);
}
.quantity-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
transform: none;
}
.quantity-display {
min-width: 60px;
text-align: center;
font-size: 1.4rem;
font-weight: 600;
color: #1f2937;
background: #f8fafc;
border-radius: 12px;
padding: 12px 16px;
border: 2px solid #e2e8f0;
transition: all 0.3s ease;
}
.quantity-display.updating {
transform: scale(1.1);
border-color: #667eea;
background: #eff6ff;
}
.remove-btn {
background: linear-gradient(135deg, #ef4444, #dc2626);
color: white;
border: none;
border-radius: 12px;
padding: 12px 20px;
font-size: 0.9rem;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
margin-left: auto;
}
.remove-btn:hover {
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(239, 68, 68, 0.3);
}
.cart-summary {
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
border-radius: 20px;
padding: 24px;
margin-top: 32px;
text-align: center;
opacity: 1;
transition: all 0.3s ease;
}
.cart-summary.hidden {
opacity: 0;
transform: translateY(20px);
}
.total-amount {
font-size: 2rem;
font-weight: 700;
margin-bottom: 8px;
}
.total-items {
opacity: 0.9;
margin-bottom: 20px;
}
.checkout-btn {
background: rgba(255, 255, 255, 0.2);
border: 2px solid rgba(255, 255, 255, 0.3);
color: white;
padding: 16px 32px;
border-radius: 12px;
font-size: 1.1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
backdrop-filter: blur(10px);
}
.checkout-btn:hover {
background: rgba(255, 255, 255, 0.3);
transform: translateY(-2px);
}
.empty-cart {
text-align: center;
padding: 60px 20px;
color: #6b7280;
opacity: 0;
transition: opacity 0.5s ease;
}
.empty-cart.show {
opacity: 1;
}
.empty-cart i {
font-size: 4rem;
margin-bottom: 20px;
opacity: 0.5;
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
.pulse {
animation: pulse 0.3s ease-in-out;
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.fade-in {
animation: fadeInUp 0.5s ease forwards;
}
@media (max-width: 768px) {
.product-content {
flex-direction: column;
text-align: center;
}
.quantity-controls {
justify-content: center;
}
.remove-btn {
margin: 16px auto 0;
}
}

View File

@@ -1,16 +1,16 @@
import { tools } from '../../store/Modules/tools'
import { CCardState } from '../CCardState'
import { CCopyBtn } from '../CCopyBtn'
import { tools } from '../../store/Modules/tools';
import { CCardState } from '../CCardState';
import { CCopyBtn } from '../CCopyBtn';
import type { IOrder} from '@src/model';
import { IOperators, IProduct } from '@src/model'
import type { PropType} from 'vue';
import { defineComponent, toRef, ref, watch, onMounted } from 'vue'
import { CTitleBanner } from '@src/components/CTitleBanner'
import { useProducts } from '@store/Products'
import { useI18n } from 'vue-i18n'
import { useQuasar } from 'quasar'
import { loadRouteLocation } from 'vue-router'
import type { IOrder } from '@src/model';
import { IOperators, IProduct } from '@src/model';
import type { PropType } from 'vue';
import { defineComponent, toRef, ref, watch, onMounted } from 'vue';
import { CTitleBanner } from '@src/components/CTitleBanner';
import { useProducts } from '@store/Products';
import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar';
import { loadRouteLocation } from 'vue-router';
export default defineComponent({
name: 'CSingleCart',
@@ -42,11 +42,11 @@ export default defineComponent({
},
components: { CTitleBanner, CCardState, CCopyBtn },
setup(props, { emit }) {
const products = useProducts()
const order = toRef(props, 'order')
const { t } = useI18n()
const products = useProducts();
const order = toRef(props, 'order');
const { t } = useI18n();
const $q = useQuasar()
const $q = useQuasar();
const orderQuantity = ref(<number | undefined>undefined);
const weight = ref(<number | undefined>undefined);
@@ -54,161 +54,179 @@ export default defineComponent({
const orderQuantityPreordered = ref(<number | undefined>undefined);
const orderTotalPriceProduct = ref(<number | undefined>undefined);
const enableQty = ref(false)
const endload = ref(false)
const enableQtyPreordered = ref(false)
const enableChangeTotalPrice = ref(false)
const enableQty = ref(false);
const endload = ref(false);
const enableQtyPreordered = ref(false);
const enableChangeTotalPrice = ref(false);
watch(orderQuantity, (newValue: any) => {
if (!newValue)
order.value.quantity = 0
else
order.value.quantity = parseFloat(newValue);
if (!newValue) order.value.quantity = 0;
else order.value.quantity = parseFloat(newValue);
enableChangeTotalPrice.value = false
enableChangeTotalPrice.value = false;
});
watch(weight, (newValue: any) => {
if (order.value.product) {
if (!newValue)
order.value.product.productInfo.weight = 0
else
order.value.product.productInfo.weight = parseFloat(newValue);
if (!newValue) order.value.product.productInfo.weight = 0;
else order.value.product.productInfo.weight = parseFloat(newValue);
}
enableChangeTotalPrice.value = false
enableChangeTotalPrice.value = false;
});
watch(price, (newValue: any) => {
if (order.value) {
if (!newValue)
order.value.price = 0
else
order.value.price = parseFloat(newValue);
if (!newValue) order.value.price = 0;
else order.value.price = parseFloat(newValue);
}
enableChangeTotalPrice.value = false
enableChangeTotalPrice.value = false;
});
watch(orderQuantityPreordered, (newValue: any) => {
if (!newValue)
order.value.quantitypreordered = 0
else
order.value.quantitypreordered = parseFloat(newValue);
if (!newValue) order.value.quantitypreordered = 0;
else order.value.quantitypreordered = parseFloat(newValue);
enableChangeTotalPrice.value = false
enableChangeTotalPrice.value = false;
});
watch(orderTotalPriceProduct, (newValue: any) => {
if (!newValue)
order.value.TotalPriceProduct = 0
else
order.value.TotalPriceProduct = parseFloat(newValue);
if (!newValue) order.value.TotalPriceProduct = 0;
else order.value.TotalPriceProduct = parseFloat(newValue);
});
watch(() => props.order.TotalPriceProduct, (newValue: any) => {
if (!newValue)
orderTotalPriceProduct.value = 0
else
orderTotalPriceProduct.value = parseFloat(newValue);
});
watch(
() => props.order.TotalPriceProduct,
(newValue: any) => {
if (!newValue) orderTotalPriceProduct.value = 0;
else orderTotalPriceProduct.value = parseFloat(newValue);
}
);
function myimgclass() {
if (props.showall) {
return 'imgNormal'
return 'imgNormal';
} else {
return 'imgSmall'
return 'imgSmall';
}
}
function qtyInCart() {
return props.order.quantity + props.order.quantitypreordered;
}
async function addsubqty(addqty: boolean, subqty: boolean) {
if (products.isQtyAvailableByOrder(props.order)) {
if (addqty) {
if (props.order.quantity >= 100)
return false
if (props.order.quantity >= 100) return false;
}
if (subqty) {
if (props.order.quantity === 0)
return false
if (props.order.quantity === 0) return false;
}
} else {
if (products.isInPreorderByOrder(props.order)) {
if (addqty) {
if (props.order.quantitypreordered >= 100)
return false
if (props.order.quantitypreordered >= 100) return false;
}
if (subqty) {
if (props.order.quantitypreordered === 0)
return false
if (props.order.quantitypreordered === 0) return false;
}
}
}
return await products.addSubQtyToItem({
addqty,
subqty,
order: props.order,
}).then((res: any) => {
if (res.risult) {
if (res.myord) {
order.value.quantity = res.myord.quantity
order.value.quantitypreordered = res.myord.quantitypreordered
return await products
.addSubQtyToItem({
addqty,
subqty,
order: props.order,
})
.then((res: any) => {
if (res.risult) {
if (res.myord) {
order.value.quantity = res.myord.quantity;
order.value.quantitypreordered = res.myord.quantitypreordered;
}
}
}
})
});
}
function isApplicatoSconto() {
const totalipotetico = order.value.product!.price * (order.value.quantity + order.value.quantitypreordered)
const totalipotetico =
order.value.product!.price *
(order.value.quantity + order.value.quantitypreordered);
if (totalipotetico.toFixed(2) > order.value.TotalPriceProduct.toFixed(2)) {
return true
return true;
}
return false
return false;
}
function removeFromCard() {
products.removeFromCart({ order: order.value })
$q.dialog({
title: order.value.product.productInfo.name,
message: 'Sicuro di voler rimuovere il prodotto dal carrello?',
ok: {
label: 'Rimuovi',
color: 'negative',
rounded: true,
},
cancel: {
label: 'Annulla',
color: 'primary',
rounded: true,
},
}).onOk(() => {
products.removeFromCart({ order: order.value });
});
}
async function updateOrder(paramstoupdate: any) {
endload.value = false
endload.value = false;
if (enableChangeTotalPrice.value) {
paramstoupdate = { ...paramstoupdate, TotalPriceProduct: order.value.TotalPriceProduct }
paramstoupdate = {
...paramstoupdate,
TotalPriceProduct: order.value.TotalPriceProduct,
};
}
const myOrdersCart = await products.updateOrderByOrder(props.idOrdersCart, order.value._id, paramstoupdate)
emit('update')
mounted()
const myOrdersCart = await products.updateOrderByOrder(
props.idOrdersCart,
order.value._id,
paramstoupdate
);
emit('update');
mounted();
}
function getRisparmio(): string {
return ((order.value.product!.price * order.value.quantity) - order.value.TotalPriceProduct).toFixed(2)
return (
order.value.product!.price * order.value.quantity -
order.value.TotalPriceProduct
).toFixed(2);
}
function mounted() {
endload.value = false
weight.value = props.order.product?.productInfo.weight
price.value = props.order.price
endload.value = false;
weight.value = props.order.product?.productInfo.weight;
price.value = props.order.price;
if (props.order.quantity !== 0) {
orderQuantity.value = props.order.quantity
enableQty.value = true
orderQuantity.value = props.order.quantity;
enableQty.value = true;
}
if (props.order.quantitypreordered !== 0) {
orderQuantityPreordered.value = props.order.quantitypreordered
enableQtyPreordered.value = true
orderQuantityPreordered.value = props.order.quantitypreordered;
enableQtyPreordered.value = true;
}
orderTotalPriceProduct.value = props.order.TotalPriceProduct
endload.value = true
orderTotalPriceProduct.value = props.order.TotalPriceProduct;
endload.value = true;
}
function changeTotalPrice() {
console.log('changeTotalPrice')
enableChangeTotalPrice.value = true
console.log('changeTotalPrice');
enableChangeTotalPrice.value = true;
}
onMounted(mounted)
onMounted(mounted);
return {
myimgclass,
@@ -229,6 +247,7 @@ export default defineComponent({
changeTotalPrice,
orderTotalPriceProduct,
endload,
}
qtyInCart,
};
},
})
});

View File

@@ -86,26 +86,30 @@
<div class="row q-mb-xs no-wrap items-center centeritems">
<q-btn
v-if="showall && !nomodif && products.CanDeleteIfSub(order)"
icon="fas fa-trash"
color="negative"
icon="fas fa-trash-alt"
round
size="xs"
size="sm"
class="elimina-btn"
@click="removeFromCard"
>
</q-btn>
<q-btn
v-else-if="showall && !nomodif"
:disable="!products.enableSubQty(order)"
size="sm"
icon="fas fa-cart-arrow-down"
:color="products.enableSubQty(order) ? 'negative' : 'grey'"
@click="addsubqty(false, true)"
rounded
:label="
<!--
:label="
t('products.subcart', {
qta: products.qtaNextSub(order, order.product),
})
"
-->
<q-btn
v-else-if="!nomodif"
:disable="!products.enableSubQty(order)"
size="sm"
class="quantity-btn"
data-gradiente="negative"
:icon="qtyInCart() === 1 ? 'fas fa-trash': 'fas fa-minus'"
:color="products.enableSubQty(order) ? undefined : 'grey'"
@click="qtyInCart() === 1 ? removeFromCard(): addsubqty(false, true)"
rounded
></q-btn>
<div v-if="editmode">
<q-input
@@ -115,6 +119,7 @@
debounce="500"
borderless
rounded
class="quantity-display"
dense
:label="t('products.quantity')"
></q-input>
@@ -124,6 +129,7 @@
autofocus
debounce="500"
borderless
class="quantity-display"
rounded
densep
:label="t('ecomm.preord')"
@@ -159,24 +165,25 @@
</q-btn>
</div>
<div
v-else-if="showall"
v-else
:class="`q-mx-sm text-blue-14 qta`"
>
{{ order.quantity + order.quantitypreordered }}
</div>
<q-btn
v-if="showall && !nomodif"
icon-right="fas fa-cart-plus"
color="positive"
:disable="!products.enableAddQty(order, order.product)"
rounded
size="sm"
:label="
<!-- :label="
t('products.addcart', {
qta: products.qtaNextAdd(order, order.product),
})
"
-->
<q-btn
v-if="!nomodif"
icon-right="fas fa-plus"
class="quantity-btn"
:disable="!products.enableAddQty(order, order.product)"
rounded
size="sm"
@click="addsubqty(true, false)"
>
</q-btn>
@@ -229,7 +236,7 @@
</div>
</q-item-label>
</q-item-section>
<q-item-section side>
<!--<q-item-section side>
<q-item-label>
<div class="col-2">
<q-btn
@@ -243,7 +250,7 @@
</q-btn>
</div>
</q-item-label>
</q-item-section>
</q-item-section>-->
<!--<q-item-section side top>
<q-item-label caption>meta</q-item-label>