Router in a good shape
This commit is contained in:
@@ -43,6 +43,9 @@ export default class Filters extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onRoomsClick(rooms) {
|
onRoomsClick(rooms) {
|
||||||
|
this.props.dispatch({type: 'UPDATE_ROUTE', action: {
|
||||||
|
params: {rooms}
|
||||||
|
}});
|
||||||
this.props.dispatch({type: 'SET_ROOMS', action: {rooms}});
|
this.props.dispatch({type: 'SET_ROOMS', action: {rooms}});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export default class Gallery extends React.Component {
|
|||||||
cls += ' selected'
|
cls += ' selected'
|
||||||
}
|
}
|
||||||
|
|
||||||
return <div onClick={this.onImageDotClick.bind(this, index)} className={cls}></div>
|
return <div key={img} onClick={this.onImageDotClick.bind(this, index)} className={cls}></div>
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>)
|
</div>)
|
||||||
|
|||||||
@@ -9,6 +9,14 @@ export default class ListingDetails extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onBackClick() {
|
onBackClick() {
|
||||||
|
this.props.dispatch({type: 'UPDATE_ROUTE', action: {
|
||||||
|
toDispatch: {
|
||||||
|
type: 'BACK_TO_RESULTS'
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
listingId: null
|
||||||
|
}
|
||||||
|
}});
|
||||||
this.props.dispatch({type: 'BACK_TO_RESULTS'});
|
this.props.dispatch({type: 'BACK_TO_RESULTS'});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,8 +22,22 @@ export default class Listings extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onListingClick(id) {
|
onListingClick(id) {
|
||||||
|
|
||||||
|
|
||||||
loadListing(id).then(l => l.text()).then(l => {
|
loadListing(id).then(l => l.text()).then(l => {
|
||||||
console.log('listing loaded', l);
|
console.log('lising clicked');
|
||||||
|
this.props.dispatch({type: 'UPDATE_ROUTE', action: {
|
||||||
|
toDispatch: {
|
||||||
|
type: 'VIEW_LISTING_DETAILS', action: {
|
||||||
|
id,
|
||||||
|
listing: JSON.parse(l)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
listingId: id
|
||||||
|
}
|
||||||
|
}});
|
||||||
|
|
||||||
this.props.dispatch({type: 'VIEW_LISTING_DETAILS', action: {
|
this.props.dispatch({type: 'VIEW_LISTING_DETAILS', action: {
|
||||||
id,
|
id,
|
||||||
listing: JSON.parse(l)
|
listing: JSON.parse(l)
|
||||||
@@ -108,6 +122,12 @@ export default class Listings extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onSortChange (e) {
|
onSortChange (e) {
|
||||||
|
this.props.dispatch({type: 'UPDATE_ROUTE', action: {
|
||||||
|
params: {
|
||||||
|
sort: e.target.value
|
||||||
|
}
|
||||||
|
}});
|
||||||
|
|
||||||
this.props.dispatch({type: 'SORT_CHANGE', action: {
|
this.props.dispatch({type: 'SORT_CHANGE', action: {
|
||||||
sort: e.target.value
|
sort: e.target.value
|
||||||
}});
|
}});
|
||||||
|
|||||||
@@ -24,15 +24,18 @@ class Main extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (props.initialState) {
|
if (props.initialState) {
|
||||||
|
props.initialState.sort = props.initialState.sort || state.sort;
|
||||||
state.filters.rooms = props.initialState.rooms;
|
state.filters.rooms = props.initialState.rooms;
|
||||||
state.filters.category = props.initialState.category;
|
state.filters.category = props.initialState.category;
|
||||||
state.sort = props.initialState.sort || state.sort;
|
state.sort = props.initialState.sort || state.sort;
|
||||||
state.listingId = props.initialState.listingId;
|
state.listingId = props.initialState.listingId;
|
||||||
state.listingDetails = true;
|
if (state.listingId) {
|
||||||
|
state.listingDetails = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.state = state;
|
this.state = state;
|
||||||
this.router = new Router(this);
|
this.router = new Router(this, props.initialState);
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch ({type, action = {}}) {
|
dispatch ({type, action = {}}) {
|
||||||
@@ -81,7 +84,6 @@ class Main extends React.Component {
|
|||||||
map.setCenter(place.geometry.location);
|
map.setCenter(place.geometry.location);
|
||||||
map.setZoom(18);
|
map.setZoom(18);
|
||||||
}
|
}
|
||||||
console.log(map.getBounds());
|
|
||||||
this.dispatch({type: 'SEARCH_PLACE_CHANGED'});
|
this.dispatch({type: 'SEARCH_PLACE_CHANGED'});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -97,13 +99,15 @@ class Main extends React.Component {
|
|||||||
this.map = map;
|
this.map = map;
|
||||||
|
|
||||||
map.addListener('zoom_changed', () => {
|
map.addListener('zoom_changed', () => {
|
||||||
console.log('zoom_changed');
|
|
||||||
this.removeAllMarkers();
|
this.removeAllMarkers();
|
||||||
this.markers = [];
|
this.markers = [];
|
||||||
});
|
});
|
||||||
|
|
||||||
map.addListener('idle', () => {
|
map.addListener('idle', () => {
|
||||||
console.log('idle');
|
this.dispatch({type: 'UPDATE_ROUTE', action: {params: {
|
||||||
|
bounds: map.getBounds().toUrlValue()
|
||||||
|
}}});
|
||||||
|
|
||||||
this.dispatch({type: 'MAP_IDLE'});
|
this.dispatch({type: 'MAP_IDLE'});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -113,9 +117,7 @@ class Main extends React.Component {
|
|||||||
|
|
||||||
if (this.state.listingId) {
|
if (this.state.listingId) {
|
||||||
|
|
||||||
console.log("IT ISSSSS");
|
|
||||||
loadListing(this.state.listingId).then(l => l.text()).then(l => {
|
loadListing(this.state.listingId).then(l => l.text()).then(l => {
|
||||||
console.log('listing loaded', l);
|
|
||||||
this.dispatch({type: 'VIEW_LISTING_DETAILS', action: {
|
this.dispatch({type: 'VIEW_LISTING_DETAILS', action: {
|
||||||
id: this.state.listingId,
|
id: this.state.listingId,
|
||||||
listing: JSON.parse(l)
|
listing: JSON.parse(l)
|
||||||
@@ -126,7 +128,6 @@ class Main extends React.Component {
|
|||||||
|
|
||||||
removeAllMarkers () {
|
removeAllMarkers () {
|
||||||
if (this.markers) {
|
if (this.markers) {
|
||||||
console.log('removeAllMarkers');
|
|
||||||
this.markers.forEach((m) => m.marker.setMap(null));
|
this.markers.forEach((m) => m.marker.setMap(null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -195,7 +196,6 @@ class Main extends React.Component {
|
|||||||
})
|
})
|
||||||
.then(({body, totalCount}) => {
|
.then(({body, totalCount}) => {
|
||||||
body.then(p => {
|
body.then(p => {
|
||||||
console.log('results_received: ', totalCount);
|
|
||||||
const data = JSON.parse(p);
|
const data = JSON.parse(p);
|
||||||
|
|
||||||
const listingExists = (id) => {
|
const listingExists = (id) => {
|
||||||
@@ -213,7 +213,6 @@ class Main extends React.Component {
|
|||||||
newMarkers.push(m);
|
newMarkers.push(m);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
console.log('markers_removed');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(const [index, prop] of data.entries()) {
|
for(const [index, prop] of data.entries()) {
|
||||||
@@ -250,19 +249,36 @@ class Main extends React.Component {
|
|||||||
});
|
});
|
||||||
|
|
||||||
marker.addListener('click', () => {
|
marker.addListener('click', () => {
|
||||||
console.log('clicking...', prop._id);
|
// Maybe move out and call when popping state
|
||||||
if (this.state.listingId) {
|
if (this.state.listingId) {
|
||||||
const prevSelected = this.findMarker(this.state.listingId);
|
const prevSelected = this.findMarker(this.state.listingId);
|
||||||
if (prevSelected) {
|
if (prevSelected) {
|
||||||
console.log('prevselected', prevSelected);
|
|
||||||
prevSelected.marker.setIcon(this.visitedMarkerIcon());
|
prevSelected.marker.setIcon(this.visitedMarkerIcon());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
marker.setIcon(this.selectedMarkerIcon());
|
marker.setIcon(this.selectedMarkerIcon());
|
||||||
|
|
||||||
|
|
||||||
loadListing(prop._id).then(l => l.text()).then(l => {
|
loadListing(prop._id).then(l => l.text()).then(l => {
|
||||||
console.log('listing loaded', l);
|
|
||||||
|
this.dispatch({type: 'UPDATE_ROUTE', action: {
|
||||||
|
toDispatch: {
|
||||||
|
type: 'VIEW_LISTING_DETAILS', action: {
|
||||||
|
id: prop._id,
|
||||||
|
listing: JSON.parse(l)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
listingId: prop._id
|
||||||
|
}
|
||||||
|
}});
|
||||||
|
|
||||||
|
//this.dispatch({type: 'UPDATE_ROUTE', action: {type: 'VIEW_LISTING_DETAILS', action: {
|
||||||
|
//id: prop._id,
|
||||||
|
//listing: JSON.parse(l)
|
||||||
|
//}}});
|
||||||
|
|
||||||
this.dispatch({type: 'VIEW_LISTING_DETAILS', action: {
|
this.dispatch({type: 'VIEW_LISTING_DETAILS', action: {
|
||||||
id: prop._id,
|
id: prop._id,
|
||||||
listing: JSON.parse(l)
|
listing: JSON.parse(l)
|
||||||
@@ -293,7 +309,18 @@ class Main extends React.Component {
|
|||||||
* Refreshes search
|
* Refreshes search
|
||||||
*/
|
*/
|
||||||
refreshListings(more = false) {
|
refreshListings(more = false) {
|
||||||
console.log('refreshListings');
|
|
||||||
|
// TODO: move somewhere else
|
||||||
|
|
||||||
|
if (!more && this.state.listingId) {
|
||||||
|
|
||||||
|
loadListing(this.state.listingId).then(l => l.text()).then(l => {
|
||||||
|
this.dispatch({type: 'VIEW_LISTING_DETAILS', action: {
|
||||||
|
id: this.state.listingId,
|
||||||
|
listing: JSON.parse(l)
|
||||||
|
}});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (!more) {
|
if (!more) {
|
||||||
this.loadPins();
|
this.loadPins();
|
||||||
@@ -332,7 +359,6 @@ class Main extends React.Component {
|
|||||||
})
|
})
|
||||||
.then(({body, totalCount}) => {
|
.then(({body, totalCount}) => {
|
||||||
body.then(p => {
|
body.then(p => {
|
||||||
console.log('results_received: ', totalCount);
|
|
||||||
const data = JSON.parse(p);
|
const data = JSON.parse(p);
|
||||||
|
|
||||||
this.dispatch({
|
this.dispatch({
|
||||||
@@ -437,9 +463,7 @@ class Main extends React.Component {
|
|||||||
const children = [];
|
const children = [];
|
||||||
|
|
||||||
if (this.state.listingDetails) {
|
if (this.state.listingDetails) {
|
||||||
console.log('CURRENT LISTINGS', this.state.listings);
|
|
||||||
const listing = this.state.listing; //this.state.listings.get(this.state.listingId);
|
const listing = this.state.listing; //this.state.listings.get(this.state.listingId);
|
||||||
console.log(this.state);
|
|
||||||
children.push(<ListingDetails
|
children.push(<ListingDetails
|
||||||
listing={listing}
|
listing={listing}
|
||||||
imageIndex={this.state.imageIndex}
|
imageIndex={this.state.imageIndex}
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ const viewListingDetails = ({ type, action }, component) => {
|
|||||||
const scrollElem = document.querySelector('.right-content');
|
const scrollElem = document.querySelector('.right-content');
|
||||||
component.savedScrollTop = scrollElem.scrollTop;
|
component.savedScrollTop = scrollElem.scrollTop;
|
||||||
|
|
||||||
|
//component.router.listingId = action.id;
|
||||||
|
|
||||||
component.setState({
|
component.setState({
|
||||||
listingDetails: true,
|
listingDetails: true,
|
||||||
listingId: action.id,
|
listingId: action.id,
|
||||||
@@ -59,8 +61,7 @@ const viewListingDetails = ({ type, action }, component) => {
|
|||||||
imageIndex: 0,
|
imageIndex: 0,
|
||||||
listing: action.listing
|
listing: action.listing
|
||||||
}, () => {
|
}, () => {
|
||||||
//window.history.pushState({}, '', `/listing/${action.id}`);
|
//component.router.update();
|
||||||
component.router.update();
|
|
||||||
markSeen(action.id);
|
markSeen(action.id);
|
||||||
const m = component.findMarker(action.id);
|
const m = component.findMarker(action.id);
|
||||||
if (m) {
|
if (m) {
|
||||||
@@ -72,7 +73,6 @@ const viewListingDetails = ({ type, action }, component) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const listingsLoaded = ({ type, action }, component) => {
|
const listingsLoaded = ({ type, action }, component) => {
|
||||||
console.log('listings_loaded', action.more);
|
|
||||||
const currentListings = new Map();
|
const currentListings = new Map();
|
||||||
|
|
||||||
for (const listing of action.listings) {
|
for (const listing of action.listings) {
|
||||||
@@ -211,9 +211,10 @@ const onListingMouseOver = ({type, action}, component) => {
|
|||||||
const backToResults = ({type, action}, component) => {
|
const backToResults = ({type, action}, component) => {
|
||||||
const prevSelected = component.findMarker(component.state.listingId);
|
const prevSelected = component.findMarker(component.state.listingId);
|
||||||
component.setState({
|
component.setState({
|
||||||
listingId: undefined,
|
listingId: null,
|
||||||
listingDetails: false
|
listingDetails: false
|
||||||
}, () => {
|
}, () => {
|
||||||
|
//component.router.update();
|
||||||
|
|
||||||
if (prevSelected) {
|
if (prevSelected) {
|
||||||
prevSelected.marker.setIcon(component.visitedMarkerIcon());
|
prevSelected.marker.setIcon(component.visitedMarkerIcon());
|
||||||
@@ -225,8 +226,6 @@ const backToResults = ({type, action}, component) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const loadMoreListings = ({type, action}, component) => {
|
const loadMoreListings = ({type, action}, component) => {
|
||||||
console.log('loading more');
|
|
||||||
|
|
||||||
const currentPage = component.state.page;
|
const currentPage = component.state.page;
|
||||||
if (currentPage * 20 < component.state.totalCount) {
|
if (currentPage * 20 < component.state.totalCount) {
|
||||||
component.setState({
|
component.setState({
|
||||||
@@ -253,10 +252,15 @@ const sortChange = ({type, action}, component) => {
|
|||||||
sort: action.sort,
|
sort: action.sort,
|
||||||
page: 0
|
page: 0
|
||||||
}, () => {
|
}, () => {
|
||||||
|
//component.router.update();
|
||||||
component.refreshListings();
|
component.refreshListings();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const updateRoute = ({type, action}, component) => {
|
||||||
|
component.router.update(action);
|
||||||
|
}
|
||||||
|
|
||||||
const handlers = {
|
const handlers = {
|
||||||
SET_MIN_PRICE: setMinPrice,
|
SET_MIN_PRICE: setMinPrice,
|
||||||
SET_MAX_PRICE: setMaxPrice,
|
SET_MAX_PRICE: setMaxPrice,
|
||||||
@@ -277,7 +281,8 @@ const handlers = {
|
|||||||
LOAD_MORE_LISTINGS: loadMoreListings,
|
LOAD_MORE_LISTINGS: loadMoreListings,
|
||||||
MAP_IDLE: mapIdle,
|
MAP_IDLE: mapIdle,
|
||||||
PINS_LOADED: pinsLoaded,
|
PINS_LOADED: pinsLoaded,
|
||||||
SORT_CHANGE: sortChange
|
SORT_CHANGE: sortChange,
|
||||||
|
UPDATE_ROUTE: updateRoute
|
||||||
};
|
};
|
||||||
|
|
||||||
export const handleMessage = ({ type, action }, component) => {
|
export const handleMessage = ({ type, action }, component) => {
|
||||||
|
|||||||
@@ -1,18 +1,78 @@
|
|||||||
export default class Router {
|
class ToggleHash {
|
||||||
constructor(comp) {
|
constructor(data, key) {
|
||||||
this.component = comp;
|
this.data = data;
|
||||||
|
this.key = key;
|
||||||
|
this.data[key] = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
update () {
|
toggle (field) {
|
||||||
// Take the state from the component and update the URL
|
if (!field) {
|
||||||
const {listingId, sort, minPrice, maxPrice, minSize, maxSize, filters: {rooms, category}} = this.component.state;
|
return;
|
||||||
const bounds = this.component.map.getBounds().toUrlValue();
|
}
|
||||||
const params = [];
|
|
||||||
params.push(`listingId=${listingId}`);
|
const val = this.data[this.key][field];
|
||||||
params.push(`sort=${sort}`);
|
this.data[this.key][field] = !val;
|
||||||
params.push(`bounds=${bounds}`);
|
}
|
||||||
params.push(`rooms=${Object.keys(rooms).filter(v => rooms[v]).join(",")}`);
|
}
|
||||||
params.push(`category=${Object.keys(category).filter(v => category[v]).join(",")}`);
|
|
||||||
window.history.pushState({}, '', `/?${params.join("&")}`);
|
export default class Router {
|
||||||
|
constructor(comp, initialState) {
|
||||||
|
this.component = comp;
|
||||||
|
this.state = initialState || {};
|
||||||
|
|
||||||
|
this.roomsToggler = new ToggleHash(this.state, 'rooms');
|
||||||
|
this.categoryToggler = new ToggleHash(this.state, 'category');
|
||||||
|
|
||||||
|
window.onpopstate = (event) => {
|
||||||
|
const state = event.state;
|
||||||
|
console.log('POPING STATE', state);
|
||||||
|
if (state) {
|
||||||
|
if (state.toDispatch) {
|
||||||
|
this.component.dispatch(state.toDispatch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update (state) {
|
||||||
|
const params = [];
|
||||||
|
if (state.params) {
|
||||||
|
|
||||||
|
this.roomsToggler.toggle(state.params.rooms);
|
||||||
|
this.categoryToggler.toggle(state.params.category);
|
||||||
|
|
||||||
|
delete state.params['rooms'];
|
||||||
|
delete state.params['category'];
|
||||||
|
|
||||||
|
this.state = Object.assign(this.state, state.params);
|
||||||
|
|
||||||
|
console.log('router state is: ', this.state);
|
||||||
|
const {listingId, bounds, sort, rooms = {}, category = {}} = this.state;
|
||||||
|
|
||||||
|
if (listingId) {
|
||||||
|
params.push(`listingId=${listingId}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
params.push(`sort=${sort}`);
|
||||||
|
params.push(`bounds=${bounds}`);
|
||||||
|
params.push(`rooms=${Object.keys(rooms).filter(v => rooms[v]).join(",")}`);
|
||||||
|
params.push(`category=${Object.keys(category).filter(v => category[v]).join(",")}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.toDispatch) {
|
||||||
|
console.log('PUSHING STATE', state);
|
||||||
|
window.history.pushState(state, '', `/?${params.join("&")}`);
|
||||||
|
} else {
|
||||||
|
const oldState = window.history.state;
|
||||||
|
if (oldState) {
|
||||||
|
const newState = Object.assign(oldState, state);
|
||||||
|
console.log('REPLACING STATE', newState);
|
||||||
|
window.history.replaceState(newState, '',`/?${params.join("&")}`);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
console.log('PUSHING STATE', state);
|
||||||
|
window.history.replaceState(state, '',`/?${params.join("&")}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user