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
2 changes: 1 addition & 1 deletion .github/workflows/lint-css-files.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ jobs:
run: npm install --only=dev
- name: Run stylelint
run: |
npx stylelint --color "./**/*.css"
npx stylelint --color style.css --config .stylelintrc.json
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1 @@
node_modules/
node_modules/
3 changes: 3 additions & 0 deletions .stylelintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "stylelint-config-standard"
}
60 changes: 59 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,59 @@
Add a readme for your dashboard here. Include content overview, data citations, and any relevant technical details.
# Markets by Transit in New York City

Created by Acharee Sirisan.

## Live website

https://jasach29.github.io/dashboard-project/

## Purpose and audience

This project responds to food access challenges, including those
experienced in food deserts, by helping NYC residents explore
farmers markets and nearby subway or Staten Island Railway
stations. It supports people who rely on public transportation
in choosing a market to visit by showing market locations,
operating hours, seasons, and nearby rail options.

## Decisions this tool supports

- Which farmers market should I visit in my chosen borough?
- What operating hours and season are listed for that market?
- Which nearby subway or Staten Island Railway stations could I investigate for my trip?

## Features

- Filter farmers markets by borough.
- Automatically zoom to the displayed markets.
- Click markets for locations, hours, and seasons.
- Click stations for names and daytime routes.
- Show or hide train stations.
- Operate the borough dropdown using a keyboard.
- Browse a market list that updates with the borough filter.

## Tools

HTML, CSS, JavaScript, Leaflet, and Papa Parse.

## Run locally

Open the project folder in VS Code. Right-click index.html and
select "Open with Live Server."

## Data sources

- [Farmers Markets in New York State](https://data.ny.gov/Economic-Development/Farmers-Markets-in-New-York-State-Map/gfni-eg8a)
- [MTA Subway Stations](https://data.ny.gov/Transportation/MTA-Subway-Stations/39hk-dx4f)
- Basemap: OpenStreetMap contributors.

## Limitations

Farmers markets may operate only on certain days or during
specific seasons. Listed hours and seasons may change or become
outdated, so users should confirm schedules before visiting.

Station points represent station locations rather than individual
entrances. The map does not calculate walking routes or travel
times, show live service, or include buses and ferries. Nearby
stations do not guarantee a convenient or accessible walking
connection. Check transit service before traveling.
153 changes: 153 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// Create a map centered on State Island.
const map = L.map("map");

map.setView([40.7128, -74.0060], 10);

// Add the background map
L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
maxZoom: 19,
attribution: '© OpenStreetMap contributors'
}).addTo(map);

// Add a practice point
const marketLayer = L.layerGroup().addTo(map);
Papa.parse("data/Farmers'_Markets.csv", {
download: true,
header: true,
skipEmptyLines: true,

complete: function(results) {
const nycCounties = ["Richmond", "Kings", "Queens", "Bronx", "New York"
];

results.data.forEach(function(market) {
const latitude = parseFloat(market.Latitude);
const longitude = parseFloat(market.Longitude);

if (
nycCounties.includes(market.County.trim()) &&
Number.isFinite(latitude) &&
Number.isFinite(longitude)
) {
L.marker([latitude, longitude], {
county: market.County.trim(),
marketData: market,
})
.addTo(marketLayer)
.bindPopup(function () {
const popup = document.createElement("div");
popup.textContent= [
market["Market Name"],
"Location: " + market["Market Location"],
"Hours: " + market["Operation Hours"],
"Season: " + market["Operation Season"]
].join("\n");

popup.style.whiteSpace = "pre-line";

return popup;
});
}
});
function updateMarketList() {
const list = document.querySelector("#market-list");
list.replaceChildren();

marketLayer.getLayers().forEach(function (marker) {
const market = marker.options.marketData;
const item = document.createElement("li");

const heading = document.createElement("h3");
heading.textContent = market["Market Name"];

const details = document.createElement("p");
details.textContent = [
"Location: " + market["Market Location"],
"Hours: " + market["Operation Hours"],
"Season: " + market["Operation Season"]
].join(" • ");

item.append(heading, details);
list.append(item);
});
}

updateMarketList();
const allMarketMarkers = marketLayer.getLayers();
const boroughFilter = document.querySelector("#borough-filter");

boroughFilter.addEventListener("change", function () {
const selectedCounty = boroughFilter.value;

marketLayer.clearLayers();

allMarketMarkers.forEach(function (marker) {
if (
selectedCounty === "all" ||
marker.options.county === selectedCounty
) {
marker.addTo(marketLayer);
}
});
updateMarketList();
const visibleMarkers = marketLayer.getLayers();
if (visibleMarkers.length > 0) {
const bounds = L.featureGroup(visibleMarkers).getBounds();

map.fitBounds(bounds, {
padding: [40,40],
maxZoom: 13
});
}
});
},
error: function(error) {
console.error("Could not load CSV: ", error);
}
});
const transitLayer = L.layerGroup().addTo(map);

L.control.layers(null, {
"Subway / Staten Island Railway stations": transitLayer
}, {
collapsed: false
}).addTo(map);
Papa.parse("data/transit_stations.csv", {
download: true,
header: true,
skipEmptyLines: true,
complete: function(results) {
results.data.forEach(function(station) {
const latitude = parseFloat(station["GTFS Latitude"]);
const longitude = parseFloat(station["GTFS Longitude"]);

if (
Number.isFinite(latitude) &&
Number.isFinite(longitude)
) {
L.circleMarker([latitude, longitude], {
radius: 5,
color: "#f05724",
weight: 1,
fillcolor: "#f97316",
fillOpacity: 0.8
})
.addTo(transitLayer)
.bindPopup(function () {
const popup = document.createElement("div");

popup.textContent = [
station["Stop Name"],
"Daytime routes: "+ station["Daytime Routes"]
].join("\n");

popup.style.whiteSpace = "pre-line";
return popup;
});
}
});
},
error: function(error) {
console.error("Could not load stations: ", error);
}
});
Loading