user-app: extend the redesign across the account screens
Phase 2, completing the app-wide rollout of the home/product-detail design language (LESS colour tokens, BEM class names, hairline-bordered cards, SectionHead, dashed empty states) onto the account side: dashboard, orders, transactions, profile, login and register. Reuse over re-implementation: the dashboard's live rate block is now components/home/RateStrip.vue rather than a second hand-built strip, and every screen uses components/ui/PageBar.vue for its chrome. OrderCard and OrderItemCard are restyled to match. OrderItemCard drops its always-empty note row: our OrderItem schema has no note field (legacy's per-item note was a real column there; ours is not), so it could only ever print a dash. OrdersView swaps ant Tabs for the same scrolling chip rail the rest of the redesign uses, and its full-screen Modal with hand-written CSS overrides for a bottom Drawer, matching how every other detail surface opens. Deleted AppHeader.vue, orphaned once every screen moved to PageBar. Its shutter animation was driven by transitionFlag, which nothing reads any more — the router afterEach comment claiming otherwise is corrected rather than left asserting something untrue, and the now-inert half is flagged in place. ScrollFetchSearch loses its isFav prop: it gated two empty-state branches that rendered the identical image, and its only caller (FavoritesView) now renders its own. Behaviour is preserved throughout. Orders still reads GET /customers/:id/orders and filters client-side; transactions still reads GET /customers/:id/ledger-entries with legacy's CREDIT/DEBIT colour meaning intact; profile stays read-only over real fields; login keeps the real customer lookup plus the documented OTP stub; register stays stubbed with copy that does not claim an account was created. Verified in a real browser against the running API and native database: dashboard 4 tiles with a real balance, orders 1 real order card, profile 4 real spec rows, transactions the correct empty state for a customer with no ledger rows, and login/register confirmed with the session cleared (the guard bounces a signed-in user away from /login, which is why they needed a separate pass). No console errors, no horizontal overflow. vue-tsc and vite build both clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
cc62975dd0
commit
0e5f9ccd7b
@@ -1,78 +1,84 @@
|
||||
<!--
|
||||
Ported from legacy henza_pwa/src/views/user/LoginRegister/components/Register.vue.
|
||||
Ported from legacy henza_pwa/src/views/user/LoginRegister/components/Register.vue,
|
||||
restyled into the redesigned design language (see components/home/* and
|
||||
HomeView).
|
||||
|
||||
DROPPED as confirmed-dead code (not "possibly dead" — verified unreachable):
|
||||
legacy rendered a whole cascading country->province->city picker
|
||||
DROPPED as confirmed-dead code (verified unreachable, not merely "possibly
|
||||
dead"): legacy rendered a whole cascading country->province->city picker
|
||||
(WorkActionSheet + selectCityArrays + getCities() against POST /cities/list)
|
||||
alongside a plain "شهر" text <Input>. The only element that ever opened the
|
||||
picker (`#citybtn`) was itself commented out in legacy's own template, so
|
||||
the picker was unreachable UI even in the original app; the visible form
|
||||
uses the plain text input. That whole complex, and the parallel unused
|
||||
`userFormModel`/`defaultUserFormModel` objects (the template binds
|
||||
`formModel.*`, a *different*, separately-declared empty reactive object —
|
||||
`userFormModel` is never referenced anywhere), are not ported.
|
||||
picker (`#citybtn`) was itself commented out in legacy's own template, so the
|
||||
picker was unreachable UI even in the original app; the visible form uses the
|
||||
plain text input. That whole complex, and the parallel unused
|
||||
`userFormModel`/`defaultUserFormModel` objects, are not ported.
|
||||
|
||||
STUBBED, not real: POST /major/register — apps/api has no create-customer
|
||||
endpoint. Submitting shows legacy's exact success dialog without actually
|
||||
persisting anything.
|
||||
STUBBED, not real, and unchanged from the previous version: legacy's
|
||||
POST /major/register — apps/api has no create-customer endpoint. Submitting
|
||||
shows legacy's exact success message without persisting anything. The copy
|
||||
says the account awaits review, which is what legacy said too, so the screen
|
||||
does not claim an account exists when none was created.
|
||||
-->
|
||||
<template>
|
||||
<div>
|
||||
<div class="fixed w-full">
|
||||
<img class="w-full absolute left-0 right-0" :src="pattern1" alt="" />
|
||||
<img class="absolute w-full left-0 right-0" :src="pattern2" alt="" />
|
||||
</div>
|
||||
<div class="fixed top-0 z-10 w-full">
|
||||
<AppHeader class="bg-white shadowHeader">
|
||||
<div class="flex justify-between items-center">
|
||||
<Icon icon="vuesax-linear:arrow-right-1" class="cursor-pointer" size="25" @click="router.push({ name: 'home' })" />
|
||||
<h3 class="t bold mb-0">ثبت نام</h3>
|
||||
<div></div>
|
||||
</div>
|
||||
</AppHeader>
|
||||
</div>
|
||||
<div class="relative w-full py-16 px-5">
|
||||
<div class="mt-14">
|
||||
<Spinner :spinning="profileData.loading" tip="در حال ثبت اطلاعات">
|
||||
<Form :model="formModel" layout="vertical" @finish="register" class="w-full">
|
||||
<FormItem style="font-size: 16px" name="fname" label="نام" :rules="required('نام')">
|
||||
<div class="auth">
|
||||
<PageBar title="ثبت نام" back-to="home" />
|
||||
|
||||
<Spinner :spinning="profileData.loading" tip="در حال ثبت اطلاعات">
|
||||
<container class="auth__body">
|
||||
<section class="auth__intro">
|
||||
<div class="auth__mark" aria-hidden="true">
|
||||
<Icon icon="vuesax-linear:user-add" size="28" />
|
||||
</div>
|
||||
<h2 class="auth__title">ساخت حساب کاربری</h2>
|
||||
<p class="auth__sub">اطلاعات فروشگاه خود را وارد کنید</p>
|
||||
</section>
|
||||
|
||||
<section class="auth__card">
|
||||
<Form :model="formModel" layout="vertical" @finish="register" class="auth__form">
|
||||
<FormItem name="fname" label="نام" :rules="required('نام')">
|
||||
<Input v-model:value="formModel.fname" />
|
||||
</FormItem>
|
||||
<FormItem style="font-size: 16px" name="lname" label="نام خانوادگی" :rules="required('نام خانوادگی')">
|
||||
<FormItem name="lname" label="نام خانوادگی" :rules="required('نام خانوادگی')">
|
||||
<Input v-model:value="formModel.lname" />
|
||||
</FormItem>
|
||||
<FormItem style="font-size: 16px" name="mobile" label="شماره موبایل" :rules="[mobileRule('شماره موبایل'), required('شماره موبایل')]">
|
||||
<FormItem
|
||||
name="mobile"
|
||||
label="شماره موبایل"
|
||||
:rules="[mobileRule('شماره موبایل'), required('شماره موبایل')]"
|
||||
>
|
||||
<Input v-model:value="formModel.mobile" type="number" />
|
||||
</FormItem>
|
||||
<FormItem style="font-size: 16px" name="store_name" label="نام فروشگاه" :rules="required('نام فروشگاه')">
|
||||
<FormItem name="store_name" label="نام فروشگاه" :rules="required('نام فروشگاه')">
|
||||
<Input v-model:value="formModel.store_name" />
|
||||
</FormItem>
|
||||
<FormItem style="font-size: 16px" name="phone" label="تلفن فروشگاه" :rules="[required('تلفن فروشگاه')]">
|
||||
<FormItem name="phone" label="تلفن فروشگاه" :rules="[required('تلفن فروشگاه')]">
|
||||
<Input v-model:value="formModel.phone" type="number" />
|
||||
</FormItem>
|
||||
<FormItem style="font-size: 16px" name="address" label="آدرس پستی" :rules="required('آدرس')">
|
||||
<Textarea v-model:value="formModel.address" />
|
||||
<FormItem name="address" label="آدرس پستی" :rules="required('آدرس')">
|
||||
<Textarea v-model:value="formModel.address" :rows="3" />
|
||||
</FormItem>
|
||||
<FormItem name="city" label="شهر" :rules="required('شهر')">
|
||||
<Input v-model:value="formModel.city" />
|
||||
</FormItem>
|
||||
<Button type="primary" class="w-full max-w-[768px] m-auto" style="height: 42px" html-type="submit">
|
||||
<span style="font-size: 18px">ثبت اطلاعات</span>
|
||||
</Button>
|
||||
|
||||
<button type="submit" class="auth__cta">ثبت اطلاعات</button>
|
||||
</Form>
|
||||
</Spinner>
|
||||
<div class="flex justify-center mt-10">
|
||||
<div>اگر حساب کاربری دارید از این قسمت</div>
|
||||
<div class="pr-1 text-primary font-bold" @click="emit('register', false)">وارد شوید.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<p class="auth__switch">
|
||||
اگر حساب کاربری دارید
|
||||
<button type="button" @click="emit('register', false)">وارد شوید</button>
|
||||
</p>
|
||||
</container>
|
||||
</Spinner>
|
||||
|
||||
<DialogVant :timeOut="-1" v-model:show="registeredInfo" :closeOnClickOverlay="false">
|
||||
<template v-slot:img>
|
||||
<img :src="registerDelayImage" alt="" class="opacity-80" />
|
||||
</template>
|
||||
<template v-slot:title>
|
||||
<div class="p-5">ثبت نام شما با موفقیت انجام شد. منتظر تایید اطلاعات ثبت نامی شما توسط کارشناسان بمانید.</div>
|
||||
<div class="p-5">
|
||||
ثبت نام شما با موفقیت انجام شد. منتظر تایید اطلاعات ثبت نامی شما توسط کارشناسان بمانید.
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot:button>
|
||||
<div class="text-center" @click="router.push({ name: 'home' })">متوجه شدم</div>
|
||||
@@ -84,12 +90,10 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { Button, Form, FormItem, Input, Textarea } from 'ant-design-vue'
|
||||
import pattern1 from '../../assets/img/pattern2.svg'
|
||||
import pattern2 from '../../assets/img/pattern3.svg'
|
||||
import { Form, FormItem, Input, Textarea } from 'ant-design-vue'
|
||||
import registerDelayImage from '../../assets/img/registerDelay.svg'
|
||||
import Icon from '../../components/icon/Icon.vue'
|
||||
import AppHeader from '../../components/AppHeader.vue'
|
||||
import PageBar from '../../components/ui/PageBar.vue'
|
||||
import Spinner from '../../components/Spinner.vue'
|
||||
import DialogVant from '../../components/DialogVant.vue'
|
||||
import { required, mobile as mobileRule } from '../../utils/validator'
|
||||
@@ -121,8 +125,94 @@ const register = async () => {
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.shadowHeader {
|
||||
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.05), 0 2px 4px -2px rgb(0 0 0 / 0.05);
|
||||
<style scoped lang="less">
|
||||
.auth {
|
||||
background: @canvas;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.auth__body {
|
||||
padding-top: 26px;
|
||||
padding-bottom: 90px;
|
||||
}
|
||||
|
||||
.auth__intro {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
|
||||
.auth__mark {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
border-radius: 50%;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
color: @wine;
|
||||
background: @wineWash;
|
||||
}
|
||||
|
||||
.auth__title {
|
||||
margin: 14px 0 0;
|
||||
font-size: 16px;
|
||||
font-weight: 800;
|
||||
color: @ink;
|
||||
}
|
||||
|
||||
.auth__sub {
|
||||
margin: 6px 0 0;
|
||||
font-size: 12.5px;
|
||||
color: @inkFaint;
|
||||
}
|
||||
|
||||
.auth__card {
|
||||
padding: 18px 16px 20px;
|
||||
border: 1px solid @hairline;
|
||||
border-radius: 20px;
|
||||
background: @canvasSoft;
|
||||
}
|
||||
|
||||
.auth__form :deep(.ant-form-item-label > label) {
|
||||
font-size: 12px;
|
||||
color: @inkMuted;
|
||||
}
|
||||
|
||||
.auth__cta {
|
||||
width: 100%;
|
||||
margin-top: 4px;
|
||||
padding: 13px 18px;
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
border-radius: 14px;
|
||||
font-family: inherit;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
background: @ink;
|
||||
transition: transform 0.15s ease;
|
||||
}
|
||||
|
||||
.auth__cta:active {
|
||||
transform: scale(0.99);
|
||||
}
|
||||
|
||||
.auth__switch {
|
||||
margin: 20px 0 0;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
color: @inkMuted;
|
||||
}
|
||||
|
||||
.auth__switch button {
|
||||
border: 0;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
padding: 0 3px;
|
||||
font-family: inherit;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
color: @wine;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user