@fleetbase/fleetops-engine
Version:
Fleet & Transport Management Extension for Fleetbase
244 lines (194 loc) • 7.73 kB
JavaScript
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { inject as service } from '@ember/service';
import { action, get } from '@ember/object';
import { task } from 'ember-concurrency';
import config from 'ember-get-config';
import { buildServiceStopsFromPayload } from '../../utils/route-visualization';
export default class ModalsUpdateOrderActivityComponent extends Component {
fetch;
intl;
notifications;
modalsManager;
activityOptions = [];
order;
selectedActivity;
customActivity = {};
proofFiles = [];
proof;
bypassProof = false;
constructor(owner, { options = {} }) {
super(...arguments);
this.order = options.order;
this.loadActivity.perform();
}
get waypoints() {
const waypoints = this.order?.payload?.waypoints;
if (typeof waypoints?.toArray === 'function') {
return waypoints.toArray();
}
return Array.isArray(waypoints) ? waypoints : Array.from(waypoints ?? []);
}
get serviceStops() {
return buildServiceStopsFromPayload(this.order?.payload);
}
get activeStopId() {
const activeStop = this.order?.tracker_data?.active_stop;
return activeStop?.uuid ?? activeStop?.public_id ?? this.order?.payload?.current_waypoint_uuid ?? this.order?.payload?.current_waypoint;
}
get isMultipleWaypointOrder() {
return this.waypoints.length > 0;
}
get orderHasStarted() {
const status = this.order?.status;
return Boolean(this.order?.started || this.order?.started_at || (status && !['created', 'dispatched'].includes(status)));
}
get shouldUseWaypointActivity() {
return this.isMultipleWaypointOrder && this.orderHasStarted;
}
get currentWaypoint() {
if (!this.shouldUseWaypointActivity) {
return null;
}
const currentWaypointId = this.activeStopId;
if (currentWaypointId) {
const stop = this.serviceStops.find(({ place }) => {
return [place?.id, place?.uuid, place?.public_id, place?.waypoint_public_id].includes(currentWaypointId);
});
if (stop?.place) {
return stop.place;
}
}
return this.serviceStops.find(({ place }) => !place?.complete)?.place ?? this.serviceStops[0]?.place;
}
get currentWaypointId() {
const waypoint = this.currentWaypoint;
return waypoint?.id ?? waypoint?.public_id ?? waypoint?.uuid;
}
get currentWaypointProofSubjectId() {
const waypoint = this.currentWaypoint;
return waypoint?.waypoint_public_id ?? waypoint?.id ?? waypoint?.public_id ?? waypoint?.uuid;
}
get selectedActivityRecord() {
if (this.selectedActivity === 'custom') {
return this.customActivity;
}
return this.activityOptions[this.selectedActivity];
}
get selectedActivityRequiresPod() {
return Boolean(this.selectedActivityRecord?.require_pod);
}
get acceptedProofFileTypes() {
return ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
}
get hasUploadedProof() {
return Boolean(this.proof?.id || this.proof?.public_id);
}
get uploadedProofId() {
return this.proof?.id ?? this.proof?.public_id;
}
*loadActivity() {
if (!this.order?.id) {
return [];
}
try {
const params = this.shouldUseWaypointActivity && this.currentWaypointId ? { waypoint: this.currentWaypointId } : {};
const activityOptions = yield this.fetch.get(`orders/next-activity/${this.order.id}`, params);
this.activityOptions = activityOptions;
return activityOptions;
} catch (err) {
this.notifications.serverError(err);
}
}
*submitActivity(modal) {
modal.startLoading();
const activity = this.selectedActivityRecord;
if (this.selectedActivity === 'custom' && !activity.status && !activity.details && !activity.code) {
modal.stopLoading();
return this.notifications.warning(this.intl.t('fleet-ops.operations.orders.index.view.invalid-warning'));
}
if (this.selectedActivityRequiresPod && this.uploadProofFile.isRunning) {
modal.stopLoading();
return this.notifications.warning('Photo proof of delivery is still uploading.');
}
if (this.selectedActivityRequiresPod && !this.hasUploadedProof && !this.bypassProof) {
modal.stopLoading();
return this.notifications.warning('Upload photo proof of delivery or choose to bypass proof of delivery.');
}
try {
yield this.fetch.patch(`orders/update-activity/${this.order.id}`, {
activity,
proof: this.hasUploadedProof ? this.uploadedProofId : null,
bypass_proof: this.selectedActivityRequiresPod && this.bypassProof,
});
if (typeof this.order?.reload === 'function') {
yield this.order.reload();
}
if (typeof this.order?.loadTrackerData === 'function') {
if (typeof this.order.set === 'function') {
this.order.set('tracker_data', null);
}
yield this.order.loadTrackerData();
}
this.modalsManager.setOption('activityCreated', activity);
this.modalsManager.setOption('proofCreated', this.hasUploadedProof ? this.proof : null);
this.notifications.success(`Order activity has been updated to ${activity.status}`);
modal.done();
} catch (error) {
this.notifications.serverError(error);
} finally {
modal.stopLoading();
}
}
*capturePhotoProof() {
const [proofFile] = this.proofFiles;
if (!proofFile) {
return null;
}
const headers = this.fetch.getHeaders();
delete headers['Content-Type'];
const subjectId = this.currentWaypointProofSubjectId;
const subjectPath = subjectId ? `/${subjectId}` : '';
const url = [get(config, 'API.host'), get(config, 'API.namespace'), `orders/${this.order.id}/capture-photo${subjectPath}`].filter(Boolean).join('/');
const response = yield proofFile.upload(url, {
data: {
remarks: 'Verified by Photo',
},
headers,
withCredentials: true,
});
return response.json();
}
*uploadProofFile(file) {
if (!file) {
return;
}
this.bypassProof = false;
this.proof = null;
this.proofFiles = [file];
try {
this.proof = this.normalizeProofResponse(yield this.capturePhotoProof.perform());
this.notifications.success('Photo proof of delivery uploaded.');
} catch (error) {
this.proof = null;
this.proofFiles = [];
this.notifications.serverError(error);
}
}
toggleBypassProof(value) {
this.bypassProof = value;
if (value) {
this.proofFiles = [];
this.proof = null;
}
}
normalizeProofResponse(response) {
if (response?.proof) {
return response.proof;
}
if (response?.data?.id || response?.data?.public_id) {
return response.data;
}
return response;
}
}