From 2a149b85976dc0b3d9a3eebbf3127e9a94374272 Mon Sep 17 00:00:00 2001 From: Chris Wen Date: Fri, 16 Jan 2026 15:47:15 +1100 Subject: [PATCH 1/3] health tools --- controller/healthToolsController.js | 32 +++++++++++++++ index.yaml | 64 +++++++++++++++++++++++++++-- routes/healthTools.js | 7 ++++ routes/index.js | 1 + 4 files changed, 101 insertions(+), 3 deletions(-) create mode 100644 controller/healthToolsController.js create mode 100644 routes/healthTools.js diff --git a/controller/healthToolsController.js b/controller/healthToolsController.js new file mode 100644 index 0000000..71e5978 --- /dev/null +++ b/controller/healthToolsController.js @@ -0,0 +1,32 @@ +const getBmi = async (req, res) => { + try { + const height = Number(req.query.height); + const weight = Number(req.query.weight); + + // Validate parameters + if (!height || !weight || height <= 0 || weight <= 0) { + return res.status(400).json({ + error: "Invalid parameters. Height and weight must be positive numbers." + }); + } + + // Calculate BMI + const bmi = weight / (height * height); + + // simple daily water intake estimation (ml) + const waterIntake = weight * 35; // 35 ml per kg + + return res.status(200).json({ + bmi: Number(bmi.toFixed(2)), + recommendedWaterIntakeMl: waterIntake + }); + + } catch (error) { + console.error(error); + return res.status(500).json({ error: "Internal server error" }); + } +}; + +module.exports = { + getBmi +}; diff --git a/index.yaml b/index.yaml index 7ad0539..4de63ff 100644 --- a/index.yaml +++ b/index.yaml @@ -2053,8 +2053,6 @@ paths: get: summary: Calculate estimated cost for a recipe description: Returns JSON array containing total cost and corresponding ingredients price - summary: Unified Health News API - description: Comprehensive API for health news management with multiple actions and flexible filtering parameters: - in: path name: recipe_id @@ -2189,7 +2187,6 @@ paths: responses: '200': description: Calculate cost successfully - description: Successfully retrieved requested data content: application/json: schema: @@ -2420,6 +2417,67 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' + /health-tools/bmi: + get: + summary: Calculate BMI and recommended daily water intake + description: > + Calculates Body Mass Index (BMI) based on height and weight, + and returns a recommended daily water intake value. + tags: + - Health Tools + parameters: + - name: height + in: query + required: true + description: Height in meters (e.g. 1.75) + schema: + type: number + format: float + example: 1.75 + - name: weight + in: query + required: true + description: Weight in kilograms (e.g. 70) + schema: + type: number + format: float + example: 70 + responses: + "200": + description: BMI and water intake calculated successfully + content: + application/json: + schema: + type: object + properties: + bmi: + type: number + format: float + example: 22.86 + recommendedWaterIntakeMl: + type: number + example: 2450 + "400": + description: Invalid query parameters + content: + application/json: + schema: + type: object + properties: + error: + type: string + example: Invalid parameters. Height and weight must be positive numbers. + "500": + description: Internal server error + content: + application/json: + schema: + type: object + properties: + error: + type: string + example: Internal server error + /recipe/nutritionlog: get: summary: Get full nutrition info for a recipe by name diff --git a/routes/healthTools.js b/routes/healthTools.js new file mode 100644 index 0000000..6e042e6 --- /dev/null +++ b/routes/healthTools.js @@ -0,0 +1,7 @@ +const express = require('express'); +const router = express.Router(); +const controller = require("../controller/healthToolsController"); + +router.get("/bmi",controller.getBmi) + +module.exports = router; \ No newline at end of file diff --git a/routes/index.js b/routes/index.js index 593f0bd..053d88b 100644 --- a/routes/index.js +++ b/routes/index.js @@ -31,6 +31,7 @@ module.exports = app => { app.use('/api/recipe/scale', require('./recipeScaling')); app.use('/api/water-intake', require('./waterIntake')); app.use('/api/health-news', require('./healthNews')); + app.use('/api/health-tools', require('./healthTools')); // Add shopping list routes app.use('/api/shopping-list', require('./shoppingList')); From 991eb39de47f4e4264d7588ea6a209a9a9849c6a Mon Sep 17 00:00:00 2001 From: Chris Wen Date: Fri, 16 Jan 2026 19:01:53 +1100 Subject: [PATCH 2/3] fix the error for image classification --- controller/imageClassificationController.js | 6 +++--- model/imageClassification.py | 7 +++++-- routes/imageClassification.js | 12 ++++++------ 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/controller/imageClassificationController.js b/controller/imageClassificationController.js index 496ec4f..b0f10af 100644 --- a/controller/imageClassificationController.js +++ b/controller/imageClassificationController.js @@ -48,12 +48,12 @@ const predictImage = (req, res) => { pythonProcess.stdout.on('data', (data) => { prediction += data.toString(); }); + console.log(prediction) + let stderrOutput = ''; // Handle errors pythonProcess.stderr.on('data', (data) => { - console.error('Error executing Python script:', data.toString()); - deleteFile(imagePath); - res.status(500).json({ error: 'Internal server error' }); + stderrOutput += data.toString(); }); // When Python script finishes execution diff --git a/model/imageClassification.py b/model/imageClassification.py index 059ad10..56ac210 100644 --- a/model/imageClassification.py +++ b/model/imageClassification.py @@ -21,11 +21,11 @@ import io # Get the relative path to the model file -model_path = os.path.join('model', 'modeltt.h5') +model_path = os.path.join('prediction_models', 'best_model_class.hdf5') try: # Load the pre-trained model - model = load_model(model_path) + model = load_model(model_path,compile=False) except Exception as e: print("Error loading model:", e) sys.exit(1) @@ -172,6 +172,9 @@ # Load image using PIL image = Image.open(io.BytesIO(image_data)) +if image.mode != 'RGB': + image = image.convert('RGB') + # Resize image to (224, 224) image = image.resize((224, 224)) diff --git a/routes/imageClassification.js b/routes/imageClassification.js index 06f30b0..f93614f 100644 --- a/routes/imageClassification.js +++ b/routes/imageClassification.js @@ -25,12 +25,12 @@ router.post('/', upload.single('image'), validateImageUpload, (req, res) => { // Call the predictImage function from the controller with req and res objects predictionController.predictImage(req, res); - // Delete the uploaded file after processing - fs.unlink(req.file.path, (err) => { - if (err) { - console.error('Error deleting file:', err); - } - }); + // // Delete the uploaded file after processing + // fs.unlink(req.file.path, (err) => { + // if (err) { + // console.error('Error deleting file:', err); + // } + // }); }); module.exports = router; From c9eea39c600d89a58c96266567f9087b50b222e2 Mon Sep 17 00:00:00 2001 From: Chris Wen Date: Tue, 20 Jan 2026 16:14:07 +1100 Subject: [PATCH 3/3] appointment api update. --- Nutrihelp-api | 1 - controller/appointmentController.js | 78 +++++++++++++++- index.yaml | 138 ++++++++++++++++++++++++++++ model/addAppointment.js | 54 ----------- model/appointmentModel.js | 115 +++++++++++++++++++++++ routes/appointment.js | 7 +- 6 files changed, 333 insertions(+), 60 deletions(-) delete mode 160000 Nutrihelp-api delete mode 100644 model/addAppointment.js create mode 100644 model/appointmentModel.js diff --git a/Nutrihelp-api b/Nutrihelp-api deleted file mode 160000 index 1313c91..0000000 --- a/Nutrihelp-api +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 1313c919f2bbd7d1091ef2879e8c3587bcc6c799 diff --git a/controller/appointmentController.js b/controller/appointmentController.js index 4d8a25c..854b96d 100644 --- a/controller/appointmentController.js +++ b/controller/appointmentController.js @@ -1,7 +1,7 @@ -const {addAppointment, addAppointmentV2} = require('../model/addAppointment.js'); -const {getAllAppointments, getAllAppointmentsV2} = require('../model/getAppointments.js'); +const {addAppointment, addAppointmentModelV2, updateAppointmentModel, deleteAppointmentById} = require('../model/appointmentModel.js'); +const {getAllAppointments, getAllAppointmentsV2 } = require('../model/getAppointments.js'); const { validationResult } = require('express-validator'); -const { appointmentValidation } = require('../validators/appointmentValidator.js'); + // Function to handle saving appointment data const saveAppointment = async (req, res) => { @@ -46,7 +46,7 @@ const saveAppointmentV2 = async (req, res) => { } = req.body; try { - const appointment = await addAppointmentV2({ + const appointment = await addAppointmentModelV2({ userId, title, doctor, @@ -70,6 +70,74 @@ const saveAppointmentV2 = async (req, res) => { } }; +const updateAppointment = async (req,res)=>{ + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ errors: errors.array() }); + } + + const { id } = req.params; + + const { + title, + doctor, + type, + date, + time, + location, + address, + phone, + notes, + reminder, + } = req.body; + + try { + const updatedAppointment = await updateAppointmentModel(id, { + title, + doctor, + type, + date, + time, + location, + address, + phone, + notes, + reminder, + }); + + if (!updatedAppointment) { + return res.status(404).json({ message: 'Appointment not found' }); + } + + res.status(200).json({ + message: 'Appointment updated successfully', + appointment: updatedAppointment, + }); + } catch (error) { + console.error('Error updating appointment:', error); + res.status(500).json({ error: 'Internal server error' }); + } +} + +const delAppointment = async (req,res)=>{ + const { id } = req.params; + + try { + const deleted = await deleteAppointmentById(id); + + if (!deleted) { + return res.status(404).json({ message: 'Appointment not found' }); + } + + res.status(200).json({ + message: 'Appointment deleted successfully', + }); + } catch (error) { + console.error('Error deleting appointment:', error); + res.status(500).json({ error: 'Internal server error' }); + } +} + // Function to handle retrieving all appointment data const getAppointments = async (req, res) => { try { @@ -114,6 +182,8 @@ const getAppointmentsV2 = async (req, res) => { module.exports = { saveAppointment, saveAppointmentV2, + updateAppointment, + delAppointment, getAppointments, getAppointmentsV2, }; diff --git a/index.yaml b/index.yaml index 4de63ff..1b2c82f 100644 --- a/index.yaml +++ b/index.yaml @@ -478,6 +478,101 @@ paths: application/json: schema: $ref: '#/components/schemas/ErrorResponse' + /appointments/v2/{id}: + put: + tags: + - Appointments + summary: Update an appointment (version 2) + parameters: + - in: path + name: id + required: true + schema: + type: integer + description: Appointment ID + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AppointmentUpdate' + responses: + '200': + description: Appointment updated successfully + content: + application/json: + schema: + type: object + properties: + message: + type: string + example: Appointment updated successfully + appointment: + $ref: '#/components/schemas/AppointmentUpdate' + '400': + description: Bad request - invalid input + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '404': + description: Appointment not found + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + delete: + tags: + - Appointments + summary: Delete an appointment (version 2) + parameters: + - in: path + name: id + required: true + schema: + type: integer + description: Appointment ID + responses: + '200': + description: Appointment deleted successfully + content: + application/json: + schema: + type: object + properties: + message: + type: string + example: Appointment deleted successfully + '404': + description: Appointment not found + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' # Shopping List API Endpoints /shopping-list/ingredient-options: @@ -3318,6 +3413,49 @@ components: reminder: type: string example: 1-day + AppointmentUpdate: + type: object + required: + - userId + - title + - doctor + - type + - date + properties: + userId: + type: integer + example: 1 + title: + type: string + example: Dr. Smith - Annual Checkup + doctor: + type: string + example: Dr. Robert Smith + type: + type: string + example: General Checkup + date: + type: string + format: date + example: "2024-12-05" + time: + type: string + example: "10:00" + location: + type: string + example: Main Street Medical Center + address: + type: string + example: 123 Main St, Suite 200 + phone: + type: string + example: "(555) 123-4567" + notes: + type: string + example: Bring insurance card and list of current medications + reminder: + type: string + example: 1-day SuccessResponse: type: object properties: diff --git a/model/addAppointment.js b/model/addAppointment.js deleted file mode 100644 index f67f0d0..0000000 --- a/model/addAppointment.js +++ /dev/null @@ -1,54 +0,0 @@ -const supabase = require('../dbConnection.js'); - -async function addAppointment(userId, date, time, description) { - try { - let { data, error } = await supabase - .from('appointments') - .insert({ user_id: userId, date, time, description }) - return data; - } catch (error) { - throw error; - } -} - -async function addAppointmentV2({ - userId, - title, - doctor, - type, - date, - time, - location, - address, - phone, - notes, - reminder -}) { - try { - const { data, error } = await supabase - .from("appointments") - .insert({ - user_id: userId, - title, - doctor, - type, - date, - time, - location, - address, - phone, - notes, - reminder - }) - .select() - .single(); - - if (error) throw error; - return data; - } catch (err) { - throw err; - } -} - - -module.exports = {addAppointment,addAppointmentV2}; diff --git a/model/appointmentModel.js b/model/appointmentModel.js new file mode 100644 index 0000000..3b9c120 --- /dev/null +++ b/model/appointmentModel.js @@ -0,0 +1,115 @@ +const supabase = require("../dbConnection.js"); + +async function addAppointment(userId, date, time, description) { + try { + let { data, error } = await supabase + .from("appointments") + .insert({ user_id: userId, date, time, description }); + return data; + } catch (error) { + throw error; + } +} + +async function addAppointmentModelV2({ + userId, + title, + doctor, + type, + date, + time, + location, + address, + phone, + notes, + reminder, +}) { + try { + const { data, error } = await supabase + .from("appointments") + .insert({ + user_id: userId, + title, + doctor, + type, + date, + time, + location, + address, + phone, + notes, + reminder, + }) + .select() + .single(); + + if (error) throw error; + return data; + } catch (err) { + throw err; + } +} + +async function updateAppointmentModel( + id, + { + title, + doctor, + type, + date, + time, + location, + address, + phone, + notes, + reminder, + }, +) { + try { + const { data, error } = await supabase + .from("appointments") + .update({ + title, + doctor, + type, + date, + time, + location, + address, + phone, + notes, + reminder, + }) + .eq("id", id) + .select() + .single(); + + if (error) throw error; + return data; + } catch (err) { + throw err; + } +} + +async function deleteAppointmentById(id) { + try { + const { data, error } = await supabase + .from("appointments") + .delete() + .eq("id", id) + .select() + .single(); + + if (error) throw error; + return data; + } catch (err) { + throw err; + } +} + +module.exports = { + addAppointment, + addAppointmentModelV2, + updateAppointmentModel, + deleteAppointmentById, +}; diff --git a/routes/appointment.js b/routes/appointment.js index 5dba1bd..580e594 100644 --- a/routes/appointment.js +++ b/routes/appointment.js @@ -3,11 +3,16 @@ const router = express.Router(); const appointmentController = require('../controller/appointmentController.js'); const { appointmentValidator,appointmentValidatorV2 } = require('../validators/appointmentValidator.js'); const validate = require('../middleware/validateRequest.js'); +const { appointmentValidation } = require('../validators/appointmentValidator.js'); // POST route for /api/appointments to save appointment data router.route('/').post(appointmentValidator, validate, appointmentController.saveAppointment); -router.route('/v2').post(appointmentValidatorV2, validate, appointmentController.saveAppointmentV2); +router.route('/v2').post(appointmentValidatorV2, appointmentValidatorV2, appointmentController.saveAppointmentV2); + +router.route('/v2/:id').put(appointmentValidatorV2, validate, appointmentController.updateAppointment); + +router.route('/v2/:id').delete(appointmentValidatorV2, appointmentController.delAppointment); // GET route for /api/appointments to retrieve all appointment data router.route('/').get(appointmentController.getAppointments);