SearchView: Removed the dynamic collection-tile grid (e.g. "پرفروشهای این هفته") and the "نتایج / N محصول" section header from the UI. Underlying data/filtering logic untouched.
DashboardView ("میز کار"): Rebuilt from scratch with a new structure, distinct from the old card+grid layout but visually aligned with HomeView (same blurred bar, @ink/@wine palette, staged reveal animation on mount):
Single hero card (ink→wine gradient) showing balance, gold/fiat debt, and identity — no quick-action icons inside it anymore.
Live gold rate folded into a slim inline row at the bottom instead of a titled section.
Iterated shadow/spacing on the hero card per feedback (softer, less clipped).
DialogVant / DialogVantOneButton (shared modal components, used in 7+ call sites: Dashboard, Cart, SingleProduct, Register, App): Replaced Vant's default dialog chrome with the app's own rounded-card language — circular icon badge for the illustration, pill-shaped primary/secondary buttons. No call-site markup changed.
LoginView: Rebuilt from scratch — full-bleed dark hero (brand + step copy) overlapped by a floating white form sheet, animated crossfade transition between the mobile-number and OTP steps, same staged entrance animation as Home/Dashboard. All auth logic (API check, OTP stub, session login) unchanged.
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
<!--
|
||||
Product card from the design: a soft grey rounded panel with the piece
|
||||
centred on it, the title beneath, then a meta line of weight + making charge.
|
||||
|
||||
On honesty of the meta line — the design mocks up a struck-through "اجرت ۱۵٪"
|
||||
next to a red "اجرت ۱۰٪", i.e. a discounted wage. The API exposes no
|
||||
promotion or discount data today (useProduct's `hasDiscountWage` is always
|
||||
null, see its header), so the struck-through half only renders when a real
|
||||
`wageBefore` is passed in. Until the backend returns one, the card shows the
|
||||
variant's genuine wage alone — the layout is identical, minus an invented
|
||||
number.
|
||||
-->
|
||||
<template>
|
||||
<article class="panel" @click="emit('open', value)">
|
||||
<div class="panel__art">
|
||||
<img v-lazy="image" :alt="title" />
|
||||
</div>
|
||||
|
||||
<h3 class="panel__title">{{ title }}</h3>
|
||||
|
||||
<div class="panel__meta">
|
||||
<span class="panel__weight">{{ min_gram }} گرم</span>
|
||||
<template v-if="wage != null">
|
||||
<span class="panel__sep" aria-hidden="true"></span>
|
||||
<span v-if="wageBefore != null" class="panel__wageOld">اجرت {{ format(wageBefore) }}٪</span>
|
||||
<span class="panel__wage">{{ format(wage) }}٪ اجرت</span>
|
||||
</template>
|
||||
</div>
|
||||
</article>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useProduct } from '../../composables/useProduct'
|
||||
import type { ProductSummary } from '../../api/client'
|
||||
|
||||
const props = defineProps<{ value: ProductSummary; wageBefore?: number | null }>()
|
||||
const emit = defineEmits<{ (e: 'open', value: ProductSummary): void }>()
|
||||
|
||||
const { image, title, min_gram, wage } = useProduct(props.value)
|
||||
|
||||
// Whole percents print bare (۱۰٪), fractional ones keep two places (۱۰.۵٪).
|
||||
function format(v: number) {
|
||||
return v % 1 === 0 ? String(v) : v.toFixed(2)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.panel {
|
||||
cursor: pointer;
|
||||
border-radius: 32px;
|
||||
background: @hairlineSoft;
|
||||
padding: 18px 16px 16px;
|
||||
text-align: center;
|
||||
transition: transform 0.2s ease, background 0.2s ease;
|
||||
}
|
||||
|
||||
.panel:active {
|
||||
transform: scale(0.985);
|
||||
}
|
||||
|
||||
.panel__art {
|
||||
height: 148px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.panel__art img {
|
||||
max-width: 78%;
|
||||
max-height: 100%;
|
||||
object-fit: contain;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.panel__title {
|
||||
margin: 14px 0 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: @ink;
|
||||
line-height: 1.6;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.panel__meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
padding-top: 9px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.panel__weight {
|
||||
color: @inkSoft;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.panel__sep {
|
||||
width: 1px;
|
||||
height: 12px;
|
||||
background: @hairline;
|
||||
}
|
||||
|
||||
.panel__wageOld {
|
||||
color: @inkFaint;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.panel__wage {
|
||||
color: @danger;
|
||||
font-weight: 600;
|
||||
font-size: 12px !important;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user