fmt
This commit is contained in:
parent
7bc591be2b
commit
f03edb86c1
2 changed files with 38 additions and 3 deletions
|
|
@ -148,7 +148,15 @@ export default function MapPage({
|
||||||
// registered free → REGISTERED_MAX_FILTERS, licensed/admin → unlimited. Hitting the
|
// registered free → REGISTERED_MAX_FILTERS, licensed/admin → unlimited. Hitting the
|
||||||
// cap opens the upgrade modal.
|
// cap opens the upgrade modal.
|
||||||
const isLoggedIn = !!user;
|
const isLoggedIn = !!user;
|
||||||
const filtersUnlimited = user?.subscription === 'licensed' || user?.isAdmin === true;
|
// Screenshot/OG renders are non-interactive previews of a (possibly shared) search.
|
||||||
|
// They go through the server's internal-request exemption, so they must render the
|
||||||
|
// full filter set rather than the capped demo view — otherwise a 4–5-filter shared
|
||||||
|
// search is silently trimmed to the anonymous cap (3) in the generated preview image.
|
||||||
|
const filtersUnlimited =
|
||||||
|
screenshotMode === true ||
|
||||||
|
ogMode === true ||
|
||||||
|
user?.subscription === 'licensed' ||
|
||||||
|
user?.isAdmin === true;
|
||||||
const effectiveFilterCap = isLoggedIn ? REGISTERED_MAX_FILTERS : DEMO_MAX_FILTERS;
|
const effectiveFilterCap = isLoggedIn ? REGISTERED_MAX_FILTERS : DEMO_MAX_FILTERS;
|
||||||
const filterLimit = filtersUnlimited ? null : effectiveFilterCap;
|
const filterLimit = filtersUnlimited ? null : effectiveFilterCap;
|
||||||
// On a shared link, non-paying users may view and adjust the shared filters but
|
// On a shared link, non-paying users may view and adjust the shared filters but
|
||||||
|
|
@ -263,6 +271,14 @@ export default function MapPage({
|
||||||
|
|
||||||
const handleAiFilterSubmit = useCallback(
|
const handleAiFilterSubmit = useCallback(
|
||||||
async (query: string) => {
|
async (query: string) => {
|
||||||
|
// On a shared link, non-paying users may adjust the shared filters but not build
|
||||||
|
// a new set. The AI box is a "build me a search" tool (and it also drives
|
||||||
|
// travel-time entries, which bypass the per-add lock), so block it outright here
|
||||||
|
// — mirroring handleAddTravelTimeEntry — and surface the upsell instead.
|
||||||
|
if (lockFilterAdds) {
|
||||||
|
handleFilterLimitReached();
|
||||||
|
return;
|
||||||
|
}
|
||||||
const context = {
|
const context = {
|
||||||
filters,
|
filters,
|
||||||
// Send the resolved variant so the AI sees the actual server mode in use,
|
// Send the resolved variant so the AI sees the actual server mode in use,
|
||||||
|
|
@ -351,6 +367,8 @@ export default function MapPage({
|
||||||
fetchAiFilters,
|
fetchAiFilters,
|
||||||
filters,
|
filters,
|
||||||
filtersUnlimited,
|
filtersUnlimited,
|
||||||
|
lockFilterAdds,
|
||||||
|
handleFilterLimitReached,
|
||||||
getMobileMapFlyToOptions,
|
getMobileMapFlyToOptions,
|
||||||
handleSetEntries,
|
handleSetEntries,
|
||||||
handleSetFilters,
|
handleSetFilters,
|
||||||
|
|
@ -707,10 +725,13 @@ export default function MapPage({
|
||||||
// link adds are blocked regardless of count, so don't auto-clear there — the user
|
// link adds are blocked regardless of count, so don't auto-clear there — the user
|
||||||
// dismisses it themselves. Prevents a stale flag from resurfacing spuriously.
|
// dismisses it themselves. Prevents a stale flag from resurfacing spuriously.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (filtersUnlimited || (!lockFilterAdds && Object.keys(filters).length < effectiveFilterCap)) {
|
if (
|
||||||
|
filtersUnlimited ||
|
||||||
|
(!lockFilterAdds && Object.keys(filters).length + entries.length < effectiveFilterCap)
|
||||||
|
) {
|
||||||
setFilterLimitHit(false);
|
setFilterLimitHit(false);
|
||||||
}
|
}
|
||||||
}, [filtersUnlimited, lockFilterAdds, effectiveFilterCap, filters]);
|
}, [filtersUnlimited, lockFilterAdds, effectiveFilterCap, filters, entries]);
|
||||||
|
|
||||||
const handleUpgradeClick = useCallback(() => {
|
const handleUpgradeClick = useCallback(() => {
|
||||||
onNavigateTo('pricing');
|
onNavigateTo('pricing');
|
||||||
|
|
|
||||||
|
|
@ -695,6 +695,20 @@ export function useFilters({
|
||||||
// per-add path). Without this, an unlicensed user could end up with >5 filters,
|
// per-add path). Without this, an unlicensed user could end up with >5 filters,
|
||||||
// which the server then rejects (400), breaking the map.
|
// which the server then rejects (400), breaking the map.
|
||||||
let next = newFilters;
|
let next = newFilters;
|
||||||
|
// On a shared link (lockAdds), a non-paying user may adjust the shared filters
|
||||||
|
// but not introduce new keys — enforce that on bulk sets too, not just in the
|
||||||
|
// per-add path, so the AI/bulk path can't be used to build a fresh set on a
|
||||||
|
// shared link. Keep only keys already present; signal if any were dropped.
|
||||||
|
if (lockAddsRef.current) {
|
||||||
|
const current = filtersRef.current;
|
||||||
|
const restricted = Object.fromEntries(
|
||||||
|
Object.entries(next).filter(([name]) => name in current)
|
||||||
|
);
|
||||||
|
if (Object.keys(restricted).length !== Object.keys(next).length) {
|
||||||
|
onFilterLimitReachedRef.current?.();
|
||||||
|
}
|
||||||
|
next = restricted;
|
||||||
|
}
|
||||||
const limit = filterLimitRef.current;
|
const limit = filterLimitRef.current;
|
||||||
if (limit != null && Object.keys(next).length > limit) {
|
if (limit != null && Object.keys(next).length > limit) {
|
||||||
next = Object.fromEntries(Object.entries(next).slice(0, limit));
|
next = Object.fromEntries(Object.entries(next).slice(0, limit));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue