diff --git a/package.json b/package.json index 9449491..bc44243 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "scripts": { "start": "react-scripts start", "build": "react-scripts build", + "build-localhost": "PUBLIC_URL=/ react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" }, diff --git a/src/assets/data/poi.geojson b/src/assets/data/poi.geojson new file mode 100644 index 0000000..101b654 --- /dev/null +++ b/src/assets/data/poi.geojson @@ -0,0 +1 @@ +{"type": "FeatureCollection", "features": [{"id": "0", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "肉老大頂級肉品涮涮鍋-敦南創始店", "address": "台北市大安區敦化南路二段331巷16號", "description": "以下優惠二擇一:\n內用 9折優惠、外帶 95折優惠\n4人同行送一盤7oz肉盤 (豬or牛)\n打卡送肉、蝦", "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [121.549826, 25.022635]}}, {"id": "1", "type": "Feature", "properties": {"status": "Inactive", "class": "餐廳", "subclass": "general_restaurant", "name": "肉老大頂級肉品涮涮鍋-東區店", "address": "台北市大安區敦化南路一段190巷48號", "description": null, "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [121.54673, 25.042521]}}, {"id": "2", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "肉老大頂級肉品涮涮鍋-淡水店", "address": "新北市淡水區民權路157號", "description": null, "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [121.460055, 25.136078]}}, {"id": "3", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "肉老大頂級肉品涮涮鍋-中和店", "address": "新北市中和區中和路380號2樓", "description": null, "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [121.510757, 25.002113]}}, {"id": "4", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "EZFive", "address": "台北市大安區安和路二段211號", "description": "招待爆米花或洋芋片", "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [121.5502, 25.026074]}}, {"id": "5", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "青沐初食", "address": "台北市大安區敦化南路二段265巷7號", "description": "平日9折優惠(不含套餐),限持員工證本人使用", "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [121.549544, 25.02548]}}, {"id": "6", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "burger", "name": "漢堡王 敦化店", "address": "台北市大安區敦化南路二段164號", "description": "提供套餐薯條升級\n早餐套餐咖啡升級研磨咖啡", "expiration": "2022-10-31"}, "geometry": {"type": "Point", "coordinates": [121.548338, 25.024428]}}, {"id": "7", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "西羅伐", "address": "台北市大安區敦化南路二段146巷1號", "description": "現職員工9折優惠", "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [121.548157, 25.025538]}}, {"id": "8", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "japanese_restaurant", "name": "竹鶴日本料理店", "address": "新竹縣竹北市光明一路175號1樓", "description": "9折優惠(現金消費)\n95折優惠(刷卡消費)", "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [121.014685, 24.830345]}}, {"id": "9", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "彭家涼麵", "address": "台北市大安區嘉興街399號1樓", "description": "全品項9折(特惠組合除外)", "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [121.551145, 25.021528]}}, {"id": "10", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "bistro", "name": "Le Chamber", "address": "台北市大安區敦化南路二段152號之一", "description": "- 用餐2~4人送一份蒜味薯條,4人以上送兩份蒜味薯條 (星期日,二,三,四需滿低消$500/位, 其他為$1000/位)\n- 25人包場75折 (兩小時, 包場費可折抵餐費)", "expiration": "2023-04-13"}, "geometry": {"type": "Point", "coordinates": [121.548167, 25.025189]}}, {"id": "11", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "炊牛王牛肉麵專賣店", "address": "新竹市東區新莊街111號", "description": "每項單品減10元(小菜除外)", "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [121.016717, 24.786749]}}, {"id": "12", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "金色三麥-台北美麗華店", "address": "台北市中山區敬業三路20號5F", "description": "LINE\n會員消費贈送\n雙倍點數", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [121.556712, 25.082926]}}, {"id": "13", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "金色三麥-台北京站店", "address": "台北市大同區承德路一段1號4F", "description": "LINE\n會員消費贈送\n雙倍點數", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [121.516784, 25.04909]}}, {"id": "14", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "金色三麥-信義誠品店", "address": "台北市信義區松高路11號", "description": "LINE\n會員消費贈送\n雙倍點數", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [121.565242, 25.039515]}}, {"id": "15", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "金色三麥-南港CITYLINK店", "address": "台北市南港區忠孝東路七段299號C棟 1樓", "description": "LINE\n會員消費贈送\n雙倍點數", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [121.604792, 25.052364]}}, {"id": "16", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "金色三麥-板橋大遠百店", "address": "新北市板橋區新站路28號9樓", "description": "LINE\n會員消費贈送\n雙倍點數", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [121.466627, 25.013622]}}, {"id": "17", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "金色三麥-新莊晶冠店", "address": "新北市新莊區五工路66號", "description": "LINE\n會員消費贈送\n雙倍點數", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [121.458702, 25.063818]}}, {"id": "18", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "金色三麥-新竹巨城店PARK15", "address": "新竹市東區中央路229號7樓", "description": "LINE\n會員消費贈送\n雙倍點數", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [120.974931, 24.809666]}}, {"id": "19", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "金色三麥-中壢SOGO店", "address": "桃園市中壢區元化路357號8樓", "description": "LINE\n會員消費贈送\n雙倍點數", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [121.223533, 24.962685]}}, {"id": "20", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "金色三麥-台中市政店", "address": "台中市西屯區市政路20號", "description": "LINE\n會員消費贈送\n雙倍點數", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [120.645394, 24.156264]}}, {"id": "21", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "金色三麥-台中勤美店", "address": "台中市西區公益路68號B1", "description": "LINE\n會員消費贈送\n雙倍點數", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [120.663866, 24.151278]}}, {"id": "22", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "金色三麥-台南南紡店", "address": "台南市東區中華東路一段366號5F", "description": "LINE\n會員消費贈送\n雙倍點數", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [120.233334, 22.990772]}}, {"id": "23", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "金色三麥-高雄義大店", "address": "高雄市大樹區學城路一段12號A區5F", "description": "LINE\n會員消費贈送\n雙倍點數", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [120.406614, 22.729832]}}, {"id": "24", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "金色三麥-漢神巨蛋店", "address": "高雄市左營區博愛二路777號4樓", "description": "LINE\n會員消費贈送\n雙倍點數", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [120.303118, 22.670155]}}, {"id": "25", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "UMAMI 金色三麥 - 微風南山店", "address": "台北市信義區松智路17號7樓", "description": "1. 門市內用消費享 原價 9 折優惠。\n2. LINE 會員消費贈送雙倍點數。\n3. 以上 優惠 二擇 一, 套餐 與其他優 惠皆不併用", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [121.565774, 25.034434]}}, {"id": "26", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "cafe", "name": "Petit Doux 微兜 Café-永康店", "address": "台北市大安區信義路二段 198 巷 7-3 號1樓", "description": "1. 門市內用消費單筆滿 500 元 不含套餐 )),即贈主廚私房菜乙份,本優惠 不累贈 。\n2. 與其它優惠皆不併用。", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [121.530682, 25.032665]}}, {"id": "27", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "cafe", "name": "Petit Doux 微兜 Café-北車京站店", "address": "台北市大同區承德路一段1號1樓", "description": "1. 門市內用消費單筆滿 500 元 不含套餐 )),即贈主廚私房菜乙份,本優惠 不累贈 。\n2. 與其它優惠皆不併用。", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [121.516784, 25.04909]}}, {"id": "28", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "cafe", "name": "Petit Doux 微兜 Café-小碧潭店", "address": "新北市新店區中央路157號5樓", "description": "1. 門市內用消費單筆滿 500 元 不含套餐 )),即贈主廚私房菜乙份,本優惠 不累贈 。\n2. 與其它優惠皆不併用。", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [121.530551, 24.972512]}}, {"id": "29", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "cafe", "name": "Petit Doux 微兜 Café-SOGO忠孝店", "address": "台北市忠孝東路四段45號11樓", "description": "1. 門市內用消費單筆滿 500 元 不含套餐 )),即贈主廚私房菜乙份,本優惠 不累贈 。\n2. 與其它優惠皆不併用。", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [121.544883, 25.041902]}}, {"id": "30", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "cafe", "name": "Petit Doux 微兜 Café-漢神巨蛋店", "address": "高雄市左營區博愛二路777號4樓", "description": "1. 門市內用消費單筆滿 500 元 不含套餐 )),即贈主廚私房菜乙份,本優惠 不累贈 。\n2. 與其它優惠皆不併用。", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [120.303118, 22.670155]}}, {"id": "31", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "cake", "name": "BAC cake sweets-台北站前凱薩門市", "address": "台北市中正區忠孝西路一段38號 ", "description": "1. 購買 6 吋以上生日蛋糕享 9 折優惠,如需宅配運費另計。\n2. 與其它優惠皆不併用", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [121.516436, 25.046215]}}, {"id": "32", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "cake", "name": "BAC cake sweets-台北忠孝光復門市", "address": "台北市光復南路240巷23號", "description": "1. 購買 6 吋以上生日蛋糕享 9 折優惠,如需宅配運費另計。\n2. 與其它優惠皆不併用", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [121.556467, 25.040658]}}, {"id": "33", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "cake", "name": "BAC cake sweets-台北忠孝Sogo門市", "address": "台北市忠孝東路四段45號B1", "description": "1. 購買 6 吋以上生日蛋糕享 9 折優惠,如需宅配運費另計。\n2. 與其它優惠皆不併用", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [121.544883, 25.041902]}}, {"id": "34", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "cake", "name": "BAC cake sweets-台中勤美門市", "address": "台中市西區公益路68號1樓", "description": "1. 購買 6 吋以上生日蛋糕享 9 折優惠,如需宅配運費另計。\n2. 與其它優惠皆不併用", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [120.663866, 24.151278]}}, {"id": "35", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "咖哩樹-台北京站店", "address": "台北市大同區承德路一段1號B3F (食樂大道)", "description": "憑員工識別證 消費享免費升級套餐", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [121.516784, 25.04909]}}, {"id": "36", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "咖哩樹-板橋環球店", "address": "新北市板橋區縣民大道二段七號B1F (美食天地)", "description": "憑員工識別證 消費享免費升級套餐", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [121.463635, 25.01433]}}, {"id": "37", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "咖哩樹-桃園A19店", "address": "桃園市中壢區高鐵南路二段352號3F (運動 ‧ 品食尚)", "description": "憑員工識別證 消費享免費升級套餐", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [121.202935, 25.002445]}}, {"id": "38", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "咖哩樹-中壢SOGO店", "address": "桃園市中壢區元化路357號B1F (美食廣場)", "description": "憑員工識別證 消費享免費升級套餐", "expiration": "2022-12-31"}, "geometry": {"type": "Point", "coordinates": [121.223533, 24.962685]}}, {"id": "39", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "drink", "name": "悠悠河畔", "address": "台北市大安區樂業街50號1樓", "description": "a.單杯飲品95折\nb.十杯飲品以上9折", "expiration": null}, "geometry": {"type": "Point", "coordinates": [121.549751, 25.022852]}}, {"id": "40", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "drink", "name": "龜記-大安信義店", "address": "台北市大安區信義路三段192號", "description": "50杯95折,100杯9折\n現場外帶自取滿百折10元,以此類推", "expiration": null}, "geometry": {"type": "Point", "coordinates": [121.543006, 25.03319]}}, {"id": "41", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "drink", "name": "山焙-和平臥龍店", "address": "10670台北市大安區和平東路二段363號", "description": "a. 自取或外帶:中杯冷飲享免費升級大杯;熱飲享95折優惠。 \nb. 外送:買10杯送1杯(以最低價飲品做為贈送) \n以上優惠須於訂購時主動出示(自取電話告知)員工識別證;現場及自取購買每張識別證可購買上限為5杯為限。", "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [121.5464319, 25.0248104274316]}}, {"id": "42", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "drink", "name": "茶三小", "address": "106台北市大安區和平東路三段123號", "description": "a. 全品項9折優惠\nb. 提前一天預訂外送滿300,88折\nc. 提前一天預訂自取滿300,87折", "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [121.5517288, 25.0246272]}}, {"id": "43", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "bread", "name": "麥將軍烘焙", "address": "106台北市大安區和平東路二段285號", "description": "消費滿百 出示貴公司相關證件 打九折, 優惠內容不包含餐盒、節慶禮盒、特價商品及不與活動併用。", "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [121.5445601, 25.0249521]}}, {"id": "44", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "shop", "name": "台灣好漁", "address": "台北市貴陽街2段1號之4", "description": "85折起", "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [121.506755, 25.039413]}}, {"id": "45", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "cake", "name": "無二蛋糕", "address": "台北市大安區安和路二段184巷10號", "description": "1. 當日消費滿600元,送當日小點心一份,送完為止\n2. 預訂蛋糕金額滿2000元,享95折優惠", "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [121.549858, 25.024992]}}, {"id": "46", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "shop", "name": "蜂蜜皇后", "address": "台北市大安區忠孝東路四段221號12樓", "description": "95折", "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [121.552577, 25.041661]}}, {"id": "47", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "魏姐包心粉圓", "address": "新竹市光復路一段360-3號", "description": "9折", "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [121.017563, 24.783541]}}, {"id": "48", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "shop", "name": "follow蜜 (築蜜企業社)", "address": "新竹縣竹北市嘉豐11路2段10號", "description": "飲品每杯 折扣5元\n蜂蜜商品(瓶裝) 9折優惠", "expiration": "自動展延"}, "geometry": null}, {"id": "49", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "drink", "name": "一手私藏世界紅茶(新竹光復店)", "address": "新竹市東區光復路一段362-15號", "description": "9折", "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [121.016116, 24.784092]}}, {"id": "50", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "BonTree 好樹早午餐", "address": "台北市基隆路二段285號", "description": "到店用餐出示識別證享有優惠價格", "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [121.549772, 25.021644]}}, {"id": "51", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "drink", "name": "日日良選 (科技大樓店)", "address": "台北市大安區和平東路二段311巷3號", "description": "飲品每杯 折扣5元,現場購買及外送皆適用", "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [121.545203, 25.024982]}}, {"id": "52", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "drink", "name": "羽上茶飲", "address": "台北市信義區莊敬路302號", "description": "買10杯送一杯\n20杯以上折95折~85折\n(欲外送請透過電話or Line點餐方能享折扣)", "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [121.563111, 25.028365]}}, {"id": "53", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "cafe", "name": "CAFE!N 延吉店", "address": "台北市大安區忠孝東路四段 50-2 號", "description": "一. 外送優惠:\n1. 單筆訂購咖啡與餐食金額滿 1,000 元享有 9 折企業會員優惠與三公里免運費外送服務。\n2. 單筆訂購咖啡與餐食金額滿 3,000 元享有 8 折企業會員優惠與三公里免運費外送服務。\n3. 企業會員訂單限定飲品與餐食 ,外送距離若超過 500 公尺,訂單請於至少 3 小時前下單。\n二. 咖啡周邊團購:\n1. 濾掛咖啡/咖啡豆,訂滿 10 組享 9 折優惠與三公里免運費外送服務。\n2. 濾掛咖啡/咖啡豆,訂滿 20 組享 8 折優惠與三公里免運費外送服務。\n\n訂購專線:(02)8771-38611 或 Line ID: cafein01", "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [121.544985, 25.041392]}}, {"id": "54", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "general_restaurant", "name": "一生懸雞(光復店)", "address": "新竹市東區光復路499號", "description": "外送雞排65元(其餘原價)\n來店消費全面九折", "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [121.014157, 24.784452]}}, {"id": "55", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "cafe", "name": "COFFEE LOVER's PLANET 敦北店", "address": "台北市大安區敦化南路1段246號號 B1", "description": "憑趨勢識別證至門市消費\n1. 可享全面9折優惠(包含購買咖啡豆)\n2. 加入門市會員,每次消費可享點數雙倍送", "expiration": null}, "geometry": {"type": "Point", "coordinates": [121.548441, 25.040146]}}, {"id": "56", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "cafe", "name": "COFFEE LOVER's PLANET 新竹店", "address": "新竹市東區中央路239號", "description": "憑趨勢識別證至門市消費\n1. 可享全面9折優惠(包含購買咖啡豆)\n2. 加入門市會員,每次消費可享點數雙倍送", "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [120.976204, 24.809614]}}, {"id": "57", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "sports", "name": "24磅咖啡羽球", "address": "台北市中正區寧波東街3-1號", "description": "a.\t單品咖啡豆享9折優惠 \nb.\t飲品享10元優惠 \nc.\t羽球拍、羽球鞋、服飾享95折優惠 \n", "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [121.519735, 25.03223]}}, {"id": "58", "type": "Feature", "properties": {"status": "Active", "class": "餐廳", "subclass": "drink", "name": "Swiido 走糖 萬隆示範店", "address": "台北市文山區羅斯福路五段211巷18號", "description": "1.\t首次外送總金額享85折優惠,免收運費且不限定外送距離。\n(門市活動優惠不能同時使用)\n2.\t第二次外送總金額享85折優惠,免收運費但折扣後之消費金額須達外送距離之規定金額。\n(外送達標金額依外送距離不同而異,門市活動優惠不能同時使用)\n3.\t凡貴公司人員至現場消費即可享有9折優惠。\n(門市活動優惠不能同時使用)\n", "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [121.539306, 25.002281]}}, {"id": "59", "type": "Feature", "properties": {"status": "Inactive", "class": "餐廳", "subclass": "drink", "name": "走糖手搖", "address": "台北市中山區長安東路二段258號", "description": "1.\t首次外送總金額享85折優惠,免收運費且不限定外送距離。\n(門市活動優惠不能同時使用)\n2.\t第二次外送總金額享85折優惠,免收運費但折扣後之消費金額須達外送距離之規定金額。\n(外送達標金額依外送距離不同而異,門市活動優惠不能同時使用)\n3.\t凡貴公司人員至現場消費即可享有9折優惠。\n(門市活動優惠不能同時使用)\n", "expiration": "自動展延"}, "geometry": {"type": "Point", "coordinates": [121.543666, 25.048158]}}]} \ No newline at end of file diff --git a/src/assets/icons/beer.svg b/src/assets/icons/beer.svg new file mode 100644 index 0000000..4b48095 --- /dev/null +++ b/src/assets/icons/beer.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/icons/bread.svg b/src/assets/icons/bread.svg new file mode 100644 index 0000000..d3bc380 --- /dev/null +++ b/src/assets/icons/bread.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/icons/burger.svg b/src/assets/icons/burger.svg new file mode 100644 index 0000000..7495b09 --- /dev/null +++ b/src/assets/icons/burger.svg @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/icons/cafe.svg b/src/assets/icons/cafe.svg new file mode 100644 index 0000000..b1ce646 --- /dev/null +++ b/src/assets/icons/cafe.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/icons/cake.svg b/src/assets/icons/cake.svg new file mode 100644 index 0000000..dd52639 --- /dev/null +++ b/src/assets/icons/cake.svg @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/icons/drink.svg b/src/assets/icons/drink.svg new file mode 100644 index 0000000..0ee5144 --- /dev/null +++ b/src/assets/icons/drink.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/icons/fruit.svg b/src/assets/icons/fruit.svg new file mode 100644 index 0000000..988af40 --- /dev/null +++ b/src/assets/icons/fruit.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/icons/general_restaurant.svg b/src/assets/icons/general_restaurant.svg new file mode 100644 index 0000000..90d08fa --- /dev/null +++ b/src/assets/icons/general_restaurant.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/icons/japanese_restaurant.svg b/src/assets/icons/japanese_restaurant.svg new file mode 100644 index 0000000..9c02488 --- /dev/null +++ b/src/assets/icons/japanese_restaurant.svg @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/icons/shop.svg b/src/assets/icons/shop.svg new file mode 100644 index 0000000..362cbb2 --- /dev/null +++ b/src/assets/icons/shop.svg @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/icons/sports.svg b/src/assets/icons/sports.svg new file mode 100644 index 0000000..699a615 --- /dev/null +++ b/src/assets/icons/sports.svg @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/icons/trend_micro.svg b/src/assets/icons/trend_micro.svg new file mode 100644 index 0000000..26d8d5f --- /dev/null +++ b/src/assets/icons/trend_micro.svg @@ -0,0 +1,30 @@ + + + + + + + diff --git a/src/assets/icons/wine.svg b/src/assets/icons/wine.svg new file mode 100644 index 0000000..72f3ef1 --- /dev/null +++ b/src/assets/icons/wine.svg @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/Map/Layer/CompanyLayer.js b/src/components/Map/Layer/CompanyLayer.js new file mode 100644 index 0000000..4b0e1c3 --- /dev/null +++ b/src/components/Map/Layer/CompanyLayer.js @@ -0,0 +1,61 @@ +import { Fragment } from "react"; +import { Source, Layer } from "react-map-gl"; + +const CompanySource = () => { + const companys = { + type: "FeatureCollection", + features: [ + { + id: "1", + type: "Feature", + geometry: { + type: "Point", + coordinates: [121.54838821352193, 25.02312941733473], + }, + properties: { + name: "趨勢科技", + "name:en": "Trend Micro Inc.", + class: "公司", + address: "106台北市大安區敦化南路二段198號", + description: + "趨勢科技為網路資安全球領導廠商,致力建立一個安全的資訊交換世界。憑藉著數十年的資安專業、全球威脅研究以及持續不斷的創新,我們跨雲端、網路、裝置及端點的網路資安平台隨時守護著全球 50 多萬家企業機構及 2.5 億以上的一般使用者。", + }, + }, + ], + }; + + const layerStyle = { + id: "company", + type: "symbol", + layout: { + "text-anchor": "top", + "text-field": "{name}\n{name:en}", + "text-font": ["Noto Sans Regular"], + "text-offset": [0, 0.6], + "text-padding": 2, + "text-size": 14, + "icon-image": "trend_micro", + }, + paint: { + "text-color": [ + "case", + ["boolean", ["feature-state", "hover"], false], + "rgba(3, 117, 214, 1)", + "#1544AF", + ], + "text-halo-blur": 0.5, + "text-halo-color": "#ffffff", + "text-halo-width": 1, + }, + }; + + return ( + + + + + + ); +}; + +export default CompanySource; diff --git a/src/components/Map/Layer/PoiLayer.js b/src/components/Map/Layer/PoiLayer.js new file mode 100644 index 0000000..5bbc644 --- /dev/null +++ b/src/components/Map/Layer/PoiLayer.js @@ -0,0 +1,42 @@ +import { Fragment } from "react"; +import { useSelector } from "react-redux"; +import { Source, Layer } from "react-map-gl"; + +const layerStyle = { + id: "poi", + type: "symbol", + layout: { + "text-anchor": "top", + "text-field": "{name}", + "text-font": ["Noto Sans Regular"], + "text-offset": [0, 0.6], + "text-padding": 2, + "text-size": 14, + "icon-image": "{subclass}", + "text-max-width": 30, + }, + paint: { + "text-color": [ + "case", + ["boolean", ["feature-state", "hover"], false], + "rgba(3, 117, 214, 1)", + "#B45118", + ], + "text-halo-blur": 0.5, + "text-halo-color": "#ffffff", + "text-halo-width": 1, + }, +}; + +const PoiLayer = () => { + const poiGeojson = useSelector((state) => state.map.poiGeojson); + return ( + + + + + + ); +}; + +export default PoiLayer; diff --git a/src/components/Map/MapView.js b/src/components/Map/MapView.js index 5ae64fa..43da354 100644 --- a/src/components/Map/MapView.js +++ b/src/components/Map/MapView.js @@ -1,10 +1,20 @@ import { useRef, useState, useCallback, Fragment } from "react"; import { useSelector, useDispatch } from "react-redux"; import { mapActions } from "../../store/map-slice"; +import { fetchPoiGeojson } from "../../store/map-actions"; -import maplibregl from "maplibre-gl"; import "maplibre-gl/dist/maplibre-gl.css"; import Map, { NavigationControl, ScaleControl } from "react-map-gl"; +import icons from "../../utils/icons"; +import PoiLayer from "./Layer/PoiLayer"; +import CompanyLayer from "./Layer/CompanyLayer"; + +// In order to solve the bug in production: Uncaught ReferenceError: y is not defined +// import maplibregl from "maplibre-gl"; +// eslint-disable-next-line import/no-webpack-loader-syntax +import maplibregl from '!maplibre-gl'; // ! is important here +import maplibreglWorker from 'maplibre-gl/dist/maplibre-gl-csp-worker'; +maplibregl.workerClass = maplibreglWorker; const MapView = () => { const dispatch = useDispatch(); @@ -14,6 +24,17 @@ const MapView = () => { const mapStyle = useSelector((state) => state.map.mapStyle); const onMapLoad = useCallback(() => { + // Add all icons to map + for (const key of Object.keys(icons)) { + let img = new Image(20, 20); + img.onload = () => mapRef.current.addImage(key, img); + img.src = icons[key]; + } + + // Fetch poi geojson from static file + dispatch(fetchPoiGeojson()); + + // Set cursor mapRef.current.on("dragstart", () => { setCursor("move"); }); @@ -21,7 +42,7 @@ const MapView = () => { mapRef.current.on("dragend", () => { setCursor("auto"); }); - }, []); + }, [dispatch]); const onMove = useCallback( (e) => { @@ -44,6 +65,10 @@ const MapView = () => { > + + {/* Custom layers */} + + ); diff --git a/src/logo.svg b/src/logo.svg deleted file mode 100644 index 9dfc1c0..0000000 --- a/src/logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/store/map-actions.js b/src/store/map-actions.js new file mode 100644 index 0000000..21a8e14 --- /dev/null +++ b/src/store/map-actions.js @@ -0,0 +1,25 @@ +import { mapActions } from "./map-slice"; +import poiGeojson from "../assets/data/poi.geojson"; + +export const fetchPoiGeojson = () => { + return async (dispatch) => { + const fetchData = async () => { + const response = await fetch(poiGeojson); + + if (!response.ok) { + throw new Error("Could not fetch poi data from static file!"); + } + + const data = await response.json(); + return data; + }; + + try { + const poiGeojson = await fetchData(); + dispatch(mapActions.setPoiGeojson(poiGeojson)); + } catch (error) { + // TODO: ui error notification + console.error(error); + } + }; +}; diff --git a/src/store/map-slice.js b/src/store/map-slice.js index 7a19746..789338e 100644 --- a/src/store/map-slice.js +++ b/src/store/map-slice.js @@ -13,32 +13,31 @@ const defaultMapStyle = { sources: { stamen_toner: { type: "raster", - tiles: [ - "https://stamen-tiles.a.ssl.fastly.net/toner/{z}/{x}/{y}.png", - ], + tiles: ["https://stamen-tiles.a.ssl.fastly.net/toner/{z}/{x}/{y}.png"], tileSize: 256, - attribution: 'Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.', + attribution: + 'Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.', }, }, sprite: "", glyphs: "https://yuchuntsao.github.io/fonts/{fontstack}/{range}.pbf", layers: [ { - "id": "background", - "type": "background", - "minzoom": 0, - "paint": { - "background-color": "rgba(255, 255, 255, 1)" - } + id: "background", + type: "background", + minzoom: 0, + paint: { + "background-color": "rgba(255, 255, 255, 1)", + }, }, { id: "stamen_toner", type: "raster", source: "stamen_toner", paint: { - 'raster-opacity': 0.3 - } - } + "raster-opacity": 0.3, + }, + }, ], }; @@ -47,11 +46,15 @@ const mapSlice = createSlice({ initialState: { viewState: defaultViewState, mapStyle: defaultMapStyle, + poiGeojson: null, }, reducers: { setViewState(state, action) { state.viewState = action.payload; - } + }, + setPoiGeojson(state, action) { + state.poiGeojson = action.payload; + }, }, }); diff --git a/src/utils/icons.js b/src/utils/icons.js new file mode 100644 index 0000000..b19d036 --- /dev/null +++ b/src/utils/icons.js @@ -0,0 +1,32 @@ +import beer from "../assets/icons/beer.svg"; +import bread from "../assets/icons/bread.svg"; +import burger from "../assets/icons/burger.svg"; +import cafe from "../assets/icons/cafe.svg"; +import cake from "../assets/icons/cake.svg"; +import drink from "../assets/icons/drink.svg"; +import fruit from "../assets/icons/fruit.svg"; +import general_restaurant from "../assets/icons/general_restaurant.svg"; +import japanese_restaurant from "../assets/icons/japanese_restaurant.svg"; +import shop from "../assets/icons/shop.svg"; +import sports from "../assets/icons/sports.svg"; +import trend_micro from "../assets/icons/trend_micro.svg"; +import wine from "../assets/icons/wine.svg"; + +// Collect all icons into an object +const icons = { + beer: beer, + bread: bread, + burger: burger, + cafe: cafe, + cake: cake, + drink: drink, + fruit: fruit, + general_restaurant: general_restaurant, + japanese_restaurant: japanese_restaurant, + shop: shop, + sports: sports, + trend_micro: trend_micro, + wine: wine, +}; + +export default icons;