feat: add gold day calculator and polish desktop UI

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-20 21:35:18 +03:30
co-authored by Cursor
parent d2737a4998
commit 444178df05
15 changed files with 574 additions and 93 deletions
@@ -34,13 +34,17 @@
}
.dgold-topbar {
position: sticky;
top: 0;
z-index: 30;
display: flex;
align-items: flex-start;
gap: 16px;
max-width: 720px;
margin: 0 auto 24px;
padding-bottom: 24px;
margin: -4px auto 20px;
padding: 12px 0 20px;
border-bottom: 1px solid rgba(15, 23, 42, 0.06);
background: #f6f7f9;
&__back {
display: inline-flex;
@@ -53,13 +53,17 @@
/* Topbar */
.dhome-topbar {
position: sticky;
top: 0;
z-index: 30;
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: 24px;
margin-bottom: 28px;
padding-bottom: 24px;
margin: -4px 0 20px;
padding: 12px 0 20px;
border-bottom: 1px solid rgba(15, 23, 42, 0.06);
background: #f6f7f9;
&__eyebrow {
font-size: 12px;
@@ -1,5 +1,5 @@
<template>
<a-form ref="formRef" :model="userFormState" class="!mt-5" name="basic" @finish="ok">
<a-form ref="formRef" :model="userFormState" class="user-profile-form !mt-5" name="basic" dir="rtl" @finish="ok">
<a-form-item :rules="[isValidPersian()]" label="نام" name="fname">
<BasicInput v-model:value="userFormState.fname" />
</a-form-item>
@@ -39,3 +39,20 @@ withDefaults(defineProps<{ showSubmit?: boolean }>(), { showSubmit: false })
const { userFormState, formRef, isValidPersian, requireNationalCode, ok } = useUserPageContext()
</script>
<style scoped>
.user-profile-form {
direction: rtl;
text-align: right;
}
:deep(.ant-form-item-label) {
text-align: right;
}
:deep(.ant-input),
:deep(.ant-input-affix-wrapper) {
direction: rtl;
text-align: right;
}
</style>
@@ -17,6 +17,7 @@ import { useTrackingSystemsFeature } from '@/composables/useTrackingSystemsFeatu
import { useSettingsStore } from '@/store/settingsStore'
import { useSupportMessenger } from '@/composables/useSupportMessenger'
import { isUserSupportChatEnabled, unreadSupportCount } from '@/utils/chat'
import { openGoldDayCalculator } from '@/composables/useGoldDayCalculator'
export interface UserMenuAction {
id: string
@@ -104,6 +105,13 @@ export function useUserPage() {
onClick: () => { editPasswordVisible.value = true },
visible: true,
},
{
id: 'goldDayCalculator',
label: 'قیمت روز طلا',
icon: 'vuesax-linear:chart-2',
onClick: () => openGoldDayCalculator(),
visible: true,
},
{
id: 'notify',
label: 'هشدار قیمت',
+12 -12
View File
@@ -31,11 +31,11 @@
</div>
<div class="duser-profile__field">
<span class="duser-profile__label">شماره تلفن همراه</span>
<span class="duser-profile__value">{{ userStore.userInfo?.mobile }}</span>
<span class="duser-profile__value duser-profile__value--ltr">{{ userStore.userInfo?.mobile }}</span>
</div>
<div v-if="userStore.userInfo?.referral_id" class="duser-profile__field">
<span class="duser-profile__label">کد معرف</span>
<span class="duser-profile__value">{{ userStore.userInfo?.referral_id }}</span>
<span class="duser-profile__value duser-profile__value--ltr">{{ userStore.userInfo?.referral_id }}</span>
</div>
</div>
@@ -83,17 +83,17 @@
<span class="duser-actions__label">{{ action.label }}</span>
<BasicIcon class="duser-actions__chevron" icon="vuesax-linear:arrow-left" size="16" />
</button>
<button
type="button"
class="duser-actions__item duser-actions__item--logout"
@click="requestLogout"
>
<span class="duser-actions__icon duser-actions__icon--logout">
<BasicIcon icon="vuesax-linear:logout" size="18" />
</span>
<span class="duser-actions__label duser-actions__label--logout">خروج</span>
</button>
</div>
<button
type="button"
class="duser-actions__item duser-actions__item--logout"
@click="requestLogout"
>
<span class="duser-actions__icon duser-actions__icon--logout">
<BasicIcon icon="vuesax-linear:logout" size="18" />
</span>
<span class="duser-actions__label duser-actions__label--logout">خروج</span>
</button>
</section>
</div>
</div>
@@ -4,22 +4,30 @@
min-height: 100%;
background: #f6f7f9;
color: #111827;
direction: rtl;
text-align: right;
}
.duser__container {
max-width: 960px;
width: 100%;
max-width: 1280px;
margin: 0 auto;
padding: 28px 36px 40px;
padding: 28px 28px 40px;
box-sizing: border-box;
}
.duser-topbar {
position: sticky;
top: 0;
z-index: 30;
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
margin-bottom: 28px;
padding-bottom: 24px;
margin: -4px 0 20px;
padding: 12px 0 20px;
border-bottom: 1px solid rgba(15, 23, 42, 0.06);
background: #f6f7f9;
&__back {
display: inline-flex;
@@ -62,8 +70,9 @@
}
.duser-grid {
/* تنظیمات و خدمات عریض‌تر از کارت پروفایل */
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(280px, 340px);
grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.4fr);
gap: 20px;
align-items: start;
}
@@ -71,8 +80,9 @@
.duser-surface {
background: #ffffff;
border-radius: 14px;
padding: 24px;
padding: 22px 20px;
box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
min-width: 0;
}
.duser-profile {
@@ -110,24 +120,32 @@
color: #6b7280;
margin: 0;
direction: ltr;
unicode-bidi: isolate;
text-align: right;
}
&__fields {
display: flex;
flex-direction: column;
gap: 14px;
flex-direction: row;
flex-wrap: nowrap;
gap: 10px;
margin-bottom: 20px;
direction: rtl;
}
&__field {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
flex: 1 1 0;
flex-direction: column;
align-items: flex-start;
justify-content: flex-start;
gap: 6px;
min-width: 0;
padding: 12px 14px;
border-radius: 10px;
background: #f9fafb;
direction: rtl;
text-align: right;
}
&__label {
@@ -137,11 +155,18 @@
}
&__value {
width: 100%;
font-size: 14px;
font-weight: 600;
color: #111827;
direction: ltr;
text-align: left;
direction: rtl;
text-align: right;
&--ltr {
direction: ltr;
unicode-bidi: isolate;
text-align: right;
}
}
&__referral-actions {
@@ -187,6 +212,9 @@
}
.duser-actions {
direction: rtl;
text-align: right;
&__title {
font-size: 13px;
font-weight: 600;
@@ -195,20 +223,28 @@
}
&__list {
display: flex;
flex-direction: column;
gap: 8px;
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px;
direction: rtl;
@media screen and (min-width: 1100px) {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
}
&__item {
display: flex;
flex-direction: row;
align-items: center;
gap: 12px;
gap: 10px;
width: 100%;
padding: 12px 14px;
min-width: 0;
padding: 14px 14px;
border: 1px solid #f3f4f6;
border-radius: 10px;
background: #fff;
direction: rtl;
text-align: right;
cursor: pointer;
font-family: inherit;
@@ -220,7 +256,8 @@
}
&--logout {
margin-top: 8px;
grid-column: 1 / -1;
margin-top: 4px;
border-color: rgba(239, 68, 68, 0.25);
&:hover {
+14 -1
View File
@@ -70,13 +70,25 @@
icon=""
iconSize="18"
size="large"
@click="editPasswordVisible = true"
@click="editPasswordVisible = true"
>
<div class="flex">
<BasicIcon icon="vuesax-linear:lock" class="absolute right-8" />
<div>تغییر رمز عبور</div>
</div>
</BasicButton>
<BasicButton
class="mt-2 w-full"
icon=""
iconSize="18"
size="large"
@click="openGoldDayCalculator"
>
<div class="flex">
<BasicIcon icon="vuesax-linear:chart-2" class="absolute right-8" />
<div>قیمت روز طلا</div>
</div>
</BasicButton>
<!-- <BasicButton
class="w-full mt-2"
size="large"
@@ -204,6 +216,7 @@ import { useSettingsStore } from '@/store/settingsStore'
import { useUserStore } from '@/store/userStore'
import { useUserPageContext } from '../composables/useUserPage'
import MobilePageHeader from '@/layouts/components/MobilePageHeader.vue'
import { openGoldDayCalculator } from '@/composables/useGoldDayCalculator'
const userStore = useUserStore()
const { trackingSystemsEnabled } = useTrackingSystemsFeature()
@@ -1,38 +1,41 @@
<template>
<div class="dwallet">
<div class="dwallet__container">
<DesktopPageTopbar
eyebrow="مالی"
title="کیف پول"
subtitle="واریز و برداشت وجه از کیف پول خود"
/>
<div class="dwallet-sticky-header">
<DesktopPageTopbar
eyebrow="مالی"
title="کیف پول"
subtitle="واریز و برداشت وجه از کیف پول خود"
:sticky="false"
/>
<div class="dwallet-toolbar">
<div class="dwallet-toggle">
<button
type="button"
class="dwallet-toggle__btn"
:class="{ 'dwallet-toggle__btn--active': isDeposit }"
@click="setIsDeposit(true)"
>
واریز
</button>
<button
type="button"
class="dwallet-toggle__btn"
:class="{ 'dwallet-toggle__btn--active': !isDeposit }"
@click="setIsDeposit(false)"
>
برداشت
</button>
</div>
<div class="dwallet-toolbar">
<div class="dwallet-toggle">
<button
type="button"
class="dwallet-toggle__btn"
:class="{ 'dwallet-toggle__btn--active': isDeposit }"
@click="setIsDeposit(true)"
>
واریز
</button>
<button
type="button"
class="dwallet-toggle__btn"
:class="{ 'dwallet-toggle__btn--active': !isDeposit }"
@click="setIsDeposit(false)"
>
برداشت
</button>
</div>
<div class="dwallet-balance-pill">
<span class="dwallet-balance-pill__label">موجودی کیف پول</span>
<span class="dwallet-balance-pill__value number-ltr">
{{ usePriceWithoutType(walletStore?.walletInfo?.cash ?? 0) }}
<span>ریال</span>
</span>
<div class="dwallet-balance-pill">
<span class="dwallet-balance-pill__label">موجودی کیف پول</span>
<span class="dwallet-balance-pill__value number-ltr">
{{ usePriceWithoutType(walletStore?.walletInfo?.cash ?? 0) }}
<span>ریال</span>
</span>
</div>
</div>
</div>
@@ -12,6 +12,21 @@
padding: 28px 36px 40px;
}
.dwallet-sticky-header {
position: sticky;
top: 0;
z-index: 30;
margin: -4px 0 20px;
padding-top: 4px;
background: #f6f7f9;
.dpage-topbar {
margin-bottom: 16px;
padding-bottom: 16px;
border-bottom: none;
}
}
.dwallet-topbar {
margin-bottom: 24px;
padding-bottom: 24px;
@@ -49,6 +64,12 @@
margin-bottom: 24px;
}
.dwallet-sticky-header .dwallet-toolbar {
margin-bottom: 0;
padding-bottom: 16px;
border-bottom: 1px solid rgba(15, 23, 42, 0.06);
}
.dwallet-toggle {
display: inline-flex;
gap: 4px;