Skip to content

Commit b8ce04a

Browse files
feat: show ballots when a division is clicked
1 parent 377f726 commit b8ce04a

File tree

3 files changed

+79
-7
lines changed

3 files changed

+79
-7
lines changed

src/App.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ function handleSearch(results) {
1515
function handleExpandedChange(expanded) {
1616
isResultsExpanded.value = expanded
1717
}
18+
19+
function handleMapSearch(results) {
20+
searchResults.value = results
21+
isResultsExpanded.value = true
22+
}
1823
</script>
1924

2025
<template>
@@ -25,6 +30,7 @@ function handleExpandedChange(expanded) {
2530
<MapView
2631
:searchResults="searchResults"
2732
:isResultsExpanded="isResultsExpanded"
33+
@update:searchResults="handleMapSearch"
2834
/>
2935
<SearchResults
3036
:results="searchResults"

src/components/MapView.vue

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,30 @@ import { ref, onMounted, onUnmounted, watch, nextTick } from 'vue'
33
import { initializeMap, addDivisionLayers, loadDivisionData } from './map/mapConfig'
44
import { highlightMatchedDivisions, fitMapToFeatures } from './map/divisionHighlighting'
55
import { fetchDivisionStats, updateSourceWithCounts } from './map/divisionStats'
6-
import { debounce } from './map/divisionUtils'
6+
import { debounce, divisionWithHyphen } from './map/divisionUtils'
7+
import { createClient } from '@supabase/supabase-js'
78
89
const mapContainer = ref(null)
910
let map = null
1011
12+
// Initialize Supabase client
13+
const supabase = createClient(
14+
import.meta.env.VITE_SUPABASE_URL,
15+
import.meta.env.VITE_SUPABASE_ANON_KEY,
16+
{
17+
auth: {
18+
persistSession: false
19+
}
20+
}
21+
)
22+
1123
// Store highlighted divisions in reactive state
1224
const highlightedDivisions = ref([])
1325
1426
// Store division stats
1527
const divisionStats = ref({})
1628
17-
// Define props for search results
29+
// Define props and emits
1830
const props = defineProps({
1931
searchResults: {
2032
type: Object,
@@ -26,11 +38,41 @@ const props = defineProps({
2638
}
2739
})
2840
41+
const emit = defineEmits(['update:searchResults'])
42+
2943
// Create debounced version of fitMapToFeatures
3044
const debouncedFitMapToFeatures = debounce((map, divisions, element) => {
3145
fitMapToFeatures(map, divisions, element)
3246
}, 300)
3347
48+
// Function to handle division clicks
49+
async function handleDivisionClick(division) {
50+
console.log('Division clicked:', division)
51+
try {
52+
const { data, error } = await supabase
53+
.from('phila_ballots')
54+
.select('name, division, id_number, birth_year, zip, ballot_status_reason')
55+
.eq('division', divisionWithHyphen(division))
56+
.limit(100)
57+
58+
if (error) {
59+
console.error('Supabase search error:', error)
60+
return
61+
}
62+
63+
console.log('Search results:', data)
64+
65+
// Update search results which will automatically update the panel
66+
emit('update:searchResults', {
67+
matches: data,
68+
divisions: [division]
69+
})
70+
71+
} catch (err) {
72+
console.error('Search error:', err)
73+
}
74+
}
75+
3476
// Watch for search results changes
3577
watch(() => props.searchResults, (newResults) => {
3678
console.log('Search results updated:', newResults)
@@ -76,16 +118,34 @@ onMounted(async () => {
76118
updateSourceWithCounts(map, divisionStats.value)
77119
78120
// Add hover interaction
79-
map.on('mousemove', 'divisions-layer', (e) => {
121+
map.on('mousemove', 'divisions-fill', (e) => {
80122
if (e.features.length > 0) {
81123
const division = e.features[0].properties.DIVISION_NUM
82124
map.setFilter('divisions-hover', ['==', ['get', 'DIVISION_NUM'], division])
83125
}
84126
})
85127
86-
map.on('mouseleave', 'divisions-layer', () => {
128+
map.on('mouseleave', 'divisions-fill', () => {
87129
map.setFilter('divisions-hover', ['==', ['get', 'DIVISION_NUM'], ''])
88130
})
131+
132+
// Add click interaction
133+
map.on('click', 'divisions-fill', (e) => {
134+
if (e.features.length > 0) {
135+
const division = e.features[0].properties.DIVISION_NUM
136+
handleDivisionClick(division)
137+
}
138+
})
139+
140+
// Set cursor to pointer when hovering over divisions
141+
map.on('mouseenter', 'divisions-fill', () => {
142+
map.getCanvas().style.cursor = 'pointer'
143+
})
144+
145+
map.on('mouseleave', 'divisions-fill', () => {
146+
map.getCanvas().style.cursor = ''
147+
})
148+
89149
} catch (err) {
90150
console.error('Error loading map data:', err)
91151
}

src/components/SearchResults.vue

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,16 @@ const sortedResults = computed(() => {
1616
return [...props.results.matches].sort((a, b) => a.name.localeCompare(b.name))
1717
})
1818
19-
// Watch for changes in results count to auto-expand/collapse
19+
// Watch for changes in results to auto-expand/collapse
2020
watch(() => props.results.matches.length, (newCount) => {
21-
isExpanded.value = newCount === 1
22-
emit('update:expanded', isExpanded.value)
21+
// Auto-expand if there are any results
22+
if (newCount > 0) {
23+
isExpanded.value = true
24+
emit('update:expanded', true)
25+
} else {
26+
isExpanded.value = false
27+
emit('update:expanded', false)
28+
}
2329
}, { immediate: true })
2430
2531
const toggleExpand = () => {

0 commit comments

Comments
 (0)