sap.ui.define([ "sap/ui/core/mvc/Controller", "sap/m/MessageBox", "sap/ui/model/Filter", "sap/ui/model/FilterOperator" ], function (Controller, MessageBox, Filter, FilterOperator) { "use strict"; return Controller.extend("restaurant.z00124ss25restaurant.controller.managerReservation", { onInit: function () { var oDataForChart = { totalReservations: 0, totalRevenue: "35,918.29", monthlyData: [ { Month: "Jan", Count: 20, Revenue: 5000 }, { Month: "Feb", Count: 30, Revenue: 7000 }, { Month: "Mar", Count: 25, Revenue: 6000 }, { Month: "Apr", Count: 15, Revenue: 3500 }, { Month: "May", Count: 10, Revenue: 2000 }, { Month: "Jun", Count: 20, Revenue: 7500 } ] }; var oDashboardModel = new sap.ui.model.json.JSONModel(oDataForChart); this.getView().setModel(oDashboardModel, "dashboard"); this._loadReservationCount(); }, _padAndEncodeId: function (id) { id = id.toString(); // Ensure it's a string if (id.length === 9) { return id; } var padding = 9 - id.length; return "%20".repeat(padding) + id; }, onModelRefresh: function () { var oTable = this.byId("reservationTable"); oTable.getBinding().refresh(true); }, formatDimensions: function (sWidth, sHeight, sDepth, sUnit) { if (sWidth && sHeight && sDepth && sUnit) { return sWidth + "x" + sHeight + "x" + sDepth + " " + (sUnit.toLowerCase()); } return null; }, initBindingEventHandler: function () { const oBusyIndicator = this.oBusyIndicator; const oTable = this.getTable(); const oBinding = oTable.getBinding(); oBinding.attachDataRequested(function () { oTable.setNoData(oBusyIndicator); }); oBinding.attachDataReceived(function () { oTable.setNoData(null); //Use default again ("No Data" in case no data is available) }); }, _resetForm: function () { this.byId("decoration").setSelectedKey(""); this.byId("location").setSelectedKey(""); this.byId("numofseats").setValue(1); }, onCreateTable: function () { var iNumberOfSeats = this.byId("numofseats").getValue(); var sDecoration = this.byId("decoration").getSelectedKey(); var sLocation = this.byId("location").getSelectedKey(); if (!iNumberOfSeats) { MessageBox.error("Please enter number of seats"); return; } if (!sDecoration) { MessageBox.error("Please select a decoration for the table"); return; } if (!sLocation) { MessageBox.error("Please select a location for the table"); return; } var oPayload = { NumberOfSeats: iNumberOfSeats, Location: sLocation, Decoration: sDecoration }; var oModel = this.getOwnerComponent().getModel(); // Show busy indicator this.getView().setBusy(true); var endPoint = "/tablePos"; oModel.create(endPoint, oPayload, { success: function (oData, oResponse) { this.getView().setBusy(false); MessageBox.success("Table created successfully", { onClose: this._resetForm.bind(this) }); }.bind(this), error: function (oError) { this.getView().setBusy(false); // Extract error message from backend response var sErrorMessage = "Error creating Table"; try { if (oError.responseText) { var oErrorResponse = JSON.parse(oError.responseText); sErrorMessage = oErrorResponse.error.message.value || (oErrorResponse.error.innererror && oErrorResponse.error.innererror.errordetails && oErrorResponse.error.innererror.errordetails.length > 0 ? oErrorResponse.error.innererror.errordetails[0].message : sErrorMessage); } } catch (e) { // Use default error message if parsing fails console.error("Error parsing error response:", e); } // Log detailed error information for debugging console.error("Error status:", oError.statusCode); console.error("Error message:", sErrorMessage); console.error("Request URL:", oError.request ? oError.request.requestUri : "unknown"); console.error("Full error object:", oError); MessageBox.error(sErrorMessage); // Test with a different endpoint if this fails if (oError.statusCode === 404) { console.log("Trying alternative endpoint format..."); this._tryAlternativeEndpoint(oPayload); } }.bind(this) }); }, onEditTable: function (oEvent) { const oContext = oEvent.getSource().getBindingContext(); if (!oContext) return; const oData = oContext.getObject(); // Create dialog only once if (!this._oEditDialog) { this._oEditDialog = new sap.m.Dialog({ title: "Edit Table", contentWidth: "400px", content: new sap.ui.layout.form.SimpleForm({ editable: true, content: [ new sap.m.Label({ text: "Table ID" }), new sap.m.Input({ value: "{/TableId}", enabled: false }), new sap.m.Label({ text: "Decoration" }), new sap.m.Input({ value: "{/Decoration}" }), new sap.m.Label({ text: "Location" }), new sap.m.Input({ value: "{/Location}" }), new sap.m.Label({ text: "Seats" }), new sap.m.StepInput({ value: "{/NumberOfSeats}", min: 1, max: 12 }) ] }), buttons: [ new sap.m.Button({ text: "Save", type: "Emphasized", press: function () { var oDialogModel = this._oEditDialog.getModel(); var oUpdatedData = oDialogModel.getData(); var oModel = this.getView().getModel(); var endPoint = "/tablePos('" + this._padAndEncodeId(oUpdatedData.TableId.trim()) + "')"; var oPayload = { Decoration: oUpdatedData.Decoration, Location: oUpdatedData.Location, NumberOfSeats: oUpdatedData.NumberOfSeats }; this.getView().setBusy(true); oModel.update(endPoint, oPayload, { success: function () { this.getView().setBusy(false); sap.m.MessageToast.show("Table updated successfully!"); this._oEditDialog.close(); this._oEditDialog.destroy(); this._oEditDialog = null; }.bind(this), error: function (oError) { this.getView().setBusy(false); sap.m.MessageBox.error("Failed to update table."); console.error(oError); }.bind(this) }); }.bind(this) }), new sap.m.Button({ text: "Delete", type: "Reject", press: function () { sap.m.MessageBox.confirm("Are you sure you want to delete this table?", { onClose: function (sAction) { if (sAction === sap.m.MessageBox.Action.OK) { this._deleteTable(); } }.bind(this) }); }.bind(this) }), new sap.m.Button({ text: "Cancel", press: function () { this._oEditDialog.close(); }.bind(this) }) ], afterClose: function () { if (this._oEditDialog) { this._oEditDialog.destroy(); this._oEditDialog = null; } }.bind(this) }); } // Bind a JSON model copy to dialog to avoid direct changes before save const oTableData = Object.assign({}, oData); const oDialogModel = new sap.ui.model.json.JSONModel(oTableData); this._oEditDialog.setModel(oDialogModel); this._oEditDialog.bindElement("/"); this._oEditDialog.open(); }, _deleteTable: function () { var oDialogModel = this._oEditDialog.getModel(); var oData = oDialogModel.getData(); var oModel = this.getView().getModel(); var sPath = "/tablePos('" + this._padAndEncodeId(oData.TableId.trim()) + "')"; this.getView().setBusy(true); oModel.remove(sPath, { success: function () { this.getView().setBusy(false); sap.m.MessageToast.show("Table deleted successfully!"); this._oEditDialog.close(); }.bind(this), error: function (oError) { this.getView().setBusy(false); sap.m.MessageBox.error("Failed to delete table."); console.error(oError); }.bind(this) }); }, onSearchLiveChange: function (oEvent) { // Get the search query var sQuery = oEvent.getParameter("newValue"); var oTable = this.byId("reservationTable"); var oBinding = oTable.getBinding("rows"); // Apply filters if (sQuery && sQuery.length > 0) { var aFilters = [ new Filter("ReservationName", FilterOperator.Contains, sQuery) ]; oBinding.filter(new Filter({ filters: aFilters, and: false })); } else { // Clear filters if search field is empty oBinding.filter([]); } }, onModelRefresh: function () { var oModel = this.getView().getModel(); oModel.refresh(true); // Hard refresh from the server }, /** * Formats a date to show only year, month, and day (YYYY-MM-DD) * @param {object} oDate - Date object or date string * @returns {string} Formatted date string */ formatDate: function (oDate) { if (!oDate) { return ""; } // Convert string to date object if needed var dateObj = (typeof oDate === "string") ? new Date(oDate) : oDate; if (isNaN(dateObj.getTime())) { return ""; } // Format as YYYY-MM-DD var year = dateObj.getFullYear(); var month = String(dateObj.getMonth() + 1).padStart(2, '0'); var day = String(dateObj.getDate()).padStart(2, '0'); return year + "-" + month + "-" + day; }, /** * Formats a time to show in HH:MM:SS format * @param {object} oTime - Time object, date object, or time string * @returns {string} Formatted time string */ formatTime: function (oTime) { if (!oTime) { return ""; } // Handle OData Edm.Time object which contains ms property if (oTime && typeof oTime === "object" && oTime.ms !== undefined && oTime.__edmType === "Edm.Time") { // Calculate hours, minutes, seconds from milliseconds var totalSeconds = Math.floor(oTime.ms / 1000); var hours = Math.floor(totalSeconds / 3600); var minutes = Math.floor((totalSeconds % 3600) / 60); var seconds = totalSeconds % 60; // Format as HH:MM:SS return String(hours).padStart(2, '0') + ":" + String(minutes).padStart(2, '0') + ":" + String(seconds).padStart(2, '0'); } var timeObj; // Handle other input types if (typeof oTime === "string") { // Try parsing as time string (like "14:30:00") if (oTime.indexOf(":") !== -1) { var parts = oTime.split(":"); timeObj = new Date(); timeObj.setHours(parseInt(parts[0], 10)); timeObj.setMinutes(parts.length > 1 ? parseInt(parts[1], 10) : 0); timeObj.setSeconds(parts.length > 2 ? parseInt(parts[2], 10) : 0); } else { // Try parsing as date string timeObj = new Date(oTime); } } else if (oTime instanceof Date) { timeObj = oTime; } else { return ""; // Unsupported format } if (isNaN(timeObj.getTime())) { return ""; } // Format as HH:MM:SS var hours = String(timeObj.getHours()).padStart(2, '0'); var minutes = String(timeObj.getMinutes()).padStart(2, '0'); var seconds = String(timeObj.getSeconds()).padStart(2, '0'); return hours + ":" + minutes + ":" + seconds; }, _loadReservationCount: function () { var oODataModel = this.getOwnerComponent().getModel(); // Show busy indicator var oDashboardModel = this.getView().getModel("dashboard"); // Read count directly from the $count endpoint oODataModel.read("/reservationPos/$count", { success: function (count) { // count is a number (integer) oDashboardModel.setProperty("/totalReservations", count); }, error: function (oError) { console.error("Failed to fetch reservation count", oError); } }); } }); });