Products: create services from the admin
- "New service": from scratch (category, who does it — cleaner, driver, career consultant or docs agent —, fixed price and duration, online, name and description in 5 languages) or as a copy of an existing service (prices, questions, checklist, booking window and question texts copied). Created switched off; delete only without orders; reorder within a category. - "Questions in the order form" builder for fixed-price services: choice, number, text, yes/no, required flag; labels stored as text overrides. - The admin itself now loads text overrides, so new service names show right away; the mini app hides missing optional texts (description, option hints) instead of showing keys. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
0edc6432b7
commit
8866616782
8 files changed
+599
-13
No files matched your search
@@ -1,7 +1,7 @@
|
||||
import { keepPreviousData, useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import type { ParamField, ParamValues } from '@barev/core';
|
||||
import { Button, Card, Center, Chip, Field, Icon, Spinner, Stepper } from '@barev/ui';
|
||||
import { dateKeyToDate, errorText, haptic, navigate, nextDays, useI18n, useLocation, useToast, useTRPC } from '@barev/web';
|
||||
import { tOptional, dateKeyToDate, errorText, haptic, navigate, nextDays, useI18n, useLocation, useToast, useTRPC } from '@barev/web';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { PageHead } from '../lib.tsx';
|
||||
|
||||
@@ -127,7 +127,7 @@ export function OrderForm({ code }: { code: string }) {
|
||||
<main className="app app--plain">
|
||||
<PageHead title={t(`services.${code}.name`)} />
|
||||
<p className="bc-muted" style={{ margin: '-4px 0 0' }}>
|
||||
{t(`services.${code}.description`)}
|
||||
{tOptional(t, `services.${code}.description`)}
|
||||
</p>
|
||||
|
||||
{/* параметры услуги */}
|
||||
@@ -335,7 +335,7 @@ function ParamInput({
|
||||
<button key={o} type="button" className="option" role="radio" aria-checked={value === o} aria-pressed={value === o} onClick={() => onChange(o)}>
|
||||
<span style={{ fontWeight: 700 }}>{t(`params.${serviceCode}.${field.key}.${o}`)}</span>
|
||||
<span className="bc-small bc-muted">
|
||||
{prices?.[o] !== undefined ? t('common.from', { price: amd(prices[o]!) }) : t(`params.${serviceCode}.${field.key}.${o}_hint`)}
|
||||
{prices?.[o] !== undefined ? t('common.from', { price: amd(prices[o]!) }) : tOptional(t, `params.${serviceCode}.${field.key}.${o}_hint`)}
|
||||
</span>
|
||||
</button>
|
||||
))}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import { Button, Card, Field, Icon } from '@barev/ui';
|
||||
import { errorText, haptic, useI18n, useToast, useTRPC } from '@barev/web';
|
||||
import { tOptional, errorText, haptic, useI18n, useToast, useTRPC } from '@barev/web';
|
||||
import { useState } from 'react';
|
||||
import { levelDiscount, PageHead, toneClass, type Level } from '../lib.tsx';
|
||||
|
||||
@@ -31,7 +31,7 @@ export function ServiceRequest({ code }: { code: string }) {
|
||||
<main className="app app--plain">
|
||||
<PageHead title={t(`services.${code}.name`)} />
|
||||
<Card className={`bc-stack ${category ? toneClass(category.code) : ''}`}>
|
||||
<p style={{ margin: 0 }}>{t(`services.${code}.description`)}</p>
|
||||
<p style={{ margin: 0 }}>{tOptional(t, `services.${code}.description`)}</p>
|
||||
{pct > 0 && <div style={{ fontWeight: 700 }}>{t('client.request.yourDiscount', { pct })}</div>}
|
||||
</Card>
|
||||
{sent ? (
|
||||
|
||||
Reference in new issue
Block a user