diff --git a/main.go b/main.go index 3a4fbd0..53c515c 100644 --- a/main.go +++ b/main.go @@ -11,6 +11,8 @@ import ( "net/http" "net/mail" "os" + + // "pocketbase/utils" "strings" "time" @@ -337,6 +339,311 @@ func main() { app = pocketbase.New() + //app.Router.GET("/verify-email", verifyEmailHandler) + + app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + + e.Router.GET("/api/custom/apicalltest", func(c echo.Context) error { + // Get the database instance + db := app.Dao().DB() + + // Define the struct for the expected result + type Chart struct { + Dataset string `json:"dataset"` + Key string `json:"key"` + Value string `json:"value"` + ValueEn string `json:"value_en"` + ValueAr string `json:"value_ar"` + } + + // Query to fetch the data + sqlQuery := "SELECT * FROM charts_variables" + var results []Chart + + // Execute the query + err := db.NewQuery(sqlQuery).All(&results) + if err != nil { + // Log the error details for better debugging + log.Printf("Failed to execute query: %v", err) + return c.JSON(http.StatusInternalServerError, map[string]string{"error": "Failed to execute query", "details": err.Error()}) + } + + // Check if results are empty + if len(results) == 0 { + return c.JSON(http.StatusNotFound, map[string]string{"error": "No records found"}) + } + + // Return the results + return c.JSON(http.StatusOK, results) + }) + + e.Router.GET("/api/getDataSet", func(c echo.Context) error { + + dataset := c.QueryParam("dataset") + if dataset == "" { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "dataset is required"}) + } + + // Fetch all matching records manually + filter := dbx.NewExp("dataset = {:dataset}", dbx.Params{"dataset": dataset}) + records, err := app.Dao().FindRecordsByExpr("charts", filter) + if err != nil { + log.Printf("Failed to fetch records for dataset '%s': %v", dataset, err) + return c.JSON(http.StatusInternalServerError, map[string]string{"error": "Failed to fetch records"}) + } + if len(records) == 0 { + return c.JSON(http.StatusNotFound, map[string]string{"error": "No records found for the given dataset"}) + } + + var aggregatedResponse []map[string]interface{} + + param := dbx.NewExp("dataset = {:dataset}", dbx.Params{"dataset": dataset}) + languageSource, err := app.Dao().FindRecordsByExpr("charts_variables", param) + if err != nil { + log.Printf("Failed to fetch language source: %v", err) + } + // Convert languageSource to []map[string]interface{} + languageSourceConverted := []map[string]interface{}{} + for _, record := range languageSource { + languageSourceConverted = append(languageSourceConverted, record.SchemaData()) + } + + filterData, err := fetchfilterJSON(dataset) + + // Translate filter data using the desired dataset and language key + // fRes, err := TranslateFilters(app, dataset, filterData, "value_en") + // if err != nil { + // log.Fatalf("Error translating filters: %v", err) + // } + + for _, record := range records { + // Extract the URL for each record + apiURL := record.GetString("url") + file_name := record.GetString("kpi_file_name") + if apiURL == "" { + log.Printf("No URL for record '%v'", record) + continue // Skip records with no URL + } + + // Fetch and convert XML to JSON + saveToFile := record.GetBool("file_status") + chartId := record.GetString("id") + if !saveToFile { // Check if saveToFile is false + _, err := fetchAndConvertXMLToJSON(apiURL, "kpi_files", file_name, "charts", chartId) + if err != nil { + log.Printf("Failed to process URL '%s': %v", apiURL, err) + continue // Skip this record and proceed with others + } + } + + // Read the JSON data from the file + chartData, err := readJSONFromFile("kpi_files", file_name) + if err != nil { + log.Printf("Failed to read JSON for KPI '%s': %v", file_name, err) + } + + // langKey := "value_en" + // cRes := utils.ProcessChartData(chartData, languageSourceConverted, langKey) + + // Prepare the structure with URL and its response + recordResult := map[string]interface{}{ + "url": apiURL, + "dataset": record.GetString("dataset"), + "main_id": record.GetString("main_id"), + "sub_id": record.GetString("sub_id"), + "kpi": record.GetString("kpi"), + "is_chart": record.GetString("is_chart"), + "chart_type": record.GetString("chart_type"), + "response": chartData, + "group_by": record.GetString("group_by"), + "chart_heading": record.GetString("chart_heading"), + } + + // Add the result to the aggregated response + aggregatedResponse = append(aggregatedResponse, recordResult) + + } + + // Create the response structure + response := map[string]interface{}{ + "filter_data": filterData, + "data": aggregatedResponse, + } + + if len(aggregatedResponse) == 0 { + return c.JSON(http.StatusInternalServerError, map[string]string{"error": "No data could be fetched from the provided URLs"}) + } + + return c.JSON(http.StatusOK, response) + }) + + e.Router.GET("/api/getHomePageData", func(c echo.Context) error { + + // Define the struct for holding the query results + mainTopics := []struct { + MainTopic string `db:"main_topic" json:"main_topic"` + MainTopicListOrder string `db:"main_topic_list_order" json:"main_topic_list_order"` + ColorPattern string `db:"color_pattern" json:"color_pattern"` + }{} + + // Execute the query + err := app.DB(). + Select("main_topic", "main_topic_list_order", "color_pattern"). + From("home_screen"). + GroupBy("main_topic", "color_pattern"). + OrderBy("main_topic_list_order ASC"). + All(&mainTopics) + + if err != nil { + log.Printf("Failed to fetch home_screen data: %v", err) + return c.JSON(http.StatusInternalServerError, map[string]string{"error": "Failed to fetch records"}) + } + + // If no records are found + if len(mainTopics) == 0 { + return c.JSON(http.StatusNotFound, map[string]string{"error": "No records found for home screen"}) + } + + // Final result structure + result := []map[string]interface{}{} + + // Loop through main topics and fetch sub-topic data for each + for _, mainTopic := range mainTopics { + + dataSets := []struct { + DataSet string `db:"data_set" json:"data_set"` + DataSetTileHeading string `db:"data_set_tile_heading" json:"data_set_tile_heading"` + ValueSource string `db:"value_source" json:"value_source"` + Value string `db:"value" json:"value"` + DataSetListOrder string `db:"data_set_list_order" json:"data_set_list_order"` + }{} + + err := app.DB(). + NewQuery("SELECT data_set, data_set_tile_heading, value_source, value, data_set_list_order FROM home_screen WHERE main_topic={:topic} "). + Bind(dbx.Params{ + "topic": mainTopic.MainTopic, + }). + All(&dataSets) + + if err != nil { + log.Printf("Error fetching data sets: %v", err) + continue + } + + // Add the main topic and its sub-topics to the result + result = append(result, map[string]interface{}{ + "main_topic": mainTopic.MainTopic, + "main_topic_list_order": mainTopic.MainTopicListOrder, + "color_pattern": mainTopic.ColorPattern, + "tile_data": dataSets, + }) + } + + // Send the combined result as JSON + return c.JSON(http.StatusOK, result) + + }) + + e.Router.GET("/api/getUAENumbersData", func(c echo.Context) error { + + // Define the struct for holding the query results + mainTopics := []struct { + MainTopic string `db:"main_topic" json:"main_topic"` + MainTopicListOrder string `db:"main_topic_list_order" json:"main_topic_list_order"` + ColorPattern string `db:"color_pattern" json:"color_pattern"` + }{} + + // Execute the query + err := app.DB(). + Select("main_topic", "main_topic_list_order", "color_pattern"). + From("uae_numbers_screen"). + GroupBy("main_topic", "color_pattern"). + OrderBy("main_topic_list_order ASC"). + All(&mainTopics) + + if err != nil { + log.Printf("Failed to fetch uae_numbers_screen data: %v", err) + return c.JSON(http.StatusInternalServerError, map[string]string{"error": "Failed to fetch records"}) + } + + // If no records are found + if len(mainTopics) == 0 { + return c.JSON(http.StatusNotFound, map[string]string{"error": "No records found for home screen"}) + } + + // Final result structure + result := []map[string]interface{}{} + + // Loop through main topics and fetch sub-topic data for each + for _, mainTopic := range mainTopics { + subTopics := []struct { + SubTopic string `db:"sub_topic" json:"sub_topic"` + SubTopicListOrder string `db:"sub_topic_list_order" json:"sub_topic_list_order"` + }{} + + // Query to get sub-topics for the current main topic + err := app.DB(). + Select("sub_topic", "sub_topic_list_order"). + From("uae_numbers_screen"). + Where(dbx.HashExp{"main_topic": mainTopic.MainTopic}). + GroupBy("sub_topic"). + OrderBy("sub_topic_list_order ASC"). + All(&subTopics) + + if err != nil { + log.Printf("Failed to fetch sub-topics for main topic %s: %v", mainTopic.MainTopic, err) + continue + } + + result2 := []map[string]interface{}{} + // Loop through sub Topics topics and fetch dataSet data for each + for _, subTopic := range subTopics { + + dataSets := []struct { + DataSet string `db:"data_set" json:"data_set"` + DataSetTileHeading string `db:"data_set_tile_heading" json:"data_set_tile_heading"` + ValueSource string `db:"value_source" json:"value_source"` + Value string `db:"value" json:"value"` + DataSetListOrder string `db:"data_set_list_order" json:"data_set_list_order"` + }{} + + // Query to get data-set for the current sub topic + err := app.DB(). + Select("data_set", "data_set_tile_heading", "value_source", "value", "data_set_list_order"). + From("uae_numbers_screen"). + Where(dbx.HashExp{"sub_topic": subTopic.SubTopic}). + OrderBy("data_set_list_order ASC"). + All(&dataSets) + + if err != nil { + log.Printf("Failed to fetch data-set for sub topic %s: %v", subTopic.SubTopic, err) + continue + } + + result2 = append(result2, map[string]interface{}{ + "sub_topic": subTopic.SubTopic, + "sub_topic_list_order": subTopic.SubTopicListOrder, + "tile_data": dataSets, + }) + } + + // Add the main topic and its sub-topics to the result + result = append(result, map[string]interface{}{ + "main_topic": mainTopic.MainTopic, + "main_topic_list_order": mainTopic.MainTopicListOrder, + "color_pattern": mainTopic.ColorPattern, + "sub_topics": result2, + }) + } + + // Send the combined result as JSON + return c.JSON(http.StatusOK, result) + + }) + + return nil + }) + //send mail while status changed from app admin app.OnRecordBeforeUpdateRequest().Add(func(e *core.RecordUpdateEvent) error { if e.Collection.Name == "users" { @@ -375,17 +682,17 @@ func main() { // Email body body := fmt.Sprintf(` - -
-Dear %s,
-Thank you for registering. Please click the link below to verify your email address:
-- Verify Email -
-If you did not register for this account, please ignore this email.
- - - `, name, verificationURL) + + +Dear %s,
+Thank you for registering. Please click the link below to verify your email address:
++ Verify Email +
+If you did not register for this account, please ignore this email.
+ + + `, name, verificationURL) // Create the email message message := &mailer.Message{ @@ -436,6 +743,147 @@ func main() { }) } + // Check if the email is already verified + if record.GetBool("reviewed") { + return c.HTML(http.StatusOK, ` + + + + + + + + + `) + } + + // Update the status + newStatus := "Approved" + record.Set("verified", true) + record.Set("status", newStatus) + record.Set("reviewed", true) + if err := app.Dao().SaveRecord(record); err != nil { + return c.JSON(500, map[string]interface{}{ + "code": 500, + "message": "Failed to verify user.", + }) + } + + // Send the status change email + err = sendStatusChangeEmail(app, record, newStatus) + if err != nil { + return c.JSON(500, map[string]interface{}{ + "code": 500, + "message": "Failed to send approval email.", + }) + } + + return c.HTML(http.StatusOK, ` + + + + + + + + + `) + }) + + return nil + }) + + app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + + // Approve Endpoint + e.Router.GET("/api/custom/reject", func(c echo.Context) error { + userId := c.QueryParam("userId") + if userId == "" { + return c.JSON(400, map[string]interface{}{ + "code": 400, + "message": "Missing userId query parameter.", + }) + } + + // Find the user record in PocketBase by userId + record, err := app.Dao().FindRecordById("users", userId) + if err != nil { + return c.JSON(500, map[string]interface{}{ + "code": 500, + "message": "Error finding user.", + }) + } + // Check if the email is already verified if record.GetBool("reviewed") { return c.HTML(http.StatusOK, ` @@ -485,147 +933,6 @@ func main() { `) } - // Update the status - newStatus := "Approved" - record.Set("verified", true) - record.Set("status", newStatus) - record.Set("reviewed", true) - if err := app.Dao().SaveRecord(record); err != nil { - return c.JSON(500, map[string]interface{}{ - "code": 500, - "message": "Failed to verify user.", - }) - } - - // Send the status change email - err = sendStatusChangeEmail(app, record, newStatus) - if err != nil { - return c.JSON(500, map[string]interface{}{ - "code": 500, - "message": "Failed to send approval email.", - }) - } - - return c.HTML(http.StatusOK, ` - - - - - - - - - `) - }) - - return nil - }) - - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { - - // Approve Endpoint - e.Router.GET("/api/custom/reject", func(c echo.Context) error { - userId := c.QueryParam("userId") - if userId == "" { - return c.JSON(400, map[string]interface{}{ - "code": 400, - "message": "Missing userId query parameter.", - }) - } - - // Find the user record in PocketBase by userId - record, err := app.Dao().FindRecordById("users", userId) - if err != nil { - return c.JSON(500, map[string]interface{}{ - "code": 500, - "message": "Error finding user.", - }) - } - - // Check if the email is already verified - if record.GetBool("reviewed") { - return c.HTML(http.StatusOK, ` - - - - - - - - - `) - } - // Check if the status is already "Denied" to avoid duplicate email if record.GetString("status") == "Denied" { return c.JSON(400, map[string]interface{}{ @@ -657,45 +964,45 @@ func main() { // Render a success message as an HTML response return c.HTML(http.StatusOK, ` - - - - - -Dear %s,
-You have received new feedback from a user through the mobile application.
-User Details:
-Feedback:
-- 1. How was your experience with us today? Rating: %s - 2. How did we perform in key areas? - 1. Ease of Use: %s - 2. Quality: %s - 3. Design: %s - 4. Redundancy: %s - 3. Additional Feedback: - 1. %s --
Thank you,
-The FCSC App Team
- - - `, adminName, userName, formattedDate, formattedDateTime, emojiRating, easeOfUse, quality, design, redundancy, additionalFeedback) + + +Dear %s,
+You have received new feedback from a user through the mobile application.
+User Details:
+Feedback:
++ 1. How was your experience with us today? Rating: %s + 2. How did we perform in key areas? + 1. Ease of Use: %s + 2. Quality: %s + 3. Design: %s + 4. Redundancy: %s + 3. Additional Feedback: + 1. %s ++
Thank you,
+The FCSC App Team
+ + + `, adminName, userName, formattedDate, formattedDateTime, emojiRating, easeOfUse, quality, design, redundancy, additionalFeedback) // Define the target type (e.g., "smtp") targetType := "feedback_receive_mail" @@ -852,8 +1159,8 @@ func main() { Subject: "YOUR VERIFICATION CODE", HTML: fmt.Sprintf( `Thanks for verifying your %s account!
-Your code is: %d
-Sincerely,
Support team.
Your code is: %d
+Sincerely,
Support team.