feat: uživatelsky přívětivější možnost zadání sledovací URL pro Bolt Food
CI / Generate TypeScript types (push) Successful in 13s
CI / Server unit tests (push) Successful in 22s
CI / Build server (push) Successful in 29s
CI / Build client (push) Successful in 37s
CI / Playwright E2E tests (push) Successful in 1m24s
CI / Build and push Docker image (push) Successful in 40s
CI / Notify (push) Successful in 2s
CI / Generate TypeScript types (push) Successful in 13s
CI / Server unit tests (push) Successful in 22s
CI / Build server (push) Successful in 29s
CI / Build client (push) Successful in 37s
CI / Playwright E2E tests (push) Successful in 1m24s
CI / Build and push Docker image (push) Successful in 40s
CI / Notify (push) Successful in 2s
This commit is contained in:
@@ -2,7 +2,7 @@ import { useCallback, useContext, useEffect, useRef, useState } from 'react';
|
||||
import { Alert, Badge, Button, Card, Form, Modal, OverlayTrigger, Table, Tooltip } from 'react-bootstrap';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faTrashCan } from '@fortawesome/free-regular-svg-icons';
|
||||
import { faBasketShopping, faChevronLeft, faChevronRight, faCircleCheck, faClockRotateLeft, faGear, faLock, faLockOpen, faSearch, faUserPlus } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faBasketShopping, faChevronLeft, faChevronRight, faCircleCheck, faClockRotateLeft, faGear, faLock, faLockOpen, faPen, faSearch, faUserPlus } from '@fortawesome/free-solid-svg-icons';
|
||||
import DatePicker, { registerLocale } from 'react-datepicker';
|
||||
import { cs } from 'date-fns/locale';
|
||||
import 'react-datepicker/dist/react-datepicker.css';
|
||||
@@ -43,6 +43,14 @@ function extractBoltToken(input: string): string | null {
|
||||
}
|
||||
}
|
||||
|
||||
/** Zkrátí dlouhý odkaz pro zobrazení v řádku (zachová začátek i konec). */
|
||||
function shortenUrl(url: string, max = 48): string {
|
||||
if (url.length <= max) return url;
|
||||
const head = Math.ceil((max - 1) / 2);
|
||||
const tail = Math.floor((max - 1) / 2);
|
||||
return `${url.slice(0, head)}…${url.slice(url.length - tail)}`;
|
||||
}
|
||||
|
||||
// Český lokál pro date picker (názvy měsíců/dnů, pondělí jako první den)
|
||||
registerLocale('cs', cs);
|
||||
|
||||
@@ -706,7 +714,7 @@ export default function OrderGroupsPage() {
|
||||
/>
|
||||
</div>
|
||||
<div className="d-flex align-items-center gap-1">
|
||||
<small className="text-muted text-nowrap">Bolt odkaz:</small>
|
||||
<small className="text-muted text-nowrap">Bolt odkaz pro sledování:</small>
|
||||
<Form.Control
|
||||
type="text"
|
||||
size="sm"
|
||||
@@ -721,23 +729,60 @@ export default function OrderGroupsPage() {
|
||||
<Button size="sm" variant="outline-secondary" onClick={() => setEditTimes(prev => { const n = { ...prev }; delete n[group.id]; return n; })}>Zrušit</Button>
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
className="d-flex align-items-center gap-3 flex-wrap"
|
||||
style={{ cursor: !isReadOnly && isCreator ? 'pointer' : undefined }}
|
||||
onClick={() => !isReadOnly && isCreator && setEditTimes(prev => ({ ...prev, [group.id]: { orderedAt: group.orderedAt ?? '', deliveryAt: group.deliveryAt ?? '', boltUrl: group.boltTrackingToken ? `${BOLT_SHARE_URL_PREFIX}${group.boltTrackingToken}` : '' } }))}
|
||||
title={!isReadOnly && isCreator ? 'Klikněte pro úpravu časů' : undefined}
|
||||
>
|
||||
<small className="text-muted">
|
||||
Objednáno v: <strong>{group.orderedAt ?? '—'}</strong>
|
||||
</small>
|
||||
<small className="text-muted">
|
||||
Doručení v: <strong>{group.deliveryAt ?? '—'}</strong>
|
||||
{group.boltTrackingToken && (
|
||||
<OverlayTrigger overlay={<Tooltip>Čas doručení se aktualizuje automaticky z Bolt Food</Tooltip>}>
|
||||
<Badge bg="success" className="ms-1">Bolt</Badge>
|
||||
</OverlayTrigger>
|
||||
)}
|
||||
</small>
|
||||
<div className="d-flex align-items-center gap-3 flex-wrap">
|
||||
{(() => {
|
||||
const canEdit = !isReadOnly && isCreator;
|
||||
// Aktivace editačního režimu – stejné chování jako tlačítko s tužkou
|
||||
const startEdit = () => canEdit && setEditTimes(prev => ({ ...prev, [group.id]: { orderedAt: group.orderedAt ?? '', deliveryAt: group.deliveryAt ?? '', boltUrl: group.boltTrackingToken ? `${BOLT_SHARE_URL_PREFIX}${group.boltTrackingToken}` : '' } }));
|
||||
const trackingUrl = group.boltTrackingToken ? `${BOLT_SHARE_URL_PREFIX}${group.boltTrackingToken}` : null;
|
||||
return (
|
||||
<>
|
||||
{canEdit && (
|
||||
<FontAwesomeIcon
|
||||
icon={faPen}
|
||||
className="action-icon"
|
||||
title="Upravit časy a odkaz pro sledování"
|
||||
onClick={startEdit}
|
||||
/>
|
||||
)}
|
||||
<small
|
||||
className="text-muted"
|
||||
style={{ cursor: canEdit ? 'pointer' : undefined }}
|
||||
onClick={startEdit}
|
||||
>
|
||||
Objednáno v: <strong>{group.orderedAt ?? '—'}</strong>
|
||||
</small>
|
||||
<small
|
||||
className="text-muted"
|
||||
style={{ cursor: canEdit ? 'pointer' : undefined }}
|
||||
onClick={startEdit}
|
||||
>
|
||||
Doručení v: <strong>{group.deliveryAt ?? '—'}</strong>
|
||||
{group.boltTrackingToken && (
|
||||
<OverlayTrigger overlay={<Tooltip>Čas doručení se aktualizuje automaticky z Bolt Food</Tooltip>}>
|
||||
<Badge bg="success" className="ms-1">Bolt</Badge>
|
||||
</OverlayTrigger>
|
||||
)}
|
||||
</small>
|
||||
<small className="text-muted text-nowrap">
|
||||
URL pro sledování:{' '}
|
||||
{trackingUrl ? (
|
||||
<a
|
||||
href={trackingUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
title={trackingUrl}
|
||||
onClick={e => e.stopPropagation()}
|
||||
>
|
||||
{shortenUrl(trackingUrl)}
|
||||
</a>
|
||||
) : (
|
||||
<strong>—</strong>
|
||||
)}
|
||||
</small>
|
||||
</>
|
||||
);
|
||||
})()}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
[
|
||||
"Proklik na nabídku podniku ze stránky objednávek"
|
||||
"Proklik na nabídku podniku ze stránky objednávek",
|
||||
"Možnost přidat URL pro sledování stavu doručení pro Bolt Food",
|
||||
"Automatická aktualizace času doručení na základě sledovací URL pro Bolt Food"
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user