feat: způsob přihlášení a správa obchodů podle konfigurace serveru
CI / Generate TypeScript types (push) Successful in 12s
CI / Server unit tests (push) Successful in 26s
CI / Build server (push) Successful in 32s
CI / Build client (push) Successful in 41s
CI / Playwright E2E tests (push) Successful in 1m47s
CI / Build and push Docker image (push) Successful in 49s
CI / Notify (push) Successful in 2s

This commit is contained in:
batmanisko committed 2026-09-24 09:30:04 +02:00
1 parent 103445dba8
commit 5f54925808
10 files changed
+185 -82

No files matched your search

@@ -6,6 +6,7 @@ import { faArrowsRotate, faPen, faPlus, faUpRightFromSquare, faXmark } from "@fo
import { addStore, deleteStore, updateStore, getStoreMenuStatus, refreshStoreMenu, Store, StoreMenuProvider, StoreScrapeInfo, StoreScrapeStatus } from "../../../../types";
import { getHumanDateTime } from "../../Utils";
import PriceHistory from "../PriceHistory";
import { useAppConfig } from "../../hooks/useGroupLimits";
import { getStoreUrls, storeUrlLabel } from "../../utils/storeUrls";
type Props = {
@@ -52,6 +53,9 @@ export default function StoreAdminModal({ isOpen, onClose, stores, onStoresChang
const [heslo, setHeslo] = useState('');
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
// Server bez admin hesla — správa (přidání/úprava/odebrání/obnovení) nejde, zbývá jen přehled.
// undefined = konfigurace nenačtena, chováme se jako dřív (správa zapnutá).
const adminEnabled = useAppConfig().storeAdmin !== false;
const [scrapeInfo, setScrapeInfo] = useState<Record<string, StoreScrapeInfo>>({});
const [refreshing, setRefreshing] = useState<string | null>(null);
// Rozbalená historie cen („obchod|služba")
@@ -209,6 +213,14 @@ export default function StoreAdminModal({ isOpen, onClose, stores, onStoresChang
</Alert>
)}
{!adminEnabled && (
<Alert variant="info">
Správa obchodů není na tomto serveru zapnutá (chybí <code>ADMIN_PASSWORD</code>).
Seznam obchodů, stav nabídek a historii cen lze jen prohlížet.
</Alert>
)}
{adminEnabled && <>
<Form.Group className="mb-3">
<Form.Label>Admin heslo</Form.Label>
<Form.Control
@@ -239,6 +251,7 @@ export default function StoreAdminModal({ isOpen, onClose, stores, onStoresChang
Přidat
</Button>
</div>
</>}
<h6>Aktuální seznam</h6>
{stores.length === 0 ? (
@@ -307,7 +320,7 @@ export default function StoreAdminModal({ isOpen, onClose, stores, onStoresChang
<span className="text-nowrap text-muted">Menu {PROVIDER_LABELS[p.provider]}:</span>
<span className={className} title={title}>{text}</span>
{/* Zakázané tlačítko nezobrazí tooltip — obalení do span ho zobrazí i bez hesla */}
<OverlayTrigger
{adminEnabled && <OverlayTrigger
placement="top"
overlay={
<Tooltip>
@@ -330,7 +343,7 @@ export default function StoreAdminModal({ isOpen, onClose, stores, onStoresChang
<FontAwesomeIcon icon={faArrowsRotate} spin={refreshing === key} />
</Button>
</span>
</OverlayTrigger>
</OverlayTrigger>}
{p.dishCount > 0 && (
<Button variant="link" size="sm" className="p-0 text-nowrap"
onClick={() => setHistoryOpen(historyOpen === key ? null : key)}>
@@ -343,7 +356,7 @@ export default function StoreAdminModal({ isOpen, onClose, stores, onStoresChang
);
})}
</div>
<div className="d-flex gap-3">
{adminEnabled && <div className="d-flex gap-3">
<FontAwesomeIcon
icon={faPen}
className="action-icon"
@@ -358,7 +371,7 @@ export default function StoreAdminModal({ isOpen, onClose, stores, onStoresChang
onClick={() => handleRemove(s.name)}
style={{ cursor: 'pointer' }}
/>
</div>
</div>}
</ListGroup.Item>
);
})}