Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 58 additions & 89 deletions app/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React, { useEffect, useRef, useState } from "react";
import React, { useRef, useState } from "react";
import { View, StyleSheet, Alert } from "react-native";
import type { Region } from "react-native-maps";
import MapView, { Circle, PROVIDER_GOOGLE } from "react-native-maps";
import { Circle, Marker } from "react-native-maps";
import MapView from "react-native-map-clustering";
import type { BBox, GeoJsonProperties } from "geojson";
import type { PointFeature } from "supercluster";
import useSupercluster from "use-supercluster";
import MarkerWithWrapper from "@/components/MarkerWithWrapper";
import jobs from "@/constants/jobs.json";
import { SearchJobAdRo } from "@/models";
import { Marker as MarkerMap } from "@/components/Marker";

export interface PointProperties {
cluster: boolean;
Expand Down Expand Up @@ -57,7 +57,8 @@ const Map = () => {
const { latDelta, lonDelta } = calculateDeltas(latitude, 75);

// TODO: This shouldn't need to be sliced!
const searchResultJobAds = jobs.searchJobAds.slice(0, 300);
// DONE
const searchResultJobAds = jobs.searchJobAds;

const regionToBoundingBox = (region: Region): BBox => {
let lngD: number;
Expand Down Expand Up @@ -92,112 +93,80 @@ const Map = () => {
setZoom(camera?.zoom ?? 10);
};

const points = searchResultJobAds.map((searchJobAd) => {
const loc = searchJobAd.primaryLocation;

return {
type: "Feature",
properties: {
job: searchJobAd.jobAd,
cluster: false,
color: "blue",
searchJobAd,
},
geometry: {
type: "Point",
coordinates: [loc.location.lng, loc.location.lat],
},
} as PointWithProperties;
});

const { clusters, supercluster } = useSupercluster({
points,
bounds,
zoom,
options: {
radius: 60,
maxZoom: 25,
},
});

function onPointPress() {
Alert.alert(`Clicked on point!`);
}

const renderMarkers = () => {
console.log(`points: ${points.length}`);
return points.map((point) => {
const initialRegion = {
latitude: DEFAULT_MAP_LOCATION.lat,
longitude: DEFAULT_MAP_LOCATION.lng,
latitudeDelta: latDelta,
longitudeDelta: lonDelta,
};
function renderRandomMarkers() {
return searchResultJobAds.map((item, index) => {
const loc = item.primaryLocation;
const company = item.jobAd.company;
return (
<MarkerWithWrapper
key={point.properties.searchJobAd.combinedId}
isSelected={false}
onPointPress={onPointPress}
point={point}
zoom={zoom}
></MarkerWithWrapper>
<Marker
onPress={onPointPress}
key={index}
coordinate={{
latitude: loc.location.lat,
longitude: loc.location.lng,
}}>
<MarkerMap
companyLogo={company.logoImg?.variants.min_dim_64_url ?? null}
/>
</Marker>
);
});
};
}

return (
<View
style={{
flex: 1,
}}
>
<View
style={{
flex: 1,
position: "relative",
}}>
<MapView
ref={mapRef}
style={styles.map}
initialRegion={initialRegion}
onRegionChangeComplete={onRegionChangeComplete}
camera={{
center: {
latitude: DEFAULT_MAP_LOCATION.lat,
longitude: DEFAULT_MAP_LOCATION.lng,
},
pitch: 0,
heading: 0,
zoom: 10,
}}
>
<MapView
ref={mapRef}
style={styles.map}
provider={PROVIDER_GOOGLE}
onRegionChangeComplete={onRegionChangeComplete}
initialRegion={{
rotateEnabled={false}
zoomEnabled={true}
pitchEnabled={false}
zoomControlEnabled={true}
showsUserLocation={true}
showsMyLocationButton={false}>
<Circle
center={{
latitude: DEFAULT_MAP_LOCATION.lat,
longitude: DEFAULT_MAP_LOCATION.lng,
latitudeDelta: latDelta,
longitudeDelta: lonDelta,
}}
camera={{
center: {
latitude: DEFAULT_MAP_LOCATION.lat,
longitude: DEFAULT_MAP_LOCATION.lng,
},
pitch: 0,
heading: 0,
zoom: 10,
}}
rotateEnabled={false}
zoomEnabled={true}
pitchEnabled={false}
zoomControlEnabled={true}
showsUserLocation={true}
showsMyLocationButton={false}
>
<Circle
center={{
latitude: DEFAULT_MAP_LOCATION.lat,
longitude: DEFAULT_MAP_LOCATION.lng,
}}
radius={1000 * 50}
strokeWidth={2}
strokeColor="blue"
/>

{renderMarkers()}
</MapView>
</View>
radius={1000 * 50}
strokeWidth={2}
strokeColor="blue"
/>
{renderRandomMarkers()}
</MapView>
</View>
);
};

const styles = StyleSheet.create({
map: {
flex: 1,
width: "100%",
height: "100%",
},
cluster: {
borderRadius: 100,
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"version": "1.0.0",
"scripts": {
"start": "expo start",
"postinstall": "node postinstall.js",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
Expand All @@ -28,6 +29,7 @@
"react": "18.2.0",
"react-dom": "18.2.0",
"react-native": "0.73.6",
"react-native-map-clustering": "^3.4.2",
"react-native-maps": "1.10.0",
"react-native-safe-area-context": "4.8.2",
"react-native-screens": "~3.29.0",
Expand Down
35 changes: 35 additions & 0 deletions postinstall.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const chalk = require("chalk");
const { readFile, writeFile, copyFile } = require("fs").promises;

console.log(chalk.green("here"));

function log(...args) {
console.log(chalk.yellow("[react-native-maps]"), ...args);
}

reactNativeMaps = async function () {
log(
"📦 Creating web compatibility of react-native-maps using an empty module loaded on web builds"
);
const modulePath = "node_modules/react-native-maps";
await writeFile(
`${modulePath}/lib/index.web.js`,
"module.exports = {}",
"utf-8"
);
await copyFile(
`${modulePath}/lib/index.d.ts`,
`${modulePath}/lib/index.web.d.ts`
);
const pkg = JSON.parse(await readFile(`${modulePath}/package.json`));
pkg["react-native"] = "lib/index.js";
pkg["main"] = "lib/index.web.js";
await writeFile(
`${modulePath}/package.json`,
JSON.stringify(pkg, null, 2),
"utf-8"
);
log("✅ script ran successfully");
};

reactNativeMaps();
Loading