forked from jsnbuchanan/crowd-funder-for-time-pwa
Fix: added back search area preview
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<section
|
<section
|
||||||
v-if="isRegistered"
|
|
||||||
id="sectionSearchLocation"
|
id="sectionSearchLocation"
|
||||||
class="bg-slate-100 rounded-md overflow-hidden px-4 py-4 mt-8 mb-8"
|
class="bg-slate-100 rounded-md overflow-hidden px-4 py-4 mt-8 mb-8"
|
||||||
aria-labelledby="searchLocationHeading"
|
aria-labelledby="searchLocationHeading"
|
||||||
@@ -8,28 +7,118 @@
|
|||||||
<h2 id="searchLocationHeading" class="mb-2 font-bold">
|
<h2 id="searchLocationHeading" class="mb-2 font-bold">
|
||||||
Location for Searches
|
Location for Searches
|
||||||
</h2>
|
</h2>
|
||||||
<div v-if="searchAreaLabel" class="mb-2">
|
|
||||||
<span class="text-slate-700">Current Area: </span>
|
<!-- Read-only map display when search area is set -->
|
||||||
<span class="font-mono">{{ searchAreaLabel }}</span>
|
<div v-if="searchBox" class="mb-4 aspect-video">
|
||||||
|
<l-map
|
||||||
|
ref="map"
|
||||||
|
:center="mapCenter"
|
||||||
|
:zoom="mapZoom"
|
||||||
|
class="!z-40 rounded-md"
|
||||||
|
>
|
||||||
|
<l-tile-layer
|
||||||
|
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||||
|
layer-type="base"
|
||||||
|
name="OpenStreetMap"
|
||||||
|
/>
|
||||||
|
<l-rectangle
|
||||||
|
:bounds="mapBounds"
|
||||||
|
:weight="2"
|
||||||
|
color="#3b82f6"
|
||||||
|
fill-color="#3b82f6"
|
||||||
|
fill-opacity="0.2"
|
||||||
|
/>
|
||||||
|
</l-map>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="w-full text-md bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-4 py-2 rounded-md"
|
class="w-full text-md bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-4 py-2 rounded-md"
|
||||||
@click="$router.push({ name: 'search-area' })"
|
@click="navigateToSearchArea"
|
||||||
>
|
>
|
||||||
Set Search Area...
|
{{ searchBox ? "Change Search Area..." : "Set Search Area..." }}
|
||||||
</button>
|
</button>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Vue, Prop, Emit } from "vue-facing-decorator";
|
import "leaflet/dist/leaflet.css";
|
||||||
|
import { Component, Vue, Prop } from "vue-facing-decorator";
|
||||||
|
import { LMap, LRectangle, LTileLayer } from "@vue-leaflet/vue-leaflet";
|
||||||
|
import { Router } from "vue-router";
|
||||||
|
import { BoundingBox } from "../db/tables/settings";
|
||||||
|
|
||||||
@Component({ name: "LocationSearchSection" })
|
@Component({
|
||||||
|
name: "LocationSearchSection",
|
||||||
|
components: {
|
||||||
|
LMap,
|
||||||
|
LRectangle,
|
||||||
|
LTileLayer,
|
||||||
|
},
|
||||||
|
})
|
||||||
export default class LocationSearchSection extends Vue {
|
export default class LocationSearchSection extends Vue {
|
||||||
@Prop({ required: true }) isRegistered!: boolean;
|
$router!: Router;
|
||||||
@Prop({ required: false }) searchAreaLabel?: string;
|
|
||||||
|
|
||||||
@Emit("set-search-area")
|
@Prop({ required: false }) searchBox?: {
|
||||||
setSearchArea() {}
|
name: string;
|
||||||
|
bbox: BoundingBox;
|
||||||
|
} | null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigate to search area management page
|
||||||
|
*/
|
||||||
|
navigateToSearchArea() {
|
||||||
|
this.$router.push({ name: "search-area" });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computed property for map center coordinates
|
||||||
|
*/
|
||||||
|
get mapCenter(): [number, number] {
|
||||||
|
if (!this.searchBox?.bbox) {
|
||||||
|
return [0, 0];
|
||||||
|
}
|
||||||
|
const bbox = this.searchBox.bbox;
|
||||||
|
const centerLat = (bbox.maxLat + bbox.minLat) / 2;
|
||||||
|
const centerLong = (bbox.eastLong + bbox.westLong) / 2;
|
||||||
|
return [centerLat, centerLong];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computed property for map zoom level
|
||||||
|
*/
|
||||||
|
get mapZoom(): number {
|
||||||
|
if (!this.searchBox?.bbox) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
// Calculate appropriate zoom based on bounding box size
|
||||||
|
const bbox = this.searchBox.bbox;
|
||||||
|
const latDiff = bbox.maxLat - bbox.minLat;
|
||||||
|
const longDiff = bbox.eastLong - bbox.westLong;
|
||||||
|
const maxDiff = Math.max(latDiff, longDiff);
|
||||||
|
|
||||||
|
// Simple zoom calculation - adjust as needed
|
||||||
|
if (maxDiff > 10) return 4;
|
||||||
|
if (maxDiff > 5) return 6;
|
||||||
|
if (maxDiff > 1) return 8;
|
||||||
|
if (maxDiff > 0.1) return 10;
|
||||||
|
return 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computed property for map bounds
|
||||||
|
*/
|
||||||
|
get mapBounds(): [[number, number], [number, number]] {
|
||||||
|
if (!this.searchBox?.bbox) {
|
||||||
|
return [
|
||||||
|
[0, 0],
|
||||||
|
[0, 0],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
const bbox = this.searchBox.bbox;
|
||||||
|
return [
|
||||||
|
[bbox.minLat, bbox.westLong],
|
||||||
|
[bbox.maxLat, bbox.eastLong],
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -144,9 +144,7 @@
|
|||||||
<PushNotificationPermission ref="pushNotificationPermission" />
|
<PushNotificationPermission ref="pushNotificationPermission" />
|
||||||
|
|
||||||
<LocationSearchSection
|
<LocationSearchSection
|
||||||
:is-registered="isRegistered"
|
:search-box="searchBox"
|
||||||
:search-area-label="searchAreaLabel"
|
|
||||||
@set-search-area="onSetSearchArea"
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- User Profile -->
|
<!-- User Profile -->
|
||||||
@@ -781,7 +779,10 @@ import {
|
|||||||
NotificationIface,
|
NotificationIface,
|
||||||
} from "../constants/app";
|
} from "../constants/app";
|
||||||
import { Contact } from "../db/tables/contacts";
|
import { Contact } from "../db/tables/contacts";
|
||||||
import { DEFAULT_PASSKEY_EXPIRATION_MINUTES } from "../db/tables/settings";
|
import {
|
||||||
|
DEFAULT_PASSKEY_EXPIRATION_MINUTES,
|
||||||
|
BoundingBox,
|
||||||
|
} from "../db/tables/settings";
|
||||||
import { EndorserRateLimits, ImageRateLimits } from "../interfaces";
|
import { EndorserRateLimits, ImageRateLimits } from "../interfaces";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -856,6 +857,7 @@ export default class AccountViewView extends Vue {
|
|||||||
hideRegisterPromptOnNewContact: boolean = false;
|
hideRegisterPromptOnNewContact: boolean = false;
|
||||||
isRegistered: boolean = false;
|
isRegistered: boolean = false;
|
||||||
isSearchAreasSet: boolean = false;
|
isSearchAreasSet: boolean = false;
|
||||||
|
searchBox: { name: string; bbox: BoundingBox } | null = null;
|
||||||
partnerApiServer: string = DEFAULT_PARTNER_API_SERVER;
|
partnerApiServer: string = DEFAULT_PARTNER_API_SERVER;
|
||||||
partnerApiServerInput: string = DEFAULT_PARTNER_API_SERVER;
|
partnerApiServerInput: string = DEFAULT_PARTNER_API_SERVER;
|
||||||
passkeyExpirationDescription: string = "";
|
passkeyExpirationDescription: string = "";
|
||||||
@@ -1015,6 +1017,7 @@ export default class AccountViewView extends Vue {
|
|||||||
!!settings.hideRegisterPromptOnNewContact;
|
!!settings.hideRegisterPromptOnNewContact;
|
||||||
this.isRegistered = !!settings?.isRegistered;
|
this.isRegistered = !!settings?.isRegistered;
|
||||||
this.isSearchAreasSet = !!settings.searchBoxes;
|
this.isSearchAreasSet = !!settings.searchBoxes;
|
||||||
|
this.searchBox = settings.searchBoxes?.[0] || null;
|
||||||
this.notifyingNewActivity = !!settings.notifyingNewActivityTime;
|
this.notifyingNewActivity = !!settings.notifyingNewActivityTime;
|
||||||
this.notifyingNewActivityTime = settings.notifyingNewActivityTime || "";
|
this.notifyingNewActivityTime = settings.notifyingNewActivityTime || "";
|
||||||
this.notifyingReminder = !!settings.notifyingReminderTime;
|
this.notifyingReminder = !!settings.notifyingReminderTime;
|
||||||
@@ -1663,22 +1666,6 @@ export default class AccountViewView extends Vue {
|
|||||||
this.notify.info("Share dialog not yet implemented.");
|
this.notify.info("Share dialog not yet implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
get searchAreaLabel(): string {
|
|
||||||
// Return a string representing the current search area, or blank if not set
|
|
||||||
// Example: return this.searchAreaName || '';
|
|
||||||
return this.isSearchAreasSet ? "Custom Area Set" : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
onSetSearchArea() {
|
|
||||||
// Call the existing logic for setting the search area, e.g., open the dialog
|
|
||||||
this.openSearchAreaDialog();
|
|
||||||
}
|
|
||||||
|
|
||||||
openSearchAreaDialog() {
|
|
||||||
// TODO: Implement search area dialog logic
|
|
||||||
this.notify.info("Search area dialog not yet implemented.");
|
|
||||||
}
|
|
||||||
|
|
||||||
onRecheckLimits() {
|
onRecheckLimits() {
|
||||||
this.checkLimits();
|
this.checkLimits();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user