diff --git a/Backend/.gitignore b/Backend/.gitignore
new file mode 100644
index 00000000..b512c09d
--- /dev/null
+++ b/Backend/.gitignore
@@ -0,0 +1 @@
+node_modules
\ No newline at end of file
diff --git a/Backend/arPoseLandmarks/downward_dog/downward_dog_landmarks.json b/Backend/arPoseLandmarks/downward_dog/downward_dog_landmarks.json
new file mode 100644
index 00000000..cffb0e99
--- /dev/null
+++ b/Backend/arPoseLandmarks/downward_dog/downward_dog_landmarks.json
@@ -0,0 +1,42 @@
+[
+ {
+ "name": "left_shoulder",
+ "x": 0.43475762009620667,
+ "y": 0.5846027731895447
+ },
+ {
+ "name": "right_shoulder",
+ "x": 0.4466809630393982,
+ "y": 0.5982203483581543
+ },
+ {
+ "name": "left_elbow",
+ "x": 0.3332710564136505,
+ "y": 0.7483700513839722
+ },
+ {
+ "name": "right_elbow",
+ "x": 0.34916260838508606,
+ "y": 0.7354578375816345
+ },
+ {
+ "name": "left_hip",
+ "x": 0.6648672223091125,
+ "y": 0.2121756225824356
+ },
+ {
+ "name": "right_hip",
+ "x": 0.6585555076599121,
+ "y": 0.2347366362810135
+ },
+ {
+ "name": "left_knee",
+ "x": 0.8213318586349487,
+ "y": 0.516678512096405
+ },
+ {
+ "name": "right_knee",
+ "x": 0.7963972687721252,
+ "y": 0.5197720527648926
+ }
+]
\ No newline at end of file
diff --git a/Backend/arPoseLandmarks/downward_dog/downward_dog_pose.jpg b/Backend/arPoseLandmarks/downward_dog/downward_dog_pose.jpg
new file mode 100644
index 00000000..28bed08c
Binary files /dev/null and b/Backend/arPoseLandmarks/downward_dog/downward_dog_pose.jpg differ
diff --git a/Backend/arPoseLandmarks/extract_pose.py b/Backend/arPoseLandmarks/extract_pose.py
new file mode 100644
index 00000000..031679cd
--- /dev/null
+++ b/Backend/arPoseLandmarks/extract_pose.py
@@ -0,0 +1,89 @@
+import cv2
+import mediapipe as mp
+import json
+import os
+
+print("[INFO] Initializing MediaPipe Pose...")
+mp_pose = mp.solutions.pose
+pose = mp_pose.Pose(
+ static_image_mode=True,
+ model_complexity=1,
+ min_detection_confidence=0.5,
+ min_tracking_confidence=0.5
+)
+mp_drawing = mp.solutions.drawing_utils
+
+# Update video path for Warrior II pose
+video_path = "../../CeylonCare/CeylonCare/assets/videos/warrior_ii.mp4" # Relative path
+output_image_path = "warrior_ii/warrior_ii.jpg"
+output_json_path = "warrior_ii/warrior_ii_landmarks.json"
+
+# Create output directories if they don't exist
+os.makedirs(os.path.dirname(output_image_path), exist_ok=True)
+os.makedirs(os.path.dirname(output_json_path), exist_ok=True)
+
+if not os.path.exists(video_path):
+ print(f"[ERROR] Video file not found at: {video_path}")
+ print("[INFO] Ensure the video is in ../../CeylonCare/CeylonCare/assets/videos/")
+ exit()
+
+print("[INFO] Loading video...")
+cap = cv2.VideoCapture(video_path)
+if not cap.isOpened():
+ print("[ERROR] Could not open video.")
+ exit()
+
+fps = cap.get(cv2.CAP_PROP_FPS)
+total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
+print(f"[DEBUG] Video FPS: {fps}, Total Frames: {total_frames}")
+
+# Adjust target time based on when the Warrior II pose is held in the video
+target_time = 5 # Adjust this based on your video
+target_frame = int(fps * target_time) if int(fps * target_time) < total_frames else total_frames - 1
+print(f"[DEBUG] Targeting frame {target_frame} at {target_time} seconds")
+cap.set(cv2.CAP_PROP_POS_FRAMES, target_frame)
+
+success, frame = cap.read()
+if not success:
+ print("[ERROR] Failed to read frame.")
+ cap.release()
+ exit()
+
+print("[INFO] Processing frame for pose detection...")
+rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
+results = pose.process(rgb_frame)
+
+if not results.pose_landmarks:
+ print("[ERROR] No pose detected.")
+ cv2.imwrite(output_image_path, frame)
+ print(f"[DEBUG] Frame saved as {output_image_path}")
+ cap.release()
+ exit()
+
+mp_drawing.draw_landmarks(frame, results.pose_landmarks, mp_pose.POSE_CONNECTIONS)
+cv2.imwrite(output_image_path, frame)
+print(f"[INFO] Frame saved as {output_image_path}")
+
+# Extract landmarks
+landmarks = results.pose_landmarks.landmark
+correct_pose = [
+ {"name": "left_shoulder", "x": landmarks[11].x, "y": landmarks[11].y},
+ {"name": "right_shoulder", "x": landmarks[12].x, "y": landmarks[12].y},
+ {"name": "left_elbow", "x": landmarks[13].x, "y": landmarks[13].y},
+ {"name": "right_elbow", "x": landmarks[14].x, "y": landmarks[14].y},
+ {"name": "left_hip", "x": landmarks[23].x, "y": landmarks[23].y},
+ {"name": "right_hip", "x": landmarks[24].x, "y": landmarks[24].y},
+ {"name": "left_knee", "x": landmarks[25].x, "y": landmarks[25].y},
+ {"name": "right_knee", "x": landmarks[26].x, "y": landmarks[26].y}
+]
+print("[DEBUG] Extracted landmarks:")
+for landmark in correct_pose:
+ print(f"[DEBUG] {landmark['name']}: x={landmark['x']:.3f}, y={landmark['y']:.3f}")
+
+with open(output_json_path, 'w') as f:
+ json.dump(correct_pose, f, indent=2)
+print(f"[INFO] Landmarks saved to {output_json_path}")
+
+cap.release()
+pose.close()
+print("[INFO] Script completed!")
\ No newline at end of file
diff --git a/Backend/arPoseLandmarks/triangle_pose/triangle_pose.jpg b/Backend/arPoseLandmarks/triangle_pose/triangle_pose.jpg
new file mode 100644
index 00000000..f1d6b5e8
Binary files /dev/null and b/Backend/arPoseLandmarks/triangle_pose/triangle_pose.jpg differ
diff --git a/Backend/arPoseLandmarks/triangle_pose/triangle_pose_landmarks.json b/Backend/arPoseLandmarks/triangle_pose/triangle_pose_landmarks.json
new file mode 100644
index 00000000..9926b205
--- /dev/null
+++ b/Backend/arPoseLandmarks/triangle_pose/triangle_pose_landmarks.json
@@ -0,0 +1,42 @@
+[
+ {
+ "name": "left_shoulder",
+ "x": 0.393909215927124,
+ "y": 0.5337827205657959
+ },
+ {
+ "name": "right_shoulder",
+ "x": 0.41303548216819763,
+ "y": 0.4024796485900879
+ },
+ {
+ "name": "left_elbow",
+ "x": 0.39781999588012695,
+ "y": 0.6615622043609619
+ },
+ {
+ "name": "right_elbow",
+ "x": 0.3966938853263855,
+ "y": 0.2836398184299469
+ },
+ {
+ "name": "left_hip",
+ "x": 0.50235915184021,
+ "y": 0.576718270778656
+ },
+ {
+ "name": "right_hip",
+ "x": 0.5291388630867004,
+ "y": 0.5406009554862976
+ },
+ {
+ "name": "left_knee",
+ "x": 0.4347962439060211,
+ "y": 0.7202959656715393
+ },
+ {
+ "name": "right_knee",
+ "x": 0.5943127870559692,
+ "y": 0.698548436164856
+ }
+]
\ No newline at end of file
diff --git a/Backend/arPoseLandmarks/warrior_ii/warrior_ii.jpg b/Backend/arPoseLandmarks/warrior_ii/warrior_ii.jpg
new file mode 100644
index 00000000..6665e044
Binary files /dev/null and b/Backend/arPoseLandmarks/warrior_ii/warrior_ii.jpg differ
diff --git a/Backend/arPoseLandmarks/warrior_ii/warrior_ii_landmarks.json b/Backend/arPoseLandmarks/warrior_ii/warrior_ii_landmarks.json
new file mode 100644
index 00000000..69fda1dc
--- /dev/null
+++ b/Backend/arPoseLandmarks/warrior_ii/warrior_ii_landmarks.json
@@ -0,0 +1,42 @@
+[
+ {
+ "name": "left_shoulder",
+ "x": 0.5757824182510376,
+ "y": 0.30987370014190674
+ },
+ {
+ "name": "right_shoulder",
+ "x": 0.48430055379867554,
+ "y": 0.3139100670814514
+ },
+ {
+ "name": "left_elbow",
+ "x": 0.650972843170166,
+ "y": 0.32717323303222656
+ },
+ {
+ "name": "right_elbow",
+ "x": 0.40994828939437866,
+ "y": 0.3287721872329712
+ },
+ {
+ "name": "left_hip",
+ "x": 0.5621575117111206,
+ "y": 0.5378085374832153
+ },
+ {
+ "name": "right_hip",
+ "x": 0.5064576864242554,
+ "y": 0.5383180379867554
+ },
+ {
+ "name": "left_knee",
+ "x": 0.6146337985992432,
+ "y": 0.6881082057952881
+ },
+ {
+ "name": "right_knee",
+ "x": 0.44796282052993774,
+ "y": 0.6910121440887451
+ }
+]
\ No newline at end of file
diff --git a/Backend/ar_model/pose_service.py b/Backend/ar_model/pose_service.py
new file mode 100644
index 00000000..deb38824
--- /dev/null
+++ b/Backend/ar_model/pose_service.py
@@ -0,0 +1,69 @@
+from flask import Flask, request, jsonify
+import cv2
+import mediapipe as mp
+import base64
+import numpy as np
+import logging
+import traceback
+
+# Set up logging for debugging and error tracking
+logging.basicConfig(level=logging.DEBUG)
+logger = logging.getLogger(__name__)
+
+app = Flask(__name__)
+mp_pose = mp.solutions.pose
+
+# Initialize MediaPipe Pose model with higher confidence thresholds
+pose = mp_pose.Pose(min_detection_confidence=0.7, min_tracking_confidence=0.7)
+
+@app.route('/process_frame', methods=['POST'])
+def process_frame():
+ try:
+ # Log incoming request
+ logger.info('[DEBUG] Received request to process frame')
+
+ # Get JSON data from request
+ data = request.json
+ if not data or 'frame' not in data:
+ logger.error('[ERROR] Invalid request: Missing frame data')
+ return jsonify({'error': 'Missing frame data'}), 400
+
+ # Extract and log frame data
+ frame_base64 = data['frame']
+ logger.debug('[DEBUG] Frame base64 length: %d', len(frame_base64))
+
+ # Decode base64 string to image
+ frame = base64.b64decode(frame_base64)
+ image = cv2.imdecode(np.frombuffer(frame, np.uint8), cv2.IMREAD_COLOR)
+ if image is None:
+ logger.error('[ERROR] Failed to decode image')
+ return jsonify({'error': 'Failed to decode image'}), 400
+
+ # Log image details
+ logger.debug('[DEBUG] Image decoded, shape: %s', image.shape)
+
+ # Convert image to RGB for MediaPipe processing
+ image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
+ results = pose.process(image_rgb)
+
+ # Process pose detection results
+ if results.pose_landmarks:
+ landmarks = [
+ {'name': f'landmark_{i}', 'x': lm.x, 'y': lm.y, 'z': lm.z}
+ for i, lm in enumerate(results.pose_landmarks.landmark)
+ ]
+ logger.info('[DEBUG] Pose landmarks detected: %d', len(landmarks))
+ return jsonify({'landmarks': landmarks})
+ else:
+ logger.warning('[WARN] No pose landmarks detected')
+ return jsonify({'landmarks': []})
+
+ except Exception as e:
+ # Log detailed error information
+ logger.error('[ERROR] Error processing frame: %s', str(e))
+ logger.error('[ERROR] Traceback: %s', traceback.format_exc())
+ return jsonify({'error': str(e)}), 500
+
+if __name__ == '__main__':
+ logger.info('[INFO] Starting pose detection service on http://0.0.0.0:5002')
+ app.run(host='0.0.0.0', port=5002, debug=True)
\ No newline at end of file
diff --git a/Backend/controllers/arController.js b/Backend/controllers/arController.js
index a730ca29..0334e87b 100644
--- a/Backend/controllers/arController.js
+++ b/Backend/controllers/arController.js
@@ -14,7 +14,7 @@ const getARRecommendations = async (req, res) => {
console.log(`[DEBUG] Received request to fetch therapy for user: ${userId}`);
try {
- const response = await axios.get(`http://localhost:5000/healthData/${userId}`);
+ const response = await axios.get(`http://192.168.60.22:5000/healthData/${userId}`);
console.log(`[DEBUG] Fetching health data for user: ${userId}, Response status: ${response.status}`);
if (response.status !== 200) {
@@ -24,7 +24,7 @@ const getARRecommendations = async (req, res) => {
const userHealthData = response.data;
console.log("[DEBUG] Fetched user health data:", JSON.stringify(userHealthData, null, 2));
- const flaskResponse = await axios.post("http://localhost:5001/predict", userHealthData);
+ const flaskResponse = await axios.post("http://192.168.60.22:5001/predict", userHealthData);
console.log("[DEBUG] Flask API Full Response:", JSON.stringify(flaskResponse.data, null, 2));
diff --git a/Backend/controllers/chatController.js b/Backend/controllers/chatController.js
index d3f9b1b1..41e740fc 100644
--- a/Backend/controllers/chatController.js
+++ b/Backend/controllers/chatController.js
@@ -33,7 +33,7 @@ const getChatRecommendation = async (req, res) => {
console.log(`[DEBUG] User health condition: ${userHealthData.healthCondition || 'general'}`);
// Send chat message and health condition to Flask app
- const flaskResponse = await axios.post("http://localhost:5001/chat", {
+ const flaskResponse = await axios.post("http://192.168.60.22:5001/chat", {
message: userInput,
userId: userId,
healthCondition: userHealthData.healthCondition || "general",
diff --git a/Backend/controllers/riskAssessController.js b/Backend/controllers/riskAssessController.js
new file mode 100644
index 00000000..0aeafb6b
--- /dev/null
+++ b/Backend/controllers/riskAssessController.js
@@ -0,0 +1,366 @@
+const { doc, setDoc, getDoc, deleteDoc, collection, getDocs, query, where } = require("firebase/firestore");
+const { db } = require("../firebaseConfig");
+
+// Get Risk Assessment Data by ID
+const getRiskAssessmentById = async (req, res) => {
+ const { id } = req.params;
+ console.log("[DEBUG] Fetching risk assessment data by ID:", id);
+
+ try {
+ const riskAssessRef = doc(db, "riskAssessments", id);
+ const riskAssessSnapshot = await getDoc(riskAssessRef);
+
+ if (riskAssessSnapshot.exists()) {
+ console.log("[DEBUG] Risk assessment data found for ID:", id);
+ res.status(200).json(riskAssessSnapshot.data());
+ } else {
+ console.log("[DEBUG] No risk assessment data found for ID:", id);
+ res.status(404).json({ error: "Risk assessment data not found" });
+ }
+ } catch (error) {
+ console.error(
+ "[ERROR] Error fetching risk assessment data for ID:",
+ id,
+ error.message
+ );
+ res.status(500).json({ error: "Failed to fetch risk assessment data" });
+ }
+};
+
+// Get Risk Assessment Data by User ID
+const getRiskAssessmentByUserId = async (req, res) => {
+ const { userId } = req.params;
+ console.log("[DEBUG] Fetching risk assessment data for user:", userId);
+
+ try {
+ const riskAssessQuery = query(
+ collection(db, "riskAssessments"),
+ where("userId", "==", userId)
+ );
+ const riskAssessSnapshot = await getDocs(riskAssessQuery);
+
+ if (!riskAssessSnapshot.empty) {
+ const riskAssessments = [];
+ riskAssessSnapshot.forEach((doc) => {
+ riskAssessments.push({
+ id: doc.id,
+ ...doc.data(),
+ });
+ });
+ console.log("[DEBUG] Risk assessment data found for user:", userId);
+ res.status(200).json(riskAssessments);
+ } else {
+ console.log("[DEBUG] No risk assessment data found for user:", userId);
+ res.status(200).json([]); // Return empty array for users with no assessments
+ }
+ } catch (error) {
+ console.error(
+ "[ERROR] Error fetching risk assessment data for user:",
+ userId,
+ error.message
+ );
+ res.status(500).json({ error: "Failed to fetch risk assessment data" });
+ }
+};
+
+// Get All Risk Assessments
+const getAllRiskAssessments = async (req, res) => {
+ console.log("[DEBUG] Fetching all risk assessment data");
+
+ try {
+ const riskAssessSnapshot = await getDocs(collection(db, "riskAssessments"));
+ const riskAssessments = [];
+
+ riskAssessSnapshot.forEach((doc) => {
+ riskAssessments.push({
+ id: doc.id,
+ ...doc.data(),
+ });
+ });
+
+ console.log("[DEBUG] Successfully fetched all risk assessment data");
+ res.status(200).json(riskAssessments);
+ } catch (error) {
+ console.error(
+ "[ERROR] Error fetching all risk assessment data:",
+ error.message
+ );
+ res.status(500).json({ error: "Failed to fetch risk assessment data" });
+ }
+};
+
+// Create Risk Assessment
+const createRiskAssessment = async (req, res) => {
+ console.log("[DEBUG] Creating new risk assessment");
+ console.log("[DEBUG] Request Body:", req.body);
+
+ try {
+ const {
+ userId,
+ username,
+ age,
+ weight,
+ height,
+ bmi,
+ gender,
+ heartDisease,
+ avgGlucoseLevel,
+ bloodGlucoseLevel,
+ hba1cLevel,
+ smokingStatus,
+ workType,
+ residenceType,
+ hypertension,
+ diabetes
+ } = req.body;
+
+ if (!userId) {
+ return res.status(400).json({ error: "User ID is required" });
+ }
+
+ // Generate a unique ID for the risk assessment
+ const riskAssessId = `risk_${userId}_${Date.now()}`;
+ const riskAssessRef = doc(db, "riskAssessments", riskAssessId);
+
+ // Calculate risk levels
+ let diabetesRiskLevel = "0";
+ let hypertensionRiskLevel = "0";
+
+ // Diabetes risk calculation - only if diabetes is 0 (no diabetes)
+ if (diabetes === "0") {
+ let riskScore = 0;
+
+ if (parseFloat(hba1cLevel) >= 6.5) {
+ diabetesRiskLevel = "high";
+ } else if (parseFloat(hba1cLevel) >= 5.7) {
+ diabetesRiskLevel = "medium";
+ }
+
+ if (parseFloat(bloodGlucoseLevel) >= 7.0) {
+ diabetesRiskLevel = "high";
+ } else if (parseFloat(bloodGlucoseLevel) >= 5.6) {
+ diabetesRiskLevel = "medium";
+ }
+
+ if (diabetesRiskLevel === "0") {
+ if (parseFloat(age) > 60) riskScore++;
+ if (hypertension === "1") riskScore++;
+ if (heartDisease === "1") riskScore++;
+ if (smokingStatus === "formerly smoked") riskScore++;
+ if (smokingStatus === "smokes") riskScore += 2;
+ if (parseFloat(bmi) > 25) riskScore += 2;
+ if (parseFloat(bmi) > 30) riskScore += 3;
+
+ if (riskScore >= 5) diabetesRiskLevel = "high";
+ else if (riskScore >= 3) diabetesRiskLevel = "medium";
+ else if (riskScore > 0) diabetesRiskLevel = "low";
+ }
+ }
+
+ // Hypertension risk calculation - only if hypertension is 0 (no hypertension)
+ if (hypertension === "0") {
+ if (smokingStatus === "smokes") {
+ hypertensionRiskLevel = "high";
+ } else if (parseFloat(age) > 65) {
+ hypertensionRiskLevel = "medium";
+ } else if (heartDisease === "1") {
+ hypertensionRiskLevel = "high";
+ } else if (hypertensionRiskLevel === "0" && (parseFloat(age) > 50 || parseFloat(bmi) > 30)) {
+ hypertensionRiskLevel = "low";
+ }
+ }
+
+ const data = {
+ userId,
+ username: username || "",
+ age: age || "",
+ weight: weight || "",
+ height: height || "",
+ bmi: bmi || "",
+ gender: gender || "",
+ heartDisease: heartDisease || "0",
+ avgGlucoseLevel: avgGlucoseLevel || "",
+ bloodGlucoseLevel: bloodGlucoseLevel || "",
+ hba1cLevel: hba1cLevel || "",
+ smokingStatus: smokingStatus || "never smoked",
+ workType: workType || "",
+ residenceType: residenceType || "",
+ hypertension: hypertension || "0",
+ diabetes: diabetes || "0",
+ diabetes_risk: diabetesRiskLevel,
+ hypertension_risk: hypertensionRiskLevel,
+ createdAt: new Date().toISOString(),
+ };
+
+ await setDoc(riskAssessRef, data);
+ console.log("[DEBUG] Risk assessment successfully created with ID:", riskAssessId);
+
+ res.status(201).json({
+ message: "Risk assessment created successfully",
+ id: riskAssessId,
+ data
+ });
+ } catch (error) {
+ console.error(
+ "[ERROR] Error creating risk assessment:",
+ error.message
+ );
+ res.status(500).json({ error: "Failed to create risk assessment" });
+ }
+}
+
+// Update Risk Assessment
+const updateRiskAssessment = async (req, res) => {
+ const { id } = req.params;
+ console.log("[DEBUG] Updating risk assessment with ID:", id);
+ console.log("[DEBUG] Request Body:", req.body);
+
+ try {
+ const riskAssessRef = doc(db, "riskAssessments", id);
+ const riskAssessSnapshot = await getDoc(riskAssessRef);
+
+ if (!riskAssessSnapshot.exists()) {
+ console.log("[DEBUG] Risk assessment not found with ID:", id);
+ return res.status(404).json({ error: "Risk assessment not found" });
+ }
+
+ const {
+ username,
+ age,
+ weight,
+ height,
+ bmi,
+ gender,
+ heartDisease,
+ avgGlucoseLevel,
+ bloodGlucoseLevel,
+ hba1cLevel,
+ smokingStatus,
+ workType,
+ residenceType,
+ hypertension,
+ diabetes
+ } = req.body;
+
+ // Calculate risk levels
+ let diabetesRiskLevel = "0";
+ let hypertensionRiskLevel = "0";
+
+ // Diabetes risk calculation - only if diabetes is 0 (no diabetes)
+ if (diabetes === "0") {
+ let riskScore = 0;
+
+ if (parseFloat(hba1cLevel) >= 6.5) {
+ diabetesRiskLevel = "high";
+ } else if (parseFloat(hba1cLevel) >= 5.7) {
+ diabetesRiskLevel = "medium";
+ }
+
+ if (parseFloat(bloodGlucoseLevel) >= 7.0) {
+ diabetesRiskLevel = "high";
+ } else if (parseFloat(bloodGlucoseLevel) >= 5.6) {
+ diabetesRiskLevel = "medium";
+ }
+
+ if (diabetesRiskLevel === "0") {
+ if (parseFloat(age) > 60) riskScore++;
+ if (hypertension === "1") riskScore++;
+ if (heartDisease === "1") riskScore++;
+ if (smokingStatus === "formerly smoked") riskScore++;
+ if (smokingStatus === "smokes") riskScore += 2;
+ if (parseFloat(bmi) > 25) riskScore += 2;
+ if (parseFloat(bmi) > 30) riskScore += 3;
+
+ if (riskScore >= 5) diabetesRiskLevel = "high";
+ else if (riskScore >= 3) diabetesRiskLevel = "medium";
+ else if (riskScore > 0) diabetesRiskLevel = "low";
+ }
+ }
+
+ // Hypertension risk calculation - only if hypertension is 0 (no hypertension)
+ if (hypertension === "0") {
+ if (smokingStatus === "smokes") {
+ hypertensionRiskLevel = "high";
+ } else if (parseFloat(age) > 65) {
+ hypertensionRiskLevel = "medium";
+ } else if (heartDisease === "1") {
+ hypertensionRiskLevel = "high";
+ } else if (hypertensionRiskLevel === "0" && (parseFloat(age) > 50 || parseFloat(bmi) > 30)) {
+ hypertensionRiskLevel = "low";
+ }
+ }
+
+ const data = {
+ username: username || riskAssessSnapshot.data().username,
+ age: age || riskAssessSnapshot.data().age,
+ weight: weight || riskAssessSnapshot.data().weight,
+ height: height || riskAssessSnapshot.data().height,
+ bmi: bmi || riskAssessSnapshot.data().bmi,
+ gender: gender || riskAssessSnapshot.data().gender,
+ heartDisease: heartDisease || riskAssessSnapshot.data().heartDisease,
+ avgGlucoseLevel: avgGlucoseLevel || riskAssessSnapshot.data().avgGlucoseLevel,
+ bloodGlucoseLevel: bloodGlucoseLevel || riskAssessSnapshot.data().bloodGlucoseLevel,
+ hba1cLevel: hba1cLevel || riskAssessSnapshot.data().hba1cLevel,
+ smokingStatus: smokingStatus || riskAssessSnapshot.data().smokingStatus,
+ workType: workType || riskAssessSnapshot.data().workType,
+ residenceType: residenceType || riskAssessSnapshot.data().residenceType,
+ hypertension: hypertension || riskAssessSnapshot.data().hypertension,
+ diabetes: diabetes || riskAssessSnapshot.data().diabetes || "0",
+ diabetes_risk: diabetesRiskLevel,
+ hypertension_risk: hypertensionRiskLevel,
+ updatedAt: new Date().toISOString(),
+ };
+
+ await setDoc(riskAssessRef, data, { merge: true });
+ console.log("[DEBUG] Risk assessment successfully updated with ID:", id);
+
+ res.status(200).json({
+ message: "Risk assessment updated successfully",
+ data
+ });
+ } catch (error) {
+ console.error(
+ "[ERROR] Error updating risk assessment:",
+ id,
+ error.message
+ );
+ res.status(500).json({ error: "Failed to update risk assessment" });
+ }
+};
+
+// Delete Risk Assessment
+const deleteRiskAssessment = async (req, res) => {
+ const { id } = req.params;
+ console.log("[DEBUG] Deleting risk assessment with ID:", id);
+
+ try {
+ const riskAssessRef = doc(db, "riskAssessments", id);
+ const riskAssessSnapshot = await getDoc(riskAssessRef);
+
+ if (!riskAssessSnapshot.exists()) {
+ console.log("[DEBUG] Risk assessment not found with ID:", id);
+ return res.status(404).json({ error: "Risk assessment not found" });
+ }
+
+ await deleteDoc(riskAssessRef);
+ console.log("[DEBUG] Risk assessment successfully deleted with ID:", id);
+
+ res.status(200).json({ message: "Risk assessment deleted successfully" });
+ } catch (error) {
+ console.error(
+ "[ERROR] Error deleting risk assessment:",
+ id,
+ error.message
+ );
+ res.status(500).json({ error: "Failed to delete risk assessment" });
+ }
+};
+
+module.exports = {
+ getRiskAssessmentById,
+ getRiskAssessmentByUserId,
+ getAllRiskAssessments,
+ createRiskAssessment,
+ updateRiskAssessment,
+ deleteRiskAssessment,
+};
diff --git a/Backend/index.js b/Backend/index.js
index da9e2121..3b1dd5bc 100644
--- a/Backend/index.js
+++ b/Backend/index.js
@@ -17,6 +17,7 @@ const {
} = require("./controllers/healthController");
const { getChatRecommendation } = require("./controllers/chatController");
const { getARRecommendations, getTherapyDetails } = require("./controllers/arController");
+const { getRiskAssessmentById, getRiskAssessmentByUserId, getAllRiskAssessments, createRiskAssessment, updateRiskAssessment, deleteRiskAssessment } = require("./controllers/riskAssessController");
const app = express();
app.use(cors({ origin: "*" }));
@@ -43,9 +44,17 @@ app.get("/therapy_details/:therapyName", getTherapyDetails);
// Chatbot Routes
app.post('/healthChat/:userId', getChatRecommendation);
+// Risk Assessment Routes
+app.get("/riskassessment/:id", getRiskAssessmentById);
+app.get("/riskassessment/user/:userId", getRiskAssessmentByUserId);
+app.get("/riskassessments", getAllRiskAssessments);
+app.post("/riskassessment", createRiskAssessment);
+app.put("/riskassessment/:id", updateRiskAssessment);
+app.delete("/riskassessment/:id", deleteRiskAssessment);
+
const PORT = 5000;
app.listen(PORT, () => {
- console.log(`[DEBUG] Backend server running at http://localhost:${PORT}`);
+ console.log(`[DEBUG] Backend server running at http://192.168.60.22:${PORT}`);
console.log('[DEBUG] Registered routes:', app._router.stack
.filter(r => r.route)
.map(r => `${r.route.path} (${Object.keys(r.route.methods).join(', ')})`));
diff --git a/Backend/package.json b/Backend/package.json
index 1d460adf..2e2b738f 100644
--- a/Backend/package.json
+++ b/Backend/package.json
@@ -3,6 +3,8 @@
"version": "1.0.0",
"main": "index.js",
"scripts": {
+ "start": "node index.js",
+ "dev": "nodemon index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
diff --git a/CeylonCare/app/_layout.tsx b/CeylonCare/app/_layout.tsx
index 55003862..29a19b46 100644
--- a/CeylonCare/app/_layout.tsx
+++ b/CeylonCare/app/_layout.tsx
@@ -16,6 +16,9 @@ import ChatScreen from "./pages/Chatbot_component/ChatScreen";
import TherapyRecommendations from "./pages/AR_component/TherapyRecommendations";
import TherapyDetails from "./pages/AR_component/TherapyDetails";
import ARAvatarScreen from "./pages/AR_component/ARAvatarScreen";
+import ViewHealthRisk from "./pages/HealthRisk/ViewHealthRisk";
+import AddHealthRisk from "./pages/HealthRisk/AddHealthRisk";
+import EditHealthRisk from "./pages/HealthRisk/EditHealthRisk";
const Stack = createStackNavigator();
@@ -99,6 +102,24 @@ const StackNavigator = () => {
component={ChatScreen}
options={{ headerShown: false }}
/>
+
+
+
+
+
+
);
};
diff --git a/CeylonCare/app/pages/AR_component/CameraTest.tsx b/CeylonCare/app/pages/AR_component/CameraTest.tsx
new file mode 100644
index 00000000..9a4528e9
--- /dev/null
+++ b/CeylonCare/app/pages/AR_component/CameraTest.tsx
@@ -0,0 +1,69 @@
+import { CameraView, CameraType, useCameraPermissions } from 'expo-camera';
+import { useState } from 'react';
+import { Button, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
+
+export default function App() {
+ const [facing, setFacing] = useState('back');
+ const [permission, requestPermission] = useCameraPermissions();
+
+ if (!permission) {
+ // Camera permissions are still loading.
+ return ;
+ }
+
+ if (!permission.granted) {
+ // Camera permissions are not granted yet.
+ return (
+
+ We need your permission to show the camera
+
+
+ );
+ }
+
+ function toggleCameraFacing() {
+ setFacing(current => (current === 'back' ? 'front' : 'back'));
+ }
+
+ return (
+
+
+
+
+ Flip Camera
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ },
+ message: {
+ textAlign: 'center',
+ paddingBottom: 10,
+ },
+ camera: {
+ flex: 1,
+ },
+ buttonContainer: {
+ flex: 1,
+ flexDirection: 'row',
+ backgroundColor: 'transparent',
+ margin: 64,
+ },
+ button: {
+ flex: 1,
+ alignSelf: 'flex-end',
+ alignItems: 'center',
+ },
+ text: {
+ fontSize: 24,
+ fontWeight: 'bold',
+ color: 'white',
+ },
+});
diff --git a/CeylonCare/app/pages/HealthRisk/AddHealthRisk.tsx b/CeylonCare/app/pages/HealthRisk/AddHealthRisk.tsx
new file mode 100644
index 00000000..4441757e
--- /dev/null
+++ b/CeylonCare/app/pages/HealthRisk/AddHealthRisk.tsx
@@ -0,0 +1,535 @@
+import React, { useState, useEffect } from 'react';
+import {
+ View, Text, TextInput, StyleSheet, TouchableOpacity,
+ ScrollView, SafeAreaView, StatusBar, Alert
+} from 'react-native';
+import { Picker } from '@react-native-picker/picker';
+import { RadioButton } from 'react-native-paper';
+import AsyncStorage from '@react-native-async-storage/async-storage';
+
+interface FormData {
+ userId: string;
+ username: string;
+ age: string;
+ weight: string;
+ height: string;
+ bmi: string;
+ gender: string;
+ heartDisease: string;
+ avgGlucoseLevel: string;
+ bloodGlucoseLevel: string;
+ hba1cLevel: string;
+ smokingStatus: string;
+ workType: string;
+ residenceType: string;
+ hypertension: string;
+ diabetes: string;
+}
+
+const AddHealthRisk = ({ navigation }: any) => {
+ const [formData, setFormData] = useState({
+ userId: '',
+ username: '',
+ age: '',
+ weight: '',
+ height: '',
+ bmi: '',
+ gender: '',
+ heartDisease: '0',
+ avgGlucoseLevel: '',
+ bloodGlucoseLevel: '',
+ hba1cLevel: '',
+ smokingStatus: 'never smoked',
+ workType: '',
+ residenceType: '',
+ hypertension: '0',
+ diabetes: '0',
+ });
+ const [warnings, setWarnings] = useState([]);
+ const [diabetesResult, setDiabetesResult] = useState('');
+ const [hypertensionResult, setHypertensionResult] = useState('');
+
+ useEffect(() => {
+ calculateBMI();
+ }, [formData.height, formData.weight]);
+
+ const calculateBMI = () => {
+ const height = parseFloat(formData.height);
+ const weight = parseFloat(formData.weight);
+
+ if (height > 0 && weight > 0) {
+ const bmi = (weight / (height * height)).toFixed(2);
+ setFormData(prev => ({ ...prev, bmi }));
+ }
+ };
+
+ const handleInputChange = (name: keyof FormData, value: string) => {
+ setFormData(prev => ({ ...prev, [name]: value }));
+ };
+
+ const validateForm = (): boolean => {
+ const newWarnings: string[] = [];
+
+ if (parseFloat(formData.age) <= 0 || parseFloat(formData.age) > 120) {
+ newWarnings.push("⚠ Age must be between 1 and 120.");
+ }
+
+ if (parseFloat(formData.weight) <= 0 || parseFloat(formData.weight) > 300) {
+ newWarnings.push("⚠ Weight must be between 1 and 300 kg.");
+ }
+
+ if (parseFloat(formData.height) <= 0.5 || parseFloat(formData.height) > 2.5) {
+ newWarnings.push("⚠ Height must be between 0.5 and 2.5 meters.");
+ }
+
+ if (parseFloat(formData.avgGlucoseLevel) <= 20 || parseFloat(formData.avgGlucoseLevel) > 600) {
+ newWarnings.push("⚠ Average glucose level is medically impossible.");
+ }
+
+ if (parseFloat(formData.bloodGlucoseLevel) < 2 || parseFloat(formData.bloodGlucoseLevel) > 30) {
+ newWarnings.push("⚠ Blood Glucose Level must be between 2 and 30 mmol/L.");
+ }
+
+ if (parseFloat(formData.hba1cLevel) < 2 || parseFloat(formData.hba1cLevel) > 20) {
+ newWarnings.push("⚠ HbA1c Level must be between 2% and 20%.");
+ }
+
+ setWarnings(newWarnings);
+ return newWarnings.length === 0;
+ };
+
+ const calculateHypertensionRisk = () => {
+ // Simplified risk calculation logic for hypertension
+ let riskLevel = "Low Risk";
+
+ // Basic hypertension risk assessment
+ if (formData.smokingStatus === "smokes") {
+ riskLevel = "High Risk";
+ } else if (parseFloat(formData.age) > 65) {
+ riskLevel = "Medium Risk";
+ } else if (formData.heartDisease === "1") {
+ riskLevel = "High Risk";
+ }
+
+ setHypertensionResult(`Hypertension Risk: ${riskLevel}`);
+ };
+
+ const calculateDiabetesRisk = () => {
+ let riskScore = 0;
+ let riskLevel = "Low Risk";
+
+ // Simplified diabetes risk calculation
+ if (parseFloat(formData.hba1cLevel) >= 6.5) {
+ riskLevel = "High Risk";
+ } else if (parseFloat(formData.hba1cLevel) >= 5.7) {
+ riskLevel = "Medium Risk";
+ }
+
+ if (parseFloat(formData.bloodGlucoseLevel) >= 7.0) {
+ riskLevel = "High Risk";
+ } else if (parseFloat(formData.bloodGlucoseLevel) >= 5.6) {
+ riskLevel = "Medium Risk";
+ }
+
+ if (riskLevel === "Low Risk") {
+ if (parseFloat(formData.age) > 60) riskScore++;
+ if (formData.hypertension === "1") riskScore++;
+ if (formData.heartDisease === "1") riskScore++;
+ if (formData.smokingStatus === "formerly smoked") riskScore++;
+ if (formData.smokingStatus === "smokes") riskScore += 2;
+ if (parseFloat(formData.bmi) > 25) riskScore += 2;
+ if (parseFloat(formData.bmi) > 30) riskScore += 3;
+
+ if (riskScore >= 5) riskLevel = "High Risk";
+ else if (riskScore >= 3) riskLevel = "Medium Risk";
+ else if (riskScore === 0) riskLevel = "No Risk";
+ }
+
+ setDiabetesResult(`Diabetes Risk: ${riskLevel}`);
+ };
+
+ const handleSubmit = async () => {
+ if (validateForm()) {
+ calculateHypertensionRisk();
+ calculateDiabetesRisk();
+ const userId = await AsyncStorage.getItem("userId");
+ const userName = await AsyncStorage.getItem("userName"); // Add this line
+
+ if (userId) {
+ formData.userId = userId;
+ formData.username = userName || ""; // Add this line
+ }
+
+ try {
+ console.log("Sending health risk data to backend...");
+ const response = await fetch("http://192.168.60.22:5000/riskassessment", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(formData),
+ });
+
+ const responseData = await response.json();
+ console.log("Response from backend:", responseData);
+
+ if (response.ok) {
+ Alert.alert("Success", "Health risk assessment completed successfully");
+ // You can navigate to a results page if needed
+ navigation.navigate("ViewHealthRisk");
+ } else {
+ throw new Error(responseData.error || "Assessment submission failed");
+ }
+ } catch (error: any) {
+ console.error("Error in health risk assessment:", error.message);
+ Alert.alert("Error", error.message);
+ }
+ } else {
+ Alert.alert("Error", "Please fill in all required fields correctly.");
+ }
+ };
+
+ return (
+
+
+
+ Comprehensive Health Risk Assessment
+
+
+ {/* Basic Information */}
+
+ Basic Information
+
+
+
+ Age (years):
+ handleInputChange('age', value)}
+ />
+
+
+
+ Gender:
+
+ handleInputChange('gender', value)}
+ >
+
+
+ Male
+
+
+
+ Female
+
+
+
+
+
+
+ Weight (kg):
+ handleInputChange('weight', value)}
+ />
+
+
+
+ Height (m):
+ handleInputChange('height', value)}
+ />
+
+
+
+ BMI (auto-calculated):
+
+
+
+ {/* Medical History */}
+
+ Medical History
+
+
+
+ Heart Disease:
+
+ handleInputChange('heartDisease', value)}
+ >
+
+
+ No
+
+
+
+ Yes
+
+
+
+
+
+
+ Hypertension:
+
+ handleInputChange('hypertension', value)}
+ >
+
+
+ No
+
+
+
+ Yes
+
+
+
+
+
+
+ Diabetes:
+
+ handleInputChange('diabetes', value)}
+ >
+
+
+ No
+
+
+
+ Yes
+
+
+
+
+
+ {/* Lifestyle */}
+
+ Lifestyle
+
+
+
+ Smoking Status:
+ handleInputChange('smokingStatus', value)}
+ style={styles.picker}
+ >
+
+
+
+
+
+
+
+ Work Type:
+ handleInputChange('workType', value)}
+ style={styles.picker}
+ >
+
+
+
+
+
+
+
+
+
+ Residence Type:
+ handleInputChange('residenceType', value)}
+ style={styles.picker}
+ >
+
+
+
+
+
+
+ {/* Glucose Measurements */}
+
+ Glucose Measurements
+
+
+
+ Average Glucose Level (mg/dL):
+ handleInputChange('avgGlucoseLevel', value)}
+ />
+
+
+
+ Blood Glucose Level (mmol/L):
+ handleInputChange('bloodGlucoseLevel', value)}
+ />
+
+
+
+ HbA1c Level (%):
+ handleInputChange('hba1cLevel', value)}
+ />
+
+
+
+ Assess Health Risks
+
+
+ {warnings.length > 0 && (
+
+ {warnings.map((warning, index) => (
+ {warning}
+ ))}
+
+ )}
+
+ {(diabetesResult !== '' || hypertensionResult !== '') && (
+
+ {hypertensionResult !== '' && (
+ {hypertensionResult}
+ )}
+ {diabetesResult !== '' && (
+ {diabetesResult}
+ )}
+
+ )}
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ safeArea: {
+ flex: 1,
+ backgroundColor: '#e0f7fa',
+ },
+ container: {
+ flex: 1,
+ padding: 20,
+ },
+ title: {
+ fontSize: 24,
+ fontWeight: 'bold',
+ color: '#004d40',
+ textAlign: 'center',
+ marginBottom: 20,
+ },
+ formContainer: {
+ backgroundColor: '#ffffffcc',
+ borderRadius: 10,
+ padding: 15,
+ },
+ sectionHeader: {
+ backgroundColor: '#80deea',
+ padding: 10,
+ borderRadius: 5,
+ marginTop: 15,
+ marginBottom: 15,
+ },
+ sectionTitle: {
+ fontWeight: 'bold',
+ color: '#004d40',
+ fontSize: 16,
+ },
+ formGroup: {
+ marginBottom: 15,
+ },
+ label: {
+ fontWeight: 'bold',
+ marginBottom: 5,
+ },
+ input: {
+ borderWidth: 1,
+ borderColor: '#bbb',
+ borderRadius: 5,
+ padding: 8,
+ fontSize: 14,
+ },
+ readonlyInput: {
+ backgroundColor: '#f5f5f5',
+ },
+ picker: {
+ borderWidth: 1,
+ borderColor: '#bbb',
+ borderRadius: 5,
+ },
+ radioGroup: {
+ flexDirection: 'row',
+ },
+ radioOption: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ marginRight: 20,
+ },
+ button: {
+ backgroundColor: '#00695c',
+ padding: 15,
+ borderRadius: 5,
+ alignItems: 'center',
+ marginTop: 20,
+ marginBottom: 30,
+ },
+ buttonText: {
+ color: 'white',
+ fontWeight: 'bold',
+ fontSize: 16,
+ },
+ warningsContainer: {
+ marginTop: 15,
+ padding: 10,
+ backgroundColor: '#ffe6e6',
+ borderRadius: 5,
+ marginBottom: 20,
+ },
+ warningText: {
+ color: 'red',
+ marginBottom: 5,
+ },
+ resultsContainer: {
+ marginTop: 20,
+ padding: 15,
+ backgroundColor: '#e8f5e9',
+ borderRadius: 5,
+ },
+ resultText: {
+ fontSize: 18,
+ fontWeight: 'bold',
+ textAlign: 'center',
+ marginBottom: 10,
+ color: '#004d40',
+ }
+});
+
+export default AddHealthRisk;
diff --git a/CeylonCare/app/pages/HealthRisk/EditHealthRisk.tsx b/CeylonCare/app/pages/HealthRisk/EditHealthRisk.tsx
new file mode 100644
index 00000000..02e0439d
--- /dev/null
+++ b/CeylonCare/app/pages/HealthRisk/EditHealthRisk.tsx
@@ -0,0 +1,592 @@
+import React, { useState, useEffect } from 'react';
+import {
+ View, Text, TextInput, StyleSheet, TouchableOpacity,
+ ScrollView, SafeAreaView, StatusBar, Alert, ActivityIndicator
+} from 'react-native';
+import { Picker } from '@react-native-picker/picker';
+import { RadioButton } from 'react-native-paper';
+import AsyncStorage from '@react-native-async-storage/async-storage';
+
+interface FormData {
+ userId: string;
+ username: string;
+ age: string;
+ weight: string;
+ height: string;
+ bmi: string;
+ gender: string;
+ heartDisease: string;
+ avgGlucoseLevel: string;
+ bloodGlucoseLevel: string;
+ hba1cLevel: string;
+ smokingStatus: string;
+ workType: string;
+ residenceType: string;
+ hypertension: string;
+ diabetes: string;
+}
+
+const EditHealthRisk = ({ route, navigation }: any) => {
+ const { riskData } = route.params;
+ const [formData, setFormData] = useState({
+ userId: riskData.userId || '',
+ username: riskData.username || '',
+ age: riskData.age || '',
+ weight: riskData.weight || '',
+ height: riskData.height || '',
+ bmi: riskData.bmi || '',
+ gender: riskData.gender || '',
+ heartDisease: riskData.heartDisease || '0',
+ avgGlucoseLevel: riskData.avgGlucoseLevel || '',
+ bloodGlucoseLevel: riskData.bloodGlucoseLevel || '',
+ hba1cLevel: riskData.hba1cLevel || '',
+ smokingStatus: riskData.smokingStatus || 'never smoked',
+ workType: riskData.workType || '',
+ residenceType: riskData.residenceType || '',
+ hypertension: riskData.hypertension || '0',
+ diabetes: riskData.diabetes || '0',
+ });
+
+ const [warnings, setWarnings] = useState([]);
+ const [diabetesResult, setDiabetesResult] = useState('');
+ const [hypertensionResult, setHypertensionResult] = useState('');
+ const [isLoading, setIsLoading] = useState(false);
+
+ useEffect(() => {
+ calculateBMI();
+ }, [formData.height, formData.weight]);
+
+ const calculateBMI = () => {
+ const height = parseFloat(formData.height);
+ const weight = parseFloat(formData.weight);
+
+ if (height > 0 && weight > 0) {
+ const bmi = (weight / (height * height)).toFixed(2);
+ setFormData(prev => ({ ...prev, bmi }));
+ }
+ };
+
+ const handleInputChange = (name: keyof FormData, value: string) => {
+ setFormData(prev => ({ ...prev, [name]: value }));
+ };
+
+ const validateForm = (): boolean => {
+ const newWarnings: string[] = [];
+
+ if (parseFloat(formData.age) <= 0 || parseFloat(formData.age) > 120) {
+ newWarnings.push("⚠ Age must be between 1 and 120.");
+ }
+
+ if (parseFloat(formData.weight) <= 0 || parseFloat(formData.weight) > 300) {
+ newWarnings.push("⚠ Weight must be between 1 and 300 kg.");
+ }
+
+ if (parseFloat(formData.height) <= 0.5 || parseFloat(formData.height) > 2.5) {
+ newWarnings.push("⚠ Height must be between 0.5 and 2.5 meters.");
+ }
+
+ if (parseFloat(formData.avgGlucoseLevel) <= 20 || parseFloat(formData.avgGlucoseLevel) > 600) {
+ newWarnings.push("⚠ Average glucose level is medically impossible.");
+ }
+
+ if (parseFloat(formData.bloodGlucoseLevel) < 2 || parseFloat(formData.bloodGlucoseLevel) > 30) {
+ newWarnings.push("⚠ Blood Glucose Level must be between 2 and 30 mmol/L.");
+ }
+
+ if (parseFloat(formData.hba1cLevel) < 2 || parseFloat(formData.hba1cLevel) > 20) {
+ newWarnings.push("⚠ HbA1c Level must be between 2% and 20%.");
+ }
+
+ setWarnings(newWarnings);
+ return newWarnings.length === 0;
+ };
+
+ const calculateHypertensionRisk = () => {
+ // Simplified risk calculation logic for hypertension
+ let riskLevel = "Low Risk";
+
+ // Basic hypertension risk assessment
+ if (formData.smokingStatus === "smokes") {
+ riskLevel = "High Risk";
+ } else if (parseFloat(formData.age) > 65) {
+ riskLevel = "Medium Risk";
+ } else if (formData.heartDisease === "1") {
+ riskLevel = "High Risk";
+ }
+
+ setHypertensionResult(`Hypertension Risk: ${riskLevel}`);
+ return riskLevel;
+ };
+
+ const calculateDiabetesRisk = () => {
+ let riskScore = 0;
+ let riskLevel = "Low Risk";
+
+ // Simplified diabetes risk calculation
+ if (parseFloat(formData.hba1cLevel) >= 6.5) {
+ riskLevel = "High Risk";
+ } else if (parseFloat(formData.hba1cLevel) >= 5.7) {
+ riskLevel = "Medium Risk";
+ }
+
+ if (parseFloat(formData.bloodGlucoseLevel) >= 7.0) {
+ riskLevel = "High Risk";
+ } else if (parseFloat(formData.bloodGlucoseLevel) >= 5.6) {
+ riskLevel = "Medium Risk";
+ }
+
+ if (riskLevel === "Low Risk") {
+ if (parseFloat(formData.age) > 60) riskScore++;
+ if (formData.hypertension === "1") riskScore++;
+ if (formData.heartDisease === "1") riskScore++;
+ if (formData.smokingStatus === "formerly smoked") riskScore++;
+ if (formData.smokingStatus === "smokes") riskScore += 2;
+ if (parseFloat(formData.bmi) > 25) riskScore += 2;
+ if (parseFloat(formData.bmi) > 30) riskScore += 3;
+
+ if (riskScore >= 5) riskLevel = "High Risk";
+ else if (riskScore >= 3) riskLevel = "Medium Risk";
+ else if (riskScore === 0) riskLevel = "No Risk";
+ }
+
+ setDiabetesResult(`Diabetes Risk: ${riskLevel}`);
+ return riskLevel;
+ };
+
+ const handleSubmit = async () => {
+ if (validateForm()) {
+ setIsLoading(true);
+ try {
+ // We don't need to calculate risk levels here as the backend will handle it
+ // Just prepare the data to send
+ const updatedData = {
+ ...formData
+ };
+
+ const response = await fetch(`http:/192.168.60.22:5000/riskassessment/${riskData.id}`, {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(updatedData),
+ });
+
+ const responseData = await response.json();
+
+ if (response.ok) {
+ Alert.alert(
+ "Success",
+ "Health risk assessment updated successfully",
+ [
+ {
+ text: "OK",
+ onPress: () => navigation.navigate("ViewHealthRisk")
+ }
+ ]
+ );
+ } else {
+ throw new Error(responseData.error || "Failed to update health risk assessment");
+ }
+ } catch (error: any) {
+ console.error("Error updating health risk assessment:", error.message);
+ Alert.alert("Error", error.message);
+ } finally {
+ setIsLoading(false);
+ }
+ }
+ };
+
+ return (
+
+
+
+ Edit Health Risk Assessment
+
+ {isLoading ? (
+
+
+ Updating your health risk assessment...
+
+ ) : (
+
+ {/* Basic Information */}
+
+ Basic Information
+
+
+
+ Age (years):
+ handleInputChange('age', value)}
+ />
+
+
+
+ Gender:
+
+ handleInputChange('gender', value)}
+ >
+
+
+ Male
+
+
+
+ Female
+
+
+
+
+
+
+ Weight (kg):
+ handleInputChange('weight', value)}
+ />
+
+
+
+ Height (m):
+ handleInputChange('height', value)}
+ />
+
+
+
+ BMI (auto-calculated):
+
+
+
+ {/* Medical History */}
+
+ Medical History
+
+
+
+ Heart Disease:
+
+ handleInputChange('heartDisease', value)}
+ >
+
+
+ No
+
+
+
+ Yes
+
+
+
+
+
+
+ Hypertension:
+
+ handleInputChange('hypertension', value)}
+ >
+
+
+ No
+
+
+
+ Yes
+
+
+
+
+
+
+ Diabetes:
+
+ handleInputChange('diabetes', value)}
+ >
+
+
+ No
+
+
+
+ Yes
+
+
+
+
+
+ {/* Lifestyle */}
+
+ Lifestyle
+
+
+
+ Smoking Status:
+ handleInputChange('smokingStatus', value)}
+ style={styles.picker}
+ >
+
+
+
+
+
+
+
+ Work Type:
+ handleInputChange('workType', value)}
+ style={styles.picker}
+ >
+
+
+
+
+
+
+
+
+
+ Residence Type:
+ handleInputChange('residenceType', value)}
+ style={styles.picker}
+ >
+
+
+
+
+
+
+ {/* Glucose Measurements */}
+
+ Glucose Measurements
+
+
+
+ Average Glucose Level (mg/dL):
+ handleInputChange('avgGlucoseLevel', value)}
+ />
+
+
+
+ Blood Glucose Level (mmol/L):
+ handleInputChange('bloodGlucoseLevel', value)}
+ />
+
+
+
+ HbA1c Level (%):
+ handleInputChange('hba1cLevel', value)}
+ />
+
+
+
+ navigation.goBack()}
+ >
+ Cancel
+
+
+
+ Update Assessment
+
+
+
+ {warnings.length > 0 && (
+
+ {warnings.map((warning, index) => (
+ {warning}
+ ))}
+
+ )}
+
+ {(diabetesResult !== '' || hypertensionResult !== '') && (
+
+ {hypertensionResult !== '' && (
+ {hypertensionResult}
+ )}
+ {diabetesResult !== '' && (
+ {diabetesResult}
+ )}
+
+ )}
+
+ )}
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ safeArea: {
+ flex: 1,
+ backgroundColor: '#e0f7fa',
+ },
+ container: {
+ flex: 1,
+ padding: 20,
+ },
+ title: {
+ fontSize: 24,
+ fontWeight: 'bold',
+ color: '#004d40',
+ textAlign: 'center',
+ marginBottom: 20,
+ },
+ formContainer: {
+ backgroundColor: '#ffffffcc',
+ borderRadius: 10,
+ padding: 15,
+ },
+ sectionHeader: {
+ backgroundColor: '#80deea',
+ padding: 10,
+ borderRadius: 5,
+ marginTop: 15,
+ marginBottom: 15,
+ },
+ sectionTitle: {
+ fontWeight: 'bold',
+ color: '#004d40',
+ fontSize: 16,
+ },
+ formGroup: {
+ marginBottom: 15,
+ },
+ label: {
+ fontWeight: 'bold',
+ marginBottom: 5,
+ },
+ input: {
+ borderWidth: 1,
+ borderColor: '#bbb',
+ borderRadius: 5,
+ padding: 8,
+ fontSize: 14,
+ },
+ readonlyInput: {
+ backgroundColor: '#f5f5f5',
+ },
+ picker: {
+ borderWidth: 1,
+ borderColor: '#bbb',
+ borderRadius: 5,
+ },
+ radioGroup: {
+ flexDirection: 'row',
+ },
+ radioOption: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ marginRight: 20,
+ },
+ actionButtons: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ marginTop: 20,
+ marginBottom: 10,
+ },
+ updateButton: {
+ backgroundColor: '#00695c',
+ padding: 15,
+ borderRadius: 5,
+ alignItems: 'center',
+ flex: 2,
+ marginLeft: 10,
+ marginBottom: 30,
+ },
+ updateButtonText: {
+ color: 'white',
+ fontWeight: 'bold',
+ fontSize: 16,
+ },
+ cancelButton: {
+ backgroundColor: '#e0e0e0',
+ padding: 15,
+ borderRadius: 5,
+ alignItems: 'center',
+ flex: 1,
+ marginBottom: 30,
+ },
+ cancelButtonText: {
+ color: '#424242',
+ fontWeight: 'bold',
+ fontSize: 16,
+ },
+ warningsContainer: {
+ marginTop: 15,
+ padding: 10,
+ backgroundColor: '#ffe6e6',
+ borderRadius: 5,
+ marginBottom: 20,
+ },
+ warningText: {
+ color: 'red',
+ marginBottom: 5,
+ },
+ resultsContainer: {
+ marginTop: 20,
+ padding: 15,
+ backgroundColor: '#e8f5e9',
+ borderRadius: 5,
+ },
+ resultText: {
+ fontSize: 18,
+ fontWeight: 'bold',
+ textAlign: 'center',
+ marginBottom: 10,
+ color: '#004d40',
+ },
+ loadingContainer: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ loadingText: {
+ marginTop: 12,
+ fontSize: 16,
+ color: '#004d40',
+ }
+});
+
+export default EditHealthRisk;
+
diff --git a/CeylonCare/app/pages/HealthRisk/ViewHealthRisk.tsx b/CeylonCare/app/pages/HealthRisk/ViewHealthRisk.tsx
new file mode 100644
index 00000000..747324fa
--- /dev/null
+++ b/CeylonCare/app/pages/HealthRisk/ViewHealthRisk.tsx
@@ -0,0 +1,500 @@
+import React, { useState, useEffect } from 'react';
+import {
+ View, Text, StyleSheet, TouchableOpacity, FlatList,
+ SafeAreaView, StatusBar, Alert, ActivityIndicator
+} from 'react-native';
+import AsyncStorage from '@react-native-async-storage/async-storage';
+import { Ionicons } from '@expo/vector-icons';
+
+interface HealthRiskData {
+ id: string;
+ userId: string;
+ username: string;
+ age: string;
+ weight: string;
+ height: string;
+ bmi: string;
+ gender: string;
+ heartDisease: string;
+ avgGlucoseLevel: string;
+ bloodGlucoseLevel: string;
+ hba1cLevel: string;
+ smokingStatus: string;
+ workType: string;
+ residenceType: string;
+ hypertension: string;
+ diabetes: string;
+ createdAt: string;
+ diabetes_risk: string;
+ hypertension_risk: string;
+}
+
+const ViewHealthRisk = ({ navigation }: any) => {
+ const [healthRisks, setHealthRisks] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [selectedRisk, setSelectedRisk] = useState(null);
+
+ useEffect(() => {
+ fetchHealthRisks();
+ }, []);
+
+ const fetchHealthRisks = async () => {
+ setLoading(true);
+ try {
+ const userId = await AsyncStorage.getItem("userId");
+ if (!userId) {
+ Alert.alert("Error", "User ID not found. Please log in again.");
+ setLoading(false);
+ return;
+ }
+
+ const userName = await AsyncStorage.getItem("userName");
+
+ const response = await fetch(`http://192.168.60.22:5000/riskassessment/user/${userId}`, {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+
+ const data = await response.json();
+
+ if (response.ok) {
+ const updatedData = data.map((item: HealthRiskData) => {
+ if (!item.username && userName) {
+ return { ...item, username: userName };
+ }
+ return item;
+ });
+
+ setHealthRisks(updatedData || []);
+ } else {
+ throw new Error(data.error || "Failed to fetch health risk assessments");
+ }
+ } catch (error: any) {
+ console.error("Error fetching health risks:", error.message);
+ Alert.alert("Error", error.message);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ const handleDeleteRisk = async (riskId: string) => {
+ Alert.alert(
+ "Confirm Deletion",
+ "Are you sure you want to delete this health risk assessment?",
+ [
+ {
+ text: "Cancel",
+ style: "cancel"
+ },
+ {
+ text: "Delete",
+ style: "destructive",
+ onPress: async () => {
+ try {
+ const response = await fetch(`http://192.168.60.22:5000/riskassessment/${riskId}`, {
+ method: "DELETE",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+
+ const data = await response.json();
+
+ if (response.ok) {
+ // Remove the deleted risk from the state
+ setHealthRisks(prevRisks => prevRisks.filter(risk => risk.id !== riskId));
+ Alert.alert("Success", "Health risk assessment deleted successfully");
+ } else {
+ throw new Error(data.error || "Failed to delete health risk assessment");
+ }
+ } catch (error: any) {
+ console.error("Error deleting health risk:", error.message);
+ Alert.alert("Error", error.message);
+ }
+ }
+ }
+ ]
+ );
+ };
+
+ const handleEditRisk = (risk: HealthRiskData) => {
+ navigation.navigate("EditHealthRisk", { riskData: risk });
+ };
+
+ const toggleRiskSelection = (riskId: string) => {
+ setSelectedRisk(prevSelected => prevSelected === riskId ? null : riskId);
+ };
+
+ const formatDate = (dateString: string) => {
+ const date = new Date(dateString);
+ return date.toLocaleDateString('en-US', {
+ year: 'numeric',
+ month: 'short',
+ day: 'numeric',
+ hour: '2-digit',
+ minute: '2-digit'
+ });
+ };
+
+ const renderRiskItem = ({ item }: { item: HealthRiskData }) => {
+ const isSelected = selectedRisk === item.id;
+
+ return (
+ toggleRiskSelection(item.id)}
+ >
+
+ {formatDate(item.createdAt)}
+ {item.username && {item.username}}
+
+
+
+
+
+
+ Age:
+ {item.age} years
+
+
+ BMI:
+ {item.bmi}
+
+
+
+
+ Gender:
+ {item.gender}
+
+
+ Smoking:
+ {item.smokingStatus}
+
+
+
+
+ Diabetes:
+ {item.diabetes === "1" ? "Yes" : "No"}
+
+
+ Hypertension:
+ {item.hypertension === "1" ? "Yes" : "No"}
+
+
+
+
+
+ Risk Assessment:
+
+
+ Diabetes
+
+ {item.diabetes === "1" ? "Has Diabetes" :
+ !item.diabetes_risk || item.diabetes_risk === "0" ? "No Risk" :
+ `${(item.diabetes_risk || "").charAt(0).toUpperCase() + (item.diabetes_risk || "").slice(1)} Risk`}
+
+
+
+
+ Hypertension
+
+ {item.hypertension === "1" ? "Has Hypertension" :
+ !item.hypertension_risk || item.hypertension_risk === "0" ? "No Risk" :
+ `${(item.hypertension_risk || "").charAt(0).toUpperCase() + (item.hypertension_risk || "").slice(1)} Risk`}
+
+
+
+
+
+
+ {isSelected && (
+
+ handleEditRisk(item)}
+ >
+
+ Edit
+
+ handleDeleteRisk(item.id)}
+ >
+
+ Delete
+
+
+ )}
+
+ );
+ };
+
+
+ return (
+
+
+
+
+ Your Health Risk Assessments
+ navigation.navigate("AddHealthRisk")}
+ >
+
+ New Assessment
+
+
+
+ {loading ? (
+
+
+ Loading your health risk assessments...
+
+ ) : healthRisks.length === 0 ? (
+
+
+ No health risk assessments found
+
+ Complete a health risk assessment to see your results here
+
+ navigation.navigate("AddHealthRisk")}
+ >
+ Start Assessment
+
+
+ ) : (
+ item.id}
+ contentContainerStyle={styles.listContainer}
+ showsVerticalScrollIndicator={false}
+ />
+ )}
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ safeArea: {
+ flex: 1,
+ backgroundColor: '#e0f7fa',
+ },
+ container: {
+ flex: 1,
+ padding: 16,
+ },
+ header: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ marginBottom: 20,
+ },
+ title: {
+ fontSize: 22,
+ fontWeight: 'bold',
+ color: '#004d40',
+ flex: 1,
+ },
+ addButton: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ backgroundColor: '#80deea',
+ paddingHorizontal: 12,
+ paddingVertical: 8,
+ borderRadius: 20,
+ },
+ addButtonText: {
+ marginLeft: 4,
+ color: '#004d40',
+ fontWeight: 'bold',
+ },
+ loadingContainer: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ loadingText: {
+ marginTop: 12,
+ fontSize: 16,
+ color: '#004d40',
+ },
+ emptyContainer: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ padding: 20,
+ },
+ emptyText: {
+ fontSize: 18,
+ fontWeight: 'bold',
+ color: '#004d40',
+ marginTop: 16,
+ },
+ emptySubText: {
+ fontSize: 14,
+ color: '#00695c',
+ textAlign: 'center',
+ marginTop: 8,
+ marginBottom: 24,
+ },
+ startButton: {
+ backgroundColor: '#00695c',
+ paddingHorizontal: 24,
+ paddingVertical: 12,
+ borderRadius: 25,
+ },
+ startButtonText: {
+ color: 'white',
+ fontWeight: 'bold',
+ fontSize: 16,
+ },
+ listContainer: {
+ paddingBottom: 20,
+ },
+ riskItem: {
+ backgroundColor: '#ffffff',
+ borderRadius: 10,
+ padding: 16,
+ marginBottom: 12,
+ elevation: 2,
+ shadowColor: '#000',
+ shadowOffset: { width: 0, height: 1 },
+ shadowOpacity: 0.2,
+ shadowRadius: 1.41,
+ },
+ selectedRiskItem: {
+ borderWidth: 2,
+ borderColor: '#00695c',
+ },
+ riskDetails: {
+ marginBottom: 12,
+ },
+ riskHeader: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ marginBottom: 12,
+ },
+ riskDate: {
+ fontSize: 14,
+ color: '#555',
+ },
+ riskContent: {
+ marginTop: 8,
+ marginBottom: 8,
+ },
+ detailRow: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ marginBottom: 8,
+ },
+ detailItem: {
+ flex: 1,
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+ detailLabel: {
+ fontSize: 14,
+ fontWeight: 'bold',
+ color: '#00695c',
+ marginRight: 4,
+ },
+ detailValue: {
+ fontSize: 14,
+ color: '#333',
+ },
+ riskBadgesContainer: {
+ marginTop: 10,
+ borderTopWidth: 1,
+ borderTopColor: '#e0e0e0',
+ paddingTop: 10,
+ },
+ riskBadgesTitle: {
+ fontSize: 14,
+ fontWeight: 'bold',
+ color: '#00695c',
+ marginBottom: 8,
+ },
+ riskBadges: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ },
+ riskBadge: {
+ flex: 1,
+ borderRadius: 8,
+ padding: 8,
+ marginHorizontal: 4,
+ alignItems: 'center',
+ },
+ riskBadgeLabel: {
+ fontSize: 12,
+ fontWeight: 'bold',
+ color: '#333',
+ marginBottom: 2,
+ },
+ riskBadgeText: {
+ fontSize: 14,
+ fontWeight: 'bold',
+ },
+ highRiskBadge: {
+ backgroundColor: '#ffcdd2',
+ },
+ mediumRiskBadge: {
+ backgroundColor: '#fff9c4',
+ },
+ lowRiskBadge: {
+ backgroundColor: '#c8e6c9',
+ },
+ actionButtons: {
+ flexDirection: 'row',
+ justifyContent: 'flex-end',
+ },
+ actionButton: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ paddingHorizontal: 12,
+ paddingVertical: 8,
+ borderRadius: 5,
+ marginLeft: 8,
+ },
+ editButton: {
+ backgroundColor: '#4caf50',
+ },
+ deleteButton: {
+ backgroundColor: '#f44336',
+ },
+ actionButtonText: {
+ color: '#fff',
+ marginLeft: 4,
+ fontWeight: 'bold',
+ },
+ username: {
+ fontSize: 14,
+ fontWeight: 'bold',
+ color: '#004d40',
+ },
+
+ noRiskBadge: {
+ backgroundColor: '#e0e0e0',
+ },
+});
+
+export default ViewHealthRisk;
diff --git a/CeylonCare/app/pages/Home.tsx b/CeylonCare/app/pages/Home.tsx
index 253f0809..a0aafdd8 100644
--- a/CeylonCare/app/pages/Home.tsx
+++ b/CeylonCare/app/pages/Home.tsx
@@ -45,6 +45,13 @@ const buttonData = [
icon: require("../../assets/images/ai_home 1.png"),
navigateTo: "ChatScreen",
},
+ {
+ id: "5",
+ title: "View Health Risks",
+ description: "Assess your risk for diabetes and hypertension",
+ icon: require("../../assets/images/health.png"),
+ navigateTo: "ViewHealthRisk",
+ },
];
const defaultProfileImage = require("../../assets/images/defaultProfileImage.png");
@@ -70,6 +77,7 @@ const Home = ({ navigation }: any) => {
const data = await response.json();
console.log("User profile fetched successfully:", data);
setUserData(data);
+ await AsyncStorage.setItem("userName", data.fullName);
} catch (error) {
console.error("Error fetching user profile:", error.message);
Alert.alert("Error", error.message);
diff --git a/CeylonCare/app/pages/Login.tsx b/CeylonCare/app/pages/Login.tsx
index e6d70ab5..62910fa4 100644
--- a/CeylonCare/app/pages/Login.tsx
+++ b/CeylonCare/app/pages/Login.tsx
@@ -41,6 +41,7 @@ const Login = ({ navigation }: any) => {
}
const responseData = await response.json();
+ console.log("Login successful. Response data:", responseData);
const { user, loginTimestamp } = responseData;
console.log("Login successful. Storing session data...");
@@ -51,7 +52,7 @@ const Login = ({ navigation }: any) => {
} else {
await AsyncStorage.setItem("loginTimestamp", loginTimestamp);
}
-
+ console.log("User data:", user);
// Store userId safely
await AsyncStorage.setItem("userId", user.uid);
diff --git a/CeylonCare/assets/ar_poses/Downward_Dog.glb b/CeylonCare/assets/ar_poses/Downward_Dog.glb
new file mode 100644
index 00000000..05cd9a77
Binary files /dev/null and b/CeylonCare/assets/ar_poses/Downward_Dog.glb differ
diff --git a/CeylonCare/assets/ar_poses/fbx/DamagedHelmet.glb b/CeylonCare/assets/ar_poses/fbx/DamagedHelmet.glb
new file mode 100644
index 00000000..2cee76d7
Binary files /dev/null and b/CeylonCare/assets/ar_poses/fbx/DamagedHelmet.glb differ
diff --git a/CeylonCare/assets/images/health.png b/CeylonCare/assets/images/health.png
new file mode 100644
index 00000000..547bd5bd
Binary files /dev/null and b/CeylonCare/assets/images/health.png differ
diff --git a/CeylonCare/eas.json b/CeylonCare/eas.json
new file mode 100644
index 00000000..db31cec6
--- /dev/null
+++ b/CeylonCare/eas.json
@@ -0,0 +1,24 @@
+{
+ "cli": {
+ "version": ">= 16.4.1",
+ "appVersionSource": "remote"
+ },
+ "build": {
+ "development": {
+ "developmentClient": true,
+ "distribution": "internal",
+ "channel": "development"
+ },
+ "preview": {
+ "distribution": "internal",
+ "channel": "preview"
+ },
+ "production": {
+ "autoIncrement": true,
+ "channel": "production"
+ }
+ },
+ "submit": {
+ "production": {}
+ }
+}
diff --git a/CeylonCare/package-lock.json b/CeylonCare/package-lock.json
index 0edb67e0..02c19ac7 100644
--- a/CeylonCare/package-lock.json
+++ b/CeylonCare/package-lock.json
@@ -17,6 +17,7 @@
"@react-native-community/datetimepicker": "8.2.0",
"@react-native-firebase/app": "^21.12.0",
"@react-native-firebase/auth": "^21.12.0",
+ "@react-native-picker/picker": "^2.11.0",
"@react-native-voice/voice": "^3.2.4",
"@react-navigation/bottom-tabs": "^7.2.0",
"@react-navigation/native": "^7.0.14",
@@ -55,6 +56,7 @@
"react-native-get-random-values": "~1.11.0",
"react-native-linear-gradient": "^2.8.3",
"react-native-modal-datetime-picker": "^18.0.0",
+ "react-native-paper": "^5.14.0",
"react-native-reanimated": "~3.16.1",
"react-native-reanimated-carousel": "^4.0.2",
"react-native-safe-area-context": "4.12.0",
@@ -158,13 +160,13 @@
}
},
"node_modules/@babel/generator": {
- "version": "7.26.10",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.10.tgz",
- "integrity": "sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.1.tgz",
+ "integrity": "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==",
"license": "MIT",
"dependencies": {
- "@babel/parser": "^7.26.10",
- "@babel/types": "^7.26.10",
+ "@babel/parser": "^7.27.1",
+ "@babel/types": "^7.27.1",
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25",
"jsesc": "^3.0.2"
@@ -174,12 +176,12 @@
}
},
"node_modules/@babel/helper-annotate-as-pure": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz",
- "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.1.tgz",
+ "integrity": "sha512-WnuuDILl9oOBbKnb4L+DyODx7iC47XfzmNCpTttFsSp6hTG7XZxu60+4IO+2/hPfcGOoKbFiwoI/+zwARbNQow==",
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.25.9"
+ "@babel/types": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -202,17 +204,17 @@
}
},
"node_modules/@babel/helper-create-class-features-plugin": {
- "version": "7.26.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.26.9.tgz",
- "integrity": "sha512-ubbUqCofvxPRurw5L8WTsCLSkQiVpov4Qx0WMA+jUN+nXBK8ADPlJO1grkFw5CWKC5+sZSOfuGMdX1aI1iT9Sg==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.1.tgz",
+ "integrity": "sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==",
"license": "MIT",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.25.9",
- "@babel/helper-member-expression-to-functions": "^7.25.9",
- "@babel/helper-optimise-call-expression": "^7.25.9",
- "@babel/helper-replace-supers": "^7.26.5",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9",
- "@babel/traverse": "^7.26.9",
+ "@babel/helper-annotate-as-pure": "^7.27.1",
+ "@babel/helper-member-expression-to-functions": "^7.27.1",
+ "@babel/helper-optimise-call-expression": "^7.27.1",
+ "@babel/helper-replace-supers": "^7.27.1",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1",
+ "@babel/traverse": "^7.27.1",
"semver": "^6.3.1"
},
"engines": {
@@ -256,26 +258,26 @@
}
},
"node_modules/@babel/helper-member-expression-to-functions": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz",
- "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz",
+ "integrity": "sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==",
"license": "MIT",
"dependencies": {
- "@babel/traverse": "^7.25.9",
- "@babel/types": "^7.25.9"
+ "@babel/traverse": "^7.27.1",
+ "@babel/types": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-module-imports": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz",
- "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
+ "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
"license": "MIT",
"dependencies": {
- "@babel/traverse": "^7.25.9",
- "@babel/types": "^7.25.9"
+ "@babel/traverse": "^7.27.1",
+ "@babel/types": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -299,21 +301,21 @@
}
},
"node_modules/@babel/helper-optimise-call-expression": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz",
- "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz",
+ "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==",
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.25.9"
+ "@babel/types": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-plugin-utils": {
- "version": "7.26.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz",
- "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz",
+ "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -337,14 +339,14 @@
}
},
"node_modules/@babel/helper-replace-supers": {
- "version": "7.26.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz",
- "integrity": "sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz",
+ "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==",
"license": "MIT",
"dependencies": {
- "@babel/helper-member-expression-to-functions": "^7.25.9",
- "@babel/helper-optimise-call-expression": "^7.25.9",
- "@babel/traverse": "^7.26.5"
+ "@babel/helper-member-expression-to-functions": "^7.27.1",
+ "@babel/helper-optimise-call-expression": "^7.27.1",
+ "@babel/traverse": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -354,40 +356,40 @@
}
},
"node_modules/@babel/helper-skip-transparent-expression-wrappers": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz",
- "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz",
+ "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==",
"license": "MIT",
"dependencies": {
- "@babel/traverse": "^7.25.9",
- "@babel/types": "^7.25.9"
+ "@babel/traverse": "^7.27.1",
+ "@babel/types": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-string-parser": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
- "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
- "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
+ "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-option": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz",
- "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
+ "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -507,12 +509,12 @@
}
},
"node_modules/@babel/parser": {
- "version": "7.26.10",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.10.tgz",
- "integrity": "sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.1.tgz",
+ "integrity": "sha512-I0dZ3ZpCrJ1c04OqlNsQcKiZlsrXf/kkE4FXzID9rIOYICsAbA8mMDzhW/luRNAHdCNt7os/u8wenklZDlUVUQ==",
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.26.10"
+ "@babel/types": "^7.27.1"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -623,14 +625,14 @@
}
},
"node_modules/@babel/plugin-proposal-decorators": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.25.9.tgz",
- "integrity": "sha512-smkNLL/O1ezy9Nhy4CNosc4Va+1wo5w4gzSZeLe6y6dM4mmHfYOCPolXQPHQxonZCF+ZyebxN9vqOolkYrSn5g==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.27.1.tgz",
+ "integrity": "sha512-DTxe4LBPrtFdsWzgpmbBKevg3e9PBy+dXRt19kSbucbZvL2uqtdqwwpluL1jfxYE0wIDTFp1nTy/q6gNLsxXrg==",
"license": "MIT",
"dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/plugin-syntax-decorators": "^7.25.9"
+ "@babel/helper-create-class-features-plugin": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/plugin-syntax-decorators": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -754,12 +756,12 @@
}
},
"node_modules/@babel/plugin-syntax-decorators": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.25.9.tgz",
- "integrity": "sha512-ryzI0McXUPJnRCvMo4lumIKZUzhYUO/ScI+Mz4YVaTLt04DHNSjEUjKVvbzQjZFLuod/cYEc07mJWhzl6v4DPg==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.27.1.tgz",
+ "integrity": "sha512-YMq8Z87Lhl8EGkmb0MwYkt36QnxC+fzCgrl66ereamPlYToRpIk5nUjKUY3QKLWq8mwUB1BgbeXcTJhZOCDg5A==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -866,12 +868,12 @@
}
},
"node_modules/@babel/plugin-syntax-jsx": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz",
- "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz",
+ "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1647,12 +1649,12 @@
}
},
"node_modules/@babel/plugin-transform-react-display-name": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.25.9.tgz",
- "integrity": "sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.27.1.tgz",
+ "integrity": "sha512-p9+Vl3yuHPmkirRrg021XiP+EETmPMQTLr6Ayjj85RLNEbb3Eya/4VI0vAdzQG9SEAl2Lnt7fy5lZyMzjYoZQQ==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1662,16 +1664,16 @@
}
},
"node_modules/@babel/plugin-transform-react-jsx": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz",
- "integrity": "sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.27.1.tgz",
+ "integrity": "sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==",
"license": "MIT",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.25.9",
- "@babel/helper-module-imports": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/plugin-syntax-jsx": "^7.25.9",
- "@babel/types": "^7.25.9"
+ "@babel/helper-annotate-as-pure": "^7.27.1",
+ "@babel/helper-module-imports": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/plugin-syntax-jsx": "^7.27.1",
+ "@babel/types": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1681,12 +1683,12 @@
}
},
"node_modules/@babel/plugin-transform-react-jsx-development": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.25.9.tgz",
- "integrity": "sha512-9mj6rm7XVYs4mdLIpbZnHOYdpW42uoiBCTVowg7sP1thUOiANgMb4UtpRivR0pp5iL+ocvUv7X4mZgFRpJEzGw==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.27.1.tgz",
+ "integrity": "sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==",
"license": "MIT",
"dependencies": {
- "@babel/plugin-transform-react-jsx": "^7.25.9"
+ "@babel/plugin-transform-react-jsx": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1726,13 +1728,13 @@
}
},
"node_modules/@babel/plugin-transform-react-pure-annotations": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.25.9.tgz",
- "integrity": "sha512-KQ/Takk3T8Qzj5TppkS1be588lkbTp5uj7w6a0LeQaTMSckU/wK0oJ/pih+T690tkgI5jfmg2TqDJvd41Sj1Cg==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.27.1.tgz",
+ "integrity": "sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==",
"license": "MIT",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-annotate-as-pure": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -2089,17 +2091,17 @@
}
},
"node_modules/@babel/preset-react": {
- "version": "7.26.3",
- "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.26.3.tgz",
- "integrity": "sha512-Nl03d6T9ky516DGK2YMxrTqvnpUW63TnJMOMonj+Zae0JiPC5BC9xPMSL6L8fiSpA5vP88qfygavVQvnLp+6Cw==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.27.1.tgz",
+ "integrity": "sha512-oJHWh2gLhU9dW9HHr42q0cI0/iHHXTLGe39qvpAZZzagHy0MzYLCnCVV0symeRvzmjHyVU7mw2K06E6u/JwbhA==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/helper-validator-option": "^7.25.9",
- "@babel/plugin-transform-react-display-name": "^7.25.9",
- "@babel/plugin-transform-react-jsx": "^7.25.9",
- "@babel/plugin-transform-react-jsx-development": "^7.25.9",
- "@babel/plugin-transform-react-pure-annotations": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-validator-option": "^7.27.1",
+ "@babel/plugin-transform-react-display-name": "^7.27.1",
+ "@babel/plugin-transform-react-jsx": "^7.27.1",
+ "@babel/plugin-transform-react-jsx-development": "^7.27.1",
+ "@babel/plugin-transform-react-pure-annotations": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -2181,30 +2183,44 @@
}
},
"node_modules/@babel/template": {
- "version": "7.26.9",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz",
- "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.1.tgz",
+ "integrity": "sha512-Fyo3ghWMqkHHpHQCoBs2VnYjR4iWFFjguTDEqA5WgZDOrFesVjMhMM2FSqTKSoUSDO1VQtavj8NFpdRBEvJTtg==",
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.26.2",
- "@babel/parser": "^7.26.9",
- "@babel/types": "^7.26.9"
+ "@babel/code-frame": "^7.27.1",
+ "@babel/parser": "^7.27.1",
+ "@babel/types": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/template/node_modules/@babel/code-frame": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
+ "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse": {
- "version": "7.26.10",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.10.tgz",
- "integrity": "sha512-k8NuDrxr0WrPH5Aupqb2LCVURP/S0vBEn5mK6iH+GIYob66U5EtoZvcdudR2jQ4cmTwhEwW1DLB+Yyas9zjF6A==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.1.tgz",
+ "integrity": "sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==",
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.26.2",
- "@babel/generator": "^7.26.10",
- "@babel/parser": "^7.26.10",
- "@babel/template": "^7.26.9",
- "@babel/types": "^7.26.10",
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.27.1",
+ "@babel/parser": "^7.27.1",
+ "@babel/template": "^7.27.1",
+ "@babel/types": "^7.27.1",
"debug": "^4.3.1",
"globals": "^11.1.0"
},
@@ -2231,14 +2247,28 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@babel/traverse/node_modules/@babel/code-frame": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
+ "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@babel/types": {
- "version": "7.26.10",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.10.tgz",
- "integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz",
+ "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==",
"license": "MIT",
"dependencies": {
- "@babel/helper-string-parser": "^7.25.9",
- "@babel/helper-validator-identifier": "^7.25.9"
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -2251,6 +2281,28 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@callstack/react-theme-provider": {
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/@callstack/react-theme-provider/-/react-theme-provider-3.0.9.tgz",
+ "integrity": "sha512-tTQ0uDSCL0ypeMa8T/E9wAZRGKWj8kXP7+6RYgPTfOPs9N07C9xM8P02GJ3feETap4Ux5S69D9nteq9mEj86NA==",
+ "license": "MIT",
+ "dependencies": {
+ "deepmerge": "^3.2.0",
+ "hoist-non-react-statics": "^3.3.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.3.0"
+ }
+ },
+ "node_modules/@callstack/react-theme-provider/node_modules/deepmerge": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-3.3.0.tgz",
+ "integrity": "sha512-GRQOafGHwMHpjPx9iCvTgpu9NojZ49q794EEL94JVEw6VaeA8XTUyBKvAkOOjBX9oJNiV6G3P+T+tihFjo2TqA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/@egjs/hammerjs": {
"version": "2.0.17",
"resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz",
@@ -2294,9 +2346,9 @@
}
},
"node_modules/@expo/cli": {
- "version": "0.22.20",
- "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-0.22.20.tgz",
- "integrity": "sha512-BU2ASlw0Gaj3ou/TxVsgvzK+XK8Z14Yq3mmLyvMcMAQrdExZLNmvMZ3A3x6q2uMgSJM3aoQBUuVXS/Ny+lYgDA==",
+ "version": "0.22.26",
+ "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-0.22.26.tgz",
+ "integrity": "sha512-I689wc8Fn/AX7aUGiwrh3HnssiORMJtR2fpksX+JIe8Cj/EDleblYMSwRPd0025wrwOV9UN1KM/RuEt/QjCS3Q==",
"license": "MIT",
"dependencies": {
"@0no-co/graphql.web": "^1.0.8",
@@ -2312,12 +2364,12 @@
"@expo/osascript": "^2.1.6",
"@expo/package-manager": "^1.7.2",
"@expo/plist": "^0.2.2",
- "@expo/prebuild-config": "^8.0.29",
+ "@expo/prebuild-config": "~8.2.0",
"@expo/rudder-sdk-node": "^1.1.1",
"@expo/spawn-async": "^1.7.2",
"@expo/ws-tunnel": "^1.0.1",
"@expo/xcpretty": "^4.3.0",
- "@react-native/dev-middleware": "0.76.7",
+ "@react-native/dev-middleware": "0.76.9",
"@urql/core": "^5.0.6",
"@urql/exchange-retry": "^1.3.0",
"accepts": "^1.3.8",
@@ -2376,6 +2428,65 @@
"expo-internal": "build/bin/cli"
}
},
+ "node_modules/@expo/cli/node_modules/@react-native/debugger-frontend": {
+ "version": "0.76.9",
+ "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.76.9.tgz",
+ "integrity": "sha512-0Ru72Bm066xmxFuOXhhvrryxvb57uI79yDSFf+hxRpktkC98NMuRenlJhslMrbJ6WjCu1vOe/9UjWNYyxXTRTA==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@expo/cli/node_modules/@react-native/dev-middleware": {
+ "version": "0.76.9",
+ "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.76.9.tgz",
+ "integrity": "sha512-xkd3C3dRcmZLjFTEAOvC14q3apMLouIvJViCZY/p1EfCMrNND31dgE1dYrLTiI045WAWMt5bD15i6f7dE2/QWA==",
+ "license": "MIT",
+ "dependencies": {
+ "@isaacs/ttlcache": "^1.4.1",
+ "@react-native/debugger-frontend": "0.76.9",
+ "chrome-launcher": "^0.15.2",
+ "chromium-edge-launcher": "^0.2.0",
+ "connect": "^3.6.5",
+ "debug": "^2.2.0",
+ "invariant": "^2.2.4",
+ "nullthrows": "^1.1.1",
+ "open": "^7.0.3",
+ "selfsigned": "^2.4.1",
+ "serve-static": "^1.13.1",
+ "ws": "^6.2.3"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@expo/cli/node_modules/@react-native/dev-middleware/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/@expo/cli/node_modules/@react-native/dev-middleware/node_modules/ws": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz",
+ "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==",
+ "license": "MIT",
+ "dependencies": {
+ "async-limiter": "~1.0.0"
+ }
+ },
+ "node_modules/@expo/cli/node_modules/bplist-creator": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.0.7.tgz",
+ "integrity": "sha512-xp/tcaV3T5PCiaY04mXga7o/TE+t95gqeLmADeBI1CvZtdWTbgBt3uLpvh4UWtenKeBhCV6oVxGk38yZr2uYEA==",
+ "license": "MIT",
+ "dependencies": {
+ "stream-buffers": "~2.2.0"
+ }
+ },
"node_modules/@expo/cli/node_modules/form-data": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.3.tgz",
@@ -2391,6 +2502,12 @@
"node": ">= 6"
}
},
+ "node_modules/@expo/cli/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
"node_modules/@expo/cli/node_modules/semver": {
"version": "7.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
@@ -2496,23 +2613,14 @@
}
},
"node_modules/@expo/devcert": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/@expo/devcert/-/devcert-1.1.4.tgz",
- "integrity": "sha512-fqBODr8c72+gBSX5Ty3SIzaY4bXainlpab78+vEYEKL3fXmsOswMLf0+KE36mUEAa36BYabX7K3EiXOXX5OPMw==",
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@expo/devcert/-/devcert-1.2.0.tgz",
+ "integrity": "sha512-Uilcv3xGELD5t/b0eM4cxBFEKQRIivB3v7i+VhWLV/gL98aw810unLKKJbGAxAIhY6Ipyz8ChWibFsKFXYwstA==",
"license": "MIT",
"dependencies": {
- "application-config-path": "^0.1.0",
- "command-exists": "^1.2.4",
+ "@expo/sudo-prompt": "^9.3.1",
"debug": "^3.1.0",
- "eol": "^0.9.1",
- "get-port": "^3.2.0",
- "glob": "^10.4.2",
- "lodash": "^4.17.21",
- "mkdirp": "^0.5.1",
- "password-prompt": "^1.0.4",
- "sudo-prompt": "^8.2.0",
- "tmp": "^0.0.33",
- "tslib": "^2.4.0"
+ "glob": "^10.4.2"
}
},
"node_modules/@expo/devcert/node_modules/debug": {
@@ -2737,9 +2845,9 @@
}
},
"node_modules/@expo/osascript": {
- "version": "2.1.6",
- "resolved": "https://registry.npmjs.org/@expo/osascript/-/osascript-2.1.6.tgz",
- "integrity": "sha512-SbMp4BUwDAKiFF4zZEJf32rRYMeNnLK9u4FaPo0lQRer60F+SKd20NTSys0wgssiVeQyQz2OhGLRx3cxYowAGw==",
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/@expo/osascript/-/osascript-2.2.4.tgz",
+ "integrity": "sha512-Q+Oyj+1pdRiHHpev9YjqfMZzByFH8UhKvSszxa0acTveijjDhQgWrq4e9T/cchBHi0GWZpGczWyiyJkk1wM1dg==",
"license": "MIT",
"dependencies": {
"@expo/spawn-async": "^1.7.2",
@@ -2750,31 +2858,37 @@
}
},
"node_modules/@expo/package-manager": {
- "version": "1.7.2",
- "resolved": "https://registry.npmjs.org/@expo/package-manager/-/package-manager-1.7.2.tgz",
- "integrity": "sha512-wT/qh9ebNjl6xr00bYkSh93b6E/78J3JPlT6WzGbxbsnv5FIZKB/nr522oWqVe1E+ML7BpXs8WugErWDN9kOFg==",
+ "version": "1.8.4",
+ "resolved": "https://registry.npmjs.org/@expo/package-manager/-/package-manager-1.8.4.tgz",
+ "integrity": "sha512-8H8tLga/NS3iS7QaX/NneRPqbObnHvVCfMCo0ShudreOFmvmgqhYjRlkZTRstSyFqefai8ONaT4VmnLHneRYYg==",
"license": "MIT",
"dependencies": {
- "@expo/json-file": "^9.0.2",
+ "@expo/json-file": "^9.1.4",
"@expo/spawn-async": "^1.7.2",
- "ansi-regex": "^5.0.0",
"chalk": "^4.0.0",
- "find-up": "^5.0.0",
- "js-yaml": "^3.13.1",
- "micromatch": "^4.0.8",
"npm-package-arg": "^11.0.0",
"ora": "^3.4.0",
- "resolve-workspace-root": "^2.0.0",
- "split": "^1.0.1",
- "sudo-prompt": "9.1.1"
+ "resolve-workspace-root": "^2.0.0"
}
},
- "node_modules/@expo/package-manager/node_modules/sudo-prompt": {
- "version": "9.1.1",
- "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-9.1.1.tgz",
- "integrity": "sha512-es33J1g2HjMpyAhz8lOR+ICmXXAqTuKbuXuUWLhOLew20oN9oUCgCJx615U/v7aioZg7IX5lIh9x34vwneu4pA==",
- "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
- "license": "MIT"
+ "node_modules/@expo/package-manager/node_modules/@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "node_modules/@expo/package-manager/node_modules/@expo/json-file": {
+ "version": "9.1.4",
+ "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-9.1.4.tgz",
+ "integrity": "sha512-7Bv86X27fPERGhw8aJEZvRcH9sk+9BenDnEmrI3ZpywKodYSBgc8lX9Y32faNVQ/p0YbDK9zdJ0BfAKNAOyi0A==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "~7.10.4",
+ "json5": "^2.2.3"
+ }
},
"node_modules/@expo/plist": {
"version": "0.2.2",
@@ -2788,9 +2902,9 @@
}
},
"node_modules/@expo/prebuild-config": {
- "version": "8.0.29",
- "resolved": "https://registry.npmjs.org/@expo/prebuild-config/-/prebuild-config-8.0.29.tgz",
- "integrity": "sha512-CoZBxUQLZpGwbnPREr2sFnObOn4j+Mp7AHxX6Rz5jhSSz2VifC1jMM4NFiXrZe6LZyjYNqBGRe3D8bAqdpVGkg==",
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/@expo/prebuild-config/-/prebuild-config-8.2.0.tgz",
+ "integrity": "sha512-CxiPpd980s0jyxi7eyN3i/7YKu3XL+8qPjBZUCYtc0+axpGweqIkq2CslyLSKHyqVyH/zlPkbVgWdyiYavFS5Q==",
"license": "MIT",
"dependencies": {
"@expo/config": "~10.0.11",
@@ -2798,7 +2912,7 @@
"@expo/config-types": "^52.0.5",
"@expo/image-utils": "^0.6.5",
"@expo/json-file": "^9.0.2",
- "@react-native/normalize-colors": "0.76.7",
+ "@react-native/normalize-colors": "0.76.9",
"debug": "^4.3.1",
"fs-extra": "^9.0.0",
"resolve-from": "^5.0.0",
@@ -2806,6 +2920,12 @@
"xml2js": "0.6.0"
}
},
+ "node_modules/@expo/prebuild-config/node_modules/@react-native/normalize-colors": {
+ "version": "0.76.9",
+ "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.76.9.tgz",
+ "integrity": "sha512-TUdMG2JGk72M9d8DYbubdOlrzTYjw+YMe/xOnLU4viDgWRHsCbtRS9x0IAxRjs3amj/7zmK3Atm8jUPvdAc8qw==",
+ "license": "MIT"
+ },
"node_modules/@expo/prebuild-config/node_modules/fs-extra": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
@@ -2902,6 +3022,12 @@
"node": ">=12"
}
},
+ "node_modules/@expo/sudo-prompt": {
+ "version": "9.3.2",
+ "resolved": "https://registry.npmjs.org/@expo/sudo-prompt/-/sudo-prompt-9.3.2.tgz",
+ "integrity": "sha512-HHQigo3rQWKMDzYDLkubN5WQOYXJJE2eNqIQC2axC2iO3mHdwnIR7FgZVvHWtBwAdzBgAP0ECp8KqS8TiMKvgw==",
+ "license": "MIT"
+ },
"node_modules/@expo/vector-icons": {
"version": "14.0.4",
"resolved": "https://registry.npmjs.org/@expo/vector-icons/-/vector-icons-14.0.4.tgz",
@@ -4928,6 +5054,19 @@
}
}
},
+ "node_modules/@react-native-picker/picker": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/@react-native-picker/picker/-/picker-2.11.0.tgz",
+ "integrity": "sha512-QuZU6gbxmOID5zZgd/H90NgBnbJ3VV6qVzp6c7/dDrmWdX8S0X5YFYgDcQFjE3dRen9wB9FWnj2VVdPU64adSg==",
+ "license": "MIT",
+ "workspaces": [
+ "example"
+ ],
+ "peerDependencies": {
+ "react": "*",
+ "react-native": "*"
+ }
+ },
"node_modules/@react-native-voice/voice": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/@react-native-voice/voice/-/voice-3.2.4.tgz",
@@ -6359,12 +6498,6 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/application-config-path": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/application-config-path/-/application-config-path-0.1.1.tgz",
- "integrity": "sha512-zy9cHePtMP0YhwG+CfHm0bgwdnga2X3gZexpdCwEj//dpb+TKajtiC8REEUJUSq6Ab4f9cgNy2l8ObXzCXFkEw==",
- "license": "MIT"
- },
"node_modules/arg": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
@@ -6621,9 +6754,9 @@
}
},
"node_modules/babel-preset-expo": {
- "version": "12.0.9",
- "resolved": "https://registry.npmjs.org/babel-preset-expo/-/babel-preset-expo-12.0.9.tgz",
- "integrity": "sha512-1c+ysrTavT49WgVAj0OX/TEzt1kU2mfPhDaDajstshNHXFKPenMPWSViA/DHrJKVIMwaqr+z3GbUOD9GtKgpdg==",
+ "version": "12.0.11",
+ "resolved": "https://registry.npmjs.org/babel-preset-expo/-/babel-preset-expo-12.0.11.tgz",
+ "integrity": "sha512-4m6D92nKEieg+7DXa8uSvpr0GjfuRfM/G0t0I/Q5hF8HleEv5ms3z4dJ+p52qXSJsm760tMqLdO93Ywuoi7cCQ==",
"license": "MIT",
"dependencies": {
"@babel/plugin-proposal-decorators": "^7.12.9",
@@ -6632,7 +6765,7 @@
"@babel/plugin-transform-parameters": "^7.22.15",
"@babel/preset-react": "^7.22.15",
"@babel/preset-typescript": "^7.23.0",
- "@react-native/babel-preset": "0.76.7",
+ "@react-native/babel-preset": "0.76.9",
"babel-plugin-react-native-web": "~0.19.13",
"react-refresh": "^0.14.2"
},
@@ -6649,6 +6782,120 @@
}
}
},
+ "node_modules/babel-preset-expo/node_modules/@react-native/babel-plugin-codegen": {
+ "version": "0.76.9",
+ "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.76.9.tgz",
+ "integrity": "sha512-vxL/vtDEIYHfWKm5oTaEmwcnNGsua/i9OjIxBDBFiJDu5i5RU3bpmDiXQm/bJxrJNPRp5lW0I0kpGihVhnMAIQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@react-native/codegen": "0.76.9"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/babel-preset-expo/node_modules/@react-native/babel-preset": {
+ "version": "0.76.9",
+ "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.76.9.tgz",
+ "integrity": "sha512-TbSeCplCM6WhL3hR2MjC/E1a9cRnMLz7i767T7mP90oWkklEjyPxWl+0GGoVGnJ8FC/jLUupg/HvREKjjif6lw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.25.2",
+ "@babel/plugin-proposal-export-default-from": "^7.24.7",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.3",
+ "@babel/plugin-syntax-export-default-from": "^7.24.7",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-transform-arrow-functions": "^7.24.7",
+ "@babel/plugin-transform-async-generator-functions": "^7.25.4",
+ "@babel/plugin-transform-async-to-generator": "^7.24.7",
+ "@babel/plugin-transform-block-scoping": "^7.25.0",
+ "@babel/plugin-transform-class-properties": "^7.25.4",
+ "@babel/plugin-transform-classes": "^7.25.4",
+ "@babel/plugin-transform-computed-properties": "^7.24.7",
+ "@babel/plugin-transform-destructuring": "^7.24.8",
+ "@babel/plugin-transform-flow-strip-types": "^7.25.2",
+ "@babel/plugin-transform-for-of": "^7.24.7",
+ "@babel/plugin-transform-function-name": "^7.25.1",
+ "@babel/plugin-transform-literals": "^7.25.2",
+ "@babel/plugin-transform-logical-assignment-operators": "^7.24.7",
+ "@babel/plugin-transform-modules-commonjs": "^7.24.8",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7",
+ "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7",
+ "@babel/plugin-transform-numeric-separator": "^7.24.7",
+ "@babel/plugin-transform-object-rest-spread": "^7.24.7",
+ "@babel/plugin-transform-optional-catch-binding": "^7.24.7",
+ "@babel/plugin-transform-optional-chaining": "^7.24.8",
+ "@babel/plugin-transform-parameters": "^7.24.7",
+ "@babel/plugin-transform-private-methods": "^7.24.7",
+ "@babel/plugin-transform-private-property-in-object": "^7.24.7",
+ "@babel/plugin-transform-react-display-name": "^7.24.7",
+ "@babel/plugin-transform-react-jsx": "^7.25.2",
+ "@babel/plugin-transform-react-jsx-self": "^7.24.7",
+ "@babel/plugin-transform-react-jsx-source": "^7.24.7",
+ "@babel/plugin-transform-regenerator": "^7.24.7",
+ "@babel/plugin-transform-runtime": "^7.24.7",
+ "@babel/plugin-transform-shorthand-properties": "^7.24.7",
+ "@babel/plugin-transform-spread": "^7.24.7",
+ "@babel/plugin-transform-sticky-regex": "^7.24.7",
+ "@babel/plugin-transform-typescript": "^7.25.2",
+ "@babel/plugin-transform-unicode-regex": "^7.24.7",
+ "@babel/template": "^7.25.0",
+ "@react-native/babel-plugin-codegen": "0.76.9",
+ "babel-plugin-syntax-hermes-parser": "^0.25.1",
+ "babel-plugin-transform-flow-enums": "^0.0.2",
+ "react-refresh": "^0.14.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@babel/core": "*"
+ }
+ },
+ "node_modules/babel-preset-expo/node_modules/@react-native/codegen": {
+ "version": "0.76.9",
+ "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.76.9.tgz",
+ "integrity": "sha512-AzlCHMTKrAVC2709V4ZGtBXmGVtWTpWm3Ruv5vXcd3/anH4mGucfJ4rjbWKdaYQJMpXa3ytGomQrsIsT/s8kgA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.25.3",
+ "glob": "^7.1.1",
+ "hermes-parser": "0.23.1",
+ "invariant": "^2.2.4",
+ "jscodeshift": "^0.14.0",
+ "mkdirp": "^0.5.1",
+ "nullthrows": "^1.1.1",
+ "yargs": "^17.6.2"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@babel/preset-env": "^7.1.6"
+ }
+ },
+ "node_modules/babel-preset-expo/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/babel-preset-jest": {
"version": "29.6.3",
"resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz",
@@ -6736,12 +6983,12 @@
"license": "ISC"
},
"node_modules/bplist-creator": {
- "version": "0.0.7",
- "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.0.7.tgz",
- "integrity": "sha512-xp/tcaV3T5PCiaY04mXga7o/TE+t95gqeLmADeBI1CvZtdWTbgBt3uLpvh4UWtenKeBhCV6oVxGk38yZr2uYEA==",
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.1.0.tgz",
+ "integrity": "sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==",
"license": "MIT",
"dependencies": {
- "stream-buffers": "~2.2.0"
+ "stream-buffers": "2.2.x"
}
},
"node_modules/bplist-parser": {
@@ -7298,12 +7545,6 @@
"node": ">= 0.8"
}
},
- "node_modules/command-exists": {
- "version": "1.2.9",
- "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz",
- "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==",
- "license": "MIT"
- },
"node_modules/commander": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
@@ -8031,12 +8272,6 @@
"node": ">=8"
}
},
- "node_modules/eol": {
- "version": "0.9.1",
- "resolved": "https://registry.npmjs.org/eol/-/eol-0.9.1.tgz",
- "integrity": "sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg==",
- "license": "MIT"
- },
"node_modules/error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
@@ -8382,22 +8617,22 @@
}
},
"node_modules/expo": {
- "version": "52.0.39",
- "resolved": "https://registry.npmjs.org/expo/-/expo-52.0.39.tgz",
- "integrity": "sha512-EOnrgj8MHSt0o0SIBhM7jCim2QpJJNonbSATn9LqNtVgKtotIg718G/OrP5/g0GUAOBDyxHH9PfNu/aq9c0vDw==",
+ "version": "52.0.46",
+ "resolved": "https://registry.npmjs.org/expo/-/expo-52.0.46.tgz",
+ "integrity": "sha512-JG89IVZLp7DWzgeiQb+0N43kWOF1DUm3esBvAS9cPFWZsM9x8nDXgbvtREcycDPA6E+yJsSC+086CigeUY6sVA==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.20.0",
- "@expo/cli": "0.22.20",
+ "@expo/cli": "0.22.26",
"@expo/config": "~10.0.11",
"@expo/config-plugins": "~9.0.17",
"@expo/fingerprint": "0.11.11",
"@expo/metro-config": "0.19.12",
"@expo/vector-icons": "^14.0.0",
- "babel-preset-expo": "~12.0.9",
- "expo-asset": "~11.0.4",
+ "babel-preset-expo": "~12.0.11",
+ "expo-asset": "~11.0.5",
"expo-constants": "~17.0.8",
- "expo-file-system": "~18.0.11",
+ "expo-file-system": "~18.0.12",
"expo-font": "~13.0.4",
"expo-keep-awake": "~14.0.3",
"expo-modules-autolinking": "2.0.8",
@@ -8407,7 +8642,9 @@
"whatwg-url-without-unicode": "8.0.0-3"
},
"bin": {
- "expo": "bin/cli"
+ "expo": "bin/cli",
+ "expo-modules-autolinking": "bin/autolinking",
+ "fingerprint": "bin/fingerprint"
},
"peerDependencies": {
"@expo/dom-webview": "*",
@@ -8429,13 +8666,13 @@
}
},
"node_modules/expo-asset": {
- "version": "11.0.4",
- "resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-11.0.4.tgz",
- "integrity": "sha512-CdIywU0HrR3wsW5c3n0cT3jW9hccZdnqGsRqY+EY/RWzJbDXtDfAQVEiFHO3mDK7oveUwrP2jK/6ZRNek41/sg==",
+ "version": "11.0.5",
+ "resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-11.0.5.tgz",
+ "integrity": "sha512-TL60LmMBGVzs3NQcO8ylWqBumMh4sx0lmeJsn7+9C88fylGDhyyVnKZ1PyTXo9CVDBkndutZx2JUEQWM9BaiXw==",
"license": "MIT",
"dependencies": {
"@expo/image-utils": "^0.6.5",
- "expo-constants": "~17.0.7",
+ "expo-constants": "~17.0.8",
"invariant": "^2.2.4",
"md5-file": "^3.2.3"
},
@@ -8508,9 +8745,9 @@
}
},
"node_modules/expo-file-system": {
- "version": "18.0.11",
- "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-18.0.11.tgz",
- "integrity": "sha512-yDwYfEzWgPXsBZHJW2RJ8Q66ceiFN9Wa5D20pp3fjXVkzPBDwxnYwiPWk4pVmCa5g4X5KYMoMne1pUrsL4OEpg==",
+ "version": "18.0.12",
+ "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-18.0.12.tgz",
+ "integrity": "sha512-HAkrd/mb8r+G3lJ9MzmGeuW2B+BxQR1joKfeCyY4deLl1zoZ48FrAWjgZjHK9aHUVhJ0ehzInu/NQtikKytaeg==",
"license": "MIT",
"dependencies": {
"web-streams-polyfill": "^3.3.2"
@@ -9334,15 +9571,6 @@
"node": ">=8.0.0"
}
},
- "node_modules/get-port": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz",
- "integrity": "sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg==",
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/get-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
@@ -11607,6 +11835,7 @@
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "dev": true,
"license": "MIT"
},
"node_modules/lodash.camelcase": {
@@ -12281,9 +12510,9 @@
}
},
"node_modules/mime-db": {
- "version": "1.53.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.53.0.tgz",
- "integrity": "sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==",
+ "version": "1.54.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
+ "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
@@ -12887,15 +13116,6 @@
"node": ">=4"
}
},
- "node_modules/os-tmpdir": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
- "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/p-finally": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
@@ -13018,16 +13238,6 @@
"node": ">= 0.8"
}
},
- "node_modules/password-prompt": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/password-prompt/-/password-prompt-1.1.3.tgz",
- "integrity": "sha512-HkrjG2aJlvF0t2BMH0e2LB/EHf3Lcq3fNMzy4GYHcQblAvOl+QQji1Lx7WRBMqpVK8p+KR7bCg7oqAMXtdgqyw==",
- "license": "0BSD",
- "dependencies": {
- "ansi-escapes": "^4.3.2",
- "cross-spawn": "^7.0.3"
- }
- },
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -13785,6 +13995,47 @@
"react-native": ">=0.65.0"
}
},
+ "node_modules/react-native-paper": {
+ "version": "5.14.0",
+ "resolved": "https://registry.npmjs.org/react-native-paper/-/react-native-paper-5.14.0.tgz",
+ "integrity": "sha512-lKqIerPMBHuFYVeKqQV6uyMQ3HPEQps3a1TUv3QqkuNQeCSUzoKDmOMFR7gW8E7a7ay6px166ngYO1Sgy9HsVg==",
+ "license": "MIT",
+ "dependencies": {
+ "@callstack/react-theme-provider": "^3.0.9",
+ "color": "^3.1.2",
+ "use-latest-callback": "^0.2.3"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-native": "*",
+ "react-native-safe-area-context": "*"
+ }
+ },
+ "node_modules/react-native-paper/node_modules/color": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz",
+ "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^1.9.3",
+ "color-string": "^1.6.0"
+ }
+ },
+ "node_modules/react-native-paper/node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/react-native-paper/node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "license": "MIT"
+ },
"node_modules/react-native-reanimated": {
"version": "3.16.7",
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.16.7.tgz",
@@ -14793,15 +15044,6 @@
"plist": "^3.0.5"
}
},
- "node_modules/simple-plist/node_modules/bplist-creator": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.1.0.tgz",
- "integrity": "sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==",
- "license": "MIT",
- "dependencies": {
- "stream-buffers": "2.2.x"
- }
- },
"node_modules/simple-plist/node_modules/bplist-parser": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz",
@@ -14881,18 +15123,6 @@
"source-map": "^0.6.0"
}
},
- "node_modules/split": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz",
- "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==",
- "license": "MIT",
- "dependencies": {
- "through": "2"
- },
- "engines": {
- "node": "*"
- }
- },
"node_modules/split-on-first": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz",
@@ -15239,13 +15469,6 @@
"node": ">= 6"
}
},
- "node_modules/sudo-prompt": {
- "version": "8.2.5",
- "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-8.2.5.tgz",
- "integrity": "sha512-rlBo3HU/1zAJUrkY6jNxDOC9eVYliG6nS4JA8u8KAshITd07tafMc/Br7xQwCSseXwJ2iCcHCE8SNWX3q8Z+kw==",
- "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
- "license": "MIT"
- },
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -15638,24 +15861,6 @@
"integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==",
"license": "MIT"
},
- "node_modules/through": {
- "version": "2.3.8",
- "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
- "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
- "license": "MIT"
- },
- "node_modules/tmp": {
- "version": "0.0.33",
- "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
- "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
- "license": "MIT",
- "dependencies": {
- "os-tmpdir": "~1.0.2"
- },
- "engines": {
- "node": ">=0.6.0"
- }
- },
"node_modules/tmpl": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
diff --git a/CeylonCare/package.json b/CeylonCare/package.json
index 7fbc51ac..225d98a9 100644
--- a/CeylonCare/package.json
+++ b/CeylonCare/package.json
@@ -24,6 +24,7 @@
"@react-native-community/datetimepicker": "8.2.0",
"@react-native-firebase/app": "^21.12.0",
"@react-native-firebase/auth": "^21.12.0",
+ "@react-native-picker/picker": "^2.11.0",
"@react-native-voice/voice": "^3.2.4",
"@react-navigation/bottom-tabs": "^7.2.0",
"@react-navigation/native": "^7.0.14",
@@ -62,6 +63,7 @@
"react-native-get-random-values": "~1.11.0",
"react-native-linear-gradient": "^2.8.3",
"react-native-modal-datetime-picker": "^18.0.0",
+ "react-native-paper": "^5.14.0",
"react-native-reanimated": "~3.16.1",
"react-native-reanimated-carousel": "^4.0.2",
"react-native-safe-area-context": "4.12.0",
@@ -91,4 +93,4 @@
}
},
"private": true
-}
+}
\ No newline at end of file