Split desktop and mobile layouts with shared page data so APIs fetch once per context.

Add layout shells, desktop views, module-level page caches, and UI fixes for auth, home, wallet, transactions, address, and related pages.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-14 10:08:46 +03:30
co-authored by Cursor
parent 4404b4cb92
commit a5e458ed25
234 changed files with 18425 additions and 5503 deletions
@@ -0,0 +1,121 @@
<template>
<div class="dearn">
<div class="dearn__container">
<header class="dearn-topbar">
<p class="dearn-topbar__eyebrow">بازاریابی</p>
<h1 class="dearn-topbar__title">کسب درآمد</h1>
<p class="dearn-topbar__subtitle">با دعوت دوستان، پاداش دریافت کنید</p>
</header>
<section class="dearn-surface dearn-referral">
<div class="dearn-referral__header">
<div class="dearn-referral__icon">
<img :src="coin" alt="" />
</div>
<div>
<h2 class="dearn-referral__title">دعوت دوستان</h2>
<p class="dearn-referral__desc">هر دعوت موفق 10 سوت طلا هدیه</p>
</div>
</div>
<div class="dearn-referral__code">
<span class="dearn-referral__code-label">کد بازاریابی</span>
<span class="dearn-referral__code-value">{{ userStore.userInfo.referral_id }}</span>
</div>
<div class="dearn-referral__actions">
<BasicButton
icon="vuesax-linear:share"
type="primary"
class="dearn-referral__btn"
icon-size="18"
@click.stop="shareCode()"
>
اشتراک گذاری
</BasicButton>
<BasicButton
icon="vuesax-linear:copy"
class="dearn-referral__btn"
icon-size="18"
@click.stop="copyCode()"
>
رونوشت
</BasicButton>
</div>
</section>
<div class="dearn-stats">
<div class="dearn-stats__card dearn-stats__card--users">
<span class="dearn-stats__value">{{ data?.usersSum ?? 0 }} عدد</span>
<span class="dearn-stats__label">تعداد زیر مجموعه</span>
</div>
<div class="dearn-stats__card dearn-stats__card--gifts">
<span class="dearn-stats__value">{{ data?.giftsSum ?? 0 }} سوت</span>
<span class="dearn-stats__label">میزان کل پاداش ها</span>
</div>
</div>
<div class="dearn-tabs">
<button
type="button"
class="dearn-tabs__btn"
:class="{ 'dearn-tabs__btn--active': isTransaction }"
@click="setIsTransaction(true)"
>
پاداش ها
</button>
<button
type="button"
class="dearn-tabs__btn"
:class="{ 'dearn-tabs__btn--active': !isTransaction }"
@click="setIsTransaction(false)"
>
فهرست زیر مجموعه
</button>
</div>
<section class="dearn-surface dearn-list">
<div v-if="loading" class="dearn-list__loading">
<TransactionSkeleton v-for="i in 6" :key="i" class="mt-1" />
</div>
<template v-else>
<div v-if="isTransaction" class="dearn-list__items">
<GiftCard v-for="(val, i) in data?.gifts" :key="i" :item="val" />
<div v-if="!data?.gifts?.length" class="dearn-empty">
<BasicIcon icon="vuesax-linear:gift" size="36" />
<p>هنوز پاداشی ثبت نشده است.</p>
</div>
</div>
<div v-else class="dearn-list__items">
<EarnCard v-for="(val, i) in data?.users" :key="i" :item="val" />
<div v-if="!data?.users?.length" class="dearn-empty">
<BasicIcon icon="vuesax-linear:people" size="36" />
<p>هنوز زیرمجموعه‌ای ثبت نشده است.</p>
</div>
</div>
</template>
</section>
</div>
</div>
</template>
<script lang="ts" setup>
import coin from '@/assets/img/coin.png'
import BasicButton from '@/components/BasicPacks/BasicButton.vue'
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
import TransactionSkeleton from '@/components/TransactionSkeleton.vue'
import EarnCard from '../components/EarnCard.vue'
import GiftCard from '../components/GiftCard.vue'
import { useEarnMoneyPageContext } from '../composables/useEarnMoneyPage'
const {
data,
userStore,
isTransaction,
loading,
setIsTransaction,
copyCode,
shareCode,
} = useEarnMoneyPageContext()
</script>