parity(apps+api): report + report/detail on the internal ledger [ref: henza_pwa views/report]

Ports "گزارش" end to end (D24), the last missing app page.

In the reference this feature computes nothing: Customer\TahesabController
proxies an external accounting system (hesab.henzagold.com and a bare IP at
31.7.68.147:3030) with TLS verification disabled, a bearer token hardcoded in
the source and a URL-embedded secret, keyed on Customer.mcode. The target has
no such system and no mcode, so per the owner's option الف this is built on our
own ledger with no external connection.

API — customer/me/report{,/detail,/balances,/:id}
- one row per CONFIRMED ledger entry with the running gold and rial balance
  after it, newest first as the reference displayed it
- only confirmed entries count, the same rule the cached
  Customer.goldDebtGrams/fiatDebtRial follow, so the statement's closing
  balance agrees with the figure shown everywhere else in the app
- fields the target has no source for (foreign currency, نام کارساخته,
  جنس فلز, the external system's internal ids) are null/zero and the UI OMITS
  the row rather than rendering a fabricated value (REP-01)

SEC-16, NOT ported: the reference's detail($id) took the factor code from the
URL and performed no ownership check at all — it never consults auth() — so any
signed-in customer could read any other customer's document by guessing a code.
Here the id is only a filter on top of a customerId scope from the token.
Tested in both directions.

Apps (both, template+script byte-identical, per-app styling only)
- ReportView with the reference's two tabs, its card rows and its «جزئیات»
  modal; ReportDocument for one document
- routes /report and /report/detail, the latter opening the second tab
- dashboard entry (v1 tile, v2 row), shown to every signed-in customer since
  the reference's hasMCode() gate has no target equivalent

Verified: build 5/5 · jest 45/45 · report 40/40 (new) ·
complete-profile 38/38 · apps smoke 43/43 · typecheck clean on all four apps.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
s.esmaeili
2026-09-23 01:49:49 +03:30
co-authored by Claude Opus 5
parent 5ad1083aee
commit 3f549f1749
99 changed files with 2230 additions and 104 deletions
+4 -6
View File
@@ -153,6 +153,7 @@ All green on `release/delivery`:
| `test-sales-expert-roundtrip.cjs` | **33/33** |
| `test-sales-expert-app-login.cjs` — expert app login (D21) | **36/36** |
| `test-complete-profile.cjs` — «تکمیل پروفایل» | **38/38** |
| `test-report.cjs` — «گزارش» | **40/40** |
| `test-name-trigger.cjs` | **9/9** |
| typecheck (api, admin-panel, user-app, user-app-v2) | ✅ clean |
@@ -177,14 +178,10 @@ the customer's balances end exactly as they started.
Nothing here blocks the delivery. Full detail in `docs/parity/ISSUES.md`.
### Missing app pages (not started)
### Missing app pages
Present in the reference PWA, absent in both apps. Listed in the owner's own
priority order:
**None.** Every page the reference PWA has now exists in both apps.
| Page | Reference | Notes |
|---|---|---|
| `report` + `report/detail` | `henza_pwa/src/views/report/` | The accounting statement — a store plus two components (`Accounting.vue`, `AccountingDetail.vue`). The largest of the four. |
### Delivered tonight
@@ -195,6 +192,7 @@ priority order:
| **«مشتریان من» (customerChoice)** | ✅ Done in both apps. Their referred customers, searchable, with a read-only detail sheet. |
| **APP-02 — admin home slider in v2** | ✅ Fixed. v2 now prefers admin-configured slides and keeps its category-derived hero as the fallback. |
| **«تکمیل پروفایل» (complete_profile)** | ✅ Done in both apps. Three document uploads (جواز کسب، سردر مغازه، کارت ملی), then the profile is marked verified. Reached from the profile screen, and only while the documents are missing — exactly the reference's condition. |
| **«گزارش» (report + report/detail)** | ✅ Done in both apps. Two tabs («کلیات حساب» / «جزئیات حساب»), a running gold and rial balance per document, and a per-document detail sheet. Built on the **internal ledger** (owner's option الف) — no connection to the external accounting system the reference proxied. See D24. |
An expert's own order lands on their **own trading account**, with the making
charge from `AdminUser.wagePercent` and the credit limit from
+275
View File
@@ -0,0 +1,275 @@
/**
* "گزارش" — the account statement (D24).
*
* The reference proxied an external accounting system
* (henza_server Customer/TahesabController). The owner chose option الف: build
* the same UI and flow over the target's OWN ledger, with no external call.
*
* Covers what the owner asked for per page — opening, the empty state, the
* error state and the main flow — plus what makes a statement trustworthy:
*
* 1. empty state: a customer with no entries gets an empty result, not a 500
* 2. main flow: entries appear with the right in/out columns
* 3. the RUNNING BALANCE is correct, and its last value agrees with the
* cached Customer.goldDebtGrams / fiatDebtRial the rest of the app shows
* 4. UNCONFIRMED entries are excluded, exactly as they are from the cached
* balance
* 5. the detail list and the single-document read
* 6. SEC-16: another customer's document id returns NOTHING. The reference's
* detail() took the factor code from the URL with no ownership check at
* all, so any signed-in customer could read anyone's document.
* 7. no token is a 401 on every route
* 8. balances endpoint agrees with the customer row
*
* Every Persian string is a literal here and travels as UTF-8 JSON (D15).
*
* Requires the API running WITH OTP_MASTER_CODE set.
* Usage: node scripts/test-report.cjs [apiBaseUrl] [masterCode]
*/
const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();
const API = (process.argv[2] || 'http://localhost:3000/api').replace(/\/$/, '');
const MASTER = process.argv[3] || '1379';
let pass = 0, fail = 0;
const failures = [];
const chk = (c, m) => {
if (c) { pass++; console.log(' PASS ' + m); }
else { fail++; failures.push(m); console.log(' FAIL ' + m); }
};
const step = (t) => console.log('\n' + t);
const call = async (method, p, body, token) => {
const res = await fetch(`${API}/${p}`, {
method,
headers: {
'Content-Type': 'application/json',
...(token ? { Authorization: 'Bearer ' + token } : {}),
},
body: body === undefined ? undefined : JSON.stringify(body),
});
const text = await res.text();
let payload = null;
try { payload = JSON.parse(text); } catch { /* empty */ }
return { status: res.status, ok: res.ok, body: payload, raw: text };
};
const signIn = (mobile) =>
call('POST', 'customer/auth/verify-otp', { username: mobile, password: MASTER });
const made = { customers: [], entries: [] };
const uniq = String(Date.now()).slice(-7);
(async () => {
step('SETUP — two customers; one with a ledger, one with none');
const mkCustomer = async (suffix, name) => {
const c = await prisma.customer.create({
data: {
fullName: name,
firstName: name.split(' ')[0],
lastName: name.split(' ').slice(1).join(' '),
mobile: `0919${uniq.slice(0, 3)}${suffix}`,
nationalCode: `nc${uniq}${suffix}`,
passwordHash: '', kind: 'APP_SHOPKEEPER', isActive: true,
goldCreditLimitGrams: '500',
},
});
made.customers.push(c.id);
return c;
};
const owner = await mkCustomer('11', 'مشتری گزارش');
const other = await mkCustomer('22', 'مشتری دیگر');
const empty = await mkCustomer('33', 'مشتری بدون سند');
console.log(` owner: ${owner.fullName} · other: ${other.fullName} · empty: ${empty.fullName}`);
// ── 7. NO TOKEN ─────────────────────────────────────────────────────────
step('7 — every route requires a session');
for (const path of ['customer/me/report', 'customer/me/report/detail', 'customer/me/report/balances']) {
const r = await call('GET', path);
chk(r.status === 401, `GET ${path} with no token -> ${r.status} (expected 401)`);
}
// ── 1. EMPTY STATE ──────────────────────────────────────────────────────
step('1 — EMPTY STATE: a customer with no ledger entries');
await call('POST', 'customer/auth/request-otp', { username: empty.mobile });
const emptyLogin = await signIn(empty.mobile);
chk(emptyLogin.ok, `the empty customer signs in -> ${emptyLogin.status}`);
const emptyToken = emptyLogin.body?.token;
const emptyReport = await call('GET', 'customer/me/report', undefined, emptyToken);
chk(emptyReport.ok, `GET report -> ${emptyReport.status}`);
chk(Array.isArray(emptyReport.body?.result) && emptyReport.body.result.length === 0,
'the statement is an empty list, not an error');
chk(emptyReport.body?.count === 0, `count is 0 (got ${emptyReport.body?.count})`);
const emptyDetail = await call('GET', 'customer/me/report/detail', undefined, emptyToken);
chk(emptyDetail.ok && emptyDetail.body?.result?.length === 0,
`the detail tab is empty too -> ${emptyDetail.status}`);
// ── BUILD A LEDGER ──────────────────────────────────────────────────────
step('SETUP — a ledger for the owner: gold out, gold in, rial in, plus one UNCONFIRMED');
const mkEntry = async (data) => {
const e = await prisma.ledgerEntry.create({ data: { customerId: owner.id, ...data } });
made.entries.push(e.id);
return e;
};
// +12.5 gold owed
await mkEntry({
currency: 'GOLD_GRAM', direction: 'DEBIT', sourceType: 'ORDER_STOCK',
amount: '12.5', confirmed: true, confirmedAt: new Date(),
note: 'سفارش اول',
});
// -4.25 gold (a melted-gold repayment, with the document metadata)
await mkEntry({
currency: 'GOLD_GRAM', direction: 'CREDIT', sourceType: 'REPAYMENT_MELTED_GOLD',
amount: '4.25', confirmed: true, confirmedAt: new Date(),
karatPerMille: 750, originalValue: '4.3', labName: 'آزمایشگاه مرکزی', hallmark: 'A-1001',
note: 'طلای آبشده',
});
// +1,000,000 rial owed
await mkEntry({
currency: 'RIAL', direction: 'DEBIT', sourceType: 'ADJUSTMENT',
amount: '1000000', confirmed: true, confirmedAt: new Date(),
note: 'اصلاحیه ریالی',
});
// An UNCONFIRMED entry that must NOT appear anywhere.
const pending = await mkEntry({
currency: 'GOLD_GRAM', direction: 'DEBIT', sourceType: 'ORDER_STOCK',
amount: '99.999', confirmed: false,
note: 'سند تاییدنشده',
});
// The cached balances the rest of the app shows.
await prisma.customer.update({
where: { id: owner.id },
data: { goldDebtGrams: '8.25', fiatDebtRial: '1000000' },
});
// One document for the OTHER customer, for the cross-read test.
const foreign = await prisma.ledgerEntry.create({
data: {
customerId: other.id, currency: 'GOLD_GRAM', direction: 'DEBIT',
sourceType: 'ORDER_STOCK', amount: '7', confirmed: true, confirmedAt: new Date(),
note: 'سند مشتری دیگر',
},
});
made.entries.push(foreign.id);
// ── 2/3/4. MAIN FLOW ────────────────────────────────────────────────────
step('2 — MAIN FLOW: the statement');
await call('POST', 'customer/auth/request-otp', { username: owner.mobile });
const login = await signIn(owner.mobile);
chk(login.ok, `the owner signs in -> ${login.status}`);
const token = login.body?.token;
const rep = await call('GET', 'customer/me/report', undefined, token);
chk(rep.ok, `GET report -> ${rep.status}`);
const rows = rep.body?.result ?? [];
chk(rows.length === 3, `three CONFIRMED entries came back (got ${rows.length})`);
// Newest first, as the reference displayed it.
chk(rows[0]?.note === 'اصلاحیه ریالی', `newest first: top row is "${rows[0]?.note}"`);
const gold = rows.find((r) => r.note === 'سفارش اول');
chk(gold?.geram_kh === '12.500', `a gold DEBIT lands in geram_kh (${gold?.geram_kh})`);
chk(gold?.geram_v === '0.000', 'and not in geram_v');
const back = rows.find((r) => r.note === 'طلای آبشده');
chk(back?.geram_v === '4.250', `a gold CREDIT lands in geram_v (${back?.geram_v})`);
const rialRow = rows.find((r) => r.note === 'اصلاحیه ریالی');
chk(rialRow?.rial_kh === '1000000.00', `a rial DEBIT lands in rial_kh (${rialRow?.rial_kh})`);
step('4 — UNCONFIRMED entries are excluded');
chk(!rows.some((r) => r.note === 'سند تاییدنشده'),
'the unconfirmed 99.999g entry does NOT appear in the statement');
step('3 — the RUNNING BALANCE');
// Oldest first: +12.5, then -4.25 => 8.25. Rows come back newest-first.
chk(gold?.tahesab_T === '12.500', `after the first entry the gold balance is 12.500 (got ${gold?.tahesab_T})`);
chk(back?.tahesab_T === '8.250', `after the repayment it is 8.250 (got ${back?.tahesab_T})`);
const cached = await prisma.customer.findUnique({ where: { id: owner.id } });
chk(String(Number(back.tahesab_T)) === String(Number(cached.goldDebtGrams)),
`and it agrees with the cached Customer.goldDebtGrams (${cached.goldDebtGrams})`);
chk(rialRow?.tahesab_P === '1000000.00',
`the rial balance is 1000000.00 (got ${rialRow?.tahesab_P})`);
chk(String(Number(rialRow.tahesab_P)) === String(Number(cached.fiatDebtRial)),
`and it agrees with the cached Customer.fiatDebtRial (${cached.fiatDebtRial})`);
step('8 — the balances endpoint agrees with the customer row');
const bal = await call('GET', 'customer/me/report/balances', undefined, token);
chk(bal.ok, `GET balances -> ${bal.status}`);
const goldBal = bal.body?.result?.find((r) => r.arz === 'gold');
const rialBal = bal.body?.result?.find((r) => r.arz === 'IRR');
chk(goldBal?.mandeh === '8.250', `gold balance ${goldBal?.mandeh}`);
chk(rialBal?.mandeh === '1000000.00', `rial balance ${rialBal?.mandeh}`);
// ── 5. DETAIL ───────────────────────────────────────────────────────────
step('5 — the detail tab and one document');
const det = await call('GET', 'customer/me/report/detail', undefined, token);
chk(det.ok, `GET detail -> ${det.status}`);
chk(det.body?.result?.length === 3, `three documents (got ${det.body?.result?.length})`);
chk(!det.body?.result?.some((d) => d.note === 'سند تاییدنشده'),
'the unconfirmed entry is excluded here too');
const melted = det.body?.result?.find((d) => d.note === 'طلای آبشده');
chk(melted?.ayar === 750, `the melted-gold document carries its عیار (${melted?.ayar})`);
chk(melted?.name_az === 'آزمایشگاه مرکزی', `and its lab name (${melted?.name_az})`);
chk(melted?.sh_sharti === 'A-1001', `and its hallmark (${melted?.sh_sharti})`);
chk(melted?.vazn === '4.300',
`وزن خالص is the PRE-normalization weight, as a paper document states (${melted?.vazn})`);
chk(melted?.nO_kar === null && melted?.jens_felez === null,
'fields the target cannot know are null, never invented (REP-01)');
const one = await call('GET', `customer/me/report/${back.factor_Code}`, undefined, token);
chk(one.ok, `GET one document -> ${one.status}`);
chk(one.body?.result?.length === 1, `exactly one row came back (got ${one.body?.result?.length})`);
chk(one.body?.result?.[0]?.factor_Code === back.factor_Code, 'and it is the one asked for');
// ── 6. SEC-16 ───────────────────────────────────────────────────────────
step("6 — SEC-16: another customer's document is NOT readable");
const stolen = await call('GET', `customer/me/report/${foreign.id}`, undefined, token);
chk(stolen.ok, `the request itself succeeds -> ${stolen.status}`);
chk(stolen.body?.result?.length === 0,
"but it returns NOTHING — the id is only a filter on top of the token's scope");
// And the reverse direction, so the scope is not accidentally one-way.
await call('POST', 'customer/auth/request-otp', { username: other.mobile });
const otherLogin = await signIn(other.mobile);
const otherToken = otherLogin.body?.token;
const reverse = await call('GET', `customer/me/report/${back.factor_Code}`, undefined, otherToken);
chk(reverse.body?.result?.length === 0,
"and the other customer cannot read the owner's document either");
const otherRep = await call('GET', 'customer/me/report', undefined, otherToken);
chk(otherRep.body?.result?.length === 1,
`the other customer sees only their OWN one entry (got ${otherRep.body?.result?.length})`);
// ── CLEANUP ─────────────────────────────────────────────────────────────
step('CLEANUP');
await prisma.ledgerEntry.deleteMany({ where: { id: { in: made.entries } } });
await prisma.customerOtp.deleteMany({ where: { customerId: { in: made.customers } } });
await prisma.customer.deleteMany({ where: { id: { in: made.customers } } });
console.log(
` deleted ${made.entries.length} ledger entr(ies) and ${made.customers.length} customer(s). ` +
'All were created by this run; no pre-existing data was touched.',
);
void pending;
console.log(`\n${'='.repeat(60)}`);
console.log(`REPORT: passed ${pass} failed ${fail}`);
if (fail) { console.log('\nFailures:'); failures.forEach((f) => console.log(' - ' + f)); }
console.log('='.repeat(60));
await prisma.$disconnect();
process.exit(fail ? 1 : 0);
})().catch(async (e) => {
console.error('\nABORTED:', e);
await prisma.$disconnect();
process.exit(1);
});
+2
View File
@@ -5,6 +5,7 @@ import { CustomersModule } from './modules/customers/customers.module';
import { CustomerAuthModule } from './modules/customer-auth/customer-auth.module';
import { SalesExpertAppModule } from './modules/sales-expert-app/sales-expert-app.module';
import { CustomerProfileModule } from './modules/customer-profile/customer-profile.module';
import { CustomerReportModule } from './modules/customer-report/customer-report.module';
import { SmsModule } from './modules/sms/sms.module';
import { OrdersModule } from './modules/orders/orders.module';
import { AccountingModule } from './modules/accounting/accounting.module';
@@ -56,6 +57,7 @@ import { SalesAgentModule } from './modules/sales-agent/sales-agent.module';
CustomerAuthModule,
SalesExpertAppModule,
CustomerProfileModule,
CustomerReportModule,
SalesAgentModule,
OrdersModule,
AccountingModule,
@@ -0,0 +1,59 @@
import { Controller, Get, Param, Query } from '@nestjs/common';
import { CustomerReportService } from './customer-report.service';
import { CurrentCustomer, CustomerAuth } from '../customer-auth/customer.guards';
import type { AuthenticatedCustomer } from '../customer-auth/customer-jwt.strategy';
/**
* "گزارش" — the customer's own account statement.
*
* Legacy endpoints, all inside the `auth:api-customer` group
* (henza_server routes/api.php:108-110):
* GET tahesab/me -> TahesabController::mandeh
* GET fin_tahesab/table -> TahesabController::index
* GET fin_tahesab/my_detail/{n} -> TahesabController::my_detail
* GET fin_tahesab/detail/{id} -> TahesabController::detail
*
* Every one of those proxied an external accounting system keyed on
* `Customer.mcode`. These read the target's own ledger instead (option الف,
* D24) — no external call, no `mcode`, and the customer always comes from the
* token. `fin_tahesab/detail/{id}` took the factor code straight from the URL
* with **no ownership check at all** (`detail()` never looks at `auth()`), so
* any signed-in customer could read any other customer's document by guessing
* a code. Here the id is only ever a filter on top of a customerId scope, so
* someone else's id returns nothing. Recorded as SEC-16.
*/
@Controller('customer/me/report')
export class CustomerReportController {
constructor(private readonly report: CustomerReportService) {}
/** "کلیات حساب" — the running statement. */
@CustomerAuth()
@Get()
summary(@CurrentCustomer() me: AuthenticatedCustomer, @Query('page') page?: string) {
return this.report.summary(me.id, Number(page) || 1);
}
/** "جزئیات حساب" — the whole detail list (the second tab). */
@CustomerAuth()
@Get('detail')
detailList(@CurrentCustomer() me: AuthenticatedCustomer, @Query('page') page?: string) {
return this.report.detail(me.id, undefined, Number(page) || 1);
}
/** The current balances, for the statement header. */
@CustomerAuth()
@Get('balances')
balances(@CurrentCustomer() me: AuthenticatedCustomer) {
return this.report.balances(me.id);
}
/**
* One document. Declared last so the literal routes above are matched first —
* Nest resolves in declaration order.
*/
@CustomerAuth()
@Get(':id')
detail(@Param('id') id: string, @CurrentCustomer() me: AuthenticatedCustomer) {
return this.report.detail(me.id, id);
}
}
@@ -0,0 +1,12 @@
import { Module } from '@nestjs/common';
import { PrismaModule } from '../../prisma/prisma.module';
import { CustomerReportController } from './customer-report.controller';
import { CustomerReportService } from './customer-report.service';
/** "گزارش" — the customer's own account statement, from the internal ledger (D24). */
@Module({
imports: [PrismaModule],
controllers: [CustomerReportController],
providers: [CustomerReportService],
})
export class CustomerReportModule {}
@@ -0,0 +1,244 @@
import { Injectable } from '@nestjs/common';
import { Prisma } from '@prisma/client';
import { PrismaService } from '../../prisma/prisma.service';
/**
* "گزارش" — the customer's account statement.
*
* ── Why this is built on the internal ledger ───────────────────────────────
*
* In the reference this whole feature is a PROXY. `Customer\TahesabController`
* (henza_server app/Http/Controllers/Customer/TahesabController.php) forwards
* every call to an external accounting system — `hesab.henzagold.com` and a
* bare IP at `31.7.68.147:3030` — with `Http::withoutVerifying()` (TLS
* verification off), a bearer token hardcoded in the source, and a URL-embedded
* `sfx` secret. It computes nothing: the PWA renders whatever that system
* returns, keyed on `Customer.mcode`, its id in that other system.
*
* The target has no such system and no `mcode`. The owner chose option الف:
* build the reference's UI and flow over OUR OWN ledger, with no external
* connection. So this service reproduces the statement's SHAPE — the same field
* names the PWA binds to (`henza_pwa/src/type/accounting.ts`) — from
* `LedgerEntry`, which is the target's system of record for the same facts.
*
* Nothing here is invented: every figure is computed from confirmed ledger
* entries. Where the external system carried a column the target has no
* equivalent for (ارز/foreign currency, وزن پلاستیک, and the internal
* bookkeeping ids `gid`/`rec`/`reg`), the field is present and ZERO/null rather
* than fabricated, so the UI binds without pretending to know something it does
* not. Recorded as REP-01 in ISSUES.md.
*/
@Injectable()
export class CustomerReportService {
constructor(private readonly prisma: PrismaService) {}
/** The reference's page size (report/index.vue:96). */
private static readonly LIMIT = 50;
/**
* "کلیات حساب" — one row per ledger entry, oldest first, each carrying the
* running balance AFTER it.
*
* The running balance is why this cannot be a plain paginated query: a row's
* `tahesab_T` depends on every entry before it. Entries are therefore folded
* in chronological order from the beginning of the account, and the requested
* page is sliced out afterwards. At the row counts this app deals with
* (one customer's own documents) that is cheap; if a customer ever
* accumulates enough entries for it to matter, the fold should move into a
* stored running total. Noted in ISSUES.md as REP-02.
*
* The reference's own list arrives oldest-first and is then `.reverse()`d for
* display (report/index.vue:191), so the app shows newest first. Same here.
*/
async summary(customerId: string, page = 1) {
const entries = await this.prisma.ledgerEntry.findMany({
// Only confirmed entries move a balance — the same rule the cached
// Customer.goldDebtGrams / fiatDebtRial follow, so the statement's final
// balance agrees with the figure shown everywhere else in the app.
where: { customerId, confirmed: true },
orderBy: [{ createdAt: 'asc' }, { id: 'asc' }],
include: { order: { select: { orderNumber: true } } },
});
let goldRunning = new Prisma.Decimal(0);
let rialRunning = new Prisma.Decimal(0);
const rows = entries.map((e, index) => {
const amount = new Prisma.Decimal(e.amount);
const isGold = e.currency === 'GOLD_GRAM';
// DEBIT increases what the customer owes; CREDIT reduces it. The same
// convention the ledger itself documents (schema.prisma:94-97).
const signed = e.direction === 'DEBIT' ? amount : amount.negated();
if (isGold) goldRunning = goldRunning.plus(signed);
else rialRunning = rialRunning.plus(signed);
return {
id: index + 1,
// The reference keyed the detail lookup on factor_Code; here it is the
// entry's own id, so the detail call needs nothing else from the client.
factor_Code: e.id,
sh_factor: e.order?.orderNumber ?? e.id.slice(-8),
tarikh: e.createdAt.toISOString(),
// Gold in / out, as separate positive columns — the reference showed
// them on two lines (Accounting.vue:21-22).
geram_v: isGold && e.direction === 'CREDIT' ? amount.toFixed(3) : '0.000',
geram_kh: isGold && e.direction === 'DEBIT' ? amount.toFixed(3) : '0.000',
rial_v: !isGold && e.direction === 'CREDIT' ? amount.toFixed(2) : '0.00',
rial_kh: !isGold && e.direction === 'DEBIT' ? amount.toFixed(2) : '0.00',
// Running balances. The reference colours these by sign
// (Accounting.vue:29, :46), so the sign must be preserved.
tahesab_T: goldRunning.toFixed(3),
tahesab_P: rialRunning.toFixed(2),
// Present so the UI binds, but the target has no foreign-currency
// ledger — always zero rather than invented. REP-01.
rial_V2: '0.00',
rial_Kh2: '0.00',
tahesabP2: '0.00',
sourceType: e.sourceType,
note: e.note,
};
});
// Newest first, as the reference displayed it.
rows.reverse();
const start = (Math.max(1, page) - 1) * CustomerReportService.LIMIT;
return {
result: rows.slice(start, start + CustomerReportService.LIMIT),
count: rows.length,
page: Math.max(1, page),
limit: CustomerReportService.LIMIT,
};
}
/**
* "جزئیات حساب" — the per-document detail.
*
* With no id, this is the whole list the second tab renders (the reference's
* `my_detail`); with one, it is the single document behind the «جزئیات» link
* (its `GetHesabDetailByFactorCode`).
*
* Scoped on customerId in the WHERE clause, so an id belonging to someone
* else simply returns nothing — ids stay unenumerable, and no id is trusted
* from the client beyond being a filter.
*/
async detail(customerId: string, entryId?: string, page = 1) {
const where: Prisma.LedgerEntryWhereInput = {
customerId,
confirmed: true,
...(entryId ? { id: entryId } : {}),
};
const entries = await this.prisma.ledgerEntry.findMany({
where,
orderBy: [{ createdAt: 'desc' }, { id: 'desc' }],
...(entryId
? {}
: {
skip: (Math.max(1, page) - 1) * CustomerReportService.LIMIT,
take: CustomerReportService.LIMIT,
}),
include: {
order: {
select: {
orderNumber: true,
totalGoldWeightGrams: true,
wageWeightGrams: true,
},
},
},
});
const result = entries.map((e) => {
const amount = new Prisma.Decimal(e.amount);
const isGold = e.currency === 'GOLD_GRAM';
return {
factor_Code: e.id,
sh_factor: e.order?.orderNumber ?? e.id.slice(-8),
tarikh: e.createdAt.toISOString(),
/// Net weight. For a melted-gold repayment the ledger keeps the weight
/// as handed over, BEFORE karat normalization (schema.prisma:685), which
/// is what a paper document states; `amount` is the normalized figure.
vazn: isGold ? (e.originalValue ?? amount).toFixed(3) : '0.000',
/// Purity, for the documents that carry one.
ayar: e.karatPerMille ?? null,
no: SOURCE_LABELS[e.sourceType] ?? e.sourceType,
/// Hallmark and lab — the target ledger carries both, from the same
/// legacy `ang` / `lab` columns the reference's document form had.
sh_sharti: e.hallmark,
name_az: e.labName,
/// Gold in / out for this document, normalized to 750 as the reference's
/// tabdil750 columns were.
tabdil750_v: isGold && e.direction === 'CREDIT' ? amount.toFixed(3) : '0.000',
tabdil750_kh: isGold && e.direction === 'DEBIT' ? amount.toFixed(3) : '0.000',
/// Unit price at the time, for the documents that have one.
fi: e.pricePerGramRialAtEntry ? e.pricePerGramRialAtEntry.toFixed(2) : null,
fiF: e.priceRial ? e.priceRial.toFixed(2) : null,
/// The making charge the order carried, where this entry came from one.
Darsad_Talayee: e.order?.wageWeightGrams ? e.order.wageWeightGrams.toFixed(3) : null,
accountName: e.accountName,
bankName: e.bankName,
transferTo: e.transferTo,
receivedAt: e.receivedAt ? e.receivedAt.toISOString() : null,
note: e.note,
/// No equivalent in the target — shown as null, never invented. REP-01.
nO_kar: null,
jens_felez: null,
Darsad: null,
maliatDarsad: null,
};
});
return { result, page: Math.max(1, page), limit: CustomerReportService.LIMIT };
}
/**
* "مانده" — the current balances.
*
* Ports the shape of TahesabController::mandeh, which answered a `result`
* array of `{arz, mandeh}`. The reference multiplied the external system's
* figures by -1 to flip its sign convention; here the cached customer
* balances are already in the app's own convention (positive = owes), so no
* flip is applied and the figure matches every other screen.
*/
async balances(customerId: string) {
const c = await this.prisma.customer.findUnique({
where: { id: customerId },
select: { goldDebtGrams: true, fiatDebtRial: true },
});
return {
status: 200,
message: '',
result: [
{ arz: 'IRR', mandeh: (c?.fiatDebtRial ?? new Prisma.Decimal(0)).toFixed(2) },
{ arz: 'gold', mandeh: (c?.goldDebtGrams ?? new Prisma.Decimal(0)).toFixed(3) },
],
};
}
}
/** The reference's `no` column held a document-type label. */
const SOURCE_LABELS: Record<string, string> = {
ORDER_STOCK: 'سفارش',
ORDER_PRE_ORDER: 'پیش‌سفارش',
REPAYMENT_MELTED_GOLD: 'طلای آبشده',
REPAYMENT_TRANSFER: 'حواله',
REPAYMENT_CHEQUE: 'چک',
REPAYMENT_CASH: 'نقدی',
WALLET_BONUS: 'هدیه',
ADJUSTMENT: 'اصلاحیه',
};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{d as f,o as v,p as g,c as s,l as e,s as u,g as p,h as m,f as t,F as y,r as P,I as k,b as C,e as b,v as h,J as x,j as B,_ as V}from"./index-D7u32dbn.js";import{P as w}from"./PageBar-CihrRnwd.js";import{a as I}from"./Spinner.vue_vue_type_style_index_0_lang-Ce4r_sA4.js";import{S as N}from"./SectionHead-CZ7O6-xd.js";import{P as F}from"./ProductCard-Ccapyn--.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./SingleProduct-BYO4_Jip.js";import"./NotifyVant.vue_vue_type_script_setup_true_lang-I8IV1V1D.js";import"./index-CnhrxceM.js";import"./DialogVant.vue_vue_type_style_index_0_lang-CVN0TLHx.js";import"./cartStore-B3Iy7abs.js";import"./dialogEmpty1-Caw7F5KL.js";import"./index-CGMkzVe8.js";import"./classCallCheck-BIPEroH2.js";const S={class:"coll"},j={key:0,class:"coll__grid"},q={key:1,class:"coll__empty"},z=f({__name:"CollectionView",setup(E){const l=x(),o=p(!1),n=p([]),d=m(()=>l.query.page||"مجموعه"),r=m(()=>n.value.filter(c=>c.collections.some(a=>a.collectionId===l.params.id)));return v(async()=>{o.value=!0;try{n.value=await g.listProducts()}finally{o.value=!1}}),(c,a)=>{const _=h("container");return t(),s("div",S,[e(w,{title:d.value,"back-to":"search"},null,8,["title"]),e(I,{spinning:o.value,tip:"درحال دریافت اطلاعات"},{default:u(()=>[e(_,{class:"coll__body"},{default:u(()=>[e(N,{title:"محصولات این مجموعه",subtitle:"برای دیدن جزئیات، روی محصول ضربه بزنید"}),r.value.length?(t(),s("div",j,[(t(!0),s(y,null,P(r.value,i=>(t(),B(F,{key:i.id,value:i},null,8,["value"]))),128))])):o.value?b("",!0):(t(),s("section",q,[e(k,{icon:"vuesax-linear:box",size:"26"}),a[0]||(a[0]=C("p",null,"در این مجموعه محصولی ثبت نشده است.",-1))]))]),_:1})]),_:1},8,["spinning"])])}}}),W=V(z,[["__scopeId","data-v-6fdc1b6f"]]);export{W as default};
import{d as f,o as v,p as g,c as s,l as e,s as u,g as p,h as m,f as t,F as y,r as P,I as k,b as C,e as b,v as h,J as x,j as B,_ as V}from"./index-DXb_5IMH.js";import{P as w}from"./PageBar-D8AimJPt.js";import{a as I}from"./Spinner.vue_vue_type_style_index_0_lang-BMAAb8Yk.js";import{S as N}from"./SectionHead-86JT-G_e.js";import{P as F}from"./ProductCard-C7Dx4Gd1.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./SingleProduct-Efr6JUR3.js";import"./NotifyVant.vue_vue_type_script_setup_true_lang-BSUvwK_b.js";import"./index-C2OFyq_j.js";import"./DialogVant.vue_vue_type_style_index_0_lang-CUUHObAn.js";import"./cartStore-CZKOLMrO.js";import"./dialogEmpty1-Caw7F5KL.js";import"./index-C32LEWo8.js";import"./classCallCheck-CkxIUjRf.js";const S={class:"coll"},j={key:0,class:"coll__grid"},q={key:1,class:"coll__empty"},z=f({__name:"CollectionView",setup(E){const l=x(),o=p(!1),n=p([]),d=m(()=>l.query.page||"مجموعه"),r=m(()=>n.value.filter(c=>c.collections.some(a=>a.collectionId===l.params.id)));return v(async()=>{o.value=!0;try{n.value=await g.listProducts()}finally{o.value=!1}}),(c,a)=>{const _=h("container");return t(),s("div",S,[e(w,{title:d.value,"back-to":"search"},null,8,["title"]),e(I,{spinning:o.value,tip:"درحال دریافت اطلاعات"},{default:u(()=>[e(_,{class:"coll__body"},{default:u(()=>[e(N,{title:"محصولات این مجموعه",subtitle:"برای دیدن جزئیات، روی محصول ضربه بزنید"}),r.value.length?(t(),s("div",j,[(t(!0),s(y,null,P(r.value,i=>(t(),B(F,{key:i.id,value:i},null,8,["value"]))),128))])):o.value?b("",!0):(t(),s("section",q,[e(k,{icon:"vuesax-linear:box",size:"26"}),a[0]||(a[0]=C("p",null,"در این مجموعه محصولی ثبت نشده است.",-1))]))]),_:1})]),_:1},8,["spinning"])])}}}),W=V(z,[["__scopeId","data-v-6fdc1b6f"]]);export{W as default};
@@ -1 +1 @@
import{d as z,o as S,c,l as a,s as d,u as w,g as r,p as N,f as i,b as s,F as P,r as B,I as u,t as o,e as m,v as D,i as F,_ as I}from"./index-D7u32dbn.js";import{P as E}from"./PageBar-CihrRnwd.js";import{a as R}from"./Spinner.vue_vue_type_style_index_0_lang-Ce4r_sA4.js";import{S as $}from"./SearchInput-CPHlMOl1.js";import{D as U}from"./index-CGMkzVe8.js";import{P as L}from"./index-B7hk2Rd_.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./classCallCheck-BIPEroH2.js";const M={class:"cch"},O={class:"cch__barExtra"},T={key:0,class:"cch__list"},j=["onClick"],q={class:"cch__head"},A={class:"cch__name"},G={class:"cch__facts"},H={class:"cch__fact"},J={dir:"ltr"},K={class:"cch__fact"},Q={dir:"ltr"},W={key:0,class:"cch__fact"},X={key:1,class:"cch__empty"},Y={key:2,class:"cch__empty"},Z={key:0,class:"cch__detail"},ss={class:"cch__detailTitle"},es={class:"cch__rows"},ts={class:"cch__row"},os={dir:"ltr"},as={class:"cch__row"},ls={dir:"ltr"},ns={class:"cch__row"},cs={class:"cch__row"},is={class:"cch__row"},rs={dir:"ltr"},_s={class:"cch__row"},ds={dir:"ltr"},us={class:"cch__row"},vs=z({__name:"CustomerChoiceView",setup(hs){const _=r([]),v=r(!1),y=r(!1),h=r(!1),b=r(null),p=r(!1),l=r(null);function g(n){const e=Number(n??0);return Number.isFinite(e)?e.toFixed(3):"0.000"}async function f(){v.value=!0,h.value=!1;try{_.value=await N.getExpertCustomers(b.value)}catch{h.value=!0,_.value=[]}finally{v.value=!1}}async function C(n){b.value=n!=null&&n.trim()?n.trim():null,await f()}async function k(){await f(),y.value=!1}function x(n){l.value=n,p.value=!0}return S(f),(n,e)=>{const V=D("container");return i(),c("div",M,[a(E,{title:"لیست مشتریان","back-to":"userPage::hasSubRoute"},{below:d(()=>[s("div",O,[a($,{onSearch:C,"place-holder":"جستجو"})])]),_:1}),a(R,{spinning:v.value&&!_.value.length,tip:"درحال دریافت اطلاعات"},{default:d(()=>[a(w(L),{modelValue:y.value,"onUpdate:modelValue":e[0]||(e[0]=t=>y.value=t),onRefresh:k},{default:d(()=>[a(V,{class:"cch__body"},{default:d(()=>[_.value.length?(i(),c("div",T,[(i(!0),c(P,null,B(_.value,t=>(i(),c("article",{key:t.id,class:"cch__card",onClick:ps=>x(t)},[s("div",q,[s("h3",A,o(t.name),1),s("span",{class:F(["cch__state",t.active===1?"is-on":"is-off"])},o(t.active===1?"فعال":"غیرفعال"),3)]),s("div",G,[s("div",H,[a(u,{icon:"vuesax-linear:mobile",size:"15"}),s("span",J,o(t.mobile||"—"),1)]),s("div",K,[a(u,{icon:"vuesax-linear:call",size:"15"}),s("span",Q,o(t.phone||"—"),1)]),t.store_name?(i(),c("div",W,[a(u,{icon:"vuesax-linear:shop",size:"15"}),s("span",null,o(t.store_name),1)])):m("",!0)])],8,j))),128))])):!v.value&&!h.value?(i(),c("section",X,[a(u,{icon:"vuesax-linear:profile-2user",size:"26"}),s("p",null,o(b.value?"مشتری با این مشخصات پیدا نشد.":"هنوز مشتری‌ای به شما معرفی نشده است."),1)])):m("",!0),h.value?(i(),c("section",Y,[a(u,{icon:"vuesax-linear:danger",size:"26"}),e[3]||(e[3]=s("p",null,"دریافت اطلاعات با خطا روبه‌رو شد.",-1)),s("button",{type:"button",class:"cch__retry",onClick:f},"تلاش دوباره")])):m("",!0)]),_:1})]),_:1},8,["modelValue"])]),_:1},8,["spinning"]),a(w(U),{open:p.value,"onUpdate:open":e[2]||(e[2]=t=>p.value=t),placement:"bottom",height:"auto",closable:!1,"body-style":{padding:"0"}},{default:d(()=>[l.value?(i(),c("div",Z,[s("h2",ss,o(l.value.name),1),s("dl",es,[s("div",ts,[e[4]||(e[4]=s("dt",null,"موبایل",-1)),s("dd",os,o(l.value.mobile||"—"),1)]),s("div",as,[e[5]||(e[5]=s("dt",null,"تلفن",-1)),s("dd",ls,o(l.value.phone||"—"),1)]),s("div",ns,[e[6]||(e[6]=s("dt",null,"نام مغازه",-1)),s("dd",null,o(l.value.store_name||"—"),1)]),s("div",cs,[e[7]||(e[7]=s("dt",null,"نام پاساژ",-1)),s("dd",null,o(l.value.pasazh_name||"—"),1)]),s("div",is,[e[8]||(e[8]=s("dt",null,"سقف اعتبار",-1)),s("dd",rs,o(g(l.value.gram_level))+" گرم",1)]),s("div",_s,[e[9]||(e[9]=s("dt",null,"بدهی گرمی",-1)),s("dd",ds,o(g(l.value.remain))+" گرم",1)]),s("div",us,[e[10]||(e[10]=s("dt",null,"وضعیت",-1)),s("dd",null,o(l.value.active===1?"فعال":"غیرفعال"),1)])]),s("button",{type:"button",class:"cch__close",onClick:e[1]||(e[1]=t=>p.value=!1)},"بستن")])):m("",!0)]),_:1},8,["open"])])}}}),xs=I(vs,[["__scopeId","data-v-e42fd341"]]);export{xs as default};
import{d as z,o as S,c,l as a,s as d,u as w,g as r,p as N,f as i,b as s,F as P,r as B,I as u,t as o,e as m,v as D,i as F,_ as I}from"./index-DXb_5IMH.js";import{P as E}from"./PageBar-D8AimJPt.js";import{a as R}from"./Spinner.vue_vue_type_style_index_0_lang-BMAAb8Yk.js";import{S as $}from"./SearchInput-Cl7K_zG_.js";import{D as U}from"./index-C32LEWo8.js";import{P as L}from"./index-vn5WboLr.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./classCallCheck-CkxIUjRf.js";const M={class:"cch"},O={class:"cch__barExtra"},T={key:0,class:"cch__list"},j=["onClick"],q={class:"cch__head"},A={class:"cch__name"},G={class:"cch__facts"},H={class:"cch__fact"},J={dir:"ltr"},K={class:"cch__fact"},Q={dir:"ltr"},W={key:0,class:"cch__fact"},X={key:1,class:"cch__empty"},Y={key:2,class:"cch__empty"},Z={key:0,class:"cch__detail"},ss={class:"cch__detailTitle"},es={class:"cch__rows"},ts={class:"cch__row"},os={dir:"ltr"},as={class:"cch__row"},ls={dir:"ltr"},ns={class:"cch__row"},cs={class:"cch__row"},is={class:"cch__row"},rs={dir:"ltr"},_s={class:"cch__row"},ds={dir:"ltr"},us={class:"cch__row"},vs=z({__name:"CustomerChoiceView",setup(hs){const _=r([]),v=r(!1),y=r(!1),h=r(!1),b=r(null),p=r(!1),l=r(null);function g(n){const e=Number(n??0);return Number.isFinite(e)?e.toFixed(3):"0.000"}async function f(){v.value=!0,h.value=!1;try{_.value=await N.getExpertCustomers(b.value)}catch{h.value=!0,_.value=[]}finally{v.value=!1}}async function C(n){b.value=n!=null&&n.trim()?n.trim():null,await f()}async function k(){await f(),y.value=!1}function x(n){l.value=n,p.value=!0}return S(f),(n,e)=>{const V=D("container");return i(),c("div",M,[a(E,{title:"لیست مشتریان","back-to":"userPage::hasSubRoute"},{below:d(()=>[s("div",O,[a($,{onSearch:C,"place-holder":"جستجو"})])]),_:1}),a(R,{spinning:v.value&&!_.value.length,tip:"درحال دریافت اطلاعات"},{default:d(()=>[a(w(L),{modelValue:y.value,"onUpdate:modelValue":e[0]||(e[0]=t=>y.value=t),onRefresh:k},{default:d(()=>[a(V,{class:"cch__body"},{default:d(()=>[_.value.length?(i(),c("div",T,[(i(!0),c(P,null,B(_.value,t=>(i(),c("article",{key:t.id,class:"cch__card",onClick:ps=>x(t)},[s("div",q,[s("h3",A,o(t.name),1),s("span",{class:F(["cch__state",t.active===1?"is-on":"is-off"])},o(t.active===1?"فعال":"غیرفعال"),3)]),s("div",G,[s("div",H,[a(u,{icon:"vuesax-linear:mobile",size:"15"}),s("span",J,o(t.mobile||"—"),1)]),s("div",K,[a(u,{icon:"vuesax-linear:call",size:"15"}),s("span",Q,o(t.phone||"—"),1)]),t.store_name?(i(),c("div",W,[a(u,{icon:"vuesax-linear:shop",size:"15"}),s("span",null,o(t.store_name),1)])):m("",!0)])],8,j))),128))])):!v.value&&!h.value?(i(),c("section",X,[a(u,{icon:"vuesax-linear:profile-2user",size:"26"}),s("p",null,o(b.value?"مشتری با این مشخصات پیدا نشد.":"هنوز مشتری‌ای به شما معرفی نشده است."),1)])):m("",!0),h.value?(i(),c("section",Y,[a(u,{icon:"vuesax-linear:danger",size:"26"}),e[3]||(e[3]=s("p",null,"دریافت اطلاعات با خطا روبه‌رو شد.",-1)),s("button",{type:"button",class:"cch__retry",onClick:f},"تلاش دوباره")])):m("",!0)]),_:1})]),_:1},8,["modelValue"])]),_:1},8,["spinning"]),a(w(U),{open:p.value,"onUpdate:open":e[2]||(e[2]=t=>p.value=t),placement:"bottom",height:"auto",closable:!1,"body-style":{padding:"0"}},{default:d(()=>[l.value?(i(),c("div",Z,[s("h2",ss,o(l.value.name),1),s("dl",es,[s("div",ts,[e[4]||(e[4]=s("dt",null,"موبایل",-1)),s("dd",os,o(l.value.mobile||"—"),1)]),s("div",as,[e[5]||(e[5]=s("dt",null,"تلفن",-1)),s("dd",ls,o(l.value.phone||"—"),1)]),s("div",ns,[e[6]||(e[6]=s("dt",null,"نام مغازه",-1)),s("dd",null,o(l.value.store_name||"—"),1)]),s("div",cs,[e[7]||(e[7]=s("dt",null,"نام پاساژ",-1)),s("dd",null,o(l.value.pasazh_name||"—"),1)]),s("div",is,[e[8]||(e[8]=s("dt",null,"سقف اعتبار",-1)),s("dd",rs,o(g(l.value.gram_level))+" گرم",1)]),s("div",_s,[e[9]||(e[9]=s("dt",null,"بدهی گرمی",-1)),s("dd",ds,o(g(l.value.remain))+" گرم",1)]),s("div",us,[e[10]||(e[10]=s("dt",null,"وضعیت",-1)),s("dd",null,o(l.value.active===1?"فعال":"غیرفعال"),1)])]),s("button",{type:"button",class:"cch__close",onClick:e[1]||(e[1]=t=>p.value=!1)},"بستن")])):m("",!0)]),_:1},8,["open"])])}}}),xs=I(vs,[["__scopeId","data-v-e42fd341"]]);export{xs as default};
@@ -0,0 +1 @@
.dash[data-v-26ecda4a]{background:#fff;min-height:100vh}.dash__bar[data-v-26ecda4a]{position:fixed;top:0;left:0;right:0;z-index:20;background:#ffffffd1;-webkit-backdrop-filter:blur(18px) saturate(140%);backdrop-filter:blur(18px) saturate(140%);border-bottom:1px solid rgba(28,45,86,.05);box-shadow:0 8px 20px -18px #1c2d568c}.dash__barInner[data-v-26ecda4a]{max-width:768px;margin:0 auto;padding:10px 16px;display:flex;align-items:center;justify-content:space-between;gap:12px}.dash__brand[data-v-26ecda4a]{font-size:14.5px;font-weight:800;color:#14161a}.dash__exit[data-v-26ecda4a]{flex:0 0 auto;width:34px;height:34px;border:0;cursor:pointer;border-radius:11px;display:grid;place-items:center;color:#7a1b33;background:#fbf2f4;transition:transform .18s ease}.dash__exit[data-v-26ecda4a]:active{transform:scale(.92)}.dash__body[data-v-26ecda4a]{padding-top:58px;padding-bottom:90px}.dash__reveal[data-v-26ecda4a]{opacity:0;transform:translate3d(0,14px,0) scale(.98);will-change:transform,opacity}.is-revealed .dash__reveal[data-v-26ecda4a]{opacity:1;transform:translateZ(0) scale(1);transition:opacity .62s cubic-bezier(.32,.72,0,1) var(--reveal-delay, 0ms),transform .62s cubic-bezier(.32,.72,0,1) var(--reveal-delay, 0ms)}@media (prefers-reduced-motion: reduce){.dash__reveal[data-v-26ecda4a]{opacity:1;transform:none}.is-revealed .dash__reveal[data-v-26ecda4a]{transition:none}}.dash__hero[data-v-26ecda4a]{margin-top:16px;margin-bottom:28px;padding:20px 18px 16px;border-radius:26px;background:linear-gradient(155deg,#14161a,#14161a 55%,#5e1427 130%);color:#fff;box-shadow:0 22px 40px -26px #14161a52}.dash__heroTop[data-v-26ecda4a]{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.dash__heroIdentity[data-v-26ecda4a]{display:flex;flex-direction:column;gap:3px;min-width:0}.dash__heroName[data-v-26ecda4a]{font-size:13.5px;font-weight:800}.dash__heroMobile[data-v-26ecda4a]{font-size:11px;color:#ffffff8c;direction:ltr;text-align:right}.dash__heroSeal[data-v-26ecda4a]{flex:0 0 auto;padding:5px 12px;border-radius:999px;font-size:10.5px;font-weight:700}.dash__heroSeal.is-debtor[data-v-26ecda4a]{color:#fff;background:#a33c55}.dash__heroSeal.is-creditor[data-v-26ecda4a]{color:#14161a;background:#ffffffe6}.dash__heroFigure[data-v-26ecda4a]{margin-top:20px;display:flex;align-items:baseline;gap:8px}.dash__heroNum[data-v-26ecda4a]{font-size:34px;font-weight:800;letter-spacing:-.5px}.dash__heroUnit[data-v-26ecda4a]{font-size:12px;font-weight:600;color:#ffffff9e}.dash__heroDebt[data-v-26ecda4a]{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:14px;padding-top:13px;border-top:1px solid rgba(255,255,255,.14);font-size:11.5px;color:#ffffff9e}.dash__heroDebt b[data-v-26ecda4a]{font-size:13px;font-weight:700;color:#fff}.dash__heroDebt i[data-v-26ecda4a]{font-style:normal;font-size:10.5px;font-weight:600;color:#ffffff9e;padding-inline-start:3px}.dash__invite[data-v-26ecda4a]{margin-top:16px;padding:26px 20px;border-radius:26px;background:#14161a;color:#fff;display:flex;flex-direction:column;align-items:center;text-align:center;gap:10px}.dash__inviteIcon[data-v-26ecda4a]{width:46px;height:46px;border-radius:50%;display:grid;place-items:center;background:#ffffff1a;margin-bottom:2px}.dash__invite h3[data-v-26ecda4a]{margin:0;font-size:14px;font-weight:800}.dash__invite p[data-v-26ecda4a]{margin:0;font-size:11.5px;color:#fff9;max-width:240px}.dash__inviteCta[data-v-26ecda4a]{margin-top:6px;padding:10px 22px;border:0;cursor:pointer;border-radius:999px;font-family:inherit;font-size:12px;font-weight:700;color:#14161a;background:#fff;transition:transform .18s ease}.dash__inviteCta[data-v-26ecda4a]:active{transform:scale(.96)}.dash__rows[data-v-26ecda4a]{margin-top:0;display:flex;flex-direction:column;gap:9px}.dash__row[data-v-26ecda4a]{display:flex;align-items:center;gap:12px;padding:13px 14px;border:1px solid #ECEDEF;border-radius:17px;cursor:pointer;background:#fff;font-family:inherit;text-align:right;transition:transform .18s ease,border-color .18s ease}.dash__row[data-v-26ecda4a]:active{transform:scale(.985);border-color:#7a1b3333}.dash__rowIcon[data-v-26ecda4a]{flex:0 0 auto;width:38px;height:38px;border-radius:12px;display:grid;place-items:center;color:#7a1b33;background:#fbf2f4}.dash__rowText[data-v-26ecda4a]{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.dash__rowText b[data-v-26ecda4a]{font-size:12.5px;font-weight:700;color:#14161a}.dash__rowText small[data-v-26ecda4a]{font-size:10.5px;color:#8a909c}.dash__rate[data-v-26ecda4a]{margin-top:14px}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
.dash[data-v-7f911406]{background:#fff;min-height:100vh}.dash__bar[data-v-7f911406]{position:fixed;top:0;left:0;right:0;z-index:20;background:#ffffffd1;-webkit-backdrop-filter:blur(18px) saturate(140%);backdrop-filter:blur(18px) saturate(140%);border-bottom:1px solid rgba(28,45,86,.05);box-shadow:0 8px 20px -18px #1c2d568c}.dash__barInner[data-v-7f911406]{max-width:768px;margin:0 auto;padding:10px 16px;display:flex;align-items:center;justify-content:space-between;gap:12px}.dash__brand[data-v-7f911406]{font-size:14.5px;font-weight:800;color:#14161a}.dash__exit[data-v-7f911406]{flex:0 0 auto;width:34px;height:34px;border:0;cursor:pointer;border-radius:11px;display:grid;place-items:center;color:#7a1b33;background:#fbf2f4;transition:transform .18s ease}.dash__exit[data-v-7f911406]:active{transform:scale(.92)}.dash__body[data-v-7f911406]{padding-top:58px;padding-bottom:90px}.dash__reveal[data-v-7f911406]{opacity:0;transform:translate3d(0,14px,0) scale(.98);will-change:transform,opacity}.is-revealed .dash__reveal[data-v-7f911406]{opacity:1;transform:translateZ(0) scale(1);transition:opacity .62s cubic-bezier(.32,.72,0,1) var(--reveal-delay, 0ms),transform .62s cubic-bezier(.32,.72,0,1) var(--reveal-delay, 0ms)}@media (prefers-reduced-motion: reduce){.dash__reveal[data-v-7f911406]{opacity:1;transform:none}.is-revealed .dash__reveal[data-v-7f911406]{transition:none}}.dash__hero[data-v-7f911406]{margin-top:16px;margin-bottom:28px;padding:20px 18px 16px;border-radius:26px;background:linear-gradient(155deg,#14161a,#14161a 55%,#5e1427 130%);color:#fff;box-shadow:0 22px 40px -26px #14161a52}.dash__heroTop[data-v-7f911406]{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.dash__heroIdentity[data-v-7f911406]{display:flex;flex-direction:column;gap:3px;min-width:0}.dash__heroName[data-v-7f911406]{font-size:13.5px;font-weight:800}.dash__heroMobile[data-v-7f911406]{font-size:11px;color:#ffffff8c;direction:ltr;text-align:right}.dash__heroSeal[data-v-7f911406]{flex:0 0 auto;padding:5px 12px;border-radius:999px;font-size:10.5px;font-weight:700}.dash__heroSeal.is-debtor[data-v-7f911406]{color:#fff;background:#a33c55}.dash__heroSeal.is-creditor[data-v-7f911406]{color:#14161a;background:#ffffffe6}.dash__heroFigure[data-v-7f911406]{margin-top:20px;display:flex;align-items:baseline;gap:8px}.dash__heroNum[data-v-7f911406]{font-size:34px;font-weight:800;letter-spacing:-.5px}.dash__heroUnit[data-v-7f911406]{font-size:12px;font-weight:600;color:#ffffff9e}.dash__heroDebt[data-v-7f911406]{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:14px;padding-top:13px;border-top:1px solid rgba(255,255,255,.14);font-size:11.5px;color:#ffffff9e}.dash__heroDebt b[data-v-7f911406]{font-size:13px;font-weight:700;color:#fff}.dash__heroDebt i[data-v-7f911406]{font-style:normal;font-size:10.5px;font-weight:600;color:#ffffff9e;padding-inline-start:3px}.dash__invite[data-v-7f911406]{margin-top:16px;padding:26px 20px;border-radius:26px;background:#14161a;color:#fff;display:flex;flex-direction:column;align-items:center;text-align:center;gap:10px}.dash__inviteIcon[data-v-7f911406]{width:46px;height:46px;border-radius:50%;display:grid;place-items:center;background:#ffffff1a;margin-bottom:2px}.dash__invite h3[data-v-7f911406]{margin:0;font-size:14px;font-weight:800}.dash__invite p[data-v-7f911406]{margin:0;font-size:11.5px;color:#fff9;max-width:240px}.dash__inviteCta[data-v-7f911406]{margin-top:6px;padding:10px 22px;border:0;cursor:pointer;border-radius:999px;font-family:inherit;font-size:12px;font-weight:700;color:#14161a;background:#fff;transition:transform .18s ease}.dash__inviteCta[data-v-7f911406]:active{transform:scale(.96)}.dash__rows[data-v-7f911406]{margin-top:0;display:flex;flex-direction:column;gap:9px}.dash__row[data-v-7f911406]{display:flex;align-items:center;gap:12px;padding:13px 14px;border:1px solid #ECEDEF;border-radius:17px;cursor:pointer;background:#fff;font-family:inherit;text-align:right;transition:transform .18s ease,border-color .18s ease}.dash__row[data-v-7f911406]:active{transform:scale(.985);border-color:#7a1b3333}.dash__rowIcon[data-v-7f911406]{flex:0 0 auto;width:38px;height:38px;border-radius:12px;display:grid;place-items:center;color:#7a1b33;background:#fbf2f4}.dash__rowText[data-v-7f911406]{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.dash__rowText b[data-v-7f911406]{font-size:12.5px;font-weight:700;color:#14161a}.dash__rowText small[data-v-7f911406]{font-size:10.5px;color:#8a909c}.dash__rate[data-v-7f911406]{margin-top:14px}
@@ -1 +1 @@
import{d as l,j as n,s as c,u as _,ao as d,f as r,b as t,A as a,D as o,t as i}from"./index-D7u32dbn.js";const m={class:"mDialog__body"},g={class:"mDialog__art"},D={class:"mDialog__title"},u={class:"mDialog__actions"},h=l({__name:"DialogVant",props:{timeOut:{},text1:{},text2:{},text3:{}},setup(s){return(e,x)=>(r(),n(_(d),{class:"mDialog"},{default:c(()=>[t("div",m,[t("div",g,[a(e.$slots,"img",{},()=>[o(i(s.text2),1)])]),t("div",D,[a(e.$slots,"title",{},()=>[o(i(s.text1),1)])]),t("div",u,[a(e.$slots,"button",{},()=>[o(i(s.text3),1)])])])]),_:3}))}});export{h as _};
import{d as l,j as n,s as c,u as _,ao as d,f as r,b as t,A as a,D as o,t as i}from"./index-DXb_5IMH.js";const m={class:"mDialog__body"},g={class:"mDialog__art"},D={class:"mDialog__title"},u={class:"mDialog__actions"},h=l({__name:"DialogVant",props:{timeOut:{},text1:{},text2:{},text3:{}},setup(s){return(e,x)=>(r(),n(_(d),{class:"mDialog"},{default:c(()=>[t("div",m,[t("div",g,[a(e.$slots,"img",{},()=>[o(i(s.text2),1)])]),t("div",D,[a(e.$slots,"title",{},()=>[o(i(s.text1),1)])]),t("div",u,[a(e.$slots,"button",{},()=>[o(i(s.text3),1)])])])]),_:3}))}});export{h as _};
@@ -1 +1 @@
import{d as f,o as g,p as y,c as o,l as e,s as c,g as p,f as t,F as m,b as i,r as b,I as h,u as k,e as P,x as C,h as x,v as F,j as B,_ as V}from"./index-D7u32dbn.js";import{P as w}from"./PageBar-CihrRnwd.js";import{a as S}from"./Spinner.vue_vue_type_style_index_0_lang-Ce4r_sA4.js";import{S as I}from"./SectionHead-CZ7O6-xd.js";import{P as N}from"./ProductCard-Ccapyn--.js";import{a as $}from"./SingleProduct-BYO4_Jip.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./cartStore-B3Iy7abs.js";import"./index-CGMkzVe8.js";import"./classCallCheck-BIPEroH2.js";import"./NotifyVant.vue_vue_type_script_setup_true_lang-I8IV1V1D.js";import"./index-CnhrxceM.js";import"./DialogVant.vue_vue_type_style_index_0_lang-CVN0TLHx.js";import"./dialogEmpty1-Caw7F5KL.js";const R={class:"favs"},j={class:"favs__grid"},z={key:1,class:"favs__empty"},E=f({__name:"FavoritesView",setup(H){const d=C(),v=$(),a=p(!1),l=p([]),r=x(()=>l.value.filter(u=>v.isFavorite(u.id)));return g(async()=>{a.value=!0;try{l.value=await y.listProducts()}finally{a.value=!1}}),(u,s)=>{const _=F("container");return t(),o("div",R,[e(w,{title:"علاقه‌مندی","back-to":"userPage::hasSubRoute"}),e(S,{spinning:a.value,tip:"در حال دریافت اطلاعات"},{default:c(()=>[e(_,{class:"favs__body"},{default:c(()=>[r.value.length?(t(),o(m,{key:0},[e(I,{title:"ذخیره‌شده‌ها",subtitle:`${r.value.length} محصول`},null,8,["subtitle"]),i("div",j,[(t(!0),o(m,null,b(r.value,n=>(t(),B(N,{key:n.id,value:n},null,8,["value"]))),128))])],64)):a.value?P("",!0):(t(),o("section",z,[e(h,{icon:"vuesax-linear:heart",size:"26"}),s[1]||(s[1]=i("p",null,"هنوز محصولی را به علاقه‌مندی‌ها اضافه نکرده‌اید.",-1)),i("button",{type:"button",class:"favs__emptyCta",onClick:s[0]||(s[0]=n=>k(d).push({name:"home"}))}," دیدن محصولات ")]))]),_:1})]),_:1},8,["spinning"])])}}}),Y=V(E,[["__scopeId","data-v-a8e72280"]]);export{Y as default};
import{d as f,o as g,p as y,c as o,l as e,s as c,g as p,f as t,F as m,b as i,r as b,I as h,u as k,e as P,x as C,h as x,v as F,j as B,_ as V}from"./index-DXb_5IMH.js";import{P as w}from"./PageBar-D8AimJPt.js";import{a as S}from"./Spinner.vue_vue_type_style_index_0_lang-BMAAb8Yk.js";import{S as I}from"./SectionHead-86JT-G_e.js";import{P as N}from"./ProductCard-C7Dx4Gd1.js";import{a as $}from"./SingleProduct-Efr6JUR3.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./cartStore-CZKOLMrO.js";import"./index-C32LEWo8.js";import"./classCallCheck-CkxIUjRf.js";import"./NotifyVant.vue_vue_type_script_setup_true_lang-BSUvwK_b.js";import"./index-C2OFyq_j.js";import"./DialogVant.vue_vue_type_style_index_0_lang-CUUHObAn.js";import"./dialogEmpty1-Caw7F5KL.js";const R={class:"favs"},j={class:"favs__grid"},z={key:1,class:"favs__empty"},E=f({__name:"FavoritesView",setup(H){const d=C(),v=$(),a=p(!1),l=p([]),r=x(()=>l.value.filter(u=>v.isFavorite(u.id)));return g(async()=>{a.value=!0;try{l.value=await y.listProducts()}finally{a.value=!1}}),(u,s)=>{const _=F("container");return t(),o("div",R,[e(w,{title:"علاقه‌مندی","back-to":"userPage::hasSubRoute"}),e(S,{spinning:a.value,tip:"در حال دریافت اطلاعات"},{default:c(()=>[e(_,{class:"favs__body"},{default:c(()=>[r.value.length?(t(),o(m,{key:0},[e(I,{title:"ذخیره‌شده‌ها",subtitle:`${r.value.length} محصول`},null,8,["subtitle"]),i("div",j,[(t(!0),o(m,null,b(r.value,n=>(t(),B(N,{key:n.id,value:n},null,8,["value"]))),128))])],64)):a.value?P("",!0):(t(),o("section",z,[e(h,{icon:"vuesax-linear:heart",size:"26"}),s[1]||(s[1]=i("p",null,"هنوز محصولی را به علاقه‌مندی‌ها اضافه نکرده‌اید.",-1)),i("button",{type:"button",class:"favs__emptyCta",onClick:s[0]||(s[0]=n=>k(d).push({name:"home"}))}," دیدن محصولات ")]))]),_:1})]),_:1},8,["spinning"])])}}}),Y=V(E,[["__scopeId","data-v-a8e72280"]]);export{Y as default};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{d,f as o,c as i,l as a,u as c,y as P,z as S,n as b,A as k,j as v,e as y,g as u,p as B,B as C,C as E,s as p,F as L,r as I,I as N,b as V,h as $,v as A,_ as F}from"./index-D7u32dbn.js";import{P as z}from"./PageBar-CihrRnwd.js";import{E as j,a as h}from"./Spinner.vue_vue_type_style_index_0_lang-Ce4r_sA4.js";import{S as D}from"./SectionHead-CZ7O6-xd.js";import{P as H}from"./ProductCard-Ccapyn--.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./SingleProduct-BYO4_Jip.js";import"./NotifyVant.vue_vue_type_script_setup_true_lang-I8IV1V1D.js";import"./index-CnhrxceM.js";import"./DialogVant.vue_vue_type_style_index_0_lang-CVN0TLHx.js";import"./cartStore-B3Iy7abs.js";import"./dialogEmpty1-Caw7F5KL.js";import"./index-CGMkzVe8.js";import"./classCallCheck-BIPEroH2.js";const T={class:"flex justify-center items-center empty"},q=d({__name:"EmptyState",props:{description:{},image:{}},setup(e){return(t,s)=>(o(),i("div",T,[a(c(j),{description:"موردی یافت نشد",image:e.image,class:"h-[200px] w-[200px] opacity-70"},null,8,["image"])]))}}),G="/assets/favoritEmpty-CIK7qR49.svg",K=d({__name:"ScrollFetchSearch",props:{loading:{type:Boolean},flag:{type:Boolean},padding:{}},emits:["fetch"],setup(e,{emit:t}){const s=t,n=P(),r=u(null);return S(r,()=>{s("fetch")},{distance:50}),(l,m)=>(o(),i("main",{class:"flex flex-col flex-1 overflow-auto no-scrollbar w-[100vw] max-w-screen-md m-auto",style:b({paddingTop:e.padding||c(n).headerHeight+"px"}),ref_key:"scrollArea",ref:r},[k(l.$slots,"default"),a(h,{cls:"my-[10px]",spinning:e.loading,indicator:!0,tip:"درحال دریافت اطلاعات"},null,8,["spinning"]),e.flag?(o(),v(q,{key:0,image:c(G)},null,8,["image"])):y("",!0)],4))}});function M(){const e=C({totalPages:0,productList:[],flag:!1});return{productsData:e,getProducts:async(s,n=!1)=>{if(!n){s.value=!0;try{e.productList=await B.listProducts(),e.flag=e.productList.length<1}catch(r){console.log(r)}finally{s.value=!1}}}}}const R={class:"newest"},Z={key:0,class:"newest__grid"},J={key:1,class:"newest__empty"},g=20,O=d({__name:"NewestView",setup(e){const{productsData:t,getProducts:s}=M(),n=u(!1),r=u(!1),l=u(g),m=$(()=>t.productList.slice(0,l.value));E(async()=>{await s(n,!1)});const w=async()=>{if(l.value<t.productList.length){l.value+=g;return}await s(r,!0)};return(Q,f)=>{const x=A("container");return o(),i("div",R,[a(z,{title:"جدیدترین محصولات","back-to":"home"}),a(h,{spinning:n.value,tip:"درحال دریافت اطلاعات"},{default:p(()=>[a(K,{class:"newest__scroll",loading:r.value,flag:c(t).flag,padding:"0px",onFetch:w},{default:p(()=>[a(x,{class:"newest__body"},{default:p(()=>[a(D,{title:"تازه‌ها",subtitle:"آخرین افزوده‌های مجموعه"}),c(t).productList.length?(o(),i("div",Z,[(o(!0),i(L,null,I(m.value,_=>(o(),v(H,{key:_.id,value:_},null,8,["value"]))),128))])):n.value?y("",!0):(o(),i("section",J,[a(N,{icon:"vuesax-linear:box",size:"26"}),f[0]||(f[0]=V("p",null,"هنوز محصولی در مجموعه ثبت نشده است.",-1))]))]),_:1})]),_:1},8,["loading","flag"])]),_:1},8,["spinning"])])}}}),ue=F(O,[["__scopeId","data-v-ecd416be"]]);export{ue as default};
import{d,f as o,c as i,l as a,u as c,y as P,z as S,n as b,A as k,j as v,e as y,g as u,p as B,B as C,C as E,s as p,F as L,r as I,I as N,b as V,h as $,v as A,_ as F}from"./index-DXb_5IMH.js";import{P as z}from"./PageBar-D8AimJPt.js";import{E as j,a as h}from"./Spinner.vue_vue_type_style_index_0_lang-BMAAb8Yk.js";import{S as D}from"./SectionHead-86JT-G_e.js";import{P as H}from"./ProductCard-C7Dx4Gd1.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./SingleProduct-Efr6JUR3.js";import"./NotifyVant.vue_vue_type_script_setup_true_lang-BSUvwK_b.js";import"./index-C2OFyq_j.js";import"./DialogVant.vue_vue_type_style_index_0_lang-CUUHObAn.js";import"./cartStore-CZKOLMrO.js";import"./dialogEmpty1-Caw7F5KL.js";import"./index-C32LEWo8.js";import"./classCallCheck-CkxIUjRf.js";const T={class:"flex justify-center items-center empty"},q=d({__name:"EmptyState",props:{description:{},image:{}},setup(e){return(t,s)=>(o(),i("div",T,[a(c(j),{description:"موردی یافت نشد",image:e.image,class:"h-[200px] w-[200px] opacity-70"},null,8,["image"])]))}}),G="/assets/favoritEmpty-CIK7qR49.svg",K=d({__name:"ScrollFetchSearch",props:{loading:{type:Boolean},flag:{type:Boolean},padding:{}},emits:["fetch"],setup(e,{emit:t}){const s=t,n=P(),r=u(null);return S(r,()=>{s("fetch")},{distance:50}),(l,m)=>(o(),i("main",{class:"flex flex-col flex-1 overflow-auto no-scrollbar w-[100vw] max-w-screen-md m-auto",style:b({paddingTop:e.padding||c(n).headerHeight+"px"}),ref_key:"scrollArea",ref:r},[k(l.$slots,"default"),a(h,{cls:"my-[10px]",spinning:e.loading,indicator:!0,tip:"درحال دریافت اطلاعات"},null,8,["spinning"]),e.flag?(o(),v(q,{key:0,image:c(G)},null,8,["image"])):y("",!0)],4))}});function M(){const e=C({totalPages:0,productList:[],flag:!1});return{productsData:e,getProducts:async(s,n=!1)=>{if(!n){s.value=!0;try{e.productList=await B.listProducts(),e.flag=e.productList.length<1}catch(r){console.log(r)}finally{s.value=!1}}}}}const R={class:"newest"},Z={key:0,class:"newest__grid"},J={key:1,class:"newest__empty"},g=20,O=d({__name:"NewestView",setup(e){const{productsData:t,getProducts:s}=M(),n=u(!1),r=u(!1),l=u(g),m=$(()=>t.productList.slice(0,l.value));E(async()=>{await s(n,!1)});const w=async()=>{if(l.value<t.productList.length){l.value+=g;return}await s(r,!0)};return(Q,f)=>{const x=A("container");return o(),i("div",R,[a(z,{title:"جدیدترین محصولات","back-to":"home"}),a(h,{spinning:n.value,tip:"درحال دریافت اطلاعات"},{default:p(()=>[a(K,{class:"newest__scroll",loading:r.value,flag:c(t).flag,padding:"0px",onFetch:w},{default:p(()=>[a(x,{class:"newest__body"},{default:p(()=>[a(D,{title:"تازه‌ها",subtitle:"آخرین افزوده‌های مجموعه"}),c(t).productList.length?(o(),i("div",Z,[(o(!0),i(L,null,I(m.value,_=>(o(),v(H,{key:_.id,value:_},null,8,["value"]))),128))])):n.value?y("",!0):(o(),i("section",J,[a(N,{icon:"vuesax-linear:box",size:"26"}),f[0]||(f[0]=V("p",null,"هنوز محصولی در مجموعه ثبت نشده است.",-1))]))]),_:1})]),_:1},8,["loading","flag"])]),_:1},8,["spinning"])])}}}),ue=F(O,[["__scopeId","data-v-ecd416be"]]);export{ue as default};
@@ -1 +1 @@
import{d as a,c as n,l as o,s as i,v as c,f as _,b as e,I as r,_ as f}from"./index-D7u32dbn.js";import{P as l}from"./PageBar-CihrRnwd.js";const p={class:"notif"},d={class:"notif__empty"},m=a({__name:"NotificationsView",setup(u){return(v,t)=>{const s=c("container");return _(),n("div",p,[o(l,{title:"اعلان‌ها","back-to":"home"}),o(s,{class:"notif__body"},{default:i(()=>[e("section",d,[o(r,{icon:"vuesax-linear:notification",size:"26"}),t[0]||(t[0]=e("p",null,"اعلانی برای نمایش وجود ندارد.",-1))])]),_:1})])}}}),N=f(m,[["__scopeId","data-v-44d0c9a5"]]);export{N as default};
import{d as a,c as n,l as o,s as i,v as c,f as _,b as e,I as r,_ as f}from"./index-DXb_5IMH.js";import{P as l}from"./PageBar-D8AimJPt.js";const p={class:"notif"},d={class:"notif__empty"},m=a({__name:"NotificationsView",setup(u){return(v,t)=>{const s=c("container");return _(),n("div",p,[o(l,{title:"اعلان‌ها","back-to":"home"}),o(s,{class:"notif__body"},{default:i(()=>[e("section",d,[o(r,{icon:"vuesax-linear:notification",size:"26"}),t[0]||(t[0]=e("p",null,"اعلانی برای نمایش وجود ندارد.",-1))])]),_:1})])}}}),N=f(m,[["__scopeId","data-v-44d0c9a5"]]);export{N as default};
@@ -1 +1 @@
import{d as m,G as r,f,c as h,l,u as w,n as x,s as p,b as o,I as y,A as V,D as N,t as v,e as _,g as B}from"./index-D7u32dbn.js";import{N as k}from"./index-CnhrxceM.js";const C={key:0,class:"flex"},O={class:"w-full text-white my-2"},S={class:"w-full flex content-end"},D=m({__name:"NotifyVant",props:{modelValue:{type:Boolean},timeOut:{},text:{},color:{}},emits:["update:modelValue"],setup(e,{emit:n}){const s=B(!0),t=e,i=n;r(()=>t.modelValue,()=>{t.timeOut!==-1&&c()});const c=()=>{setTimeout(()=>{i("update:modelValue",!1)},t.timeOut)};return(u,a)=>e.modelValue?(f(),h("div",C,[l(w(k),{show:s.value,"onUpdate:show":a[0]||(a[0]=d=>s.value=d),style:x(e.color)},{default:p(()=>[o("div",O,[o("div",S,[l(y,{icon:"vuesax-linear:info-circle",class:"ml-[20px] text-white",size:"25"}),o("div",null,[V(u.$slots,"default",{},()=>[N(v(e.text),1)])])])])]),_:3},8,["show","style"])])):_("",!0)}});export{D as _};
import{d as m,G as r,f,c as h,l,u as w,n as x,s as p,b as o,I as y,A as V,D as N,t as v,e as _,g as B}from"./index-DXb_5IMH.js";import{N as k}from"./index-C2OFyq_j.js";const C={key:0,class:"flex"},O={class:"w-full text-white my-2"},S={class:"w-full flex content-end"},D=m({__name:"NotifyVant",props:{modelValue:{type:Boolean},timeOut:{},text:{},color:{}},emits:["update:modelValue"],setup(e,{emit:n}){const s=B(!0),t=e,i=n;r(()=>t.modelValue,()=>{t.timeOut!==-1&&c()});const c=()=>{setTimeout(()=>{i("update:modelValue",!1)},t.timeOut)};return(u,a)=>e.modelValue?(f(),h("div",C,[l(w(k),{show:s.value,"onUpdate:show":a[0]||(a[0]=d=>s.value=d),style:x(e.color)},{default:p(()=>[o("div",O,[o("div",S,[l(y,{icon:"vuesax-linear:info-circle",class:"ml-[20px] text-white",size:"25"}),o("div",null,[V(u.$slots,"default",{},()=>[N(v(e.text),1)])])])])]),_:3},8,["show","style"])])):_("",!0)}});export{D as _};
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{d as _,c as s,b as a,l as d,I as b,t as u,A as i,f as t,x as p,_ as k}from"./index-D7u32dbn.js";const h={class:"bar"},f={class:"bar__inner"},m={key:1,class:"bar__spacer","aria-hidden":"true"},B={class:"bar__title"},g={class:"bar__trailing"},v=_({__name:"PageBar",props:{title:{},back:{type:Boolean,default:!0},backTo:{}},setup(e){const o=e,r=p();function l(){o.backTo?r.push({name:o.backTo}):r.back()}return(n,c)=>(t(),s("header",h,[a("div",f,[e.back?(t(),s("button",{key:0,type:"button",class:"bar__btn","aria-label":"بازگشت",onClick:l},[d(b,{icon:"vuesax-linear:arrow-right-1",size:"20"})])):(t(),s("span",m)),a("h1",B,u(e.title),1),a("div",g,[i(n.$slots,"trailing",{},()=>[c[0]||(c[0]=a("span",{class:"bar__spacer","aria-hidden":"true"},null,-1))],!0)])]),i(n.$slots,"below",{},void 0,!0)]))}}),x=k(v,[["__scopeId","data-v-d2d3dfeb"]]);export{x as P};
import{d as _,c as s,b as a,l as d,I as b,t as u,A as i,f as t,x as p,_ as k}from"./index-DXb_5IMH.js";const h={class:"bar"},f={class:"bar__inner"},m={key:1,class:"bar__spacer","aria-hidden":"true"},B={class:"bar__title"},g={class:"bar__trailing"},v=_({__name:"PageBar",props:{title:{},back:{type:Boolean,default:!0},backTo:{}},setup(e){const o=e,r=p();function l(){o.backTo?r.push({name:o.backTo}):r.back()}return(n,c)=>(t(),s("header",h,[a("div",f,[e.back?(t(),s("button",{key:0,type:"button",class:"bar__btn","aria-label":"بازگشت",onClick:l},[d(b,{icon:"vuesax-linear:arrow-right-1",size:"20"})])):(t(),s("span",m)),a("h1",B,u(e.title),1),a("div",g,[i(n.$slots,"trailing",{},()=>[c[0]||(c[0]=a("span",{class:"bar__spacer","aria-hidden":"true"},null,-1))],!0)])]),i(n.$slots,"below",{},void 0,!0)]))}}),x=k(v,[["__scopeId","data-v-d2d3dfeb"]]);export{x as P};
@@ -1 +1 @@
import{d as D,k as F,f as t,c as a,F as P,b as o,u as e,w as S,l as p,I as h,a4 as z,i as N,e as c,t as _,D as V,s as I,j as E,g as O,_ as U}from"./index-D7u32dbn.js";import{a as $,S as j}from"./SingleProduct-BYO4_Jip.js";import{u as q}from"./cartStore-B3Iy7abs.js";import{D as L}from"./index-CGMkzVe8.js";const M={class:"pc__art"},T=["alt"],A={key:1,class:"pc__artEmpty","aria-hidden":"true"},G=["aria-label"],H={key:2,class:"pc__flag"},J={key:3,class:"pc__flag pc__flag--soft"},K={class:"pc__title"},Q={class:"pc__weight"},R={key:0,class:"pc__meta"},W={key:0,class:"pc__wageOld"},X={class:"pc__wage"},Y=D({__name:"ProductCard",props:{value:{},wageBefore:{}},setup(d){const w=d,r=$(),{image:v,id:i,title:f,min_gram:y,wage:m,is_exist:k,qty:b,isPreOrder:x}=q(w.value),l=O(!1);function C(){l.value=!0}function g(n){return n%1===0?String(n):n.toFixed(2)}return(n,s)=>{const B=F("lazy");return t(),a(P,null,[o("article",{class:"pc",onClick:C},[o("div",M,[e(v)?S((t(),a("img",{key:0,alt:e(f)},null,8,T)),[[B,e(v)]]):(t(),a("div",A,[p(h,{icon:"vuesax-linear:diamonds",size:"26"})])),o("button",{type:"button",class:N(["pc__fav",{"is-on":e(r).isFavorite(e(i))}]),"aria-label":e(r).isFavorite(e(i))?"حذف از علاقه‌مندی":"افزودن به علاقه‌مندی",onClick:s[0]||(s[0]=z(u=>e(r).toggle(e(i)),["stop"]))},[p(h,{icon:e(r).isFavorite(e(i))?"vuesax-linear:heart-fill":"vuesax-linear:heart",size:"16"},null,8,["icon"])],10,G),e(k)?e(x)&&e(b)===0?(t(),a("span",J,"پیش‌سفارش")):c("",!0):(t(),a("span",H,"ناموجود"))]),o("h3",K,_(e(f)),1),o("p",Q,[V(_(e(y))+" ",1),s[3]||(s[3]=o("span",{class:"pc__weightUnit"},"گرم",-1))]),e(m)!=null?(t(),a("div",R,[d.wageBefore!=null?(t(),a("span",W,"اجرت "+_(g(d.wageBefore))+"٪",1)):c("",!0),o("span",X,_(g(e(m)))+"٪ اجرت",1)])):c("",!0)]),p(e(L),{visible:l.value,"onUpdate:visible":s[2]||(s[2]=u=>l.value=u),placement:"bottom",closable:!1,class:"rtl",height:"100vh",bodyStyle:{padding:0,position:"relative"}},{default:I(()=>[l.value?(t(),E(j,{id:e(i),key:e(i),onCloseDrawer:s[1]||(s[1]=u=>l.value=!1)},null,8,["id"])):c("",!0)]),_:1},8,["visible"])],64)}}}),ae=U(Y,[["__scopeId","data-v-ed785ed2"]]);export{ae as P};
import{d as D,k as F,f as t,c as a,F as P,b as o,u as e,w as S,l as p,I as h,a4 as z,i as N,e as c,t as _,D as V,s as I,j as E,g as O,_ as U}from"./index-DXb_5IMH.js";import{a as $,S as j}from"./SingleProduct-Efr6JUR3.js";import{u as q}from"./cartStore-CZKOLMrO.js";import{D as L}from"./index-C32LEWo8.js";const M={class:"pc__art"},T=["alt"],A={key:1,class:"pc__artEmpty","aria-hidden":"true"},G=["aria-label"],H={key:2,class:"pc__flag"},J={key:3,class:"pc__flag pc__flag--soft"},K={class:"pc__title"},Q={class:"pc__weight"},R={key:0,class:"pc__meta"},W={key:0,class:"pc__wageOld"},X={class:"pc__wage"},Y=D({__name:"ProductCard",props:{value:{},wageBefore:{}},setup(d){const w=d,r=$(),{image:v,id:i,title:f,min_gram:y,wage:m,is_exist:k,qty:b,isPreOrder:x}=q(w.value),l=O(!1);function C(){l.value=!0}function g(n){return n%1===0?String(n):n.toFixed(2)}return(n,s)=>{const B=F("lazy");return t(),a(P,null,[o("article",{class:"pc",onClick:C},[o("div",M,[e(v)?S((t(),a("img",{key:0,alt:e(f)},null,8,T)),[[B,e(v)]]):(t(),a("div",A,[p(h,{icon:"vuesax-linear:diamonds",size:"26"})])),o("button",{type:"button",class:N(["pc__fav",{"is-on":e(r).isFavorite(e(i))}]),"aria-label":e(r).isFavorite(e(i))?"حذف از علاقه‌مندی":"افزودن به علاقه‌مندی",onClick:s[0]||(s[0]=z(u=>e(r).toggle(e(i)),["stop"]))},[p(h,{icon:e(r).isFavorite(e(i))?"vuesax-linear:heart-fill":"vuesax-linear:heart",size:"16"},null,8,["icon"])],10,G),e(k)?e(x)&&e(b)===0?(t(),a("span",J,"پیش‌سفارش")):c("",!0):(t(),a("span",H,"ناموجود"))]),o("h3",K,_(e(f)),1),o("p",Q,[V(_(e(y))+" ",1),s[3]||(s[3]=o("span",{class:"pc__weightUnit"},"گرم",-1))]),e(m)!=null?(t(),a("div",R,[d.wageBefore!=null?(t(),a("span",W,"اجرت "+_(g(d.wageBefore))+"٪",1)):c("",!0),o("span",X,_(g(e(m)))+"٪ اجرت",1)])):c("",!0)]),p(e(L),{visible:l.value,"onUpdate:visible":s[2]||(s[2]=u=>l.value=u),placement:"bottom",closable:!1,class:"rtl",height:"100vh",bodyStyle:{padding:0,position:"relative"}},{default:I(()=>[l.value?(t(),E(j,{id:e(i),key:e(i),onCloseDrawer:s[1]||(s[1]=u=>l.value=!1)},null,8,["id"])):c("",!0)]),_:1},8,["visible"])],64)}}}),ae=U(Y,[["__scopeId","data-v-ed785ed2"]]);export{ae as P};
@@ -1 +1 @@
import{d as y,E as T,o as b,p as k,c as l,l as i,s as V,g as p,v as P,f as n,b as e,I as d,t as a,e as r,i as g,u as B,h as f,x as C,_ as D}from"./index-D7u32dbn.js";import{P as N}from"./PageBar-CihrRnwd.js";import{S as h}from"./SectionHead-CZ7O6-xd.js";const x={class:"prof"},R={class:"prof__identity"},F={class:"prof__avatar","aria-hidden":"true"},M={class:"prof__name"},w={key:0,class:"prof__mobile"},O={key:0,class:"prof__block"},U={class:"prof__specs"},z={class:"prof__spec"},L={class:"prof__spec"},A={class:"prof__spec"},W={class:"prof__spec"},H={key:1,class:"prof__empty"},$=y({__name:"ProfileView",setup(j){const _={UNVERIFIED:"احراز نشده",STEP_ONE_SUBMITTED:"مرحله اول ثبت شده",STEP_TWO_SUBMITTED:"مرحله دوم ثبت شده",VERIFIED:"تایید شده"},v=T(),s=p(null),u=p(!1),m=f(()=>{var t;return((t=s.value)==null?void 0:t.verificationStep)==="VERIFIED"}),E=f(()=>{var o;const t=(o=s.value)==null?void 0:o.verificationStep;return!!t&&t!=="VERIFIED"&&t!=="STEP_TWO_SUBMITTED"}),S=C();return b(async()=>{if(v.isLoggedIn){u.value=!0;try{s.value=await k.getMe()}finally{u.value=!1}}}),(t,o)=>{const I=P("container");return n(),l("div",x,[i(N,{title:"اطلاعات کاربری","back-to":"userPage::hasSubRoute"}),i(I,{class:"prof__body"},{default:V(()=>{var c;return[e("section",R,[e("div",F,[i(d,{icon:"vuesax-linear:user",size:"30"})]),e("h2",M,a(((c=s.value)==null?void 0:c.fullName)??"—"),1),s.value?(n(),l("p",w,a(s.value.mobile),1)):r("",!0),s.value?(n(),l("span",{key:1,class:g(["prof__seal",m.value?"is-ok":"is-pending"])},a(_[s.value.verificationStep]??s.value.verificationStep),3)):r("",!0)]),s.value?(n(),l("section",O,[i(h,{title:"مشخصات",subtitle:"اطلاعات ثبت‌شده حساب شما"}),e("dl",U,[e("div",z,[o[1]||(o[1]=e("dt",null,"نام و نام خانوادگی",-1)),e("dd",null,a(s.value.fullName),1)]),e("div",L,[o[2]||(o[2]=e("dt",null,"تلفن همراه",-1)),e("dd",null,a(s.value.mobile),1)]),e("div",A,[o[3]||(o[3]=e("dt",null,"کد ملی",-1)),e("dd",null,a(s.value.nationalCode),1)]),e("div",W,[o[4]||(o[4]=e("dt",null,"وضعیت احراز هویت",-1)),e("dd",null,a(_[s.value.verificationStep]??s.value.verificationStep),1)])])])):u.value?r("",!0):(n(),l("section",H,[i(d,{icon:"vuesax-linear:user",size:"26"}),o[5]||(o[5]=e("p",null,"اطلاعات حساب در دسترس نیست.",-1))])),E.value?(n(),l("button",{key:2,type:"button",class:"prof__complete",onClick:o[0]||(o[0]=q=>B(S).push({name:"completeProfile"}))}," تکمیل پروفایل ")):r("",!0)]}),_:1})])}}}),Q=D($,[["__scopeId","data-v-33e6f62c"]]);export{Q as default};
import{d as y,E as T,o as b,p as k,c as l,l as i,s as V,g as p,v as P,f as n,b as e,I as d,t as a,e as r,i as g,u as B,h as f,x as C,_ as D}from"./index-DXb_5IMH.js";import{P as N}from"./PageBar-D8AimJPt.js";import{S as h}from"./SectionHead-86JT-G_e.js";const x={class:"prof"},R={class:"prof__identity"},F={class:"prof__avatar","aria-hidden":"true"},M={class:"prof__name"},w={key:0,class:"prof__mobile"},O={key:0,class:"prof__block"},U={class:"prof__specs"},z={class:"prof__spec"},L={class:"prof__spec"},A={class:"prof__spec"},W={class:"prof__spec"},H={key:1,class:"prof__empty"},$=y({__name:"ProfileView",setup(j){const _={UNVERIFIED:"احراز نشده",STEP_ONE_SUBMITTED:"مرحله اول ثبت شده",STEP_TWO_SUBMITTED:"مرحله دوم ثبت شده",VERIFIED:"تایید شده"},v=T(),s=p(null),u=p(!1),m=f(()=>{var t;return((t=s.value)==null?void 0:t.verificationStep)==="VERIFIED"}),E=f(()=>{var o;const t=(o=s.value)==null?void 0:o.verificationStep;return!!t&&t!=="VERIFIED"&&t!=="STEP_TWO_SUBMITTED"}),S=C();return b(async()=>{if(v.isLoggedIn){u.value=!0;try{s.value=await k.getMe()}finally{u.value=!1}}}),(t,o)=>{const I=P("container");return n(),l("div",x,[i(N,{title:"اطلاعات کاربری","back-to":"userPage::hasSubRoute"}),i(I,{class:"prof__body"},{default:V(()=>{var c;return[e("section",R,[e("div",F,[i(d,{icon:"vuesax-linear:user",size:"30"})]),e("h2",M,a(((c=s.value)==null?void 0:c.fullName)??"—"),1),s.value?(n(),l("p",w,a(s.value.mobile),1)):r("",!0),s.value?(n(),l("span",{key:1,class:g(["prof__seal",m.value?"is-ok":"is-pending"])},a(_[s.value.verificationStep]??s.value.verificationStep),3)):r("",!0)]),s.value?(n(),l("section",O,[i(h,{title:"مشخصات",subtitle:"اطلاعات ثبت‌شده حساب شما"}),e("dl",U,[e("div",z,[o[1]||(o[1]=e("dt",null,"نام و نام خانوادگی",-1)),e("dd",null,a(s.value.fullName),1)]),e("div",L,[o[2]||(o[2]=e("dt",null,"تلفن همراه",-1)),e("dd",null,a(s.value.mobile),1)]),e("div",A,[o[3]||(o[3]=e("dt",null,"کد ملی",-1)),e("dd",null,a(s.value.nationalCode),1)]),e("div",W,[o[4]||(o[4]=e("dt",null,"وضعیت احراز هویت",-1)),e("dd",null,a(_[s.value.verificationStep]??s.value.verificationStep),1)])])])):u.value?r("",!0):(n(),l("section",H,[i(d,{icon:"vuesax-linear:user",size:"26"}),o[5]||(o[5]=e("p",null,"اطلاعات حساب در دسترس نیست.",-1))])),E.value?(n(),l("button",{key:2,type:"button",class:"prof__complete",onClick:o[0]||(o[0]=q=>B(S).push({name:"completeProfile"}))}," تکمیل پروفایل ")):r("",!0)]}),_:1})])}}}),Q=D($,[["__scopeId","data-v-33e6f62c"]]);export{Q as default};
@@ -1 +1 @@
import{p as n,j as d}from"./filters-CLL9nGZ2.js";import{d as l,c as s,i as u,b as a,D as m,t as i,u as c,e as _,h as v,f as r,_ as q}from"./index-D7u32dbn.js";const f={key:0,class:"rate-strip__value"},y={class:"rate-strip__num"},k={key:1,class:"rate-strip__value rate-strip__value--muted"},x={key:2,class:"rate-strip__time"},B=l({__name:"RateStrip",props:{quote:{},compact:{type:Boolean}},setup(t){const o=t,p=v(()=>o.quote?o.quote.pricePerGramRial.split(".")[0]:"");return(R,e)=>(r(),s("div",{class:u(["rate-strip",{"is-empty":!t.quote,"rate-strip--compact":t.compact}])},[e[1]||(e[1]=a("div",{class:"rate-strip__label"},[a("span",{class:"rate-strip__dot","aria-hidden":"true"}),m(" نرخ طلای ۱۸ عیار ")],-1)),t.quote?(r(),s("div",f,[a("span",y,i(c(n)(p.value)),1),e[0]||(e[0]=a("span",{class:"rate-strip__unit"},"ریال / گرم",-1))])):(r(),s("div",k,"در انتظار اعلام نرخ")),t.quote?(r(),s("div",x,i(c(d)(t.quote.quotedAt)),1)):_("",!0)],2))}}),C=q(B,[["__scopeId","data-v-0b16738e"]]);export{C as R};
import{p as n,j as d}from"./filters-CLL9nGZ2.js";import{d as l,c as s,i as u,b as a,D as m,t as i,u as c,e as _,h as v,f as r,_ as q}from"./index-DXb_5IMH.js";const f={key:0,class:"rate-strip__value"},y={class:"rate-strip__num"},k={key:1,class:"rate-strip__value rate-strip__value--muted"},x={key:2,class:"rate-strip__time"},B=l({__name:"RateStrip",props:{quote:{},compact:{type:Boolean}},setup(t){const o=t,p=v(()=>o.quote?o.quote.pricePerGramRial.split(".")[0]:"");return(R,e)=>(r(),s("div",{class:u(["rate-strip",{"is-empty":!t.quote,"rate-strip--compact":t.compact}])},[e[1]||(e[1]=a("div",{class:"rate-strip__label"},[a("span",{class:"rate-strip__dot","aria-hidden":"true"}),m(" نرخ طلای ۱۸ عیار ")],-1)),t.quote?(r(),s("div",f,[a("span",y,i(c(n)(p.value)),1),e[0]||(e[0]=a("span",{class:"rate-strip__unit"},"ریال / گرم",-1))])):(r(),s("div",k,"در انتظار اعلام نرخ")),t.quote?(r(),s("div",x,i(c(d)(t.quote.quotedAt)),1)):_("",!0)],2))}}),C=q(B,[["__scopeId","data-v-0b16738e"]]);export{C as R};
+1
View File
@@ -0,0 +1 @@
.doc[data-v-8de7ea07]{padding:18px 2px;background:transparent;border:none;border-bottom:1px solid #ECEDEF}.doc[data-v-8de7ea07]:last-child{border-bottom:none}.doc__head[data-v-8de7ea07]{display:flex;justify-content:space-between;gap:10px;margin-bottom:10px;font-size:13px;font-weight:600}.doc__muted[data-v-8de7ea07]{color:#5b616e;font-weight:500;margin-left:4px}.doc__rows[data-v-8de7ea07]{margin:0;display:flex;flex-direction:column}.doc__row[data-v-8de7ea07]{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:9px 0;border-bottom:1px dashed #F4F5F6}.doc__row[data-v-8de7ea07]:last-child{border-bottom:none}.doc__row dt[data-v-8de7ea07]{font-size:12.5px;color:#5b616e;white-space:nowrap}.doc__row dd[data-v-8de7ea07]{margin:0;font-size:13.5px;font-weight:600;text-align:left}.doc__gold[data-v-8de7ea07]{display:flex;justify-content:space-between;align-items:center;margin-top:10px;padding-top:10px;border-top:1px dashed #ECEDEF;font-size:13px;font-weight:700}.doc__stack[data-v-8de7ea07]{display:flex;flex-direction:column;align-items:flex-end;gap:2px}.is-in[data-v-8de7ea07]{color:#16a34a}.is-out[data-v-8de7ea07]{color:#dc2626}.rep__tabs[data-v-9457295a]{display:flex;gap:24px;padding:0 16px 10px}.rep__tab[data-v-9457295a]{padding:8px 0;border:none;border-bottom:2px solid transparent;background:transparent;font-family:inherit;font-size:14px;font-weight:600;color:#8a909c;cursor:pointer}.rep__tab.is-on[data-v-9457295a]{color:#14161a;border-bottom-color:#7a1b33}.rep__body[data-v-9457295a]{padding-top:126px;padding-bottom:90px}.rep__list[data-v-9457295a]{display:flex;flex-direction:column;padding-top:8px}.rep__card[data-v-9457295a]{padding:18px 2px;background:transparent;border:none;border-bottom:1px solid #ECEDEF}.rep__card[data-v-9457295a]:last-child{border-bottom:none}.rep__head[data-v-9457295a]{display:flex;justify-content:space-between;gap:10px;margin-bottom:12px;font-size:13px;font-weight:600}.rep__muted[data-v-9457295a]{color:#5b616e;font-weight:500;margin-left:4px}.rep__pair[data-v-9457295a]{display:flex;justify-content:space-between;align-items:center;padding:8px 0;font-size:13px;color:#5b616e}.rep__pair.is-balance[data-v-9457295a]{padding-top:10px;border-top:1px dashed #ECEDEF;color:#14161a;font-weight:700}.rep__stack[data-v-9457295a]{display:flex;flex-direction:column;align-items:flex-end;gap:2px;font-weight:600}.is-in[data-v-9457295a]{color:#16a34a}.is-out[data-v-9457295a]{color:#dc2626}.rep__more[data-v-9457295a],.rep__sentinel[data-v-9457295a]{padding:12px 0;text-align:center;font-size:12px;color:#5b616e}.rep__more[data-v-9457295a]{width:100%;margin-top:6px;border:none;background:transparent;font-family:inherit;font-weight:700;color:#7a1b33;cursor:pointer}.rep__empty[data-v-9457295a]{margin-top:40px;padding:34px 20px;display:flex;flex-direction:column;align-items:center;gap:10px;color:#5b616e;font-size:13px}.rep__retry[data-v-9457295a]{padding:8px 18px;border-radius:999px;border:1px solid #ECEDEF;background:#fff;font-family:inherit;font-size:12px;font-weight:600;cursor:pointer}.rep__modal[data-v-9457295a]{padding:20px 16px 24px}.rep__modalEmpty[data-v-9457295a]{padding:24px 0;text-align:center;font-size:13px;color:#5b616e}.rep__close[data-v-9457295a]{margin-top:18px;width:100%;padding:14px;border:none;border-radius:999px;background:#7a1b33;color:#fff;font-family:inherit;font-size:14px;font-weight:700;cursor:pointer}
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{d as v,a9 as h,G as m,f as t,c as l,l as n,I as r,w as f,aa as b,b as x,ab as k,e as I,B as w,g as y,_ as B}from"./index-D7u32dbn.js";const C={class:"si"},S=["placeholder"],V=v({__name:"SearchInput",props:{placeHolder:{}},emits:["search"],setup(i,{emit:d}){const c=d,a=w({clear:!1}),e=y(void 0),s=()=>{c("search",e.value)},u=()=>{e.value=void 0,a.clear=!1,c("search",void 0)},p=h(e,700);return m(p,()=>{e?a.clear=!0:a.clear=!1,s()}),(N,o)=>(t(),l("div",C,[n(r,{icon:"vuesax-linear:search-normal-1",class:"si__icon",size:"18",onClick:s}),f(x("input",{"onUpdate:modelValue":o[0]||(o[0]=_=>e.value=_),class:"si__input",placeholder:i.placeHolder,onKeyup:k(s,["enter"])},null,40,S),[[b,e.value]]),a.clear?(t(),l("button",{key:0,type:"button",class:"si__clear","aria-label":"پاک کردن",onClick:u},[n(r,{icon:"vuesax-linear:add",size:"16"})])):I("",!0)]))}}),D=B(V,[["__scopeId","data-v-8ebd3183"]]);export{D as S};
import{d as v,a9 as h,G as m,f as t,c as l,l as n,I as r,w as f,aa as b,b as x,ab as k,e as I,B as w,g as y,_ as B}from"./index-DXb_5IMH.js";const C={class:"si"},S=["placeholder"],V=v({__name:"SearchInput",props:{placeHolder:{}},emits:["search"],setup(i,{emit:d}){const c=d,a=w({clear:!1}),e=y(void 0),s=()=>{c("search",e.value)},u=()=>{e.value=void 0,a.clear=!1,c("search",void 0)},p=h(e,700);return m(p,()=>{e?a.clear=!0:a.clear=!1,s()}),(N,o)=>(t(),l("div",C,[n(r,{icon:"vuesax-linear:search-normal-1",class:"si__icon",size:"18",onClick:s}),f(x("input",{"onUpdate:modelValue":o[0]||(o[0]=_=>e.value=_),class:"si__input",placeholder:i.placeHolder,onKeyup:k(s,["enter"])},null,40,S),[[b,e.value]]),a.clear?(t(),l("button",{key:0,type:"button",class:"si__clear","aria-label":"پاک کردن",onClick:u},[n(r,{icon:"vuesax-linear:add",size:"16"})])):I("",!0)]))}}),D=B(V,[["__scopeId","data-v-8ebd3183"]]);export{D as S};
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{d as r,f as t,c as s,b as o,t as a,e as n,D as _,l as d,I as u,_ as b}from"./index-D7u32dbn.js";const m={class:"sec"},f={class:"sec__text"},x={class:"sec__title"},h={key:0,class:"sec__sub"},k=r({__name:"SectionHead",props:{title:{},subtitle:{},actionLabel:{}},emits:["action"],setup(e,{emit:i}){const l=i;return(p,c)=>(t(),s("header",m,[o("div",f,[o("h2",x,a(e.title),1),e.subtitle?(t(),s("p",h,a(e.subtitle),1)):n("",!0)]),e.actionLabel?(t(),s("button",{key:0,type:"button",class:"sec__action",onClick:c[0]||(c[0]=v=>l("action"))},[_(a(e.actionLabel)+" ",1),d(u,{icon:"vuesax-linear:arrow-left-2",size:"15"})])):n("",!0)]))}}),N=b(k,[["__scopeId","data-v-e5c65b7c"]]);export{N as S};
import{d as r,f as t,c as s,b as o,t as a,e as n,D as _,l as d,I as u,_ as b}from"./index-DXb_5IMH.js";const m={class:"sec"},f={class:"sec__text"},x={class:"sec__title"},h={key:0,class:"sec__sub"},k=r({__name:"SectionHead",props:{title:{},subtitle:{},actionLabel:{}},emits:["action"],setup(e,{emit:i}){const l=i;return(p,c)=>(t(),s("header",m,[o("div",f,[o("h2",x,a(e.title),1),e.subtitle?(t(),s("p",h,a(e.subtitle),1)):n("",!0)]),e.actionLabel?(t(),s("button",{key:0,type:"button",class:"sec__action",onClick:c[0]||(c[0]=v=>l("action"))},[_(a(e.actionLabel)+" ",1),d(u,{icon:"vuesax-linear:arrow-left-2",size:"15"})])):n("",!0)]))}}),N=b(k,[["__scopeId","data-v-e5c65b7c"]]);export{N as S};
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{d as k,E as A,o as C,p as D,c as i,l as r,s as f,j as w,u as E,e as m,g as u,f as l,F as y,b as s,r as L,I as g,t as o,i as p,v as N,_ as M}from"./index-D7u32dbn.js";import{P}from"./PageBar-CihrRnwd.js";import{a as O}from"./Spinner.vue_vue_type_style_index_0_lang-Ce4r_sA4.js";import{S as B}from"./SectionHead-CZ7O6-xd.js";import{j as R,p as U}from"./filters-CLL9nGZ2.js";import{D as I}from"./index-CGMkzVe8.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./classCallCheck-BIPEroH2.js";const V={class:"tx"},$={class:"tx__list"},Y=["onClick"],j={class:"tx__main"},z={class:"tx__head"},F={class:"tx__kind"},G={key:0,class:"tx__note"},H={class:"tx__foot"},J={class:"tx__date"},K={key:1,class:"tx__empty"},Q={class:"sheet"},W={class:"sheet__specs"},q={class:"sheet__spec"},X={class:"sheet__spec"},Z={class:"sheet__spec"},ss={class:"sheet__spec"},es={class:"sheet__spec"},ts=k({__name:"TransactionsView",setup(os){const x={ORDER_STOCK:"سفارش",ORDER_PRE_ORDER:"سفارش ساخت",REPAYMENT_MELTED_GOLD:"طلای آب‌شده",REPAYMENT_TRANSFER:"حواله",REPAYMENT_CHEQUE:"چک",REPAYMENT_CASH:"پولی",WALLET_BONUS:"پاداش",ADJUSTMENT:"اصلاحیه"},T=A(),_=u(!1),d=u([]),v=u(!1),n=u(null),c=a=>a.direction==="CREDIT",h=a=>a.currency==="GOLD_GRAM"?`${a.amount} گرم`:`${U(a.amount)} ریال`,S=a=>{n.value=a,v.value=!0};return C(async()=>{if(T.isLoggedIn){_.value=!0;try{d.value=await D.getMyLedgerEntries()}finally{_.value=!1}}}),(a,e)=>{const b=N("container");return l(),i("div",V,[r(P,{title:"اسناد","back-to":"userPage::hasSubRoute"}),r(O,{spinning:_.value,tip:"درحال دریافت اطلاعات"},{default:f(()=>[r(b,{class:"tx__body"},{default:f(()=>[d.value.length?(l(),i(y,{key:0},[r(B,{title:"گردش حساب",subtitle:`${d.value.length} سند`},null,8,["subtitle"]),s("div",$,[(l(!0),i(y,null,L(d.value,t=>(l(),i("article",{key:t.id,class:"tx__row",onClick:ns=>S(t)},[s("span",{class:p(["tx__mark",c(t)?"is-in":"is-out"]),"aria-hidden":"true"},[r(g,{icon:c(t)?"vuesax-linear:arrow-down":"vuesax-linear:arrow-up",size:"16"},null,8,["icon"])],2),s("div",j,[s("div",z,[s("h3",F,o(x[t.sourceType]??t.sourceType),1),s("span",{class:p(["tx__amount",c(t)?"is-in":"is-out"])},o(h(t)),3)]),t.note?(l(),i("p",G,o(t.note),1)):m("",!0),s("div",H,[s("span",J,o(E(R)(t.createdAt)),1),s("span",{class:p(["tx__state",{"is-pending":!t.confirmed}])},o(t.confirmed?"تایید شده":"در انتظار تایید"),3)])])],8,Y))),128))])],64)):_.value?m("",!0):(l(),i("section",K,[r(g,{icon:"vuesax-linear:receipt-text",size:"26"}),e[1]||(e[1]=s("p",null,"سندی برای حساب شما ثبت نشده است.",-1))]))]),_:1})]),_:1},8,["spinning"]),n.value?(l(),w(E(I),{key:0,visible:v.value,"onUpdate:visible":e[0]||(e[0]=t=>v.value=t),placement:"bottom",closable:!1,height:"420px",class:"rtl",bodyStyle:{padding:0}},{default:f(()=>[s("div",Q,[e[7]||(e[7]=s("h3",{class:"sheet__title"},"جزئیات سند",-1)),s("dl",W,[s("div",q,[e[2]||(e[2]=s("dt",null,"نوع سند",-1)),s("dd",null,o(x[n.value.sourceType]??n.value.sourceType),1)]),s("div",X,[e[3]||(e[3]=s("dt",null,"مبلغ",-1)),s("dd",{class:p(c(n.value)?"is-in":"is-out")},o(h(n.value)),3)]),s("div",Z,[e[4]||(e[4]=s("dt",null,"وضعیت",-1)),s("dd",null,o(n.value.confirmed?"تایید شده":"در انتظار تایید"),1)]),s("div",ss,[e[5]||(e[5]=s("dt",null,"تاریخ",-1)),s("dd",null,o(E(R)(n.value.createdAt)),1)]),s("div",es,[e[6]||(e[6]=s("dt",null,"توضیحات",-1)),s("dd",null,o(n.value.note||"—"),1)])])])]),_:1},8,["visible"])):m("",!0)])}}}),ps=M(ts,[["__scopeId","data-v-d21f0dcb"]]);export{ps as default};
import{d as k,E as A,o as C,p as D,c as i,l as r,s as f,j as w,u as E,e as m,g as u,f as l,F as y,b as s,r as L,I as g,t as o,i as p,v as N,_ as M}from"./index-DXb_5IMH.js";import{P}from"./PageBar-D8AimJPt.js";import{a as O}from"./Spinner.vue_vue_type_style_index_0_lang-BMAAb8Yk.js";import{S as B}from"./SectionHead-86JT-G_e.js";import{j as R,p as U}from"./filters-CLL9nGZ2.js";import{D as I}from"./index-C32LEWo8.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./classCallCheck-CkxIUjRf.js";const V={class:"tx"},$={class:"tx__list"},Y=["onClick"],j={class:"tx__main"},z={class:"tx__head"},F={class:"tx__kind"},G={key:0,class:"tx__note"},H={class:"tx__foot"},J={class:"tx__date"},K={key:1,class:"tx__empty"},Q={class:"sheet"},W={class:"sheet__specs"},q={class:"sheet__spec"},X={class:"sheet__spec"},Z={class:"sheet__spec"},ss={class:"sheet__spec"},es={class:"sheet__spec"},ts=k({__name:"TransactionsView",setup(os){const x={ORDER_STOCK:"سفارش",ORDER_PRE_ORDER:"سفارش ساخت",REPAYMENT_MELTED_GOLD:"طلای آب‌شده",REPAYMENT_TRANSFER:"حواله",REPAYMENT_CHEQUE:"چک",REPAYMENT_CASH:"پولی",WALLET_BONUS:"پاداش",ADJUSTMENT:"اصلاحیه"},T=A(),_=u(!1),d=u([]),v=u(!1),n=u(null),c=a=>a.direction==="CREDIT",h=a=>a.currency==="GOLD_GRAM"?`${a.amount} گرم`:`${U(a.amount)} ریال`,S=a=>{n.value=a,v.value=!0};return C(async()=>{if(T.isLoggedIn){_.value=!0;try{d.value=await D.getMyLedgerEntries()}finally{_.value=!1}}}),(a,e)=>{const b=N("container");return l(),i("div",V,[r(P,{title:"اسناد","back-to":"userPage::hasSubRoute"}),r(O,{spinning:_.value,tip:"درحال دریافت اطلاعات"},{default:f(()=>[r(b,{class:"tx__body"},{default:f(()=>[d.value.length?(l(),i(y,{key:0},[r(B,{title:"گردش حساب",subtitle:`${d.value.length} سند`},null,8,["subtitle"]),s("div",$,[(l(!0),i(y,null,L(d.value,t=>(l(),i("article",{key:t.id,class:"tx__row",onClick:ns=>S(t)},[s("span",{class:p(["tx__mark",c(t)?"is-in":"is-out"]),"aria-hidden":"true"},[r(g,{icon:c(t)?"vuesax-linear:arrow-down":"vuesax-linear:arrow-up",size:"16"},null,8,["icon"])],2),s("div",j,[s("div",z,[s("h3",F,o(x[t.sourceType]??t.sourceType),1),s("span",{class:p(["tx__amount",c(t)?"is-in":"is-out"])},o(h(t)),3)]),t.note?(l(),i("p",G,o(t.note),1)):m("",!0),s("div",H,[s("span",J,o(E(R)(t.createdAt)),1),s("span",{class:p(["tx__state",{"is-pending":!t.confirmed}])},o(t.confirmed?"تایید شده":"در انتظار تایید"),3)])])],8,Y))),128))])],64)):_.value?m("",!0):(l(),i("section",K,[r(g,{icon:"vuesax-linear:receipt-text",size:"26"}),e[1]||(e[1]=s("p",null,"سندی برای حساب شما ثبت نشده است.",-1))]))]),_:1})]),_:1},8,["spinning"]),n.value?(l(),w(E(I),{key:0,visible:v.value,"onUpdate:visible":e[0]||(e[0]=t=>v.value=t),placement:"bottom",closable:!1,height:"420px",class:"rtl",bodyStyle:{padding:0}},{default:f(()=>[s("div",Q,[e[7]||(e[7]=s("h3",{class:"sheet__title"},"جزئیات سند",-1)),s("dl",W,[s("div",q,[e[2]||(e[2]=s("dt",null,"نوع سند",-1)),s("dd",null,o(x[n.value.sourceType]??n.value.sourceType),1)]),s("div",X,[e[3]||(e[3]=s("dt",null,"مبلغ",-1)),s("dd",{class:p(c(n.value)?"is-in":"is-out")},o(h(n.value)),3)]),s("div",Z,[e[4]||(e[4]=s("dt",null,"وضعیت",-1)),s("dd",null,o(n.value.confirmed?"تایید شده":"در انتظار تایید"),1)]),s("div",ss,[e[5]||(e[5]=s("dt",null,"تاریخ",-1)),s("dd",null,o(E(R)(n.value.createdAt)),1)]),s("div",es,[e[6]||(e[6]=s("dt",null,"توضیحات",-1)),s("dd",null,o(n.value.note||"—"),1)])])])]),_:1},8,["visible"])):m("",!0)])}}}),ps=M(ts,[["__scopeId","data-v-d21f0dcb"]]);export{ps as default};
@@ -1 +1 @@
import{g as d,u as O,h as a,m as _,p as C}from"./index-D7u32dbn.js";function F(t){return(t.qty??0)>0||!!t.isPreOrder}function S(t){if(!t||t.length===0)return null;const e=t.filter(F);return(e.length?e:t).reduce((i,r)=>parseFloat(r.defaultWagePercent)<parseFloat(i.defaultWagePercent)?r:i)}function w(t,e){const s=d(t),i=a(()=>{var o,m;return(m=(o=s.value.images)==null?void 0:o[0])==null?void 0:m.url}),r=a(()=>s.value.id),n=a(()=>s.value.title),l=a(()=>s.value.variants),c=d(e??S(O(l))),v=a(()=>c.value?parseFloat(c.value.rashWeightGrams):0),y=a(()=>c.value?parseFloat(c.value.defaultWagePercent):null),g=d(null),h=a(()=>{var o;return((o=c.value)==null?void 0:o.qty)??0}),f=a(()=>{var o;return((o=c.value)==null?void 0:o.isPreOrder)??!1}),x=a(()=>h.value>0||f.value),q=a(()=>s.value.productCode??null),P=d(!1);return{product:s,image:i,id:r,title:n,productCode:q,variants:l,selectedVariant:c,min_gram:v,wage:y,hasDiscountWage:g,qty:h,isPreOrder:f,is_exist:x,has_warranty:P}}const p="appCart";function W(){try{const t=localStorage.getItem(p);return t?JSON.parse(t):[]}catch{return[]}}function u(t){localStorage.setItem(p,JSON.stringify(t))}const I=_("cart",{state:()=>({items:W()}),actions:{async init(){try{const t=await C.listProducts(),e=[];for(const s of this.items){const i=t.find(n=>n.id===s.pid),r=i==null?void 0:i.variants.find(n=>n.id===s.vid);i&&r&&e.push({...s,product:i})}this.items=e,u(this.items)}catch(t){console.log(t)}},addToCart(t){var i,r;const e=(r=(i=t.product)==null?void 0:i.variants)==null?void 0:r.find(n=>n.id===t.vid);if(!e||!((e.qty??0)>0||e.isPreOrder))return!1;const s=this.find_index(t);return s===-1?this.items.push({...t,qty:this.capQty(t.qty,e)}):(this.items[s].product=t.product,this.items[s].qty=this.capQty(t.qty,e)),u(this.items),!0},capQty(t,e){const s=Math.max(1,Math.floor(t)||1);if(e.isPreOrder)return s;const i=e.qty??0;return i>0?Math.min(s,i):s},maxQty(t){const e=this.find_index(t);if(e===-1)return null;const s=this.variant(this.items[e]);return!s||s.isPreOrder?null:(s.qty??0)>0?s.qty:null},remove(t){const e=this.find_index(t);e>-1&&this.items.splice(e,1),u(this.items)},updateFeild(t,e,s,i){if(!this.isInCart(s))return!1;const r=e??this.find_index(s);if(i==="qty"){const n=this.variant(this.items[r]);t=n?this.capQty(Number(t),n):Math.max(1,Number(t)||1)}return this.items[r][i]=t,u(this.items),!0},find_index(t){return this.items.findIndex(e=>e.pid===t.pid&&e.vid===t.vid)},isInCart(t){return this.find_index(t)>-1},variant(t){return t.product.variants.find(e=>e.id===t.vid)},total(){return this.items.reduce((t,e)=>{const s=this.variant(e);return t+(s?parseFloat(s.rashWeightGrams)*e.qty:0)},0).toFixed(2)},clear(){this.items=[],u(this.items)}}});export{I as a,F as i,w as u};
import{g as d,u as O,h as a,m as _,p as C}from"./index-DXb_5IMH.js";function F(t){return(t.qty??0)>0||!!t.isPreOrder}function S(t){if(!t||t.length===0)return null;const e=t.filter(F);return(e.length?e:t).reduce((i,r)=>parseFloat(r.defaultWagePercent)<parseFloat(i.defaultWagePercent)?r:i)}function w(t,e){const s=d(t),i=a(()=>{var o,m;return(m=(o=s.value.images)==null?void 0:o[0])==null?void 0:m.url}),r=a(()=>s.value.id),n=a(()=>s.value.title),l=a(()=>s.value.variants),c=d(e??S(O(l))),v=a(()=>c.value?parseFloat(c.value.rashWeightGrams):0),y=a(()=>c.value?parseFloat(c.value.defaultWagePercent):null),g=d(null),h=a(()=>{var o;return((o=c.value)==null?void 0:o.qty)??0}),f=a(()=>{var o;return((o=c.value)==null?void 0:o.isPreOrder)??!1}),x=a(()=>h.value>0||f.value),q=a(()=>s.value.productCode??null),P=d(!1);return{product:s,image:i,id:r,title:n,productCode:q,variants:l,selectedVariant:c,min_gram:v,wage:y,hasDiscountWage:g,qty:h,isPreOrder:f,is_exist:x,has_warranty:P}}const p="appCart";function W(){try{const t=localStorage.getItem(p);return t?JSON.parse(t):[]}catch{return[]}}function u(t){localStorage.setItem(p,JSON.stringify(t))}const I=_("cart",{state:()=>({items:W()}),actions:{async init(){try{const t=await C.listProducts(),e=[];for(const s of this.items){const i=t.find(n=>n.id===s.pid),r=i==null?void 0:i.variants.find(n=>n.id===s.vid);i&&r&&e.push({...s,product:i})}this.items=e,u(this.items)}catch(t){console.log(t)}},addToCart(t){var i,r;const e=(r=(i=t.product)==null?void 0:i.variants)==null?void 0:r.find(n=>n.id===t.vid);if(!e||!((e.qty??0)>0||e.isPreOrder))return!1;const s=this.find_index(t);return s===-1?this.items.push({...t,qty:this.capQty(t.qty,e)}):(this.items[s].product=t.product,this.items[s].qty=this.capQty(t.qty,e)),u(this.items),!0},capQty(t,e){const s=Math.max(1,Math.floor(t)||1);if(e.isPreOrder)return s;const i=e.qty??0;return i>0?Math.min(s,i):s},maxQty(t){const e=this.find_index(t);if(e===-1)return null;const s=this.variant(this.items[e]);return!s||s.isPreOrder?null:(s.qty??0)>0?s.qty:null},remove(t){const e=this.find_index(t);e>-1&&this.items.splice(e,1),u(this.items)},updateFeild(t,e,s,i){if(!this.isInCart(s))return!1;const r=e??this.find_index(s);if(i==="qty"){const n=this.variant(this.items[r]);t=n?this.capQty(Number(t),n):Math.max(1,Number(t)||1)}return this.items[r][i]=t,u(this.items),!0},find_index(t){return this.items.findIndex(e=>e.pid===t.pid&&e.vid===t.vid)},isInCart(t){return this.find_index(t)>-1},variant(t){return t.product.variants.find(e=>e.id===t.vid)},total(){return this.items.reduce((t,e)=>{const s=this.variant(e);return t+(s?parseFloat(s.rashWeightGrams)*e.qty:0)},0).toFixed(2)},clear(){this.items=[],u(this.items)}}});export{I as a,F as i,w as u};
@@ -1 +1 @@
import{c as l}from"./Spinner.vue_vue_type_style_index_0_lang-Ce4r_sA4.js";var f=function(n){return setTimeout(n,16)},c=function(n){return clearTimeout(n)};typeof window<"u"&&"requestAnimationFrame"in window&&(f=function(n){return window.requestAnimationFrame(n)},c=function(n){return window.cancelAnimationFrame(n)});var i=0,o=new Map;function u(e){o.delete(e)}function w(e){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:1;i+=1;var r=i;function a(t){if(t===0)u(r),e();else{var s=f(function(){a(t-1)});o.set(r,s)}}return a(n),r}w.cancel=function(e){var n=o.get(e);return u(n),c(n)};function m(e,n){for(var r=l({},e),a=0;a<n.length;a+=1){var t=n[a];delete r[t]}return r}function p(e,n,r){return Object.defineProperty(e,"prototype",{writable:!1}),e}function v(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}export{p as _,v as a,m as o,w};
import{c as l}from"./Spinner.vue_vue_type_style_index_0_lang-BMAAb8Yk.js";var f=function(n){return setTimeout(n,16)},c=function(n){return clearTimeout(n)};typeof window<"u"&&"requestAnimationFrame"in window&&(f=function(n){return window.requestAnimationFrame(n)},c=function(n){return window.cancelAnimationFrame(n)});var i=0,o=new Map;function u(e){o.delete(e)}function w(e){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:1;i+=1;var r=i;function a(t){if(t===0)u(r),e();else{var s=f(function(){a(t-1)});o.set(r,s)}}return a(n),r}w.cancel=function(e){var n=o.get(e);return u(n),c(n)};function m(e,n){for(var r=l({},e),a=0;a<n.length;a+=1){var t=n[a];delete r[t]}return r}function p(e,n,r){return Object.defineProperty(e,"prototype",{writable:!1}),e}function v(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}export{p as _,v as a,m as o,w};
@@ -1 +1 @@
import{d as r,l as c,a2 as p,ap as l,aq as d,$ as i,ar as u,as as m,ad as f,at as e,ac as g,ak as k}from"./index-D7u32dbn.js";const[h,P]=g("notify"),w=["lockScroll","position","show","teleport","zIndex"],y=i({},u,{type:e("danger"),color:String,message:f,position:e("top"),className:m,background:String,lockScroll:Boolean});var S=r({name:h,props:y,emits:["update:show"],setup(a,{emit:s,slots:o}){const t=n=>s("update:show",n);return()=>c(d,p({class:[P([a.type]),a.className],style:{color:a.color,background:a.background},overlay:!1,duration:.2,"onUpdate:show":t},l(a,w)),{default:()=>[o.default?o.default():a.message]})}});const b=k(S);export{b as N,S as s};
import{d as r,l as c,a2 as p,ap as l,aq as d,$ as i,ar as u,as as m,ad as f,at as e,ac as g,ak as k}from"./index-DXb_5IMH.js";const[h,P]=g("notify"),w=["lockScroll","position","show","teleport","zIndex"],y=i({},u,{type:e("danger"),color:String,message:f,position:e("top"),className:m,background:String,lockScroll:Boolean});var S=r({name:h,props:y,emits:["update:show"],setup(a,{emit:s,slots:o}){const t=n=>s("update:show",n);return()=>c(d,p({class:[P([a.type]),a.className],style:{color:a.color,background:a.background},overlay:!1,duration:.2,"onUpdate:show":t},l(a,w)),{default:()=>[o.default?o.default():a.message]})}});const b=k(S);export{b as N,S as s};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{ac as y,d as L,ad as $,ae as w,G as A,af as B,l as c,g as D,B as N,L as p,ag as G,q as I,ah as f,ai as M,aj as R,ak as U}from"./index-D7u32dbn.js";const[Y,r,j]=y("pull-refresh"),x=50,q=["pulling","loosing","success"],C={disabled:Boolean,modelValue:Boolean,headHeight:f(x),successText:String,pullingText:String,loosingText:String,loadingText:String,pullDistance:$,successDuration:f(500),animationDuration:f(300)};var F=L({name:Y,props:C,emits:["change","refresh","update:modelValue"],setup(s,{emit:d,slots:o}){let u;const g=D(),T=D(),H=w(g),e=N({status:"normal",distance:0,duration:0}),i=R(),P=()=>{if(s.headHeight!==x)return{height:`${s.headHeight}px`}},h=()=>e.status!=="loading"&&e.status!=="success"&&!s.disabled,k=t=>{const a=+(s.pullDistance||s.headHeight);return t>a&&(t<a*2?t=a+(t-a)/2:t=a*1.5+(t-a*2)/4),Math.round(t)},n=(t,a)=>{const l=+(s.pullDistance||s.headHeight);e.distance=t,a?e.status="loading":t===0?e.status="normal":t<l?e.status="pulling":e.status="loosing",d("change",{status:e.status,distance:t})},m=()=>{const{status:t}=e;return t==="normal"?"":s[`${t}Text`]||j(t)},E=()=>{const{status:t,distance:a}=e;if(o[t])return o[t]({distance:a});const l=[];return q.includes(t)&&l.push(c("div",{class:r("text")},[m()])),t==="loading"&&l.push(c(p,{class:r("loading")},{default:m})),l},V=()=>{e.status="success",setTimeout(()=>{n(0)},+s.successDuration)},v=t=>{u=M(H.value)===0,u&&(e.duration=0,i.start(t))},_=t=>{h()&&v(t)},b=t=>{if(h()){u||v(t);const{deltaY:a}=i;i.move(t),u&&a.value>=0&&i.isVertical()&&(G(t),n(k(a.value)))}},S=()=>{u&&i.deltaY.value&&h()&&(e.duration=+s.animationDuration,e.status==="loosing"?(n(+s.headHeight,!0),d("update:modelValue",!0),I(()=>d("refresh"))):n(0))};return A(()=>s.modelValue,t=>{e.duration=+s.animationDuration,t?n(+s.headHeight,!0):o.success||s.successText?V():n(0,!1)}),B("touchmove",b,{target:T}),()=>{var t;const a={transitionDuration:`${e.duration}ms`,transform:e.distance?`translate3d(0,${e.distance}px, 0)`:""};return c("div",{ref:g,class:r()},[c("div",{ref:T,class:r("track"),style:a,onTouchstartPassive:_,onTouchend:S,onTouchcancel:S},[c("div",{class:r("head"),style:P()},[E()]),(t=o.default)==null?void 0:t.call(o)])])}}});const z=U(F);export{z as P};
import{ac as y,d as L,ad as $,ae as w,G as A,af as B,l as c,g as D,B as N,L as p,ag as G,q as I,ah as f,ai as M,aj as R,ak as U}from"./index-DXb_5IMH.js";const[Y,r,j]=y("pull-refresh"),x=50,q=["pulling","loosing","success"],C={disabled:Boolean,modelValue:Boolean,headHeight:f(x),successText:String,pullingText:String,loosingText:String,loadingText:String,pullDistance:$,successDuration:f(500),animationDuration:f(300)};var F=L({name:Y,props:C,emits:["change","refresh","update:modelValue"],setup(s,{emit:d,slots:o}){let u;const g=D(),T=D(),H=w(g),e=N({status:"normal",distance:0,duration:0}),i=R(),P=()=>{if(s.headHeight!==x)return{height:`${s.headHeight}px`}},h=()=>e.status!=="loading"&&e.status!=="success"&&!s.disabled,k=t=>{const a=+(s.pullDistance||s.headHeight);return t>a&&(t<a*2?t=a+(t-a)/2:t=a*1.5+(t-a*2)/4),Math.round(t)},n=(t,a)=>{const l=+(s.pullDistance||s.headHeight);e.distance=t,a?e.status="loading":t===0?e.status="normal":t<l?e.status="pulling":e.status="loosing",d("change",{status:e.status,distance:t})},m=()=>{const{status:t}=e;return t==="normal"?"":s[`${t}Text`]||j(t)},E=()=>{const{status:t,distance:a}=e;if(o[t])return o[t]({distance:a});const l=[];return q.includes(t)&&l.push(c("div",{class:r("text")},[m()])),t==="loading"&&l.push(c(p,{class:r("loading")},{default:m})),l},V=()=>{e.status="success",setTimeout(()=>{n(0)},+s.successDuration)},v=t=>{u=M(H.value)===0,u&&(e.duration=0,i.start(t))},_=t=>{h()&&v(t)},b=t=>{if(h()){u||v(t);const{deltaY:a}=i;i.move(t),u&&a.value>=0&&i.isVertical()&&(G(t),n(k(a.value)))}},S=()=>{u&&i.deltaY.value&&h()&&(e.duration=+s.animationDuration,e.status==="loosing"?(n(+s.headHeight,!0),d("update:modelValue",!0),I(()=>d("refresh"))):n(0))};return A(()=>s.modelValue,t=>{e.duration=+s.animationDuration,t?n(+s.headHeight,!0):o.success||s.successText?V():n(0,!1)}),B("touchmove",b,{target:T}),()=>{var t;const a={transitionDuration:`${e.duration}ms`,transform:e.distance?`translate3d(0,${e.distance}px, 0)`:""};return c("div",{ref:g,class:r()},[c("div",{ref:T,class:r("track"),style:a,onTouchstartPassive:_,onTouchend:S,onTouchcancel:S},[c("div",{class:r("head"),style:P()},[E()]),(t=o.default)==null?void 0:t.call(o)])])}}});const z=U(F);export{z as P};
+1 -1
View File
@@ -9,7 +9,7 @@
<meta name="background-color" content="#1C2D56" />
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport" />
<title>طلای منتزر</title>
<script type="module" crossorigin src="/assets/index-D7u32dbn.js"></script>
<script type="module" crossorigin src="/assets/index-DXb_5IMH.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-D-jEuKqG.css">
<link rel="manifest" href="/manifest.webmanifest"></head>
<body style="background-color: #1C2D56">
+1 -1
View File
File diff suppressed because one or more lines are too long
+85
View File
@@ -213,6 +213,72 @@ export interface ExpertChildOrder {
items: OrderItemDetail[];
customer: { id: string; name: string; mobile: string } | null;
}
/**
* D24 — "گزارش", the account statement.
*
* The field names are the reference's (henza_pwa/src/type/accounting.ts), so
* the ported components bind exactly as they did. Money and weights travel as
* decimal STRINGS, never as JS numbers, so no figure is rounded in transit.
*/
export interface ReportRow {
id: number;
/** The ledger entry id; what the detail call is keyed on. */
factor_Code: string;
sh_factor: string;
tarikh: string;
/** Gold in / out, as separate positive columns. */
geram_v: string;
geram_kh: string;
rial_v: string;
rial_kh: string;
/** Running balances AFTER this row. Signed: negative means in credit. */
tahesab_T: string;
tahesab_P: string;
/** No foreign-currency ledger in the target — always zero (REP-01). */
rial_V2: string;
rial_Kh2: string;
tahesabP2: string;
sourceType: string;
note: string | null;
}
export interface ReportPage {
result: ReportRow[];
count: number;
page: number;
limit: number;
}
/** One document's detail. Fields the target cannot know are null, not invented. */
export interface ReportDetailRow {
factor_Code: string;
sh_factor: string;
tarikh: string;
vazn: string;
ayar: number | null;
no: string;
sh_sharti: string | null;
name_az: string | null;
tabdil750_v: string;
tabdil750_kh: string;
fi: string | null;
fiF: string | null;
Darsad_Talayee: string | null;
accountName: string | null;
bankName: string | null;
transferTo: string | null;
receivedAt: string | null;
note: string | null;
nO_kar: null;
jens_felez: null;
Darsad: null;
maliatDarsad: null;
}
export interface ReportBalance {
arz: string;
mandeh: string;
}
export const api = {
listProducts: () => request<ProductSummary[]>('/catalog/products'),
/**
@@ -311,4 +377,23 @@ export const api = {
method: 'POST',
body: JSON.stringify(payload),
}),
// ── report / report detail (D24) ─────────────────────────────────────
// The reference proxied an external accounting system
// (henza_server Customer/TahesabController). These read the target's own
// ledger instead — no external call — and the customer comes from the token.
getReport: (page = 1) =>
request<ReportPage>(`/customer/me/report?page=${page}`),
getReportDetailList: (page = 1) =>
request<{ result: ReportDetailRow[]; page: number; limit: number }>(
`/customer/me/report/detail?page=${page}`,
),
getReportBalances: () =>
request<{ status: number; message: string; result: ReportBalance[] }>(
'/customer/me/report/balances',
),
getReportDocument: (id: string) =>
request<{ result: ReportDetailRow[]; page: number; limit: number }>(
`/customer/me/report/${encodeURIComponent(id)}`,
),
};
+15
View File
@@ -62,6 +62,21 @@ export const router = createRouter({
component: () => import('../views/user/CompleteProfileView.vue'),
meta: { title: 'تکمیل پروفایل', layout: 'FullPage', requiresAuth: true, requiresIncompleteProfile: true },
},
// D24 — the account statement. Reference paths and names kept
// (henza_pwa router/index.ts:163-165, :191-193). The detail route opens
// the same page on its second tab, as the reference did.
{
path: '/report',
name: 'report',
component: () => import('../views/report/ReportView.vue'),
meta: { title: 'گزارش', layout: 'FullPage', requiresAuth: true },
},
{
path: '/report/detail',
name: 'reportDetail',
component: () => import('../views/report/ReportView.vue'),
meta: { title: 'جزئیات حساب', layout: 'FullPage', requiresAuth: true },
},
{ path: '/notifications', name: 'notifications', component: () => import('../views/user/NotificationsView.vue') },
{ path: '/search', name: 'search', component: () => import('../views/search/SearchView.vue') },
{ path: '/collection/:id?', name: 'collection', component: () => import('../views/search/CollectionView.vue') },
@@ -0,0 +1,198 @@
<!--
One document of "جزئیات حساب".
Ported from henza_pwa/src/views/report/components/AccountingDetail.vue,
restyled into this app's design language. The LOGIC is the reference's and is
identical in user-app; only the styling differs.
Kept from the reference: شماره سند + تاریخ, وزن خالص, عیار, نوع سند,
شماره انگ, نام آزمایشگاه, قیمت, and the طلا in/out pair normalized to 750
(AccountingDetail.vue:6-85).
Rows the reference showed that the target has no equivalent for — نام کارساخته
(nO_kar), جنس فلز (jens_felez) and the two extra percentage lines — are
OMITTED rather than rendered blank or zero. They came from an external
accounting system the target does not have; the API returns null for them and
this component skips a row whose value is null, so the card never asserts
something it does not know. Recorded as REP-01.
Rows the target CAN fill and the reference could not are added at the end
(bank/account/destination), since those live on our own ledger entry.
-->
<template>
<article class="doc">
<header class="doc__head">
<span><span class="doc__muted">شماره سند:</span> {{ item.sh_factor }}</span>
<span><span class="doc__muted">تاریخ:</span> {{ jdate(item.tarikh) }}</span>
</header>
<dl class="doc__rows">
<div class="doc__row">
<dt>نوع سند</dt>
<dd>{{ item.no }}</dd>
</div>
<div class="doc__row">
<dt>وزن خالص</dt>
<dd dir="ltr">{{ item.vazn }}</dd>
</div>
<div v-if="item.ayar !== null" class="doc__row">
<dt>عیار</dt>
<dd dir="ltr">{{ item.ayar }}</dd>
</div>
<div v-if="item.sh_sharti" class="doc__row">
<dt>شماره انگ</dt>
<dd dir="ltr">{{ item.sh_sharti }}</dd>
</div>
<div v-if="item.name_az" class="doc__row">
<dt>نام آزمایشگاه</dt>
<dd>{{ item.name_az }}</dd>
</div>
<div v-if="item.Darsad_Talayee" class="doc__row">
<dt>اجرت (گرم)</dt>
<dd dir="ltr">{{ item.Darsad_Talayee }}</dd>
</div>
<div v-if="item.fi" class="doc__row">
<dt>قیمت هر گرم</dt>
<dd dir="ltr">{{ rial(item.fi) }}</dd>
</div>
<div v-if="item.fiF" class="doc__row">
<dt>مبلغ سند</dt>
<dd dir="ltr">{{ rial(item.fiF) }}</dd>
</div>
<div v-if="item.bankName" class="doc__row">
<dt>بانک</dt>
<dd>{{ item.bankName }}</dd>
</div>
<div v-if="item.accountName" class="doc__row">
<dt>نام حساب</dt>
<dd>{{ item.accountName }}</dd>
</div>
<div v-if="item.transferTo" class="doc__row">
<dt>مقصد حواله</dt>
<dd>{{ item.transferTo }}</dd>
</div>
<div v-if="item.receivedAt" class="doc__row">
<dt>تاریخ دریافت</dt>
<dd>{{ jdate(item.receivedAt) }}</dd>
</div>
<div v-if="item.note" class="doc__row">
<dt>توضیحات</dt>
<dd>{{ item.note }}</dd>
</div>
</dl>
<div class="doc__gold">
<span>طلا</span>
<div class="doc__stack">
<span dir="ltr" class="is-in">{{ item.tabdil750_v }}</span>
<span dir="ltr" class="is-out">{{ item.tabdil750_kh }}</span>
</div>
</div>
</article>
</template>
<script setup lang="ts">
import { jdate, price } from '../../utils/filters'
import type { ReportDetailRow } from '../../api/client'
defineProps<{ item: ReportDetailRow }>()
/** Same rule as the statement: group the whole part only. */
function rial(value: string): string {
const n = parseFloat(value)
if (!Number.isFinite(n)) return value
const whole = Math.trunc(Math.abs(n)).toString()
return (n < 0 ? '-' : '') + price(whole)
}
</script>
<style scoped lang="less">
/*
v2 styling. The template and script above are IDENTICAL to user-app's — only
this block differs. v2 draws the document as a flat, hairline-separated block
rather than an outlined card.
*/
.doc {
padding: 18px 2px;
background: transparent;
border: none;
border-bottom: 1px solid @hairline;
}
.doc:last-child {
border-bottom: none;
}
.doc__head {
display: flex;
justify-content: space-between;
gap: 10px;
margin-bottom: 10px;
font-size: 13px;
font-weight: 600;
}
.doc__muted {
color: @inkMuted;
font-weight: 500;
margin-left: 4px;
}
.doc__rows {
margin: 0;
display: flex;
flex-direction: column;
}
.doc__row {
display: flex;
justify-content: space-between;
align-items: center;
gap: 12px;
padding: 9px 0;
border-bottom: 1px dashed @hairlineSoft;
}
.doc__row:last-child {
border-bottom: none;
}
.doc__row dt {
font-size: 12.5px;
color: @inkMuted;
white-space: nowrap;
}
.doc__row dd {
margin: 0;
font-size: 13.5px;
font-weight: 600;
text-align: left;
}
.doc__gold {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 10px;
padding-top: 10px;
border-top: 1px dashed @hairline;
font-size: 13px;
font-weight: 700;
}
.doc__stack {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 2px;
}
.is-in {
color: #16a34a;
}
.is-out {
color: #dc2626;
}
</style>
@@ -0,0 +1,441 @@
<!--
"گزارش" — the customer's account statement.
Ported from henza_pwa/src/views/report/index.vue (route /report, name
report) plus its two card components (components/Accounting.vue,
components/AccountingDetail.vue), restyled into this app's design language.
The LOGIC is the reference's and is identical in user-app; only the
styling differs.
Kept from the reference:
- the title "گزارش" and the back arrow to the dashboard (index.vue:7-10)
- the two tabs «کلیات حساب» / «جزئیات حساب» (:15-16), switching clears the
list and re-queries from page 1 (:178-181)
- the summary card's rows, in the reference's order: شماره سند + تاریخ,
طلا (in/out), مانده طلا, ریال (in/out), مانده ریال (Accounting.vue:5-48)
- balances coloured by sign — red when negative (Accounting.vue:29, :46)
- the «جزئیات» link opening the document in a modal (:66, index.vue:44-52)
- paging by scroll on the detail tab (:231-241)
Deliberately NOT ported: the ارز (foreign-currency) rows. The reference read
them from an external accounting system; the target has no foreign-currency
ledger, so showing a hardcoded "0 $" would assert something untrue. Recorded
as REP-01.
The reference gated this page on `myStore.hasMCode()` (index.vue:174-177) —
the customer's id in that external system. The target has no mcode, so the
gate is simply a session, and the server scopes every row to the token.
-->
<template>
<div class="rep">
<PageBar title="گزارش" back-to="userPage::hasSubRoute">
<template #below>
<div class="rep__tabs">
<button
type="button"
class="rep__tab"
:class="{ 'is-on': activeKey === '1' }"
@click="changeTab('1')"
>
کلیات حساب
</button>
<button
type="button"
class="rep__tab"
:class="{ 'is-on': activeKey === '2' }"
@click="changeTab('2')"
>
جزئیات حساب
</button>
</div>
</template>
</PageBar>
<Spinner :spinning="loading && !rows.length && !details.length" tip="درحال دریافت اطلاعات">
<PullRefresh v-model="refreshing" @refresh="onRefresh">
<container class="rep__body">
<!-- ── کلیات حساب ─────────────────────────────────────────── -->
<template v-if="activeKey === '1'">
<div v-if="rows.length" class="rep__list">
<article v-for="item in rows" :key="item.factor_Code" class="rep__card">
<header class="rep__head">
<span><span class="rep__muted">شماره سند:</span> {{ item.sh_factor }}</span>
<span><span class="rep__muted">تاریخ:</span> {{ jdate(item.tarikh) }}</span>
</header>
<div class="rep__pair">
<span>طلا</span>
<div class="rep__stack">
<span dir="ltr" class="is-in">{{ item.geram_v }}</span>
<span dir="ltr" class="is-out">{{ item.geram_kh }}</span>
</div>
</div>
<div class="rep__pair is-balance">
<span>مانده طلا:</span>
<span dir="ltr" :class="sign(item.tahesab_T)">{{ item.tahesab_T }}</span>
</div>
<div class="rep__pair">
<span>ریال</span>
<div class="rep__stack">
<span dir="ltr" class="is-in">{{ rial(item.rial_v) }}</span>
<span dir="ltr" class="is-out">{{ rial(item.rial_kh) }}</span>
</div>
</div>
<div class="rep__pair is-balance">
<span>مانده ریال:</span>
<span dir="ltr" :class="sign(item.tahesab_P)">{{ rial(item.tahesab_P) }}</span>
</div>
<button type="button" class="rep__more" @click="openDetail(item)">جزئیات</button>
</article>
</div>
<section v-else-if="!loading && !failed" class="rep__empty">
<Icon icon="vuesax-linear:receipt-text" size="26" />
<p>هنوز سندی برای حساب شما ثبت نشده است.</p>
</section>
</template>
<!-- ── جزئیات حساب ────────────────────────────────────────── -->
<template v-else>
<div v-if="details.length" class="rep__list">
<ReportDocument v-for="d in details" :key="d.factor_Code" :item="d" />
</div>
<section v-else-if="!loading && !failed" class="rep__empty">
<Icon icon="vuesax-linear:receipt-text" size="26" />
<p>هنوز سندی برای حساب شما ثبت نشده است.</p>
</section>
</template>
<section v-if="failed" class="rep__empty">
<Icon icon="vuesax-linear:danger" size="26" />
<p>دریافت اطلاعات با خطا روبه‌رو شد.</p>
<button type="button" class="rep__retry" @click="reload">تلاش دوباره</button>
</section>
<div v-if="loading && (rows.length || details.length)" class="rep__more">در حال دریافت…</div>
<div ref="sentinel" class="rep__sentinel" />
</container>
</PullRefresh>
</Spinner>
<Drawer
v-model:open="modalOpen"
placement="bottom"
height="auto"
:closable="false"
:body-style="{ padding: '0' }"
>
<div class="rep__modal">
<Spinner :spinning="modalLoading" tip="درحال دریافت اطلاعات">
<ReportDocument v-for="d in modalRows" :key="d.factor_Code" :item="d" />
<p v-if="!modalLoading && !modalRows.length" class="rep__modalEmpty">
جزئیاتی برای این سند ثبت نشده است.
</p>
</Spinner>
<button type="button" class="rep__close" @click="modalOpen = false">بازگشت</button>
</div>
</Drawer>
</div>
</template>
<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref } from 'vue'
import { useRoute } from 'vue-router'
import { Drawer } from 'ant-design-vue'
import { PullRefresh } from 'vant'
import Icon from '../../components/icon/Icon.vue'
import PageBar from '../../components/ui/PageBar.vue'
import Spinner from '../../components/Spinner.vue'
import ReportDocument from './ReportDocument.vue'
import { jdate, price } from '../../utils/filters'
import { api, type ReportRow, type ReportDetailRow } from '../../api/client'
const route = useRoute()
/**
* The reference had /report and /report/detail as two routes. The detail one
* lands on the same screen with the second tab already selected, which is what
* its 'جزئیات حساب' tab showed.
*/
const activeKey = ref<'1' | '2'>(route.name === 'reportDetail' ? '2' : '1')
const rows = ref<ReportRow[]>([])
const details = ref<ReportDetailRow[]>([])
const page = ref(1)
const hasMore = ref(true)
const loading = ref(false)
const refreshing = ref(false)
const failed = ref(false)
const modalOpen = ref(false)
const modalLoading = ref(false)
const modalRows = ref<ReportDetailRow[]>([])
/**
* price() groups digits from the right, so a decimal tail would be grouped
* too. Rial figures are whole here, so the .00 is dropped before grouping and
* a negative sign is preserved outside the grouping.
*/
function rial(value: string): string {
const n = parseFloat(value)
if (!Number.isFinite(n)) return value
const whole = Math.trunc(Math.abs(n)).toString()
return (n < 0 ? '-' : '') + price(whole)
}
/** The reference coloured a balance by its sign (Accounting.vue:29). */
function sign(value: string): string {
return parseFloat(value) < 0 ? 'is-out' : 'is-in'
}
async function fetchPage() {
if (loading.value || !hasMore.value) return
loading.value = true
failed.value = false
try {
if (activeKey.value === '1') {
const data = await api.getReport(page.value)
rows.value = [...rows.value, ...(data.result ?? [])]
if ((data.result?.length ?? 0) < (data.limit ?? 50)) hasMore.value = false
else page.value += 1
} else {
const data = await api.getReportDetailList(page.value)
details.value = [...details.value, ...(data.result ?? [])]
if ((data.result?.length ?? 0) < (data.limit ?? 50)) hasMore.value = false
else page.value += 1
}
} catch {
failed.value = true
hasMore.value = false
} finally {
loading.value = false
}
}
function reset() {
rows.value = []
details.value = []
page.value = 1
hasMore.value = true
failed.value = false
}
async function reload() {
reset()
await fetchPage()
}
/** The reference cleared the list and re-queried on tab change (index.vue:178). */
async function changeTab(key: '1' | '2') {
if (activeKey.value === key) return
activeKey.value = key
await reload()
}
async function onRefresh() {
await reload()
refreshing.value = false
}
/** The «جزئیات» link — the reference opened the same card in a modal. */
async function openDetail(item: ReportRow) {
modalOpen.value = true
modalLoading.value = true
modalRows.value = []
try {
const data = await api.getReportDocument(item.factor_Code)
modalRows.value = data.result ?? []
} catch {
modalRows.value = []
} finally {
modalLoading.value = false
}
}
// The reference paged by scroll on the detail tab (index.vue:231-241).
const sentinel = ref<HTMLElement | null>(null)
let observer: IntersectionObserver | null = null
onMounted(async () => {
await fetchPage()
if (typeof IntersectionObserver !== 'undefined') {
observer = new IntersectionObserver((entries) => {
if (entries.some((e) => e.isIntersecting)) void fetchPage()
})
if (sentinel.value) observer.observe(sentinel.value)
}
})
onBeforeUnmount(() => observer?.disconnect())
</script>
<style scoped lang="less">
/*
v2 styling. The template and script above are IDENTICAL to user-app's — only
this block differs. v2 uses its underlined tab strip and a continuous,
hairline-separated statement rather than outlined cards.
*/
.rep__tabs {
display: flex;
gap: 24px;
padding: 0 16px 10px;
}
.rep__tab {
padding: 8px 0;
border: none;
border-bottom: 2px solid transparent;
background: transparent;
font-family: inherit;
font-size: 14px;
font-weight: 600;
color: @inkFaint;
cursor: pointer;
}
.rep__tab.is-on {
color: @ink;
border-bottom-color: @wine;
}
.rep__body {
padding-top: 126px;
padding-bottom: 90px;
}
.rep__list {
display: flex;
flex-direction: column;
padding-top: 8px;
}
.rep__card {
padding: 18px 2px;
background: transparent;
border: none;
border-bottom: 1px solid @hairline;
}
.rep__card:last-child {
border-bottom: none;
}
.rep__head {
display: flex;
justify-content: space-between;
gap: 10px;
margin-bottom: 12px;
font-size: 13px;
font-weight: 600;
}
.rep__muted {
color: @inkMuted;
font-weight: 500;
margin-left: 4px;
}
.rep__pair {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 0;
font-size: 13px;
color: @inkMuted;
}
.rep__pair.is-balance {
padding-top: 10px;
border-top: 1px dashed @hairline;
color: @ink;
font-weight: 700;
}
.rep__stack {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 2px;
font-weight: 600;
}
.is-in {
color: #16a34a;
}
.is-out {
color: #dc2626;
}
.rep__more,
.rep__sentinel {
padding: 12px 0;
text-align: center;
font-size: 12px;
color: @inkMuted;
}
.rep__more {
width: 100%;
margin-top: 6px;
border: none;
background: transparent;
font-family: inherit;
font-weight: 700;
color: @wine;
cursor: pointer;
}
.rep__empty {
margin-top: 40px;
padding: 34px 20px;
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
color: @inkMuted;
font-size: 13px;
}
.rep__retry {
padding: 8px 18px;
border-radius: 999px;
border: 1px solid @hairline;
background: @canvas;
font-family: inherit;
font-size: 12px;
font-weight: 600;
cursor: pointer;
}
.rep__modal {
padding: 20px 16px 24px;
}
.rep__modalEmpty {
padding: 24px 0;
text-align: center;
font-size: 13px;
color: @inkMuted;
}
.rep__close {
margin-top: 18px;
width: 100%;
padding: 14px;
border: none;
border-radius: 999px;
background: @wine;
color: #fff;
font-family: inherit;
font-size: 14px;
font-weight: 700;
cursor: pointer;
}
</style>
@@ -151,6 +151,22 @@
</span>
<Icon icon="vuesax-linear:arrow-left-2" size="16" color="#8A909C" />
</button>
<!--
D24 — the account statement. The reference put it on the dashboard
too, gated on hasMCode() (Dashboard.vue:179, :449). The target has no
mcode, so every signed-in customer sees it and the server scopes it
to their token.
-->
<button type="button" class="dash__row" @click="goToDetails(6)">
<span class="dash__rowIcon" aria-hidden="true">
<Icon icon="vuesax-linear:chart-2" size="18" />
</span>
<span class="dash__rowText">
<b>گزارش</b>
<small>گردش حساب طلایی و ریالی شما</small>
</span>
<Icon icon="vuesax-linear:arrow-left-2" size="16" color="#8A909C" />
</button>
<!--
D21 — the two sales-expert entries, rendered only for an expert, in
@@ -260,6 +276,7 @@ function goToDetails(id: number) {
if (id === 3) router.push({ name: 'favoritesList' })
if (id === 4) router.push({ name: 'ChildOrder' })
if (id === 5) router.push({ name: 'customerChoice' })
if (id === 6) router.push({ name: 'report' })
}
function logOut() {
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{d as f,o as v,q as g,c as s,k as e,s as u,g as p,h as m,i as t,F as y,r as k,I as P,b as x,f as C,v as b,K as h,x as B,_ as V}from"./index-0lMAZRQB.js";import{P as w}from"./PageBar-DP6LpIFv.js";import{a as I}from"./Spinner.vue_vue_type_style_index_0_lang-Q7UPdMbi.js";import{S as N}from"./SectionHead-BuisDFZg.js";import{P as q}from"./ProductCard-Cbfp9CSN.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./SingleProduct-BCX5wlE-.js";import"./NotifyVant.vue_vue_type_script_setup_true_lang-BKaF0fT-.js";import"./index-W8LzFWDq.js";import"./DialogVant.vue_vue_type_style_index_0_lang-DiDmrjDM.js";import"./cartStore-qaurfaGv.js";import"./dialogEmpty1-Caw7F5KL.js";import"./index-BlJivYzz.js";import"./classCallCheck-Tw9-kd3s.js";const F={class:"coll"},S={key:0,class:"coll__grid"},z={key:1,class:"coll__empty"},E=f({__name:"CollectionView",setup(H){const l=h(),o=p(!1),n=p([]),d=m(()=>l.query.page||"مجموعه"),i=m(()=>n.value.filter(r=>r.collections.some(a=>a.collectionId===l.params.id)));return v(async()=>{o.value=!0;try{n.value=await g.listProducts()}finally{o.value=!1}}),(r,a)=>{const _=b("container");return t(),s("div",F,[e(w,{title:d.value,"back-to":"search"},null,8,["title"]),e(I,{spinning:o.value,tip:"درحال دریافت اطلاعات"},{default:u(()=>[e(_,{class:"coll__body"},{default:u(()=>[e(N,{title:"محصولات این مجموعه",subtitle:"برای دیدن جزئیات، روی محصول ضربه بزنید"}),i.value.length?(t(),s("div",S,[(t(!0),s(y,null,k(i.value,c=>(t(),B(q,{key:c.id,value:c},null,8,["value"]))),128))])):o.value?C("",!0):(t(),s("section",z,[e(P,{icon:"vuesax-linear:box",size:"26"}),a[0]||(a[0]=x("p",null,"در این مجموعه محصولی ثبت نشده است.",-1))]))]),_:1})]),_:1},8,["spinning"])])}}}),W=V(E,[["__scopeId","data-v-4e05d52b"]]);export{W as default};
import{d as f,o as v,q as g,c as s,k as e,s as u,g as p,h as m,i as t,F as y,r as k,I as P,b as x,f as C,v as b,K as h,x as B,_ as V}from"./index-BrtROTwT.js";import{P as w}from"./PageBar-Dh4JEEwN.js";import{a as I}from"./Spinner.vue_vue_type_style_index_0_lang-DTTCd0cJ.js";import{S as N}from"./SectionHead-CiVUI4hB.js";import{P as q}from"./ProductCard-DDelyzoS.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./SingleProduct-BtjwWkoB.js";import"./NotifyVant.vue_vue_type_script_setup_true_lang-cAF7h1vK.js";import"./index-DypKz_AO.js";import"./DialogVant.vue_vue_type_style_index_0_lang-Cbw1QjpS.js";import"./cartStore-NY9cOv5n.js";import"./dialogEmpty1-Caw7F5KL.js";import"./index-DixO0OJ3.js";import"./classCallCheck-DE78qYAT.js";const F={class:"coll"},S={key:0,class:"coll__grid"},z={key:1,class:"coll__empty"},E=f({__name:"CollectionView",setup(H){const l=h(),o=p(!1),n=p([]),d=m(()=>l.query.page||"مجموعه"),i=m(()=>n.value.filter(r=>r.collections.some(a=>a.collectionId===l.params.id)));return v(async()=>{o.value=!0;try{n.value=await g.listProducts()}finally{o.value=!1}}),(r,a)=>{const _=b("container");return t(),s("div",F,[e(w,{title:d.value,"back-to":"search"},null,8,["title"]),e(I,{spinning:o.value,tip:"درحال دریافت اطلاعات"},{default:u(()=>[e(_,{class:"coll__body"},{default:u(()=>[e(N,{title:"محصولات این مجموعه",subtitle:"برای دیدن جزئیات، روی محصول ضربه بزنید"}),i.value.length?(t(),s("div",S,[(t(!0),s(y,null,k(i.value,c=>(t(),B(q,{key:c.id,value:c},null,8,["value"]))),128))])):o.value?C("",!0):(t(),s("section",z,[e(P,{icon:"vuesax-linear:box",size:"26"}),a[0]||(a[0]=x("p",null,"در این مجموعه محصولی ثبت نشده است.",-1))]))]),_:1})]),_:1},8,["spinning"])])}}}),W=V(E,[["__scopeId","data-v-4e05d52b"]]);export{W as default};
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{d as z,o as S,c,k as a,s as d,u as w,g as r,q as N,i,b as s,F as P,r as B,I as u,t as o,f as m,v as D,e as F,_ as I}from"./index-0lMAZRQB.js";import{P as E}from"./PageBar-DP6LpIFv.js";import{a as R}from"./Spinner.vue_vue_type_style_index_0_lang-Q7UPdMbi.js";import{S as $}from"./SearchInput-BoLb-2jQ.js";import{D as U}from"./index-BlJivYzz.js";import{P as q}from"./index-CWibuKdZ.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./classCallCheck-Tw9-kd3s.js";const L={class:"cch"},M={class:"cch__barExtra"},O={key:0,class:"cch__list"},T=["onClick"],j={class:"cch__head"},A={class:"cch__name"},G={class:"cch__facts"},H={class:"cch__fact"},J={dir:"ltr"},K={class:"cch__fact"},Q={dir:"ltr"},W={key:0,class:"cch__fact"},X={key:1,class:"cch__empty"},Y={key:2,class:"cch__empty"},Z={key:0,class:"cch__detail"},ss={class:"cch__detailTitle"},es={class:"cch__rows"},ts={class:"cch__row"},os={dir:"ltr"},as={class:"cch__row"},ls={dir:"ltr"},ns={class:"cch__row"},cs={class:"cch__row"},is={class:"cch__row"},rs={dir:"ltr"},_s={class:"cch__row"},ds={dir:"ltr"},us={class:"cch__row"},vs=z({__name:"CustomerChoiceView",setup(hs){const _=r([]),v=r(!1),y=r(!1),h=r(!1),b=r(null),p=r(!1),l=r(null);function g(n){const e=Number(n??0);return Number.isFinite(e)?e.toFixed(3):"0.000"}async function f(){v.value=!0,h.value=!1;try{_.value=await N.getExpertCustomers(b.value)}catch{h.value=!0,_.value=[]}finally{v.value=!1}}async function k(n){b.value=n!=null&&n.trim()?n.trim():null,await f()}async function C(){await f(),y.value=!1}function x(n){l.value=n,p.value=!0}return S(f),(n,e)=>{const V=D("container");return i(),c("div",L,[a(E,{title:"لیست مشتریان","back-to":"userPage::hasSubRoute"},{below:d(()=>[s("div",M,[a($,{onSearch:k,"place-holder":"جستجو"})])]),_:1}),a(R,{spinning:v.value&&!_.value.length,tip:"درحال دریافت اطلاعات"},{default:d(()=>[a(w(q),{modelValue:y.value,"onUpdate:modelValue":e[0]||(e[0]=t=>y.value=t),onRefresh:C},{default:d(()=>[a(V,{class:"cch__body"},{default:d(()=>[_.value.length?(i(),c("div",O,[(i(!0),c(P,null,B(_.value,t=>(i(),c("article",{key:t.id,class:"cch__card",onClick:ps=>x(t)},[s("div",j,[s("h3",A,o(t.name),1),s("span",{class:F(["cch__state",t.active===1?"is-on":"is-off"])},o(t.active===1?"فعال":"غیرفعال"),3)]),s("div",G,[s("div",H,[a(u,{icon:"vuesax-linear:mobile",size:"15"}),s("span",J,o(t.mobile||"—"),1)]),s("div",K,[a(u,{icon:"vuesax-linear:call",size:"15"}),s("span",Q,o(t.phone||"—"),1)]),t.store_name?(i(),c("div",W,[a(u,{icon:"vuesax-linear:shop",size:"15"}),s("span",null,o(t.store_name),1)])):m("",!0)])],8,T))),128))])):!v.value&&!h.value?(i(),c("section",X,[a(u,{icon:"vuesax-linear:profile-2user",size:"26"}),s("p",null,o(b.value?"مشتری با این مشخصات پیدا نشد.":"هنوز مشتری‌ای به شما معرفی نشده است."),1)])):m("",!0),h.value?(i(),c("section",Y,[a(u,{icon:"vuesax-linear:danger",size:"26"}),e[3]||(e[3]=s("p",null,"دریافت اطلاعات با خطا روبه‌رو شد.",-1)),s("button",{type:"button",class:"cch__retry",onClick:f},"تلاش دوباره")])):m("",!0)]),_:1})]),_:1},8,["modelValue"])]),_:1},8,["spinning"]),a(w(U),{open:p.value,"onUpdate:open":e[2]||(e[2]=t=>p.value=t),placement:"bottom",height:"auto",closable:!1,"body-style":{padding:"0"}},{default:d(()=>[l.value?(i(),c("div",Z,[s("h2",ss,o(l.value.name),1),s("dl",es,[s("div",ts,[e[4]||(e[4]=s("dt",null,"موبایل",-1)),s("dd",os,o(l.value.mobile||"—"),1)]),s("div",as,[e[5]||(e[5]=s("dt",null,"تلفن",-1)),s("dd",ls,o(l.value.phone||"—"),1)]),s("div",ns,[e[6]||(e[6]=s("dt",null,"نام مغازه",-1)),s("dd",null,o(l.value.store_name||"—"),1)]),s("div",cs,[e[7]||(e[7]=s("dt",null,"نام پاساژ",-1)),s("dd",null,o(l.value.pasazh_name||"—"),1)]),s("div",is,[e[8]||(e[8]=s("dt",null,"سقف اعتبار",-1)),s("dd",rs,o(g(l.value.gram_level))+" گرم",1)]),s("div",_s,[e[9]||(e[9]=s("dt",null,"بدهی گرمی",-1)),s("dd",ds,o(g(l.value.remain))+" گرم",1)]),s("div",us,[e[10]||(e[10]=s("dt",null,"وضعیت",-1)),s("dd",null,o(l.value.active===1?"فعال":"غیرفعال"),1)])]),s("button",{type:"button",class:"cch__close",onClick:e[1]||(e[1]=t=>p.value=!1)},"بستن")])):m("",!0)]),_:1},8,["open"])])}}}),xs=I(vs,[["__scopeId","data-v-0f43a8be"]]);export{xs as default};
import{d as z,o as S,c,k as a,s as d,u as w,g as r,q as N,i,b as s,F as P,r as B,I as u,t as o,f as m,v as D,e as F,_ as I}from"./index-BrtROTwT.js";import{P as E}from"./PageBar-Dh4JEEwN.js";import{a as R}from"./Spinner.vue_vue_type_style_index_0_lang-DTTCd0cJ.js";import{S as $}from"./SearchInput-Br9l2s1o.js";import{D as U}from"./index-DixO0OJ3.js";import{P as q}from"./index-DPfyaKOl.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./classCallCheck-DE78qYAT.js";const L={class:"cch"},M={class:"cch__barExtra"},O={key:0,class:"cch__list"},T=["onClick"],j={class:"cch__head"},A={class:"cch__name"},G={class:"cch__facts"},H={class:"cch__fact"},J={dir:"ltr"},K={class:"cch__fact"},Q={dir:"ltr"},W={key:0,class:"cch__fact"},X={key:1,class:"cch__empty"},Y={key:2,class:"cch__empty"},Z={key:0,class:"cch__detail"},ss={class:"cch__detailTitle"},es={class:"cch__rows"},ts={class:"cch__row"},os={dir:"ltr"},as={class:"cch__row"},ls={dir:"ltr"},ns={class:"cch__row"},cs={class:"cch__row"},is={class:"cch__row"},rs={dir:"ltr"},_s={class:"cch__row"},ds={dir:"ltr"},us={class:"cch__row"},vs=z({__name:"CustomerChoiceView",setup(hs){const _=r([]),v=r(!1),y=r(!1),h=r(!1),b=r(null),p=r(!1),l=r(null);function g(n){const e=Number(n??0);return Number.isFinite(e)?e.toFixed(3):"0.000"}async function f(){v.value=!0,h.value=!1;try{_.value=await N.getExpertCustomers(b.value)}catch{h.value=!0,_.value=[]}finally{v.value=!1}}async function k(n){b.value=n!=null&&n.trim()?n.trim():null,await f()}async function C(){await f(),y.value=!1}function x(n){l.value=n,p.value=!0}return S(f),(n,e)=>{const V=D("container");return i(),c("div",L,[a(E,{title:"لیست مشتریان","back-to":"userPage::hasSubRoute"},{below:d(()=>[s("div",M,[a($,{onSearch:k,"place-holder":"جستجو"})])]),_:1}),a(R,{spinning:v.value&&!_.value.length,tip:"درحال دریافت اطلاعات"},{default:d(()=>[a(w(q),{modelValue:y.value,"onUpdate:modelValue":e[0]||(e[0]=t=>y.value=t),onRefresh:C},{default:d(()=>[a(V,{class:"cch__body"},{default:d(()=>[_.value.length?(i(),c("div",O,[(i(!0),c(P,null,B(_.value,t=>(i(),c("article",{key:t.id,class:"cch__card",onClick:ps=>x(t)},[s("div",j,[s("h3",A,o(t.name),1),s("span",{class:F(["cch__state",t.active===1?"is-on":"is-off"])},o(t.active===1?"فعال":"غیرفعال"),3)]),s("div",G,[s("div",H,[a(u,{icon:"vuesax-linear:mobile",size:"15"}),s("span",J,o(t.mobile||"—"),1)]),s("div",K,[a(u,{icon:"vuesax-linear:call",size:"15"}),s("span",Q,o(t.phone||"—"),1)]),t.store_name?(i(),c("div",W,[a(u,{icon:"vuesax-linear:shop",size:"15"}),s("span",null,o(t.store_name),1)])):m("",!0)])],8,T))),128))])):!v.value&&!h.value?(i(),c("section",X,[a(u,{icon:"vuesax-linear:profile-2user",size:"26"}),s("p",null,o(b.value?"مشتری با این مشخصات پیدا نشد.":"هنوز مشتری‌ای به شما معرفی نشده است."),1)])):m("",!0),h.value?(i(),c("section",Y,[a(u,{icon:"vuesax-linear:danger",size:"26"}),e[3]||(e[3]=s("p",null,"دریافت اطلاعات با خطا روبه‌رو شد.",-1)),s("button",{type:"button",class:"cch__retry",onClick:f},"تلاش دوباره")])):m("",!0)]),_:1})]),_:1},8,["modelValue"])]),_:1},8,["spinning"]),a(w(U),{open:p.value,"onUpdate:open":e[2]||(e[2]=t=>p.value=t),placement:"bottom",height:"auto",closable:!1,"body-style":{padding:"0"}},{default:d(()=>[l.value?(i(),c("div",Z,[s("h2",ss,o(l.value.name),1),s("dl",es,[s("div",ts,[e[4]||(e[4]=s("dt",null,"موبایل",-1)),s("dd",os,o(l.value.mobile||"—"),1)]),s("div",as,[e[5]||(e[5]=s("dt",null,"تلفن",-1)),s("dd",ls,o(l.value.phone||"—"),1)]),s("div",ns,[e[6]||(e[6]=s("dt",null,"نام مغازه",-1)),s("dd",null,o(l.value.store_name||"—"),1)]),s("div",cs,[e[7]||(e[7]=s("dt",null,"نام پاساژ",-1)),s("dd",null,o(l.value.pasazh_name||"—"),1)]),s("div",is,[e[8]||(e[8]=s("dt",null,"سقف اعتبار",-1)),s("dd",rs,o(g(l.value.gram_level))+" گرم",1)]),s("div",_s,[e[9]||(e[9]=s("dt",null,"بدهی گرمی",-1)),s("dd",ds,o(g(l.value.remain))+" گرم",1)]),s("div",us,[e[10]||(e[10]=s("dt",null,"وضعیت",-1)),s("dd",null,o(l.value.active===1?"فعال":"غیرفعال"),1)])]),s("button",{type:"button",class:"cch__close",onClick:e[1]||(e[1]=t=>p.value=!1)},"بستن")])):m("",!0)]),_:1},8,["open"])])}}}),xs=I(vs,[["__scopeId","data-v-0f43a8be"]]);export{xs as default};
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
.dash[data-v-65fb4be1]{background:#fff;min-height:100vh}.dash__bar[data-v-65fb4be1]{position:fixed;top:0;left:0;right:0;z-index:20;background:#ffffffe0;-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);border-bottom:1px solid #ECEDEF}.dash__barInner[data-v-65fb4be1]{max-width:768px;margin:0 auto;padding:11px 16px;display:flex;align-items:center;justify-content:space-between;gap:12px}.dash__barTitle[data-v-65fb4be1]{margin:0;font-size:14.5px;font-weight:800;color:#14161a}.dash__barBtn[data-v-65fb4be1]{flex:0 0 auto;width:38px;height:38px;border:0;cursor:pointer;border-radius:12px;display:grid;place-items:center;color:#7a1b33;background:#fbf2f4}.dash__barBtn[data-v-65fb4be1]:active{transform:scale(.94)}.dash__barSpacer[data-v-65fb4be1]{display:block;width:38px;height:38px}.dash__body[data-v-65fb4be1]{padding-top:76px;padding-bottom:90px}.dash__balance[data-v-65fb4be1]{padding:16px;border-radius:20px;background:#14161a;color:#fff;box-shadow:0 14px 30px -22px #14161af2}.dash__balanceHead[data-v-65fb4be1]{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.dash__eyebrow[data-v-65fb4be1]{font-size:11.5px;color:#ffffff9e}.dash__figure[data-v-65fb4be1]{padding-top:5px;font-size:25px;font-weight:800;letter-spacing:-.3px}.dash__unit[data-v-65fb4be1]{font-size:11.5px;font-weight:600;color:#ffffff9e;padding-inline-start:4px}.dash__seal[data-v-65fb4be1]{flex:0 0 auto;padding:5px 12px;border-radius:999px;font-size:10.5px;font-weight:700}.dash__seal.is-debtor[data-v-65fb4be1]{color:#fff;background:#a33c55}.dash__seal.is-creditor[data-v-65fb4be1]{color:#14161a;background:#ffffffe6}.dash__balanceRow[data-v-65fb4be1]{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:16px;padding-top:13px;border-top:1px solid rgba(255,255,255,.13)}.dash__rowLabel[data-v-65fb4be1]{font-size:11.5px;color:#ffffff9e}.dash__rowValue[data-v-65fb4be1]{font-size:13.5px;font-weight:700}.dash__rowValue i[data-v-65fb4be1]{font-style:normal;font-size:10.5px;font-weight:600;color:#ffffff9e;padding-inline-start:3px}.dash__identity[data-v-65fb4be1]{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:13px;padding-top:13px;border-top:1px solid rgba(255,255,255,.13)}.dash__name[data-v-65fb4be1]{font-size:12.5px;font-weight:700}.dash__mobile[data-v-65fb4be1]{font-size:11.5px;color:#ffffff9e;direction:ltr}.dash__invite[data-v-65fb4be1]{display:flex;align-items:center;gap:12px;padding:16px;border:1px solid #ECEDEF;border-radius:20px;background:#fafafa}.dash__inviteIcon[data-v-65fb4be1]{flex:0 0 42px;width:42px;height:42px;border-radius:50%;display:grid;place-items:center;color:#7a1b33;background:#fbf2f4}.dash__inviteCopy[data-v-65fb4be1]{flex:1;min-width:0}.dash__inviteCopy h3[data-v-65fb4be1]{margin:0;font-size:13px;font-weight:800;color:#14161a}.dash__inviteCopy p[data-v-65fb4be1]{margin:4px 0 0;font-size:11.5px;color:#8a909c}.dash__inviteCta[data-v-65fb4be1]{flex:0 0 auto;padding:9px 14px;border:0;cursor:pointer;border-radius:999px;font-family:inherit;font-size:11.5px;font-weight:700;color:#fff;background:#14161a}.dash__section[data-v-65fb4be1]{margin-top:26px}.dash__grid[data-v-65fb4be1]{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:9px}.dash__tile[data-v-65fb4be1]{display:flex;flex-direction:column;align-items:center;gap:8px;padding:14px 6px;border:1px solid #ECEDEF;border-radius:16px;cursor:pointer;background:#fff;font-family:inherit;transition:transform .18s ease}.dash__tile[data-v-65fb4be1]:active{transform:scale(.97)}.dash__tile.is-disabled[data-v-65fb4be1]{opacity:.4}.dash__tileIcon[data-v-65fb4be1]{width:38px;height:38px;border-radius:12px;display:grid;place-items:center;color:#22262e;background:#f4f5f6}.dash__tileTitle[data-v-65fb4be1]{font-size:11px;font-weight:700;color:#22262e}
-1
View File
@@ -1 +0,0 @@
.dash[data-v-25cce518]{background:#fff;min-height:100vh}.dash__bar[data-v-25cce518]{position:fixed;top:0;left:0;right:0;z-index:20;background:#ffffffe0;-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);border-bottom:1px solid #ECEDEF}.dash__barInner[data-v-25cce518]{max-width:768px;margin:0 auto;padding:11px 16px;display:flex;align-items:center;justify-content:space-between;gap:12px}.dash__barTitle[data-v-25cce518]{margin:0;font-size:14.5px;font-weight:800;color:#14161a}.dash__barBtn[data-v-25cce518]{flex:0 0 auto;width:38px;height:38px;border:0;cursor:pointer;border-radius:12px;display:grid;place-items:center;color:#7a1b33;background:#fbf2f4}.dash__barBtn[data-v-25cce518]:active{transform:scale(.94)}.dash__barSpacer[data-v-25cce518]{display:block;width:38px;height:38px}.dash__body[data-v-25cce518]{padding-top:76px;padding-bottom:90px}.dash__balance[data-v-25cce518]{padding:16px;border-radius:20px;background:#14161a;color:#fff;box-shadow:0 14px 30px -22px #14161af2}.dash__balanceHead[data-v-25cce518]{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.dash__eyebrow[data-v-25cce518]{font-size:11.5px;color:#ffffff9e}.dash__figure[data-v-25cce518]{padding-top:5px;font-size:25px;font-weight:800;letter-spacing:-.3px}.dash__unit[data-v-25cce518]{font-size:11.5px;font-weight:600;color:#ffffff9e;padding-inline-start:4px}.dash__seal[data-v-25cce518]{flex:0 0 auto;padding:5px 12px;border-radius:999px;font-size:10.5px;font-weight:700}.dash__seal.is-debtor[data-v-25cce518]{color:#fff;background:#a33c55}.dash__seal.is-creditor[data-v-25cce518]{color:#14161a;background:#ffffffe6}.dash__balanceRow[data-v-25cce518]{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:16px;padding-top:13px;border-top:1px solid rgba(255,255,255,.13)}.dash__rowLabel[data-v-25cce518]{font-size:11.5px;color:#ffffff9e}.dash__rowValue[data-v-25cce518]{font-size:13.5px;font-weight:700}.dash__rowValue i[data-v-25cce518]{font-style:normal;font-size:10.5px;font-weight:600;color:#ffffff9e;padding-inline-start:3px}.dash__identity[data-v-25cce518]{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:13px;padding-top:13px;border-top:1px solid rgba(255,255,255,.13)}.dash__name[data-v-25cce518]{font-size:12.5px;font-weight:700}.dash__mobile[data-v-25cce518]{font-size:11.5px;color:#ffffff9e;direction:ltr}.dash__invite[data-v-25cce518]{display:flex;align-items:center;gap:12px;padding:16px;border:1px solid #ECEDEF;border-radius:20px;background:#fafafa}.dash__inviteIcon[data-v-25cce518]{flex:0 0 42px;width:42px;height:42px;border-radius:50%;display:grid;place-items:center;color:#7a1b33;background:#fbf2f4}.dash__inviteCopy[data-v-25cce518]{flex:1;min-width:0}.dash__inviteCopy h3[data-v-25cce518]{margin:0;font-size:13px;font-weight:800;color:#14161a}.dash__inviteCopy p[data-v-25cce518]{margin:4px 0 0;font-size:11.5px;color:#8a909c}.dash__inviteCta[data-v-25cce518]{flex:0 0 auto;padding:9px 14px;border:0;cursor:pointer;border-radius:999px;font-family:inherit;font-size:11.5px;font-weight:700;color:#fff;background:#14161a}.dash__section[data-v-25cce518]{margin-top:26px}.dash__grid[data-v-25cce518]{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:9px}.dash__tile[data-v-25cce518]{display:flex;flex-direction:column;align-items:center;gap:8px;padding:14px 6px;border:1px solid #ECEDEF;border-radius:16px;cursor:pointer;background:#fff;font-family:inherit;transition:transform .18s ease}.dash__tile[data-v-25cce518]:active{transform:scale(.97)}.dash__tile.is-disabled[data-v-25cce518]{opacity:.4}.dash__tileIcon[data-v-25cce518]{width:38px;height:38px;border-radius:12px;display:grid;place-items:center;color:#22262e;background:#f4f5f6}.dash__tileTitle[data-v-25cce518]{font-size:11px;font-weight:700;color:#22262e}
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{d as l,x as n,s as r,u as d,ap as c,i as x,b as t,B as o,E as a,t as i}from"./index-0lMAZRQB.js";const f={class:"my-4"},u={class:"w-full flex justify-center"},m={class:"w-full flex justify-center text-[18px] font-semibold"},_={class:"grid grid-cols-2 border-t border-solid border-[#E5E7EB] pt-4 mx-2 mt-6 font-semibold text-[15px]"},g=l({__name:"DialogVant",props:{timeOut:{},text1:{},text2:{},text3:{}},setup(e){return(s,p)=>(x(),n(d(c),null,{default:r(()=>[t("div",f,[t("div",u,[o(s.$slots,"img",{},()=>[a(i(e.text2),1)])]),t("div",m,[o(s.$slots,"title",{},()=>[a(i(e.text1),1)])]),t("div",_,[o(s.$slots,"button",{},()=>[a(i(e.text3),1)])])])]),_:3}))}});export{g as _};
import{d as l,x as n,s as r,u as d,ap as c,i as x,b as t,B as o,E as a,t as i}from"./index-BrtROTwT.js";const f={class:"my-4"},u={class:"w-full flex justify-center"},m={class:"w-full flex justify-center text-[18px] font-semibold"},_={class:"grid grid-cols-2 border-t border-solid border-[#E5E7EB] pt-4 mx-2 mt-6 font-semibold text-[15px]"},g=l({__name:"DialogVant",props:{timeOut:{},text1:{},text2:{},text3:{}},setup(e){return(s,p)=>(x(),n(d(c),null,{default:r(()=>[t("div",f,[t("div",u,[o(s.$slots,"img",{},()=>[a(i(e.text2),1)])]),t("div",m,[o(s.$slots,"title",{},()=>[a(i(e.text1),1)])]),t("div",_,[o(s.$slots,"button",{},()=>[a(i(e.text3),1)])])])]),_:3}))}});export{g as _};
@@ -1 +1 @@
import{d as f,o as y,q as b,c as o,k as e,s as c,g as m,i as t,F as p,b as i,r as g,I as k,u as h,f as P,y as C,h as x,v as F,x as B,_ as V}from"./index-0lMAZRQB.js";import{P as w}from"./PageBar-DP6LpIFv.js";import{a as S}from"./Spinner.vue_vue_type_style_index_0_lang-Q7UPdMbi.js";import{S as I}from"./SectionHead-BuisDFZg.js";import{P as N}from"./ProductCard-Cbfp9CSN.js";import{u as $}from"./SingleProduct-BCX5wlE-.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./cartStore-qaurfaGv.js";import"./index-BlJivYzz.js";import"./classCallCheck-Tw9-kd3s.js";import"./NotifyVant.vue_vue_type_script_setup_true_lang-BKaF0fT-.js";import"./index-W8LzFWDq.js";import"./DialogVant.vue_vue_type_style_index_0_lang-DiDmrjDM.js";import"./dialogEmpty1-Caw7F5KL.js";const R={class:"favs"},q={class:"favs__grid"},z={key:1,class:"favs__empty"},E=f({__name:"FavoritesView",setup(H){const d=C(),v=$(),a=m(!1),l=m([]),r=x(()=>l.value.filter(u=>v.isFavorite(u.id)));return y(async()=>{a.value=!0;try{l.value=await b.listProducts()}finally{a.value=!1}}),(u,s)=>{const _=F("container");return t(),o("div",R,[e(w,{title:"علاقه‌مندی","back-to":"userPage::hasSubRoute"}),e(S,{spinning:a.value,tip:"در حال دریافت اطلاعات"},{default:c(()=>[e(_,{class:"favs__body"},{default:c(()=>[r.value.length?(t(),o(p,{key:0},[e(I,{title:"ذخیره‌شده‌ها",subtitle:`${r.value.length} محصول`},null,8,["subtitle"]),i("div",q,[(t(!0),o(p,null,g(r.value,n=>(t(),B(N,{key:n.id,value:n},null,8,["value"]))),128))])],64)):a.value?P("",!0):(t(),o("section",z,[e(k,{icon:"vuesax-linear:heart",size:"26"}),s[1]||(s[1]=i("p",null,"هنوز محصولی را به علاقه‌مندی‌ها اضافه نکرده‌اید.",-1)),i("button",{type:"button",class:"favs__emptyCta",onClick:s[0]||(s[0]=n=>h(d).push({name:"home"}))}," دیدن محصولات ")]))]),_:1})]),_:1},8,["spinning"])])}}}),Y=V(E,[["__scopeId","data-v-93bb7c6a"]]);export{Y as default};
import{d as f,o as y,q as b,c as o,k as e,s as c,g as m,i as t,F as p,b as i,r as g,I as k,u as h,f as P,y as C,h as x,v as F,x as B,_ as V}from"./index-BrtROTwT.js";import{P as w}from"./PageBar-Dh4JEEwN.js";import{a as S}from"./Spinner.vue_vue_type_style_index_0_lang-DTTCd0cJ.js";import{S as I}from"./SectionHead-CiVUI4hB.js";import{P as N}from"./ProductCard-DDelyzoS.js";import{u as $}from"./SingleProduct-BtjwWkoB.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./cartStore-NY9cOv5n.js";import"./index-DixO0OJ3.js";import"./classCallCheck-DE78qYAT.js";import"./NotifyVant.vue_vue_type_script_setup_true_lang-cAF7h1vK.js";import"./index-DypKz_AO.js";import"./DialogVant.vue_vue_type_style_index_0_lang-Cbw1QjpS.js";import"./dialogEmpty1-Caw7F5KL.js";const R={class:"favs"},q={class:"favs__grid"},z={key:1,class:"favs__empty"},E=f({__name:"FavoritesView",setup(H){const d=C(),v=$(),a=m(!1),l=m([]),r=x(()=>l.value.filter(u=>v.isFavorite(u.id)));return y(async()=>{a.value=!0;try{l.value=await b.listProducts()}finally{a.value=!1}}),(u,s)=>{const _=F("container");return t(),o("div",R,[e(w,{title:"علاقه‌مندی","back-to":"userPage::hasSubRoute"}),e(S,{spinning:a.value,tip:"در حال دریافت اطلاعات"},{default:c(()=>[e(_,{class:"favs__body"},{default:c(()=>[r.value.length?(t(),o(p,{key:0},[e(I,{title:"ذخیره‌شده‌ها",subtitle:`${r.value.length} محصول`},null,8,["subtitle"]),i("div",q,[(t(!0),o(p,null,g(r.value,n=>(t(),B(N,{key:n.id,value:n},null,8,["value"]))),128))])],64)):a.value?P("",!0):(t(),o("section",z,[e(k,{icon:"vuesax-linear:heart",size:"26"}),s[1]||(s[1]=i("p",null,"هنوز محصولی را به علاقه‌مندی‌ها اضافه نکرده‌اید.",-1)),i("button",{type:"button",class:"favs__emptyCta",onClick:s[0]||(s[0]=n=>h(d).push({name:"home"}))}," دیدن محصولات ")]))]),_:1})]),_:1},8,["spinning"])])}}}),Y=V(E,[["__scopeId","data-v-93bb7c6a"]]);export{Y as default};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{P as x}from"./PageBar-DP6LpIFv.js";import{E as P,a as _}from"./Spinner.vue_vue_type_style_index_0_lang-Q7UPdMbi.js";import{S}from"./SectionHead-BuisDFZg.js";import{P as k}from"./ProductCard-Cbfp9CSN.js";import{d,i as n,c,k as o,u as l,z as B,A as C,n as E,B as b,x as v,f as y,g as u,q as L,C as $,D as A,s as p,F,r as I,h as N,v as V,_ as D}from"./index-0lMAZRQB.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./SingleProduct-BCX5wlE-.js";import"./NotifyVant.vue_vue_type_script_setup_true_lang-BKaF0fT-.js";import"./index-W8LzFWDq.js";import"./DialogVant.vue_vue_type_style_index_0_lang-DiDmrjDM.js";import"./cartStore-qaurfaGv.js";import"./dialogEmpty1-Caw7F5KL.js";import"./index-BlJivYzz.js";import"./classCallCheck-Tw9-kd3s.js";const q={class:"flex justify-center items-center empty"},z=d({__name:"EmptyState",props:{description:{},image:{}},setup(t){return(e,a)=>(n(),c("div",q,[o(l(P),{description:"موردی یافت نشد",image:t.image,class:"h-[200px] w-[200px] opacity-70"},null,8,["image"])]))}}),H="/assets/favoritEmpty-CIK7qR49.svg",T=d({__name:"ScrollFetchSearch",props:{loading:{type:Boolean},flag:{type:Boolean},padding:{}},emits:["fetch"],setup(t,{emit:e}){const a=e,r=B(),s=u(null);return C(s,()=>{a("fetch")},{distance:50}),(i,m)=>(n(),c("main",{class:"flex flex-col flex-1 overflow-auto no-scrollbar w-[100vw] max-w-screen-md m-auto",style:E({paddingTop:t.padding||l(r).headerHeight+"px"}),ref_key:"scrollArea",ref:s},[b(i.$slots,"default"),o(_,{cls:"my-[10px]",spinning:t.loading,indicator:!0,tip:"درحال دریافت اطلاعات"},null,8,["spinning"]),t.flag?(n(),v(z,{key:0,image:l(H)},null,8,["image"])):y("",!0)],4))}});function j(){const t=$({totalPages:0,productList:[],flag:!1});return{productsData:t,getProducts:async(a,r=!1)=>{if(!r){a.value=!0;try{t.productList=await L.listProducts(),t.flag=t.productList.length<1}catch(s){console.log(s)}finally{a.value=!1}}}}}const G={class:"newest"},K={key:0,class:"newest__grid"},g=20,M=d({__name:"NewestView",setup(t){const{productsData:e,getProducts:a}=j(),r=u(!1),s=u(!1),i=u(g),m=N(()=>e.productList.slice(0,i.value));A(async()=>{await a(r,!1)});const h=async()=>{if(i.value<e.productList.length){i.value+=g;return}await a(s,!0)};return(R,Z)=>{const w=V("container");return n(),c("div",G,[o(x,{title:"جدیدترین محصولات","back-to":"home"}),o(_,{spinning:r.value,tip:"درحال دریافت اطلاعات"},{default:p(()=>[o(T,{class:"newest__scroll",loading:s.value,flag:l(e).flag,padding:"0px",onFetch:h},{default:p(()=>[o(w,{class:"newest__body"},{default:p(()=>[o(S,{title:"تازه‌ها",subtitle:"آخرین افزوده‌های مجموعه"}),l(e).productList.length?(n(),c("div",K,[(n(!0),c(F,null,I(m.value,f=>(n(),v(k,{key:f.id,value:f},null,8,["value"]))),128))])):y("",!0)]),_:1})]),_:1},8,["loading","flag"])]),_:1},8,["spinning"])])}}}),it=D(M,[["__scopeId","data-v-62cb523e"]]);export{it as default};
import{P as x}from"./PageBar-Dh4JEEwN.js";import{E as P,a as _}from"./Spinner.vue_vue_type_style_index_0_lang-DTTCd0cJ.js";import{S}from"./SectionHead-CiVUI4hB.js";import{P as k}from"./ProductCard-DDelyzoS.js";import{d,i as n,c,k as o,u as l,z as B,A as C,n as E,B as b,x as v,f as y,g as u,q as L,C as $,D as A,s as p,F,r as I,h as N,v as V,_ as D}from"./index-BrtROTwT.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./SingleProduct-BtjwWkoB.js";import"./NotifyVant.vue_vue_type_script_setup_true_lang-cAF7h1vK.js";import"./index-DypKz_AO.js";import"./DialogVant.vue_vue_type_style_index_0_lang-Cbw1QjpS.js";import"./cartStore-NY9cOv5n.js";import"./dialogEmpty1-Caw7F5KL.js";import"./index-DixO0OJ3.js";import"./classCallCheck-DE78qYAT.js";const q={class:"flex justify-center items-center empty"},z=d({__name:"EmptyState",props:{description:{},image:{}},setup(t){return(e,a)=>(n(),c("div",q,[o(l(P),{description:"موردی یافت نشد",image:t.image,class:"h-[200px] w-[200px] opacity-70"},null,8,["image"])]))}}),H="/assets/favoritEmpty-CIK7qR49.svg",T=d({__name:"ScrollFetchSearch",props:{loading:{type:Boolean},flag:{type:Boolean},padding:{}},emits:["fetch"],setup(t,{emit:e}){const a=e,r=B(),s=u(null);return C(s,()=>{a("fetch")},{distance:50}),(i,m)=>(n(),c("main",{class:"flex flex-col flex-1 overflow-auto no-scrollbar w-[100vw] max-w-screen-md m-auto",style:E({paddingTop:t.padding||l(r).headerHeight+"px"}),ref_key:"scrollArea",ref:s},[b(i.$slots,"default"),o(_,{cls:"my-[10px]",spinning:t.loading,indicator:!0,tip:"درحال دریافت اطلاعات"},null,8,["spinning"]),t.flag?(n(),v(z,{key:0,image:l(H)},null,8,["image"])):y("",!0)],4))}});function j(){const t=$({totalPages:0,productList:[],flag:!1});return{productsData:t,getProducts:async(a,r=!1)=>{if(!r){a.value=!0;try{t.productList=await L.listProducts(),t.flag=t.productList.length<1}catch(s){console.log(s)}finally{a.value=!1}}}}}const G={class:"newest"},K={key:0,class:"newest__grid"},g=20,M=d({__name:"NewestView",setup(t){const{productsData:e,getProducts:a}=j(),r=u(!1),s=u(!1),i=u(g),m=N(()=>e.productList.slice(0,i.value));A(async()=>{await a(r,!1)});const h=async()=>{if(i.value<e.productList.length){i.value+=g;return}await a(s,!0)};return(R,Z)=>{const w=V("container");return n(),c("div",G,[o(x,{title:"جدیدترین محصولات","back-to":"home"}),o(_,{spinning:r.value,tip:"درحال دریافت اطلاعات"},{default:p(()=>[o(T,{class:"newest__scroll",loading:s.value,flag:l(e).flag,padding:"0px",onFetch:h},{default:p(()=>[o(w,{class:"newest__body"},{default:p(()=>[o(S,{title:"تازه‌ها",subtitle:"آخرین افزوده‌های مجموعه"}),l(e).productList.length?(n(),c("div",K,[(n(!0),c(F,null,I(m.value,f=>(n(),v(k,{key:f.id,value:f},null,8,["value"]))),128))])):y("",!0)]),_:1})]),_:1},8,["loading","flag"])]),_:1},8,["spinning"])])}}}),it=D(M,[["__scopeId","data-v-62cb523e"]]);export{it as default};
@@ -1 +1 @@
import{d as a,c as n,k as o,s as i,v as c,i as _,b as e,I as r,_ as p}from"./index-0lMAZRQB.js";import{P as d}from"./PageBar-DP6LpIFv.js";const f={class:"notif"},l={class:"notif__empty"},m=a({__name:"NotificationsView",setup(u){return(v,t)=>{const s=c("container");return _(),n("div",f,[o(d,{title:"اعلان‌ها","back-to":"home"}),o(s,{class:"notif__body"},{default:i(()=>[e("section",l,[o(r,{icon:"vuesax-linear:notification",size:"26"}),t[0]||(t[0]=e("p",null,"اعلانی برای نمایش وجود ندارد.",-1))])]),_:1})])}}}),B=p(m,[["__scopeId","data-v-44d0c9a5"]]);export{B as default};
import{d as a,c as n,k as o,s as i,v as c,i as _,b as e,I as r,_ as p}from"./index-BrtROTwT.js";import{P as d}from"./PageBar-Dh4JEEwN.js";const f={class:"notif"},l={class:"notif__empty"},m=a({__name:"NotificationsView",setup(u){return(v,t)=>{const s=c("container");return _(),n("div",f,[o(d,{title:"اعلان‌ها","back-to":"home"}),o(s,{class:"notif__body"},{default:i(()=>[e("section",l,[o(r,{icon:"vuesax-linear:notification",size:"26"}),t[0]||(t[0]=e("p",null,"اعلانی برای نمایش وجود ندارد.",-1))])]),_:1})])}}}),B=p(m,[["__scopeId","data-v-44d0c9a5"]]);export{B as default};
@@ -1 +1 @@
import{d as m,H as r,i as f,c as h,k as l,u as w,n as x,s as p,b as o,I as y,B as V,E as N,t as v,f as B,g as _}from"./index-0lMAZRQB.js";import{N as k}from"./index-W8LzFWDq.js";const C={key:0,class:"flex"},O={class:"w-full text-white my-2"},S={class:"w-full flex content-end"},E=m({__name:"NotifyVant",props:{modelValue:{type:Boolean},timeOut:{},text:{},color:{}},emits:["update:modelValue"],setup(e,{emit:i}){const s=_(!0),t=e,n=i;r(()=>t.modelValue,()=>{t.timeOut!==-1&&c()});const c=()=>{setTimeout(()=>{n("update:modelValue",!1)},t.timeOut)};return(u,a)=>e.modelValue?(f(),h("div",C,[l(w(k),{show:s.value,"onUpdate:show":a[0]||(a[0]=d=>s.value=d),style:x(e.color)},{default:p(()=>[o("div",O,[o("div",S,[l(y,{icon:"vuesax-linear:info-circle",class:"ml-[20px] text-white",size:"25"}),o("div",null,[V(u.$slots,"default",{},()=>[N(v(e.text),1)])])])])]),_:3},8,["show","style"])])):B("",!0)}});export{E as _};
import{d as m,H as r,i as f,c as h,k as l,u as w,n as x,s as p,b as o,I as y,B as V,E as N,t as v,f as B,g as _}from"./index-BrtROTwT.js";import{N as k}from"./index-DypKz_AO.js";const C={key:0,class:"flex"},O={class:"w-full text-white my-2"},S={class:"w-full flex content-end"},E=m({__name:"NotifyVant",props:{modelValue:{type:Boolean},timeOut:{},text:{},color:{}},emits:["update:modelValue"],setup(e,{emit:i}){const s=_(!0),t=e,n=i;r(()=>t.modelValue,()=>{t.timeOut!==-1&&c()});const c=()=>{setTimeout(()=>{n("update:modelValue",!1)},t.timeOut)};return(u,a)=>e.modelValue?(f(),h("div",C,[l(w(k),{show:s.value,"onUpdate:show":a[0]||(a[0]=d=>s.value=d),style:x(e.color)},{default:p(()=>[o("div",O,[o("div",S,[l(y,{icon:"vuesax-linear:info-circle",class:"ml-[20px] text-white",size:"25"}),o("div",null,[V(u.$slots,"default",{},()=>[N(v(e.text),1)])])])])]),_:3},8,["show","style"])])):B("",!0)}});export{E as _};
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{d as _,c as s,b as a,k as d,I as b,t as u,B as i,i as t,y as p,_ as k}from"./index-0lMAZRQB.js";const h={class:"bar"},f={class:"bar__inner"},B={key:1,class:"bar__spacer","aria-hidden":"true"},m={class:"bar__title"},g={class:"bar__trailing"},y=_({__name:"PageBar",props:{title:{},back:{type:Boolean,default:!0},backTo:{}},setup(e){const o=e,r=p();function l(){o.backTo?r.push({name:o.backTo}):r.back()}return(n,c)=>(t(),s("header",h,[a("div",f,[e.back?(t(),s("button",{key:0,type:"button",class:"bar__btn","aria-label":"بازگشت",onClick:l},[d(b,{icon:"vuesax-linear:arrow-right-1",size:"20"})])):(t(),s("span",B)),a("h1",m,u(e.title),1),a("div",g,[i(n.$slots,"trailing",{},()=>[c[0]||(c[0]=a("span",{class:"bar__spacer","aria-hidden":"true"},null,-1))],!0)])]),i(n.$slots,"below",{},void 0,!0)]))}}),I=k(y,[["__scopeId","data-v-d2d3dfeb"]]);export{I as P};
import{d as _,c as s,b as a,k as d,I as b,t as u,B as i,i as t,y as p,_ as k}from"./index-BrtROTwT.js";const h={class:"bar"},f={class:"bar__inner"},B={key:1,class:"bar__spacer","aria-hidden":"true"},m={class:"bar__title"},g={class:"bar__trailing"},y=_({__name:"PageBar",props:{title:{},back:{type:Boolean,default:!0},backTo:{}},setup(e){const o=e,r=p();function l(){o.backTo?r.push({name:o.backTo}):r.back()}return(n,c)=>(t(),s("header",h,[a("div",f,[e.back?(t(),s("button",{key:0,type:"button",class:"bar__btn","aria-label":"بازگشت",onClick:l},[d(b,{icon:"vuesax-linear:arrow-right-1",size:"20"})])):(t(),s("span",B)),a("h1",m,u(e.title),1),a("div",g,[i(n.$slots,"trailing",{},()=>[c[0]||(c[0]=a("span",{class:"bar__spacer","aria-hidden":"true"},null,-1))],!0)])]),i(n.$slots,"below",{},void 0,!0)]))}}),I=k(y,[["__scopeId","data-v-d2d3dfeb"]]);export{I as P};
@@ -1 +1 @@
import{d as D,l as P,i as s,c as i,F as S,b as t,u as e,w as z,k as _,I as f,j as B,e as I,f as d,t as u,s as N,x as V,g as E,h as $,_ as j}from"./index-0lMAZRQB.js";import{u as q,S as L}from"./SingleProduct-BCX5wlE-.js";import{u as M}from"./cartStore-qaurfaGv.js";import{D as O}from"./index-BlJivYzz.js";const U={class:"pc__art"},A=["alt"],G={key:1,class:"pc__artEmpty","aria-hidden":"true"},H=["aria-label"],J={key:2,class:"pc__flag"},K={key:3,class:"pc__flag pc__flag--soft"},Q={class:"pc__body"},R={class:"pc__title"},T={class:"pc__meta"},W={class:"pc__weight"},X={key:0,class:"pc__wage"},Y=D({__name:"ProductCard",props:{value:{}},setup(g){const h=g,n=q(),{image:p,id:a,title:v,min_gram:y,wage:m,is_exist:b,qty:k,isPreOrder:w}=M(h.value),l=E(!1);function x(){l.value=!0}const C=$(()=>{const r=m.value;return r==null?"":r%1===0?String(r):r.toFixed(2)});return(r,o)=>{const F=P("lazy");return s(),i(S,null,[t("article",{class:"pc",onClick:x},[t("div",U,[e(p)?z((s(),i("img",{key:0,alt:e(v)},null,8,A)),[[F,e(p)]]):(s(),i("div",G,[_(f,{icon:"vuesax-linear:diamonds",size:"26"})])),t("button",{type:"button",class:I(["pc__fav",{"is-on":e(n).isFavorite(e(a))}]),"aria-label":e(n).isFavorite(e(a))?"حذف از علاقه‌مندی":"افزودن به علاقه‌مندی",onClick:o[0]||(o[0]=B(c=>e(n).toggle(e(a)),["stop"]))},[_(f,{icon:e(n).isFavorite(e(a))?"vuesax-linear:heart-fill":"vuesax-linear:heart",size:"16"},null,8,["icon"])],10,H),e(b)?e(w)&&e(k)===0?(s(),i("span",K,"پیش‌سفارش")):d("",!0):(s(),i("span",J,"ناموجود"))]),t("div",Q,[t("h3",R,u(e(v)),1),t("div",T,[t("span",W,u(e(y))+" گرم",1),e(m)!=null?(s(),i("span",X,"اجرت "+u(C.value)+"٪",1)):d("",!0)])])]),_(e(O),{visible:l.value,"onUpdate:visible":o[2]||(o[2]=c=>l.value=c),placement:"bottom",closable:!1,class:"rtl",height:"100vh",bodyStyle:{padding:0,position:"relative"}},{default:N(()=>[l.value?(s(),V(L,{id:e(a),key:e(a),onCloseDrawer:o[1]||(o[1]=c=>l.value=!1)},null,8,["id"])):d("",!0)]),_:1},8,["visible"])],64)}}}),ae=j(Y,[["__scopeId","data-v-5658bc04"]]);export{ae as P};
import{d as D,l as P,i as s,c as i,F as S,b as t,u as e,w as z,k as _,I as f,j as B,e as I,f as d,t as u,s as N,x as V,g as E,h as $,_ as j}from"./index-BrtROTwT.js";import{u as q,S as L}from"./SingleProduct-BtjwWkoB.js";import{u as M}from"./cartStore-NY9cOv5n.js";import{D as O}from"./index-DixO0OJ3.js";const U={class:"pc__art"},A=["alt"],G={key:1,class:"pc__artEmpty","aria-hidden":"true"},H=["aria-label"],J={key:2,class:"pc__flag"},K={key:3,class:"pc__flag pc__flag--soft"},Q={class:"pc__body"},R={class:"pc__title"},T={class:"pc__meta"},W={class:"pc__weight"},X={key:0,class:"pc__wage"},Y=D({__name:"ProductCard",props:{value:{}},setup(g){const h=g,n=q(),{image:p,id:a,title:v,min_gram:y,wage:m,is_exist:b,qty:k,isPreOrder:w}=M(h.value),l=E(!1);function x(){l.value=!0}const C=$(()=>{const r=m.value;return r==null?"":r%1===0?String(r):r.toFixed(2)});return(r,o)=>{const F=P("lazy");return s(),i(S,null,[t("article",{class:"pc",onClick:x},[t("div",U,[e(p)?z((s(),i("img",{key:0,alt:e(v)},null,8,A)),[[F,e(p)]]):(s(),i("div",G,[_(f,{icon:"vuesax-linear:diamonds",size:"26"})])),t("button",{type:"button",class:I(["pc__fav",{"is-on":e(n).isFavorite(e(a))}]),"aria-label":e(n).isFavorite(e(a))?"حذف از علاقه‌مندی":"افزودن به علاقه‌مندی",onClick:o[0]||(o[0]=B(c=>e(n).toggle(e(a)),["stop"]))},[_(f,{icon:e(n).isFavorite(e(a))?"vuesax-linear:heart-fill":"vuesax-linear:heart",size:"16"},null,8,["icon"])],10,H),e(b)?e(w)&&e(k)===0?(s(),i("span",K,"پیش‌سفارش")):d("",!0):(s(),i("span",J,"ناموجود"))]),t("div",Q,[t("h3",R,u(e(v)),1),t("div",T,[t("span",W,u(e(y))+" گرم",1),e(m)!=null?(s(),i("span",X,"اجرت "+u(C.value)+"٪",1)):d("",!0)])])]),_(e(O),{visible:l.value,"onUpdate:visible":o[2]||(o[2]=c=>l.value=c),placement:"bottom",closable:!1,class:"rtl",height:"100vh",bodyStyle:{padding:0,position:"relative"}},{default:N(()=>[l.value?(s(),V(L,{id:e(a),key:e(a),onCloseDrawer:o[1]||(o[1]=c=>l.value=!1)},null,8,["id"])):d("",!0)]),_:1},8,["visible"])],64)}}}),ae=j(Y,[["__scopeId","data-v-5658bc04"]]);export{ae as P};
@@ -1 +1 @@
import{d as y,G as b,o as k,q as T,c as l,k as i,s as V,g as d,v as P,i as n,b as e,I as p,t as a,f as r,e as g,u as B,h as f,y as C,_ as D}from"./index-0lMAZRQB.js";import{P as N}from"./PageBar-DP6LpIFv.js";import{S as h}from"./SectionHead-BuisDFZg.js";const R={class:"prof"},x={class:"prof__identity"},F={class:"prof__avatar","aria-hidden":"true"},M={class:"prof__name"},w={key:0,class:"prof__mobile"},O={key:0,class:"prof__block"},U={class:"prof__specs"},z={class:"prof__spec"},L={class:"prof__spec"},A={class:"prof__spec"},W={class:"prof__spec"},q={key:1,class:"prof__empty"},G=y({__name:"ProfileView",setup(H){const _={UNVERIFIED:"احراز نشده",STEP_ONE_SUBMITTED:"مرحله اول ثبت شده",STEP_TWO_SUBMITTED:"مرحله دوم ثبت شده",VERIFIED:"تایید شده"},v=b(),s=d(null),u=d(!1),m=f(()=>{var t;return((t=s.value)==null?void 0:t.verificationStep)==="VERIFIED"}),S=f(()=>{var o;const t=(o=s.value)==null?void 0:o.verificationStep;return!!t&&t!=="VERIFIED"&&t!=="STEP_TWO_SUBMITTED"}),E=C();return k(async()=>{if(v.isLoggedIn){u.value=!0;try{s.value=await T.getMe()}finally{u.value=!1}}}),(t,o)=>{const I=P("container");return n(),l("div",R,[i(N,{title:"اطلاعات کاربری","back-to":"userPage::hasSubRoute"}),i(I,{class:"prof__body"},{default:V(()=>{var c;return[e("section",x,[e("div",F,[i(p,{icon:"vuesax-linear:user",size:"30"})]),e("h2",M,a(((c=s.value)==null?void 0:c.fullName)??"—"),1),s.value?(n(),l("p",w,a(s.value.mobile),1)):r("",!0),s.value?(n(),l("span",{key:1,class:g(["prof__seal",m.value?"is-ok":"is-pending"])},a(_[s.value.verificationStep]??s.value.verificationStep),3)):r("",!0)]),s.value?(n(),l("section",O,[i(h,{title:"مشخصات",subtitle:"اطلاعات ثبت‌شده حساب شما"}),e("dl",U,[e("div",z,[o[1]||(o[1]=e("dt",null,"نام و نام خانوادگی",-1)),e("dd",null,a(s.value.fullName),1)]),e("div",L,[o[2]||(o[2]=e("dt",null,"تلفن همراه",-1)),e("dd",null,a(s.value.mobile),1)]),e("div",A,[o[3]||(o[3]=e("dt",null,"کد ملی",-1)),e("dd",null,a(s.value.nationalCode),1)]),e("div",W,[o[4]||(o[4]=e("dt",null,"وضعیت احراز هویت",-1)),e("dd",null,a(_[s.value.verificationStep]??s.value.verificationStep),1)])])])):u.value?r("",!0):(n(),l("section",q,[i(p,{icon:"vuesax-linear:user",size:"26"}),o[5]||(o[5]=e("p",null,"اطلاعات حساب در دسترس نیست.",-1))])),S.value?(n(),l("button",{key:2,type:"button",class:"prof__complete",onClick:o[0]||(o[0]=$=>B(E).push({name:"completeProfile"}))}," تکمیل پروفایل ")):r("",!0)]}),_:1})])}}}),Q=D(G,[["__scopeId","data-v-bde55e2f"]]);export{Q as default};
import{d as y,G as b,o as k,q as T,c as l,k as i,s as V,g as d,v as P,i as n,b as e,I as p,t as a,f as r,e as g,u as B,h as f,y as C,_ as D}from"./index-BrtROTwT.js";import{P as N}from"./PageBar-Dh4JEEwN.js";import{S as h}from"./SectionHead-CiVUI4hB.js";const R={class:"prof"},x={class:"prof__identity"},F={class:"prof__avatar","aria-hidden":"true"},M={class:"prof__name"},w={key:0,class:"prof__mobile"},O={key:0,class:"prof__block"},U={class:"prof__specs"},z={class:"prof__spec"},L={class:"prof__spec"},A={class:"prof__spec"},W={class:"prof__spec"},q={key:1,class:"prof__empty"},G=y({__name:"ProfileView",setup(H){const _={UNVERIFIED:"احراز نشده",STEP_ONE_SUBMITTED:"مرحله اول ثبت شده",STEP_TWO_SUBMITTED:"مرحله دوم ثبت شده",VERIFIED:"تایید شده"},v=b(),s=d(null),u=d(!1),m=f(()=>{var t;return((t=s.value)==null?void 0:t.verificationStep)==="VERIFIED"}),S=f(()=>{var o;const t=(o=s.value)==null?void 0:o.verificationStep;return!!t&&t!=="VERIFIED"&&t!=="STEP_TWO_SUBMITTED"}),E=C();return k(async()=>{if(v.isLoggedIn){u.value=!0;try{s.value=await T.getMe()}finally{u.value=!1}}}),(t,o)=>{const I=P("container");return n(),l("div",R,[i(N,{title:"اطلاعات کاربری","back-to":"userPage::hasSubRoute"}),i(I,{class:"prof__body"},{default:V(()=>{var c;return[e("section",x,[e("div",F,[i(p,{icon:"vuesax-linear:user",size:"30"})]),e("h2",M,a(((c=s.value)==null?void 0:c.fullName)??"—"),1),s.value?(n(),l("p",w,a(s.value.mobile),1)):r("",!0),s.value?(n(),l("span",{key:1,class:g(["prof__seal",m.value?"is-ok":"is-pending"])},a(_[s.value.verificationStep]??s.value.verificationStep),3)):r("",!0)]),s.value?(n(),l("section",O,[i(h,{title:"مشخصات",subtitle:"اطلاعات ثبت‌شده حساب شما"}),e("dl",U,[e("div",z,[o[1]||(o[1]=e("dt",null,"نام و نام خانوادگی",-1)),e("dd",null,a(s.value.fullName),1)]),e("div",L,[o[2]||(o[2]=e("dt",null,"تلفن همراه",-1)),e("dd",null,a(s.value.mobile),1)]),e("div",A,[o[3]||(o[3]=e("dt",null,"کد ملی",-1)),e("dd",null,a(s.value.nationalCode),1)]),e("div",W,[o[4]||(o[4]=e("dt",null,"وضعیت احراز هویت",-1)),e("dd",null,a(_[s.value.verificationStep]??s.value.verificationStep),1)])])])):u.value?r("",!0):(n(),l("section",q,[i(p,{icon:"vuesax-linear:user",size:"26"}),o[5]||(o[5]=e("p",null,"اطلاعات حساب در دسترس نیست.",-1))])),S.value?(n(),l("button",{key:2,type:"button",class:"prof__complete",onClick:o[0]||(o[0]=$=>B(E).push({name:"completeProfile"}))}," تکمیل پروفایل ")):r("",!0)]}),_:1})])}}}),Q=D(G,[["__scopeId","data-v-bde55e2f"]]);export{Q as default};
@@ -1 +1 @@
import{p as c,j as d}from"./filters-CLL9nGZ2.js";import{d as u,c as s,e as _,b as a,E as l,t as i,u as n,f as m,h as v,i as r,_ as q}from"./index-0lMAZRQB.js";const f={key:0,class:"rate-strip__value"},k={class:"rate-strip__num"},y={key:1,class:"rate-strip__value rate-strip__value--muted"},x={key:2,class:"rate-strip__time"},R=u({__name:"RateStrip",props:{quote:{}},setup(t){const o=t,p=v(()=>o.quote?o.quote.pricePerGramRial.split(".")[0]:"");return(b,e)=>(r(),s("div",{class:_(["rate-strip",{"is-empty":!t.quote}])},[e[1]||(e[1]=a("div",{class:"rate-strip__label"},[a("span",{class:"rate-strip__dot","aria-hidden":"true"}),l(" نرخ طلای ۱۸ عیار ")],-1)),t.quote?(r(),s("div",f,[a("span",k,i(n(c)(p.value)),1),e[0]||(e[0]=a("span",{class:"rate-strip__unit"},"ریال / گرم",-1))])):(r(),s("div",y,"در انتظار اعلام نرخ")),t.quote?(r(),s("div",x,i(n(d)(t.quote.quotedAt)),1)):m("",!0)],2))}}),C=q(R,[["__scopeId","data-v-16b4c8d5"]]);export{C as R};
import{p as c,j as d}from"./filters-CLL9nGZ2.js";import{d as u,c as s,e as _,b as a,E as l,t as i,u as n,f as m,h as v,i as r,_ as q}from"./index-BrtROTwT.js";const f={key:0,class:"rate-strip__value"},k={class:"rate-strip__num"},y={key:1,class:"rate-strip__value rate-strip__value--muted"},x={key:2,class:"rate-strip__time"},R=u({__name:"RateStrip",props:{quote:{}},setup(t){const o=t,p=v(()=>o.quote?o.quote.pricePerGramRial.split(".")[0]:"");return(b,e)=>(r(),s("div",{class:_(["rate-strip",{"is-empty":!t.quote}])},[e[1]||(e[1]=a("div",{class:"rate-strip__label"},[a("span",{class:"rate-strip__dot","aria-hidden":"true"}),l(" نرخ طلای ۱۸ عیار ")],-1)),t.quote?(r(),s("div",f,[a("span",k,i(n(c)(p.value)),1),e[0]||(e[0]=a("span",{class:"rate-strip__unit"},"ریال / گرم",-1))])):(r(),s("div",y,"در انتظار اعلام نرخ")),t.quote?(r(),s("div",x,i(n(d)(t.quote.quotedAt)),1)):m("",!0)],2))}}),C=q(R,[["__scopeId","data-v-16b4c8d5"]]);export{C as R};
+1
View File
@@ -0,0 +1 @@
.doc[data-v-f58a45b8]{padding:16px;background:#fff;border:1px solid #ECEDEF;border-radius:18px}.doc__head[data-v-f58a45b8]{display:flex;justify-content:space-between;gap:10px;margin-bottom:12px;font-size:13px;font-weight:600}.doc__muted[data-v-f58a45b8]{color:#5b616e;font-weight:500;margin-left:4px}.doc__rows[data-v-f58a45b8]{margin:0;display:flex;flex-direction:column;gap:2px}.doc__row[data-v-f58a45b8]{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:10px 12px;background:#fafafa;border-radius:10px}.doc__row dt[data-v-f58a45b8]{font-size:12.5px;color:#5b616e;white-space:nowrap}.doc__row dd[data-v-f58a45b8]{margin:0;font-size:13.5px;font-weight:600;text-align:left}.doc__gold[data-v-f58a45b8]{display:flex;justify-content:space-between;align-items:center;margin-top:8px;padding:10px 12px;background:#f4f5f6;border-radius:10px;font-size:13px;font-weight:700}.doc__stack[data-v-f58a45b8]{display:flex;flex-direction:column;align-items:flex-end;gap:2px}.is-in[data-v-f58a45b8]{color:#16a34a}.is-out[data-v-f58a45b8]{color:#dc2626}.rep__tabs[data-v-857bd503]{display:flex;gap:8px;padding:0 16px 12px}.rep__tab[data-v-857bd503]{flex:1;padding:10px;border:1px solid #ECEDEF;border-radius:999px;background:#fff;font-family:inherit;font-size:13px;font-weight:600;color:#5b616e;cursor:pointer}.rep__tab.is-on[data-v-857bd503]{background:#14161a;border-color:#14161a;color:#fff}.rep__body[data-v-857bd503]{padding-top:132px;padding-bottom:90px}.rep__list[data-v-857bd503]{display:flex;flex-direction:column;padding-top:16px;gap:11px}.rep__card[data-v-857bd503]{padding:16px;background:#fff;border:1px solid #ECEDEF;border-radius:18px}.rep__head[data-v-857bd503]{display:flex;justify-content:space-between;gap:10px;margin-bottom:12px;font-size:13px;font-weight:600}.rep__muted[data-v-857bd503]{color:#5b616e;font-weight:500;margin-left:4px}.rep__pair[data-v-857bd503]{display:flex;justify-content:space-between;align-items:center;padding:9px 12px;margin-bottom:6px;background:#fafafa;border-radius:10px;font-size:13px}.rep__pair.is-balance[data-v-857bd503]{background:#f4f5f6;font-weight:700}.rep__stack[data-v-857bd503]{display:flex;flex-direction:column;align-items:flex-end;gap:2px;font-weight:600}.is-in[data-v-857bd503]{color:#16a34a}.is-out[data-v-857bd503]{color:#dc2626}.rep__more[data-v-857bd503],.rep__sentinel[data-v-857bd503]{padding:12px 0;text-align:center;font-size:12px;color:#5b616e}.rep__more[data-v-857bd503]{width:100%;margin-top:4px;border:none;background:transparent;font-family:inherit;font-weight:700;color:#7a1b33;cursor:pointer}.rep__empty[data-v-857bd503]{margin-top:8px;padding:34px 20px;border:1px dashed #ECEDEF;border-radius:18px;display:flex;flex-direction:column;align-items:center;gap:10px;color:#5b616e;font-size:13px}.rep__retry[data-v-857bd503]{padding:8px 18px;border-radius:999px;border:1px solid #ECEDEF;background:#fff;font-family:inherit;font-size:12px;font-weight:600;cursor:pointer}.rep__modal[data-v-857bd503]{padding:20px 16px 24px}.rep__modalEmpty[data-v-857bd503]{padding:24px 0;text-align:center;font-size:13px;color:#5b616e}.rep__close[data-v-857bd503]{margin-top:18px;width:100%;padding:13px;border:none;border-radius:14px;background:#14161a;color:#fff;font-family:inherit;font-size:14px;font-weight:700;cursor:pointer}
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{d as v,aa as h,H as m,i as t,c as l,k as n,I as r,w as f,ab as b,b as k,ac as x,f as C,C as I,g as w,_ as y}from"./index-0lMAZRQB.js";const S={class:"si"},V=["placeholder"],B=v({__name:"SearchInput",props:{placeHolder:{}},emits:["search"],setup(i,{emit:d}){const c=d,a=I({clear:!1}),e=w(void 0),s=()=>{c("search",e.value)},u=()=>{e.value=void 0,a.clear=!1,c("search",void 0)},p=h(e,700);return m(p,()=>{e?a.clear=!0:a.clear=!1,s()}),(H,o)=>(t(),l("div",S,[n(r,{icon:"vuesax-linear:search-normal-1",class:"si__icon",size:"18",onClick:s}),f(k("input",{"onUpdate:modelValue":o[0]||(o[0]=_=>e.value=_),class:"si__input",placeholder:i.placeHolder,onKeyup:x(s,["enter"])},null,40,V),[[b,e.value]]),a.clear?(t(),l("button",{key:0,type:"button",class:"si__clear","aria-label":"پاک کردن",onClick:u},[n(r,{icon:"vuesax-linear:add",size:"16"})])):C("",!0)]))}}),z=y(B,[["__scopeId","data-v-4c50067a"]]);export{z as S};
import{d as v,aa as h,H as m,i as t,c as l,k as n,I as r,w as f,ab as b,b as k,ac as x,f as C,C as I,g as w,_ as y}from"./index-BrtROTwT.js";const S={class:"si"},V=["placeholder"],B=v({__name:"SearchInput",props:{placeHolder:{}},emits:["search"],setup(i,{emit:d}){const c=d,a=I({clear:!1}),e=w(void 0),s=()=>{c("search",e.value)},u=()=>{e.value=void 0,a.clear=!1,c("search",void 0)},p=h(e,700);return m(p,()=>{e?a.clear=!0:a.clear=!1,s()}),(H,o)=>(t(),l("div",S,[n(r,{icon:"vuesax-linear:search-normal-1",class:"si__icon",size:"18",onClick:s}),f(k("input",{"onUpdate:modelValue":o[0]||(o[0]=_=>e.value=_),class:"si__input",placeholder:i.placeHolder,onKeyup:x(s,["enter"])},null,40,V),[[b,e.value]]),a.clear?(t(),l("button",{key:0,type:"button",class:"si__clear","aria-label":"پاک کردن",onClick:u},[n(r,{icon:"vuesax-linear:add",size:"16"})])):C("",!0)]))}}),z=y(B,[["__scopeId","data-v-4c50067a"]]);export{z as S};
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{d as r,c as t,b as o,t as s,f as n,E as _,k as d,I as u,i as a,_ as b}from"./index-0lMAZRQB.js";const m={class:"sec"},f={class:"sec__text"},k={class:"sec__title"},x={key:0,class:"sec__sub"},h=r({__name:"SectionHead",props:{title:{},subtitle:{},actionLabel:{}},emits:["action"],setup(e,{emit:i}){const l=i;return(p,c)=>(a(),t("header",m,[o("div",f,[o("h2",k,s(e.title),1),e.subtitle?(a(),t("p",x,s(e.subtitle),1)):n("",!0)]),e.actionLabel?(a(),t("button",{key:0,type:"button",class:"sec__action",onClick:c[0]||(c[0]=v=>l("action"))},[_(s(e.actionLabel)+" ",1),d(u,{icon:"vuesax-linear:arrow-left-2",size:"15"})])):n("",!0)]))}}),N=b(h,[["__scopeId","data-v-e5c65b7c"]]);export{N as S};
import{d as r,c as t,b as o,t as s,f as n,E as _,k as d,I as u,i as a,_ as b}from"./index-BrtROTwT.js";const m={class:"sec"},f={class:"sec__text"},k={class:"sec__title"},x={key:0,class:"sec__sub"},h=r({__name:"SectionHead",props:{title:{},subtitle:{},actionLabel:{}},emits:["action"],setup(e,{emit:i}){const l=i;return(p,c)=>(a(),t("header",m,[o("div",f,[o("h2",k,s(e.title),1),e.subtitle?(a(),t("p",x,s(e.subtitle),1)):n("",!0)]),e.actionLabel?(a(),t("button",{key:0,type:"button",class:"sec__action",onClick:c[0]||(c[0]=v=>l("action"))},[_(s(e.actionLabel)+" ",1),d(u,{icon:"vuesax-linear:arrow-left-2",size:"15"})])):n("",!0)]))}}),N=b(h,[["__scopeId","data-v-e5c65b7c"]]);export{N as S};
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{d as b,G as A,o as C,q as D,c as i,k as r,s as f,x as w,u as E,f as m,g as u,i as l,F as y,b as s,r as L,I as g,t as o,e as p,v as N,_ as M}from"./index-0lMAZRQB.js";import{P}from"./PageBar-DP6LpIFv.js";import{a as O}from"./Spinner.vue_vue_type_style_index_0_lang-Q7UPdMbi.js";import{S as B}from"./SectionHead-BuisDFZg.js";import{j as R,p as U}from"./filters-CLL9nGZ2.js";import{D as I}from"./index-BlJivYzz.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./classCallCheck-Tw9-kd3s.js";const V={class:"tx"},$={class:"tx__list"},G=["onClick"],Y={class:"tx__main"},z={class:"tx__head"},F={class:"tx__kind"},H={key:0,class:"tx__note"},j={class:"tx__foot"},q={class:"tx__date"},J={key:1,class:"tx__empty"},K={class:"sheet"},Q={class:"sheet__specs"},W={class:"sheet__spec"},X={class:"sheet__spec"},Z={class:"sheet__spec"},ss={class:"sheet__spec"},es={class:"sheet__spec"},ts=b({__name:"TransactionsView",setup(os){const x={ORDER_STOCK:"سفارش",ORDER_PRE_ORDER:"سفارش ساخت",REPAYMENT_MELTED_GOLD:"طلای آب‌شده",REPAYMENT_TRANSFER:"حواله",REPAYMENT_CHEQUE:"چک",REPAYMENT_CASH:"پولی",WALLET_BONUS:"پاداش",ADJUSTMENT:"اصلاحیه"},T=A(),_=u(!1),d=u([]),v=u(!1),n=u(null),c=a=>a.direction==="CREDIT",h=a=>a.currency==="GOLD_GRAM"?`${a.amount} گرم`:`${U(a.amount)} ریال`,k=a=>{n.value=a,v.value=!0};return C(async()=>{if(T.isLoggedIn){_.value=!0;try{d.value=await D.getMyLedgerEntries()}finally{_.value=!1}}}),(a,e)=>{const S=N("container");return l(),i("div",V,[r(P,{title:"اسناد","back-to":"userPage::hasSubRoute"}),r(O,{spinning:_.value,tip:"درحال دریافت اطلاعات"},{default:f(()=>[r(S,{class:"tx__body"},{default:f(()=>[d.value.length?(l(),i(y,{key:0},[r(B,{title:"گردش حساب",subtitle:`${d.value.length} سند`},null,8,["subtitle"]),s("div",$,[(l(!0),i(y,null,L(d.value,t=>(l(),i("article",{key:t.id,class:"tx__row",onClick:ns=>k(t)},[s("span",{class:p(["tx__mark",c(t)?"is-in":"is-out"]),"aria-hidden":"true"},[r(g,{icon:c(t)?"vuesax-linear:arrow-down":"vuesax-linear:arrow-up",size:"16"},null,8,["icon"])],2),s("div",Y,[s("div",z,[s("h3",F,o(x[t.sourceType]??t.sourceType),1),s("span",{class:p(["tx__amount",c(t)?"is-in":"is-out"])},o(h(t)),3)]),t.note?(l(),i("p",H,o(t.note),1)):m("",!0),s("div",j,[s("span",q,o(E(R)(t.createdAt)),1),s("span",{class:p(["tx__state",{"is-pending":!t.confirmed}])},o(t.confirmed?"تایید شده":"در انتظار تایید"),3)])])],8,G))),128))])],64)):_.value?m("",!0):(l(),i("section",J,[r(g,{icon:"vuesax-linear:receipt-text",size:"26"}),e[1]||(e[1]=s("p",null,"سندی برای حساب شما ثبت نشده است.",-1))]))]),_:1})]),_:1},8,["spinning"]),n.value?(l(),w(E(I),{key:0,visible:v.value,"onUpdate:visible":e[0]||(e[0]=t=>v.value=t),placement:"bottom",closable:!1,height:"420px",class:"rtl",bodyStyle:{padding:0}},{default:f(()=>[s("div",K,[e[7]||(e[7]=s("h3",{class:"sheet__title"},"جزئیات سند",-1)),s("dl",Q,[s("div",W,[e[2]||(e[2]=s("dt",null,"نوع سند",-1)),s("dd",null,o(x[n.value.sourceType]??n.value.sourceType),1)]),s("div",X,[e[3]||(e[3]=s("dt",null,"مبلغ",-1)),s("dd",{class:p(c(n.value)?"is-in":"is-out")},o(h(n.value)),3)]),s("div",Z,[e[4]||(e[4]=s("dt",null,"وضعیت",-1)),s("dd",null,o(n.value.confirmed?"تایید شده":"در انتظار تایید"),1)]),s("div",ss,[e[5]||(e[5]=s("dt",null,"تاریخ",-1)),s("dd",null,o(E(R)(n.value.createdAt)),1)]),s("div",es,[e[6]||(e[6]=s("dt",null,"توضیحات",-1)),s("dd",null,o(n.value.note||"—"),1)])])])]),_:1},8,["visible"])):m("",!0)])}}}),ps=M(ts,[["__scopeId","data-v-d21f0dcb"]]);export{ps as default};
import{d as b,G as A,o as C,q as D,c as i,k as r,s as f,x as w,u as E,f as m,g as u,i as l,F as y,b as s,r as L,I as g,t as o,e as p,v as N,_ as M}from"./index-BrtROTwT.js";import{P}from"./PageBar-Dh4JEEwN.js";import{a as O}from"./Spinner.vue_vue_type_style_index_0_lang-DTTCd0cJ.js";import{S as B}from"./SectionHead-CiVUI4hB.js";import{j as R,p as U}from"./filters-CLL9nGZ2.js";import{D as I}from"./index-DixO0OJ3.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./classCallCheck-DE78qYAT.js";const V={class:"tx"},$={class:"tx__list"},G=["onClick"],Y={class:"tx__main"},z={class:"tx__head"},F={class:"tx__kind"},H={key:0,class:"tx__note"},j={class:"tx__foot"},q={class:"tx__date"},J={key:1,class:"tx__empty"},K={class:"sheet"},Q={class:"sheet__specs"},W={class:"sheet__spec"},X={class:"sheet__spec"},Z={class:"sheet__spec"},ss={class:"sheet__spec"},es={class:"sheet__spec"},ts=b({__name:"TransactionsView",setup(os){const x={ORDER_STOCK:"سفارش",ORDER_PRE_ORDER:"سفارش ساخت",REPAYMENT_MELTED_GOLD:"طلای آب‌شده",REPAYMENT_TRANSFER:"حواله",REPAYMENT_CHEQUE:"چک",REPAYMENT_CASH:"پولی",WALLET_BONUS:"پاداش",ADJUSTMENT:"اصلاحیه"},T=A(),_=u(!1),d=u([]),v=u(!1),n=u(null),c=a=>a.direction==="CREDIT",h=a=>a.currency==="GOLD_GRAM"?`${a.amount} گرم`:`${U(a.amount)} ریال`,k=a=>{n.value=a,v.value=!0};return C(async()=>{if(T.isLoggedIn){_.value=!0;try{d.value=await D.getMyLedgerEntries()}finally{_.value=!1}}}),(a,e)=>{const S=N("container");return l(),i("div",V,[r(P,{title:"اسناد","back-to":"userPage::hasSubRoute"}),r(O,{spinning:_.value,tip:"درحال دریافت اطلاعات"},{default:f(()=>[r(S,{class:"tx__body"},{default:f(()=>[d.value.length?(l(),i(y,{key:0},[r(B,{title:"گردش حساب",subtitle:`${d.value.length} سند`},null,8,["subtitle"]),s("div",$,[(l(!0),i(y,null,L(d.value,t=>(l(),i("article",{key:t.id,class:"tx__row",onClick:ns=>k(t)},[s("span",{class:p(["tx__mark",c(t)?"is-in":"is-out"]),"aria-hidden":"true"},[r(g,{icon:c(t)?"vuesax-linear:arrow-down":"vuesax-linear:arrow-up",size:"16"},null,8,["icon"])],2),s("div",Y,[s("div",z,[s("h3",F,o(x[t.sourceType]??t.sourceType),1),s("span",{class:p(["tx__amount",c(t)?"is-in":"is-out"])},o(h(t)),3)]),t.note?(l(),i("p",H,o(t.note),1)):m("",!0),s("div",j,[s("span",q,o(E(R)(t.createdAt)),1),s("span",{class:p(["tx__state",{"is-pending":!t.confirmed}])},o(t.confirmed?"تایید شده":"در انتظار تایید"),3)])])],8,G))),128))])],64)):_.value?m("",!0):(l(),i("section",J,[r(g,{icon:"vuesax-linear:receipt-text",size:"26"}),e[1]||(e[1]=s("p",null,"سندی برای حساب شما ثبت نشده است.",-1))]))]),_:1})]),_:1},8,["spinning"]),n.value?(l(),w(E(I),{key:0,visible:v.value,"onUpdate:visible":e[0]||(e[0]=t=>v.value=t),placement:"bottom",closable:!1,height:"420px",class:"rtl",bodyStyle:{padding:0}},{default:f(()=>[s("div",K,[e[7]||(e[7]=s("h3",{class:"sheet__title"},"جزئیات سند",-1)),s("dl",Q,[s("div",W,[e[2]||(e[2]=s("dt",null,"نوع سند",-1)),s("dd",null,o(x[n.value.sourceType]??n.value.sourceType),1)]),s("div",X,[e[3]||(e[3]=s("dt",null,"مبلغ",-1)),s("dd",{class:p(c(n.value)?"is-in":"is-out")},o(h(n.value)),3)]),s("div",Z,[e[4]||(e[4]=s("dt",null,"وضعیت",-1)),s("dd",null,o(n.value.confirmed?"تایید شده":"در انتظار تایید"),1)]),s("div",ss,[e[5]||(e[5]=s("dt",null,"تاریخ",-1)),s("dd",null,o(E(R)(n.value.createdAt)),1)]),s("div",es,[e[6]||(e[6]=s("dt",null,"توضیحات",-1)),s("dd",null,o(n.value.note||"—"),1)])])])]),_:1},8,["visible"])):m("",!0)])}}}),ps=M(ts,[["__scopeId","data-v-d21f0dcb"]]);export{ps as default};
@@ -1 +1 @@
import{g as d,u as C,h as a,m as F,q as S}from"./index-0lMAZRQB.js";function W(t){return(t.qty??0)>0||!!t.isPreOrder}function Q(t){if(!t||t.length===0)return null;const e=t.filter(W);return(e.length?e:t).reduce((s,r)=>parseFloat(r.defaultWagePercent)<parseFloat(s.defaultWagePercent)?r:s)}function M(t,e){const i=d(t),s=a(()=>i.value.id),r=a(()=>i.value.title),n=a(()=>i.value.variants),o=d(e??Q(C(n))),y=a(()=>{var u,f,m,p;return((f=(u=o.value)==null?void 0:u.image)==null?void 0:f.url)??((p=(m=i.value.images)==null?void 0:m[0])==null?void 0:p.url)}),g=a(()=>o.value?parseFloat(o.value.rashWeightGrams):0),x=a(()=>o.value?parseFloat(o.value.defaultWagePercent):null),q=d(null),l=a(()=>{var u;return((u=o.value)==null?void 0:u.qty)??0}),h=a(()=>{var u;return((u=o.value)==null?void 0:u.isPreOrder)??!1}),P=a(()=>l.value>0||h.value),O=a(()=>i.value.productCode??null),_=d(!1);return{product:i,image:y,id:s,title:r,productCode:O,variants:n,selectedVariant:o,min_gram:g,wage:x,hasDiscountWage:q,qty:l,isPreOrder:h,is_exist:P,has_warranty:_}}const v="appCart";function w(){try{const t=localStorage.getItem(v);return t?JSON.parse(t):[]}catch{return[]}}function c(t){localStorage.setItem(v,JSON.stringify(t))}const N=F("cart",{state:()=>({items:w()}),actions:{async init(){try{const t=await S.listProducts(),e=[];for(const i of this.items){const s=t.find(n=>n.id===i.pid),r=s==null?void 0:s.variants.find(n=>n.id===i.vid);s&&r&&e.push({...i,product:s})}this.items=e,c(this.items)}catch(t){console.log(t)}},addToCart(t){var s,r;const e=(r=(s=t.product)==null?void 0:s.variants)==null?void 0:r.find(n=>n.id===t.vid);if(!e||!((e.qty??0)>0||e.isPreOrder))return!1;const i=this.find_index(t);return i===-1?this.items.push({...t,qty:this.capQty(t.qty,e)}):(this.items[i].product=t.product,this.items[i].qty=this.capQty(t.qty,e)),c(this.items),!0},capQty(t,e){const i=Math.max(1,Math.floor(t)||1);if(e.isPreOrder)return i;const s=e.qty??0;return s>0?Math.min(i,s):i},maxQty(t){const e=this.find_index(t);if(e===-1)return null;const i=this.variant(this.items[e]);return!i||i.isPreOrder?null:(i.qty??0)>0?i.qty:null},remove(t){const e=this.find_index(t);e>-1&&this.items.splice(e,1),c(this.items)},updateFeild(t,e,i,s){if(!this.isInCart(i))return!1;const r=e??this.find_index(i);if(s==="qty"){const n=this.variant(this.items[r]);t=n?this.capQty(Number(t),n):Math.max(1,Number(t)||1)}return this.items[r][s]=t,c(this.items),!0},find_index(t){return this.items.findIndex(e=>e.pid===t.pid&&e.vid===t.vid)},isInCart(t){return this.find_index(t)>-1},variant(t){return t.product.variants.find(e=>e.id===t.vid)},total(){return this.items.reduce((t,e)=>{const i=this.variant(e);return t+(i?parseFloat(i.rashWeightGrams)*e.qty:0)},0).toFixed(2)},clear(){this.items=[],c(this.items)}}});export{N as a,W as i,M as u};
import{g as d,u as C,h as a,m as F,q as S}from"./index-BrtROTwT.js";function W(t){return(t.qty??0)>0||!!t.isPreOrder}function Q(t){if(!t||t.length===0)return null;const e=t.filter(W);return(e.length?e:t).reduce((s,r)=>parseFloat(r.defaultWagePercent)<parseFloat(s.defaultWagePercent)?r:s)}function M(t,e){const i=d(t),s=a(()=>i.value.id),r=a(()=>i.value.title),n=a(()=>i.value.variants),o=d(e??Q(C(n))),y=a(()=>{var u,f,m,p;return((f=(u=o.value)==null?void 0:u.image)==null?void 0:f.url)??((p=(m=i.value.images)==null?void 0:m[0])==null?void 0:p.url)}),g=a(()=>o.value?parseFloat(o.value.rashWeightGrams):0),x=a(()=>o.value?parseFloat(o.value.defaultWagePercent):null),q=d(null),l=a(()=>{var u;return((u=o.value)==null?void 0:u.qty)??0}),h=a(()=>{var u;return((u=o.value)==null?void 0:u.isPreOrder)??!1}),P=a(()=>l.value>0||h.value),O=a(()=>i.value.productCode??null),_=d(!1);return{product:i,image:y,id:s,title:r,productCode:O,variants:n,selectedVariant:o,min_gram:g,wage:x,hasDiscountWage:q,qty:l,isPreOrder:h,is_exist:P,has_warranty:_}}const v="appCart";function w(){try{const t=localStorage.getItem(v);return t?JSON.parse(t):[]}catch{return[]}}function c(t){localStorage.setItem(v,JSON.stringify(t))}const N=F("cart",{state:()=>({items:w()}),actions:{async init(){try{const t=await S.listProducts(),e=[];for(const i of this.items){const s=t.find(n=>n.id===i.pid),r=s==null?void 0:s.variants.find(n=>n.id===i.vid);s&&r&&e.push({...i,product:s})}this.items=e,c(this.items)}catch(t){console.log(t)}},addToCart(t){var s,r;const e=(r=(s=t.product)==null?void 0:s.variants)==null?void 0:r.find(n=>n.id===t.vid);if(!e||!((e.qty??0)>0||e.isPreOrder))return!1;const i=this.find_index(t);return i===-1?this.items.push({...t,qty:this.capQty(t.qty,e)}):(this.items[i].product=t.product,this.items[i].qty=this.capQty(t.qty,e)),c(this.items),!0},capQty(t,e){const i=Math.max(1,Math.floor(t)||1);if(e.isPreOrder)return i;const s=e.qty??0;return s>0?Math.min(i,s):i},maxQty(t){const e=this.find_index(t);if(e===-1)return null;const i=this.variant(this.items[e]);return!i||i.isPreOrder?null:(i.qty??0)>0?i.qty:null},remove(t){const e=this.find_index(t);e>-1&&this.items.splice(e,1),c(this.items)},updateFeild(t,e,i,s){if(!this.isInCart(i))return!1;const r=e??this.find_index(i);if(s==="qty"){const n=this.variant(this.items[r]);t=n?this.capQty(Number(t),n):Math.max(1,Number(t)||1)}return this.items[r][s]=t,c(this.items),!0},find_index(t){return this.items.findIndex(e=>e.pid===t.pid&&e.vid===t.vid)},isInCart(t){return this.find_index(t)>-1},variant(t){return t.product.variants.find(e=>e.id===t.vid)},total(){return this.items.reduce((t,e)=>{const i=this.variant(e);return t+(i?parseFloat(i.rashWeightGrams)*e.qty:0)},0).toFixed(2)},clear(){this.items=[],c(this.items)}}});export{N as a,W as i,M as u};
@@ -1 +1 @@
import{c as l}from"./Spinner.vue_vue_type_style_index_0_lang-Q7UPdMbi.js";var f=function(n){return setTimeout(n,16)},c=function(n){return clearTimeout(n)};typeof window<"u"&&"requestAnimationFrame"in window&&(f=function(n){return window.requestAnimationFrame(n)},c=function(n){return window.cancelAnimationFrame(n)});var i=0,o=new Map;function u(e){o.delete(e)}function w(e){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:1;i+=1;var r=i;function a(t){if(t===0)u(r),e();else{var s=f(function(){a(t-1)});o.set(r,s)}}return a(n),r}w.cancel=function(e){var n=o.get(e);return u(n),c(n)};function m(e,n){for(var r=l({},e),a=0;a<n.length;a+=1){var t=n[a];delete r[t]}return r}function p(e,n,r){return Object.defineProperty(e,"prototype",{writable:!1}),e}function v(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}export{p as _,v as a,m as o,w};
import{c as l}from"./Spinner.vue_vue_type_style_index_0_lang-DTTCd0cJ.js";var f=function(n){return setTimeout(n,16)},c=function(n){return clearTimeout(n)};typeof window<"u"&&"requestAnimationFrame"in window&&(f=function(n){return window.requestAnimationFrame(n)},c=function(n){return window.cancelAnimationFrame(n)});var i=0,o=new Map;function u(e){o.delete(e)}function w(e){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:1;i+=1;var r=i;function a(t){if(t===0)u(r),e();else{var s=f(function(){a(t-1)});o.set(r,s)}}return a(n),r}w.cancel=function(e){var n=o.get(e);return u(n),c(n)};function m(e,n){for(var r=l({},e),a=0;a<n.length;a+=1){var t=n[a];delete r[t]}return r}function p(e,n,r){return Object.defineProperty(e,"prototype",{writable:!1}),e}function v(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}export{p as _,v as a,m as o,w};
@@ -1 +1 @@
import{m as e}from"./index-0lMAZRQB.js";const t={colors:[],brands:[],ciny_id:[],limit_percent:[],limit_gram:[],has_discount:!1,text:void 0,cats:void 0,page:0},i=e("filters",{state:()=>({query:{...t}}),actions:{reset(){this.query={...t}}}});export{i as u};
import{m as e}from"./index-BrtROTwT.js";const t={colors:[],brands:[],ciny_id:[],limit_percent:[],limit_gram:[],has_discount:!1,text:void 0,cats:void 0,page:0},i=e("filters",{state:()=>({query:{...t}}),actions:{reset(){this.query={...t}}}});export{i as u};
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{ad as y,d as L,ae as N,af as $,H as w,ag as A,k as c,g as D,C as p,L as B,ah as C,N as I,ai as f,aj as M,ak as R,al as U}from"./index-0lMAZRQB.js";const[Y,r,j]=y("pull-refresh"),x=50,F=["pulling","loosing","success"],G={disabled:Boolean,modelValue:Boolean,headHeight:f(x),successText:String,pullingText:String,loosingText:String,loadingText:String,pullDistance:N,successDuration:f(500),animationDuration:f(300)};var X=L({name:Y,props:G,emits:["change","refresh","update:modelValue"],setup(s,{emit:d,slots:o}){let u;const g=D(),T=D(),H=$(g),e=p({status:"normal",distance:0,duration:0}),i=R(),P=()=>{if(s.headHeight!==x)return{height:`${s.headHeight}px`}},h=()=>e.status!=="loading"&&e.status!=="success"&&!s.disabled,k=t=>{const a=+(s.pullDistance||s.headHeight);return t>a&&(t<a*2?t=a+(t-a)/2:t=a*1.5+(t-a*2)/4),Math.round(t)},n=(t,a)=>{const l=+(s.pullDistance||s.headHeight);e.distance=t,a?e.status="loading":t===0?e.status="normal":t<l?e.status="pulling":e.status="loosing",d("change",{status:e.status,distance:t})},m=()=>{const{status:t}=e;return t==="normal"?"":s[`${t}Text`]||j(t)},E=()=>{const{status:t,distance:a}=e;if(o[t])return o[t]({distance:a});const l=[];return F.includes(t)&&l.push(c("div",{class:r("text")},[m()])),t==="loading"&&l.push(c(B,{class:r("loading")},{default:m})),l},V=()=>{e.status="success",setTimeout(()=>{n(0)},+s.successDuration)},v=t=>{u=M(H.value)===0,u&&(e.duration=0,i.start(t))},_=t=>{h()&&v(t)},b=t=>{if(h()){u||v(t);const{deltaY:a}=i;i.move(t),u&&a.value>=0&&i.isVertical()&&(C(t),n(k(a.value)))}},S=()=>{u&&i.deltaY.value&&h()&&(e.duration=+s.animationDuration,e.status==="loosing"?(n(+s.headHeight,!0),d("update:modelValue",!0),I(()=>d("refresh"))):n(0))};return w(()=>s.modelValue,t=>{e.duration=+s.animationDuration,t?n(+s.headHeight,!0):o.success||s.successText?V():n(0,!1)}),A("touchmove",b,{target:T}),()=>{var t;const a={transitionDuration:`${e.duration}ms`,transform:e.distance?`translate3d(0,${e.distance}px, 0)`:""};return c("div",{ref:g,class:r()},[c("div",{ref:T,class:r("track"),style:a,onTouchstartPassive:_,onTouchend:S,onTouchcancel:S},[c("div",{class:r("head"),style:P()},[E()]),(t=o.default)==null?void 0:t.call(o)])])}}});const z=U(X);export{z as P};
import{ad as y,d as L,ae as N,af as $,H as w,ag as A,k as c,g as D,C as p,L as B,ah as C,N as I,ai as f,aj as M,ak as R,al as U}from"./index-BrtROTwT.js";const[Y,r,j]=y("pull-refresh"),x=50,F=["pulling","loosing","success"],G={disabled:Boolean,modelValue:Boolean,headHeight:f(x),successText:String,pullingText:String,loosingText:String,loadingText:String,pullDistance:N,successDuration:f(500),animationDuration:f(300)};var X=L({name:Y,props:G,emits:["change","refresh","update:modelValue"],setup(s,{emit:d,slots:o}){let u;const g=D(),T=D(),H=$(g),e=p({status:"normal",distance:0,duration:0}),i=R(),P=()=>{if(s.headHeight!==x)return{height:`${s.headHeight}px`}},h=()=>e.status!=="loading"&&e.status!=="success"&&!s.disabled,k=t=>{const a=+(s.pullDistance||s.headHeight);return t>a&&(t<a*2?t=a+(t-a)/2:t=a*1.5+(t-a*2)/4),Math.round(t)},n=(t,a)=>{const l=+(s.pullDistance||s.headHeight);e.distance=t,a?e.status="loading":t===0?e.status="normal":t<l?e.status="pulling":e.status="loosing",d("change",{status:e.status,distance:t})},m=()=>{const{status:t}=e;return t==="normal"?"":s[`${t}Text`]||j(t)},E=()=>{const{status:t,distance:a}=e;if(o[t])return o[t]({distance:a});const l=[];return F.includes(t)&&l.push(c("div",{class:r("text")},[m()])),t==="loading"&&l.push(c(B,{class:r("loading")},{default:m})),l},V=()=>{e.status="success",setTimeout(()=>{n(0)},+s.successDuration)},v=t=>{u=M(H.value)===0,u&&(e.duration=0,i.start(t))},_=t=>{h()&&v(t)},b=t=>{if(h()){u||v(t);const{deltaY:a}=i;i.move(t),u&&a.value>=0&&i.isVertical()&&(C(t),n(k(a.value)))}},S=()=>{u&&i.deltaY.value&&h()&&(e.duration=+s.animationDuration,e.status==="loosing"?(n(+s.headHeight,!0),d("update:modelValue",!0),I(()=>d("refresh"))):n(0))};return w(()=>s.modelValue,t=>{e.duration=+s.animationDuration,t?n(+s.headHeight,!0):o.success||s.successText?V():n(0,!1)}),A("touchmove",b,{target:T}),()=>{var t;const a={transitionDuration:`${e.duration}ms`,transform:e.distance?`translate3d(0,${e.distance}px, 0)`:""};return c("div",{ref:g,class:r()},[c("div",{ref:T,class:r("track"),style:a,onTouchstartPassive:_,onTouchend:S,onTouchcancel:S},[c("div",{class:r("head"),style:P()},[E()]),(t=o.default)==null?void 0:t.call(o)])])}}});const z=U(X);export{z as P};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{d as r,k as c,a4 as l,aq as p,ar as d,a1 as i,as as u,at as m,ae as f,au as o,ad as g,al as k}from"./index-0lMAZRQB.js";const[h,P]=g("notify"),w=["lockScroll","position","show","teleport","zIndex"],y=i({},u,{type:o("danger"),color:String,message:f,position:o("top"),className:m,background:String,lockScroll:Boolean});var S=r({name:h,props:y,emits:["update:show"],setup(a,{emit:s,slots:e}){const t=n=>s("update:show",n);return()=>c(d,l({class:[P([a.type]),a.className],style:{color:a.color,background:a.background},overlay:!1,duration:.2,"onUpdate:show":t},p(a,w)),{default:()=>[e.default?e.default():a.message]})}});const b=k(S);export{b as N,S as s};
import{d as r,k as c,a4 as l,aq as p,ar as d,a1 as i,as as u,at as m,ae as f,au as o,ad as g,al as k}from"./index-BrtROTwT.js";const[h,P]=g("notify"),w=["lockScroll","position","show","teleport","zIndex"],y=i({},u,{type:o("danger"),color:String,message:f,position:o("top"),className:m,background:String,lockScroll:Boolean});var S=r({name:h,props:y,emits:["update:show"],setup(a,{emit:s,slots:e}){const t=n=>s("update:show",n);return()=>c(d,l({class:[P([a.type]),a.className],style:{color:a.color,background:a.background},overlay:!1,duration:.2,"onUpdate:show":t},p(a,w)),{default:()=>[e.default?e.default():a.message]})}});const b=k(S);export{b as N,S as s};
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -9,8 +9,8 @@
<meta name="background-color" content="#1C2D56" />
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport" />
<title>طلای منتزر</title>
<script type="module" crossorigin src="/assets/index-0lMAZRQB.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-CpQh57KC.css">
<script type="module" crossorigin src="/assets/index-BrtROTwT.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-DmO-cYMw.css">
<link rel="manifest" href="/manifest.webmanifest"></head>
<body style="background-color: #fff">
<div class="bg-white w-screen h-screen fixed"></div>
+1 -1
View File
File diff suppressed because one or more lines are too long
+85
View File
@@ -228,6 +228,72 @@ export interface ExpertChildOrder {
items: OrderItemDetail[];
customer: { id: string; name: string; mobile: string } | null;
}
/**
* D24 — "گزارش", the account statement.
*
* The field names are the reference's (henza_pwa/src/type/accounting.ts), so
* the ported components bind exactly as they did. Money and weights travel as
* decimal STRINGS, never as JS numbers, so no figure is rounded in transit.
*/
export interface ReportRow {
id: number;
/** The ledger entry id; what the detail call is keyed on. */
factor_Code: string;
sh_factor: string;
tarikh: string;
/** Gold in / out, as separate positive columns. */
geram_v: string;
geram_kh: string;
rial_v: string;
rial_kh: string;
/** Running balances AFTER this row. Signed: negative means in credit. */
tahesab_T: string;
tahesab_P: string;
/** No foreign-currency ledger in the target — always zero (REP-01). */
rial_V2: string;
rial_Kh2: string;
tahesabP2: string;
sourceType: string;
note: string | null;
}
export interface ReportPage {
result: ReportRow[];
count: number;
page: number;
limit: number;
}
/** One document's detail. Fields the target cannot know are null, not invented. */
export interface ReportDetailRow {
factor_Code: string;
sh_factor: string;
tarikh: string;
vazn: string;
ayar: number | null;
no: string;
sh_sharti: string | null;
name_az: string | null;
tabdil750_v: string;
tabdil750_kh: string;
fi: string | null;
fiF: string | null;
Darsad_Talayee: string | null;
accountName: string | null;
bankName: string | null;
transferTo: string | null;
receivedAt: string | null;
note: string | null;
nO_kar: null;
jens_felez: null;
Darsad: null;
maliatDarsad: null;
}
export interface ReportBalance {
arz: string;
mandeh: string;
}
export const api = {
listProducts: () => request<ProductSummary[]>('/catalog/products'),
@@ -328,4 +394,23 @@ export const api = {
method: 'POST',
body: JSON.stringify(payload),
}),
// ── report / report detail (D24) ─────────────────────────────────────
// The reference proxied an external accounting system
// (henza_server Customer/TahesabController). These read the target's own
// ledger instead — no external call — and the customer comes from the token.
getReport: (page = 1) =>
request<ReportPage>(`/customer/me/report?page=${page}`),
getReportDetailList: (page = 1) =>
request<{ result: ReportDetailRow[]; page: number; limit: number }>(
`/customer/me/report/detail?page=${page}`,
),
getReportBalances: () =>
request<{ status: number; message: string; result: ReportBalance[] }>(
'/customer/me/report/balances',
),
getReportDocument: (id: string) =>
request<{ result: ReportDetailRow[]; page: number; limit: number }>(
`/customer/me/report/${encodeURIComponent(id)}`,
),
};
+15
View File
@@ -62,6 +62,21 @@ export const router = createRouter({
component: () => import('../views/user/CompleteProfileView.vue'),
meta: { title: 'تکمیل پروفایل', layout: 'FullPage', requiresAuth: true, requiresIncompleteProfile: true },
},
// D24 — the account statement. Reference paths and names kept
// (henza_pwa router/index.ts:163-165, :191-193). The detail route opens
// the same page on its second tab, as the reference did.
{
path: '/report',
name: 'report',
component: () => import('../views/report/ReportView.vue'),
meta: { title: 'گزارش', layout: 'FullPage', requiresAuth: true },
},
{
path: '/report/detail',
name: 'reportDetail',
component: () => import('../views/report/ReportView.vue'),
meta: { title: 'جزئیات حساب', layout: 'FullPage', requiresAuth: true },
},
{ path: '/notifications', name: 'notifications', component: () => import('../views/user/NotificationsView.vue') },
{ path: '/search', name: 'search', component: () => import('../views/search/SearchView.vue') },
{ path: '/collection/:id?', name: 'collection', component: () => import('../views/search/CollectionView.vue') },
@@ -0,0 +1,188 @@
<!--
One document of "جزئیات حساب".
Ported from henza_pwa/src/views/report/components/AccountingDetail.vue,
restyled into this app's design language. The LOGIC is the reference's and is
identical in user-app-v2; only the styling differs.
Kept from the reference: شماره سند + تاریخ, وزن خالص, عیار, نوع سند,
شماره انگ, نام آزمایشگاه, قیمت, and the طلا in/out pair normalized to 750
(AccountingDetail.vue:6-85).
Rows the reference showed that the target has no equivalent for — نام کارساخته
(nO_kar), جنس فلز (jens_felez) and the two extra percentage lines — are
OMITTED rather than rendered blank or zero. They came from an external
accounting system the target does not have; the API returns null for them and
this component skips a row whose value is null, so the card never asserts
something it does not know. Recorded as REP-01.
Rows the target CAN fill and the reference could not are added at the end
(bank/account/destination), since those live on our own ledger entry.
-->
<template>
<article class="doc">
<header class="doc__head">
<span><span class="doc__muted">شماره سند:</span> {{ item.sh_factor }}</span>
<span><span class="doc__muted">تاریخ:</span> {{ jdate(item.tarikh) }}</span>
</header>
<dl class="doc__rows">
<div class="doc__row">
<dt>نوع سند</dt>
<dd>{{ item.no }}</dd>
</div>
<div class="doc__row">
<dt>وزن خالص</dt>
<dd dir="ltr">{{ item.vazn }}</dd>
</div>
<div v-if="item.ayar !== null" class="doc__row">
<dt>عیار</dt>
<dd dir="ltr">{{ item.ayar }}</dd>
</div>
<div v-if="item.sh_sharti" class="doc__row">
<dt>شماره انگ</dt>
<dd dir="ltr">{{ item.sh_sharti }}</dd>
</div>
<div v-if="item.name_az" class="doc__row">
<dt>نام آزمایشگاه</dt>
<dd>{{ item.name_az }}</dd>
</div>
<div v-if="item.Darsad_Talayee" class="doc__row">
<dt>اجرت (گرم)</dt>
<dd dir="ltr">{{ item.Darsad_Talayee }}</dd>
</div>
<div v-if="item.fi" class="doc__row">
<dt>قیمت هر گرم</dt>
<dd dir="ltr">{{ rial(item.fi) }}</dd>
</div>
<div v-if="item.fiF" class="doc__row">
<dt>مبلغ سند</dt>
<dd dir="ltr">{{ rial(item.fiF) }}</dd>
</div>
<div v-if="item.bankName" class="doc__row">
<dt>بانک</dt>
<dd>{{ item.bankName }}</dd>
</div>
<div v-if="item.accountName" class="doc__row">
<dt>نام حساب</dt>
<dd>{{ item.accountName }}</dd>
</div>
<div v-if="item.transferTo" class="doc__row">
<dt>مقصد حواله</dt>
<dd>{{ item.transferTo }}</dd>
</div>
<div v-if="item.receivedAt" class="doc__row">
<dt>تاریخ دریافت</dt>
<dd>{{ jdate(item.receivedAt) }}</dd>
</div>
<div v-if="item.note" class="doc__row">
<dt>توضیحات</dt>
<dd>{{ item.note }}</dd>
</div>
</dl>
<div class="doc__gold">
<span>طلا</span>
<div class="doc__stack">
<span dir="ltr" class="is-in">{{ item.tabdil750_v }}</span>
<span dir="ltr" class="is-out">{{ item.tabdil750_kh }}</span>
</div>
</div>
</article>
</template>
<script setup lang="ts">
import { jdate, price } from '../../utils/filters'
import type { ReportDetailRow } from '../../api/client'
defineProps<{ item: ReportDetailRow }>()
/** Same rule as the statement: group the whole part only. */
function rial(value: string): string {
const n = parseFloat(value)
if (!Number.isFinite(n)) return value
const whole = Math.trunc(Math.abs(n)).toString()
return (n < 0 ? '-' : '') + price(whole)
}
</script>
<style scoped lang="less">
.doc {
padding: 16px;
background: @canvas;
border: 1px solid @hairline;
border-radius: 18px;
}
.doc__head {
display: flex;
justify-content: space-between;
gap: 10px;
margin-bottom: 12px;
font-size: 13px;
font-weight: 600;
}
.doc__muted {
color: @inkMuted;
font-weight: 500;
margin-left: 4px;
}
.doc__rows {
margin: 0;
display: flex;
flex-direction: column;
gap: 2px;
}
.doc__row {
display: flex;
justify-content: space-between;
align-items: center;
gap: 12px;
padding: 10px 12px;
background: @canvasSoft;
border-radius: 10px;
}
.doc__row dt {
font-size: 12.5px;
color: @inkMuted;
white-space: nowrap;
}
.doc__row dd {
margin: 0;
font-size: 13.5px;
font-weight: 600;
text-align: left;
}
.doc__gold {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 8px;
padding: 10px 12px;
background: @hairlineSoft;
border-radius: 10px;
font-size: 13px;
font-weight: 700;
}
.doc__stack {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 2px;
}
.is-in {
color: #16a34a;
}
.is-out {
color: #dc2626;
}
</style>
@@ -0,0 +1,437 @@
<!--
"گزارش" — the customer's account statement.
Ported from henza_pwa/src/views/report/index.vue (route /report, name
report) plus its two card components (components/Accounting.vue,
components/AccountingDetail.vue), restyled into this app's design language.
The LOGIC is the reference's and is identical in user-app-v2; only the
styling differs.
Kept from the reference:
- the title "گزارش" and the back arrow to the dashboard (index.vue:7-10)
- the two tabs «کلیات حساب» / «جزئیات حساب» (:15-16), switching clears the
list and re-queries from page 1 (:178-181)
- the summary card's rows, in the reference's order: شماره سند + تاریخ,
طلا (in/out), مانده طلا, ریال (in/out), مانده ریال (Accounting.vue:5-48)
- balances coloured by sign — red when negative (Accounting.vue:29, :46)
- the «جزئیات» link opening the document in a modal (:66, index.vue:44-52)
- paging by scroll on the detail tab (:231-241)
Deliberately NOT ported: the ارز (foreign-currency) rows. The reference read
them from an external accounting system; the target has no foreign-currency
ledger, so showing a hardcoded "0 $" would assert something untrue. Recorded
as REP-01.
The reference gated this page on `myStore.hasMCode()` (index.vue:174-177) —
the customer's id in that external system. The target has no mcode, so the
gate is simply a session, and the server scopes every row to the token.
-->
<template>
<div class="rep">
<PageBar title="گزارش" back-to="userPage::hasSubRoute">
<template #below>
<div class="rep__tabs">
<button
type="button"
class="rep__tab"
:class="{ 'is-on': activeKey === '1' }"
@click="changeTab('1')"
>
کلیات حساب
</button>
<button
type="button"
class="rep__tab"
:class="{ 'is-on': activeKey === '2' }"
@click="changeTab('2')"
>
جزئیات حساب
</button>
</div>
</template>
</PageBar>
<Spinner :spinning="loading && !rows.length && !details.length" tip="درحال دریافت اطلاعات">
<PullRefresh v-model="refreshing" @refresh="onRefresh">
<container class="rep__body">
<!-- ── کلیات حساب ─────────────────────────────────────────── -->
<template v-if="activeKey === '1'">
<div v-if="rows.length" class="rep__list">
<article v-for="item in rows" :key="item.factor_Code" class="rep__card">
<header class="rep__head">
<span><span class="rep__muted">شماره سند:</span> {{ item.sh_factor }}</span>
<span><span class="rep__muted">تاریخ:</span> {{ jdate(item.tarikh) }}</span>
</header>
<div class="rep__pair">
<span>طلا</span>
<div class="rep__stack">
<span dir="ltr" class="is-in">{{ item.geram_v }}</span>
<span dir="ltr" class="is-out">{{ item.geram_kh }}</span>
</div>
</div>
<div class="rep__pair is-balance">
<span>مانده طلا:</span>
<span dir="ltr" :class="sign(item.tahesab_T)">{{ item.tahesab_T }}</span>
</div>
<div class="rep__pair">
<span>ریال</span>
<div class="rep__stack">
<span dir="ltr" class="is-in">{{ rial(item.rial_v) }}</span>
<span dir="ltr" class="is-out">{{ rial(item.rial_kh) }}</span>
</div>
</div>
<div class="rep__pair is-balance">
<span>مانده ریال:</span>
<span dir="ltr" :class="sign(item.tahesab_P)">{{ rial(item.tahesab_P) }}</span>
</div>
<button type="button" class="rep__more" @click="openDetail(item)">جزئیات</button>
</article>
</div>
<section v-else-if="!loading && !failed" class="rep__empty">
<Icon icon="vuesax-linear:receipt-text" size="26" />
<p>هنوز سندی برای حساب شما ثبت نشده است.</p>
</section>
</template>
<!-- ── جزئیات حساب ────────────────────────────────────────── -->
<template v-else>
<div v-if="details.length" class="rep__list">
<ReportDocument v-for="d in details" :key="d.factor_Code" :item="d" />
</div>
<section v-else-if="!loading && !failed" class="rep__empty">
<Icon icon="vuesax-linear:receipt-text" size="26" />
<p>هنوز سندی برای حساب شما ثبت نشده است.</p>
</section>
</template>
<section v-if="failed" class="rep__empty">
<Icon icon="vuesax-linear:danger" size="26" />
<p>دریافت اطلاعات با خطا روبه‌رو شد.</p>
<button type="button" class="rep__retry" @click="reload">تلاش دوباره</button>
</section>
<div v-if="loading && (rows.length || details.length)" class="rep__more">در حال دریافت…</div>
<div ref="sentinel" class="rep__sentinel" />
</container>
</PullRefresh>
</Spinner>
<Drawer
v-model:open="modalOpen"
placement="bottom"
height="auto"
:closable="false"
:body-style="{ padding: '0' }"
>
<div class="rep__modal">
<Spinner :spinning="modalLoading" tip="درحال دریافت اطلاعات">
<ReportDocument v-for="d in modalRows" :key="d.factor_Code" :item="d" />
<p v-if="!modalLoading && !modalRows.length" class="rep__modalEmpty">
جزئیاتی برای این سند ثبت نشده است.
</p>
</Spinner>
<button type="button" class="rep__close" @click="modalOpen = false">بازگشت</button>
</div>
</Drawer>
</div>
</template>
<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref } from 'vue'
import { useRoute } from 'vue-router'
import { Drawer } from 'ant-design-vue'
import { PullRefresh } from 'vant'
import Icon from '../../components/icon/Icon.vue'
import PageBar from '../../components/ui/PageBar.vue'
import Spinner from '../../components/Spinner.vue'
import ReportDocument from './ReportDocument.vue'
import { jdate, price } from '../../utils/filters'
import { api, type ReportRow, type ReportDetailRow } from '../../api/client'
const route = useRoute()
/**
* The reference had /report and /report/detail as two routes. The detail one
* lands on the same screen with the second tab already selected, which is what
* its 'جزئیات حساب' tab showed.
*/
const activeKey = ref<'1' | '2'>(route.name === 'reportDetail' ? '2' : '1')
const rows = ref<ReportRow[]>([])
const details = ref<ReportDetailRow[]>([])
const page = ref(1)
const hasMore = ref(true)
const loading = ref(false)
const refreshing = ref(false)
const failed = ref(false)
const modalOpen = ref(false)
const modalLoading = ref(false)
const modalRows = ref<ReportDetailRow[]>([])
/**
* price() groups digits from the right, so a decimal tail would be grouped
* too. Rial figures are whole here, so the .00 is dropped before grouping and
* a negative sign is preserved outside the grouping.
*/
function rial(value: string): string {
const n = parseFloat(value)
if (!Number.isFinite(n)) return value
const whole = Math.trunc(Math.abs(n)).toString()
return (n < 0 ? '-' : '') + price(whole)
}
/** The reference coloured a balance by its sign (Accounting.vue:29). */
function sign(value: string): string {
return parseFloat(value) < 0 ? 'is-out' : 'is-in'
}
async function fetchPage() {
if (loading.value || !hasMore.value) return
loading.value = true
failed.value = false
try {
if (activeKey.value === '1') {
const data = await api.getReport(page.value)
rows.value = [...rows.value, ...(data.result ?? [])]
if ((data.result?.length ?? 0) < (data.limit ?? 50)) hasMore.value = false
else page.value += 1
} else {
const data = await api.getReportDetailList(page.value)
details.value = [...details.value, ...(data.result ?? [])]
if ((data.result?.length ?? 0) < (data.limit ?? 50)) hasMore.value = false
else page.value += 1
}
} catch {
failed.value = true
hasMore.value = false
} finally {
loading.value = false
}
}
function reset() {
rows.value = []
details.value = []
page.value = 1
hasMore.value = true
failed.value = false
}
async function reload() {
reset()
await fetchPage()
}
/** The reference cleared the list and re-queried on tab change (index.vue:178). */
async function changeTab(key: '1' | '2') {
if (activeKey.value === key) return
activeKey.value = key
await reload()
}
async function onRefresh() {
await reload()
refreshing.value = false
}
/** The «جزئیات» link — the reference opened the same card in a modal. */
async function openDetail(item: ReportRow) {
modalOpen.value = true
modalLoading.value = true
modalRows.value = []
try {
const data = await api.getReportDocument(item.factor_Code)
modalRows.value = data.result ?? []
} catch {
modalRows.value = []
} finally {
modalLoading.value = false
}
}
// The reference paged by scroll on the detail tab (index.vue:231-241).
const sentinel = ref<HTMLElement | null>(null)
let observer: IntersectionObserver | null = null
onMounted(async () => {
await fetchPage()
if (typeof IntersectionObserver !== 'undefined') {
observer = new IntersectionObserver((entries) => {
if (entries.some((e) => e.isIntersecting)) void fetchPage()
})
if (sentinel.value) observer.observe(sentinel.value)
}
})
onBeforeUnmount(() => observer?.disconnect())
</script>
<style scoped lang="less">
.rep__tabs {
display: flex;
gap: 8px;
padding: 0 16px 12px;
}
.rep__tab {
flex: 1;
padding: 10px;
border: 1px solid @hairline;
border-radius: 999px;
background: @canvas;
font-family: inherit;
font-size: 13px;
font-weight: 600;
color: @inkMuted;
cursor: pointer;
}
.rep__tab.is-on {
background: @ink;
border-color: @ink;
color: #fff;
}
.rep__body {
padding-top: 132px;
padding-bottom: 90px;
}
.rep__list {
display: flex;
flex-direction: column;
padding-top: 16px;
gap: 11px;
}
.rep__card {
padding: 16px;
background: @canvas;
border: 1px solid @hairline;
border-radius: 18px;
}
.rep__head {
display: flex;
justify-content: space-between;
gap: 10px;
margin-bottom: 12px;
font-size: 13px;
font-weight: 600;
}
.rep__muted {
color: @inkMuted;
font-weight: 500;
margin-left: 4px;
}
.rep__pair {
display: flex;
justify-content: space-between;
align-items: center;
padding: 9px 12px;
margin-bottom: 6px;
background: @canvasSoft;
border-radius: 10px;
font-size: 13px;
}
.rep__pair.is-balance {
background: @hairlineSoft;
font-weight: 700;
}
.rep__stack {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 2px;
font-weight: 600;
}
.is-in {
color: #16a34a;
}
.is-out {
color: #dc2626;
}
.rep__more,
.rep__sentinel {
padding: 12px 0;
text-align: center;
font-size: 12px;
color: @inkMuted;
}
.rep__more {
width: 100%;
margin-top: 4px;
border: none;
background: transparent;
font-family: inherit;
font-weight: 700;
color: @wine;
cursor: pointer;
}
.rep__empty {
margin-top: 8px;
padding: 34px 20px;
border: 1px dashed @hairline;
border-radius: 18px;
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
color: @inkMuted;
font-size: 13px;
}
.rep__retry {
padding: 8px 18px;
border-radius: 999px;
border: 1px solid @hairline;
background: @canvas;
font-family: inherit;
font-size: 12px;
font-weight: 600;
cursor: pointer;
}
.rep__modal {
padding: 20px 16px 24px;
}
.rep__modalEmpty {
padding: 24px 0;
text-align: center;
font-size: 13px;
color: @inkMuted;
}
.rep__close {
margin-top: 18px;
width: 100%;
padding: 13px;
border: none;
border-radius: 14px;
background: @ink;
color: #fff;
font-family: inherit;
font-size: 14px;
font-weight: 700;
cursor: pointer;
}
</style>
@@ -186,6 +186,10 @@ const BASE_TILES = [
{ id: 1, icon: 'vuesax-linear:receipt-text', title: 'اسناد', disabled: false },
{ id: 2, icon: 'vuesax-linear:user', title: 'پروفایل', disabled: false },
{ id: 3, icon: 'vuesax-linear:heart', title: 'علاقمندی', disabled: false },
// D24 — the account statement. The reference put it on the dashboard too,
// gated on hasMCode() (Dashboard.vue:179, :449). The target has no mcode, so
// every signed-in customer sees it and the server scopes it to their token.
{ id: 6, icon: 'vuesax-linear:chart-2', title: 'گزارش', disabled: false },
]
/**
@@ -214,6 +218,7 @@ function goToDetails(id: number) {
if (id === 3) router.push({ name: 'favoritesList' })
if (id === 4) router.push({ name: 'ChildOrder' })
if (id === 5) router.push({ name: 'customerChoice' })
if (id === 6) router.push({ name: 'report' })
}
function logOut() {
+1 -1
View File
@@ -1 +1 @@
{"root":["./src/app.vue","./src/env.d.ts","./src/main.ts","./src/sw.ts","./src/api/client.ts","./src/components/dialogvant.vue","./src/components/dialogvantonebutton.vue","./src/components/emptystate.vue","./src/components/notifyvant.vue","./src/components/spinner.vue","./src/components/viewall.vue","./src/components/home/accountstrip.vue","./src/components/home/categoryrail.vue","./src/components/home/ratestrip.vue","./src/components/home/sectionhead.vue","./src/components/home/showcasecard.vue","./src/components/home/showcaseslider.vue","./src/components/icon/icon.vue","./src/components/input/otpinput.vue","./src/components/input/singleotpinput.vue","./src/components/product/cartitem.vue","./src/components/product/category.vue","./src/components/product/galleryslider.vue","./src/components/product/ordercard.vue","./src/components/product/orderitemcard.vue","./src/components/product/productcard.vue","./src/components/product/singleproduct.vue","./src/components/search/filters.vue","./src/components/search/searchinput.vue","./src/components/slider/homeslider.vue","./src/components/slider/slider.vue","./src/components/ui/container.vue","./src/components/ui/contentwrapper.vue","./src/components/ui/dropdown.vue","./src/components/ui/navigation.vue","./src/components/ui/pagebar.vue","./src/components/ui/scrollfetch.vue","./src/components/ui/scrollfetchaftersearch.vue","./src/components/ui/scrollfetchsearch.vue","./src/components/upload/singleimageuploader.vue","./src/composables/useorderitemproduct.ts","./src/composables/useproduct.ts","./src/composables/useproductdetail.ts","./src/composables/useproducts.ts","./src/composables/userefresh.ts","./src/layout/fullpagelayout.vue","./src/layout/masterlayout.vue","./src/router/index.ts","./src/stores/cartstore.ts","./src/stores/configstore.ts","./src/stores/favoritesstore.ts","./src/stores/filtersstore.ts","./src/stores/loadingstore.ts","./src/stores/navstore.ts","./src/stores/session.ts","./src/stores/transitionstore.ts","./src/stores/windowdatastore.ts","./src/types/moment-jalaali-shim.d.ts","./src/types/swiper-shim.d.ts","./src/utils/checkaccess.ts","./src/utils/filters.ts","./src/utils/orderstatus.ts","./src/utils/validator.ts","./src/views/cartview.vue","./src/views/homeview.vue","./src/views/newestview.vue","./src/views/expert/childordersview.vue","./src/views/expert/customerchoiceview.vue","./src/views/search/collectionview.vue","./src/views/search/searchview.vue","./src/views/user/completeprofileview.vue","./src/views/user/dashboardview.vue","./src/views/user/favoritesview.vue","./src/views/user/loginregisterview.vue","./src/views/user/loginview.vue","./src/views/user/notificationsview.vue","./src/views/user/ordersview.vue","./src/views/user/profileview.vue","./src/views/user/registerview.vue","./src/views/user/transactionsview.vue"],"version":"5.9.3"}
{"root":["./src/app.vue","./src/env.d.ts","./src/main.ts","./src/sw.ts","./src/api/client.ts","./src/components/dialogvant.vue","./src/components/dialogvantonebutton.vue","./src/components/emptystate.vue","./src/components/notifyvant.vue","./src/components/spinner.vue","./src/components/viewall.vue","./src/components/home/accountstrip.vue","./src/components/home/categoryrail.vue","./src/components/home/ratestrip.vue","./src/components/home/sectionhead.vue","./src/components/home/showcasecard.vue","./src/components/home/showcaseslider.vue","./src/components/icon/icon.vue","./src/components/input/otpinput.vue","./src/components/input/singleotpinput.vue","./src/components/product/cartitem.vue","./src/components/product/category.vue","./src/components/product/galleryslider.vue","./src/components/product/ordercard.vue","./src/components/product/orderitemcard.vue","./src/components/product/productcard.vue","./src/components/product/singleproduct.vue","./src/components/search/filters.vue","./src/components/search/searchinput.vue","./src/components/slider/homeslider.vue","./src/components/slider/slider.vue","./src/components/ui/container.vue","./src/components/ui/contentwrapper.vue","./src/components/ui/dropdown.vue","./src/components/ui/navigation.vue","./src/components/ui/pagebar.vue","./src/components/ui/scrollfetch.vue","./src/components/ui/scrollfetchaftersearch.vue","./src/components/ui/scrollfetchsearch.vue","./src/components/upload/singleimageuploader.vue","./src/composables/useorderitemproduct.ts","./src/composables/useproduct.ts","./src/composables/useproductdetail.ts","./src/composables/useproducts.ts","./src/composables/userefresh.ts","./src/layout/fullpagelayout.vue","./src/layout/masterlayout.vue","./src/router/index.ts","./src/stores/cartstore.ts","./src/stores/configstore.ts","./src/stores/favoritesstore.ts","./src/stores/filtersstore.ts","./src/stores/loadingstore.ts","./src/stores/navstore.ts","./src/stores/session.ts","./src/stores/transitionstore.ts","./src/stores/windowdatastore.ts","./src/types/moment-jalaali-shim.d.ts","./src/types/swiper-shim.d.ts","./src/utils/checkaccess.ts","./src/utils/filters.ts","./src/utils/orderstatus.ts","./src/utils/validator.ts","./src/views/cartview.vue","./src/views/homeview.vue","./src/views/newestview.vue","./src/views/expert/childordersview.vue","./src/views/expert/customerchoiceview.vue","./src/views/report/reportdocument.vue","./src/views/report/reportview.vue","./src/views/search/collectionview.vue","./src/views/search/searchview.vue","./src/views/user/completeprofileview.vue","./src/views/user/dashboardview.vue","./src/views/user/favoritesview.vue","./src/views/user/loginregisterview.vue","./src/views/user/loginview.vue","./src/views/user/notificationsview.vue","./src/views/user/ordersview.vue","./src/views/user/profileview.vue","./src/views/user/registerview.vue","./src/views/user/transactionsview.vue"],"version":"5.9.3"}
+37
View File
@@ -1301,3 +1301,40 @@ clear warning; the lower-risk option was chosen (D19), since failing the boot
could take down a running deployment that has not set the variable yet. A
banner as loud as the master-OTP one now fires at boot, and DELIVERY.md lists
it as the **first** pre-release step (REL-03).
## D24 — «گزارش» (report + report/detail) on the internal ledger, 2026-09-23
**In the reference this feature computes nothing.** `Customer\TahesabController`
(henza_server `app/Http/Controllers/Customer/TahesabController.php`) forwards
every call to an external accounting system — `hesab.henzagold.com` and a bare
IP at `31.7.68.147:3030` — with `Http::withoutVerifying()` (TLS verification
off), a bearer token hardcoded in the source and a URL-embedded `sfx` secret,
keyed on `Customer.mcode`, the customer's id in that other system. The PWA
renders whatever comes back.
The target has no such system and no `mcode`. **The owner chose option الف:**
build the reference's UI and flow over our own ledger, with no external
connection. So `customer/me/report*` reproduces the statement's SHAPE — the
field names `henza_pwa/src/type/accounting.ts` declares, so the ported
components bind unchanged — from `LedgerEntry`.
**Honesty rule.** Every figure is computed from confirmed ledger entries.
Where the external system carried a column the target has no equivalent for
(foreign currency, وزن پلاستیک, نام کارساخته, جنس فلز and its internal
bookkeeping ids), the field is `null`/zero and the UI **omits the row** rather
than rendering a fabricated value. Recorded as REP-01.
**Two things the target does better, deliberately:**
- Only **confirmed** entries count, the same rule the cached
`Customer.goldDebtGrams` / `fiatDebtRial` follow — so the statement's closing
balance agrees with the figure shown everywhere else in the app. Asserted by
the test.
- **SEC-16:** the reference's `detail($id)` took the factor code from the URL
and performed **no ownership check whatsoever** — it never looks at `auth()`
— so any signed-in customer could read any other customer's document by
guessing a code. Here the id is only ever a filter on top of a `customerId`
scope, so someone else's id returns nothing. Tested in both directions.
The reference gated the page on `myStore.hasMCode()`; with no mcode in the
target the gate is simply a session, and the server scopes every row to the
token.
+9
View File
@@ -156,3 +156,12 @@ Severity: `Critical` (money loss / security / data loss) · `High` · `Medium`
| **SEC-15** | Low (reference bug, NOT ported) | REF `Major/CustomerController.php:110-112` | `sendSmsToAdmin()` hardcoded four real personal mobile numbers in the source. | `$admin_mobile = ['0990…','0913…','0912…','0919…'];` | **Not ported.** The target reads `PROFILE_ADMIN_MOBILES` (comma-separated, blank = notify nobody), so no personal number is committed to this repository. |
| **APP-03** | Low (reference bug, NOT ported) | REF `completeProfile.vue:175-181` | `refresh()` called `window.setInterval(() => window.location.reload(), 1000)` — an **unterminated** timer that reloaded the whole page every second forever, not a one-off refresh. | `completeProfile.vue:178-180` | **Not ported.** The target navigates home once after the success dialog. |
| **UPL-01** | Medium (gap, fixed) | TGT `admin-uploads.controller.ts` | The reference let the app upload documents through the same `file/create` the admin panel used, inside its `auth:api-customer` group (`routes/api.php:95`). The target's copy of that route is **admin-guarded**, which no app token can pass — so without a customer-facing upload route, complete_profile could not have worked at all. | `AdminUploadsController` has no `@CustomerAuth()` route | ✅ Added `POST customer/me/documents`, reusing `AdminUploadsService` unchanged so the size limit, MIME whitelist and stored-name scheme are identical on both paths. The uploader is recorded as `null` rather than as an admin, since that column is an AdminUser FK. |
## report — found while porting the page (2026-09-23)
| ID | Severity | Where | Description | Evidence | Suggested fix |
|---|---|---|---|---|---|
| **SEC-16** | High (reference bug, NOT ported) | REF `Customer/TahesabController.php::detail()` | The document-detail endpoint took the factor code straight from the URL and performed **no ownership check at all** — the method never consults `auth()`. Any signed-in customer could read any other customer's accounting document by guessing or enumerating a code. | `public function detail(Request $request, $id)` → proxies `GetHesabDetailByFactorCode?Factor_Code=$id` with no customer scope | **Not ported.** In the target the id is only a filter on top of a `customerId` scope taken from the token, so another customer's id returns nothing. Asserted in both directions by `test-report.cjs` §6. |
| **REP-01** | Medium (documented gap) | REF external Tahesab system vs TGT `LedgerEntry` | The reference's statement carried columns the target has no source for: foreign currency (`rial_V2`/`rial_Kh2`/`tahesabP2`), `vaznPlastik`, `nO_kar` (نام کارساخته), `jens_felez` (جنس فلز) and the external system's internal ids (`gid`/`rec`/`reg`). | `henza_pwa/src/type/accounting.ts`; `AccountingDetail.vue:34-46` | The API returns `null`/zero for these and the UI **omits** the row rather than showing a fabricated value. If the business needs them, they need columns on `LedgerEntry` first. |
| **REP-02** | Low (performance) | TGT `customer-report.service.ts` `summary()` | The running balance makes a row depend on every entry before it, so the whole confirmed ledger for the customer is folded in memory and the page sliced afterwards. Cheap at one customer's own document counts; linear in their history. | `summary()` `findMany` without `take` | If a customer ever accumulates enough entries for it to matter, move the fold to a stored running total written at entry time. |
| **SEC-17** | Medium (reference, not applicable to target) | REF `Customer/TahesabController.php` | The reference calls the external accounting system with `Http::withoutVerifying()` (TLS certificate verification **disabled**) against a bare IP, with a bearer token and an `sfx` secret hardcoded in the source and embedded in the URL. | `->withToken("S3F1P8…")`, `sfx=wcG97tkF…` in four URLs | Not applicable — the target makes no external call. Listed so it is not reintroduced if a Tahesab integration is ever added; the credentials in that reference file should be rotated regardless. |