2025-12-18 13:50:39 +08:00
< template >
< AppLayout >
2025-12-25 08:41:36 -08:00
< div class = "mx-auto max-w-4xl space-y-6" >
2025-12-18 13:50:39 +08:00
< div class = "grid grid-cols-1 gap-6 sm:grid-cols-3" >
2026-01-04 22:23:19 +08:00
< StatCard :title = "t('profile.accountBalance')" : value = "formatCurrency(user?.balance || 0)" :icon = "WalletIcon" icon -variant = " success " / >
< StatCard :title = "t('profile.concurrencyLimit')" : value = "user?.concurrency || 0" :icon = "BoltIcon" icon -variant = " warning " / >
< StatCard :title = "t('profile.memberSince')" : value = "formatDate(user?.created_at || '', { year: 'numeric', month: 'long' })" :icon = "CalendarIcon" icon -variant = " primary " / >
2025-12-18 13:50:39 +08:00
< / div >
2026-01-04 22:23:19 +08:00
< ProfileInfoCard :user = "user" / >
< div v-if = "contactInfo" class="card border-primary-200 bg-primary-50 dark:bg-primary-900/20 p-6" >
< div class = "flex items-center gap-4" >
2026-01-04 22:26:33 -08:00
< div class = "p-3 bg-primary-100 rounded-xl text-primary-600" > < Icon name = "chat" size = "lg" / > < / div >
2026-01-04 22:23:19 +08:00
< div > < h3 class = "font-semibold text-primary-800 dark:text-primary-200" > { { t ( 'common.contactSupport' ) } } < / h3 > < p class = "text-sm font-medium" > { { contactInfo } } < / p > < / div >
2025-12-18 13:50:39 +08:00
< / div >
< / div >
2026-01-04 22:23:19 +08:00
< ProfileEditForm : initial -username = " user ? .username | | ' ' " / >
< ProfilePasswordForm / >
2025-12-18 13:50:39 +08:00
< / div >
< / AppLayout >
< / template >
< script setup lang = "ts" >
2026-01-04 22:23:19 +08:00
import { ref , computed , h , onMounted } from 'vue' ; import { useI18n } from 'vue-i18n'
import { useAuthStore } from '@/stores/auth' ; import { formatDate } from '@/utils/format'
import { authAPI } from '@/api' ; import AppLayout from '@/components/layout/AppLayout.vue'
2025-12-18 13:50:39 +08:00
import StatCard from '@/components/common/StatCard.vue'
2026-01-04 22:23:19 +08:00
import ProfileInfoCard from '@/components/user/profile/ProfileInfoCard.vue'
import ProfileEditForm from '@/components/user/profile/ProfileEditForm.vue'
import ProfilePasswordForm from '@/components/user/profile/ProfilePasswordForm.vue'
2026-01-04 22:26:33 -08:00
import { Icon } from '@/components/icons'
2025-12-18 13:50:39 +08:00
2026-01-04 22:23:19 +08:00
const { t } = useI18n ( ) ; const authStore = useAuthStore ( ) ; const user = computed ( ( ) => authStore . user )
2025-12-18 13:50:39 +08:00
const contactInfo = ref ( '' )
2026-01-04 22:23:19 +08:00
const WalletIcon = { render : ( ) => h ( 'svg' , { fill : 'none' , viewBox : '0 0 24 24' , stroke : 'currentColor' , 'stroke-width' : '1.5' } , [ h ( 'path' , { d : 'M21 12a2.25 2.25 0 00-2.25-2.25H15a3 3 0 11-6 0H5.25A2.25 2.25 0 003 12' } ) ] ) }
const BoltIcon = { render : ( ) => h ( 'svg' , { fill : 'none' , viewBox : '0 0 24 24' , stroke : 'currentColor' , 'stroke-width' : '1.5' } , [ h ( 'path' , { d : 'm3.75 13.5 10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z' } ) ] ) }
const CalendarIcon = { render : ( ) => h ( 'svg' , { fill : 'none' , viewBox : '0 0 24 24' , stroke : 'currentColor' , 'stroke-width' : '1.5' } , [ h ( 'path' , { d : 'M6.75 3v2.25M17.25 3v2.25' } ) ] ) }
2025-12-23 11:26:22 +08:00
2026-01-06 12:42:06 +08:00
onMounted ( async ( ) => { try { const s = await authAPI . getPublicSettings ( ) ; contactInfo . value = s . contact _info || '' } catch ( error ) { console . error ( 'Failed to load contact info:' , error ) } } )
2026-01-04 22:23:19 +08:00
const formatCurrency = ( v : number ) => ` $ ${ v . toFixed ( 2 ) } `
< / script >