Files
mp-pilates/packages/app/src/components/ProfileMenu.vue
richarjiang 3a29aca0db feat(app): implement home, booking, and profile pages
Home: brand banner, studio info swiper, smart quick entries based on
membership status, upcoming bookings, card shop horizontal scroll
Booking: 7-day date selector, time period filter, slot cards with
status, booking confirm popup with membership picker
Profile: user card with login, training stats, menu with admin entry
8 reusable components: BrandBanner, StudioInfo, QuickEntry,
UpcomingBooking, CardShop, DateSelector, SlotCard, BookingConfirmPopup,
TimePeriodFilter, UserCard, TrainingStats, ProfileMenu
2026-04-02 14:35:17 +08:00

164 lines
3.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="profile-menu">
<template v-for="item in menuItems" :key="item.key">
<!-- Separator -->
<view v-if="item.type === 'separator'" class="profile-menu__separator" />
<!-- Menu item -->
<view
v-else
class="profile-menu__item"
:class="{ 'profile-menu__item--admin': item.isAdmin }"
hover-class="profile-menu__item--hover"
hover-stay-time="150"
@tap="navigate(item.path!)"
>
<view class="profile-menu__icon-wrap" :class="{ 'profile-menu__icon-wrap--admin': item.isAdmin }">
<text class="profile-menu__icon">{{ item.icon }}</text>
</view>
<text class="profile-menu__title" :class="{ 'profile-menu__title--admin': item.isAdmin }">
{{ item.title }}
</text>
<text class="profile-menu__arrow"></text>
</view>
</template>
</view>
</template>
<script setup lang="ts">
import { computed } from 'vue'
interface MenuItem {
key: string
type: 'item' | 'separator'
icon?: string
title?: string
path?: string
isAdmin?: boolean
}
const props = defineProps<{
isAdmin: boolean
}>()
const menuItems = computed<MenuItem[]>(() => {
const items: MenuItem[] = [
{
key: 'membership',
type: 'item',
icon: '💳',
title: '我的会员卡',
path: '/pages/profile/membership',
},
{
key: 'bookings',
type: 'item',
icon: '📅',
title: '我的预约',
path: '/pages/profile/bookings',
},
{
key: 'info',
type: 'item',
icon: '👤',
title: '个人信息',
path: '/pages/profile/info',
},
]
if (props.isAdmin) {
items.push({ key: 'sep', type: 'separator' })
items.push({
key: 'admin',
type: 'item',
icon: '⚙️',
title: '管理中心',
path: '/pages/admin/index',
isAdmin: true,
})
}
return items
})
function navigate(path: string) {
uni.navigateTo({ url: path })
}
</script>
<style lang="scss" scoped>
.profile-menu {
background: $bg-card;
border-radius: $radius-lg;
margin: $spacing-md $spacing-lg 0;
overflow: hidden;
&__separator {
height: $spacing-sm;
background: $bg-page;
}
&__item {
display: flex;
align-items: center;
padding: $spacing-md $spacing-lg;
border-bottom: 1rpx solid $border-color;
background: $bg-card;
transition: background 0.15s;
&:last-child {
border-bottom: none;
}
&--hover {
background: #f9f9f9;
}
&--admin {
// Admin row gets a subtle accent tint
}
}
&__icon-wrap {
width: 64rpx;
height: 64rpx;
border-radius: $radius-sm;
background: rgba($brand-color, 0.06);
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
margin-right: $spacing-md;
&--admin {
background: rgba($accent-color, 0.12);
}
}
&__icon {
font-size: 32rpx;
line-height: 1;
}
&__title {
flex: 1;
font-size: 30rpx;
color: $text-primary;
font-weight: 400;
&--admin {
color: $accent-color;
font-weight: 500;
}
}
&__arrow {
font-size: 36rpx;
color: $text-hint;
line-height: 1;
transform: scaleX(0.6);
transform-origin: center;
}
}
</style>