diff --git a/package-lock.json b/package-lock.json index 9bb8eb9..f6bb467 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,7 +30,7 @@ "react-native": "0.79.0", "react-native-alert-notification": "^0.4.2", "react-native-app-intro-slider": "^4.0.4", - "react-native-bouncy-checkbox": "^4.1.3", + "react-native-bouncy-checkbox": "^4.1.2", "react-native-date-picker": "^5.0.13", "react-native-gesture-handler": "^2.30.0", "react-native-gifted-charts": "^1.4.70", @@ -55,7 +55,7 @@ "@babel/core": "^7.25.2", "@babel/preset-env": "^7.25.3", "@babel/runtime": "^7.25.0", - "@react-native-community/cli": "^18.0.1", + "@react-native-community/cli": "18.0.0", "@react-native-community/cli-platform-android": "18.0.0", "@react-native-community/cli-platform-ios": "18.0.0", "@react-native/babel-preset": "0.79.0", @@ -105,6 +105,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -136,6 +137,7 @@ "integrity": "sha512-fcdRcWahONYo+JRnJg1/AekOacGvKx12Gu0qXJXFi2WBqQA1i7+O5PaxRB7kxE/Op94dExnCiiar6T09pvdHpA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", "eslint-visitor-keys": "^2.1.0", @@ -2782,18 +2784,19 @@ } }, "node_modules/@react-native-community/cli": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-18.0.1.tgz", - "integrity": "sha512-nEEYwfyP00j9i4nr/HhwPabDscoBhhCjxDBpcKERi2oTYHcBr3FTu9PV1gbeJCa4vRCHr6b6VgOcVTdy99NddQ==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-18.0.0.tgz", + "integrity": "sha512-DyKptlG78XPFo7tDod+we5a3R+U9qjyhaVFbOPvH4pFNu5Dehewtol/srl44K6Cszq0aEMlAJZ3juk0W4WnOJA==", "devOptional": true, "license": "MIT", + "peer": true, "dependencies": { - "@react-native-community/cli-clean": "18.0.1", - "@react-native-community/cli-config": "18.0.1", - "@react-native-community/cli-doctor": "18.0.1", - "@react-native-community/cli-server-api": "18.0.1", - "@react-native-community/cli-tools": "18.0.1", - "@react-native-community/cli-types": "18.0.1", + "@react-native-community/cli-clean": "18.0.0", + "@react-native-community/cli-config": "18.0.0", + "@react-native-community/cli-doctor": "18.0.0", + "@react-native-community/cli-server-api": "18.0.0", + "@react-native-community/cli-tools": "18.0.0", + "@react-native-community/cli-types": "18.0.0", "chalk": "^4.1.2", "commander": "^9.4.1", "deepmerge": "^4.3.0", @@ -2812,58 +2815,26 @@ } }, "node_modules/@react-native-community/cli-clean": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-clean/-/cli-clean-18.0.1.tgz", - "integrity": "sha512-brXqk//lmA2Vs5lGq9YLhk7X4IYBSrDRte6t1AktouJpCrH4Tp1sl45yJDS2CHOi/OY1oOfI3kA61tXNX5a/5A==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-clean/-/cli-clean-18.0.0.tgz", + "integrity": "sha512-+k64EnJaMI5U8iNDF9AftHBJW+pO/isAhncEXuKRc6IjRtIh6yoaUIIf5+C98fgjfux7CNRZAMQIkPbZodv2Gw==", "devOptional": true, "license": "MIT", "dependencies": { - "@react-native-community/cli-tools": "18.0.1", + "@react-native-community/cli-tools": "18.0.0", "chalk": "^4.1.2", "execa": "^5.0.0", "fast-glob": "^3.3.2" } }, - "node_modules/@react-native-community/cli-clean/node_modules/@react-native-community/cli-tools": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-18.0.1.tgz", - "integrity": "sha512-WxWFXwfYhHR2eYiB4lkHZVC/PmIkRWeVHBQKmn0h1mecr3GrHYO4BzW1jpD5Xt6XZ9jojQ9wE5xrCqXjiMSAIQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@vscode/sudo-prompt": "^9.0.0", - "appdirsjs": "^1.2.4", - "chalk": "^4.1.2", - "execa": "^5.0.0", - "find-up": "^5.0.0", - "launch-editor": "^2.9.1", - "mime": "^2.4.1", - "ora": "^5.4.1", - "prompts": "^2.4.2", - "semver": "^7.5.2" - } - }, - "node_modules/@react-native-community/cli-clean/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "devOptional": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@react-native-community/cli-config": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-config/-/cli-config-18.0.1.tgz", - "integrity": "sha512-O4DDJVMx+DYfwEgF/6lB4hoI9sVjrYW6AlLqeJY/D2XH2e4yqK/Pr3SAi4sOMgvjvYZKzLHqIQVxx54v+LyMQA==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-config/-/cli-config-18.0.0.tgz", + "integrity": "sha512-GUGvyek06JRF4mfd9zXao9YQW4+H8ny69HznqNXVRtVSIIekFyjOpKQeSEzdcyqJEEa5gej22GOz1JCHMKBccg==", "devOptional": true, "license": "MIT", "dependencies": { - "@react-native-community/cli-tools": "18.0.1", + "@react-native-community/cli-tools": "18.0.0", "chalk": "^4.1.2", "cosmiconfig": "^9.0.0", "deepmerge": "^4.3.0", @@ -2875,7 +2846,7 @@ "version": "18.0.0", "resolved": "https://registry.npmjs.org/@react-native-community/cli-config-android/-/cli-config-android-18.0.0.tgz", "integrity": "sha512-pgnhEO2cmOeb+bBFEBZFYjeFjDTqWoV0JTorTiugj9bb4RQRCl8cr35baVlBGhxAuaio3722CsJ9GRF1oHjP8w==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@react-native-community/cli-tools": "18.0.0", @@ -2888,7 +2859,7 @@ "version": "18.0.0", "resolved": "https://registry.npmjs.org/@react-native-community/cli-config-apple/-/cli-config-apple-18.0.0.tgz", "integrity": "sha512-6edjTt3mlNMFBuB/Xd6u0O7GEkhJiKvQgmcoBH18FsNy5cpiHDwQsG8EWM5cHeINp1gMK845qq9fFsTko6gqyQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@react-native-community/cli-tools": "18.0.0", @@ -2897,50 +2868,18 @@ "fast-glob": "^3.3.2" } }, - "node_modules/@react-native-community/cli-config/node_modules/@react-native-community/cli-tools": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-18.0.1.tgz", - "integrity": "sha512-WxWFXwfYhHR2eYiB4lkHZVC/PmIkRWeVHBQKmn0h1mecr3GrHYO4BzW1jpD5Xt6XZ9jojQ9wE5xrCqXjiMSAIQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@vscode/sudo-prompt": "^9.0.0", - "appdirsjs": "^1.2.4", - "chalk": "^4.1.2", - "execa": "^5.0.0", - "find-up": "^5.0.0", - "launch-editor": "^2.9.1", - "mime": "^2.4.1", - "ora": "^5.4.1", - "prompts": "^2.4.2", - "semver": "^7.5.2" - } - }, - "node_modules/@react-native-community/cli-config/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "devOptional": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@react-native-community/cli-doctor": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-doctor/-/cli-doctor-18.0.1.tgz", - "integrity": "sha512-B1UWpiVeJ45DX0ip1Et62knAHLzeA1B3XcTJu16PscednnNxV6GBH52kRUoWMsB8HQ8f9IWdFTol8LAp5Y0wwg==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-doctor/-/cli-doctor-18.0.0.tgz", + "integrity": "sha512-cD3LJfu2h2QSFmZai+fl7RrORKodd5XHSuB7Y9oF1zkebpRYN720vaUtK+GsepqBOElwKk5gl8uVolJ3j+xm8A==", "devOptional": true, "license": "MIT", "dependencies": { - "@react-native-community/cli-config": "18.0.1", - "@react-native-community/cli-platform-android": "18.0.1", - "@react-native-community/cli-platform-apple": "18.0.1", - "@react-native-community/cli-platform-ios": "18.0.1", - "@react-native-community/cli-tools": "18.0.1", + "@react-native-community/cli-config": "18.0.0", + "@react-native-community/cli-platform-android": "18.0.0", + "@react-native-community/cli-platform-apple": "18.0.0", + "@react-native-community/cli-platform-ios": "18.0.0", + "@react-native-community/cli-tools": "18.0.0", "chalk": "^4.1.2", "command-exists": "^1.2.8", "deepmerge": "^4.3.0", @@ -2953,89 +2892,6 @@ "yaml": "^2.2.1" } }, - "node_modules/@react-native-community/cli-doctor/node_modules/@react-native-community/cli-config-android": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-config-android/-/cli-config-android-18.0.1.tgz", - "integrity": "sha512-1wzmGLfS7qgzm0ZfwX/f6Lat/af8/UYdjwtb3ap6RfKNclvIoap0wN6uBeiANmLfk0/BhoG8K1vKtIPwlU/V1A==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@react-native-community/cli-tools": "18.0.1", - "chalk": "^4.1.2", - "fast-glob": "^3.3.2", - "fast-xml-parser": "^4.4.1" - } - }, - "node_modules/@react-native-community/cli-doctor/node_modules/@react-native-community/cli-config-apple": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-config-apple/-/cli-config-apple-18.0.1.tgz", - "integrity": "sha512-ybr1ZrOSd/Z+oCJ1qVSKVQauvneObTu3VjvYPhhrme7tUUSaYmd3iikaWonbKk5rVp+2WqOFR6Cy7XqVfwwG8A==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@react-native-community/cli-tools": "18.0.1", - "chalk": "^4.1.2", - "execa": "^5.0.0", - "fast-glob": "^3.3.2" - } - }, - "node_modules/@react-native-community/cli-doctor/node_modules/@react-native-community/cli-platform-android": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-android/-/cli-platform-android-18.0.1.tgz", - "integrity": "sha512-DCltVWDR7jfZZG5MXREVKG0fmIr1b0irEhmdkk/R87dG6HJ8tGXWXnAa4Kap8bx2v6lKFXDW5QxNecyyLCOkVw==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@react-native-community/cli-config-android": "18.0.1", - "@react-native-community/cli-tools": "18.0.1", - "chalk": "^4.1.2", - "execa": "^5.0.0", - "logkitty": "^0.7.1" - } - }, - "node_modules/@react-native-community/cli-doctor/node_modules/@react-native-community/cli-platform-apple": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-apple/-/cli-platform-apple-18.0.1.tgz", - "integrity": "sha512-7WxGXT/ui7VtyLVjx5rkYkkTMlbufI6p5BdRKjGp/zQDnDzs/0rle0JEHJxwgvs5VQnt+VOnHBMipkQAhydIqQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@react-native-community/cli-config-apple": "18.0.1", - "@react-native-community/cli-tools": "18.0.1", - "chalk": "^4.1.2", - "execa": "^5.0.0", - "fast-xml-parser": "^4.4.1" - } - }, - "node_modules/@react-native-community/cli-doctor/node_modules/@react-native-community/cli-platform-ios": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-ios/-/cli-platform-ios-18.0.1.tgz", - "integrity": "sha512-GtO1FB+xaz+vcHIdvl94AkD5B8Y+H8XHb6QwnYX+A3WwteGsHrR8iD/bLLcRtNPtLaAWMa/RgWJpgs4KG+eU4w==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@react-native-community/cli-platform-apple": "18.0.1" - } - }, - "node_modules/@react-native-community/cli-doctor/node_modules/@react-native-community/cli-tools": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-18.0.1.tgz", - "integrity": "sha512-WxWFXwfYhHR2eYiB4lkHZVC/PmIkRWeVHBQKmn0h1mecr3GrHYO4BzW1jpD5Xt6XZ9jojQ9wE5xrCqXjiMSAIQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@vscode/sudo-prompt": "^9.0.0", - "appdirsjs": "^1.2.4", - "chalk": "^4.1.2", - "execa": "^5.0.0", - "find-up": "^5.0.0", - "launch-editor": "^2.9.1", - "mime": "^2.4.1", - "ora": "^5.4.1", - "prompts": "^2.4.2", - "semver": "^7.5.2" - } - }, "node_modules/@react-native-community/cli-doctor/node_modules/semver": { "version": "7.7.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", @@ -3053,7 +2909,7 @@ "version": "18.0.0", "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-android/-/cli-platform-android-18.0.0.tgz", "integrity": "sha512-3Y3RleN/des1C3oRS6s6fDvFYKN0KwsLrYFRpVx9vzdDnH1OGyFJOy4DbrruSPtdNiHUpvvHnOOxeLMj0+/tmw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@react-native-community/cli-config-android": "18.0.0", @@ -3067,7 +2923,7 @@ "version": "18.0.0", "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-apple/-/cli-platform-apple-18.0.0.tgz", "integrity": "sha512-zD18gdP5Wr8BSLJ79xtHuPYcg2Vi/nL+WsGsPm7TZjzR5ZU2WbY/tZ+qTGVTQYhQaah+92sU+Dam7gStMrF/fA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@react-native-community/cli-config-apple": "18.0.0", @@ -3081,20 +2937,20 @@ "version": "18.0.0", "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-ios/-/cli-platform-ios-18.0.0.tgz", "integrity": "sha512-05Nvkkre/4Gao1TYqyP1wGet8td1dAH0CLJKqLNl9Te6ihnrQ8/8OhjIna5xw0iEFr9An8VdLfaPu1Dgv2qAnQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@react-native-community/cli-platform-apple": "18.0.0" } }, "node_modules/@react-native-community/cli-server-api": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-server-api/-/cli-server-api-18.0.1.tgz", - "integrity": "sha512-ZRy2IjEM4ljP05bZcnXho0sCxVGI/9SkWkLuzXl+cRu/4I8vLRleihn2GJCopg82QHLLrajUCHhpDKE8NJWcRw==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-server-api/-/cli-server-api-18.0.0.tgz", + "integrity": "sha512-tdmGV7ZntYmzrXWheZNpAy6dVI2yrsX4sQH+xAzU7lCfKHk6J8GucxedduXnB5qBB4JgSrrbzg2RLNxv5v0S/Q==", "devOptional": true, "license": "MIT", "dependencies": { - "@react-native-community/cli-tools": "18.0.1", + "@react-native-community/cli-tools": "18.0.0", "body-parser": "^1.20.3", "compression": "^1.7.1", "connect": "^3.6.5", @@ -3106,43 +2962,11 @@ "ws": "^6.2.3" } }, - "node_modules/@react-native-community/cli-server-api/node_modules/@react-native-community/cli-tools": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-18.0.1.tgz", - "integrity": "sha512-WxWFXwfYhHR2eYiB4lkHZVC/PmIkRWeVHBQKmn0h1mecr3GrHYO4BzW1jpD5Xt6XZ9jojQ9wE5xrCqXjiMSAIQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@vscode/sudo-prompt": "^9.0.0", - "appdirsjs": "^1.2.4", - "chalk": "^4.1.2", - "execa": "^5.0.0", - "find-up": "^5.0.0", - "launch-editor": "^2.9.1", - "mime": "^2.4.1", - "ora": "^5.4.1", - "prompts": "^2.4.2", - "semver": "^7.5.2" - } - }, - "node_modules/@react-native-community/cli-server-api/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "devOptional": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@react-native-community/cli-tools": { "version": "18.0.0", "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-18.0.0.tgz", "integrity": "sha512-oR6FcDEcSDYos79vZy4+Tj8jgAE0Xf5HEiRXMJFGISYLRx7tvslSaK8SodUOW9TZe2bCZOb5QSvj8zeMpORmxg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@vscode/sudo-prompt": "^9.0.0", @@ -3161,7 +2985,7 @@ "version": "7.7.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, + "devOptional": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -3171,34 +2995,15 @@ } }, "node_modules/@react-native-community/cli-types": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-types/-/cli-types-18.0.1.tgz", - "integrity": "sha512-pGxr/TSP9Xiw2+9TUn3OWLdcuI4+PJozPsCYZVTGWJ96X6Pv7YX/rNy4emIDkaWaFZ7IWgWXUA725KhEINSf3Q==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-types/-/cli-types-18.0.0.tgz", + "integrity": "sha512-J84+4IRXl8WlVdoe1maTD5skYZZO9CbQ6LNXEHx1kaZcFmvPZKfjsaxuyQ+8BsSqZnM2izOw8dEWnAp/Zuwb0w==", "devOptional": true, "license": "MIT", "dependencies": { "joi": "^17.2.1" } }, - "node_modules/@react-native-community/cli/node_modules/@react-native-community/cli-tools": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-18.0.1.tgz", - "integrity": "sha512-WxWFXwfYhHR2eYiB4lkHZVC/PmIkRWeVHBQKmn0h1mecr3GrHYO4BzW1jpD5Xt6XZ9jojQ9wE5xrCqXjiMSAIQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@vscode/sudo-prompt": "^9.0.0", - "appdirsjs": "^1.2.4", - "chalk": "^4.1.2", - "execa": "^5.0.0", - "find-up": "^5.0.0", - "launch-editor": "^2.9.1", - "mime": "^2.4.1", - "ora": "^5.4.1", - "prompts": "^2.4.2", - "semver": "^7.5.2" - } - }, "node_modules/@react-native-community/cli/node_modules/semver": { "version": "7.7.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", @@ -3213,9 +3018,9 @@ } }, "node_modules/@react-native-documents/picker": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/@react-native-documents/picker/-/picker-11.0.4.tgz", - "integrity": "sha512-lbwcBwXMwZ5eTvNI6j/HqPjyB87moRCA8k7EoLCXF4KsLNt2jYDBXkUONX/WcMRMyQEaJPWB77W2zMCcRdX4jw==", + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@react-native-documents/picker/-/picker-11.0.3.tgz", + "integrity": "sha512-q+vQNT1NtZcFGwsDpTwMKNNcgOEq6foFDGlPQVt8H7KaEjCjC+wTGdXuVSe8JJr2uO9xZR6kJ7aRHReZ4XDRBw==", "license": "MIT", "peerDependencies": { "react": "*", @@ -3227,6 +3032,7 @@ "resolved": "https://registry.npmjs.org/@react-native-masked-view/masked-view/-/masked-view-0.3.2.tgz", "integrity": "sha512-XwuQoW7/GEgWRMovOQtX3A4PrXhyaZm0lVUiY8qJDvdngjLms9Cpdck6SmGAUNqQwcj2EadHC1HwL0bEyoa/SQ==", "license": "MIT", + "peer": true, "peerDependencies": { "react": ">=16", "react-native": ">=0.57" @@ -3657,6 +3463,7 @@ "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-7.1.26.tgz", "integrity": "sha512-RhKmeD0E2ejzKS6z8elAfdfwShpcdkYY8zJzvHYLq+wv183BBcElTeyMLcIX6wIn7QutXeI92Yi21t7aUWfqNQ==", "license": "MIT", + "peer": true, "dependencies": { "@react-navigation/core": "^7.13.7", "escape-string-regexp": "^4.0.0", @@ -3948,6 +3755,7 @@ "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -4281,6 +4089,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz", "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -4349,6 +4158,7 @@ "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "7.18.0", @@ -4383,6 +4193,7 @@ "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/types": "7.18.0", @@ -4614,6 +4425,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5286,6 +5098,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -6611,6 +6424,7 @@ "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -8809,6 +8623,7 @@ "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", @@ -11398,6 +11213,7 @@ "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin-prettier.js" }, @@ -11635,6 +11451,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz", "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -11699,6 +11516,7 @@ "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.79.0.tgz", "integrity": "sha512-fLG/zl/YF30TWTmp2bbo3flHSFGe4WTyVkb7/wJnMEC39jjXVSCxfDtvSUVavhCc03fA/RTkWWvlmg7NEJk7Vg==", "license": "MIT", + "peer": true, "dependencies": { "@jest/create-cache-key-function": "^29.7.0", "@react-native/assets-registry": "0.79.0", @@ -11780,13 +11598,12 @@ "license": "MIT" }, "node_modules/react-native-bouncy-checkbox": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/react-native-bouncy-checkbox/-/react-native-bouncy-checkbox-4.1.3.tgz", - "integrity": "sha512-duS0gN2FuLpAdEPuurWW3G+f9QhKCQTc9R51aQwPYTT6d01B2lZ/yzyzYbpPAv9SY142oieeUZLufPyjuOx3Ww==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/react-native-bouncy-checkbox/-/react-native-bouncy-checkbox-4.1.2.tgz", + "integrity": "sha512-hB7YwCGTNoMpTPOPiP+RWyQH35S6vxUbc7IGEW/Rqyp7GonEyhtqtthmxiphneRXnywMh8CZwND7OnvppJZscg==", "license": "MIT", "dependencies": { - "@freakycoder/react-native-bounceable": "^1.0.3", - "react-native-bouncy-checkbox": "^4.1.2" + "@freakycoder/react-native-bounceable": "^1.0.3" } }, "node_modules/react-native-date-picker": { @@ -11804,6 +11621,7 @@ "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.30.0.tgz", "integrity": "sha512-5YsnKHGa0X9C8lb5oCnKm0fLUPM6CRduvUUw2Bav4RIj/C3HcFh4RIUnF8wgG6JQWCL1//gRx4v+LVWgcIQdGA==", "license": "MIT", + "peer": true, "dependencies": { "@egjs/hammerjs": "^2.0.17", "hoist-non-react-statics": "^3.3.0", @@ -11865,6 +11683,7 @@ "resolved": "https://registry.npmjs.org/react-native-linear-gradient/-/react-native-linear-gradient-2.8.3.tgz", "integrity": "sha512-KflAXZcEg54PXkLyflaSZQ3PJp4uC4whM7nT/Uot9m0e/qxFV3p6uor1983D1YOBJbJN7rrWdqIjq0T42jOJyA==", "license": "MIT", + "peer": true, "peerDependencies": { "react": "*", "react-native": "*" @@ -11938,6 +11757,7 @@ "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.6.2.tgz", "integrity": "sha512-4XGqMNj5qjUTYywJqpdWZ9IG8jgkS3h06sfVjfw5yZQZfWnRFXczi0GnYyFyCc2EBps/qFmoCH8fez//WumdVg==", "license": "MIT", + "peer": true, "peerDependencies": { "react": "*", "react-native": "*" @@ -11948,6 +11768,7 @@ "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-4.12.0.tgz", "integrity": "sha512-T2KL6RcDSYDRZswh9glRe600Hvaeq240U21eaqv0uxCNmJz05UeFc4YGQgbFPI8XsakPKx3HjNonItxElFy+QA==", "license": "MIT", + "peer": true, "dependencies": { "react-freeze": "^1.0.0", "react-native-is-edge-to-edge": "^1.1.7", @@ -11975,6 +11796,7 @@ "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.15.1.tgz", "integrity": "sha512-ZUD1xwc3Hwo4cOmOLumjJVoc7lEf9oQFlHnLmgccLC19fNm6LVEdtB+Cnip6gEi0PG3wfvVzskViEtrySQP8Fw==", "license": "MIT", + "peer": true, "dependencies": { "css-select": "^5.1.0", "css-tree": "^1.1.3", @@ -12082,6 +11904,7 @@ "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", + "peer": true, "dependencies": { "@types/use-sync-external-store": "^0.0.6", "use-sync-external-store": "^1.4.0" @@ -12142,7 +11965,8 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/redux-persist": { "version": "6.0.0", @@ -13619,6 +13443,7 @@ "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", "devOptional": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/src/Axios/Axios.ts b/src/Axios/Axios.ts index 7420661..1bdc8cd 100644 --- a/src/Axios/Axios.ts +++ b/src/Axios/Axios.ts @@ -20,7 +20,7 @@ export const apiCall = async ( data, params, // withCredentials: true, - baseURL: Variable.Main_Base, + // baseURL: Variable.Main_Base, headers: { Authentication: `Bearer ${token?.token}`, 'Content-Type': contentType || 'application/json', @@ -31,7 +31,6 @@ export const apiCall = async ( } catch (error: any) { const errorMessage = error?.response?.data?.error; { error?.response?.data?.error && showErrorAlert(error?.response?.data?.error || '') } - console.log(errorMessage, '---------------url error'); if (error?.response?.status === 401) { store.dispatch(setToken({})); diff --git a/src/Component/Counter/CountdownTimer.tsx b/src/Component/Counter/CountdownTimer.tsx index e7781b2..62eef69 100644 --- a/src/Component/Counter/CountdownTimer.tsx +++ b/src/Component/Counter/CountdownTimer.tsx @@ -2,12 +2,15 @@ import React, { useEffect, useState, useCallback } from 'react'; import { View, Text, StyleSheet } from 'react-native'; import colors from '../../Constant/Color'; import moment from 'moment'; +import LottieView from 'lottie-react-native'; interface CountdownTimerProps { - endDate: string; // Expected format: "DD-MM-YYYY HH:mm:ss" + endDate: string; + myStyle?: any + size?: number // Expected format: "DD-MM-YYYY HH:mm:ss" } -const CountdownTimer: React.FC = React.memo(({ endDate }) => { +const CountdownTimer: React.FC = React.memo(({ endDate, myStyle = {}, size = 20 }) => { const calculateTimeLeft = useCallback(() => { if (!endDate) return null; @@ -43,8 +46,14 @@ const CountdownTimer: React.FC = React.memo(({ endDate }) = return ( - - {timeLeft.days}d {timeLeft.hours}h {timeLeft.minutes}m {timeLeft.seconds}s + + + {timeLeft.days}D {timeLeft.hours}H {timeLeft.minutes}M {timeLeft.seconds}S ); @@ -58,15 +67,18 @@ const styles = StyleSheet.create({ paddingVertical: 5, paddingHorizontal: 10, borderWidth: 1, - borderColor: colors.primary, + borderColor: colors.black, borderRadius: 25, + flexDirection: 'row', alignItems: 'center', justifyContent: 'center', + }, timerText: { fontSize: 14, fontWeight: 'bold', - color: colors.primary, + color: colors.black, + paddingLeft: 5 }, expiredText: { fontSize: 12, diff --git a/src/Component/Header/InsideHeader.tsx b/src/Component/Header/InsideHeader.tsx index 3530722..5314581 100644 --- a/src/Component/Header/InsideHeader.tsx +++ b/src/Component/Header/InsideHeader.tsx @@ -50,7 +50,7 @@ const InsideHeader: React.FC = ({ title, showArrow = false }) => { {title} - { navigation.navigate(NavigationString.Emd) }}> + { navigation.navigate(NavigationString.Home) }}> void; + onClose: () => void; +}; + +const ConfirmDialog: React.FC = ({ + visible, + title = 'Confirm', + message, + confirmText = 'Confirm', + cancelText = 'Cancel', + onConfirm, + onClose, +}) => { + return ( + + {/* Overlay (click to close) */} + + {/* Stop propagation */} + + {/* Title */} + {title} + + {/* Message */} + {message} + + {/* Actions */} + + + {cancelText} + + + { + onConfirm(); + onClose(); + }} + > + {confirmText} + + + + + + ); +}; + +export default ConfirmDialog; + +const styles = StyleSheet.create({ + overlay: { + flex: 1, + backgroundColor: 'rgba(0,0,0,0.5)', + justifyContent: 'center', + alignItems: 'center', + }, + container: { + width: '85%', + backgroundColor: '#fff', + borderRadius: 12, + padding: 20, + elevation: 5, + }, + title: { + fontSize: 18, + fontWeight: '600', + marginBottom: 8, + textAlign: 'center', + }, + message: { + fontSize: 15, + color: '#444', + textAlign: 'center', + marginBottom: 20, + }, + actions: { + flexDirection: 'row', + justifyContent: 'flex-end', + }, + cancelBtn: { + paddingVertical: 10, + paddingHorizontal: 16, + marginRight: 10, + }, + cancelText: { + fontSize: 14, + color: '#666', + }, + confirmBtn: { + backgroundColor: '#1f4b6dff', + paddingVertical: 10, + paddingHorizontal: 18, + borderRadius: 6, + }, + confirmText: { + color: '#fff', + fontSize: 14, + fontWeight: '500', + }, +}); diff --git a/src/Constant/NavigationString.tsx b/src/Constant/NavigationString.tsx index b6414a3..6370fc7 100644 --- a/src/Constant/NavigationString.tsx +++ b/src/Constant/NavigationString.tsx @@ -12,6 +12,8 @@ const NavigationString = { Emd: 'Emd', StartBidding: 'StartBidding', PurchaseAuctionList:'PurchaseAuctionList', + StartReverseBidding:'StartReverseBidding' + PurchaseAuctionList:'PurchaseAuctionList', // tender PurchaseTenderList:'PurchaseTenderList', ProceedToPurTender:'ProceedToPurTender', diff --git a/src/Navigation/MainStack.jsx b/src/Navigation/MainStack.jsx index f50b2a8..1b8025b 100644 --- a/src/Navigation/MainStack.jsx +++ b/src/Navigation/MainStack.jsx @@ -40,6 +40,7 @@ export default function MainStack() { + ); diff --git a/src/Screens/Auction/Auction.tsx b/src/Screens/Auction/Auction.tsx index 462002a..11efd31 100644 --- a/src/Screens/Auction/Auction.tsx +++ b/src/Screens/Auction/Auction.tsx @@ -1,17 +1,7 @@ import React, { useState, useRef } from 'react'; -import { - View, - Text, - StyleSheet, - TouchableOpacity, - Animated, - Dimensions, -} from 'react-native'; +import { View, Text, StyleSheet, TouchableOpacity, Animated, Dimensions } from 'react-native'; import { InsideHeader } from '../../Component/Index'; -import { - useFetchLiveAuction, - useFetchPurchaseAuction, -} from '../../Services/BBPS/Hooks'; +import { useFetchLiveAuction, useFetchPurchaseAuction } from '../../Services/BBPS/Hooks'; import colors from '../../Constant/Color'; import LiveAuction from './LiveAuction'; import PurchaseAuction from './PurchaseAuction'; @@ -20,7 +10,6 @@ import { useNavigation } from '@react-navigation/native'; import NavigationString from '../../Constant/NavigationString'; import FontsFamily from '../../Constant/FontsFamily'; import { useSelector } from 'react-redux'; -const { width } = Dimensions.get('screen') const TAB_WIDTH = 140; const TAB_HEIGHT = 44; @@ -30,7 +19,6 @@ const Auction = () => { const { data: purchaseAuctionData = {} } = useFetchPurchaseAuction(); const SelectedPurchaseList = useSelector((state: any) => state.selectPurchaseAuction); - const liveCount = Array.isArray(liveAuctionData?.result) ? liveAuctionData?.pages[0]?.totalCount : 0; @@ -101,7 +89,7 @@ const Auction = () => { {/* Cart */} - {SelectedPurchaseList.length && + {SelectedPurchaseList.length && {SelectedPurchaseList.length} } { Navigation.navigate(NavigationString.PurchaseList) }}> diff --git a/src/Screens/Auction/LiveAuction.tsx b/src/Screens/Auction/LiveAuction.tsx index 2d3f641..532a1e8 100644 --- a/src/Screens/Auction/LiveAuction.tsx +++ b/src/Screens/Auction/LiveAuction.tsx @@ -9,6 +9,9 @@ import { Skelton } from '../../Component/Index'; import colors from '../../Constant/Color'; import { useDispatch, useSelector } from 'react-redux'; import { selectPurchaseAuctionSlice, togglePurchaseAuction } from '../../Redux/Slices/selectPurchaseAuction'; +import { apiCall } from '../../Axios/Axios'; +import { GET_MY_AUCTION, LIVE_AUCTION } from '../../Services/BBPS/ApiUrls'; +import moment from 'moment'; const LiveAuction = () => { const navigation: any = useNavigation(); @@ -16,6 +19,7 @@ const LiveAuction = () => { const SelectedPurchaseList = useSelector((state: any) => state.selectPurchaseAuction); const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading, isRefetching, refetch }: any = useFetchLiveAuction(); const [showRefreshBanner, setShowRefreshBanner] = useState(false); + const [allBoolean, setAllBoolean] = useState({ liveAuctionData: [] }) useEffect(() => { if (isRefetching) { @@ -64,6 +68,39 @@ const LiveAuction = () => { [SelectedPurchaseList] ); + const getMyAuction = async () => { + try { + + const res = await apiCall('get', `${GET_MY_AUCTION}`,); + + if (res?.statusCode === 200) { + const purchasedIds = new Set( + res.data.map((item: any) => item.auctionId), + ); + + const filteredLive = data?.result.map((item: any) => ({ + ...item, + active: !purchasedIds.has(item.auctionId), // false if match, true otherwise + })); + + setAllBoolean(prev => ({ + ...prev, + liveAuctionData: filteredLive + })); + } + } catch (error) { + console.error('getMyAuction error', error); + } finally { + setAllBoolean(prev => ({ ...prev, isLoading: false })); + } + }; + + useEffect(() => { + if (data?.result?.length > 0) { + getMyAuction() + } + }, [data]) + if (isLoading) { return ; } @@ -110,8 +147,8 @@ const LiveAuction = () => { )} String(item.auctionId)} + data={allBoolean.liveAuctionData ?? []} + keyExtractor={(item: any) => String(item.auctionNumber)} renderItem={renderItem} showsVerticalScrollIndicator={false} contentContainerStyle={{ paddingBottom: 50, paddingTop: 10 }} diff --git a/src/Screens/Auction/LiveAuctionTile.tsx b/src/Screens/Auction/LiveAuctionTile.tsx index 54f5f08..e243a91 100644 --- a/src/Screens/Auction/LiveAuctionTile.tsx +++ b/src/Screens/Auction/LiveAuctionTile.tsx @@ -22,89 +22,93 @@ const LiveAuctionTile: React.FC = ({ return ( {/* Status Tag */} - - setShowDetail(true)} - > - {/* Header */} - - - - #{auctionNumber} - - ₹{auctionFees} - - - {/* Work Title */} - - {auctionOfWork ?? 'General Auction Work'} - - - {/* Info Grid */} - - - - - Start - {auctionDispatchDate ?? '-'} - - - - - - - Deadline - - {moment(purchaseEnd, 'DD-MM-YYYY HH:mm:ss').format('DD MMM, YY')} - - - - - - {/* Action Bar */} - - setShowDetail(true)}> - - Details - - - - + + - {purchaseEnded ? 'Expired' : isPurchased ? 'Remove' : 'Add to Cart'} - - {!purchaseEnded && ( - - )} - - + {/* Header */} + + setShowDetail(true)}> + + #{auctionNumber} + + ₹{auctionFees} + + + {/* Work Title */} + + {auctionOfWork ?? 'General Auction Work'} + + + {/* Info Grid */} + + + + + Start + {auctionDispatchDate ?? '-'} + + + + + + + Deadline + + {moment(purchaseEnd, 'DD-MM-YYYY HH:mm:ss').format('DD MMM, YY')} + + + + + + {/* Action Bar */} + + setShowDetail(true)}> + + Details + + + + + {purchaseEnded ? 'Expired' : !data.active ? 'Purchased' : isPurchased ? 'Remove' : 'Add to Cart'} + + {!purchaseEnded && ( + + )} + + + + {/* Auction Detail Modal */} + + + : setShowDetail(false)} /> + } - {/* Auction Detail Modal */} - setShowDetail(false)} /> - ); }; diff --git a/src/Screens/Auction/Modal/AuctionDetail.tsx b/src/Screens/Auction/Modal/AuctionDetail.tsx index aa8c28c..4802cb4 100644 --- a/src/Screens/Auction/Modal/AuctionDetail.tsx +++ b/src/Screens/Auction/Modal/AuctionDetail.tsx @@ -1,30 +1,8 @@ import React, { memo, useState } from 'react'; -import { - View, - Text, - StyleSheet, - TouchableOpacity, - ScrollView, - SafeAreaView, - Platform, - StatusBar, -} from 'react-native'; +import { View, Text, StyleSheet, TouchableOpacity, ScrollView, SafeAreaView, Platform, StatusBar } from 'react-native'; import Modal from 'react-native-modal'; import moment from 'moment'; -import { - X, - Hash, - Briefcase, - Calendar, - CreditCard, - FileText, - Download, - Eye, - Layers, - ArrowLeft, - Info, - Clock -} from 'lucide-react-native'; +import { Briefcase, Calendar, FileText, Download, Eye, Layers, ArrowLeft, Clock } from 'lucide-react-native'; import colors from '../../../Constant/Color'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import AuctionItemDetail from './AuctionItemDetail'; @@ -69,13 +47,15 @@ const AuctionFullDetail: React.FC = ({ visible, onClose, data }) => { - + {/* Full Header */} @@ -191,23 +171,25 @@ const AuctionFullDetail: React.FC = ({ visible, onClose, data }) => { - { setAllBoolean((prev: any) => ({ ...prev, showItemDetail: false })) }} visible={allBoolean.showItemDetail} /> - + + { setAllBoolean((prev: any) => ({ ...prev, showItemDetail: false })) }} visible={allBoolean.showItemDetail} /> + ); }; diff --git a/src/Screens/Auction/Modal/AuctionItemDetail.tsx b/src/Screens/Auction/Modal/AuctionItemDetail.tsx index ec8d290..befda66 100644 --- a/src/Screens/Auction/Modal/AuctionItemDetail.tsx +++ b/src/Screens/Auction/Modal/AuctionItemDetail.tsx @@ -79,13 +79,16 @@ const AuctionItemDetail: React.FC = ({ visible, onClose, data = ITEM_DUMM - + {/* Navbar */} @@ -171,7 +174,7 @@ const AuctionItemDetail: React.FC = ({ visible, onClose, data = ITEM_DUMM - + ); }; diff --git a/src/Screens/Auction/PurchaseAuction.tsx b/src/Screens/Auction/PurchaseAuction.tsx index 9a5f139..194651d 100644 --- a/src/Screens/Auction/PurchaseAuction.tsx +++ b/src/Screens/Auction/PurchaseAuction.tsx @@ -11,6 +11,7 @@ import { SearchInput } from '../../Component/Serach/SeacrhInput'; import { Skelton } from '../../Component/Index'; import { allBooleanProps } from './types/types'; import FilterModal from './Modal/FilterModal'; +import NavigationString from '../../Constant/NavigationString'; const PurchaseAuction = () => { @@ -51,11 +52,10 @@ const PurchaseAuction = () => { { - navigation.navigate('AuctionDetail', { item, onAddToPurchase: () => { }, routeFrom: 'PurchasedAuction' }); }} onStartBidding={() => { Dispatch(setAuction(item)) - // navigation.navigate(NavigationString, { data: item }) + navigation.navigate(NavigationString.Emd) }} buttonEnable={isAuctionActive(item)} isAuctionEnd={isAuctionEnd(item)} diff --git a/src/Screens/Auction/PurchaseAuctionList.tsx b/src/Screens/Auction/PurchaseAuctionList.tsx index c64be80..9b50757 100644 --- a/src/Screens/Auction/PurchaseAuctionList.tsx +++ b/src/Screens/Auction/PurchaseAuctionList.tsx @@ -3,8 +3,12 @@ import { View, Text, FlatList, StyleSheet, TouchableOpacity, Alert } from 'react import { InsideHeader, Loader } from '../../Component/Index'; import colors from '../../Constant/Color'; import { CreditCard, Calendar, User, DollarSign, ArrowRight } from 'lucide-react-native'; -import { useSelector } from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; import { useOfflineAuctionPurchase } from '../../Services/BBPS/Hooks'; +import { showSuccessAlert } from '../../Constant/ShowDailog'; +import { clearPurchaseAuction } from '../../Redux/Slices/selectPurchaseAuction'; +import { CommonActions, useNavigation } from '@react-navigation/native'; +import NavigationString from '../../Constant/NavigationString'; const dummyAuctionList = [ { @@ -46,6 +50,8 @@ const dummyAuctionList = [ ]; const PurchaseAuctionList = () => { + const Navigation = useNavigation() + const Dispatch = useDispatch() const [loading, setLoading] = useState(false); const [list, setList] = useState(dummyAuctionList); const SelectedPurchaseList = useSelector((state: any) => state.selectPurchaseAuction); @@ -81,7 +87,16 @@ const PurchaseAuctionList = () => { try { mutate(body, { onSuccess: (res) => { - console.log(res, '---------------------purchsase response'); + if (res.statusCode == 200) { + showSuccessAlert(res.message) + Dispatch(clearPurchaseAuction()) + Navigation.dispatch( + CommonActions.reset({ + index: 0, + routes: [{ name: NavigationString.Home }], + }) + ); + } }, onError: (error) => { console.log(error, "================purchse Error"); @@ -165,16 +180,16 @@ const PurchaseAuctionList = () => { style={[styles.button, { marginLeft: 8 }]} onPress={() => handlePurchase('offline')} > - Purchase Offline - + { + isPending ? : <> + Purchase Offline + + + } + - {loading && ( - - - - )} ); }; diff --git a/src/Screens/Auction/PurchaseAuctionTile.tsx b/src/Screens/Auction/PurchaseAuctionTile.tsx index 3bc8c4c..9b183e4 100644 --- a/src/Screens/Auction/PurchaseAuctionTile.tsx +++ b/src/Screens/Auction/PurchaseAuctionTile.tsx @@ -1,28 +1,13 @@ import React from 'react'; -import { - View, - Text, - StyleSheet, - TouchableOpacity, - Platform, -} from 'react-native'; -import Animated, { - FadeInUp, - useAnimatedStyle, - useSharedValue, - withTiming, -} from 'react-native-reanimated'; +import { View, Text, StyleSheet, TouchableOpacity, Platform } from 'react-native'; +import Animated, { FadeInUp, useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated'; import moment from 'moment'; import CountdownTimer from '../../Component/Counter/CountdownTimer'; import colors from '../../Constant/Color'; +import AuctionDetail from './Modal/AuctionDetail'; -const PurchaseAuctionTile = ({ - item, - onPressDetails, - onStartBidding, - buttonEnable, - isAuctionEnd, -}: any) => { +const PurchaseAuctionTile = ({ item, onPressDetails, onStartBidding, buttonEnable, isAuctionEnd }: any) => { + const [showDetail, setShowDetail] = React.useState(false); const scale = useSharedValue(1); const elevation = useSharedValue(8); @@ -43,232 +28,237 @@ const PurchaseAuctionTile = ({ elevation.value = withTiming(8, { duration: 160 }); }; - const statusColor = isAuctionEnd - ? '#EF4444' - : buttonEnable - ? colors.primary - : '#94A3B8'; + const statusColor = isAuctionEnd ? '#EF4444' : buttonEnable ? colors.primary : '#94A3B8'; - const lightStatusBg = isAuctionEnd - ? '#FEF2F2' - : buttonEnable - ? '#EFF6FF' - : '#F8FAFC'; + const lightStatusBg = isAuctionEnd ? '#FEF2F2' : buttonEnable ? '#EFF6FF' : '#F8FAFC'; + console.log(item?.keyDates?.auctionBidding?.endDateTime, 'kk'); return ( - - + {!showDetail ? - + setShowDetail(true)} + onPressIn={handlePressIn} + onPressOut={handlePressOut} + style={styles.cardInternal} + > + - - {/* Header */} - - - - - - {isAuctionEnd ? 'ENDED' : buttonEnable ? 'LIVE' : 'PENDING'} + + {/* Header */} + + + + + + {isAuctionEnd ? 'ENDED' : buttonEnable ? 'LIVE' : 'PENDING'} + + + {item.auctionNumber} + + + + + ₹{item.auctionFees?.toLocaleString()} + Auction Fee - {item.auctionNumber} - - - ₹{item.auctionFees?.toLocaleString()} + {/* Date */} + + + Bidding Start: + {moment( + item?.keyDates?.auctionBidding?.startDateTime?.replace(' kk', ''), + 'DD-MM-YYYY HH:mm:ss' + ).format('DD MMM YYYY, hh:mm A')} - Auction Fee - - - - {/* Date */} - - - Bidding Ends: - {moment(item?.keyDates?.auctionBidding?.endDateTime).format( - 'DD MMM, hh:mm A' - )} - - - - {/* Footer */} - - - Remaining Time - {buttonEnable && !isAuctionEnd ? ( - - ) : ( - --:--:-- - )} - - - - - {isAuctionEnd - ? 'Bidding Closed' - : !buttonEnable - ? 'Payment Required' - : 'Proceed to Start Bidding'} + + Bidding Ends: + {moment( + item?.keyDates?.auctionBidding?.endDateTime?.replace(' kk', ''), + 'DD-MM-YYYY HH:mm:ss' + ).format('DD MMM YYYY, hh:mm A')} - + + + {/* Footer */} + + + Remaining Time + {buttonEnable && !isAuctionEnd ? ( + + ) : ( + --:--:-- + )} + + + + + {isAuctionEnd + ? 'Bidding Closed' + : !buttonEnable + ? 'Pending Bid' + : 'Proceed to Start Bidding'} + + + - - - + + : + setShowDetail(false)} /> + } + ); }; export default PurchaseAuctionTile; const styles = StyleSheet.create({ - shadowContainer: { - marginHorizontal: 5, - marginTop: 14, - marginBottom: 6, - borderRadius: 16, - backgroundColor: '#fff', - elevation: 8, - }, - cardInternal: { - borderRadius: 16, - overflow: 'hidden', - flexDirection: 'row', - backgroundColor: '#fff', - }, - statusAccent: { - width: 5, - height: '100%', - }, - mainInfo: { - flex: 1, - padding: 16, - }, - headerRow: { - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'flex-start', - marginBottom: 12, - }, - statusBadge: { - flexDirection: 'row', - alignItems: 'center', - paddingHorizontal: 8, - paddingVertical: 3, - borderRadius: 6, - marginBottom: 6, - alignSelf: 'flex-start', - }, - statusDot: { - width: 6, - height: 6, - borderRadius: 3, - marginRight: 5, - }, - statusText: { - fontSize: 10, - fontWeight: '800', - letterSpacing: 0.5, - }, - title: { - fontWeight: '800', - fontSize: 16, - color: '#1E293B', - }, - amountContainer: { - alignItems: 'flex-end', - }, - amount: { - fontWeight: '900', - fontSize: 18, - color: '#0F172A', - }, - feeLabel: { - fontSize: 10, - color: '#64748B', - fontWeight: '500', - }, - dateRow: { - backgroundColor: '#F8FAFC', - paddingHorizontal: 10, - paddingVertical: 8, - borderRadius: 10, - marginBottom: 16, - borderWidth: 1, - borderColor: '#F1F5F9', - }, - dateText: { - fontSize: 12, - color: '#334155', - fontWeight: '600', - }, - dateLabel: { - fontWeight: '400', - color: '#64748B', - }, - footer: { - borderTopWidth: 1, - borderTopColor: '#F1F5F9', - paddingTop: 12, - }, - footerTop: { - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - marginBottom: 12, - }, - footerLabel: { - fontSize: 11, - fontWeight: '600', - color: '#94A3B8', - textTransform: 'uppercase', - }, - endedText: { - fontSize: 13, - fontWeight: '700', - color: '#CBD5E1', - }, - actionButton: { - width: '100%', - height: 48, - borderRadius: 12, - justifyContent: 'center', - alignItems: 'center', - ...Platform.select({ - ios: { - shadowColor: '#000', - shadowOffset: { width: 0, height: 2 }, - shadowOpacity: 0.1, - shadowRadius: 4, - }, - }), - }, - disabledButton: { - backgroundColor: '#E2E8F0', - }, - addText: { - color: '#fff', - fontSize: 14, - fontWeight: '800', - letterSpacing: 0.2, - }, + shadowContainer: { + marginHorizontal: 5, + marginTop: 14, + marginBottom: 6, + borderRadius: 16, + backgroundColor: '#fff', + elevation: 8, + }, + cardInternal: { + borderRadius: 16, + overflow: 'hidden', + flexDirection: 'row', + backgroundColor: '#fff', + }, + statusAccent: { + width: 5, + height: '100%', + }, + mainInfo: { + flex: 1, + padding: 16, + }, + headerRow: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'flex-start', + marginBottom: 12, + }, + statusBadge: { + flexDirection: 'row', + alignItems: 'center', + paddingHorizontal: 8, + paddingVertical: 3, + borderRadius: 6, + marginBottom: 6, + alignSelf: 'flex-start', + }, + statusDot: { + width: 6, + height: 6, + borderRadius: 3, + marginRight: 5, + }, + statusText: { + fontSize: 10, + fontWeight: '800', + letterSpacing: 0.5, + }, + title: { + fontWeight: '800', + fontSize: 16, + color: '#1E293B', + }, + amountContainer: { + alignItems: 'flex-end', + }, + amount: { + fontWeight: '900', + fontSize: 18, + color: '#0F172A', + }, + feeLabel: { + fontSize: 10, + color: '#64748B', + fontWeight: '500', + }, + dateRow: { + backgroundColor: '#F8FAFC', + paddingHorizontal: 10, + paddingVertical: 8, + borderRadius: 10, + marginBottom: 16, + borderWidth: 1, + borderColor: '#F1F5F9', + }, + dateText: { + fontSize: 12, + color: '#334155', + fontWeight: '600', + }, + dateLabel: { + fontWeight: '400', + color: '#64748B', + }, + footer: { + borderTopWidth: 1, + borderTopColor: '#F1F5F9', + paddingTop: 12, + }, + footerTop: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + marginBottom: 12, + }, + footerLabel: { + fontSize: 11, + fontWeight: '600', + color: '#94A3B8', + textTransform: 'uppercase', + }, + endedText: { + fontSize: 13, + fontWeight: '700', + color: '#CBD5E1', + }, + actionButton: { + width: '100%', + height: 48, + borderRadius: 12, + justifyContent: 'center', + alignItems: 'center', + ...Platform.select({ + ios: { + shadowColor: '#000', + shadowOffset: { width: 0, height: 2 }, + shadowOpacity: 0.1, + shadowRadius: 4, + }, + }), + }, + disabledButton: { + backgroundColor: '#E2E8F0', + }, + addText: { + color: '#fff', + fontSize: 14, + fontWeight: '800', + letterSpacing: 0.2, + }, }); diff --git a/src/Screens/Bidding/Component/BiddingCard.tsx b/src/Screens/Bidding/Component/BiddingCard.tsx new file mode 100644 index 0000000..853e785 --- /dev/null +++ b/src/Screens/Bidding/Component/BiddingCard.tsx @@ -0,0 +1,218 @@ +import React, { memo, useCallback, useRef } from 'react'; +import { View, Text, TouchableOpacity, StyleSheet, Platform } from 'react-native'; +import Animated, { FadeInUp, Layout, interpolate, useAnimatedStyle, useSharedValue, withSpring } from 'react-native-reanimated'; +import colors from '../../../Constant/Color'; +import AuctionItemDetail from '../../Auction/Modal/AuctionItemDetail'; +import MainStyle from '../../../Styles/MainStyle'; + +const BiddingCard = ({ item, bidValue, onIncrease, onDecrease, onPlaceBid, SelectedAuction }: any) => { + const [showDetail, setShowDetail] = React.useState(false); + const isMin = bidValue <= item.bidAmount; + + // 🔒 Persist expand state safely + const expandedRef = useRef(false); + const animation = useSharedValue(0); + + const toggleExpand = useCallback(() => { + expandedRef.current = !expandedRef.current; + animation.value = withSpring(expandedRef.current ? 1 : 0, { + damping: 15, + stiffness: 140, + }); + }, []); + + const bodyStyle = useAnimatedStyle(() => ({ + height: interpolate(animation.value, [0, 1], [0, 190]), + opacity: interpolate(animation.value, [0, 0.5, 1], [0, 0, 1]), + marginTop: interpolate(animation.value, [0, 1], [0, 15]), + })); + + const arrowStyle = useAnimatedStyle(() => ({ + transform: [ + { + rotate: `${interpolate(animation.value, [0, 1], [0, 180])}deg`, + }, + ], + })); + + return ( + + { + !showDetail ? + {/* HEADER */} + { setShowDetail(true) }} + style={styles.cardHeader} + > + + {item.productName} + {/* auctionStartValueFigure */} + + Initial Amt : {item?.auctionStartValueFigure} + + + + + + + + {item.me ? 'LEADING' : 'LIVE'} + + + + + ▼ + + + + {SelectedAuction?.auctionNumber} + + + + + + {/* PRICE INFO */} + + + Current Bid + ₹{item?.bidAmount} + + + + Increment + + +₹{item.bidVariationValue} + + + + + {/* COLLAPSIBLE BODY */} + + + + Set Your Bid + + + + − + + + + ₹ + {bidValue} + + + + + + + + + + Confirm Bid + + + + : + { setShowDetail(false) }} visible={showDetail} /> + } + + + ) +}; + +export default memo(BiddingCard); +const styles = StyleSheet.create({ + card: { + backgroundColor: '#FFF', + borderRadius: 24, + padding: 20, + marginBottom: 16, + borderWidth: 1, + borderColor: '#E2E8F0', + overflow: 'hidden', + ...Platform.select({ + ios: { + shadowColor: '#000', + shadowOpacity: 0.05, + shadowRadius: 10, + }, + android: { elevation: 2 }, + }), + }, + leadingCard: { + borderColor: '#22C55E', + borderWidth: 2, + backgroundColor: '#F0FDF4', + }, + cardHeader: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'flex-start', + }, + headerRight: { flexDirection: 'column', alignItems: 'center', gap: 8 }, + productName: { fontSize: 18, fontWeight: 'bold', color: '#1E293B' }, + itemIdText: { fontSize: 12, color: '#64748B', marginTop: 2 }, + badge: { paddingHorizontal: 10, paddingVertical: 4, borderRadius: 8 }, + liveBadge: { backgroundColor: '#FEE2E2' }, + meBadge: { backgroundColor: '#BBF7D0' }, + badgeText: { fontSize: 10, fontWeight: '900' }, + liveText: { color: '#EF4444' }, + meText: { color: '#15803D' }, + arrow: { fontSize: 10, color: '#94A3B8' }, + priceRow: { flexDirection: 'row', justifyContent: 'space-between', marginTop: 20 }, + label: { + fontSize: 11, + color: '#94A3B8', + textTransform: 'uppercase', + fontWeight: '600', + }, + mainPrice: { fontSize: 22, fontWeight: '900', color: '#0F172A' }, + incrementText: { fontSize: 16, fontWeight: '700', color: '#3B82F6' }, + collapsibleContainer: { overflow: 'hidden' }, + divider: { height: 1, backgroundColor: '#E2E8F0', marginVertical: 10 }, + bidLabel: { fontSize: 13, fontWeight: '600', color: '#475569', marginBottom: 10 }, + stepperContainer: { flexDirection: 'row', gap: 12, marginBottom: 20 }, + stepBtn: { + width: 45, + height: 45, + backgroundColor: colors.primary, + borderRadius: 12, + justifyContent: 'center', + alignItems: 'center', + }, + disabledBtn: { backgroundColor: '#CBD5E1' }, + stepText: { color: '#FFF', fontSize: 20, fontWeight: 'bold' }, + inputBox: { + flex: 1, + height: 45, + backgroundColor: '#F1F5F9', + borderRadius: 12, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + }, + currency: { fontSize: 16, fontWeight: 'bold', color: '#64748B', marginRight: 4 }, + bidValueText: { fontSize: 18, fontWeight: '800', color: '#0F172A' }, + submitBtn: { + height: 50, + backgroundColor: colors.primary, + borderRadius: 15, + justifyContent: 'center', + alignItems: 'center', + }, + submitBtnText: { color: '#FFF', fontSize: 16, fontWeight: 'bold' }, +}); diff --git a/src/Screens/Bidding/Component/ReverseBiddingCard.tsx b/src/Screens/Bidding/Component/ReverseBiddingCard.tsx new file mode 100644 index 0000000..ee484ae --- /dev/null +++ b/src/Screens/Bidding/Component/ReverseBiddingCard.tsx @@ -0,0 +1,370 @@ +import React, { memo, useCallback, useRef, useState } from 'react'; +import { View, Text, TouchableOpacity, StyleSheet, Platform, TextInput } from 'react-native'; +import Animated, { FadeInUp, Layout, interpolate, useAnimatedStyle, useSharedValue, withSpring } from 'react-native-reanimated'; +import colors from '../../../Constant/Color'; +import AuctionItemDetail from '../../Auction/Modal/AuctionItemDetail'; +import MainStyle from '../../../Styles/MainStyle'; +import axios, { all } from 'axios'; +import Variables from '../../../Constant/Variable'; +import { useSelector } from 'react-redux'; +import { showErrorAlert, showSuccessAlert } from '../../../Constant/ShowDailog'; +import { Loader } from '../../../Component/Index'; + +const ReverseBiddingCard = ({ item, bidValue, onIncrease, onDecrease, onPlaceBid, SelectedAuction, allBoolean, setAllBoolean }: any) => { + const Token = useSelector((state: any) => state.token.token) + const [allState, setAllState] = useState({ isLoading: false }) + const [showDetail, setShowDetail] = useState(false); + const [value, setValue] = useState(`${item.bidAmount}`); + const canDecrease = bidValue > item.emdAmount; + const canIncrease = bidValue < item.bidAmount; + // Animation Part Rohit Start + + const expandedRef = useRef(false); + const animation = useSharedValue(0); + + const toggleExpand = useCallback(() => { + expandedRef.current = !expandedRef.current; + animation.value = withSpring(expandedRef.current ? 1 : 0, { + damping: 15, + stiffness: 140, + }); + }, []); + + const bodyStyle = useAnimatedStyle(() => ({ + height: interpolate(animation.value, [0, 1], [0, 190]), + opacity: interpolate(animation.value, [0, 0.5, 1], [0, 0, 1]), + marginTop: interpolate(animation.value, [0, 1], [0, 15]), + })); + const bodyStyle2 = useAnimatedStyle(() => ({ + height: interpolate(animation.value, [0, 1], [0, 100]), + opacity: interpolate(animation.value, [0, 0.5, 1], [0, 0, 1]), + marginTop: interpolate(animation.value, [0, 1], [0, 15]), + })); + + const arrowStyle = useAnimatedStyle(() => ({ + transform: [ + { + rotate: `${interpolate(animation.value, [0, 1], [0, 180])}deg`, + }, + ], + })); + + // Animation Part Rohit End + + const MAX_VALUE = Number(item.auctionStartValue); + + const handleChange = (text: string) => { + let cleaned = text.replace(/[^0-9.]/g, ''); + if ((cleaned.match(/\./g) || []).length > 1) return; + if (cleaned === '') { + setValue(''); + return; + } + const numericValue = Number(cleaned); + if (numericValue < 0) return; + if (numericValue > MAX_VALUE) return; + setValue(cleaned); + }; + + const oneTimePlaceBid = async () => { + try { + setAllState((prev: any) => ({ ...prev, isLoading: true })) + const payload = { + itemId: item.id, + bidAmount: Number(value), + auctionId: SelectedAuction.auctionId, + contractorId: Token.contractorId, + fullName: Token.fullName, + }; + + + const res = await axios.post( + `${Variables.socketUrl}bidding/placeBidForAuction`, + [payload], + { headers: { Authentication: `Bearer ${Token.token}` } } + ); + + if (res.data.statusCode === 200) { + showSuccessAlert(res.data.message); + } + setAllBoolean((prev: any) => ({ ...prev, reload: !prev.reload })) + } catch (error) { + if (axios.isAxiosError(error)) { + showErrorAlert(error.response?.data.message) + } else { + console.log('UNKNOWN ERROR:', error); + } + + } finally { + setAllState((prev: any) => ({ ...prev, isLoading: false })) + } + } + + return ( + + {!showDetail ? ( + + {/* HEADER */} + setShowDetail(true)} + style={styles.cardHeader} + > + + {item.productName} + + Initial Amt : ₹{item.auctionStartValue} + + + + + + + + {item.me ? 'LEADING' : 'LIVE'} + + + + + ▼ + + + + {SelectedAuction?.auctionNumber} + + + + + {/* PRICE INFO */} + + + Current Bid + ₹{item.bidAmount || item.auctionStartValue} + + + + Decrement + + -₹{item.emdAmount} + + + + + {/* COLLAPSIBLE BODY */} + {/* */} + + + + Set Your Bid + + + {/* DECREASE */} + {!allBoolean.oneTimeBid && + − + } + + {/* VALUE */} + {!allBoolean.oneTimeBid && + ₹ + {bidValue} + } + { + (allBoolean.oneTimeBid || allBoolean.rebid) && + ₹ + + + + } + + {/* INCREASE */} + {!allBoolean.oneTimeBid && + + + } + + + + { + allState.isLoading ? : Confirm Bid + } + + + {/* {(allBoolean.oneTimeBid && allBoolean.rebid) ? + + { + allState.isLoading ? : Confirm Bid + } + : + (allBoolean.oneTimeBid && !item.me) ? + { + allState.isLoading ? : Confirm Bid + } + : null + } */} + + + ) : ( + setShowDetail(false)} + visible={showDetail} + /> + )} + + ); +}; + +export default ReverseBiddingCard; + +const styles = StyleSheet.create({ + inputBox2: { + flexDirection: 'row', + alignItems: 'center', + backgroundColor: '#F1F5F9', + borderRadius: 12, + height: 45, + paddingHorizontal: 12, + width: '100%' + }, + currency2: { + fontSize: 16, + fontWeight: 'bold', + color: '#64748B', + marginRight: 4, + }, + input: { + flex: 1, + fontSize: 18, + fontWeight: '700', + color: '#0F172A', + width: '100%' + }, + card: { + backgroundColor: '#FFF', + borderRadius: 24, + padding: 20, + marginBottom: 16, + borderWidth: 1, + borderColor: '#E2E8F0', + overflow: 'hidden', + ...Platform.select({ + ios: { + shadowColor: '#000', + shadowOpacity: 0.05, + shadowRadius: 10, + }, + android: { elevation: 2 }, + }), + }, + leadingCard: { + borderColor: '#22C55E', + borderWidth: 2, + backgroundColor: '#F0FDF4', + }, + cardHeader: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'flex-start', + }, + headerRight: { flexDirection: 'column', alignItems: 'center', gap: 8 }, + productName: { fontSize: 18, fontWeight: 'bold', color: '#1E293B' }, + itemIdText: { fontSize: 12, color: '#64748B', marginTop: 2 }, + badge: { paddingHorizontal: 10, paddingVertical: 4, borderRadius: 8 }, + liveBadge: { backgroundColor: '#FEE2E2' }, + meBadge: { backgroundColor: '#BBF7D0' }, + badgeText: { fontSize: 10, fontWeight: '900' }, + liveText: { color: '#EF4444' }, + meText: { color: '#15803D' }, + arrow: { fontSize: 10, color: '#94A3B8' }, + priceRow: { flexDirection: 'row', justifyContent: 'space-between', marginTop: 20 }, + label: { + fontSize: 11, + color: '#94A3B8', + textTransform: 'uppercase', + fontWeight: '600', + }, + mainPrice: { fontSize: 22, fontWeight: '900', color: '#0F172A' }, + incrementText: { fontSize: 16, fontWeight: '700', color: '#3B82F6' }, + collapsibleContainer: { overflow: 'hidden' }, + divider: { height: 1, backgroundColor: '#E2E8F0', marginVertical: 10 }, + bidLabel: { fontSize: 13, fontWeight: '600', color: '#475569', marginBottom: 10 }, + stepperContainer: { flexDirection: 'row', gap: 12, marginBottom: 20 }, + stepBtn: { + width: 45, + height: 45, + backgroundColor: colors.primary, + borderRadius: 12, + justifyContent: 'center', + alignItems: 'center', + }, + disabledBtn: { backgroundColor: '#CBD5E1' }, + stepText: { color: '#FFF', fontSize: 20, fontWeight: 'bold' }, + inputBox: { + flex: 1, + height: 45, + backgroundColor: '#F1F5F9', + borderRadius: 12, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + }, + currency: { fontSize: 16, fontWeight: 'bold', color: '#64748B', marginRight: 4 }, + bidValueText: { fontSize: 18, fontWeight: '800', color: '#0F172A' }, + submitBtn: { + height: 50, + backgroundColor: colors.primary, + borderRadius: 15, + justifyContent: 'center', + alignItems: 'center', + }, + submitBtnText: { color: '#FFF', fontSize: 16, fontWeight: 'bold' }, +}); diff --git a/src/Screens/Bidding/Component/TemplateFormModal.tsx b/src/Screens/Bidding/Component/TemplateFormModal.tsx new file mode 100644 index 0000000..a4420d3 --- /dev/null +++ b/src/Screens/Bidding/Component/TemplateFormModal.tsx @@ -0,0 +1,416 @@ +import React, { useState } from 'react' +import { Modal, View, Text, StyleSheet, TextInput, TouchableOpacity, ScrollView } from 'react-native' +import { Formik } from 'formik' +import * as Yup from 'yup' +import { pick } from '@react-native-documents/picker' +import { useSelector } from 'react-redux' +import { apiCall } from '../../../Axios/Axios' +import { TECHNICAL_DOCUMENT_SUBMIT, TECHNICAL_VALUE_SUBMIT } from '../../../Services/BBPS/ApiUrls' +import { Props } from '../Type/BidType' +import colors from '../../../Constant/Color' +import { Loader } from '../../../Component/Index' +import { useNavigation } from '@react-navigation/native' +import NavigationString from '../../../Constant/NavigationString' + +const TemplateFormModal: React.FC = ({ visible, template, setAllBoolean }) => { + if (!template) return null + + const SelectedAuction = useSelector((state: any) => state.auction.auction) + const Navigation: any = useNavigation() + const [loading, setLoading] = useState(false) + const initialValues = template.labels.reduce((acc: any, label: any) => { + acc[label.labelName] = '' + return acc + }, {}) + + const validationSchema = Yup.object( + template.labels.reduce((acc: any, label: any) => { + if (label.mandatory) { + acc[label.labelName] = + label.labelType === '3' + ? Yup.mixed().required(`${label.labelName} is required`) + : Yup.string().required(`${label.labelName} is required`) + } + return acc + }, {}) + ) + + const pickFile = async (fieldName: string, setFieldValue: any) => { + try { + const result = await pick({ + type: ['application/pdf'], + allowMultiSelection: false, + }) + const file = result[0] + setFieldValue(fieldName, { + name: file.name ?? 'document.pdf', + uri: file.uri, + type: 'application/pdf', + size: file.size, + }) + } catch (e) { + console.log(e) + } + } + + const renderInput = ( + label: any, + value: any, + setFieldValue: any, + error?: string, + touched?: boolean + ) => { + const showError = touched && error + + if (label.labelType === '3') { + return ( + + + {label.labelName} + {label.mandatory && *} + + + + pickFile(label.labelName, setFieldValue) + } + > + + {value?.name || 'Upload PDF'} + + + + {showError && ( + {error} + )} + + ) + } + + return ( + + + {label.labelName} + {label.mandatory && *} + + + + setFieldValue(label.labelName, text) + } + keyboardType={ + label.labelType === '1' || label.labelType === '4' + ? 'numeric' + : 'default' + } + /> + + {showError && ( + {error} + )} + + ) + } + + const onClose = () => { + setAllBoolean((prev: any) => ({ + ...prev, + technicalDocModalVisible: false, + })) + } + + const onSubmit = async (payload: any) => { + try { + const jsonBody = { + auctiontId: SelectedAuction.auctionId, + technicalDocumentTemplateId: payload.templateNameId, + labelValues: [] as any[], + } + + const fileFormData = new FormData() + let hasFile = false + + Object.entries(payload.values).forEach( + ([labelName, labelValue]: any) => { + if (typeof labelValue === 'object' && labelValue?.uri) { + hasFile = true + fileFormData.append(labelName, { + uri: labelValue.uri, + name: labelValue.name, + type: labelValue.type, + } as any) + } else { + jsonBody.labelValues.push({ + labelName, + labelValue: String(labelValue), + }) + } + } + ) + + const rs1: any = await apiCall('post', TECHNICAL_VALUE_SUBMIT, jsonBody) + + + if (hasFile) { + fileFormData.append( + 'auctiontId', + String(SelectedAuction.auctionId) + ) + fileFormData.append( + 'technicalDocumentTemplateId', + String(payload.templateNameId) + ) + + const res2: any = await apiCall( + 'post', + TECHNICAL_DOCUMENT_SUBMIT, + fileFormData, + {}, + 'multipart/form-data' + ) + console.log(res2, '-------------res2'); + if (rs1.statusCode == 200 && res2.statusCode == 200) { + Navigation.navigate(NavigationString.StartBidding) + setAllBoolean((prev: any) => ({ ...prev, technicalDocModalVisible: false })) + + } + + } else { + if (rs1.statusCode == 200) { + Navigation.navigate(NavigationString.StartBidding) + setAllBoolean((prev: any) => ({ ...prev, technicalDocModalVisible: false })) + } + } + + } catch (e) { + console.log(e) + } finally { + setLoading(false) + } + } + + return ( + + + + + + Technical Documents + + Fill the form, Click save when you're done. + + + + + ✕ + + + + + + + Template + + + + {template.templateName} + + + { + setLoading(true) + onSubmit({ + templateNameId: template.templateNameId, + auctionIds: template.auctionIds, + values, + }) + }} + > + {({ handleSubmit, values, errors, touched, setFieldValue }) => ( + <> + {template.labels.map((label: any) => + renderInput( + label, + values[label.labelName], + setFieldValue, + // errors[label.labelName], + // touched[label.labelName] + ) + )} + + + handleSubmit()} + disabled={loading} + > + {loading ? ( + + ) : ( + + Submit + + )} + + + + )} + + + + + + + ) + +} + +export default TemplateFormModal + +const styles = StyleSheet.create({ + screen: { + flex: 1, + backgroundColor: '#F9FAFB', + }, + header: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + paddingHorizontal: 16, + paddingVertical: 14, + backgroundColor: '#FFFFFF', + borderBottomWidth: 1, + borderColor: '#E5E7EB', + }, + headerLeft: { + flex: 1, + }, + headerTitle: { + fontSize: 16, + fontWeight: '700', + color: '#111827', + }, + headerSubtitle: { + fontSize: 12, + color: '#6B7280', + marginTop: 2, + }, + closeBtn: { + padding: 6, + }, + closeText: { + fontSize: 18, + color: '#6B7280', + }, + content: { + paddingHorizontal: 16, + }, + card: { + backgroundColor: '#FFFFFF', + borderColor: '#E5E7EB', + paddingVertical: 20 + }, + templateHeading: { + fontSize: 18, + fontWeight: '700', + textAlign: 'center', + marginBottom: 16, + color: '#111827', + }, + + templateBox: { + borderWidth: 1, + borderColor: '#E5E7EB', + borderRadius: 10, + padding: 16, + }, + templateName: { + fontSize: 14, + fontWeight: '700', + color: '#111827', + marginBottom: 12, + }, + field: { + marginBottom: 14, + }, + label: { + fontSize: 13, + fontWeight: '600', + color: '#374151', + marginBottom: 6, + }, + required: { + color: '#EF4444', + }, + input: { + backgroundColor: '#FFFFFF', + borderWidth: 1, + borderColor: '#E5E7EB', + borderRadius: 8, + padding: 12, + fontSize: 14, + color: '#111827', + }, + filePicker: { + borderWidth: 1, + borderColor: '#E5E7EB', + borderRadius: 8, + padding: 12, + }, + fileText: { + color: '#6B7280', + fontSize: 14, + }, + fileSelected: { + color: '#111827', + fontWeight: '600', + }, + errorText: { + color: '#EF4444', + fontSize: 12, + marginTop: 4, + }, + errorBorder: { + borderColor: '#EF4444', + }, + submitRow: { + marginTop: 20, + alignItems: 'flex-end', + height:50 + }, + submitBtn: { + backgroundColor: colors.primary, + paddingVertical: 10, + paddingHorizontal: 22, + borderRadius: 8, + minWidth: 120, + alignItems: 'center', + }, + submitText: { + color: '#FFFFFF', + fontWeight: '700', + fontSize: 14, + }, +}) + diff --git a/src/Screens/Bidding/Emd.tsx b/src/Screens/Bidding/Emd.tsx index fc22411..90a86ea 100644 --- a/src/Screens/Bidding/Emd.tsx +++ b/src/Screens/Bidding/Emd.tsx @@ -1,37 +1,31 @@ -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { View, Text, FlatList, TouchableOpacity, StyleSheet, TextInput, Alert } from 'react-native'; import { pick } from '@react-native-documents/picker'; import Animated, { FadeInDown, FadeOutUp, Layout } from 'react-native-reanimated'; // import BouncyCheckbox from 'react-native-bouncy-checkbox'; -import { InsideHeader, Skelton } from '../../Component/Index'; +import BouncyCheckbox from 'react-native-bouncy-checkbox'; +import { InsideHeader, Loader, Skelton } from '../../Component/Index'; import colors from '../../Constant/Color'; import EmdComplete from './Component/EmdComplete'; import NavigationString from '../../Constant/NavigationString'; import { useNavigation } from '@react-navigation/native'; +import { useSelector } from 'react-redux'; +import { useAuctionItem, useEmdCheck } from '../../Services/BBPS/Hooks'; +import { apiCall } from '../../Axios/Axios'; +import { AUCTION_ITEM_SUBMIT, CHECK_TECHNICAL_DOCUMENTAION, GET_TECHNICAL_DOCUMENTAION } from '../../Services/BBPS/ApiUrls'; +import TemplateFormModal from './Component/TemplateFormModal'; +import { SelectedItem } from './Type/BidType'; -const DUMMY_AUCTION_ITEMS = [ - { id: 1, productName: 'Iron Scrap Lot A', emdAmount: 50000, itemDocumentName: null }, - { id: 2, productName: 'Steel Rods Lot B', emdAmount: 75000, itemDocumentName: 'old_emd.pdf' }, - { id: 3, productName: 'Copper Wire Lot C', emdAmount: 60000, itemDocumentName: null }, -]; - -type SelectedItem = { - auctionItemId: number; - productImageName: string; - file: { - name: string; - uri: string; - type: string; - } | null; -}; const Emd = () => { const Navigation: any = useNavigation() + const SelectedAuction = useSelector((state: any) => state.auction.auction) const [selectedItems, setSelectedItems] = useState([]); const [acceptedPolicy, setAcceptedPolicy] = useState(false); - const [isComplete, setIsComplete] = useState(false); + const [allBoolean, setAllBoolean] = useState({ isSubmitEmdLoading: false, isEmdComplete: false, auctionItems: [], technicalDocumentStatus: false, selectTemplate: {}, technicalDocModalVisible: false }) + const { mutate } = useEmdCheck() + const { mutate: AuctionItemMutate, isPending } = useAuctionItem() - /* ---------------- Helpers ---------------- */ const isSelected = (id: number) => selectedItems.some(i => i.auctionItemId === id); const toggleSelect = (item: any, checked: boolean) => { @@ -70,27 +64,6 @@ const Emd = () => { }; - const handleSubmit = () => { - if (!acceptedPolicy) { - Alert.alert('Policy Required', 'Please accept terms'); - return; - } - - if (selectedItems.length === 0) { - Alert.alert('Select Item', 'Please select at least one item'); - return; - } - - for (const item of selectedItems) { - if (!item.productImageName || !item.file) { - Alert.alert('Incomplete', 'Upload documents for all selected items'); - return; - } - } - - console.log('✅ SUBMITTED:', selectedItems); - setIsComplete(true); - }; /* ---------------- Render Item ---------------- */ const renderItem = ({ item }: any) => { @@ -141,6 +114,7 @@ const Emd = () => { updateSelectedItem(item.id, { productImageName: text }) } style={styles.input} + placeholderTextColor={colors.lightText} /> { ); }; + // Api calls + const getAuctionItem = async () => { + try { + setAllBoolean((prev: any) => ({ ...prev, isLoading: true })) + if (SelectedAuction.auctionPattern === 'Forward') { + const payload = { auctionNumber: SelectedAuction.auctionNumber, status: 'Forward' } + AuctionItemMutate(payload, { + onSuccess: (res) => { + if (res.statusCode == 200) { + setAllBoolean((prev: any) => ({ ...prev, auctionItems: Array.isArray(res?.data) ? res.data : [res.data] })) + } + }, + onError: (err) => { + + } + }) + + } else if (SelectedAuction.auctionPattern === 'Reverse') { + const payload = { auctionNumber: SelectedAuction.auctionNumber, status: 'Reverse' } + AuctionItemMutate(payload, { + onSuccess: (res) => { + if (res.statusCode == 200) { + setAllBoolean((prev: any) => ({ ...prev, auctionItems: Array.isArray(res?.data) ? res.data : [res.data] })) + } + }, + onError: (err) => { + + } + }) + + } + } catch (error) { + console.log('Auction fetch error', error) + } finally { + setAllBoolean((prev: any) => ({ ...prev, isLoading: false })) + } + } + + const getTemplateDocumentation = async () => { + try { + if (SelectedAuction.technicalDocReq) { + const res = await apiCall('get', CHECK_TECHNICAL_DOCUMENTAION, {}, { auctionId: SelectedAuction.auctionId }) + + if (res.data) { + setAllBoolean((prev: any) => ({ ...prev, technicalDocumentStatus: true })) + } else { + const res = await apiCall('get', GET_TECHNICAL_DOCUMENTAION,) + const auctionIdToFind = String(SelectedAuction.auctionId); + const matchedObject = res.data.find((item: any) => + item.auctionIds + .split(',') + .map((id: any) => id.trim()) + .includes(auctionIdToFind) + ); + setAllBoolean((prev: any) => ({ ...prev, selectTemplate: matchedObject, technicalDocModalVisible: true })) + } + } + + + } catch (error) { + console.log('Auction fetch error', error) + } finally { + setAllBoolean((prev: any) => ({ ...prev, isLoading: false })) + } + } + + const AlreadyEmdCheck = async () => { + try { + mutate({ auctionNumber: SelectedAuction.auctionNumber }, { + onSuccess: (res => { + console.log(SelectedAuction.auctionNumber, res , SelectedAuction,'iiiiiiiiiiiiiiiiiiiiiiiii'); + + if (res.statusCode == 200) { + if (res.message == 'No EMD Documents') { + setAllBoolean((prev: any) => ({ ...prev, isEmdComplete: false })) + getAuctionItem() + } else { + if (!SelectedAuction.technicalDocReq) { + setAllBoolean((prev: any) => ({ ...prev, isEmdComplete: true, technicalDocumentStatus: true })) + } else { + setAllBoolean((prev: any) => ({ ...prev, isEmdComplete: true })) + getTemplateDocumentation() + } + + } + } + }), + onError: (err) => { + + } + }) + } catch (error) { + console.log('EMD Check Error:', error) + } finally { + setAllBoolean((prev: any) => ({ ...prev, isLoading: false })) + } + } + + const handleSubmit = async () => { + setAllBoolean((prev: any) => ({ ...prev, isSubmitEmdLoading: true })) + if (!acceptedPolicy) { + Alert.alert('Policy Required', 'Please accept terms'); + return; + } + + if (selectedItems.length === 0) { + Alert.alert('Select Item', 'Please select at least one item'); + return; + } + + for (const item of selectedItems) { + if (!item.productImageName || !item.file) { + Alert.alert('Incomplete', 'Upload documents for all selected items'); + return; + } + } + try { + const formData = new FormData() + + formData.append('auctionId', String(SelectedAuction.auctionId)) + + selectedItems.forEach((item: any) => { + formData.append( + 'auctionItemId', + String(item.auctionItemId) + ) + + formData.append( + 'productImageName', + item.productImageName + ) + + formData.append('files', { + uri: item.file.uri, + name: item.file.name, + type: item.file.type || 'application/pdf', + } as any) + }) + + const res = await apiCall('post', AUCTION_ITEM_SUBMIT, formData, {}, 'multipart/form-data') + if (res.statusCode == 200) { + if (SelectedAuction.technicalDocReq) { + getTemplateDocumentation() + } else { + if (SelectedAuction.auctionPattern === 'Forward') { + Navigation.navigate(NavigationString.StartBidding) + } else { + Navigation.navigate(NavigationString.StartReverseBidding) + } + } + } + } catch (error) { + console.log('Submit error', error) + Alert.alert('Error', 'Failed to submit EMD') + } finally { + setAllBoolean((prev: any) => ({ ...prev, isSubmitEmdLoading: true })) + } + }; + + const EmdContinueHandle = async () => { + + if (allBoolean.technicalDocumentStatus) { + if (SelectedAuction.auctionPattern === 'Forward') { + Navigation.navigate(NavigationString.StartBidding) + } else { + Navigation.navigate(NavigationString.StartReverseBidding) + } + } else { + getTemplateDocumentation() + } + } + useEffect(() => { + AlreadyEmdCheck() + }, []) + return ( + {SelectedAuction.technicalDocReq && allBoolean.technicalDocModalVisible && + + } - {false ? ( + {isPending ? ( - ) : true ? ( - { Navigation.navigate(NavigationString.StartBidding) }} /> + ) : allBoolean.isEmdComplete ? ( + ) : <> item.id.toString()} + data={allBoolean.auctionItems} + keyExtractor={(item: any) => item.auctionId} renderItem={renderItem} contentContainerStyle={{ paddingBottom: 170 }} /> @@ -200,7 +352,10 @@ const Emd = () => { onPress={handleSubmit} disabled={!acceptedPolicy} > - Submit EMD + { + allBoolean.isSubmitEmdLoading ? : Submit EMD + } + @@ -277,6 +432,7 @@ const styles = StyleSheet.create({ padding: 12, backgroundColor: '#FFFFFF', fontSize: 14, + color: colors.black }, uploadBtn: { diff --git a/src/Screens/Bidding/StartBidding.tsx b/src/Screens/Bidding/StartBidding.tsx index 2adf4e0..eb74a14 100644 --- a/src/Screens/Bidding/StartBidding.tsx +++ b/src/Screens/Bidding/StartBidding.tsx @@ -1,154 +1,136 @@ -import React, { useEffect, useState, useCallback } from 'react'; -import { - View, - Text, - FlatList, - TextInput, - TouchableOpacity, - StyleSheet, - Platform, - Alert, -} from 'react-native'; +import React, { useCallback, useEffect, useState } from 'react'; +import { View, FlatList, StyleSheet, Platform, Alert, BackHandler, Text } from 'react-native'; import LottieView from 'lottie-react-native'; -import Animated, { - FadeInUp, - useSharedValue, - useAnimatedStyle, - withSpring, - withTiming, - Layout, - interpolate, -} from 'react-native-reanimated'; import { InsideHeader } from '../../Component/Index'; import colors from '../../Constant/Color'; +import { useWebSocketService } from '../../socket/Socket'; +import Variables from '../../Constant/Variable'; +import { useSelector } from 'react-redux'; +import { apiCall } from '../../Axios/Axios'; +import { FORWARD_AUCTION_ITEM, REVERSE_AUCTION_ITEM, SELECTED_AUCTION_ITEM } from '../../Services/BBPS/ApiUrls'; +import BiddingCard from './Component/BiddingCard'; +import { CommonActions, useFocusEffect, useNavigation } from '@react-navigation/native'; +import NavigationString from '../../Constant/NavigationString'; +import CountdownTimer from '../../Component/Counter/CountdownTimer'; +import FontsFamily from '../../Constant/FontsFamily'; -/* ---------------- Types ---------------- */ -interface AuctionItem { - id: number; - productName: string; - auctionStartValueFigure: number; - bidVariationValue: number; - bidAmount: number; - bidAvilable: number; - me: boolean; -} +const StartBidding = () => { + const SelectedAuction = useSelector((state: any) => state.auction.auction); + const loginUser = useSelector((state: any) => state.token.token) + const Navigation: any = useNavigation() + const [items, setItems] = useState([]); + const [bidValues, setBidValues] = useState>({}); + const [allBoolean, setAllBoolean] = useState({ showSuccess: false, showDialog: false, bidPayload: {} }) + const { subscribe, createRoom, placeBid } = useWebSocketService( + Variables.webSocketUrl, + () => console.log('Connected!'), + (error) => console.log('WebSocket Error:', error), + loginUser.token, + ); -/* ---------------- Dummy Data ---------------- */ -const DUMMY_AUCTION = { auctionNumber: 'AUC-2025-001' }; -const DUMMY_ITEMS: AuctionItem[] = [ - { id: 1, productName: 'Iron Scrap Lot', auctionStartValueFigure: 20000, bidVariationValue: 500, bidAmount: 20000, bidAvilable: 20000, me: false }, - { id: 2, productName: 'Steel Rod Bundle', auctionStartValueFigure: 35000, bidVariationValue: 1000, bidAmount: 35000, bidAvilable: 35000, me: true }, - { id: 3, productName: 'Copper Wire Roll', auctionStartValueFigure: 15000, bidVariationValue: 250, bidAmount: 15000, bidAvilable: 0, me: false }, -]; + const getAllAcutionItems = async () => { + try { + const payload = { auctionNumber: SelectedAuction.auctionNumber }; + let auctionItem: any[] = []; -/* ---------------- Bidding Card ---------------- */ -const BiddingCard = ({ item, bidValue, onIncrease, onDecrease, onPlaceBid }: any) => { - const [expanded, setExpanded] = useState(false); - const isMin = bidValue <= item.bidAmount; + if (SelectedAuction.auctionPattern === 'Forward') { + const res = await apiCall('get', FORWARD_AUCTION_ITEM, {}, payload); + if (res?.statusCode === 200) auctionItem = res.data || []; + } else { + const res = await apiCall('get', REVERSE_AUCTION_ITEM, {}, payload); + if (res?.statusCode === 200) auctionItem = res.data || []; + } - const animation = useSharedValue(0); + const selectedRes = await apiCall('get', SELECTED_AUCTION_ITEM, {}, payload); +console.log(selectedRes,'jhhhhhhhhhh'); - const toggleExpand = () => { - setExpanded(!expanded); - animation.value = withSpring(expanded ? 0 : 1, { damping: 15 }); + const uniqueArray: number[] = Array.from( + new Set(selectedRes?.data || []) + ); + + const filteredItems = auctionItem.filter(item => + uniqueArray.includes(item.id) + ); + + + const result = await createRoom(SelectedAuction.auctionNumber); + + subscribe(`/topic/room/${SelectedAuction.auctionNumber}`, data => { + console.log('🔥 BID UPDATE:', data); + }); + + const bidAmountMap2 = new Map(); + + (result || []).forEach((r: any) => { + bidAmountMap2.set(r.auctionItemId, { + bidAmount: r.bidAmount, + contractorId: r.contractorId, + }); + }); + + + + const bidAmountMap = new Map(); + + (result || []).forEach((r: any) => { + bidAmountMap.set(r.auctionItemId, r.bidAmount); + }); + + const updatedFilteredItems = filteredItems.map(item => { + const bidData = bidAmountMap2.get(item.id); + return { + ...item, + bidAmount: bidData?.bidAmount ?? item.auctionStartValueFigure, + bidAvilable: bidData?.bidAmount ?? 0, + me: bidData?.contractorId == loginUser.contractorId ? true : false + }; + }); + + const initialBids: Record = {}; + updatedFilteredItems.forEach(item => { + initialBids[item.id] = item.bidAmount; + }); + setBidValues(initialBids); + setItems(updatedFilteredItems); + + } catch (error) { + console.error('Error fetching auction items:', error); + } }; - const bodyStyle = useAnimatedStyle(() => { - return { - height: interpolate(animation.value, [0, 1], [0, 190]), - opacity: interpolate(animation.value, [0, 0.5, 1], [0, 0, 1]), - marginTop: interpolate(animation.value, [0, 1], [0, 15]), - }; + subscribe(`/topic/room/${SelectedAuction.auctionNumber}`, async (message) => { + // console.log('RAW MESSAGE:', message[message.length - 1]); + const result = message[message.length - 1] + + const updatedBidItem = (prev: any[]) => + prev.map(item => + item.id === result.auctionItemId + ? { ...item, bidAmount: result.bidAmount, me: result.contractorId == loginUser.contractorId ? true : false } + : item + ); + + setItems(updatedBidItem); + + setBidValues(prev => ({ + ...prev, + [result.auctionItemId]: result.bidAmount, + })); + try { + + } catch (err) { + console.log('JSON parse error:', err); + } }); - const arrowStyle = useAnimatedStyle(() => ({ - transform: [{ rotate: `${interpolate(animation.value, [0, 1], [0, 180])}deg` }], - })); + useEffect(() => { + getAllAcutionItems(); + subscribe(`/topic/room/${SelectedAuction.auctionNumber}`, (data) => { }); + }, []); - return ( - - {/* Header - Always Visible */} - - - {item.productName} - {DUMMY_AUCTION.auctionNumber} - - - - - - {item.me ? 'LEADING' : 'LIVE'} - - - ▼ - - - - {/* Main Price Info - Always Visible */} - - - Current Bid - ₹{item.bidAmount.toLocaleString()} - - - Increment - +₹{item.bidVariationValue} - - - - {/* Collapsible Section */} - - - - Set Your Bid - - - − - - - - ₹ - {bidValue.toLocaleString()} - - - - + - - - - - Confirm Bid - - - - ); -}; - -/* ---------------- Main Screen ---------------- */ -const StartBidding = () => { - const [items, setItems] = useState(DUMMY_ITEMS); - const [bidValues, setBidValues] = useState>({}); - const [showSuccess, setShowSuccess] = useState(false); useEffect(() => { const initial: Record = {}; - items.forEach(item => { + items.forEach((item: any) => { initial[item.id] = item.bidAmount + item.bidVariationValue; }); setBidValues(initial); @@ -158,38 +140,133 @@ const StartBidding = () => { setBidValues(prev => ({ ...prev, [id]: prev[id] + val })); }; - const handlePlaceBid = (item: AuctionItem) => { - Alert.alert('Confirm', `Place bid for ₹${bidValues[item.id]}?`, [ - { text: 'No' }, - { - text: 'Yes, Bid', - onPress: () => { - setItems(prev => prev.map(i => i.id === item.id ? { ...i, bidAmount: bidValues[item.id], me: true } : i)); - setShowSuccess(true); - setTimeout(() => setShowSuccess(false), 2000); - } - } - ]); + const submitBid = async (item: any) => { + const payload = { + itemId: item.id, + bidAmount: bidValues[item.id], + auctionId: SelectedAuction.auctionId, + contractorId: loginUser.contractorId, + fullName: loginUser.fullName, + roomId: SelectedAuction.auctionNumber, + }; + setAllBoolean((prev: any) => ({ ...prev, bidPayload: payload, })); + Alert.alert( + 'Confirm Bid', + `Are you sure you want to place a bid of ₹${payload.bidAmount}?`, + [ + { + text: 'Cancel', + style: 'cancel', + }, + { + text: 'Submit', + onPress: () => { + + placeBidSubmit(payload); + }, + }, + ], + { cancelable: true } + ); }; + const placeBidSubmit = async (data: any) => { + try { + const result: any = await placeBid(data); + + if (result?.status && result.data) { + const updatedBidItem = (prev: any[]) => + prev.map(item => + item.id === result.data.auctionItemId + ? { ...item, bidAmount: result.data.bidAmount, me: result.data?.contractorId == loginUser.contractorId ? true : false } + : item + ); + + // setItems(updatedBidItem); + + + // setBidValues((prev: any) => ({ + // ...prev, + // [result.data.auctionItemId]: { + // ...prev[result.data.auctionItemId], + // bidAmount: result.data.bidAmount, + // }, + // })); + getAllAcutionItems() + } + } catch (error) { + console.error('Error placing bid:', error); + } + }; + + useFocusEffect( + useCallback(() => { + const onBackPress = () => { + Alert.alert( + 'Confirm', + 'Do you want to go back to Dashboard?', + [ + { text: 'Cancel', style: 'cancel' }, + { + text: 'Yes', + onPress: () => { + Navigation.dispatch( + CommonActions.reset({ + index: 0, + routes: [{ name: NavigationString.Home }], + }) + ); + }, + }, + ], + { cancelable: true } + ); + + return true; // block default back action + }; + + const subscription = BackHandler.addEventListener( + 'hardwareBackPress', + onBackPress + ); + + return () => subscription.remove(); + }, [Navigation]) + ); return ( + + + {SelectedAuction.deptName} + + + + + + + item.id.toString()} - renderItem={({ item }) => ( + renderItem={({ item, index }) => ( handleUpdate(item.id, item.bidVariationValue)} onDecrease={() => handleUpdate(item.id, -item.bidVariationValue)} - onPlaceBid={() => handlePlaceBid(item)} + onPlaceBid={() => { submitBid(item) }} + SelectedAuction={SelectedAuction} /> )} contentContainerStyle={{ padding: 16 }} /> - {showSuccess && ( + + {allBoolean.showSuccess && ( { export default StartBidding; -/* ---------------- Modern Styles ---------------- */ const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: colors.white }, + container2: { + paddingHorizontal: 16, + paddingTop: 12, + paddingBottom: 8, + }, + title: { + fontSize: 18, + fontFamily: FontsFamily.poppinsSemiBold, + color: colors.black, + marginBottom: 6, + // textAlign:'center' + }, + timerWrapper: { + alignItems: 'center', + }, card: { backgroundColor: '#FFF', borderRadius: 24, diff --git a/src/Screens/Bidding/StartReverseBidding.tsx b/src/Screens/Bidding/StartReverseBidding.tsx new file mode 100644 index 0000000..9d7edf3 --- /dev/null +++ b/src/Screens/Bidding/StartReverseBidding.tsx @@ -0,0 +1,401 @@ +import React, { useCallback, useEffect, useState } from 'react'; +import { View, FlatList, StyleSheet, Platform, Alert, BackHandler, Text, ToastAndroid } from 'react-native'; +import LottieView from 'lottie-react-native'; +import { InsideHeader } from '../../Component/Index'; +import colors from '../../Constant/Color'; +import { useWebSocketService } from '../../socket/Socket'; +import Variables from '../../Constant/Variable'; +import { useSelector } from 'react-redux'; +import { apiCall } from '../../Axios/Axios'; +import { AUCTION_ONE_TIME_BID, GET_AUCTION_DETAILS, REVERSE_AUCTION_ITEM, SELECTED_AUCTION_ITEM } from '../../Services/BBPS/ApiUrls'; +import { CommonActions, useFocusEffect, useNavigation } from '@react-navigation/native'; +import NavigationString from '../../Constant/NavigationString'; +import CountdownTimer from '../../Component/Counter/CountdownTimer'; +import FontsFamily from '../../Constant/FontsFamily'; +import ReverseBiddingCard from './Component/ReverseBiddingCard'; + +const StartReverseBidding = () => { + const SelectedAuction = useSelector((state: any) => state.auction.auction); + const loginUser = useSelector((state: any) => state.token.token) + const Navigation: any = useNavigation() + const [items, setItems] = useState([]); + const [bidValues, setBidValues] = useState>({}); + const [allBoolean, setAllBoolean] = useState({ showSuccess: false, showDialog: false, bidPayload: {}, oneTimeBid: false, rebid: false, reload: false }) + const { subscribe, createRoom, placeBid } = useWebSocketService( + Variables.webSocketUrl, + () => console.log('Connected!'), + (error) => console.log('WebSocket Error:', error), + loginUser.token, + ); + const getAuction = async () => { + const selectedRes = await apiCall('get', GET_AUCTION_DETAILS, {}, { id: SelectedAuction.auctionId }); + if (selectedRes.statusCode == 200 && selectedRes.data.contractorId.length) { + setAllBoolean((prev: any) => ({ ...prev, oneTimeBid: true })) + } + } + + const getOneTimeBidValue = async () => { + try { + const selectedRes = await apiCall('get', AUCTION_ONE_TIME_BID, {}, { auctionId: SelectedAuction.auctionId }); + if (selectedRes.statusCode == 200) { + return selectedRes.data + } else { + return [] + } + } catch (error) { + + } + + } + + const getAllAcutionItems = async () => { + try { + const payload = { auctionNumber: SelectedAuction.auctionNumber }; + let auctionItem: any[] = []; + + if (SelectedAuction.auctionPattern === 'Reverse') { + const res = await apiCall('get', REVERSE_AUCTION_ITEM, {}, payload); + if (res?.statusCode === 200) auctionItem = res.data || []; + } + + const selectedRes = await apiCall('get', SELECTED_AUCTION_ITEM, {}, payload); + + const uniqueArray: number[] = Array.from( + new Set(selectedRes?.data || []) + ); + + const filteredItems = auctionItem.filter(item => + uniqueArray.includes(item.id) + ); + + if (SelectedAuction.auctionCategories == 'Live') { + const result = await createRoom(SelectedAuction.auctionNumber); + + subscribe(`/topic/room/${SelectedAuction.auctionNumber}`, data => { + console.log('🔥 BID UPDATE:', data); + }); + const bidAmountMap2 = new Map(); + + (result || []).forEach((r: any) => { + bidAmountMap2.set(r.auctionItemId, { + bidAmount: r.bidAmount, + contractorId: r.contractorId, + }); + }); + // Check One Time bid enable butoon + if (SelectedAuction.auctionCategories != 'Live') { + const myBid = result.find( + (bid: any) => bid.contractorId === loginUser.contractorId + ); + + if (myBid) { + setAllBoolean((prev: any) => ({ ...prev, oneTimeBid: true })) + } + } + + const bidAmountMap = new Map(); + + (result || []).forEach((r: any) => { + bidAmountMap.set(r.auctionItemId, r.bidAmount); + }); + + const updatedFilteredItems = filteredItems.map(item => { + const bidData = bidAmountMap2.get(item.id); + return { + ...item, + bidAmount: bidData?.bidAmount ?? item.auctionStartValue, + bidAvilable: bidData?.bidAmount ?? 0, + me: bidData?.contractorId == loginUser.contractorId ? true : false + }; + }); + + const initialBids: Record = {}; + updatedFilteredItems.forEach(item => { + initialBids[item.id] = item.bidAmount; + }); + setBidValues(initialBids); + setItems(updatedFilteredItems); + } else { + let result = [] + if (SelectedAuction.rebidAllowed) { + setAllBoolean((prev: any) => ({ ...prev, rebid: true })) + } + + if (SelectedAuction.auctionCategories != 'Live') { + result = await getOneTimeBidValue() + } + const bidMap = new Map(); + + result.forEach((bid: any) => { + bidMap.set(bid.auctionItemId, bid); + }); + const mergedData = auctionItem.map((item: any) => { + const bid = bidMap.get(item.id); + + if (!bid) { + return { + ...item, + bidAmount: item.auctionStartValue, + contractorId: item.contractorId, + }; + } + + return { + ...item, + bidAmount: bid.bidAmount, + bidId: bid.bidId, + contractorId: bid.contractorId, + contractorName: bid.contractorName, + me: bid.contractorId === loginUser.contractorId, + bidTime: bid.bidTime, + }; + }); + const initialBids: Record = {}; + mergedData.forEach(item => { + initialBids[item.id] = item.bidAmount; + }); + setBidValues(initialBids); + setItems(mergedData) + setBidValues(initialBids); + } + } catch (error) { + console.error('Error fetching auction items:', error); + } + }; + + subscribe(`/topic/room/${SelectedAuction.auctionNumber}`, async (message) => { + + const result = message[message.length - 1] + + const updatedBidItem = (prev: any[]) => + prev.map(item => + item.id === result.auctionItemId + ? { ...item, bidAmount: result.bidAmount, me: result.contractorId == loginUser.contractorId ? true : false } + : item + ); + + setItems(updatedBidItem); + + setBidValues(prev => ({ + ...prev, + [result.auctionItemId]: result.bidAmount, + })); + try { + + } catch (err) { + console.log('JSON parse error:', err); + } + }); + + useEffect(() => { + if (SelectedAuction.auctionCategories == 'One-time') { + getAuction() + } + getAllAcutionItems(); + subscribe(`/topic/room/${SelectedAuction.auctionNumber}`, (data) => { }); + }, [allBoolean.reload]); + + useEffect(() => { + const initial: Record = {}; + items.forEach((item: any) => { + initial[item.id] = item.bidAmount + item.bidVariationValue; + }); + setBidValues(initial); + }, []); + + const handleUpdate = (id: number, val: number) => { + setBidValues(prev => ({ ...prev, [id]: prev[id] + val })); + }; + + const submitBid = async (item: any) => { + const payload = { + itemId: item.id, + bidAmount: bidValues[item.id], + auctionId: SelectedAuction.auctionId, + contractorId: loginUser.contractorId, + fullName: loginUser.fullName, + roomId: SelectedAuction.auctionNumber, + }; + setAllBoolean((prev: any) => ({ ...prev, bidPayload: payload, })); + Alert.alert( + 'Confirm Bid', + `Are you sure you want to place a bid of ₹${payload.bidAmount}?`, + [ + { + text: 'Cancel', + style: 'cancel', + }, + { + text: 'Submit', + onPress: () => { + placeBidSubmit(payload); + }, + }, + ], + { cancelable: true } + ); + }; + + const placeBidSubmit = async (data: any) => { + try { + const result: any = await placeBid(data); + console.log(result, 'kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk'); + + if (result?.status && result.data) { + const updatedBidItem = (prev: any[]) => + prev.map(item => + item.id === result.data.auctionItemId + ? { ...item, bidAmount: result.data.bidAmount, me: result.data?.contractorId == loginUser.contractorId ? true : false } + : item + ); + + getAllAcutionItems() + } + } catch (error) { + console.error('Error placing bid:', error); + } + }; + + useFocusEffect( + useCallback(() => { + const onBackPress = () => { + Alert.alert( + 'Confirm', + 'Do you want to go back to Dashboard?', + [ + { text: 'Cancel', style: 'cancel' }, + { + text: 'Yes', + onPress: () => { + Navigation.dispatch( + CommonActions.reset({ + index: 0, + routes: [{ name: NavigationString.Home }], + }) + ); + }, + }, + ], + { cancelable: true } + ); + + return true; // block default back action + }; + + const subscription = BackHandler.addEventListener( + 'hardwareBackPress', + onBackPress + ); + + return () => subscription.remove(); + }, [Navigation]) + ); + + return ( + + + + + {SelectedAuction.deptName} + + + + + + + + item.id.toString()} + renderItem={({ item, index }) => ( + handleUpdate(item.id, item.emdAmount)} + onDecrease={() => handleUpdate(item.id, -item.emdAmount)} + onPlaceBid={() => { submitBid(item) }} + SelectedAuction={SelectedAuction} + allBoolean={allBoolean} + setAllBoolean={setAllBoolean} + /> + )} + contentContainerStyle={{ padding: 16 }} + /> + + {allBoolean.showSuccess && ( + + + + )} + + ); +}; + +export default StartReverseBidding; + +const styles = StyleSheet.create({ + container: { flex: 1, backgroundColor: colors.white }, + container2: { + paddingHorizontal: 16, + paddingTop: 12, + paddingBottom: 8, + }, + title: { + fontSize: 18, + fontFamily: FontsFamily.poppinsSemiBold, + color: colors.black, + marginBottom: 6, + // textAlign:'center' + }, + timerWrapper: { + alignItems: 'center', + }, + card: { + backgroundColor: '#FFF', + borderRadius: 24, + padding: 20, + marginBottom: 16, + borderWidth: 1, + borderColor: '#E2E8F0', + overflow: 'hidden', + ...Platform.select({ ios: { shadowColor: '#000', shadowOpacity: 0.05, shadowRadius: 10 }, android: { elevation: 2 } }), + }, + leadingCard: { borderColor: '#22C55E', borderWidth: 2, backgroundColor: '#F0FDF4' }, + cardHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'flex-start' }, + headerRight: { flexDirection: 'row', alignItems: 'center', gap: 8 }, + productName: { fontSize: 18, fontWeight: 'bold', color: '#1E293B' }, + itemIdText: { fontSize: 12, color: '#64748B', marginTop: 2 }, + badge: { paddingHorizontal: 10, paddingVertical: 4, borderRadius: 8 }, + liveBadge: { backgroundColor: '#FEE2E2' }, + meBadge: { backgroundColor: '#BBF7D0' }, + badgeText: { fontSize: 10, fontWeight: '900' }, + liveText: { color: '#EF4444' }, + meText: { color: '#15803D' }, + arrow: { fontSize: 10, color: '#94A3B8' }, + priceRow: { flexDirection: 'row', justifyContent: 'space-between', marginTop: 20 }, + label: { fontSize: 11, color: '#94A3B8', textTransform: 'uppercase', fontWeight: '600' }, + mainPrice: { fontSize: 22, fontWeight: '900', color: '#0F172A' }, + incrementText: { fontSize: 16, fontWeight: '700', color: '#3B82F6' }, + collapsibleContainer: { overflow: 'hidden' }, + divider: { height: 1, backgroundColor: '#E2E8F0', marginVertical: 10 }, + bidLabel: { fontSize: 13, fontWeight: '600', color: '#475569', marginBottom: 10 }, + stepperContainer: { flexDirection: 'row', gap: 12, marginBottom: 20 }, + stepBtn: { width: 45, height: 45, backgroundColor: colors.primary, borderRadius: 12, justifyContent: 'center', alignItems: 'center' }, + disabledBtn: { backgroundColor: '#CBD5E1' }, + stepText: { color: '#FFF', fontSize: 20, fontWeight: 'bold' }, + inputBox: { flex: 1, height: 45, backgroundColor: '#F1F5F9', borderRadius: 12, flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }, + currency: { fontSize: 16, fontWeight: 'bold', color: '#64748B', marginRight: 4 }, + bidValueText: { fontSize: 18, fontWeight: '800', color: '#0F172A' }, + submitBtn: { height: 50, backgroundColor: colors.primary, borderRadius: 15, justifyContent: 'center', alignItems: 'center' }, + submitBtnText: { color: '#FFF', fontSize: 16, fontWeight: 'bold' }, + overlay: { ...StyleSheet.absoluteFillObject, backgroundColor: 'rgba(255,255,255,0.7)', justifyContent: 'center', alignItems: 'center', zIndex: 99 }, +}); \ No newline at end of file diff --git a/src/Screens/Bidding/Type/BidType.tsx b/src/Screens/Bidding/Type/BidType.tsx index cbd6f17..c65fda2 100644 --- a/src/Screens/Bidding/Type/BidType.tsx +++ b/src/Screens/Bidding/Type/BidType.tsx @@ -15,4 +15,21 @@ export type allBooleanType = { activeItemId: number | null acitveItemData: any timeEnd: boolean -} \ No newline at end of file +} +export interface Props { + visible: boolean + setAllBoolean: any + allBoolean: any + template: any +} + + +export type SelectedItem = { + auctionItemId: number; + productImageName: string; + file: { + name: string; + uri: string; + type: string; + } | null; +}; \ No newline at end of file diff --git a/src/Screens/index.ts b/src/Screens/index.ts index 3f4d9de..95b8b49 100644 --- a/src/Screens/index.ts +++ b/src/Screens/index.ts @@ -3,6 +3,7 @@ import PurchaseAuctionList from "./Auction/PurchaseAuctionList"; import PurchaseList from "./Auction/PurchaseList"; import Emd from "./Bidding/Emd"; import StartBidding from "./Bidding/StartBidding"; +import StartReverseBidding from "./Bidding/StartReverseBidding"; import Home from "./Home/Home"; import Login from "./Login/Login"; import Onboarding from "./Onboarding/Onboarding"; @@ -28,6 +29,7 @@ const Screens = { PurchaseTenderList, ProceedToPurTender, TenderBidding, - ProceedToBidDetail + ProceedToBidDetail, + StartReverseBidding } export default Screens \ No newline at end of file diff --git a/src/Services/BBPS/ApiUrls.tsx b/src/Services/BBPS/ApiUrls.tsx index d360396..8bd4b5b 100644 --- a/src/Services/BBPS/ApiUrls.tsx +++ b/src/Services/BBPS/ApiUrls.tsx @@ -41,7 +41,7 @@ const GET_DOCID = `${BASE_URL}eTendering/download/docId?docId=` const DOWNLOAD_DOC = `${BASE_URL}eTendering/download/docId?docId=` const TWO_FACTOR_AUTH = `${BASE_URL}contractor/two-factor-auth?status=` const AUCTION_LOGIN = `https://api.godemo.in/Auction/auction/loginWithoutDecryption` -const GET_AUCTION_DETAILS = `${BASE_URL_Auction}api/auction/getAuction/id?id=` +const GET_AUCTION_DETAILS = `${BASE_URL_Auction}api/auction/getAuction/id` const TANDER_PURCHASE_STATUS = `https://procurelinc.in/EProcurementSB/tenderPayment/transactionStatus?orderNo=` const GET_MY_AUCTION = `${BASE_URL_Auction}api/auction/getMyAuction` const GET_MY_TENDER = "https://procurelinc.in/EProcurementSB/tenderBidding/getAllPurchasedTendersByConId" @@ -62,6 +62,7 @@ const ITEM_DOCUMENT_DOWNLOAD = `${BASE_URL_Auction}api/auction/home/downloadDocu // Rohit const DASHBOARD_COUNT = `${BASE_URL_Auction}api/auction/home/dashboard/counts` +const AUCTION_ONE_TIME_BID =`${BASE_URL_Auction}api/bidding/getBidForAuction` //tender @@ -77,6 +78,7 @@ const SUBMIT_ENVELOPE_FILE_B = `${BASE_URL}tenderBidding/addDocumentsEnvelopeB?r export { // Rohit DASHBOARD_COUNT, + AUCTION_ONE_TIME_BID, ITEM_DOCUMENT_DOWNLOAD, ITEM_DETAIL, TECHNICAL_DOCUMENT_SUBMIT, diff --git a/src/Services/BBPS/Hooks.ts b/src/Services/BBPS/Hooks.ts index 070195a..84e1d49 100644 --- a/src/Services/BBPS/Hooks.ts +++ b/src/Services/BBPS/Hooks.ts @@ -1,4 +1,5 @@ import { useInfiniteQuery, useMutation, useQuery } from '@tanstack/react-query'; +import { fetchAuctionItem, fetchDashboard, fetchEmdCheck, fetchLiveAuction, fetchLiveTender, fetchPurchaseAuction, fetchPurchaseTender, offlineAuctionPurchase, userLogin } from './apis'; import { fetchDashboard, fetchLiveAuction, fetchLiveTender, fetchPurchaseAuction, fetchPurchaseTender, offlineAuctionPurchase, userLogin, offlineTenderPurchase, fetchTenderById, proceedToBid } from './apis'; // User diff --git a/src/Services/BBPS/apis.ts b/src/Services/BBPS/apis.ts index d952b04..d2a2eea 100644 --- a/src/Services/BBPS/apis.ts +++ b/src/Services/BBPS/apis.ts @@ -1,5 +1,5 @@ import axios from "axios"; -import { DASHBOARD_COUNT, GET_MY_AUCTION, GET_MY_TENDER, GET_TENDER_DETAILS, LIVE_AUCTION, LIVE_TENDER, LOG_IN_URL, PROCEED_PURCHASE_AUCTION, PROCEED_TO_BID, PURCHASE_TENDER_OFFLINE, TENDER_LOGIN } from "./ApiUrls"; +import { DASHBOARD_COUNT, EMD_CHECK, FORARD_AUCTION_ITEM, GET_MY_AUCTION, GET_MY_TENDER, GET_TENDER_DETAILS, LIVE_AUCTION, LIVE_TENDER, LOG_IN_URL, PROCEED_PURCHASE_AUCTION, PROCEED_TO_BID, PURCHASE_OFFLINE_AUCTION, PURCHASE_TENDER_OFFLINE, REVERSE_AUCTION_ITEM, TENDER_LOGIN } from "./ApiUrls"; import { apiCall } from "../../Axios/Axios"; // User @@ -31,8 +31,35 @@ export const fetchLiveAuction = async (payload: any): Promise => { // Auction Purchase offline export const offlineAuctionPurchase = async (payload: any): Promise => { try { - const response = await axios.post(PROCEED_PURCHASE_AUCTION, payload); - return response.data; + const response = await apiCall('post', `${PURCHASE_OFFLINE_AUCTION}`, payload); + return response; + } catch (error: any) { + throw error.response?.data || error.message; + } +}; + +// EMD + +export const fetchEmdCheck = async (payload: any): Promise => { + try { + const response = await apiCall('get', `${EMD_CHECK}`, {}, payload); + return response; + } catch (error: any) { + throw error.response?.data || error.message; + } +}; + +export const fetchAuctionItem = async (payload: any): Promise => { + try { + if (payload.status == 'Reverse') { + const response = await apiCall('get', `${REVERSE_AUCTION_ITEM}`, {}, payload); + return response; + } else { + const response = await apiCall('get', `${FORARD_AUCTION_ITEM}`, {}, payload); + return response; + } + + } catch (error: any) { throw error.response?.data || error.message; } diff --git a/src/lottie/clock.json b/src/lottie/clock.json new file mode 100644 index 0000000..bff9234 --- /dev/null +++ b/src/lottie/clock.json @@ -0,0 +1 @@ +{"v":"5.4.4","fr":24,"ip":0,"op":28,"w":24,"h":24,"nm":"clock","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Corner between arrows","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[12,12,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-1,-3],[-1,0.414],[1,0.395],[1,-3]],"c":true}],"e":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-0.031,-2.431],[-0.031,-0.155],[0.031,-0.168],[0.031,-2.431]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":14,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-0.031,-2.431],[-0.031,-0.155],[0.031,-0.168],[0.031,-2.431]],"c":true}],"e":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-1,-3],[-1,0.414],[1,0.395],[1,-3]],"c":true}]},{"t":28}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":28,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Static hand","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[12,12,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0,-6],[0,0]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":28,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Middle","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[12,12,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-0.552],[0.552,0],[0,0.552],[-0.552,0]],"o":[[0,0.552],[-0.552,0],[0,-0.552],[0.552,0]],"v":[[1,0],[0,1],[-1,0],[0,-1]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":28,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Moving hand","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0],"e":[360]},{"t":28}],"ix":10},"p":{"a":0,"k":[12,12,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.293,-0.293],[4,4]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":28,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Base","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[12,12,0],"ix":2},"a":{"a":0,"k":[12,12,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,-4.971],[-4.971,0],[0,4.971],[4.971,0]],"o":[[-4.971,0],[0,4.971],[4.971,0],[0,-4.971],[0,0]],"v":[[0,-9],[-9,0],[0,9],[9,0],[0,-9]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[12,12],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":28,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/src/socket/Socket.tsx b/src/socket/Socket.tsx index d0a5f0e..c755536 100644 --- a/src/socket/Socket.tsx +++ b/src/socket/Socket.tsx @@ -51,8 +51,8 @@ const reducer = (state: State, action: Action): State => { export const useWebSocketService = ( webSocketUrl: string, onConnectCallback: () => void, - onErrorCallback: (error: string) => void -) => { + onErrorCallback: (error: string) => void, + Token: any) => { const [state, dispatch] = useReducer(reducer, { client: null, subscriptions: new Map(), @@ -84,7 +84,7 @@ export const useWebSocketService = ( onConnect: () => { isConnected.current = true; - console.log('✅ WebSocket connected'); + // console.log('✅ WebSocket connected'); // 🔁 Flush queued subscriptions pendingSubscriptions.current.forEach(sub => @@ -111,7 +111,7 @@ export const useWebSocketService = ( // 🧠 Queue if not connected if (!client || !isConnected.current) { - console.log('⏳ Queued subscription:', destination); + // console.log('⏳ Queued subscription:', destination); pendingSubscriptions.current.push({ destination, callback }); return; } @@ -123,7 +123,6 @@ export const useWebSocketService = ( try { const parsed = JSON.parse(message.body); - console.log('📡 LIVE DATA:', parsed); callback(parsed); } catch (e) { console.error('❌ JSON parse error', e); @@ -151,7 +150,6 @@ export const useWebSocketService = ( // ================= ROOM ================= const createRoom = async (roomId: any) => { - const Token = useSelector((prev: any) => prev.token.token) if (!roomId) return; try { @@ -160,7 +158,7 @@ export const useWebSocketService = ( null, { params: { roomId }, - headers: { Authentication: `Bearer ${Token.token}` }, + headers: { Authentication: `Bearer ${Token}` }, } ); @@ -175,11 +173,11 @@ export const useWebSocketService = ( }; const joinRoom = async (roomId: any) => { - const Token = useSelector((prev: any) => prev.token.token) + try { const { data } = await axios.get( `${Variables.socketUrl}livebidding/joinRoom?roomId=${roomId}`, - { headers: { Authentication: `Bearer ${Token.token}` } } + { headers: { Authentication: `Bearer ${Token}` } } ); if (data.statusCode === 200) return data.data.bids; @@ -190,17 +188,17 @@ export const useWebSocketService = ( // ================= BID ================= const placeBid = async (BidDTO: any) => { - const Token = useSelector((prev: any) => prev.token.token) + try { const res = await axios.post( `${Variables.socketUrl}livebidding/placeBid`, BidDTO, - { headers: { Authentication: `Bearer ${Token.token}` } } + { headers: { Authentication: `Bearer ${Token}` } } ); if (res.data.statusCode === 200) { showSuccessAlert(res.data.message); - return { data: res.data.data, status: true }; + return { data: res.data.data, status: true, message: res.data.message }; } } catch (err: any) { if (err?.response?.data?.statusCode === 400) { diff --git a/waste.ts b/waste.ts new file mode 100644 index 0000000..0c84711 --- /dev/null +++ b/waste.ts @@ -0,0 +1,340 @@ +// import React, { useCallback, useEffect, useState } from 'react'; +// import { View, FlatList, StyleSheet, Platform, Alert, BackHandler, Text, ToastAndroid } from 'react-native'; +// import LottieView from 'lottie-react-native'; +// import { InsideHeader } from '../../Component/Index'; +// import colors from '../../Constant/Color'; +// import { useWebSocketService } from '../../socket/Socket'; +// import Variables from '../../Constant/Variable'; +// import { useSelector } from 'react-redux'; +// import { apiCall } from '../../Axios/Axios'; +// import { FORWARD_AUCTION_ITEM, REVERSE_AUCTION_ITEM, SELECTED_AUCTION_ITEM } from '../../Services/BBPS/ApiUrls'; +// import BiddingCard from './Component/BiddingCard'; +// import { CommonActions, useFocusEffect, useNavigation } from '@react-navigation/native'; +// import NavigationString from '../../Constant/NavigationString'; +// import CountdownTimer from '../../Component/Counter/CountdownTimer'; +// import FontsFamily from '../../Constant/FontsFamily'; + +// const StartBidding = () => { +// const SelectedAuction = useSelector((state: any) => state.auction.auction); +// const loginUser = useSelector((state: any) => state.token.token) +// const Navigation: any = useNavigation() +// const [items, setItems] = useState([]); +// const [bidValues, setBidValues] = useState>({}); +// const [allBoolean, setAllBoolean] = useState({ showSuccess: false, showDialog: false, bidPayload: {} }) +// const { subscribe, createRoom, placeBid } = useWebSocketService( +// Variables.webSocketUrl, +// () => console.log('Connected!'), +// (error) => console.log('WebSocket Error:', error), +// loginUser.token, +// ); + +// const getAllAcutionItems = async () => { +// try { +// const payload = { auctionNumber: SelectedAuction.auctionNumber }; +// let auctionItem: any[] = []; + +// if (SelectedAuction.auctionPattern === 'Forward') { +// const res = await apiCall('get', FORWARD_AUCTION_ITEM, {}, payload); +// if (res?.statusCode === 200) auctionItem = res.data || []; +// } else if(SelectedAuction.auctionPattern === 'Reverse') { +// const res = await apiCall('get', REVERSE_AUCTION_ITEM, {}, payload); +// if (res?.statusCode === 200) auctionItem = res.data || []; +// } + +// const selectedRes = await apiCall('get', SELECTED_AUCTION_ITEM, {}, payload); + +// const uniqueArray: number[] = Array.from( +// new Set(selectedRes?.data || []) +// ); + +// const filteredItems = auctionItem.filter(item => +// uniqueArray.includes(item.id) +// ); + + +// const result = await createRoom(SelectedAuction.auctionNumber); + +// subscribe(`/topic/room/${SelectedAuction.auctionNumber}`, data => { +// console.log('🔥 BID UPDATE:', data); +// }); + +// const bidAmountMap2 = new Map(); + +// (result || []).forEach((r: any) => { +// bidAmountMap2.set(r.auctionItemId, { +// bidAmount: r.bidAmount, +// contractorId: r.contractorId, +// }); +// }); + + + +// const bidAmountMap = new Map(); + +// (result || []).forEach((r: any) => { +// bidAmountMap.set(r.auctionItemId, r.bidAmount); +// }); + +// const updatedFilteredItems = filteredItems.map(item => { +// const bidData = bidAmountMap2.get(item.id); +// return { +// ...item, +// bidAmount: bidData?.bidAmount ?? item.auctionStartValueFigure, +// bidAvilable: bidData?.bidAmount ?? 0, +// me: bidData?.contractorId == loginUser.contractorId ? true : false +// }; +// }); + +// const initialBids: Record = {}; +// updatedFilteredItems.forEach(item => { +// initialBids[item.id] = item.bidAmount; +// }); +// setBidValues(initialBids); +// setItems(updatedFilteredItems); + +// } catch (error) { +// console.error('Error fetching auction items:', error); +// } +// }; + +// subscribe(`/topic/room/${SelectedAuction.auctionNumber}`, async (message) => { + +// const result = message[message.length - 1] + +// const updatedBidItem = (prev: any[]) => +// prev.map(item => +// item.id === result.auctionItemId +// ? { ...item, bidAmount: result.bidAmount, me: result.contractorId == loginUser.contractorId ? true : false } +// : item +// ); + +// setItems(updatedBidItem); + +// setBidValues(prev => ({ +// ...prev, +// [result.auctionItemId]: result.bidAmount, +// })); +// try { + +// } catch (err) { +// console.log('JSON parse error:', err); +// } +// }); + +// useEffect(() => { +// getAllAcutionItems(); +// subscribe(`/topic/room/${SelectedAuction.auctionNumber}`, (data) => { }); +// }, []); + + +// useEffect(() => { +// const initial: Record = {}; +// items.forEach((item: any) => { +// initial[item.id] = item.bidAmount + item.bidVariationValue; +// }); +// setBidValues(initial); +// }, []); + +// const handleUpdate = (id: number, val: number) => { +// setBidValues(prev => ({ ...prev, [id]: prev[id] + val })); +// }; + +// const submitBid = async (item: any) => { +// const payload = { +// itemId: item.id, +// bidAmount: bidValues[item.id], +// auctionId: SelectedAuction.auctionId, +// contractorId: loginUser.contractorId, +// fullName: loginUser.fullName, +// roomId: SelectedAuction.auctionNumber, +// }; +// setAllBoolean((prev: any) => ({ ...prev, bidPayload: payload, })); +// Alert.alert( +// 'Confirm Bid', +// `Are you sure you want to place a bid of ₹${payload.bidAmount}?`, +// [ +// { +// text: 'Cancel', +// style: 'cancel', +// }, +// { +// text: 'Submit', +// onPress: () => { +// placeBidSubmit(payload); +// }, +// }, +// ], +// { cancelable: true } +// ); +// }; + +// const placeBidSubmit = async (data: any) => { +// try { +// const result: any = await placeBid(data); + +// if (result?.status && result.data) { +// const updatedBidItem = (prev: any[]) => +// prev.map(item => +// item.id === result.data.auctionItemId +// ? { ...item, bidAmount: result.data.bidAmount, me: result.data?.contractorId == loginUser.contractorId ? true : false } +// : item +// ); + +// // ToastAndroid.show(result.message, ToastAndroid.SHORT) +// // setItems(updatedBidItem); + + +// // setBidValues((prev: any) => ({ +// // ...prev, +// // [result.data.auctionItemId]: { +// // ...prev[result.data.auctionItemId], +// // bidAmount: result.data.bidAmount, +// // }, +// // })); +// getAllAcutionItems() +// } +// } catch (error) { +// console.error('Error placing bid:', error); +// } +// }; + +// useFocusEffect( +// useCallback(() => { +// const onBackPress = () => { +// Alert.alert( +// 'Confirm', +// 'Do you want to go back to Dashboard?', +// [ +// { text: 'Cancel', style: 'cancel' }, +// { +// text: 'Yes', +// onPress: () => { +// Navigation.dispatch( +// CommonActions.reset({ +// index: 0, +// routes: [{ name: NavigationString.Home }], +// }) +// ); +// }, +// }, +// ], +// { cancelable: true } +// ); + +// return true; // block default back action +// }; + +// const subscription = BackHandler.addEventListener( +// 'hardwareBackPress', +// onBackPress +// ); + +// return () => subscription.remove(); +// }, [Navigation]) +// ); +// return ( +// +// +// +// +// {SelectedAuction.deptName} +// + +// +// +// +// + +// item.id.toString()} +// renderItem={({ item, index }) => ( +// handleUpdate(item.id, item.bidVariationValue)} +// onDecrease={() => handleUpdate(item.id, -item.bidVariationValue)} +// onPlaceBid={() => { submitBid(item) }} +// SelectedAuction={SelectedAuction} +// /> +// )} +// contentContainerStyle={{ padding: 16 }} +// /> + +// {allBoolean.showSuccess && ( +// +// +// +// )} +// +// ); +// }; + +// export default StartBidding; + +// const styles = StyleSheet.create({ +// container: { flex: 1, backgroundColor: colors.white }, +// container2: { +// paddingHorizontal: 16, +// paddingTop: 12, +// paddingBottom: 8, +// }, +// title: { +// fontSize: 18, +// fontFamily: FontsFamily.poppinsSemiBold, +// color: colors.black, +// marginBottom: 6, +// // textAlign:'center' +// }, +// timerWrapper: { +// alignItems: 'center', +// }, +// card: { +// backgroundColor: '#FFF', +// borderRadius: 24, +// padding: 20, +// marginBottom: 16, +// borderWidth: 1, +// borderColor: '#E2E8F0', +// overflow: 'hidden', +// ...Platform.select({ ios: { shadowColor: '#000', shadowOpacity: 0.05, shadowRadius: 10 }, android: { elevation: 2 } }), +// }, +// leadingCard: { borderColor: '#22C55E', borderWidth: 2, backgroundColor: '#F0FDF4' }, +// cardHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'flex-start' }, +// headerRight: { flexDirection: 'row', alignItems: 'center', gap: 8 }, +// productName: { fontSize: 18, fontWeight: 'bold', color: '#1E293B' }, +// itemIdText: { fontSize: 12, color: '#64748B', marginTop: 2 }, +// badge: { paddingHorizontal: 10, paddingVertical: 4, borderRadius: 8 }, +// liveBadge: { backgroundColor: '#FEE2E2' }, +// meBadge: { backgroundColor: '#BBF7D0' }, +// badgeText: { fontSize: 10, fontWeight: '900' }, +// liveText: { color: '#EF4444' }, +// meText: { color: '#15803D' }, +// arrow: { fontSize: 10, color: '#94A3B8' }, +// priceRow: { flexDirection: 'row', justifyContent: 'space-between', marginTop: 20 }, +// label: { fontSize: 11, color: '#94A3B8', textTransform: 'uppercase', fontWeight: '600' }, +// mainPrice: { fontSize: 22, fontWeight: '900', color: '#0F172A' }, +// incrementText: { fontSize: 16, fontWeight: '700', color: '#3B82F6' }, +// collapsibleContainer: { overflow: 'hidden' }, +// divider: { height: 1, backgroundColor: '#E2E8F0', marginVertical: 10 }, +// bidLabel: { fontSize: 13, fontWeight: '600', color: '#475569', marginBottom: 10 }, +// stepperContainer: { flexDirection: 'row', gap: 12, marginBottom: 20 }, +// stepBtn: { width: 45, height: 45, backgroundColor: colors.primary, borderRadius: 12, justifyContent: 'center', alignItems: 'center' }, +// disabledBtn: { backgroundColor: '#CBD5E1' }, +// stepText: { color: '#FFF', fontSize: 20, fontWeight: 'bold' }, +// inputBox: { flex: 1, height: 45, backgroundColor: '#F1F5F9', borderRadius: 12, flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }, +// currency: { fontSize: 16, fontWeight: 'bold', color: '#64748B', marginRight: 4 }, +// bidValueText: { fontSize: 18, fontWeight: '800', color: '#0F172A' }, +// submitBtn: { height: 50, backgroundColor: colors.primary, borderRadius: 15, justifyContent: 'center', alignItems: 'center' }, +// submitBtnText: { color: '#FFF', fontSize: 16, fontWeight: 'bold' }, +// overlay: { ...StyleSheet.absoluteFillObject, backgroundColor: 'rgba(255,255,255,0.7)', justifyContent: 'center', alignItems: 'center', zIndex: 99 }, +// }); \ No newline at end of file