fix: add page cart

This commit is contained in:
2026-03-25 15:56:52 +01:00
parent 8f37ecbac2
commit fef83eb46b
10 changed files with 548 additions and 101 deletions

3
bo/components.d.ts vendored
View File

@@ -12,6 +12,7 @@ export {}
declare module 'vue' {
export interface GlobalComponents {
Cart1: typeof import('./src/components/customer/Cart1.vue')['default']
CartSelector: typeof import('./src/components/customer/CartSelector.vue')['default']
CategoryMenu: typeof import('./src/components/inner/categoryMenu.vue')['default']
Cs_PrivacyPolicyView: typeof import('./src/components/terms/cs_PrivacyPolicyView.vue')['default']
Cs_TermsAndConditionsView: typeof import('./src/components/terms/cs_TermsAndConditionsView.vue')['default']
@@ -20,6 +21,8 @@ declare module 'vue' {
LangSwitch: typeof import('./src/components/inner/langSwitch.vue')['default']
PageAddresses: typeof import('./src/components/customer/PageAddresses.vue')['default']
PageCart: typeof import('./src/components/customer/PageCart.vue')['default']
PageCarts: typeof import('./src/components/customer/PageCarts.vue')['default']
PageCheckout: typeof import('./src/components/customer/PageCheckout.vue')['default']
PageCreateAccount: typeof import('./src/components/customer/PageCreateAccount.vue')['default']
PageCustomerData: typeof import('./src/components/customer/PageCustomerData.vue')['default']
PageProductCardFull: typeof import('./src/components/customer/PageProductCardFull.vue')['default']

View File

@@ -34,11 +34,8 @@ const authStore = useAuthStore()
<RouterLink :to="{ name: 'customer-data' }">
Customer Data
</RouterLink>
<RouterLink :to="{ name: 'cart' }">
Cart
</RouterLink>
<RouterLink :to="{ name: 'cart1' }">
Cart1
<RouterLink :to="{ name: 'carts' }">
Carts
</RouterLink>
<div class="flex items-center gap-2">
<!-- Language Switcher -->

View File

@@ -122,3 +122,4 @@ function goToProduct(productId: number) {
})
}
</script>

View File

@@ -1,74 +0,0 @@
<template>
<component :is="Default || 'div'">
<div class="container mx-auto mt-20">
<h2
class="font-semibold text-black dark:text-white pb-6 text-2xl">
{{ t('Cart Items') }}
</h2>
<div
class="bg-(--second-light) dark:bg-(--main-dark) rounded-lg border border-(--border-light) dark:border-(--border-dark) overflow-hidden">
<div v-if="cartStore.items.length > 0" class="divide-y divide-(--border-light) dark:divide-(--border-dark)">
<div v-for="item in cartStore.items" :key="item.id" class="flex items-center justify-between p-4 gap-4">
<div class="grid grid-cols-5 w-[100%]">
<div
class="w-20 bg-(--second-light) dark:bg-(--main-dark) rounded flex items-center justify-center overflow-hidden">
<img v-if="item.image" :src="item.image" :alt="item.name" class="w-full h-full object-cover" />
<UIcon v-else name="mdi:package-variant" class="text-xl text-gray-400" />
</div>
<p class="text-black dark:text-white text-sm font-medium truncate">{{ item.name }}</p>
<p class="text-black dark:text-white text-sm font-medium truncate">{{ item.product_number }}</p>
<p class="text-black dark:text-white font-medium">${{ (item.price * item.quantity).toFixed(2) }}</p>
<div class="flex items-center justify-end gap-10">
<UInputNumber v-model="item.quantity" class="text-gray-500 dark:text-gray-400 text-sm" />
<div class="flex justify-center">
<button @click="removeItem(item.id)"
class="p-2 text-red-500 bg-red-100 dark:bg-(--main-dark) rounded transition-colors"
:title="t('Remove')">
<UIcon name="material-symbols:delete" class="text-[20px]" />
</button>
</div>
</div>
</div>
</div>
</div>
<div v-else class="p-8 text-center">
<UIcon name="mdi:cart-outline" class="text-5xl text-gray-300 dark:text-gray-600 mb-4 mx-auto" />
<p class="text-gray-500 dark:text-gray-400">{{ t('Your cart is empty') }}</p>
</div>
</div>
<div v-if="cartStore.items.length > 0" class="flex gap-4 justify-end items-center pt-6">
<UButton color="primary" @click="handleContinueToCheckout"
class="bg-(--accent-blue-light) dark:bg-(--accent-blue-dark) text-white hover:bg-(--accent-blue-dark) dark:hover:bg-(--accent-blue-light)">
{{ t('Continue to Checkout') }}
</UButton>
<UButton variant="outline" color="neutral" @click="handleCancel"
class="text-black dark:text-white border-(--border-light) dark:border-(--border-dark) hover:bg-gray-100 dark:hover:bg-gray-700">
{{ t('Cancel') }}
</UButton>
</div>
</div>
</component>
</template>
<script setup lang="ts">
import { useCartStore } from '@/stores/cart'
import { ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { useRouter } from 'vue-router'
import Default from '@/layouts/default.vue'
const cartStore = useCartStore()
const { t } = useI18n()
const router = useRouter()
function handleCancel() {
router.back()
}
function handleContinueToCheckout() {
router.push({ name: 'cart' })
}
function removeItem(itemId: number) {
cartStore.removeItem(itemId)
}
</script>

View File

@@ -0,0 +1,233 @@
<template>
<div class="relative">
<button
@click="toggleDropdown"
class="flex items-center gap-2 px-4 py-2 bg-(--second-light) dark:bg-(--main-dark) border border-(--border-light) dark:border-(--border-dark) rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors"
>
<UIcon name="mdi:cart" class="text-lg" />
<span class="text-black dark:text-white font-medium">{{ activeCartName }}</span>
<UIcon :name="isOpen ? 'mdi:chevron-up' : 'mdi:chevron-down'" class="text-lg" />
</button>
<div
v-if="isOpen"
class="absolute top-full right-0 mt-2 w-64 bg-white dark:bg-gray-800 border border-(--border-light) dark:border-(--border-dark) rounded-lg shadow-lg z-50"
>
<div class="divide-y divide-(--border-light) dark:divide-(--border-dark)">
<div
v-for="cart in carts"
:key="cart.id"
class="flex items-center justify-between p-3 hover:bg-gray-50 dark:hover:bg-gray-700"
:class="{ 'bg-blue-50 dark:bg-blue-900/20': cart.id === activeCartId }"
>
<button
@click="selectCart(cart.id)"
class="flex-1 text-left"
>
<span class="text-black dark:text-white">{{ cart.name }}</span>
<span class="text-gray-500 dark:text-gray-400 text-sm ml-2">({{ cart.items.length }})</span>
</button>
<div class="flex items-center gap-1">
<button
@click.stop="startEditing(cart)"
class="p-1.5 text-gray-500 hover:text-(--accent-blue-light) dark:hover:text-(--accent-blue-dark) hover:bg-gray-100 dark:hover:bg-gray-600 rounded"
:title="t('Edit')"
>
<UIcon name="mdi:pencil" class="text-base" />
</button>
<button
@click.stop="confirmDelete(cart)"
class="p-1.5 text-gray-500 hover:text-red-500 hover:bg-gray-100 dark:hover:bg-gray-600 rounded"
:title="t('Delete')"
>
<UIcon name="mdi:delete" class="text-base" />
</button>
</div>
</div>
</div>
<div class="p-3 border-t border-(--border-light) dark:border-(--border-dark)">
<button
@click="showCreateModal = true"
class="w-full flex items-center gap-2 text-(--accent-blue-light) dark:text-(--accent-blue-dark) hover:bg-gray-50 dark:hover:bg-gray-700 p-2 rounded"
>
<UIcon name="mdi:plus" class="text-lg" />
<span>{{ t('Create New Cart') }}</span>
</button>
</div>
</div>
<div
v-if="isOpen"
@click="closeDropdown"
class="fixed inset-0 z-40"
/>
</div>
<div
v-if="showCreateModal"
class="fixed inset-0 z-50 flex items-center justify-center bg-black/50"
@click.self="showCreateModal = false"
>
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl p-6 w-96">
<h3 class="text-lg font-semibold text-black dark:text-white mb-4">{{ t('Create New Cart') }}</h3>
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
{{ t('Cart Name') }}
</label>
<UInput
v-model="newCartName"
:placeholder="t('Enter cart name')"
class="w-full"
/>
</div>
<div class="flex gap-3 justify-end">
<UButton
variant="outline"
color="neutral"
@click="showCreateModal = false"
>
{{ t('Cancel') }}
</UButton>
<UButton
color="primary"
@click="createNewCart"
:disabled="!newCartName.trim()"
>
{{ t('Create and Continue') }}
</UButton>
</div>
</div>
</div>
<div
v-if="editingCart"
class="fixed inset-0 z-50 flex items-center justify-center bg-black/50"
@click.self="editingCart = null"
>
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl p-6 w-96">
<h3 class="text-lg font-semibold text-black dark:text-white mb-4">{{ t('Edit Cart Name') }}</h3>
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
{{ t('Cart Name') }}
</label>
<UInput
v-model="editCartName"
:placeholder="t('Enter cart name')"
class="w-full"
/>
</div>
<div class="flex gap-3 justify-end">
<UButton
variant="outline"
color="neutral"
@click="editingCart = null"
>
{{ t('Cancel') }}
</UButton>
<UButton
color="primary"
@click="saveEditedCart"
:disabled="!editCartName.trim()"
>
{{ t('Save') }}
</UButton>
</div>
</div>
</div>
<div
v-if="deletingCart"
class="fixed inset-0 z-50 flex items-center justify-center bg-black/50"
@click.self="deletingCart = null"
>
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl p-6 w-96">
<h3 class="text-lg font-semibold text-black dark:text-white mb-4">{{ t('Delete Cart') }}</h3>
<p class="text-gray-600 dark:text-gray-400 mb-6">
{{ t('Are you sure you want to delete') }} "{{ deletingCart.name }}"?
</p>
<div class="flex gap-3 justify-end">
<UButton
variant="outline"
color="neutral"
@click="deletingCart = null"
>
{{ t('Cancel') }}
</UButton>
<UButton
color="error"
@click="confirmDeleteCart"
>
{{ t('Delete') }}
</UButton>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { useCartStore } from '@/stores/cart'
import { useI18n } from 'vue-i18n'
const cartStore = useCartStore()
const { t } = useI18n()
const isOpen = ref(false)
const showCreateModal = ref(false)
const newCartName = ref('')
const editingCart = ref<{ id: string; name: string } | null>(null)
const editCartName = ref('')
const deletingCart = ref<{ id: string; name: string } | null>(null)
const carts = computed(() => cartStore.carts)
const activeCartId = computed(() => cartStore.activeCartId)
const activeCartName = computed(() => {
const cart = cartStore.activeCart
return cart ? cart.name : t('Select Cart')
})
function toggleDropdown() {
isOpen.value = !isOpen.value
}
function closeDropdown() {
isOpen.value = false
}
function selectCart(cartId: string) {
cartStore.setActiveCart(cartId)
closeDropdown()
}
function startEditing(cart: { id: string; name: string }) {
editingCart.value = { id: cart.id, name: cart.name }
editCartName.value = cart.name
}
function saveEditedCart() {
if (editingCart.value && editCartName.value.trim()) {
cartStore.renameCart(editingCart.value.id, editCartName.value.trim())
editingCart.value = null
}
}
function confirmDelete(cart: { id: string; name: string }) {
deletingCart.value = cart
}
function confirmDeleteCart() {
if (deletingCart.value) {
cartStore.deleteCart(deletingCart.value.id)
deletingCart.value = null
}
}
function createNewCart() {
if (newCartName.value.trim()) {
cartStore.createCart(newCartName.value.trim())
newCartName.value = ''
showCreateModal.value = false
}
}
</script>

View File

@@ -188,10 +188,7 @@ function removeItem(itemId: number) {
function placeOrder() {
if (canPlaceOrder.value) {
console.log('Placing order...')
alert(t('Order placed successfully!'))
cartStore.clearCart()
router.push({ name: 'home' })
router.push({ name: 'checkout' })
}
}

View File

@@ -0,0 +1,100 @@
<template>
<component :is="Default || 'div'">
<div class="container mx-auto mt-20">
<div class="flex justify-between items-center pb-6">
<div class="flex gap-2 items-center">
<h2 class="font-semibold text-black dark:text-white text-2xl ">
{{ t('Shopping') }}
</h2>
<p class="font-semibold text-(--accent-blue-light) dark:text-(--accent-blue-dark) text-2xl">{{
cartStore.activeCart?.name }}</p>
</div>
<CartSelector />
</div>
<div
class="bg-(--second-light) dark:bg-(--main-dark) rounded-lg border border-(--border-light) dark:border-(--border-dark) overflow-hidden">
<div v-if="cartStore.items.length > 0"
class="divide-y divide-(--border-light) dark:divide-(--border-dark)">
<div v-for="item in cartStore.items" :key="item.id"
class="flex items-center justify-between p-4 gap-4">
<div class="grid grid-cols-5 w-[100%] flex items-center">
<div
class="w-20 bg-white dark:bg-gray-700 rounded flex items-center justify-center overflow-hidden">
<img v-if="item.image" :src="item.image" :alt="item.name"
class="w-full h-full object-cover" />
<UIcon v-else name="mdi:package-variant" class="text-xl text-gray-400" />
</div>
<p class="text-black dark:text-white text-sm font-medium truncate">
{{ item.name }}
</p>
<p class="text-gray-600 dark:text-gray-400 text-sm truncate">
{{ item.product_number }}
</p>
<p class="text-black dark:text-white font-medium">
${{ item.price.toFixed(2) }}
</p>
<div class="flex items-center justify-end gap-10">
<p class="text-black dark:text-white font-medium">
${{ (item.price * item.quantity).toFixed(2) }}
</p>
<div class="flex items-center justify-end gap-10">
<UInputNumber v-model="item.quantity"
class="text-gray-500 dark:text-gray-400 text-sm" :min="1"
@update:model-value="(val: number) => cartStore.updateQuantity(item.id, val)" />
<div class="flex justify-center">
<button @click="removeItem(item.id)"
class="p-2 text-red-500 bg-red-100 dark:bg-(--main-dark) rounded transition-colors"
:title="t('Remove')">
<UIcon name="material-symbols:delete" class="text-[20px]" />
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div v-else class="p-8 text-center">
<UIcon name="mdi:cart-outline" class="text-5xl text-gray-300 dark:text-gray-600 mb-4 mx-auto" />
<p class="text-gray-500 dark:text-gray-400">{{ t('Your cart is empty') }}</p>
<RouterLink :to="{ name: 'product-card-full' }"
class="inline-block mt-4 text-(--accent-blue-light) dark:text-(--accent-blue-dark) hover:underline">
{{ t('Continue Shopping') }}
</RouterLink>
</div>
</div>
<div v-if="cartStore.items.length > 0" class="flex gap-4 justify-end items-center pt-6">
<UButton color="primary" @click="handleContinueToCart"
class="bg-(--accent-blue-light) dark:bg-(--accent-blue-dark) text-white hover:bg-(--accent-blue-dark) dark:hover:bg-(--accent-blue-light)">
{{ t('Continue to Checkout') }}
</UButton>
<UButton variant="outline" color="neutral" @click="handleCancel"
class="text-black dark:text-white border-(--border-light) dark:border-(--border-dark) hover:bg-gray-100 dark:hover:bg-gray-700">
{{ t('Cancel') }}
</UButton>
</div>
</div>
</component>
</template>
<script setup lang="ts">
import { useCartStore } from '@/stores/cart'
import { useI18n } from 'vue-i18n'
import { useRouter } from 'vue-router'
import Default from '@/layouts/default.vue'
import CartSelector from './CartSelector.vue'
const cartStore = useCartStore()
const { t } = useI18n()
const router = useRouter()
function handleCancel() {
router.back()
}
function handleContinueToCart() {
router.push({ name: 'cart' })
}
function removeItem(itemId: number) {
cartStore.removeItem(itemId)
}
</script>

View File

@@ -0,0 +1,79 @@
<template>
<component :is="Default || 'div'">
<div class="container mx-auto mt-20">
<div class="max-w-2xl mx-auto">
<div class="grid grid-cols-3 pb-6">
<button variant="outline" color="neutral" @click="goBackToCart"
class="text-(--accent-blue-light) dark:text-(--accent-blue-dark) flex items-center gap-2">
<UIcon name="mdi:arrow-left" />
{{ t('Back') }}
</button>
<h2 class="font-semibold text-black dark:text-white text-2xl text-center">
{{ t('Checkout') }}
</h2>
</div>
<div
class="bg-(--second-light) dark:bg-(--main-dark) rounded-lg border border-(--border-light) dark:border-(--border-dark) overflow-hidden mb-6">
<div class="p-6">
<h3 class="text-lg font-semibold text-black dark:text-white mb-4">
{{ t('Order Summary') }}
</h3>
<div class="space-y-3 border-b border-(--border-light) dark:border-(--border-dark) pb-4 mb-4">
<div class="flex justify-between">
<span class="text-gray-600 dark:text-gray-400">{{ t('Products') }}</span>
<span class="text-black dark:text-white">{{ cartStore.items.length }} {{ t('items')
}}</span>
</div>
<div class="flex justify-between">
<span class="text-gray-600 dark:text-gray-400">{{ t('Products total') }}</span>
<span class="text-black dark:text-white">${{ cartStore.productsTotal.toFixed(2)
}}</span>
</div>
<div class="flex justify-between">
<span class="text-gray-600 dark:text-gray-400">{{ t('VAT') }}</span>
<span class="text-black dark:text-white">${{ cartStore.vatAmount.toFixed(2) }}</span>
</div>
</div>
<div class="flex justify-between mb-6">
<span class="text-black dark:text-white font-semibold text-lg">{{ t('Total') }}</span>
<span class="text-(--accent-blue-light) dark:text-(--accent-blue-dark) font-bold text-lg">
${{ cartStore.orderTotal.toFixed(2) }}
</span>
</div>
<div class="space-y-2 mb-4">
<div v-for="item in cartStore.items" :key="item.id" class="flex items-center gap-3 text-sm">
<div
class="w-10 h-10 bg-white dark:bg-gray-700 rounded flex items-center justify-center overflow-hidden">
<img v-if="item.image" :src="item.image" :alt="item.name"
class="w-full h-full object-cover" />
<UIcon v-else name="mdi:package-variant" class="text-lg text-gray-400" />
</div>
<span class="text-black dark:text-white flex-1 truncate">{{ item.name }}</span>
<span class="text-gray-600 dark:text-gray-400">x{{ item.quantity }}</span>
<span class="text-black dark:text-white">${{ (item.price * item.quantity).toFixed(2)
}}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</component>
</template>
<script setup lang="ts">
import { useCartStore } from '@/stores/cart'
import { useI18n } from 'vue-i18n'
import { useRouter } from 'vue-router'
import Default from '@/layouts/default.vue'
const cartStore = useCartStore()
const { t } = useI18n()
const router = useRouter()
function goBackToCart() {
router.push({ name: 'cart' })
}
</script>

View File

@@ -33,7 +33,8 @@ const router = createRouter({
{ path: 'customer-data', component: () => import('@/components/customer/PageCustomerData.vue'), name: 'customer-data' },
{ path: 'create-account', component: () => import('@/components/customer/PageCreateAccount.vue'), name: 'create-account' },
{ path: 'cart', component: () => import('@/components/customer/PageCart.vue'), name: 'cart' },
{ path: 'cart1', component: () => import('@/components/customer/Cart1.vue'), name: 'cart1' },
{ path: 'carts', component: () => import('@/components/customer/PageCarts.vue'), name: 'carts' },
{ path: 'checkout', component: () => import('@/components/customer/PageCheckout.vue'), name: 'checkout' },
{ path: 'products-list', component: () => import('@/components/admin/PageProductsList.vue'), name: 'products-list' },
{ path: 'login', component: () => import('@/views/LoginView.vue'), name: 'login', meta: { guest: true, } },
{ path: 'register', component: () => import('@/views/RegisterView.vue'), name: 'register', meta: { guest: true } },

View File

@@ -18,8 +18,16 @@ export interface DeliveryMethod {
description: string
}
export interface Cart {
id: string
name: string
items: CartItem[]
}
export const useCartStore = defineStore('cart', () => {
const items = ref<CartItem[]>([])
const carts = ref<Cart[]>([])
const activeCartId = ref<string | null>(null)
const selectedAddressId = ref<number | null>(null)
const selectedDeliveryMethodId = ref<number | null>(null)
const shippingCost = ref(0)
@@ -31,13 +39,15 @@ export const useCartStore = defineStore('cart', () => {
{ id: 3, name: 'Priority Delivery', price: 30, description: 'Next business day' }
])
function initMockData() {
items.value = [
{ id: 1, productId: 101, name: 'Premium Widget Pro', product_number: 'NC209/7000', image: '/img/product-1.jpg', price: 129.99, quantity: 2 },
{ id: 2, productId: 102, name: 'Ultra Gadget X', product_number: 'NC234/6453', image: '/img/product-2.jpg', price: 89.50, quantity: 1 },
{ id: 3, productId: 103, name: 'Mega Tool Set', product_number: 'NC324/9030', image: '/img/product-3.jpg', price: 249.00, quantity: 3 }
]
}
const items = computed(() => {
if (!activeCartId.value) return []
const cart = carts.value.find(c => c.id === activeCartId.value)
return cart ? cart.items : []
})
const activeCart = computed(() => {
return carts.value.find(c => c.id === activeCartId.value) || null
})
const productsTotal = computed(() => {
return items.value.reduce((sum, item) => sum + (item.price * item.quantity), 0)
@@ -55,8 +65,63 @@ export const useCartStore = defineStore('cart', () => {
return items.value.reduce((sum, item) => sum + item.quantity, 0)
})
function createCart(name: string): Cart {
const newCart: Cart = {
id: `cart-${Date.now()}`,
name,
items: []
}
carts.value.push(newCart)
activeCartId.value = newCart.id
return newCart
}
function deleteCart(cartId: string) {
const index = carts.value.findIndex(c => c.id === cartId)
if (index !== -1) {
carts.value.splice(index, 1)
if (activeCartId.value === cartId) {
const firstCart = carts.value[0]
activeCartId.value = firstCart ? firstCart.id : null
}
}
}
function renameCart(cartId: string, newName: string) {
const cart = carts.value.find(c => c.id === cartId)
if (cart) {
cart.name = newName
}
}
function setActiveCart(cartId: string) {
const cart = carts.value.find(c => c.id === cartId)
if (cart) {
activeCartId.value = cartId
}
}
function addItemToActiveCart(item: CartItem) {
if (!activeCartId.value) {
createCart('Cart 1')
}
const cart = carts.value.find(c => c.id === activeCartId.value)
if (cart) {
const existingItem = cart.items.find(i => i.productId === item.productId)
if (existingItem) {
existingItem.quantity += item.quantity
} else {
cart.items.push(item)
}
}
}
function updateQuantity(itemId: number, quantity: number) {
const item = items.value.find(i => i.id === itemId)
const cart = carts.value.find(c => c.id === activeCartId.value)
if (!cart) return
const item = cart.items.find(i => i.id === itemId)
if (item) {
if (quantity <= 0) {
removeItem(itemId)
@@ -67,12 +132,14 @@ export const useCartStore = defineStore('cart', () => {
}
function deleteProduct(id: number): boolean {
const index = items.value.findIndex(a => a.id === id)
const cart = carts.value.find(c => c.id === activeCartId.value)
if (!cart) return false
const index = cart.items.findIndex(a => a.id === id)
if (index === -1) return false
items.value.splice(index, 1)
cart.items.splice(index, 1)
resetProductPagination()
return true
}
@@ -81,14 +148,20 @@ export const useCartStore = defineStore('cart', () => {
}
function removeItem(itemId: number) {
const index = items.value.findIndex(i => i.id === itemId)
const cart = carts.value.find(c => c.id === activeCartId.value)
if (!cart) return
const index = cart.items.findIndex(i => i.id === itemId)
if (index !== -1) {
items.value.splice(index, 1)
cart.items.splice(index, 1)
}
}
function clearCart() {
items.value = []
const cart = carts.value.find(c => c.id === activeCartId.value)
if (cart) {
cart.items = []
}
selectedAddressId.value = null
selectedDeliveryMethodId.value = null
shippingCost.value = 0
@@ -106,9 +179,40 @@ export const useCartStore = defineStore('cart', () => {
}
}
function initMockData() {
const cart1: Cart = {
id: 'cart-1',
name: 'Cart 1',
items: [
{ id: 1, productId: 101, name: 'Premium Widget Pro', product_number: 'NC209/7000', image: '/img/product-1.jpg', price: 129.99, quantity: 2 },
{ id: 2, productId: 102, name: 'Ultra Gadget X', product_number: 'NC234/6453', image: '/img/product-2.jpg', price: 89.50, quantity: 1 }
]
}
const cart2: Cart = {
id: 'cart-2',
name: 'Cart 2',
items: [
{ id: 3, productId: 103, name: 'Mega Tool Set', product_number: 'NC324/9030', image: '/img/product-3.jpg', price: 249.00, quantity: 3 }
]
}
const cart3: Cart = {
id: 'cart-3',
name: 'Cart 3',
items: []
}
carts.value = [cart1, cart2, cart3]
activeCartId.value = 'cart-1'
}
initMockData()
return {
carts,
activeCartId,
activeCart,
items,
selectedAddressId,
selectedDeliveryMethodId,
@@ -119,8 +223,14 @@ export const useCartStore = defineStore('cart', () => {
vatAmount,
orderTotal,
itemCount,
deleteProduct,
createCart,
deleteCart,
renameCart,
setActiveCart,
addItemToActiveCart,
updateQuantity,
deleteProduct,
removeItem,
clearCart,
setSelectedAddress,