fix(market): drop floating cart button, badge the navbar Cart tab

The floating "Cart (N)" button (fixed bottom-4 right-4) was hidden
behind the bottom navbar — both occupy the same screen position.
The navbar already has a Cart tab, so the floating button is
redundant.

- Remove CartButton.vue component and its usages from MarketPage
  and StallView.
- Add a count badge to the Cart tab in the market app navbar that
  shows marketStore.totalCartItems when > 0.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Padreug 2026-05-03 16:38:48 +02:00
commit 8792a884cd
4 changed files with 11 additions and 33 deletions

View file

@ -6,6 +6,7 @@ import LoginDialog from '@/components/auth/LoginDialog.vue'
import { useTheme } from '@/components/theme-provider' import { useTheme } from '@/components/theme-provider'
import { toast } from 'vue-sonner' import { toast } from 'vue-sonner'
import { useAuth } from '@/composables/useAuthService' import { useAuth } from '@/composables/useAuthService'
import { useMarketStore } from '@/modules/market/stores/market'
import { import {
Store, ShoppingCart, Package, LogIn, User as UserIcon, Store, ShoppingCart, Package, LogIn, User as UserIcon,
} from 'lucide-vue-next' } from 'lucide-vue-next'
@ -15,6 +16,7 @@ const router = useRouter()
useTheme() useTheme()
const { isAuthenticated } = useAuth() const { isAuthenticated } = useAuth()
const marketStore = useMarketStore()
const showLoginDialog = ref(false) const showLoginDialog = ref(false)
@ -23,12 +25,13 @@ interface Tab {
icon: any icon: any
path?: string path?: string
authRequired?: boolean authRequired?: boolean
badge?: () => number
onClick?: () => void onClick?: () => void
} }
const bottomTabs = computed<Tab[]>(() => [ const bottomTabs = computed<Tab[]>(() => [
{ name: 'Browse', icon: Store, path: '/market' }, { name: 'Browse', icon: Store, path: '/market' },
{ name: 'Cart', icon: ShoppingCart, path: '/cart' }, { name: 'Cart', icon: ShoppingCart, path: '/cart', badge: () => marketStore.totalCartItems },
{ name: 'My Store', icon: Package, path: '/market/dashboard', authRequired: true }, { name: 'My Store', icon: Package, path: '/market/dashboard', authRequired: true },
isAuthenticated.value isAuthenticated.value
? { name: 'Profile', icon: UserIcon, path: '/profile' } ? { name: 'Profile', icon: UserIcon, path: '/profile' }
@ -92,7 +95,13 @@ async function handleLoginSuccess() {
]" ]"
@click="onTabClick(tab)" @click="onTabClick(tab)"
> >
<span class="relative inline-flex">
<component :is="tab.icon" class="w-5 h-5" /> <component :is="tab.icon" class="w-5 h-5" />
<span
v-if="tab.badge && tab.badge() > 0"
class="absolute -top-1.5 -right-2 min-w-[16px] h-4 px-1 rounded-full bg-primary text-primary-foreground text-[10px] font-semibold leading-4 text-center"
>{{ tab.badge() }}</span>
</span>
<span class="text-[10px] font-medium">{{ tab.name }}</span> <span class="text-[10px] font-medium">{{ tab.name }}</span>
</button> </button>
</div> </div>

View file

@ -1,23 +0,0 @@
<template>
<!-- Cart Summary Button -->
<div v-if="marketStore.totalCartItems > 0" class="fixed bottom-4 right-4 z-50">
<Button @click="viewCart" class="shadow-lg">
<ShoppingCart class="w-5 h-5 mr-2" />
Cart ({{ marketStore.totalCartItems }})
</Button>
</div>
</template>
<script setup lang="ts">
import { useRouter } from 'vue-router'
import { useMarketStore } from '@/modules/market/stores/market'
import { Button } from '@/components/ui/button'
import { ShoppingCart } from 'lucide-vue-next'
const router = useRouter()
const marketStore = useMarketStore()
const viewCart = () => {
router.push('/cart')
}
</script>

View file

@ -67,9 +67,6 @@
@view-stall="viewStall" @view-stall="viewStall"
/> />
<!-- Cart Summary -->
<CartButton />
</LoadingErrorState> </LoadingErrorState>
</div> </div>
</template> </template>
@ -86,7 +83,6 @@ import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar'
import MarketSearchBar from '../components/MarketSearchBar.vue' import MarketSearchBar from '../components/MarketSearchBar.vue'
import ProductGrid from '../components/ProductGrid.vue' import ProductGrid from '../components/ProductGrid.vue'
import CategoryFilterBar from '../components/CategoryFilterBar.vue' import CategoryFilterBar from '../components/CategoryFilterBar.vue'
import CartButton from '../components/CartButton.vue'
import LoadingErrorState from '../components/LoadingErrorState.vue' import LoadingErrorState from '../components/LoadingErrorState.vue'
import type { Product } from '../types/market' import type { Product } from '../types/market'
import type { FuzzySearchOptions } from '@/composables/useFuzzySearch' import type { FuzzySearchOptions } from '@/composables/useFuzzySearch'

View file

@ -131,9 +131,6 @@
/> />
</div> </div>
<!-- Cart Summary -->
<CartButton />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -153,7 +150,6 @@ import {
import { ArrowLeft, Store, X } from 'lucide-vue-next' import { ArrowLeft, Store, X } from 'lucide-vue-next'
import MarketSearchBar from '../components/MarketSearchBar.vue' import MarketSearchBar from '../components/MarketSearchBar.vue'
import ProductGrid from '../components/ProductGrid.vue' import ProductGrid from '../components/ProductGrid.vue'
import CartButton from '../components/CartButton.vue'
import CategoryFilterBar from '../components/CategoryFilterBar.vue' import CategoryFilterBar from '../components/CategoryFilterBar.vue'
import type { Product, Stall } from '../types/market' import type { Product, Stall } from '../types/market'
import type { FuzzySearchOptions } from '@/composables/useFuzzySearch' import type { FuzzySearchOptions } from '@/composables/useFuzzySearch'