gaf-mobile
Version:
GAF mobile Web site
322 lines (292 loc) • 9.55 kB
JavaScript
module('gafMobileApp')
/**
* @ngdoc directive
* @name gafMobileApp.hireme-modal
* @restrict E
* @description
* A component for the modal of creating HireMe (HM) projects
* @example
* <pre module="gafMobileApp">
* ...
* <hireme-modal module="gafMobileApp"
* user="{ id: 123, username: hiremefreelancer }"
* currency="{ id: 1, code: 'USD', sign: '$', exchange_rate: 2 }"
* close="function() { ... }"
* </hireme-modal>
* ...
* </pre>
*/
.directive('hiremeModal', function() {
return {
restrict: 'E',
templateUrl: 'components/hireme-modal/hireme-modal.html',
scope: {
user: '=', // user to offer project to
currency: '=', // currency of hireme project
close: '&' // callback for closing this modal
},
controller: 'HiremeModalCtrl',
controllerAs: 'ctrl',
bindToController: true
};
})
/**
* @ngdoc controller
* @name gafMobileApp.HiremeModalCtrl
* @description
* Controller for creating HireMe projects
*/
.controller('HiremeModalCtrl', function(Hireme, Projects, $q,
$location, Experiments) {
var _this = this;
// TODO: Cleanup AB test for creating Hourly Hireme projects
_this.supportsHourly = Experiments.activateTest(
'FOT-2546_mbw_hourly_hireme',
true);
/**
* @ngdoc property
* @name gafMobileApp.HiremeModalCtrl#sameTitleCtr
* @propertyOf gafMobileApp.HiremeModalCtrl
* @description
* Will be appended to the title of the new HM project indicating the count
* of projects--between the employer and freelancer--with the same title.
* This will be incremented each time the posting of the HM project due to
* a duplicate title error.
*/
var sameTitleCtr = 2;
/**
* @ngdoc property
* @name gafMobileApp.HiremeModalCtrl#minimumBudget
* @propertyOf gafMobileApp.HiremeModalCtrl
* @description
* The minimum budget for the current selected currency for the HM project
*/
_this.minimumBudget = 0;
/**
* @ngdoc property
* @name gafMobileApp.HiremeModalCtrl#maximumBudget
* @propertyOf gafMobileApp.HiremeModalCtrl
* @description
* The maximum budget for the current selected currency for the HM project
*/
_this.maximumBudget = 0;
/**
* @ngdoc property
* @name gafMobileApp.HiremeModalCtrl#hiremeProject
* @propertyOf gafMobileApp.HiremeModalCtrl
* @description
* Holds the properties of the new HM project to create
*/
_this.hiremeProject = {};
/**
* @ngdoc property
* @name gafMobileApp.HiremeModalCtrl#currencies
* @propertyOf gafMobileApp.HiremeModalCtrl
* @description
* Array of supported currencies
*/
_this.currencies = [];
/**
* @ngdoc property
* @name gafMobileApp.HiremeModalCtrl#loading
* @propertyOf gafMobileApp.HiremeModalCtrl
* @description
* Indicates whether there is an ongoing transaction
*/
_this.loading = false;
/**
* @ngdoc property
* @name gafMobileApp.HiremeModalCtrl#error
* @propertyOf gafMobileApp.HiremeModalCtrl
* @description
* Holds the current error encountered in creating the HM project
*/
_this.error = {};
/**
* @ngdoc method
* @name gafMobileApp.HiremeModalCtrl#getMinimumBudget
* @methodOf gafMobileApp.HiremeModalCtrl
* @description
* Retrieves the minimum budget of the HM project for the given currency
* @return {Promise} A promise for getting the minimum budget for the given
* currency
*/
var getMinimumBudget = function(currency, projectType) {
return Hireme.minimumBudget(currency, projectType);
};
/**
* @ngdoc method
* @name gafMobileApp.HiremeModalCtrl#getMaximumBudget
* @methodOf gafMobileApp.HiremeModalCtrl
* @description
* Retrieves the maximum budget of the HM project for the given currency
* @return {Promise} A promise for getting the maximum budget for the given
* currency
*/
var getMaximumBudget = function(currency) {
return Hireme.maximumBudget(currency);
};
/**
* @ngdoc method
* @name gafMobileApp.HiremeModalCtrl#createFixedProjectSuccess
* @methodOf gafMobileApp.HiremeModalCtrl
* @description
* Success callback after creating a fixed Hireme project
*/
var createFixedProjectSuccess = function(newProject) {
_this.loading = false;
Projects.setCurrent(newProject);
_this.close();
};
/**
* @ngdoc method
* @name gafMobileApp.HiremeModalCtrl#createHourlyProjectSuccess
* @methodOf gafMobileApp.HiremeModalCtrl
* @description
* Success callback after creating a fixed Hireme project
*/
var createHourlyProjectSuccess = function(newProject) {
_this.loading = false;
$location.url(
'/projects/project-' + newProject.get().id +
'?createMilestoneFor=' + newProject.get().hireme_initial_bid.bidder_id +
'#management');
};
/**
* @ngdoc method
* @name gafMobileApp.HiremeModalCtrl#createProject
* @methodOf gafMobileApp.HiremeModalCtrl
* @description
* Returns a promise that creates the Hireme project then calls the new project
* with the specified success callback. If a duplicate error is encountered,
* this will increment the title then retry posting. Else, this will just store
* the error.
*/
var createProject = function(successCallback) {
_this.error = {};
var title = _this.hiremeProject.title;
return Hireme.createForUser(_this.user,
_this.hiremeProject.budget,
_this.hiremeProject.currency, title, {
days: _this.hiremeProject.days,
type: _this.hiremeProject.type
}).then(successCallback)
.catch(function(error) {
_this.error = error;
if (_this.error.hiremeDuplicateTitle) {
if (title.match(/ -- \d+$/)) {
title = title.replace(/\d+$/, ++sameTitleCtr);
} else {
title += ' -- ' + sameTitleCtr;
}
_this.hiremeProject.title = title;
createProject(successCallback);
} else {
_this.loading = false;
}
});
};
/**
* @ngdoc method
* @name gafMobileApp.HiremeModalCtrl#hireMe
* @methodOf gafMobileApp.HiremeModalCtrl
* @description
* Creates the HM project
* @return
* A promise that:
* - resolves to setting the newly created HM project as the
* current project;
* - increments the title then retries posting it again when an error
* is returned by the API due to a duplicate title error
* - stores the error for frontend display due to other errors
*/
_this.hireMe = function() {
_this.loading = true;
createProject(_this.hiremeProject.type === 'fixed' ?
createFixedProjectSuccess : createHourlyProjectSuccess);
};
/**
* @ngdoc method
* @name gafMobileApp.HiremeModalCtrl#onCurrencyChange
* @methodOf gafMobileApp.HiremeModalCtrl
* @description
* Refreshes the budget range when the currency is changed
*/
_this.onCurrencyChange = function(currency) {
getMinimumBudget(currency, _this.hiremeProject.type)
.then(function(minimum) {
_this.minimumBudget = minimum;
});
getMaximumBudget(currency).then(function(maximum) {
_this.maximumBudget = maximum;
});
};
/**
* @ngdoc method
* @name gafMobileApp.HiremeModalCtrl#onTypeChange
* @methodOf gafMobileApp.HiremeModalCtrl
* @description
* Refreshes the minimum budget when the project type is changed,
* along with other relevant project properties
*/
_this.onTypeChange = function(projectType) {
_this.error = {};
_this.hiremeProject.type = projectType;
getMinimumBudget(_this.hiremeProject.currency, projectType)
.then(function(minimum) {
_this.minimumBudget = minimum;
if (projectType === 'fixed') {
_this.hiremeProject.budget = minimum;
}
});
// update hiremeProject to contain only the needed properties for that type
var defaults = Hireme.getDefaultValues( _this.user,
_this.hiremeProject.currency,
projectType);
if (projectType === 'fixed') {
delete _this.hiremeProject.hourly_project_info;
_this.hiremeProject.days = defaults.days;
}
if (projectType === 'hourly') {
delete _this.hiremeProject.days;
_this.hiremeProject.hourly_project_info = defaults.hourly_project_info;
var rate = _this.user.hourly_rate || 10;
var exchangeRate = _this.hiremeProject.currency.exchange_rate;
// If it is an hourly project change the budget to
// freelancer's hourly rate.
_this.hiremeProject.budget = parseFloat(
(rate / exchangeRate).toFixed(0)
);
}
};
_this.loading = true;
var current = Projects.getCurrent().get();
var currentIsNewHiremeProject = (current.hireme && current.user &&
current.currency && current.type);
var preloads = {
currencies: Hireme.getCurrencies()
};
if (currentIsNewHiremeProject) {
preloads.minimum = getMinimumBudget(current.currency, current.type);
preloads.maximum = getMaximumBudget(current.currency);
} else {
preloads.minimum = getMinimumBudget(_this.currency);
preloads.maximum = getMaximumBudget(_this.currency);
}
$q.all(preloads).then(function(results) {
_this.currencies = results.currencies.getList();
_this.minimumBudget = results.minimum;
_this.maximumBudget = results.maximum;
if (currentIsNewHiremeProject) {
_this.hiremeProject = current;
_this.hireMe();
} else {
_this.hiremeProject = Hireme.getDefaultValues(
_this.user,
_this.currency);
_this.hiremeProject.budget = _this.minimumBudget;
_this.loading = false;
}
});
});
;
angular.