Remove DialogVant/NotifyVant and add Toast and Sheet components with useToast, useReveal, and usePageTransition composables. Rework Navigation, RegisterView, and styles across both apps; rebuild dist assets. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
230 lines
5.6 KiB
Vue
230 lines
5.6 KiB
Vue
<!--
|
|
The "حساب" block that sits BELOW the shop content on the home screen.
|
|
|
|
Two genuinely different states:
|
|
- signed out: a quiet invitation, no fabricated numbers.
|
|
- signed in: the customer's real gram position from GET /customers/:id
|
|
(goldDebtGrams / fiatDebtRial), labelled بدهکار or بستانکار the same way
|
|
DashboardView does, since the ledger stores debt as a signed figure.
|
|
-->
|
|
<template>
|
|
<section class="acct">
|
|
<template v-if="customer">
|
|
<div class="acct__head">
|
|
<div>
|
|
<div class="acct__eyebrow">{{ positionLabel }}</div>
|
|
<div class="acct__figure">
|
|
{{ grams }}
|
|
<span class="acct__unit">گرم</span>
|
|
</div>
|
|
</div>
|
|
<span class="acct__seal" :class="isDebtor ? 'is-debtor' : 'is-creditor'">
|
|
{{ isDebtor ? 'بدهکار' : 'بستانکار' }}
|
|
</span>
|
|
</div>
|
|
|
|
<div class="acct__row">
|
|
<span class="acct__rowLabel">بدهی ریالی</span>
|
|
<span class="acct__rowValue">{{ price(fiat) }} <i>ریال</i></span>
|
|
</div>
|
|
|
|
<div class="acct__actions">
|
|
<button type="button" class="acct__action" @click="emit('go', 'ordersList')">
|
|
<Icon icon="vuesax-linear:box" size="18" />
|
|
سفارشها
|
|
</button>
|
|
<button type="button" class="acct__action" @click="emit('go', 'transactionsList')">
|
|
<Icon icon="vuesax-linear:receipt-text" size="18" />
|
|
اسناد
|
|
</button>
|
|
<button type="button" class="acct__action" @click="emit('go', 'profileData')">
|
|
<Icon icon="vuesax-linear:user" size="18" />
|
|
پروفایل
|
|
</button>
|
|
</div>
|
|
</template>
|
|
|
|
<template v-else>
|
|
<div class="acct__invite">
|
|
<div class="acct__inviteIcon" aria-hidden="true">
|
|
<Icon icon="vuesax-linear:security-user" size="20" />
|
|
</div>
|
|
<div class="acct__inviteCopy">
|
|
<h3>حساب گرمی شما</h3>
|
|
<p>برای دیدن موجودی، سفارشها و اسناد خود وارد شوید.</p>
|
|
</div>
|
|
<button type="button" class="acct__inviteCta" @click="emit('login')">ورود / ثبتنام</button>
|
|
</div>
|
|
</template>
|
|
</section>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed } from 'vue'
|
|
import Icon from '../icon/Icon.vue'
|
|
import { price } from '../../utils/filters'
|
|
import type { CustomerDetail } from '../../api/client'
|
|
|
|
const props = defineProps<{ customer: CustomerDetail | null }>()
|
|
const emit = defineEmits<{ (e: 'go', route: string): void; (e: 'login'): void }>()
|
|
|
|
const isDebtor = computed(() => (props.customer ? parseFloat(props.customer.goldDebtGrams) > 0 : false))
|
|
const positionLabel = computed(() => (isDebtor.value ? 'مانده بدهی گرمی' : 'مانده بستانکاری گرمی'))
|
|
const grams = computed(() => (props.customer ? Math.abs(parseFloat(props.customer.goldDebtGrams)) : 0))
|
|
const fiat = computed(() => (props.customer ? props.customer.fiatDebtRial.split('.')[0] : '0'))
|
|
</script>
|
|
|
|
<style scoped lang="less">
|
|
.acct {
|
|
border-radius: 20px;
|
|
padding: 18px;
|
|
background: @primary;
|
|
color: #fff;
|
|
box-shadow: 0 22px 44px -32px rgba(20, 22, 26, 0.9);
|
|
}
|
|
|
|
.acct__head {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
justify-content: space-between;
|
|
gap: 12px;
|
|
}
|
|
|
|
.acct__eyebrow {
|
|
font-size: 11px;
|
|
color: rgba(255, 255, 255, 0.55);
|
|
padding-bottom: 7px;
|
|
}
|
|
|
|
.acct__figure {
|
|
font-size: 26px;
|
|
font-weight: 800;
|
|
letter-spacing: 0.3px;
|
|
}
|
|
|
|
.acct__unit {
|
|
font-size: 12px;
|
|
font-weight: 500;
|
|
color: rgba(255, 255, 255, 0.55);
|
|
padding-inline-start: 3px;
|
|
}
|
|
|
|
.acct__seal {
|
|
font-size: 10.5px;
|
|
font-weight: 700;
|
|
padding: 5px 11px;
|
|
border-radius: 999px;
|
|
}
|
|
.acct__seal.is-debtor {
|
|
color: #fff;
|
|
background: @wine;
|
|
}
|
|
.acct__seal.is-creditor {
|
|
color: #fff;
|
|
background: rgba(255, 255, 255, 0.13);
|
|
}
|
|
|
|
.acct__row {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
margin-top: 16px;
|
|
padding-top: 13px;
|
|
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
|
font-size: 12.5px;
|
|
}
|
|
|
|
.acct__rowLabel {
|
|
color: rgba(255, 255, 255, 0.55);
|
|
}
|
|
|
|
.acct__rowValue {
|
|
font-weight: 700;
|
|
}
|
|
.acct__rowValue i {
|
|
font-style: normal;
|
|
font-size: 10px;
|
|
font-weight: 500;
|
|
color: rgba(255, 255, 255, 0.5);
|
|
}
|
|
|
|
.acct__actions {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, 1fr);
|
|
gap: 8px;
|
|
margin-top: 16px;
|
|
}
|
|
|
|
.acct__action {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 6px;
|
|
padding: 11px 4px;
|
|
border: 0;
|
|
cursor: pointer;
|
|
border-radius: 13px;
|
|
font-family: inherit;
|
|
font-size: 11.5px;
|
|
font-weight: 600;
|
|
color: rgba(255, 255, 255, 0.88);
|
|
background: rgba(255, 255, 255, 0.07);
|
|
transition: background 0.18s ease, transform 0.18s ease;
|
|
}
|
|
.acct__action:active {
|
|
transform: scale(0.97);
|
|
}
|
|
|
|
.acct__invite {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 13px;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.acct__inviteIcon {
|
|
width: 40px;
|
|
height: 40px;
|
|
border-radius: 13px;
|
|
display: grid;
|
|
place-items: center;
|
|
color: #fff;
|
|
background: @wine;
|
|
flex: 0 0 auto;
|
|
}
|
|
|
|
.acct__inviteCopy {
|
|
flex: 1 1 150px;
|
|
}
|
|
.acct__inviteCopy h3 {
|
|
margin: 0;
|
|
font-size: 14px;
|
|
font-weight: 700;
|
|
color: #fff;
|
|
}
|
|
.acct__inviteCopy p {
|
|
margin: 5px 0 0;
|
|
font-size: 11.5px;
|
|
line-height: 1.8;
|
|
color: rgba(255, 255, 255, 0.58);
|
|
}
|
|
|
|
.acct__inviteCta {
|
|
flex: 1 1 100%;
|
|
margin-top: 4px;
|
|
padding: 12px;
|
|
border: 0;
|
|
cursor: pointer;
|
|
border-radius: 13px;
|
|
background: #fff;
|
|
color: @ink;
|
|
font-family: inherit;
|
|
font-size: 13px;
|
|
font-weight: 700;
|
|
transition: transform 0.18s ease;
|
|
}
|
|
.acct__inviteCta:active {
|
|
transform: scale(0.98);
|
|
}
|
|
</style>
|