chasestarr / ideas

Dump for app ideas. Find in issues
0 stars 0 forks source link

coffee shop share service #5

Open chasestarr opened 8 years ago

chasestarr commented 8 years ago

When working at a busy cafe, you can flag your table on the site with an open seat at your table.

chasestarr commented 8 years ago

integrate google maps api with a database to keep track of "flagged" locations.

chasestarr commented 8 years ago

Take advantage of Yelp search api to grab relevant cafe locations. Add link to review the location, provide rating in app.

chasestarr commented 8 years ago

github repo: https://github.com/chasestarr/fifty-fifty

chasestarr commented 8 years ago

Yelp API documentation: https://www.yelp.com/developers/documentation/v2/overview

chasestarr commented 8 years ago

video overview of yelp API: https://youtu.be/K_Fvx7pKlSE?t=3m44s

notes from the video: search api pull local bus based on location and geospacial gps, city name - aid in getting that api

search api, business api search - high level business - business lookup

ssearch by gps, city or neighborhood

business api - review snippet action links delivery, make reservation

chasestarr commented 8 years ago

I kind of like the visuals of https://www.mapbox.com/ more than google maps.. will need to research and compare the apis.

chasestarr commented 8 years ago

Completed basic search functionality.

At this point the app can:

To do:

chasestarr commented 8 years ago

Ran into an issue that I did not foresee (although I should have).

Once I have a map with markers loaded to the screen, If I click the "host table" button - how will my app know which business was triggered?

I send a geojson object into mapbox to display the markers.. There has to be a way to read from that data.

pic I want this to work like the picture above. Not sure how farmlogs does it...

chasestarr commented 8 years ago

"host table" could trigger a page reload.

  1. update database
  2. reload page and geoJSON
  3. display updated information

Edit: this still doesn't solve the "not knowing which marker is selected" problem

chasestarr commented 8 years ago

OK sort of figured it out, but it feels a bit hacky...

tooltip description variable:

var descript = "Address: " + element.location.address[0] + 
                "<br>Rating: " + starRating(element.rating) + 
                "<br><button type='button' class='hostButton' id ='" + element.id + "'>Host table</button>";

This will add the business id from yelp's api as the id of each "host table" button. When the button is clicked, check what the id is then perform db update on that id data.

chasestarr commented 8 years ago

I ran into a weird bug in my tooltip code:

var descript = "Address: " + element.location.address[0] + 
"<br>Rating: " + starRating(element.rating) + 
'<br><button onclick="hostTable();" type="button" class="hostButton" id ="' + element.id + '">Host table</button>';     

For some reason, onclick never makes it into the rendered html. Below is the output from chrome inspector:

<button type="button" class="hostButton" id="fifty-fifty-coffee-and-tea-san-francisco">Host table</button>

This issue on stackoverflow seems a bit related..

chasestarr commented 8 years ago

Found out that leaflet does not render links and onclicks within the map. I needed to "bind" the html contents to a custom tooltip layout. Based this format from here.

var map = L.mapbox.map('map', 'mapbox.light').setView({{center|json|raw}}, 12);
        var myLayer = L.mapbox.featureLayer().addTo(map);
        myLayer.on('layeradd', function(e) {
            var marker = e.layer;
            var feature = marker.feature;

            var content = "<b><a href='"+ feature.properties.url + "' target='_blank' class='businessTitle'>" + feature.properties.title + "<\/a><\/b>" +
            "<br>Address: " + feature.properties.address +
            "<br>Rating: " + feature.properties.rating + 
            "<br><button onclick='hostTable();' type='button' class='hostButton' id='" + feature.properties.id + "'>Host table<\/button>";

            marker.bindPopup(content, {closeButton: false});
        });
        myLayer.setGeoJSON({{geojson|json|raw}});

...whew there's not that much information about this effect. :dizzy:

chasestarr commented 8 years ago

I've been stuck on an issue with returning the result of an async database lookup for a couple of days now.

var searchYelp = function(params, callback){
    yelp.search(params, function(e,res){
        // console.log(res);
        if(e) return console.log(e);
        var center = [res.region.center.latitude, res.region.center.longitude];
        //Map api response to format readable by mapbox
        var businessData = res.businesses.map(function(element){
            var coordObj = element.location.coordinate; 

            var output = readDB(element.id, function(tableStatus){
                var obj = {
                    type: "Feature",
                    geometry:{
                        type: "Point",
                        coordinates: [coordObj.longitude,coordObj.latitude]
                    },
                    properties:{
                        title: element.name,
                        url: element.url,
                        address: element.location.address[0],
                        rating: starRating(element.rating),
                        host: tableStatus,
                        id: element.id,
                        "marker-color": "#fc4353",
                        "marker-size": "small"      
                    }
                };
                return obj;
            });
            console.log(output);

        });
        //package data to not repeat center obj
        var geoObj = {
            center: center,
            geoJSON: businessData
        }
        callback(geoObj);
    });   
};

var readDB = function(id, callback){
    MongoClient.connect('mongodb://localhost:27017/fifty-fifty', function(e,db){
        var cursor = db.collection("tables").find({_id: id});
        cursor.each(function(e,doc){
            if(e) throw e;
            if(doc == null){
                callback(false);
            } else {
                callback(doc.host);
            }
        });
    });
};

Currently, the program reaches console.log(output) before any value for it has been defined. I've been trying different ways to solve this issue, but I seem to always be coming back to this same problem. some variable has not been defined

chasestarr commented 8 years ago

this stackoverflow thread could be helpful. Haven't had a chance to read yet.

http://stackoverflow.com/questions/25229739/race-condition-and-common-mistakes

chasestarr commented 8 years ago

Back after a bit of a break from writing these entires. In the mean time I ask for some help on the project from a friend. He helped me out quite a bit by explaining some best practices when working with mongodb (using the mongoose package) as well as explained how to use js promises.

From what I understand, promises work similarly to callbacks in that they execute the next block in the chain once an action has finished (in my case a db lookup or an async function).

I learned what "callback hell" was! haha - basically my life last week. :astonished: The promise code structure made my code more linear and easier to follow. It turns out that my issue was: i needed to return the geojson object to mapbox, but it was being held up by the db lookup!

We fixed the issue by refactoring the code to populate a new array with each geojson object, and set up a counter on the action. Once the counter reaches the array length, execute my callback and then send the data to the front-end html.

chasestarr commented 8 years ago

Once this whole ordeal was worked out, I refactored all of my code into ES6. This wasn't too tough; mostly just updating anonymous functions to fat arrow syntax, converting vars to lets, and fixing a couple bugs when in "strict" mode.

The only weird thing was in my "app.listen" call, I could not convert that anonymous function into the new syntax. I looked up the issue and there seem to be some quirks when combining the "this" keyword with the new format. I haven't had a chance to dive into how "this" works yet, but I plan on it soon!

^^^ Going back to the app.listen weirdness. I started reading the "You don't know JS" chapter on "this" and object prototypes. Turns out that the fact arrow actually points the "this" keyword to the lexical scope. It looks like that break's the pattern express is using to get the listen function working.

chasestarr commented 8 years ago

in true hacker fashion, I wrote some really gross code to get the app to save previous locations. Before this, whenever you would "host" a table, it would reset the map view back to the default location, rather than center the map over your previous location.

let locPrev = "";

    if(loc && locPrev == ""){
        locPrev = loc;
        params = {term: 'coffee', location: loc};
    } else if(loc == null && locPrev == ""){
        params = {term: 'coffee', location: 'san+francisco'};
    } else if(loc && locPrev != ""){
        locPrev = loc;
        params  = {term: 'coffee', location: loc};
    } else {
        params  = {term: 'coffee', location: locPrev};
    }

Not very elegant, but it works for now. :dizzy:

chasestarr commented 8 years ago

All of my planned functionality has been implemented.

Behind the scenes I managed to:

chasestarr commented 8 years ago

Woo! so I reorganized the code structure for the project. At first the task seemed quite large, but once getting started it turned out to be fairly straightforward.

I did a good amount of research into the node module system and it makes a lot of sense! :sunglasses:

chasestarr commented 8 years ago

I got the www.letspl.it domain!