diff --git a/.gitignore b/.gitignore index c252908..6996578 100644 --- a/.gitignore +++ b/.gitignore @@ -129,4 +129,6 @@ docs/pages/versions/*/react-native/*.diff !crsqlite.xcframework # iOS -**/ios/.xcode.env.local \ No newline at end of file +**/ios/.xcode.env.local + +eas.json \ No newline at end of file diff --git a/app.json b/app.json index 5add738..44e6854 100644 --- a/app.json +++ b/app.json @@ -5,27 +5,36 @@ "scheme": "pharmatech", "version": "0.2.0", "orientation": "portrait", - "icon": "./src/assets/images/icon.png", + "icon": "./src/assets/images/PharmaTech-icon.png", "userInterfaceStyle": "light", "newArchEnabled": true, "splash": { - "image": "src/assets/images/splash-icon.png", + "image": "src/assets/images/PharmaTech-icon.png", "resizeMode": "contain", - "backgroundColor": "#ffffff" + "backgroundColor": "#1C2143" }, "ios": { + "config": { + "googleMapsApiKey": "process.env.GOOGLE_MAPS_API_KEY" + }, "supportsTablet": true }, "android": { + "permissions": ["ACCESS_FINE_LOCATION", "ACCESS_COARSE_LOCATION"], "adaptiveIcon": { - "foregroundImage": "./src/assets/images/icon.png", - "backgroundColor": "#ffffff" + "foregroundImage": "./src/assets/images/PharmaTech-icon.png", + "backgroundColor": "#1C2143" }, - "package": "com.pharmatech.pharmatech" + "package": "com.pharmatech.pharmatech", + "config": { + "googleMaps": { + "apiKey": "AIzaSyAoesWK-4-JCtlF5TkHPLn3iInC8tiGNg4" + } + } }, "web": { "bundler": "metro", - "favicon": "./src/assets/images/icon.png" + "favicon": "./src/assets/images/PharmaTech-icon.png" }, "extra": { "router": { @@ -42,6 +51,16 @@ "updates": { "url": "https://u.expo.dev/3b8bad5d-7426-4881-aebd-cfb1ccf0795d" }, - "plugins": ["expo-font", "expo-router", "expo-secure-store"] + "plugins": [ + "expo-font", + "expo-router", + "expo-secure-store", + [ + "expo-image-picker", + { + "photosPermission": "Allow $(PRODUCT_NAME) to access your camera." + } + ] + ] } } diff --git a/declarations.d.ts b/declarations.d.ts index 894d908..933d520 100644 --- a/declarations.d.ts +++ b/declarations.d.ts @@ -2,3 +2,8 @@ declare module '*.png' { const value: number; export default value; } + +declare module '*.jpg' { + const value: string; + export default value; +} diff --git a/eas.json b/eas.json deleted file mode 100644 index bbf20f3..0000000 --- a/eas.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "build": { - "preview": { - "android": { - "buildType": "apk" - }, - "env": { - "PHARMATECH_DEV_MODE": "true" - } - }, - "production": { - "env": { - "PHARMATECH_DEV_MODE": "false" - } - } - } -} diff --git a/package-lock.json b/package-lock.json index 4479c82..64e45d6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,20 +1,26 @@ { "name": "app", - "version": "0.1.0", + "version": "0.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "app", - "version": "0.1.0", + "version": "0.2.0", "dependencies": { "@expo-google-fonts/poppins": "^0.2.3", - "@pharmatech/sdk": "^0.3.1", + "@pharmatech/sdk": "^0.4.21", + "@ptomasroos/react-native-multi-slider": "^2.2.2", + "@react-native-community/slider": "^4.5.6", + "@reduxjs/toolkit": "^2.6.1", "date-fns": "^4.1.0", "expo": "~52.0.37", "expo-constants": "~17.0.7", + "expo-dev-client": "~5.0.20", "expo-font": "~13.0.4", + "expo-image-picker": "~16.0.6", "expo-linking": "~7.0.5", + "expo-location": "^18.0.10", "expo-modules-core": "^2.2.2", "expo-router": "~4.0.17", "expo-secure-store": "~14.0.1", @@ -28,11 +34,15 @@ "react-native": "0.76.7", "react-native-calendars": "^1.1310.0", "react-native-heroicons": "^4.0.0", + "react-native-maps": "1.18.0", "react-native-pager-view": "^6.7.0", "react-native-reanimated": "^3.16.2", "react-native-safe-area-context": "4.12.0", "react-native-screens": "~4.4.0", + "react-native-sse": "^1.2.1", "react-native-svg": "^15.11.2", + "react-redux": "^9.2.0", + "socket.io-client": "^4.8.1", "tailwindcss": "^3.4.17" }, "devDependencies": { @@ -379,12 +389,12 @@ } }, "node_modules/@babel/helpers": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.9.tgz", - "integrity": "sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.10.tgz", + "integrity": "sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==", "dependencies": { "@babel/template": "^7.26.9", - "@babel/types": "^7.26.9" + "@babel/types": "^7.26.10" }, "engines": { "node": ">=6.9.0" @@ -2000,9 +2010,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.9.tgz", - "integrity": "sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.10.tgz", + "integrity": "sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -2075,9 +2085,9 @@ } }, "node_modules/@babel/types": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.9.tgz", - "integrity": "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.10.tgz", + "integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==", "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" @@ -2410,13 +2420,14 @@ } }, "node_modules/@expo/config": { - "version": "10.0.10", - "resolved": "https://registry.npmjs.org/@expo/config/-/config-10.0.10.tgz", - "integrity": "sha512-wI9/iam3Irk99ADGM/FyD7YrrEibIZXR4huSZiU5zt9o3dASOKhqepiNJex4YPiktLfKhYrpSEJtwno1g0SrgA==", + "version": "10.0.11", + "resolved": "https://registry.npmjs.org/@expo/config/-/config-10.0.11.tgz", + "integrity": "sha512-nociJ4zr/NmbVfMNe9j/+zRlt7wz/siISu7PjdWE4WE+elEGxWWxsGzltdJG0llzrM+khx8qUiFK5aiVcdMBww==", + "license": "MIT", "dependencies": { "@babel/code-frame": "~7.10.4", - "@expo/config-plugins": "~9.0.15", - "@expo/config-types": "^52.0.4", + "@expo/config-plugins": "~9.0.17", + "@expo/config-types": "^52.0.5", "@expo/json-file": "^9.0.2", "deepmerge": "^4.3.1", "getenv": "^1.0.0", @@ -2430,9 +2441,9 @@ } }, "node_modules/@expo/config-plugins": { - "version": "9.0.16", - "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-9.0.16.tgz", - "integrity": "sha512-AnJzmFB7ztM0JZBn+Ut6BQYC2WeGDzfIhBZVOIPMQbdBqvwJ7TmFEsGTGSxdwU/VqJaJK2sWxyt1zbWkpIYCEA==", + "version": "9.0.17", + "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-9.0.17.tgz", + "integrity": "sha512-m24F1COquwOm7PBl5wRbkT9P9DviCXe0D7S7nQsolfbhdCWuvMkfXeoWmgjtdhy7sDlOyIgBrAdnB6MfsWKqIg==", "license": "MIT", "dependencies": { "@expo/config-types": "^52.0.5", @@ -2843,15 +2854,14 @@ "integrity": "sha512-Doz2bfiPndXYFPMRwPyGa1k5QaKDVpY806UJj570epIiMzWaYyCtobasyfC++qfIXVb5Ocy7r3tP9d62hAQ7IQ==" }, "node_modules/@expo/server": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@expo/server/-/server-0.5.1.tgz", - "integrity": "sha512-lk8pKKw0eVP6rqkDR46vQB3vLA46z4KNGrqHpjD/SvMu1cGaRmQG2cQdX44mQtG8WyO9EYau+fBMHQQS2OTFKg==", - "license": "MIT", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@expo/server/-/server-0.5.3.tgz", + "integrity": "sha512-WXsWzeBs5v/h0PUfHyNLLz07rwwO5myQ1A5DGYewyyGLmsyl61yVCe8AgAlp1wkiMsqhj2hZqI2u3K10QnCMrQ==", "dependencies": { - "@remix-run/node": "^2.12.0", "abort-controller": "^3.0.0", "debug": "^4.3.4", - "source-map-support": "~0.5.21" + "source-map-support": "~0.5.21", + "undici": "^6.18.2" } }, "node_modules/@expo/spawn-async": { @@ -3583,9 +3593,9 @@ } }, "node_modules/@pharmatech/sdk": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@pharmatech/sdk/-/sdk-0.3.1.tgz", - "integrity": "sha512-kEfGpYXrnFi75GAZYTkAIKWEwi67bDQBc/rZJ9ZMcgWnJkET9eLCbNWwhQmd0tZOlPOAUOOtuVpI5rSAlCuqkA==", + "version": "0.4.21", + "resolved": "https://registry.npmjs.org/@pharmatech/sdk/-/sdk-0.4.21.tgz", + "integrity": "sha512-fxyXlgKN3qLxuGVg6bmRS5DhqfLOLsCYazffax5x0iYFFBIQHQBVRLltm5h84jvOEM0oA7ipD08VVXWMyBj/vQ==", "license": "MIT", "dependencies": { "axios": "^1.8.1" @@ -3600,6 +3610,16 @@ "node": ">=14" } }, + "node_modules/@ptomasroos/react-native-multi-slider": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@ptomasroos/react-native-multi-slider/-/react-native-multi-slider-2.2.2.tgz", + "integrity": "sha512-HWyCnRD3Z3SbHK2FLWYmBBqd1B4iXipeKv1+AK0FoY/CElEDTEixHE8hN60TsqxalPrznn798LE2Q4tHuCiyaA==", + "license": "MIT", + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, "node_modules/@radix-ui/react-compose-refs": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.0.tgz", @@ -3625,6 +3645,12 @@ "react": "^16.8 || ^17.0 || ^18.0" } }, + "node_modules/@react-native-community/slider": { + "version": "4.5.6", + "resolved": "https://registry.npmjs.org/@react-native-community/slider/-/slider-4.5.6.tgz", + "integrity": "sha512-UhLPFeqx0YfPLrEz8ffT3uqAyXWu6iqFjohNsbp4cOU7hnJwg2RXtDnYHoHMr7MOkZDVdlLMdrSrAuzY6KGqrg==", + "license": "MIT" + }, "node_modules/@react-native/assets-registry": { "version": "0.76.7", "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.76.7.tgz", @@ -4075,131 +4101,35 @@ "nanoid": "3.3.8" } }, - "node_modules/@remix-run/node": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/@remix-run/node/-/node-2.16.0.tgz", - "integrity": "sha512-9yYBYCHYO1+bIScGAtOy5/r4BoTS8E5lpQmjWP99UxSCSiKHPEO76V9Z8mmmarTNis/FPN+sUwfmbQWNHLA2vw==", + "node_modules/@reduxjs/toolkit": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.6.1.tgz", + "integrity": "sha512-SSlIqZNYhqm/oMkXbtofwZSt9lrncblzo6YcZ9zoX+zLngRBrCOjK4lNLdkNucJF58RHOWrD9txT3bT3piH7Zw==", "license": "MIT", "dependencies": { - "@remix-run/server-runtime": "2.16.0", - "@remix-run/web-fetch": "^4.4.2", - "@web3-storage/multipart-parser": "^1.0.0", - "cookie-signature": "^1.1.0", - "source-map-support": "^0.5.21", - "stream-slice": "^0.1.2", - "undici": "^6.11.1" - }, - "engines": { - "node": ">=18.0.0" + "immer": "^10.0.3", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" }, "peerDependencies": { - "typescript": "^5.1.0" + "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", + "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" }, "peerDependenciesMeta": { - "typescript": { + "react": { "optional": true - } - } - }, - "node_modules/@remix-run/router": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.0.tgz", - "integrity": "sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==", - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@remix-run/server-runtime": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/@remix-run/server-runtime/-/server-runtime-2.16.0.tgz", - "integrity": "sha512-gbuc4slxPi+pT47MrUYprX/wCuDlYL6H3LHZSvimWO1kDCBt8oefHzdHDPjLi4B1xzqXZomswTbuJzpZ7xRRTg==", - "license": "MIT", - "dependencies": { - "@remix-run/router": "1.23.0", - "@types/cookie": "^0.6.0", - "@web3-storage/multipart-parser": "^1.0.0", - "cookie": "^0.6.0", - "set-cookie-parser": "^2.4.8", - "source-map": "^0.7.3", - "turbo-stream": "2.4.0" - }, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "typescript": "^5.1.0" - }, - "peerDependenciesMeta": { - "typescript": { + }, + "react-redux": { "optional": true } } }, - "node_modules/@remix-run/server-runtime/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "license": "BSD-3-Clause", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@remix-run/web-blob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@remix-run/web-blob/-/web-blob-3.1.0.tgz", - "integrity": "sha512-owGzFLbqPH9PlKb8KvpNJ0NO74HWE2euAn61eEiyCXX/oteoVzTVSN8mpLgDjaxBf2btj5/nUllSUgpyd6IH6g==", - "license": "MIT", - "dependencies": { - "@remix-run/web-stream": "^1.1.0", - "web-encoding": "1.1.5" - } - }, - "node_modules/@remix-run/web-fetch": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@remix-run/web-fetch/-/web-fetch-4.4.2.tgz", - "integrity": "sha512-jgKfzA713/4kAW/oZ4bC3MoLWyjModOVDjFPNseVqcJKSafgIscrYL9G50SurEYLswPuoU3HzSbO0jQCMYWHhA==", - "license": "MIT", - "dependencies": { - "@remix-run/web-blob": "^3.1.0", - "@remix-run/web-file": "^3.1.0", - "@remix-run/web-form-data": "^3.1.0", - "@remix-run/web-stream": "^1.1.0", - "@web3-storage/multipart-parser": "^1.0.0", - "abort-controller": "^3.0.0", - "data-uri-to-buffer": "^3.0.1", - "mrmime": "^1.0.0" - }, - "engines": { - "node": "^10.17 || >=12.3" - } - }, - "node_modules/@remix-run/web-file": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@remix-run/web-file/-/web-file-3.1.0.tgz", - "integrity": "sha512-dW2MNGwoiEYhlspOAXFBasmLeYshyAyhIdrlXBi06Duex5tDr3ut2LFKVj7tyHLmn8nnNwFf1BjNbkQpygC2aQ==", - "license": "MIT", - "dependencies": { - "@remix-run/web-blob": "^3.1.0" - } - }, - "node_modules/@remix-run/web-form-data": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@remix-run/web-form-data/-/web-form-data-3.1.0.tgz", - "integrity": "sha512-NdeohLMdrb+pHxMQ/Geuzdp0eqPbea+Ieo8M8Jx2lGC6TBHsgHzYcBvr0LyPdPVycNRDEpWpiDdCOdCryo3f9A==", - "license": "MIT", - "dependencies": { - "web-encoding": "1.1.5" - } - }, - "node_modules/@remix-run/web-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@remix-run/web-stream/-/web-stream-1.1.0.tgz", - "integrity": "sha512-KRJtwrjRV5Bb+pM7zxcTJkhIqWWSy+MYsIxHK+0m5atcznsf15YwUBWHWulZerV2+vvHH1Lp1DD7pw6qKW8SgA==", - "license": "MIT", - "dependencies": { - "web-streams-polyfill": "^3.1.1" - } + "node_modules/@reduxjs/toolkit/node_modules/reselect": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", + "license": "MIT" }, "node_modules/@segment/loosely-validate-event": { "version": "2.0.0", @@ -4231,6 +4161,11 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" + }, "node_modules/@svgr/babel-plugin-add-jsx-attribute": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", @@ -4760,12 +4695,6 @@ "@babel/types": "^7.20.7" } }, - "node_modules/@types/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", - "license": "MIT" - }, "node_modules/@types/eslint": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", @@ -4791,6 +4720,12 @@ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==" }, + "node_modules/@types/geojson": { + "version": "7946.0.16", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", + "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", + "license": "MIT" + }, "node_modules/@types/graceful-fs": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", @@ -4894,6 +4829,12 @@ "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==" }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", + "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", + "license": "MIT" + }, "node_modules/@types/yargs": { "version": "17.0.33", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", @@ -5136,12 +5077,6 @@ "@urql/core": "^5.0.0" } }, - "node_modules/@web3-storage/multipart-parser": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@web3-storage/multipart-parser/-/multipart-parser-1.0.0.tgz", - "integrity": "sha512-BEO6al7BYqcnfX15W2cnGR+Q566ACXAT9UQykORCWW80lmkpWsnEob6zJS1ZVBKsSJC8+7vJkHwlp+lXG1UCdw==", - "license": "(Apache-2.0 AND MIT)" - }, "node_modules/@webassemblyjs/ast": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", @@ -5309,13 +5244,6 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "peer": true }, - "node_modules/@zxing/text-encoding": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz", - "integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==", - "license": "(Unlicense OR Apache-2.0)", - "optional": true - }, "node_modules/abab": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", @@ -5742,6 +5670,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, "dependencies": { "possible-typed-array-names": "^1.0.0" }, @@ -5753,10 +5682,9 @@ } }, "node_modules/axios": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.1.tgz", - "integrity": "sha512-NN+fvwH/kV01dYUQ3PTOZns4LWtWhOFCAhQ/pHb88WQ1hNe5V/dvFwc4VJcDL11LT9xSX0QtsR8sWUuyOuOq7g==", - "license": "MIT", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", + "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -5767,7 +5695,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", - "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -6313,6 +6240,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", @@ -6342,6 +6270,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "dev": true, "dependencies": { "call-bind-apply-helpers": "^1.0.1", "get-intrinsic": "^1.2.6" @@ -6824,24 +6753,6 @@ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, - "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", - "license": "MIT", - "engines": { - "node": ">=6.6.0" - } - }, "node_modules/core-js": { "version": "3.40.0", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.40.0.tgz", @@ -6935,6 +6846,16 @@ "node": ">=8" } }, + "node_modules/css-in-js-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-3.1.0.tgz", + "integrity": "sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==", + "optional": true, + "peer": true, + "dependencies": { + "hyphenate-style-name": "^1.0.3" + } + }, "node_modules/css-select": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", @@ -7055,15 +6976,6 @@ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "devOptional": true }, - "node_modules/data-uri-to-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz", - "integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==", - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, "node_modules/data-urls": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", @@ -7261,6 +7173,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -7571,6 +7484,62 @@ "once": "^1.4.0" } }, + "node_modules/engine.io-client": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz", + "integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1", + "xmlhttprequest-ssl": "~2.1.1" + } + }, + "node_modules/engine.io-client/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/engine.io-client/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/enhanced-resolve": { "version": "5.18.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", @@ -8336,6 +8305,80 @@ "react-native": "*" } }, + "node_modules/expo-dev-client": { + "version": "5.0.20", + "resolved": "https://registry.npmjs.org/expo-dev-client/-/expo-dev-client-5.0.20.tgz", + "integrity": "sha512-bLNkHdU7V3I4UefgJbJnIDUBUL0LxIal/xYEx9BbgDd3B7wgQKY//+BpPIxBOKCQ22lkyiHY8y9tLhO903sAgg==", + "license": "MIT", + "dependencies": { + "expo-dev-launcher": "5.0.35", + "expo-dev-menu": "6.0.25", + "expo-dev-menu-interface": "1.9.3", + "expo-manifests": "~0.15.8", + "expo-updates-interface": "~1.0.0" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-dev-launcher": { + "version": "5.0.35", + "resolved": "https://registry.npmjs.org/expo-dev-launcher/-/expo-dev-launcher-5.0.35.tgz", + "integrity": "sha512-hEQr0ZREnUMxZ6wtQgfK1lzYnbb0zar3HqYZhmANzXmE6UEPbQ4GByLzhpfz/d+xxdBVQZsrHdtiV28KPG2sog==", + "license": "MIT", + "dependencies": { + "ajv": "8.11.0", + "expo-dev-menu": "6.0.25", + "expo-manifests": "~0.15.8", + "resolve-from": "^5.0.0" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-dev-launcher/node_modules/ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/expo-dev-launcher/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/expo-dev-menu": { + "version": "6.0.25", + "resolved": "https://registry.npmjs.org/expo-dev-menu/-/expo-dev-menu-6.0.25.tgz", + "integrity": "sha512-K2m4z/I+CPWbMtHlDzU68lHaQs52De0v5gbsjAmA5ig8FrYh4MKZvPxSVANaiKENzgmtglu8qaFh7ua9Gt2TfA==", + "license": "MIT", + "dependencies": { + "expo-dev-menu-interface": "1.9.3" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-dev-menu-interface": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/expo-dev-menu-interface/-/expo-dev-menu-interface-1.9.3.tgz", + "integrity": "sha512-KY/dWTBE1l47i9V366JN5rC6YIdOc9hz8yAmZzkl5DrPia5l3M2WIjtnpHC9zUkNjiSiG2urYoOAq4H/uLdmyg==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, "node_modules/expo-eas-client": { "version": "0.13.3", "resolved": "https://registry.npmjs.org/expo-eas-client/-/expo-eas-client-0.13.3.tgz", @@ -8366,6 +8409,25 @@ "react": "*" } }, + "node_modules/expo-image-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/expo-image-loader/-/expo-image-loader-5.0.0.tgz", + "integrity": "sha512-Eg+5FHtyzv3Jjw9dHwu2pWy4xjf8fu3V0Asyy42kO+t/FbvW/vjUixpTjPtgKQLQh+2/9Nk4JjFDV6FwCnF2ZA==", + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-image-picker": { + "version": "16.0.6", + "resolved": "https://registry.npmjs.org/expo-image-picker/-/expo-image-picker-16.0.6.tgz", + "integrity": "sha512-HN4xZirFjsFDIsWFb12AZh19fRzuvZjj2ll17cGr19VNRP06S/VPQU3Tdccn5vwUzQhOBlLu704CnNm278boiQ==", + "dependencies": { + "expo-image-loader": "~5.0.0" + }, + "peerDependencies": { + "expo": "*" + } + }, "node_modules/expo-json-utils": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/expo-json-utils/-/expo-json-utils-0.14.0.tgz", @@ -8395,13 +8457,22 @@ "react-native": "*" } }, + "node_modules/expo-location": { + "version": "18.0.10", + "resolved": "https://registry.npmjs.org/expo-location/-/expo-location-18.0.10.tgz", + "integrity": "sha512-R0Iioz0UZ9Ts8TACPngh8uDFbajJhVa5/igLqWB8Pq/gp8UHuwj7PC8XbZV7avsFoShYjaxrOhf4U7IONeKLgg==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, "node_modules/expo-manifests": { - "version": "0.15.7", - "resolved": "https://registry.npmjs.org/expo-manifests/-/expo-manifests-0.15.7.tgz", - "integrity": "sha512-IVzLcPamzUi4Br96xw6JPHaa1vjYupUnMqYyV1Mtd9VQojS5hJsf5VcVzbAMZE/cFGzWLZ1oJa6QXxYjN39Uww==", + "version": "0.15.8", + "resolved": "https://registry.npmjs.org/expo-manifests/-/expo-manifests-0.15.8.tgz", + "integrity": "sha512-VuIyaMfRfLZeETNsRohqhy1l7iZ7I+HKMPfZXVL2Yn17TT0WkOhZoq1DzYwPbOHPgp1Uk6phNa86EyaHrD2DLw==", "license": "MIT", "dependencies": { - "@expo/config": "~10.0.10", + "@expo/config": "~10.0.11", "expo-json-utils": "~0.14.0" }, "peerDependencies": { @@ -8637,6 +8708,13 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-loops": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-loops/-/fast-loops-1.1.4.tgz", + "integrity": "sha512-8dbd3XWoKCTms18ize6JmQF1SFnnfj5s0B7rRry22EofgMu7B6LKHVh+XfFqFGsqnbH54xgeO83PzpKI+ODhlg==", + "optional": true, + "peer": true + }, "node_modules/fast-uri": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", @@ -8875,6 +8953,7 @@ "version": "0.3.5", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, "dependencies": { "is-callable": "^1.2.7" }, @@ -9251,6 +9330,16 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, + "node_modules/graphql": { + "version": "15.8.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.8.0.tgz", + "integrity": "sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==", + "optional": true, + "peer": true, + "engines": { + "node": ">= 10.x" + } + }, "node_modules/has-bigints": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", @@ -9275,6 +9364,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, "dependencies": { "es-define-property": "^1.0.0" }, @@ -9464,6 +9554,13 @@ "url": "https://github.com/sponsors/typicode" } }, + "node_modules/hyphenate-style-name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz", + "integrity": "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==", + "optional": true, + "peer": true + }, "node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", @@ -9516,6 +9613,16 @@ "node": ">=16.x" } }, + "node_modules/immer": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz", + "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/import-fresh": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", @@ -9649,6 +9756,17 @@ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, + "node_modules/inline-style-prefixer": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-6.0.4.tgz", + "integrity": "sha512-FwXmZC2zbeeS7NzGjJ6pAiqRhXR0ugUShSNb6GApMl6da0/XGc4MOJsoWAywia52EEWbXNSy0pzkwz/+Y+swSg==", + "optional": true, + "peer": true, + "dependencies": { + "css-in-js-utils": "^3.1.0", + "fast-loops": "^1.1.3" + } + }, "node_modules/internal-ip": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", @@ -9699,22 +9817,6 @@ "node": ">= 0.10" } }, - "node_modules/is-arguments": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", - "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-array-buffer": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", @@ -9828,6 +9930,7 @@ "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -9947,6 +10050,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", + "dev": true, "dependencies": { "call-bound": "^1.0.3", "get-proto": "^1.0.0", @@ -10043,6 +10147,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", @@ -10128,6 +10233,7 @@ "version": "1.1.15", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, "dependencies": { "which-typed-array": "^1.1.16" }, @@ -12570,15 +12676,6 @@ "node": "*" } }, - "node_modules/mrmime": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", - "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -13516,6 +13613,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, "engines": { "node": ">= 0.4" } @@ -13769,8 +13867,7 @@ "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "license": "MIT" + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, "node_modules/psl": { "version": "1.15.0", @@ -14374,6 +14471,28 @@ "react-native": ">=0.73.0" } }, + "node_modules/react-native-maps": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/react-native-maps/-/react-native-maps-1.18.0.tgz", + "integrity": "sha512-S17nYUqeMptgIPaAZuVRo+eRelPreBBYQWw6jsxU7qQ12p+THSfFaqabcNn7fBmsXhT3T27iIl8ek8v1H8BaGw==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.13" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": ">= 17.0.1", + "react-native": ">= 0.64.3", + "react-native-web": ">= 0.11" + }, + "peerDependenciesMeta": { + "react-native-web": { + "optional": true + } + } + }, "node_modules/react-native-pager-view": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/react-native-pager-view/-/react-native-pager-view-6.7.0.tgz", @@ -14430,6 +14549,11 @@ "react-native": "*" } }, + "node_modules/react-native-sse": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/react-native-sse/-/react-native-sse-1.2.1.tgz", + "integrity": "sha512-zejanlScF+IB9tYnbdry0MT34qjBXbiV/E72qGz33W/tX1bx8MXsbB4lxiuPETc9v/008vYZ60yjIstW22VlVg==" + }, "node_modules/react-native-svg": { "version": "15.11.2", "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.11.2.tgz", @@ -14468,6 +14592,41 @@ "integrity": "sha512-Ns7Bn9H/Tyw278+5SQx9oAblDZ7JixyzeOczcBK8dipQk2pD7Djkcfnf1nB/8RErAmMLL9iXgW0QHqiII8AhKw==", "license": "MIT" }, + "node_modules/react-native-web": { + "version": "0.19.13", + "resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.19.13.tgz", + "integrity": "sha512-etv3bN8rJglrRCp/uL4p7l8QvUNUC++QwDbdZ8CB7BvZiMvsxfFIRM1j04vxNldG3uo2puRd6OSWR3ibtmc29A==", + "optional": true, + "peer": true, + "dependencies": { + "@babel/runtime": "^7.18.6", + "@react-native/normalize-colors": "^0.74.1", + "fbjs": "^3.0.4", + "inline-style-prefixer": "^6.0.1", + "memoize-one": "^6.0.0", + "nullthrows": "^1.1.1", + "postcss-value-parser": "^4.2.0", + "styleq": "^0.1.3" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/react-native-web/node_modules/@react-native/normalize-colors": { + "version": "0.74.89", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.74.89.tgz", + "integrity": "sha512-qoMMXddVKVhZ8PA1AbUCk83trpd6N+1nF2A6k1i6LsQObyS92fELuk8kU/lQs6M7BsMHwqyLCpQJ1uFgNvIQXg==", + "optional": true, + "peer": true + }, + "node_modules/react-native-web/node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", + "optional": true, + "peer": true + }, "node_modules/react-native/node_modules/babel-plugin-syntax-hermes-parser": { "version": "0.23.1", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.23.1.tgz", @@ -14536,6 +14695,29 @@ "async-limiter": "~1.0.0" } }, + "node_modules/react-redux": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", + "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", + "license": "MIT", + "dependencies": { + "@types/use-sync-external-store": "^0.0.6", + "use-sync-external-store": "^1.4.0" + }, + "peerDependencies": { + "@types/react": "^18.2.25 || ^19", + "react": "^18.0 || ^19", + "redux": "^5.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, "node_modules/react-refresh": { "version": "0.14.2", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", @@ -14670,6 +14852,21 @@ "node": ">=8" } }, + "node_modules/redux": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", + "license": "MIT" + }, + "node_modules/redux-thunk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", + "license": "MIT", + "peerDependencies": { + "redux": "^5.0.0" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -15039,6 +15236,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -15319,16 +15517,11 @@ "resolved": "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz", "integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==" }, - "node_modules/set-cookie-parser": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", - "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", - "license": "MIT" - }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -15586,6 +15779,64 @@ "tslib": "^2.0.3" } }, + "node_modules/socket.io-client": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz", + "integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.6.1", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-client/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -15755,12 +16006,6 @@ "node": ">= 0.10.0" } }, - "node_modules/stream-slice": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/stream-slice/-/stream-slice-0.1.2.tgz", - "integrity": "sha512-QzQxpoacatkreL6jsxnVb7X5R/pGw9OUv2qWTYWnmLpg4NdN31snPy/f3TdQE1ZUXaThRvj1Zw4/OGg0ZkaLMA==", - "license": "MIT" - }, "node_modules/strict-uri-encode": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", @@ -16017,6 +16262,13 @@ "resolved": "https://registry.npmjs.org/structured-headers/-/structured-headers-0.4.1.tgz", "integrity": "sha512-0MP/Cxx5SzeeZ10p/bZI0S6MpgD+yxAhi1BOQ34jgnMXsCq3j1t6tQnZu+KdlL7dvJTLT3g9xN8tl10TqgFMcg==" }, + "node_modules/styleq": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/styleq/-/styleq-0.1.3.tgz", + "integrity": "sha512-3ZUifmCDCQanjeej1f6kyl/BeP/Vae5EYkQ9iJfUm/QwZvlgnZzyflqAsAWYURdtea8Vkvswu2GrC57h3qffcA==", + "optional": true, + "peer": true + }, "node_modules/sucrase": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", @@ -16633,12 +16885,6 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, - "node_modules/turbo-stream": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz", - "integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==", - "license": "ISC" - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -16748,7 +16994,7 @@ "version": "5.7.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", - "devOptional": true, + "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -16953,7 +17199,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -16985,19 +17230,6 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, - "node_modules/util": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -17099,18 +17331,6 @@ "defaults": "^1.0.3" } }, - "node_modules/web-encoding": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz", - "integrity": "sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==", - "license": "MIT", - "dependencies": { - "util": "^0.12.3" - }, - "optionalDependencies": { - "@zxing/text-encoding": "0.9.0" - } - }, "node_modules/web-streams-polyfill": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", @@ -17337,6 +17557,7 @@ "version": "1.1.18", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz", "integrity": "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==", + "dev": true, "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", @@ -17564,6 +17785,14 @@ "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", + "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index bc59c48..0fe1cfc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "app", - "version": "0.2.0", + "version": "1.0.0", "main": "index.ts", "scripts": { "start": "expo start", @@ -19,12 +19,18 @@ }, "dependencies": { "@expo-google-fonts/poppins": "^0.2.3", - "@pharmatech/sdk": "^0.3.1", + "@pharmatech/sdk": "^0.4.21", + "@ptomasroos/react-native-multi-slider": "^2.2.2", + "@react-native-community/slider": "^4.5.6", + "@reduxjs/toolkit": "^2.6.1", "date-fns": "^4.1.0", "expo": "~52.0.37", "expo-constants": "~17.0.7", + "expo-dev-client": "~5.0.20", "expo-font": "~13.0.4", + "expo-image-picker": "~16.0.6", "expo-linking": "~7.0.5", + "expo-location": "^18.0.10", "expo-modules-core": "^2.2.2", "expo-router": "~4.0.17", "expo-secure-store": "~14.0.1", @@ -38,11 +44,15 @@ "react-native": "0.76.7", "react-native-calendars": "^1.1310.0", "react-native-heroicons": "^4.0.0", + "react-native-maps": "1.18.0", "react-native-pager-view": "^6.7.0", "react-native-reanimated": "^3.16.2", "react-native-safe-area-context": "4.12.0", "react-native-screens": "~4.4.0", + "react-native-sse": "^1.2.1", "react-native-svg": "^15.11.2", + "react-redux": "^9.2.0", + "socket.io-client": "^4.8.1", "tailwindcss": "^3.4.17" }, "devDependencies": { diff --git a/src/app/(delivery-tabs)/_layout.tsx b/src/app/(delivery-tabs)/_layout.tsx new file mode 100644 index 0000000..14b1f43 --- /dev/null +++ b/src/app/(delivery-tabs)/_layout.tsx @@ -0,0 +1,57 @@ +import React from 'react'; +import { Tabs } from 'expo-router'; +import { View, StyleSheet } from 'react-native'; +import { Colors } from '../../styles/theme'; +import PoppinsText from '../../components/PoppinsText'; +import { HomeIcon, ClockIcon } from 'react-native-heroicons/outline'; +import TopBarDelivery from '../../components/TopBarDelivery'; +import { AlertProvider } from '../../components/AlertProvider'; // Importar el AlertProvider +import { TabBar } from '../../components/TabBar'; + +export default function DeliveryTabLayout() { + return ( + + + + }> + ( + + Home + + ), + headerShown: false, + title: 'Home', + tabBarIcon: () => ( + + ), + }} + /> + ( + + Historial + + ), + headerShown: false, + title: 'Historial', + tabBarIcon: () => ( + + ), + }} + /> + + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, +}); diff --git a/src/app/(delivery-tabs)/deliveryHistory.tsx b/src/app/(delivery-tabs)/deliveryHistory.tsx new file mode 100644 index 0000000..ff6b5b9 --- /dev/null +++ b/src/app/(delivery-tabs)/deliveryHistory.tsx @@ -0,0 +1,6 @@ +import React from 'react'; +import DeliveryHistoryScreen from '../../screens/delivery/DeliveryHistoryScreen'; + +export default function DeliveryHistory() { + return ; +} diff --git a/src/app/(delivery-tabs)/index.tsx b/src/app/(delivery-tabs)/index.tsx new file mode 100644 index 0000000..8255937 --- /dev/null +++ b/src/app/(delivery-tabs)/index.tsx @@ -0,0 +1,6 @@ +import React from 'react'; +import DeliveryHomeScreen from '../../screens/delivery/DeliveryHomeScreen'; + +export default function DeliveryHome() { + return ; +} diff --git a/src/app/(tabs)/_layout.tsx b/src/app/(tabs)/_layout.tsx index c403537..27b9f64 100644 --- a/src/app/(tabs)/_layout.tsx +++ b/src/app/(tabs)/_layout.tsx @@ -3,22 +3,32 @@ import { ListBulletIcon, MapPinIcon, TagIcon, - LifebuoyIcon, } from 'react-native-heroicons/outline'; import { Tabs } from 'expo-router'; import { Colors } from '../../styles/theme'; import PoppinsText from '../../components/PoppinsText'; import { View, StyleSheet } from 'react-native'; import TopBar from '../../components/TopBar'; +import { TabBar } from '../../components/TabBar'; export default function TabLayout() { return ( } // Siempre renderiza la TabBar screenOptions={{ - tabBarActiveTintColor: Colors.primary, - tabBarStyle: { backgroundColor: Colors.secondaryWhite }, + tabBarHideOnKeyboard: true, + tabBarVisibilityAnimationConfig: { + show: { + animation: 'timing', + config: { duration: 0 }, + }, + hide: { + animation: 'timing', + config: { duration: 0 }, + }, + }, }} > - ( - - Soporte - - ), - title: 'Soporte', - headerShown: false, - tabBarIcon: () => ( - - ), - }} - /> ); diff --git a/src/app/(tabs)/support.tsx b/src/app/(tabs)/support.tsx deleted file mode 100644 index 600e4de..0000000 --- a/src/app/(tabs)/support.tsx +++ /dev/null @@ -1,7 +0,0 @@ -// app/(tabs)/support.tsx -import React from 'react'; -import SupportScreen from '../../screens/tab/SupportScreen'; - -export default function TabsHome() { - return ; -} diff --git a/src/app/_layout.tsx b/src/app/_layout.tsx index bf3dc4e..0440b97 100644 --- a/src/app/_layout.tsx +++ b/src/app/_layout.tsx @@ -1,4 +1,4 @@ -import React, { useEffect } from 'react'; +import React, { useEffect, useState } from 'react'; import { View, ActivityIndicator, @@ -13,7 +13,11 @@ import { Poppins_600SemiBold, } from '@expo-google-fonts/poppins'; import { Stack } from 'expo-router/stack'; -import { ChevronLeftIcon } from 'react-native-heroicons/outline'; +import { ChevronLeftIcon, XMarkIcon } from 'react-native-heroicons/outline'; +import { Provider } from 'react-redux'; +import { store } from '../redux/store'; +import { Colors } from '../styles/theme'; +import { NotificationsProvider } from '../hooks/useNotifications'; SplashScreen.preventAutoHideAsync(); @@ -24,51 +28,172 @@ export default function RootLayout() { Poppins_600SemiBold, }); + const [isAppReady, setIsAppReady] = useState(false); + useEffect(() => { - if (fontsLoaded) { - SplashScreen.hideAsync(); - } + const prepareApp = async () => { + if (fontsLoaded) { + SplashScreen.hideAsync(); + setIsAppReady(true); // Marca la app como lista + } + }; + + prepareApp(); }, [fontsLoaded]); - if (!fontsLoaded) { + if (!isAppReady) { return ( - + ); } return ( - ({ - headerBackVisible: false, - headerLeft: () => - navigation.canGoBack() ? ( - - - - ) : null, - headerBackTitleVisible: false, - })} - > - - - + + + ({ + headerBackVisible: false, + headerStyle: { + backgroundColor: Colors.bgColor, // Color específico para esta pantalla + }, + headerShadowVisible: false, + headerLeft: () => + navigation.canGoBack() ? ( + + + + ) : null, + headerBackTitleVisible: false, + })} + > + {/* Cambia la pantalla inicial al SplashScreen personalizado */} + - - - - - + + + + + + + + + + + + + + + + + + + ({ + headerTitle: '', + headerLeft: undefined, + headerRight: () => ( + navigation.goBack()}> + + + ), + })} + /> + + + + + + + ({ + headerTitle: '', + headerTransparent: true, + headerShown: true, + headerLeft: () => ( + navigation.goBack()} + style={{ + padding: 12, + marginLeft: -12, + flexDirection: 'row', + alignItems: 'center', + }} + > + + + ), + })} + /> + + + + + ); } diff --git a/src/app/active-orders.tsx b/src/app/active-orders.tsx new file mode 100644 index 0000000..96416d0 --- /dev/null +++ b/src/app/active-orders.tsx @@ -0,0 +1,3 @@ +import ActiveOrdersScreen from '../screens/ActiveOrdersScreen'; + +export default ActiveOrdersScreen; diff --git a/src/app/branchDetail/[id].tsx b/src/app/branchDetail/[id].tsx new file mode 100644 index 0000000..b37d3f7 --- /dev/null +++ b/src/app/branchDetail/[id].tsx @@ -0,0 +1,2 @@ +import BranchDetailScreen from '../../screens/BranchDetailScreen'; +export default BranchDetailScreen; diff --git a/src/app/branchDetail/_layout.tsx b/src/app/branchDetail/_layout.tsx new file mode 100644 index 0000000..c4d9d43 --- /dev/null +++ b/src/app/branchDetail/_layout.tsx @@ -0,0 +1,38 @@ +import React from 'react'; +import { TouchableOpacity, View, StyleSheet } from 'react-native'; +import { Stack } from 'expo-router'; +import { ChevronLeftIcon } from 'react-native-heroicons/outline'; + +export default function BranchDetailLayout() { + return ( + ({ + headerShown: true, + headerTransparent: true, + headerTitle: '', + headerLeft: () => + navigation.canGoBack() ? ( + + + + + + ) : null, + })} + /> + ); +} + +const styles = StyleSheet.create({ + iconContainer: { + marginLeft: -8, + }, +}); diff --git a/src/app/cart.tsx b/src/app/cart.tsx new file mode 100644 index 0000000..3c79068 --- /dev/null +++ b/src/app/cart.tsx @@ -0,0 +1,3 @@ +import CartListScreen from '../../src/screens/CartListScreen'; + +export default CartListScreen; diff --git a/src/app/categoryDetail/[id].tsx b/src/app/categoryDetail/[id].tsx new file mode 100644 index 0000000..a220fef --- /dev/null +++ b/src/app/categoryDetail/[id].tsx @@ -0,0 +1,2 @@ +import CategoryDetailScreen from '../../screens/CategoryDetailScreen'; +export default CategoryDetailScreen; diff --git a/src/app/categoryDetail/_layout.tsx b/src/app/categoryDetail/_layout.tsx new file mode 100644 index 0000000..cb44643 --- /dev/null +++ b/src/app/categoryDetail/_layout.tsx @@ -0,0 +1,38 @@ +import React from 'react'; +import { TouchableOpacity, View, StyleSheet } from 'react-native'; +import { Stack } from 'expo-router'; +import { ChevronLeftIcon } from 'react-native-heroicons/outline'; + +export default function CategoryDetailLayout() { + return ( + ({ + headerShown: true, + headerTransparent: true, + headerTitle: '', + headerLeft: () => + navigation.canGoBack() ? ( + + + + + + ) : null, + })} + /> + ); +} + +const styles = StyleSheet.create({ + iconContainer: { + marginLeft: -8, + }, +}); diff --git a/src/app/change-direction/[id].tsx b/src/app/change-direction/[id].tsx new file mode 100644 index 0000000..c098574 --- /dev/null +++ b/src/app/change-direction/[id].tsx @@ -0,0 +1,2 @@ +import ChangeDirectionScreen from '../../screens/DirectionChangeScreen'; +export default ChangeDirectionScreen; diff --git a/src/app/change-direction/_layout.tsx b/src/app/change-direction/_layout.tsx new file mode 100644 index 0000000..12e0b44 --- /dev/null +++ b/src/app/change-direction/_layout.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import { Stack } from 'expo-router'; + +export default function DirectionLayout() { + return ( + + ); +} diff --git a/src/app/change-password.tsx b/src/app/change-password.tsx new file mode 100644 index 0000000..e14c711 --- /dev/null +++ b/src/app/change-password.tsx @@ -0,0 +1,2 @@ +import ChangePasswordScreen from '../screens/PasswordChangeScreen'; +export default ChangePasswordScreen; diff --git a/src/app/checkout.tsx b/src/app/checkout.tsx new file mode 100644 index 0000000..741cfb9 --- /dev/null +++ b/src/app/checkout.tsx @@ -0,0 +1,3 @@ +import CheckoutScreen from '../screens/CheckoutScreen'; + +export default CheckoutScreen; diff --git a/src/app/createDirection.tsx b/src/app/createDirection.tsx new file mode 100644 index 0000000..1ae1ce1 --- /dev/null +++ b/src/app/createDirection.tsx @@ -0,0 +1,2 @@ +import DirectionCreateScreen from '../screens/DirectionCreateScreen'; +export default DirectionCreateScreen; diff --git a/src/app/deliveryDetail/[id].tsx b/src/app/deliveryDetail/[id].tsx new file mode 100644 index 0000000..6f8a55f --- /dev/null +++ b/src/app/deliveryDetail/[id].tsx @@ -0,0 +1,2 @@ +import DeliveryDetailScreen from '../../screens/delivery/DeliveryDetailScreen'; +export default DeliveryDetailScreen; diff --git a/src/app/deliveryDetail/_layout.tsx b/src/app/deliveryDetail/_layout.tsx new file mode 100644 index 0000000..2fe1a7e --- /dev/null +++ b/src/app/deliveryDetail/_layout.tsx @@ -0,0 +1,38 @@ +import React from 'react'; +import { TouchableOpacity, View, StyleSheet } from 'react-native'; +import { Stack } from 'expo-router'; +import { ChevronLeftIcon } from 'react-native-heroicons/outline'; + +export default function DeliveryDetailLayout() { + return ( + ({ + headerShown: true, + headerTransparent: true, + headerTitle: '', + headerLeft: () => + navigation.canGoBack() ? ( + + + + + + ) : null, + })} + /> + ); +} + +const styles = StyleSheet.create({ + iconContainer: { + marginLeft: -8, + }, +}); diff --git a/src/app/deliveryHistoryDetail/[id].tsx b/src/app/deliveryHistoryDetail/[id].tsx new file mode 100644 index 0000000..c7fb885 --- /dev/null +++ b/src/app/deliveryHistoryDetail/[id].tsx @@ -0,0 +1,2 @@ +import DeliveryHistoryDetailScreen from '../../screens/delivery/DeliveryHistoryDetailScreen'; +export default DeliveryHistoryDetailScreen; diff --git a/src/app/deliveryHistoryDetail/_layout.tsx b/src/app/deliveryHistoryDetail/_layout.tsx new file mode 100644 index 0000000..2fe1a7e --- /dev/null +++ b/src/app/deliveryHistoryDetail/_layout.tsx @@ -0,0 +1,38 @@ +import React from 'react'; +import { TouchableOpacity, View, StyleSheet } from 'react-native'; +import { Stack } from 'expo-router'; +import { ChevronLeftIcon } from 'react-native-heroicons/outline'; + +export default function DeliveryDetailLayout() { + return ( + ({ + headerShown: true, + headerTransparent: true, + headerTitle: '', + headerLeft: () => + navigation.canGoBack() ? ( + + + + + + ) : null, + })} + /> + ); +} + +const styles = StyleSheet.create({ + iconContainer: { + marginLeft: -8, + }, +}); diff --git a/src/app/direction.tsx b/src/app/direction.tsx new file mode 100644 index 0000000..4dbdacc --- /dev/null +++ b/src/app/direction.tsx @@ -0,0 +1,2 @@ +import DirectionScreen from '../screens/DirectionScreen'; +export default DirectionScreen; diff --git a/src/app/in-progress-order.tsx b/src/app/in-progress-order.tsx new file mode 100644 index 0000000..746011c --- /dev/null +++ b/src/app/in-progress-order.tsx @@ -0,0 +1,3 @@ +import InProgressOrderScreen from '../screens/InProgressOrderScreen'; + +export default InProgressOrderScreen; diff --git a/src/app/index.tsx b/src/app/index.tsx index ef45edd..c644d4f 100644 --- a/src/app/index.tsx +++ b/src/app/index.tsx @@ -1,5 +1,5 @@ import { Redirect } from 'expo-router'; export default function Index() { - return ; + return ; } diff --git a/src/app/loggedInPasswordRecovery.tsx b/src/app/loggedInPasswordRecovery.tsx new file mode 100644 index 0000000..49cfc60 --- /dev/null +++ b/src/app/loggedInPasswordRecovery.tsx @@ -0,0 +1,2 @@ +import LoggedInPasswordRecoveryScreen from '../screens/LoggedInPasswordRecoveryScreen'; +export default LoggedInPasswordRecoveryScreen; diff --git a/src/app/menu.tsx b/src/app/menu.tsx new file mode 100644 index 0000000..fb8d623 --- /dev/null +++ b/src/app/menu.tsx @@ -0,0 +1,2 @@ +import MenuScreen from '../screens/MenuScreen'; +export default MenuScreen; diff --git a/src/app/notifications.tsx b/src/app/notifications.tsx new file mode 100644 index 0000000..58b88a6 --- /dev/null +++ b/src/app/notifications.tsx @@ -0,0 +1,2 @@ +import NotificationsScreen from '../screens/NotificationsScreen'; +export default NotificationsScreen; diff --git a/src/app/order/[id].tsx b/src/app/order/[id].tsx new file mode 100644 index 0000000..0645eb6 --- /dev/null +++ b/src/app/order/[id].tsx @@ -0,0 +1,2 @@ +import OrderDetailScreen from '../../screens/OrderDetailScreen'; +export default OrderDetailScreen; diff --git a/src/app/order/_layout.tsx b/src/app/order/_layout.tsx new file mode 100644 index 0000000..365a7bd --- /dev/null +++ b/src/app/order/_layout.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import { Stack } from 'expo-router'; + +export default function OrdersLayout() { + return ( + + ); +} diff --git a/src/app/order/tracking/[id].tsx b/src/app/order/tracking/[id].tsx new file mode 100644 index 0000000..6d95284 --- /dev/null +++ b/src/app/order/tracking/[id].tsx @@ -0,0 +1,2 @@ +import OrderTrackingScreen from '../../../screens/OrderTrackingScreen'; +export default OrderTrackingScreen; diff --git a/src/app/order/tracking/_layout.tsx b/src/app/order/tracking/_layout.tsx new file mode 100644 index 0000000..c0f43ee --- /dev/null +++ b/src/app/order/tracking/_layout.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import { Stack } from 'expo-router'; + +export default function OrdersTrackingLayout() { + return ( + + ); +} diff --git a/src/app/orders.tsx b/src/app/orders.tsx new file mode 100644 index 0000000..929cce9 --- /dev/null +++ b/src/app/orders.tsx @@ -0,0 +1,2 @@ +import OrdersScreen from '../screens/OrdersScreen'; +export default OrdersScreen; diff --git a/src/app/products/[productId]/_layout.tsx b/src/app/products/[productId]/_layout.tsx new file mode 100644 index 0000000..c87c606 --- /dev/null +++ b/src/app/products/[productId]/_layout.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import { Stack } from 'expo-router'; + +export default function ProductIdLayout() { + return ( + + ); +} diff --git a/src/app/products/[productId]/presentation/[id].tsx b/src/app/products/[productId]/presentation/[id].tsx new file mode 100644 index 0000000..9e295fd --- /dev/null +++ b/src/app/products/[productId]/presentation/[id].tsx @@ -0,0 +1,2 @@ +import ProductDetailScreen from '../../../../screens/ProductDetailScreen'; +export default ProductDetailScreen; diff --git a/src/app/products/[productId]/presentation/_layout.tsx b/src/app/products/[productId]/presentation/_layout.tsx new file mode 100644 index 0000000..1bbfe4d --- /dev/null +++ b/src/app/products/[productId]/presentation/_layout.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import { Stack } from 'expo-router'; + +export default function PresentationLayout() { + return ( + + ); +} diff --git a/src/app/products/_layout.tsx b/src/app/products/_layout.tsx new file mode 100644 index 0000000..04160e7 --- /dev/null +++ b/src/app/products/_layout.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import { Stack } from 'expo-router'; + +export default function ProductsLayout() { + return ( + + ); +} diff --git a/src/app/profile.tsx b/src/app/profile.tsx new file mode 100644 index 0000000..f48c96f --- /dev/null +++ b/src/app/profile.tsx @@ -0,0 +1,2 @@ +import ProfileScreen from '../screens/ProfileScreen'; +export default ProfileScreen; diff --git a/src/app/search/[query].tsx b/src/app/search/[query].tsx new file mode 100644 index 0000000..8864333 --- /dev/null +++ b/src/app/search/[query].tsx @@ -0,0 +1,2 @@ +import SearchProductScreen from '../../screens/SearchProductScreen'; +export default SearchProductScreen; diff --git a/src/app/search/_layout.tsx b/src/app/search/_layout.tsx new file mode 100644 index 0000000..7f2e24a --- /dev/null +++ b/src/app/search/_layout.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import { Stack } from 'expo-router'; + +export default function SearchLayout() { + return ( + + ); +} diff --git a/src/app/selectLocation.tsx b/src/app/selectLocation.tsx new file mode 100644 index 0000000..4dfa35d --- /dev/null +++ b/src/app/selectLocation.tsx @@ -0,0 +1,2 @@ +import SelectLocationScreen from '../screens/SelectLocationScreen'; +export default SelectLocationScreen; diff --git a/src/app/splash.tsx b/src/app/splash.tsx new file mode 100644 index 0000000..d5011e5 --- /dev/null +++ b/src/app/splash.tsx @@ -0,0 +1,2 @@ +import SplashScreen from '../screens/SplashScreen'; +export default SplashScreen; diff --git a/src/assets/images/PharmaTech-icon.png b/src/assets/images/PharmaTech-icon.png new file mode 100644 index 0000000..2afdb37 Binary files /dev/null and b/src/assets/images/PharmaTech-icon.png differ diff --git a/src/assets/images/defaults/category.png b/src/assets/images/defaults/category.png new file mode 100644 index 0000000..ddecb47 Binary files /dev/null and b/src/assets/images/defaults/category.png differ diff --git a/src/assets/images/notifications/e.svg b/src/assets/images/notifications/e.svg new file mode 100644 index 0000000..56e4734 --- /dev/null +++ b/src/assets/images/notifications/e.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/images/notifications/f.svg b/src/assets/images/notifications/f.svg new file mode 100644 index 0000000..aa3a765 --- /dev/null +++ b/src/assets/images/notifications/f.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/images/notifications/image.svg b/src/assets/images/notifications/image.svg new file mode 100644 index 0000000..2b74403 --- /dev/null +++ b/src/assets/images/notifications/image.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/images/notifications/m.svg b/src/assets/images/notifications/m.svg new file mode 100644 index 0000000..a5b7463 --- /dev/null +++ b/src/assets/images/notifications/m.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/images/notifications/r.svg b/src/assets/images/notifications/r.svg new file mode 100644 index 0000000..abb5ee3 --- /dev/null +++ b/src/assets/images/notifications/r.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/images/notifications/w.svg b/src/assets/images/notifications/w.svg new file mode 100644 index 0000000..85e6f67 --- /dev/null +++ b/src/assets/images/notifications/w.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/components/AlertProvider.tsx b/src/components/AlertProvider.tsx new file mode 100644 index 0000000..9dda4fc --- /dev/null +++ b/src/components/AlertProvider.tsx @@ -0,0 +1,74 @@ +import React, { createContext, useContext, useState } from 'react'; +import { View, StyleSheet } from 'react-native'; +import Alert from './Alerts'; + +type AlertContextType = { + showAlert: ( + type: 'success' | 'error' | 'info' | 'warning', + title: string, + message: string, + ) => void; +}; + +const AlertContext = createContext(undefined); + +export const AlertProvider: React.FC<{ children: React.ReactNode }> = ({ + children, +}) => { + const [visible, setVisible] = useState(false); + const [type, setType] = useState<'success' | 'error' | 'info' | 'warning'>( + 'info', + ); + const [title, setTitle] = useState(''); + const [message, setMessage] = useState(''); + + const showAlert = ( + alertType: 'success' | 'error' | 'info' | 'warning', + alertTitle: string, + alertMessage: string, + ) => { + setType(alertType); + setTitle(alertTitle); + setMessage(alertMessage); + setVisible(true); + + // Ocultar la alerta automáticamente después de 3 segundos + setTimeout(() => setVisible(false), 3000); + }; + + return ( + + {children} + {visible && ( + + setVisible(false)} + /> + + )} + + ); +}; + +export const useAlert = (): AlertContextType => { + const context = useContext(AlertContext); + if (!context) { + throw new Error('useAlert must be used within an AlertProvider'); + } + return context; +}; + +const styles = StyleSheet.create({ + alertContainer: { + position: 'absolute', + top: 20, + left: '50%', + transform: [{ translateX: -163 }], // Centrar horizontalmente + zIndex: 1000, + width: 326, + }, +}); diff --git a/src/components/Alerts.tsx b/src/components/Alerts.tsx index 758bf0a..440cad0 100644 --- a/src/components/Alerts.tsx +++ b/src/components/Alerts.tsx @@ -22,6 +22,8 @@ interface AlertProps { onClose?: () => void; } +let activeAlertClose: (() => void) | null = null; + const Alert: React.FC = ({ title, message, @@ -62,6 +64,12 @@ const Alert: React.FC = ({ const opacity = useRef(new Animated.Value(0)).current; useEffect(() => { + // Close any active alert before showing a new one + if (activeAlertClose) { + activeAlertClose(); + } + activeAlertClose = handleClose; + Animated.parallel([ Animated.timing(translateY, { toValue: 0, @@ -73,6 +81,12 @@ const Alert: React.FC = ({ useNativeDriver: true, }), ]).start(); + + return () => { + if (activeAlertClose === handleClose) { + activeAlertClose = null; + } + }; }, []); const handleClose = () => { @@ -88,7 +102,7 @@ const Alert: React.FC = ({ useNativeDriver: true, }), ]).start(() => { - onClose?.(); + if (onClose) onClose(); }); }; diff --git a/src/components/Avatar.tsx b/src/components/Avatar.tsx new file mode 100644 index 0000000..facb744 --- /dev/null +++ b/src/components/Avatar.tsx @@ -0,0 +1,151 @@ +import React, { useEffect, useState } from 'react'; +import { Image, View, StyleSheet, ActivityIndicator } from 'react-native'; +import { Colors } from '../styles/theme'; +import { UserService } from '../services/user'; +import PoppinsText from './PoppinsText'; +import * as SecureStore from 'expo-secure-store'; +import { usePathname } from 'expo-router'; + +type AvatarProps = { + scale?: number; // Propiedad para definir el tamaño del avatar +}; + +const Avatar: React.FC = ({ scale = 32 }) => { + const [profile, setProfile] = useState<{ uri?: string; name?: string }>({}); + const [loading, setLoading] = useState(true); + const pathname = usePathname(); + + useEffect(() => { + const fetchProfile = async () => { + setLoading(true); + + const token = await SecureStore.getItemAsync('auth_token'); + if (!token) { + console.warn( + 'No se encontró el token de autenticación. Usando datos locales.', + ); + + const userData = await SecureStore.getItemAsync('user_data'); + if (userData) { + const { firstName, lastName } = JSON.parse(userData); + setProfile({ + name: `${firstName} ${lastName}`, + }); + } else { + console.error('No se encontraron datos del usuario en SecureStore.'); + } + + setLoading(false); + return; + } + + const response = await UserService.getProfile(); + if (response.success) { + const { firstName, lastName } = response.data!; + const profilePicture = response.data.profile.profilePicture; + setProfile({ + uri: + profilePicture !== 'https://via.placeholder.com/150' + ? profilePicture + : '', + name: `${firstName} ${lastName}`, + }); + } else { + console.error('Error fetching profile:', response.error); + } + setLoading(false); + }; + + fetchProfile(); + }, [pathname]); + + const getInitials = (fullName: string): string => { + const words = fullName.trim().split(' '); + if (words.length === 1) return words[0].charAt(0).toUpperCase(); + return (words[0].charAt(0) + words[1].charAt(0)).toUpperCase(); + }; + + // Cálculo dinámico de tamaño y fuentes + const avatarSize = scale; + const fontSize = avatarSize / 2.5; + const lineHeight = fontSize + 1; + const marginTop = avatarSize / 10; + + if (loading) { + return ( + + + + ); + } + + return ( + + {profile.uri ? ( + + ) : ( + + {profile.name ? getInitials(profile.name) : ''} + + )} + + ); +}; + +const styles = StyleSheet.create({ + avatar: { + backgroundColor: Colors.primary, + alignItems: 'center', + justifyContent: 'center', + overflow: 'hidden', + }, + avatarImage: { + resizeMode: 'cover', + }, + initials: { + color: Colors.textWhite, + textAlign: 'center', + }, + avatarContainer: { + backgroundColor: Colors.primary, + alignItems: 'center', + justifyContent: 'center', + overflow: 'hidden', + }, + loadingContainer: { + backgroundColor: Colors.stroke, + }, +}); + +export default Avatar; diff --git a/src/components/AvatarWithMenu.tsx b/src/components/AvatarWithMenu.tsx new file mode 100644 index 0000000..3432caa --- /dev/null +++ b/src/components/AvatarWithMenu.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { View, TouchableOpacity, StyleSheet } from 'react-native'; +import Avatar from './Avatar'; +import { useRouter } from 'expo-router'; + +const AvatarWithMenu: React.FC = () => { + const router = useRouter(); + + return ( + + router.push('menu')}> + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + position: 'absolute', + top: -15, + left: 0, + zIndex: 100, + }, +}); + +export default AvatarWithMenu; diff --git a/src/components/Badge.tsx b/src/components/Badge.tsx new file mode 100644 index 0000000..e308669 --- /dev/null +++ b/src/components/Badge.tsx @@ -0,0 +1,173 @@ +import React from 'react'; +import { + View, + StyleSheet, + StyleProp, + ViewStyle, + TextStyle, +} from 'react-native'; +import { Colors } from '../styles/theme'; +import PoppinsText from './PoppinsText'; + +export interface BadgeProps { + variant: 'filled' | 'outlined' | 'text'; + color: + | 'primary' + | 'warning' + | 'danger' + | 'success' + | 'info' + | 'secondary_300' + | 'primary_300'; + size: 'tiny' | 'small' | 'medium' | 'large'; + borderRadius?: 'rounded' | 'square'; + textColor?: string; + children: React.ReactNode; +} + +const Badge: React.FC = ({ + variant, + color, + size, + borderRadius = 'rounded', + textColor, + children, +}) => { + const sizeStyles: Record> = { + tiny: { height: 17, fontSize: 10, minWidth: 17 }, + small: { height: 24, fontSize: 12, minWidth: 24 }, + medium: { height: 32, fontSize: 14, minWidth: 32 }, + large: { height: 40, fontSize: 16, minWidth: 40 }, + }; + + const borderRadiusStyles: Record> = { + rounded: { borderRadius: 9999 }, + square: { borderRadius: 4 }, + }; + + const colorStyles: Record< + string, + Record> + > = { + filled: { + primary: { backgroundColor: Colors.primary, color: Colors.textWhite }, + warning: { + backgroundColor: Colors.semanticWarning, + color: Colors.textWhite, + }, + danger: { + backgroundColor: Colors.semanticDanger, + color: Colors.textWhite, + }, + success: { + backgroundColor: Colors.semanticSuccess, + color: Colors.textWhite, + }, + info: { backgroundColor: Colors.semanticInfo, color: Colors.textWhite }, + + secondary_300: { + backgroundColor: Colors.secondary_300, + color: Colors.textWhite, + }, + + primary_300: { + backgroundColor: Colors.primary_300, + color: Colors.textWhite, + }, + }, + outlined: { + primary: { + borderColor: Colors.primary, + borderWidth: 1, + color: Colors.primary, + }, + warning: { + borderColor: Colors.semanticWarning, + borderWidth: 1, + color: Colors.semanticWarning, + }, + danger: { + borderColor: Colors.semanticDanger, + borderWidth: 1, + color: Colors.semanticDanger, + }, + success: { + borderColor: Colors.semanticSuccess, + borderWidth: 1, + color: Colors.semanticSuccess, + }, + info: { + borderColor: Colors.semanticInfo, + borderWidth: 1, + color: Colors.semanticInfo, + }, + secondary_300: { + borderColor: Colors.secondary_300, + borderWidth: 1, + color: Colors.secondary_300, + }, + primary_300: { + borderColor: Colors.primary_300, + borderWidth: 1, + color: Colors.primary_300, + }, + }, + text: { + primary: { color: Colors.primary }, + warning: { color: Colors.semanticWarning }, + danger: { color: Colors.semanticDanger }, + success: { color: Colors.semanticSuccess }, + info: { color: Colors.semanticInfo }, + secondary_300: { color: Colors.secondary_300 }, + primary_300: { color: Colors.primary_300 }, + }, + }; + + const variantStyle = colorStyles[variant][color]; + const sizeStyle = sizeStyles[size]; + const borderRadiusStyle = borderRadiusStyles[borderRadius]; + + return ( + 1 ? 6 : 4 }, + ]} + > + + {children} + + + ); +}; + +const styles = StyleSheet.create({ + base: { + justifyContent: 'center', + alignItems: 'center', + paddingHorizontal: 4, + }, + text: { + textAlign: 'center', + marginTop: 1.5, + lineHeight: 16, + fontSize: 10, + }, +}); + +export default Badge; diff --git a/src/components/BranchCard.tsx b/src/components/BranchCard.tsx new file mode 100644 index 0000000..e6dd46a --- /dev/null +++ b/src/components/BranchCard.tsx @@ -0,0 +1,45 @@ +import React from 'react'; +import { StyleSheet, TouchableOpacity } from 'react-native'; +import { BranchResponse } from '@pharmatech/sdk'; +import { Colors, FontSizes } from '../styles/theme'; +import PoppinsText from './PoppinsText'; + +type BranchCardProps = { + branch: BranchResponse; + onPress: () => void; +}; + +const BranchCard: React.FC = ({ branch, onPress }) => { + return ( + + {branch.name} + {branch.address} + + ); +}; + +const styles = StyleSheet.create({ + card: { + backgroundColor: Colors.menuWhite, + borderRadius: 8, + padding: 16, + marginBottom: 10, + shadowColor: '#000', + shadowOpacity: 0.1, + shadowRadius: 4, + elevation: 2, + }, + name: { + fontSize: FontSizes.s2.size, + lineHeight: FontSizes.s2.lineHeight, + color: Colors.primary, + marginBottom: 4, + }, + address: { + fontSize: FontSizes.b3.size, + lineHeight: FontSizes.b3.lineHeight, + color: Colors.textLowContrast, + }, +}); + +export default BranchCard; diff --git a/src/components/BranchMap.tsx b/src/components/BranchMap.tsx new file mode 100644 index 0000000..e6556e7 --- /dev/null +++ b/src/components/BranchMap.tsx @@ -0,0 +1,117 @@ +import React, { useMemo } from 'react'; +import { StyleSheet, View } from 'react-native'; +import MapView, { Marker, PROVIDER_GOOGLE } from 'react-native-maps'; +import { Colors } from '../styles/theme'; +import { MapPinIcon } from 'react-native-heroicons/solid'; +import PoppinsText from './PoppinsText'; + +type Branch = { + id: string; + name: string; + address: string; + latitude: number | null | undefined; + longitude: number | null | undefined; + stockQuantity: number; +}; + +type BranchMapProps = { + branches: Branch[]; +}; + +// Componente Marker personalizado con React.memo +const CustomMarker = React.memo(({ branch }: { branch: Branch }) => ( + + + + + +)); + +CustomMarker.displayName = 'CustomMarker'; + +const BranchMap: React.FC = ({ branches }) => { + // Memorizar las sucursales válidas + const validBranches = useMemo( + () => + branches.filter( + (branch) => + branch.latitude !== null && + branch.latitude !== undefined && + branch.longitude !== null && + branch.longitude !== undefined, + ), + [branches], + ); + + const initialRegion = useMemo( + () => + validBranches.length > 0 + ? { + latitude: validBranches[0].latitude!, + longitude: validBranches[0].longitude!, + latitudeDelta: 0.1, + longitudeDelta: 0.1, + } + : { + latitude: 10.0678, // Coordenadas de Barquisimeto, estado Lara, Venezuela + longitude: -69.3467, + latitudeDelta: 0.1, + longitudeDelta: 0.1, + }, + [validBranches], + ); + + return ( + + {validBranches.length > 0 ? ( + + {validBranches.map((branch) => ( + + ))} + + ) : ( + + + No hay sucursales disponibles para mostrar en el mapa. + + + )} + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, // Asegura que el mapa ocupe todo el espacio disponible + }, + map: { + ...StyleSheet.absoluteFillObject, // Hace que el mapa ocupe todo el espacio del contenedor + }, + noDataContainer: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + }, + noDataText: { + textAlign: 'center', + color: 'gray', + }, + customMarker: { + alignItems: 'center', + justifyContent: 'center', + }, +}); + +export default BranchMap; diff --git a/src/components/BranchMapModal.tsx b/src/components/BranchMapModal.tsx new file mode 100644 index 0000000..9d15c5d --- /dev/null +++ b/src/components/BranchMapModal.tsx @@ -0,0 +1,115 @@ +import React from 'react'; +import { Modal, View, StyleSheet, TouchableOpacity } from 'react-native'; +import { XMarkIcon, MapPinIcon } from 'react-native-heroicons/solid'; +import PoppinsText from './PoppinsText'; +import BranchMap from './BranchMap'; // Import BranchMap +import { Colors } from '../styles/theme'; + +const BranchMapModal = ({ + visible, + onClose, + branchName, + branchCoordinates, +}: { + visible: boolean; + onClose: () => void; + branchName: string | null; + branchCoordinates: { latitude: number; longitude: number } | null; // Add branchCoordinates prop +}) => { + return ( + + + + + + + + Dirección de Sucursal + + + {branchCoordinates ? ( + + ) : ( + + )} + + + + + {branchName} + + + + + ); +}; + +const styles = StyleSheet.create({ + overlay: { + flex: 1, + backgroundColor: 'rgba(0,0,0,0.4)', + justifyContent: 'center', + alignItems: 'center', + }, + modal: { + width: 352, + height: 448, + backgroundColor: Colors.menuWhite, + borderRadius: 16, + padding: 20, + alignItems: 'center', + position: 'relative', + elevation: 8, + }, + closeButton: { + position: 'absolute', + top: 20, + right: 20, + zIndex: 10, + }, + title: { + fontSize: 16, + fontWeight: '600', + color: Colors.textMain, + textAlign: 'center', + marginTop: 20, + marginBottom: 16, + }, + mapContainer: { + width: 285, + height: 285, + borderRadius: 12, + overflow: 'hidden', + backgroundColor: Colors.gray_100, + marginBottom: 20, + }, + fakeMap: { + flex: 1, + backgroundColor: '#ccc', + }, + branchInfo: { + flexDirection: 'row', + alignSelf: 'flex-start', + alignItems: 'center', + marginLeft: 5, + }, + branchName: { + fontSize: 14, + color: Colors.textMain, + marginLeft: 6, + textAlign: 'left', + }, +}); + +export default BranchMapModal; diff --git a/src/components/Button.tsx b/src/components/Button.tsx index d123ef0..fac699e 100644 --- a/src/components/Button.tsx +++ b/src/components/Button.tsx @@ -17,7 +17,8 @@ export type ButtonVariant = | 'secondaryLight' | 'secondaryWhite' | 'secondaryGray' - | 'disabled'; + | 'disabled' + | 'iconCancel'; export type ButtonMode = 'filled' | 'outline'; @@ -67,6 +68,10 @@ const getButtonStyles = ( backgroundColor = Colors.stroke; borderColor = Colors.stroke; break; + case 'iconCancel': // Nuevo color para el botón "Descartar" + backgroundColor = Colors.iconCancel; + borderColor = Colors.iconCancel; + break; default: backgroundColor = Colors.primary; borderColor = Colors.primary; @@ -98,19 +103,23 @@ const getTextColor = (variant: ButtonVariant, mode: ButtonMode): string => { return Colors.secondaryGray; case 'disabled': return Colors.disableText; + case 'iconCancel': // Color para el texto del botón "Descartar" + return Colors.iconCancel; default: return Colors.primary; } } return variant === 'secondaryWhite' ? Colors.textHighContrast - : variant === 'secondary' - ? Colors.textHighContrast - : variant === 'secondaryLight' + : variant === 'iconCancel' + ? Colors.textWhite + : variant === 'disabled' ? Colors.textHighContrast - : variant === 'disabled' - ? Colors.disableText - : Colors.textWhite; + : variant === 'secondary' + ? Colors.textHighContrast + : variant === 'secondaryLight' + ? Colors.disableText + : Colors.textWhite; }; const getFontSizeStyle = (size: ButtonSize): TextStyle => { diff --git a/src/components/Card.tsx b/src/components/Card.tsx index d494007..8e492cb 100644 --- a/src/components/Card.tsx +++ b/src/components/Card.tsx @@ -1,21 +1,18 @@ import React from 'react'; -import { View, StyleSheet, Image } from 'react-native'; +import { View, StyleSheet, Image, TouchableOpacity } from 'react-native'; import { Colors, FontSizes } from '../styles/theme'; import PoppinsText from './PoppinsText'; import CardButton from './CardButton'; import { truncateString } from '../utils/commons'; +import { useCart } from '../hooks/useCart'; +import { Product } from '../types/Product'; +import { useRouter } from 'expo-router'; +import { formatPrice } from '../utils/formatPrice'; -interface ProductCardProps { - imageUrl?: string; - name: string; - category?: string; - originalPrice: string; - discount?: string; - finalPrice?: string; - getQuantity?: (count: number) => void; -} - -const ProductCard: React.FC = ({ +const ProductCard: React.FC = ({ + id, + presentationId, + productId, imageUrl, name, category, @@ -24,107 +21,130 @@ const ProductCard: React.FC = ({ finalPrice, getQuantity, }) => { + const { getItemQuantity, addToCart } = useCart(); + const router = useRouter(); + const computedFinalPrice = discount + ? (finalPrice * (100 - discount)) / 100 + : finalPrice; + return ( - - + + router.push( + '/products/' + productId + '/presentation/' + presentationId, + ) + } + > + - {category} - - - - - + + {category} - - - - {truncateString(name)} - {discount && ( - - - ${originalPrice} - - {discount}% + + + + { + if (getQuantity) getQuantity(quantity); + // Asegura que price siempre sea number + addToCart({ + id, + name, + price: originalPrice ?? 0, + quantity, + image: imageUrl, + discount: discount ?? 0, + }); + }} + initialValue={getItemQuantity(id)} + /> + - )} - - ${finalPrice} - + + + {truncateString(name)} + {discount && ( + + + ${formatPrice(originalPrice ?? 0)} + + {discount}% + + )} + + ${formatPrice(computedFinalPrice)} + + - + ); }; const styles = StyleSheet.create({ card: { margin: 10, - backgroundColor: '#fff', + backgroundColor: Colors.menuWhite, borderWidth: 1, - borderColor: '#ccc', + borderColor: Colors.gray_100, borderRadius: 15, - padding: 16, + padding: 10, paddingBottom: 5, - shadowColor: '#000', - shadowOffset: { width: 0, height: 2 }, - shadowOpacity: 0.1, - shadowRadius: 4, - elevation: 3, marginBottom: 16, - maxWidth: 170, - minWidth: 170, - minHeight: 330, - maxHeight: 330, + maxWidth: 140, + minWidth: 140, + minHeight: 315, + maxHeight: 315, }, tag: { backgroundColor: Colors.semanticInfo, borderRadius: 50, paddingHorizontal: 9, color: Colors.textWhite, - fontSize: FontSizes.c2.size, + fontSize: FontSizes.c3.size, maxWidth: '100%', }, imageContainer: { - backgroundColor: Colors.secondaryGray, - minHeight: 140, - maxHeight: 140, + minHeight: 118, + maxHeight: 118, + maxWidth: 114, borderRadius: 15, marginVertical: 8, }, cardButtonContainer: { position: 'relative', top: -30, - left: 63, + left: 58, maxWidth: '65%', alignItems: 'flex-end', zIndex: 999, }, description: { - marginHorizontal: 4, + marginHorizontal: 2, + justifyContent: 'center', }, name: { fontSize: FontSizes.s2.size, - marginBottom: 8, + marginBottom: 6, + minHeight: 70, + maxHeight: 70, }, priceContainer: { flexDirection: 'row', @@ -134,16 +154,16 @@ const styles = StyleSheet.create({ fontSize: FontSizes.b1.size, color: Colors.disableText, textDecorationLine: 'line-through', - marginRight: 18, + marginRight: 14, }, discount: { fontSize: FontSizes.c1.size, backgroundColor: Colors.semanticInfo, borderRadius: 5, - padding: 5, + padding: 4, }, finalPrice: { - fontSize: 20, + fontSize: FontSizes.s1.size, }, }); diff --git a/src/components/CardButton.tsx b/src/components/CardButton.tsx index 256e198..1ab08d0 100644 --- a/src/components/CardButton.tsx +++ b/src/components/CardButton.tsx @@ -6,33 +6,63 @@ import { Colors, FontSizes } from '../styles/theme'; interface CardButtonProps { getValue?: (count: number) => void; + initialValue: number; + size?: number; + syncQuantity?: (count: number) => void; + disabled?: boolean; + showNoStockAlert?: () => void; // <-- nuevo prop opcional } -const CardButton: React.FC = ({ getValue }) => { - const [count, setCount] = useState(0); +const CardButton: React.FC = ({ + getValue, + initialValue = 0, + size = 4, + syncQuantity, + disabled = false, // <-- Valor por defecto + showNoStockAlert, // <-- Add this line +}) => { + const [count, setCount] = useState(initialValue); const [showCounter, setShowCounter] = useState(false); + const [hasInteracted, setHasInteracted] = useState(false); + + const toggleCounter = () => setShowCounter(count > 0); + useEffect(toggleCounter, [count]); useEffect(() => { - if (count == 0) setShowCounter(false); - else { - setShowCounter(true); - } - if (getValue) { + if (hasInteracted && getValue) { getValue(count); } + if (hasInteracted && syncQuantity) { + syncQuantity(count); + } }, [count]); + useEffect(() => { + setCount(initialValue); + }, [initialValue]); + const incrementCount = () => { + if (disabled) { + if (showNoStockAlert) showNoStockAlert(); + return; + } + setHasInteracted(true); setCount((prev) => prev + 1); }; const decrementCount = () => { + if (disabled) { + if (showNoStockAlert) showNoStockAlert(); + return; + } if (count > 0) { + setHasInteracted(true); setCount((prev) => prev - 1); } }; const showCounterIncrement = () => { + if (disabled) return; // <-- No permitir si está deshabilitado setShowCounter(true); incrementCount(); }; @@ -41,9 +71,14 @@ const CardButton: React.FC = ({ getValue }) => { {!showCounter ? ( { - showCounterIncrement(); + if (disabled && showNoStockAlert) showNoStockAlert(); + else showCounterIncrement(); }} > @@ -51,10 +86,19 @@ const CardButton: React.FC = ({ getValue }) => { ) : ( - + { + if (disabled && showNoStockAlert) showNoStockAlert(); + else decrementCount(); + }} > @@ -65,7 +109,10 @@ const CardButton: React.FC = ({ getValue }) => { { + if (disabled && showNoStockAlert) showNoStockAlert(); + else incrementCount(); + }} > @@ -85,8 +132,6 @@ const styles = StyleSheet.create({ }, mainButton: { backgroundColor: Colors.primary, - paddingVertical: 5, - paddingHorizontal: 5, borderRadius: 50, elevation: 3, }, @@ -96,7 +141,6 @@ const styles = StyleSheet.create({ gap: 15, backgroundColor: Colors.primary, borderRadius: 50, - padding: 5, }, counterButton: { width: 20, diff --git a/src/components/Carousel.tsx b/src/components/Carousel.tsx index c9c54ac..a80adb9 100644 --- a/src/components/Carousel.tsx +++ b/src/components/Carousel.tsx @@ -1,32 +1,24 @@ import React from 'react'; import { View, StyleSheet, Dimensions, ScrollView } from 'react-native'; import ProductCard from './Card'; -import { ProductPresentation } from '../types/api'; +import { Product } from '../types/Product'; const { width: screenWidth } = Dimensions.get('window'); -type ProductCardProps = { - cards: ProductPresentation[]; +type CarouselProps = { + cards: Product[]; }; -const Carrusel: React.FC = ({ cards }) => { +const Carousel: React.FC = ({ cards }) => { return ( {cards.map((item, index) => ( - + ))} @@ -38,10 +30,10 @@ const styles = StyleSheet.create({ flex: 1, }, card: { - width: screenWidth - 170, // Ancho de cada card + width: screenWidth - 207, // Ancho de cada card borderRadius: 10, alignItems: 'center', }, }); -export default Carrusel; +export default Carousel; diff --git a/src/components/CartTotal.tsx b/src/components/CartTotal.tsx new file mode 100644 index 0000000..cb35ecb --- /dev/null +++ b/src/components/CartTotal.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import { useSelector } from 'react-redux'; +import { RootState } from '../redux/store'; +import { Text } from 'react-native'; + +const CartTotal = () => { + const total = useSelector((state: RootState) => state.cart.total); + + return Total del carrito: ${total}; +}; + +export default CartTotal; diff --git a/src/components/Checkbox.tsx b/src/components/Checkbox.tsx index 3631545..7b8233d 100644 --- a/src/components/Checkbox.tsx +++ b/src/components/Checkbox.tsx @@ -6,8 +6,9 @@ import PoppinsText from './PoppinsText'; interface CheckboxProps { checked: boolean; - onChange: (checked: boolean) => void; + onChange: (checked: boolean, value: string) => void; label?: string; + value: string; disabled?: boolean; color?: string; size?: number; @@ -18,6 +19,7 @@ const Checkbox: React.FC = ({ checked, onChange, label, + value, disabled = false, color = Colors.primary, size = 24, @@ -25,7 +27,7 @@ const Checkbox: React.FC = ({ }) => { const handlePress = () => { if (!disabled) { - onChange(!checked); + onChange(!checked, value); } }; diff --git a/src/components/Coupon.tsx b/src/components/Coupon.tsx new file mode 100644 index 0000000..2d98bcb --- /dev/null +++ b/src/components/Coupon.tsx @@ -0,0 +1,154 @@ +// src/components/Coupon.tsx +import React, { useState } from 'react'; +import { View, StyleSheet } from 'react-native'; +import Input from './Input'; +import Button from './Button'; +import PoppinsText from './PoppinsText'; +import { Colors, FontSizes } from '../styles/theme'; +import { CouponService } from '../services/coupon'; +import { useDispatch, useSelector } from 'react-redux'; +import { RootState } from '../redux/store'; +import { + setCouponDiscount, + setCouponApplied, + setLastAppliedCoupon, +} from '../redux/slices/checkoutSlice'; + +interface CouponProps { + onApplyCoupon: (discount: number) => void; + onCouponApplied: () => void; + isLoading?: boolean; +} + +const Coupon: React.FC = ({ isLoading = false }) => { + const dispatch = useDispatch(); + const lastAppliedCoupon = useSelector( + (state: RootState) => state.checkout.lastAppliedCoupon, + ); + + const [couponCode, setCouponCode] = useState(lastAppliedCoupon || ''); + const [validationMessage, setValidationMessage] = useState( + null, + ); + const [loading, setLoading] = useState(false); + + const handleApply = async () => { + const code = couponCode.trim(); + if (!code) return; + + setLoading(true); + setValidationMessage(null); + + try { + const response = await CouponService.validateCoupon(code); + const { discount, expirationDate } = response; + if (new Date(expirationDate) < new Date()) { + setValidationMessage('El cupón ha expirado.'); + } else { + setValidationMessage( + `Cupón válido. Se aplicó ${discount}% de descuento.`, + ); + dispatch(setCouponDiscount(discount)); + dispatch(setCouponApplied(true)); + dispatch(setLastAppliedCoupon(code)); + } + } catch (err: unknown) { + const msg = (err instanceof Error && err.message.toLowerCase?.()) ?? ''; + if ( + typeof msg === 'string' && + (msg.includes('not found') || msg.includes('no encontrado')) + ) { + setValidationMessage('Cupón inválido.'); + } else { + setValidationMessage('Error al validar el cupón.'); + console.error('Error en validateCoupon:', err); + } + } finally { + setLoading(false); + } + }; + + const handleChange = (text: string) => { + setCouponCode(text); + }; + + return ( + + Ingresa el Cupón + + + + +