Order card: 'Message provider' and 'Call' buttons, also for a pending offer

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
zabudko-ruandClaude Opus 5.5 committed 2026-10-21 02:32:36 +04:00
1 parent e7de4f5893
commit a848bb13e2
5 files changed
+49 -7

No files matched your search

+32 -5
View File
@@ -419,6 +419,7 @@ function ProviderPanel({ order: d, onChanged, canChat }: { order: OrderData; onC
</div>
{d.provider ? (
<>
<div className="bo-person">
<Avatar name={d.provider.name} id={d.provider.id} size={40} />
<a href={`#/providers/${d.provider.id}`} style={{ minWidth: 0, color: 'inherit', textDecoration: 'none' }}>
@@ -427,13 +428,11 @@ function ProviderPanel({ order: d, onChanged, canChat }: { order: OrderData; onC
{[d.company?.name, d.provider.phone, d.provider.username && `@${d.provider.username}`].filter(Boolean).join(' · ') || '—'}
</span>
</a>
{canChat && (
<button type="button" className="bo-iconbtn" title={t('ord.writeProvider')} aria-label={t('ord.writeProvider')} onClick={() => chat.mutate({ providerId: d.provider!.id })}>
<I name="chats" size={20} />
</button>
)}
</div>
<ContactRow providerId={d.provider.id} phone={d.provider.phone} canChat={canChat} onChat={(id) => chat.mutate({ providerId: id })} busy={chat.isPending} />
</>
) : d.pending ? (
<>
<div className="bo-pendingbox">
{d.pending.auto ? <I name="bot" size={20} /> : <I name="send" size={20} />}
<span className="bo-grow">
@@ -443,6 +442,8 @@ function ProviderPanel({ order: d, onChanged, canChat }: { order: OrderData; onC
</span>
</span>
</div>
{d.pending.providerId && <ContactRow providerId={d.pending.providerId} phone={d.pending.phone} canChat={canChat} onChat={(id) => chat.mutate({ providerId: id })} busy={chat.isPending} />}
</>
) : d.canAssign ? (
<>
<div className="bo-assignbar">
@@ -496,6 +497,32 @@ function ProviderPanel({ order: d, onChanged, canChat }: { order: OrderData; onC
);
}
/** Связаться с исполнителем: чат в рабочем боте и звонок */
function ContactRow({ providerId, phone, canChat, onChat, busy }: { providerId: string; phone: string | null; canChat: boolean; onChat: (id: string) => void; busy: boolean }) {
const { t } = useT();
return (
<div className="bo-contact">
{canChat && (
<button type="button" className="bo-btn bo-btn--sm" onClick={() => onChat(providerId)} disabled={busy}>
<I name="chats" size={16} />
{t('ord.writeProvider')}
</button>
)}
{phone ? (
<a className="bo-btn bo-btn--ghost bo-btn--sm" href={`tel:${phone.replace(/[^\d+]/g, '')}`}>
<I name="phone" size={16} />
{t('ord.call')}
</a>
) : (
<span className="bo-btn bo-btn--ghost bo-btn--sm" aria-disabled="true" title={t('ord.noPhone')} style={{ opacity: 0.45, cursor: 'default' }}>
<I name="phone" size={16} />
{t('ord.call')}
</span>
)}
</div>
);
}
// ───── диалоги ─────
function RescheduleDialog({ order: d, onClose, onDone }: { order: OrderData; onClose: () => void; onDone: () => void }) {