Compare commits
No commits in common. "main" and "Intefrating_API_Dashboard" have entirely different histories.
main
...
Intefratin
13
index.html
@ -5,7 +5,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>OnFieldWork.com</title>
|
<title>Marco PMS</title>
|
||||||
|
|
||||||
<meta name="description" content="" />
|
<meta name="description" content="" />
|
||||||
|
|
||||||
@ -46,8 +46,6 @@
|
|||||||
<link rel="stylesheet" href="/assets/vendor/libs/animate-css/animate.css" />
|
<link rel="stylesheet" href="/assets/vendor/libs/animate-css/animate.css" />
|
||||||
<link rel="stylesheet" href="/assets/vendor/libs/sweetalert2/sweetalert2.css" />
|
<link rel="stylesheet" href="/assets/vendor/libs/sweetalert2/sweetalert2.css" />
|
||||||
<link rel="stylesheet" href="/assets/vendor/libs/spinkit/spinkit.css" />
|
<link rel="stylesheet" href="/assets/vendor/libs/spinkit/spinkit.css" />
|
||||||
<link rel="stylesheet" href="/assets/vendor/libs/tagify/tagify.css" />
|
|
||||||
<link rel="stylesheet" href="/assets/vendor/libs/tagify/tagify.js" />
|
|
||||||
|
|
||||||
<!-- Helpers -->
|
<!-- Helpers -->
|
||||||
<script src="/assets/vendor/js/helpers.js"></script>
|
<script src="/assets/vendor/js/helpers.js"></script>
|
||||||
@ -96,15 +94,6 @@
|
|||||||
<script src="/assets/js/main.js"></script>
|
<script src="/assets/js/main.js"></script>
|
||||||
|
|
||||||
<!-- Page JS -->
|
<!-- Page JS -->
|
||||||
<script src="/assets/js/form-wizard-icons.js"></script>
|
|
||||||
<script src="/assets/js/dashboards-analytics.js"></script>
|
|
||||||
|
|
||||||
<!-- Bloack Ui -->
|
|
||||||
<!-- <script src="/assets/js/extended-ui-blockui.js"></script> -->
|
|
||||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
|
||||||
|
|
||||||
<!-- BlockUI core plugin -->
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js"></script>
|
|
||||||
<script src="/assets/js/form-wizard-icons.js"></script>
|
<script src="/assets/js/form-wizard-icons.js"></script>
|
||||||
<script src="/assets/js/dashboards-analytics.js"></script>
|
<script src="/assets/js/dashboards-analytics.js"></script>
|
||||||
|
|
||||||
|
|||||||
119
package-lock.json
generated
@ -809,9 +809,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@jridgewell/source-map": {
|
"node_modules/@jridgewell/source-map": {
|
||||||
"version": "0.3.11",
|
"version": "0.3.6",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
|
||||||
"integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==",
|
"integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -1552,13 +1552,13 @@
|
|||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "24.5.2",
|
"version": "22.13.13",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.13.tgz",
|
||||||
"integrity": "sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ==",
|
"integrity": "sha512-ClsL5nMwKaBRwPcCvH8E7+nU4GxHVx1axNvMZTFHMEfNI7oahimt26P5zjVCRrjiIWj6YFXfE1v3dEp94wLcGQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": "~7.12.0"
|
"undici-types": "~6.20.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/prop-types": {
|
"node_modules/@types/prop-types": {
|
||||||
@ -1835,10 +1835,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/acorn": {
|
"node_modules/acorn": {
|
||||||
"version": "8.15.0",
|
"version": "8.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
|
||||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
|
||||||
"license": "MIT",
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"acorn": "bin/acorn"
|
"acorn": "bin/acorn"
|
||||||
},
|
},
|
||||||
@ -1846,19 +1845,6 @@
|
|||||||
"node": ">=0.4.0"
|
"node": ">=0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/acorn-import-phases": {
|
|
||||||
"version": "1.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz",
|
|
||||||
"integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10.13.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"acorn": "^8.14.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/acorn-jsx": {
|
"node_modules/acorn-jsx": {
|
||||||
"version": "5.3.2",
|
"version": "5.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
|
||||||
@ -2639,9 +2625,9 @@
|
|||||||
"integrity": "sha512-ZpSAUOZ2Izby7qnZluSrAlGgGQzucmFbN0n64dYzocYxnxV5ufurpj3VgEe4cUp7ir9LmeLxNYo8bVnlM8bQHw=="
|
"integrity": "sha512-ZpSAUOZ2Izby7qnZluSrAlGgGQzucmFbN0n64dYzocYxnxV5ufurpj3VgEe4cUp7ir9LmeLxNYo8bVnlM8bQHw=="
|
||||||
},
|
},
|
||||||
"node_modules/enhanced-resolve": {
|
"node_modules/enhanced-resolve": {
|
||||||
"version": "5.18.3",
|
"version": "5.18.1",
|
||||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
|
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz",
|
||||||
"integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==",
|
"integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -2755,9 +2741,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/es-module-lexer": {
|
"node_modules/es-module-lexer": {
|
||||||
"version": "1.7.0",
|
"version": "1.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz",
|
||||||
"integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
|
"integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
@ -3152,9 +3138,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/fast-uri": {
|
"node_modules/fast-uri": {
|
||||||
"version": "3.1.0",
|
"version": "3.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz",
|
||||||
"integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==",
|
"integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "github",
|
"type": "github",
|
||||||
@ -5177,9 +5163,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/schema-utils": {
|
"node_modules/schema-utils": {
|
||||||
"version": "4.3.2",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz",
|
||||||
"integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==",
|
"integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -5581,28 +5567,24 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tapable": {
|
"node_modules/tapable": {
|
||||||
"version": "2.2.3",
|
"version": "2.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
|
||||||
"integrity": "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==",
|
"integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/webpack"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/terser": {
|
"node_modules/terser": {
|
||||||
"version": "5.44.0",
|
"version": "5.39.0",
|
||||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.44.0.tgz",
|
"resolved": "https://registry.npmjs.org/terser/-/terser-5.39.0.tgz",
|
||||||
"integrity": "sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==",
|
"integrity": "sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==",
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"peer": true,
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/source-map": "^0.3.3",
|
"@jridgewell/source-map": "^0.3.3",
|
||||||
"acorn": "^8.15.0",
|
"acorn": "^8.8.2",
|
||||||
"commander": "^2.20.0",
|
"commander": "^2.20.0",
|
||||||
"source-map-support": "~0.5.20"
|
"source-map-support": "~0.5.20"
|
||||||
},
|
},
|
||||||
@ -5795,9 +5777,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/undici-types": {
|
"node_modules/undici-types": {
|
||||||
"version": "7.12.0",
|
"version": "6.20.0",
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
|
||||||
"integrity": "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==",
|
"integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
@ -5925,9 +5907,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/watchpack": {
|
"node_modules/watchpack": {
|
||||||
"version": "2.4.4",
|
"version": "2.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz",
|
||||||
"integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==",
|
"integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -5945,23 +5927,21 @@
|
|||||||
"license": "BSD-2-Clause"
|
"license": "BSD-2-Clause"
|
||||||
},
|
},
|
||||||
"node_modules/webpack": {
|
"node_modules/webpack": {
|
||||||
"version": "5.101.3",
|
"version": "5.98.0",
|
||||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.101.3.tgz",
|
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.98.0.tgz",
|
||||||
"integrity": "sha512-7b0dTKR3Ed//AD/6kkx/o7duS8H3f1a4w3BYpIriX4BzIhjkn4teo05cptsxvLesHFKK5KObnadmCHBwGc+51A==",
|
"integrity": "sha512-UFynvx+gM44Gv9qFgj0acCQK2VE1CtdfwFdimkapco3hlPCJ/zeq73n2yVKimVbtm+TnApIugGhLJnkU6gjYXA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/eslint-scope": "^3.7.7",
|
"@types/eslint-scope": "^3.7.7",
|
||||||
"@types/estree": "^1.0.8",
|
"@types/estree": "^1.0.6",
|
||||||
"@types/json-schema": "^7.0.15",
|
|
||||||
"@webassemblyjs/ast": "^1.14.1",
|
"@webassemblyjs/ast": "^1.14.1",
|
||||||
"@webassemblyjs/wasm-edit": "^1.14.1",
|
"@webassemblyjs/wasm-edit": "^1.14.1",
|
||||||
"@webassemblyjs/wasm-parser": "^1.14.1",
|
"@webassemblyjs/wasm-parser": "^1.14.1",
|
||||||
"acorn": "^8.15.0",
|
"acorn": "^8.14.0",
|
||||||
"acorn-import-phases": "^1.0.3",
|
|
||||||
"browserslist": "^4.24.0",
|
"browserslist": "^4.24.0",
|
||||||
"chrome-trace-event": "^1.0.2",
|
"chrome-trace-event": "^1.0.2",
|
||||||
"enhanced-resolve": "^5.17.3",
|
"enhanced-resolve": "^5.17.1",
|
||||||
"es-module-lexer": "^1.2.1",
|
"es-module-lexer": "^1.2.1",
|
||||||
"eslint-scope": "5.1.1",
|
"eslint-scope": "5.1.1",
|
||||||
"events": "^3.2.0",
|
"events": "^3.2.0",
|
||||||
@ -5971,11 +5951,11 @@
|
|||||||
"loader-runner": "^4.2.0",
|
"loader-runner": "^4.2.0",
|
||||||
"mime-types": "^2.1.27",
|
"mime-types": "^2.1.27",
|
||||||
"neo-async": "^2.6.2",
|
"neo-async": "^2.6.2",
|
||||||
"schema-utils": "^4.3.2",
|
"schema-utils": "^4.3.0",
|
||||||
"tapable": "^2.1.1",
|
"tapable": "^2.1.1",
|
||||||
"terser-webpack-plugin": "^5.3.11",
|
"terser-webpack-plugin": "^5.3.11",
|
||||||
"watchpack": "^2.4.1",
|
"watchpack": "^2.4.1",
|
||||||
"webpack-sources": "^3.3.3"
|
"webpack-sources": "^3.2.3"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"webpack": "bin/webpack.js"
|
"webpack": "bin/webpack.js"
|
||||||
@ -5994,22 +5974,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/webpack-sources": {
|
"node_modules/webpack-sources": {
|
||||||
"version": "3.3.3",
|
"version": "3.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
|
||||||
"integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==",
|
"integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10.13.0"
|
"node": ">=10.13.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/webpack/node_modules/@types/estree": {
|
|
||||||
"version": "1.0.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
|
||||||
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true
|
|
||||||
},
|
|
||||||
"node_modules/webpack/node_modules/eslint-scope": {
|
"node_modules/webpack/node_modules/eslint-scope": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
|
||||||
|
|||||||
@ -1,458 +1,8 @@
|
|||||||
:root,
|
:root,
|
||||||
[data-bs-theme="light"] {
|
[data-bs-theme="light"] {
|
||||||
--bs-nav-link-font-size: 0.7375rem;
|
--bs-nav-link-font-size: 0.7375rem;
|
||||||
--bg-border-color :#f8f6f6
|
|
||||||
}
|
|
||||||
.offcanvas.offcanvas-wide {
|
|
||||||
width: 700px !important; /* adjust as needed */
|
|
||||||
}
|
|
||||||
.sticky-section {
|
|
||||||
position: sticky;
|
|
||||||
top: var(--sticky-top, 0px) !important;
|
|
||||||
z-index: 1025;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ===========================% Background_Colors %========================================================== */
|
|
||||||
.bg-light-primary {
|
|
||||||
background-color: color-mix(in srgb, var(--bs-primary) 10.4%, transparent);
|
|
||||||
border:var(--bs-primary-border-subtle)
|
|
||||||
}
|
|
||||||
.bg-light-secondary {
|
|
||||||
background-color: color-mix(in srgb, var(--bs-secondary) 10.4%, transparent);
|
|
||||||
}
|
|
||||||
.bg-light-danger {
|
|
||||||
background-color: color-mix(in srgb, var(--bs-danger) 10.4%, transparent);
|
|
||||||
}
|
|
||||||
.bg-light-success {
|
|
||||||
background-color: color-mix(in srgb, var(--bs-success) 10.4%, transparent);
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-light-info {
|
|
||||||
background-color: color-mix(in srgb, var(--bs-info) 10.4%, transparent);
|
|
||||||
}
|
|
||||||
.bg-light-warning {
|
|
||||||
background-color: color-mix(in srgb, var(--bs-warning) 10.4%, transparent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-header {
|
.card-header {
|
||||||
padding: 0.5rem var(--bs-card-cap-padding-x);
|
padding: 0.5rem var(--bs-card-cap-padding-x);
|
||||||
}
|
}
|
||||||
.table_header_border {
|
|
||||||
border-bottom:2px solid var(--bs-table-border-color) ;
|
|
||||||
}
|
|
||||||
.text-gary-80 {
|
|
||||||
color:var(--bs-gray-500)
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-royalblue{
|
|
||||||
color: #1796e3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-md {
|
|
||||||
font-size: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-md-b {
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
.stepper-container {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.timeline-horizontal {
|
|
||||||
position: relative;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.timeline-item {
|
|
||||||
position: relative;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.timeline-point {
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: #dee2e6;
|
|
||||||
color: #6c757d;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
font-weight: 600;
|
|
||||||
z-index: 2;
|
|
||||||
position: relative;
|
|
||||||
padding: 3px;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.timeline-point.completed {
|
|
||||||
background-color: var(--bs-success);
|
|
||||||
color: #fff;
|
|
||||||
box-shadow: 0 0 5px rgba(25, 135, 84, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.timeline-point.failed {
|
|
||||||
background-color: var(--bs-danger);
|
|
||||||
color: #fff;
|
|
||||||
box-shadow: 0 0 5px rgba(220, 53, 69, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.timeline-point.active {
|
|
||||||
background-color: var(--bs-info);
|
|
||||||
color: #fff;
|
|
||||||
transform: scale(1.15);
|
|
||||||
box-shadow: 0 0 6px rgba(13, 202, 240, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.timeline-line-horizontal {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
top: 10px;
|
|
||||||
left: 50%;
|
|
||||||
width: 100%;
|
|
||||||
height: 2px;
|
|
||||||
background-color: #dee2e6;
|
|
||||||
z-index: 1;
|
|
||||||
transition: background-color 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make line green for completed sections */
|
|
||||||
.timeline-item.completed ~ .timeline-line-horizontal {
|
|
||||||
background-color: var(--bs-success);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Optional: subtle pulse for active step */
|
|
||||||
.timeline-point.active::after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
width: 25px;
|
|
||||||
height: 25px;
|
|
||||||
border-radius: 50%;
|
|
||||||
border: 2px solid var(--bs-info);
|
|
||||||
animation: pulse 1.5s infinite;
|
|
||||||
opacity: 0.6;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes pulse {
|
|
||||||
0% {
|
|
||||||
transform: scale(1);
|
|
||||||
opacity: 0.6;
|
|
||||||
}
|
|
||||||
70% {
|
|
||||||
transform: scale(1.5);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: scale(1);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.text-xxs { font-size: 0.55rem; } /* 8px */
|
|
||||||
.text-xs { font-size: 0.75rem; } /* 12px */
|
|
||||||
.text-sm { font-size: 0.875rem; } /* 14px */
|
|
||||||
.text-base { font-size: 1rem; } /* 16px */
|
|
||||||
.text-lg { font-size: 1.125rem; } /* 18px */
|
|
||||||
.text-xl { font-size: 1.25rem; } /* 20px */
|
|
||||||
.text-2xl { font-size: 1.5rem; } /* 24px */
|
|
||||||
.text-3xl { font-size: 1.875rem; } /* 30px */
|
|
||||||
.text-4xl { font-size: 2.25rem; } /* 36px */
|
|
||||||
.text-5xl { font-size: 3rem; } /* 48px */
|
|
||||||
.text-6xl { font-size: 3.75rem; } /* 60px */
|
|
||||||
.text-7xl { font-size: 4.5rem; } /* 72px */
|
|
||||||
.text-8xl { font-size: 6rem; } /* 96px */
|
|
||||||
.text-9xl { font-size: 8rem; } /* 128px */
|
|
||||||
|
|
||||||
|
|
||||||
/* */
|
|
||||||
|
|
||||||
.w-0 { width: 0px; }
|
|
||||||
.w-px { width: 1px; }
|
|
||||||
.w-1 { width: 0.25rem; } /* 4px */
|
|
||||||
.w-2 { width: 0.5rem; } /* 8px */
|
|
||||||
.w-3 { width: 0.75rem; } /* 12px */
|
|
||||||
.w-4 { width: 1rem; } /* 16px */
|
|
||||||
.w-5 { width: 1.25rem; } /* 20px */
|
|
||||||
.w-6 { width: 1.5rem; } /* 24px */
|
|
||||||
.w-8 { width: 2rem; } /* 32px */
|
|
||||||
.w-10 { width: 2.5rem; } /* 40px */
|
|
||||||
.w-12 { width: 3rem; } /* 48px */
|
|
||||||
.w-16 { width: 4rem; } /* 64px */
|
|
||||||
.w-20 { width: 5rem; } /* 80px */
|
|
||||||
.w-24 { width: 6rem; } /* 96px */
|
|
||||||
.w-32 { width: 8rem; } /* 128px */
|
|
||||||
.w-40 { width: 10rem; } /* 160px */
|
|
||||||
.w-48 { width: 12rem; } /* 192px */
|
|
||||||
.w-56 { width: 14rem; } /* 224px */
|
|
||||||
.w-64 { width: 16rem; } /* 256px */
|
|
||||||
.w-auto { width: auto; }
|
|
||||||
.w-full { width: 100%; }
|
|
||||||
.w-screen{ width: 100vw; }
|
|
||||||
.w-min { width: min-content; }
|
|
||||||
.w-max { width: max-content; }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.h-0 { height: 0px; }
|
|
||||||
.h-px { height: 1px; }
|
|
||||||
.h-1 { height: 0.25rem; } /* 4px */
|
|
||||||
.h-2 { height: 0.5rem; } /* 8px */
|
|
||||||
.h-3 { height: 0.75rem; } /* 12px */
|
|
||||||
.h-4 { height: 1rem; } /* 16px */
|
|
||||||
.h-5 { height: 1.25rem; } /* 20px */
|
|
||||||
.h-6 { height: 1.5rem; } /* 24px */
|
|
||||||
.h-8 { height: 2rem; } /* 32px */
|
|
||||||
.h-10 { height: 2.5rem; } /* 40px */
|
|
||||||
.h-12 { height: 3rem; } /* 48px */
|
|
||||||
.h-16 { height: 4rem; } /* 64px */
|
|
||||||
.h-20 { height: 5rem; } /* 80px */
|
|
||||||
.h-24 { height: 6rem; } /* 96px */
|
|
||||||
.h-32 { height: 8rem; } /* 128px */
|
|
||||||
.h-40 { height: 10rem; } /* 160px */
|
|
||||||
.h-48 { height: 12rem; } /* 192px */
|
|
||||||
.h-56 { height: 14rem; } /* 224px */
|
|
||||||
.h-64 { height: 16rem; } /* 256px */
|
|
||||||
.h-auto { height: auto; }
|
|
||||||
.h-full { height: 100%; }
|
|
||||||
.h-screen{ height: 100vh; }
|
|
||||||
.h-min { height: min-content; }
|
|
||||||
.h-max { height: max-content; }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ==========================
|
|
||||||
Base Font Sizes (mobile first)
|
|
||||||
========================== */
|
|
||||||
.text-xxs { font-size: 0.55rem; } /* 8px */
|
|
||||||
.text-xs { font-size: 0.75rem; } /* 12px */
|
|
||||||
.text-sm { font-size: 0.875rem; } /* 14px */
|
|
||||||
.text-base{ font-size: 1rem; } /* 16px */
|
|
||||||
.text-lg { font-size: 1.125rem; } /* 18px */
|
|
||||||
.text-xl { font-size: 1.25rem; } /* 20px */
|
|
||||||
.text-2xl { font-size: 1.5rem; } /* 24px */
|
|
||||||
.text-3xl { font-size: 1.875rem; } /* 30px */
|
|
||||||
.text-4xl { font-size: 2.25rem; } /* 36px */
|
|
||||||
.text-5xl { font-size: 3rem; } /* 48px */
|
|
||||||
.text-6xl { font-size: 3.75rem; } /* 60px */
|
|
||||||
.text-7xl { font-size: 4.5rem; } /* 72px */
|
|
||||||
.text-8xl { font-size: 6rem; } /* 96px */
|
|
||||||
.text-9xl { font-size: 8rem; } /* 128px */
|
|
||||||
|
|
||||||
/* ==========================
|
|
||||||
Base Heights
|
|
||||||
========================== */
|
|
||||||
.h-0 { height: 0; }
|
|
||||||
.h-px { height: 1px; }
|
|
||||||
.h-1 { height: 0.25rem; } /* 4px */
|
|
||||||
.h-2 { height: 0.5rem; } /* 8px */
|
|
||||||
.h-3 { height: 0.75rem; } /* 12px */
|
|
||||||
.h-4 { height: 1rem; } /* 16px */
|
|
||||||
.h-5 { height: 1.25rem; } /* 20px */
|
|
||||||
.h-6 { height: 1.5rem; } /* 24px */
|
|
||||||
.h-8 { height: 2rem; } /* 32px */
|
|
||||||
.h-10 { height: 2.5rem; } /* 40px */
|
|
||||||
.h-12 { height: 3rem; } /* 48px */
|
|
||||||
.h-16 { height: 4rem; } /* 64px */
|
|
||||||
.h-20 { height: 5rem; } /* 80px */
|
|
||||||
.h-24 { height: 6rem; } /* 96px */
|
|
||||||
.h-32 { height: 8rem; } /* 128px */
|
|
||||||
.h-40 { height: 10rem; } /* 160px */
|
|
||||||
.h-48 { height: 12rem; } /* 192px */
|
|
||||||
.h-56 { height: 14rem; } /* 224px */
|
|
||||||
.h-64 { height: 16rem; } /* 256px */
|
|
||||||
.h-70 { height: 20rem; } /* 256px */
|
|
||||||
.h-74 { max-height: 35rem; } /* 256px */
|
|
||||||
.h-full { height: 100%; }
|
|
||||||
|
|
||||||
.h-screen{ height: 100vh; }
|
|
||||||
|
|
||||||
/* ==========================
|
|
||||||
Base Widths
|
|
||||||
========================== */
|
|
||||||
.w-0 { width: 0; }
|
|
||||||
.w-px { width: 1px; }
|
|
||||||
.w-1 { width: 0.25rem; }
|
|
||||||
.w-2 { width: 0.5rem; }
|
|
||||||
.w-3 { width: 0.75rem; }
|
|
||||||
.w-4 { width: 1rem; }
|
|
||||||
.w-5 { width: 1.25rem; }
|
|
||||||
.w-6 { width: 1.5rem; }
|
|
||||||
.w-8 { width: 2rem; }
|
|
||||||
.w-10 { width: 2.5rem; }
|
|
||||||
.w-12 { width: 3rem; }
|
|
||||||
.w-16 { width: 4rem; }
|
|
||||||
.w-20 { width: 5rem; }
|
|
||||||
.w-24 { width: 6rem; }
|
|
||||||
.w-32 { width: 8rem; }
|
|
||||||
.w-40 { width: 10rem; }
|
|
||||||
.w-48 { width: 12rem; }
|
|
||||||
.w-56 { width: 14rem; }
|
|
||||||
.w-64 { width: 16rem; }
|
|
||||||
.w-full { width: 100%; }
|
|
||||||
.w-screen{ width: 100vw; }
|
|
||||||
|
|
||||||
/* ==========================
|
|
||||||
Responsive Variants
|
|
||||||
========================== */
|
|
||||||
@media (min-width: 576px) { /* sm */
|
|
||||||
/* Font */
|
|
||||||
.text-xxs-sm { font-size: 0.55rem; }
|
|
||||||
.text-xs-sm { font-size: 0.75rem; }
|
|
||||||
.text-sm-sm { font-size: 0.875rem; }
|
|
||||||
.text-base-sm{ font-size: 1rem; }
|
|
||||||
.text-lg-sm { font-size: 1.125rem; }
|
|
||||||
.text-xl-sm { font-size: 1.25rem; }
|
|
||||||
.text-2xl-sm{ font-size: 1.5rem; }
|
|
||||||
|
|
||||||
/* Height */
|
|
||||||
.h-1-sm{ height: 0.25rem; }
|
|
||||||
.h-2-sm{ height: 0.5rem; }
|
|
||||||
.h-3-sm{ height: 0.75rem; }
|
|
||||||
.h-4-sm{ height: 1rem; }
|
|
||||||
.h-5-sm{ height: 1.25rem; }
|
|
||||||
.h-6-sm{ height: 1.5rem; }
|
|
||||||
.h-8-sm{ height: 2rem; }
|
|
||||||
.h-10-sm{ height: 2.5rem; }
|
|
||||||
|
|
||||||
/* Width */
|
|
||||||
.w-1-sm{ width: 0.25rem; }
|
|
||||||
.w-2-sm{ width: 0.5rem; }
|
|
||||||
.w-3-sm{ width: 0.75rem; }
|
|
||||||
.w-4-sm{ width: 1rem; }
|
|
||||||
.w-5-sm{ width: 1.25rem; }
|
|
||||||
.w-6-sm{ width: 1.5rem; }
|
|
||||||
.w-8-sm{ width: 2rem; }
|
|
||||||
.w-10-sm{ width: 2.5rem; }
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 768px) { /* md */
|
|
||||||
/* Font */
|
|
||||||
.text-xxs-md { font-size: 0.55rem; }
|
|
||||||
.text-xs-md { font-size: 0.75rem; }
|
|
||||||
.text-sm-md { font-size: 0.875rem; }
|
|
||||||
.text-base-md{ font-size: 1rem; }
|
|
||||||
.text-lg-md { font-size: 1.125rem; }
|
|
||||||
.text-xl-md { font-size: 1.25rem; }
|
|
||||||
.text-2xl-md{ font-size: 1.5rem; }
|
|
||||||
|
|
||||||
/* Height */
|
|
||||||
.h-1-md{ height: 0.25rem; }
|
|
||||||
.h-2-md{ height: 0.5rem; }
|
|
||||||
.h-3-md{ height: 0.75rem; }
|
|
||||||
.h-4-md{ height: 1rem; }
|
|
||||||
.h-5-md{ height: 1.25rem; }
|
|
||||||
.h-6-md{ height: 1.5rem; }
|
|
||||||
.h-8-md{ height: 2rem; }
|
|
||||||
.h-10-md{ height: 2.5rem; }
|
|
||||||
|
|
||||||
/* Width */
|
|
||||||
.w-1-md{ width: 0.25rem; }
|
|
||||||
.w-2-md{ width: 0.5rem; }
|
|
||||||
.w-3-md{ width: 0.75rem; }
|
|
||||||
.w-4-md{ width: 1rem; }
|
|
||||||
.w-5-md{ width: 1.25rem; }
|
|
||||||
.w-6-md{ width: 1.5rem; }
|
|
||||||
.w-8-md{ width: 2rem; }
|
|
||||||
.w-10-md{ width: 2.5rem; }
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 992px) { /* lg */
|
|
||||||
/* Font */
|
|
||||||
.text-xxs-lg { font-size: 0.55rem; }
|
|
||||||
.text-xs-lg { font-size: 0.75rem; }
|
|
||||||
.text-sm-lg { font-size: 0.875rem; }
|
|
||||||
.text-base-lg{ font-size: 1rem; }
|
|
||||||
.text-lg-lg { font-size: 1.125rem; }
|
|
||||||
.text-xl-lg { font-size: 1.25rem; }
|
|
||||||
.text-2xl-lg{ font-size: 1.5rem; }
|
|
||||||
|
|
||||||
/* Height */
|
|
||||||
.h-1-lg{ height: 0.25rem; }
|
|
||||||
.h-2-lg{ height: 0.5rem; }
|
|
||||||
.h-3-lg{ height: 0.75rem; }
|
|
||||||
.h-4-lg{ height: 1rem; }
|
|
||||||
.h-5-lg{ height: 1.25rem; }
|
|
||||||
.h-6-lg{ height: 1.5rem; }
|
|
||||||
.h-8-lg{ height: 2rem; }
|
|
||||||
.h-10-lg{ height: 2.5rem; }
|
|
||||||
|
|
||||||
/* Width */
|
|
||||||
.w-1-lg{ width: 0.25rem; }
|
|
||||||
.w-2-lg{ width: 0.5rem; }
|
|
||||||
.w-3-lg{ width: 0.75rem; }
|
|
||||||
.w-4-lg{ width: 1rem; }
|
|
||||||
.w-5-lg{ width: 1.25rem; }
|
|
||||||
.w-6-lg{ width: 1.5rem; }
|
|
||||||
.w-8-lg{ width: 2rem; }
|
|
||||||
.w-10-lg{ width: 2.5rem; }
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1200px) { /* xl */
|
|
||||||
/* Font */
|
|
||||||
.text-xxs-xl { font-size: 0.55rem; }
|
|
||||||
.text-xs-xl { font-size: 0.75rem; }
|
|
||||||
.text-sm-xl { font-size: 0.875rem; }
|
|
||||||
.text-base-xl{ font-size: 1rem; }
|
|
||||||
.text-lg-xl { font-size: 1.125rem; }
|
|
||||||
.text-xl-xl { font-size: 1.25rem; }
|
|
||||||
.text-2xl-xl{ font-size: 1.5rem; }
|
|
||||||
|
|
||||||
/* Height */
|
|
||||||
.h-1-xl{ height: 0.25rem; }
|
|
||||||
.h-2-xl{ height: 0.5rem; }
|
|
||||||
.h-3-xl{ height: 0.75rem; }
|
|
||||||
.h-4-xl{ height: 1rem; }
|
|
||||||
.h-5-xl{ height: 1.25rem; }
|
|
||||||
.h-6-xl{ height: 1.5rem; }
|
|
||||||
.h-8-xl{ height: 2rem; }
|
|
||||||
.h-10-xl{ height: 2.5rem; }
|
|
||||||
|
|
||||||
/* Width */
|
|
||||||
.w-1-xl{ width: 0.25rem; }
|
|
||||||
.w-2-xl{ width: 0.5rem; }
|
|
||||||
.w-3-xl{ width: 0.75rem; }
|
|
||||||
.w-4-xl{ width: 1rem; }
|
|
||||||
.w-5-xl{ width: 1.25rem; }
|
|
||||||
.w-6-xl{ width: 1.5rem; }
|
|
||||||
.w-8-xl{ width: 2rem; }
|
|
||||||
.w-10-xl{ width: 2.5rem; }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------Text------------------------- */
|
|
||||||
@media (min-width: 576px) {
|
|
||||||
.fs-sm-1 { font-size: calc(1.3rem + 1.6vw) !important; }
|
|
||||||
.fs-sm-2 { font-size: calc(1.2rem + 1.2vw) !important; }
|
|
||||||
.fs-sm-3 { font-size: calc(1.1rem + 0.8vw) !important; }
|
|
||||||
.fs-sm-4 { font-size: calc(1rem + 0.5vw) !important; }
|
|
||||||
.fs-sm-5 { font-size: 1.05rem !important; }
|
|
||||||
.fs-sm-6 { font-size: 0.9rem !important; }
|
|
||||||
|
|
||||||
.fs-sm-tiny { font-size: 72% !important; }
|
|
||||||
.fs-sm-big { font-size: 115% !important; }
|
|
||||||
.fs-sm-large { font-size: 155% !important; }
|
|
||||||
.fs-sm-xlarge { font-size: 175% !important; }
|
|
||||||
.fs-sm-xxlarge { font-size: calc(1.6rem + 3.5vw) !important; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 💻 Medium devices (≥768px) */
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
.fs-md-1 { font-size: calc(1.4125rem + 1.95vw) !important; }
|
|
||||||
.fs-md-2 { font-size: calc(1.3625rem + 1.35vw) !important; }
|
|
||||||
.fs-md-3 { font-size: calc(1.3rem + 0.6vw) !important; }
|
|
||||||
.fs-md-4 { font-size: calc(1.275rem + 0.3vw) !important; }
|
|
||||||
.fs-md-5 { font-size: 1.125rem !important; }
|
|
||||||
.fs-md-6 { font-size: 0.9375rem !important; }
|
|
||||||
|
|
||||||
.fs-md-tiny { font-size: 70% !important; }
|
|
||||||
.fs-md-big { font-size: 112% !important; }
|
|
||||||
.fs-md-large { font-size: 150% !important; }
|
|
||||||
.fs-md-xlarge { font-size: 170% !important; }
|
|
||||||
.fs-md-xxlarge { font-size: calc(1.725rem + 5.7vw) !important; }
|
|
||||||
}
|
|
||||||
|
|||||||
@ -30,6 +30,11 @@
|
|||||||
width: 45px;
|
width: 45px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.app-brand-logo-border {
|
||||||
|
border: 1px solid #d5d5d5;
|
||||||
|
}
|
||||||
.app-brand-text {
|
.app-brand-text {
|
||||||
font-size: 1.75rem;
|
font-size: 1.75rem;
|
||||||
letter-spacing: -0.5px;
|
letter-spacing: -0.5px;
|
||||||
@ -160,9 +165,10 @@ thead tr {
|
|||||||
|
|
||||||
.app-brand-logo-login {
|
.app-brand-logo-login {
|
||||||
max-width: 50px; /* default for mobile */
|
max-width: 50px; /* default for mobile */
|
||||||
height: auto; /* keep aspect ratio */
|
height: auto; /* keep aspect ratio */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Tablet and up (≥768px) */
|
/* Tablet and up (≥768px) */
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
.app-brand-logo-login {
|
.app-brand-logo-login {
|
||||||
@ -176,3 +182,4 @@ thead tr {
|
|||||||
max-width: 80px;
|
max-width: 80px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
|
||||||
<svg width="800px" height="800px" viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<rect width="120" height="120" fill="#EFF1F3"/>
|
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M33.2503 38.4816C33.2603 37.0472 34.4199 35.8864 35.8543 35.875H83.1463C84.5848 35.875 85.7503 37.0431 85.7503 38.4816V80.5184C85.7403 81.9528 84.5807 83.1136 83.1463 83.125H35.8543C34.4158 83.1236 33.2503 81.957 33.2503 80.5184V38.4816ZM80.5006 41.1251H38.5006V77.8751L62.8921 53.4783C63.9172 52.4536 65.5788 52.4536 66.6039 53.4783L80.5006 67.4013V41.1251ZM43.75 51.6249C43.75 54.5244 46.1005 56.8749 49 56.8749C51.8995 56.8749 54.25 54.5244 54.25 51.6249C54.25 48.7254 51.8995 46.3749 49 46.3749C46.1005 46.3749 43.75 48.7254 43.75 51.6249Z" fill="#687787"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 888 B |
|
Before Width: | Height: | Size: 7.2 KiB |
21
public/assets/vendor/css/core.css
vendored
@ -76,7 +76,6 @@
|
|||||||
--bs-dark-border-subtle: #bfc0c6;
|
--bs-dark-border-subtle: #bfc0c6;
|
||||||
--bs-white-rgb: 255, 255, 255;
|
--bs-white-rgb: 255, 255, 255;
|
||||||
--bs-black-rgb: 34, 48, 62;
|
--bs-black-rgb: 34, 48, 62;
|
||||||
--bs-font-roboto:"Segoe UI", Roboto, "sans-serif",
|
|
||||||
--bs-font-sans-serif: "Public Sans", -apple-system, blinkmacsystemfont,
|
--bs-font-sans-serif: "Public Sans", -apple-system, blinkmacsystemfont,
|
||||||
"Segoe UI", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans",
|
"Segoe UI", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans",
|
||||||
"Helvetica Neue", sans-serif;
|
"Helvetica Neue", sans-serif;
|
||||||
@ -89,7 +88,7 @@
|
|||||||
);
|
);
|
||||||
--bs-root-font-size: 16px;
|
--bs-root-font-size: 16px;
|
||||||
--bs-body-font-family: var(--bs-font-sans-serif);
|
--bs-body-font-family: var(--bs-font-sans-serif);
|
||||||
--bs-body-font-size: 0.85rem;
|
--bs-body-font-size: 0.8375rem;
|
||||||
--bs-body-font-weight: 400;
|
--bs-body-font-weight: 400;
|
||||||
--bs-body-line-height: 1.375;
|
--bs-body-line-height: 1.375;
|
||||||
--bs-body-color: #646e78;
|
--bs-body-color: #646e78;
|
||||||
@ -9060,7 +9059,7 @@ img[data-app-light-img][data-app-dark-img] {
|
|||||||
}
|
}
|
||||||
.table th {
|
.table th {
|
||||||
color: var(--bs-heading-color);
|
color: var(--bs-heading-color);
|
||||||
font-size: 0.8025rem;
|
font-size: 0.8125rem;
|
||||||
letter-spacing: 0.2px;
|
letter-spacing: 0.2px;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
@ -18614,10 +18613,6 @@ li:not(:first-child) .dropdown-item,
|
|||||||
min-height: 70vh !important;
|
min-height: 70vh !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-min-h{
|
|
||||||
min-height: 60vh !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.flex-fill {
|
.flex-fill {
|
||||||
flex: 1 1 auto !important;
|
flex: 1 1 auto !important;
|
||||||
}
|
}
|
||||||
@ -20345,7 +20340,7 @@ li:not(:first-child) .dropdown-item,
|
|||||||
}
|
}
|
||||||
|
|
||||||
.fs-6 {
|
.fs-6 {
|
||||||
font-size: 0.8375rem !important;
|
font-size: 0.9375rem !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fs-tiny {
|
.fs-tiny {
|
||||||
@ -32560,7 +32555,9 @@ body:not(.modal-open) .layout-content-navbar .layout-navbar {
|
|||||||
.bg-blue {
|
.bg-blue {
|
||||||
background-color:var(--bs-blue)
|
background-color:var(--bs-blue)
|
||||||
}
|
}
|
||||||
|
.text-blue{
|
||||||
|
color:var(--bs-blue)
|
||||||
|
}
|
||||||
.bg-indigo {
|
.bg-indigo {
|
||||||
background-color:var(--bs-indigo)
|
background-color:var(--bs-indigo)
|
||||||
}
|
}
|
||||||
@ -32572,10 +32569,4 @@ body:not(.modal-open) .layout-content-navbar .layout-navbar {
|
|||||||
}
|
}
|
||||||
.text-red{
|
.text-red{
|
||||||
color:var(--bs-red)
|
color:var(--bs-red)
|
||||||
}
|
|
||||||
.text-blue{
|
|
||||||
color:var(--bs-blue)
|
|
||||||
}
|
|
||||||
.text-green{
|
|
||||||
color:var(--bs-green)
|
|
||||||
}
|
}
|
||||||
879
public/assets/vendor/libs/tagify/tagify.css
vendored
@ -1,879 +0,0 @@
|
|||||||
@charset "UTF-8";
|
|
||||||
:root {
|
|
||||||
--tagify-dd-color-primary: rgb(53,149,246);
|
|
||||||
--tagify-dd-bg-color: white;
|
|
||||||
--tagify-dd-item-pad: .3em .5em;
|
|
||||||
--tagify-dd-max-height: 300px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tagify {
|
|
||||||
--tags-disabled-bg: #F1F1F1;
|
|
||||||
--tags-border-color: #DDD;
|
|
||||||
--tags-hover-border-color: #CCC;
|
|
||||||
--tags-focus-border-color: #3595f6;
|
|
||||||
--tag-border-radius: 3px;
|
|
||||||
--tag-bg: rgba(167, 172, 178, 0.5);
|
|
||||||
--tag-hover: #D3E2E2;
|
|
||||||
--tag-text-color: black;
|
|
||||||
--tag-text-color--edit: black;
|
|
||||||
--tag-pad: 0.3em 0.5em;
|
|
||||||
--tag-inset-shadow-size: 2em;
|
|
||||||
--tag-invalid-color: #ff3e1d;
|
|
||||||
--tag-invalid-bg: rgba(255, 62, 29, 0.5);
|
|
||||||
--tag--min-width: 1ch;
|
|
||||||
--tag--max-width: auto;
|
|
||||||
--tag-hide-transition: 0.3s;
|
|
||||||
--tag-remove-bg: rgba(255, 62, 29, 0.3);
|
|
||||||
--tag-remove-btn-color: #7a838b;
|
|
||||||
--tag-remove-btn-bg: none;
|
|
||||||
--tag-remove-btn-bg--hover: #ff2804;
|
|
||||||
--input-color: inherit;
|
|
||||||
--placeholder-color: rgba(0, 0, 0, 0.4);
|
|
||||||
--placeholder-color-focus: rgba(0, 0, 0, 0.25);
|
|
||||||
--loader-size: .8em;
|
|
||||||
--readonly-striped: 1;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
border: 1px solid var(--tags-border-color);
|
|
||||||
padding: 0;
|
|
||||||
line-height: 0;
|
|
||||||
cursor: text;
|
|
||||||
outline: none;
|
|
||||||
position: relative;
|
|
||||||
box-sizing: border-box;
|
|
||||||
transition: 0.1s;
|
|
||||||
}
|
|
||||||
@keyframes tags--bump {
|
|
||||||
30% {
|
|
||||||
transform: scale(1.2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes rotateLoader {
|
|
||||||
to {
|
|
||||||
transform: rotate(1turn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.tagify:hover:not(.tagify--focus):not(.tagify--invalid) {
|
|
||||||
--tags-border-color: var(--tags-hover-border-color);
|
|
||||||
}
|
|
||||||
.tagify[disabled] {
|
|
||||||
background: var(--tags-disabled-bg);
|
|
||||||
filter: saturate(0);
|
|
||||||
opacity: 0.5;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
.tagify[readonly].tagify--select, .tagify[disabled].tagify--select {
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
.tagify[readonly]:not(.tagify--mix):not(.tagify--select), .tagify[disabled]:not(.tagify--mix):not(.tagify--select) {
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
.tagify[readonly]:not(.tagify--mix):not(.tagify--select) > .tagify__input, .tagify[disabled]:not(.tagify--mix):not(.tagify--select) > .tagify__input {
|
|
||||||
visibility: hidden;
|
|
||||||
width: 0;
|
|
||||||
margin: 5px 0;
|
|
||||||
}
|
|
||||||
.tagify[readonly]:not(.tagify--mix):not(.tagify--select) .tagify__tag > div, .tagify[disabled]:not(.tagify--mix):not(.tagify--select) .tagify__tag > div {
|
|
||||||
padding: var(--tag-pad);
|
|
||||||
}
|
|
||||||
.tagify[readonly]:not(.tagify--mix):not(.tagify--select) .tagify__tag > div::before, .tagify[disabled]:not(.tagify--mix):not(.tagify--select) .tagify__tag > div::before {
|
|
||||||
animation: readonlyStyles 1s calc(-1s * (var(--readonly-striped) - 1)) paused;
|
|
||||||
}
|
|
||||||
@keyframes readonlyStyles {
|
|
||||||
0% {
|
|
||||||
background: linear-gradient(45deg, var(--tag-bg) 25%, transparent 25%, transparent 50%, var(--tag-bg) 50%, var(--tag-bg) 75%, transparent 75%, transparent) 0/5px 5px;
|
|
||||||
box-shadow: none;
|
|
||||||
filter: brightness(0.95);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.tagify[readonly] .tagify__tag__removeBtn, .tagify[disabled] .tagify__tag__removeBtn {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.tagify--loading .tagify__input > br:last-child {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.tagify--loading .tagify__input::before {
|
|
||||||
content: none;
|
|
||||||
}
|
|
||||||
.tagify--loading .tagify__input::after {
|
|
||||||
content: "";
|
|
||||||
vertical-align: middle;
|
|
||||||
opacity: 1;
|
|
||||||
width: 0.7em;
|
|
||||||
height: 0.7em;
|
|
||||||
width: var(--loader-size);
|
|
||||||
height: var(--loader-size);
|
|
||||||
min-width: 0;
|
|
||||||
border: 3px solid;
|
|
||||||
border-color: #EEE #BBB #888 transparent;
|
|
||||||
border-radius: 50%;
|
|
||||||
animation: rotateLoader 0.4s infinite linear;
|
|
||||||
content: "" !important;
|
|
||||||
margin: -2px 0 -2px 0.5em;
|
|
||||||
}
|
|
||||||
.tagify--loading .tagify__input:empty::after {
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
.tagify + input,
|
|
||||||
.tagify + textarea {
|
|
||||||
position: absolute !important;
|
|
||||||
left: -9999em !important;
|
|
||||||
transform: scale(0) !important;
|
|
||||||
}
|
|
||||||
.tagify__tag {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
max-width: calc(var(--tag--max-width) - 10px);
|
|
||||||
margin-inline: 5px 0;
|
|
||||||
margin-block: 5px;
|
|
||||||
position: relative;
|
|
||||||
z-index: 1;
|
|
||||||
outline: none;
|
|
||||||
line-height: normal;
|
|
||||||
cursor: default;
|
|
||||||
transition: 0.13s ease-out;
|
|
||||||
}
|
|
||||||
.tagify__tag > div {
|
|
||||||
vertical-align: top;
|
|
||||||
box-sizing: border-box;
|
|
||||||
max-width: 100%;
|
|
||||||
padding: var(--tag-pad);
|
|
||||||
color: var(--tag-text-color);
|
|
||||||
line-height: inherit;
|
|
||||||
border-radius: var(--tag-border-radius);
|
|
||||||
white-space: nowrap;
|
|
||||||
transition: 0.13s ease-out;
|
|
||||||
}
|
|
||||||
.tagify__tag > div > * {
|
|
||||||
white-space: pre-wrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: top;
|
|
||||||
min-width: var(--tag--min-width);
|
|
||||||
max-width: var(--tag--max-width);
|
|
||||||
transition: 0.8s ease, 0.1s color;
|
|
||||||
}
|
|
||||||
.tagify__tag > div > *[contenteditable] {
|
|
||||||
outline: none;
|
|
||||||
user-select: text;
|
|
||||||
cursor: text;
|
|
||||||
margin: -2px;
|
|
||||||
padding: 2px;
|
|
||||||
max-width: 350px;
|
|
||||||
}
|
|
||||||
.tagify__tag > div::before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
border-radius: inherit;
|
|
||||||
inset: var(--tag-bg-inset, 0);
|
|
||||||
z-index: -1;
|
|
||||||
pointer-events: none;
|
|
||||||
transition: 120ms ease;
|
|
||||||
animation: tags--bump 0.3s ease-out 1;
|
|
||||||
box-shadow: 0 0 0 var(--tag-inset-shadow-size) var(--tag-bg) inset;
|
|
||||||
}
|
|
||||||
.tagify__tag:hover:not([readonly]) div::before, .tagify__tag:focus div::before {
|
|
||||||
--tag-bg-inset: -2.5px;
|
|
||||||
--tag-bg: var(--tag-hover);
|
|
||||||
}
|
|
||||||
.tagify__tag--loading {
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
.tagify__tag--loading .tagify__tag__removeBtn {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.tagify__tag--loading::after {
|
|
||||||
--loader-size: .4em;
|
|
||||||
content: "";
|
|
||||||
vertical-align: middle;
|
|
||||||
opacity: 1;
|
|
||||||
width: 0.7em;
|
|
||||||
height: 0.7em;
|
|
||||||
width: var(--loader-size);
|
|
||||||
height: var(--loader-size);
|
|
||||||
min-width: 0;
|
|
||||||
border: 3px solid;
|
|
||||||
border-color: #EEE #BBB #888 transparent;
|
|
||||||
border-radius: 50%;
|
|
||||||
animation: rotateLoader 0.4s infinite linear;
|
|
||||||
margin: 0 0.5em 0 -0.1em;
|
|
||||||
}
|
|
||||||
.tagify__tag--flash div::before {
|
|
||||||
animation: none;
|
|
||||||
}
|
|
||||||
.tagify__tag--hide {
|
|
||||||
width: 0 !important;
|
|
||||||
padding-left: 0;
|
|
||||||
padding-right: 0;
|
|
||||||
margin-left: 0;
|
|
||||||
margin-right: 0;
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0);
|
|
||||||
transition: var(--tag-hide-transition);
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
.tagify__tag--hide > div > * {
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
.tagify__tag.tagify--noAnim > div::before {
|
|
||||||
animation: none;
|
|
||||||
}
|
|
||||||
.tagify__tag.tagify--notAllowed:not(.tagify__tag--editable) div > span {
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
.tagify__tag.tagify--notAllowed:not(.tagify__tag--editable) div::before {
|
|
||||||
--tag-bg: var(--tag-invalid-bg);
|
|
||||||
transition: 0.2s;
|
|
||||||
}
|
|
||||||
.tagify__tag[readonly] .tagify__tag__removeBtn {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.tagify__tag[readonly] > div::before {
|
|
||||||
animation: readonlyStyles 1s calc(-1s * (var(--readonly-striped) - 1)) paused;
|
|
||||||
}
|
|
||||||
@keyframes readonlyStyles {
|
|
||||||
0% {
|
|
||||||
background: linear-gradient(45deg, var(--tag-bg) 25%, transparent 25%, transparent 50%, var(--tag-bg) 50%, var(--tag-bg) 75%, transparent 75%, transparent) 0/5px 5px;
|
|
||||||
box-shadow: none;
|
|
||||||
filter: brightness(0.95);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.tagify__tag--editable > div {
|
|
||||||
color: var(--tag-text-color--edit);
|
|
||||||
}
|
|
||||||
.tagify__tag--editable > div::before {
|
|
||||||
box-shadow: 0 0 0 2px var(--tag-hover) inset !important;
|
|
||||||
}
|
|
||||||
.tagify__tag--editable > .tagify__tag__removeBtn {
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
.tagify__tag--editable > .tagify__tag__removeBtn::after {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateX(100%) translateX(5px);
|
|
||||||
}
|
|
||||||
.tagify__tag--editable.tagify--invalid > div::before {
|
|
||||||
box-shadow: 0 0 0 2px var(--tag-invalid-color) inset !important;
|
|
||||||
}
|
|
||||||
.tagify__tag__removeBtn {
|
|
||||||
order: 5;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
border-radius: 50px;
|
|
||||||
cursor: pointer;
|
|
||||||
font: 14px/1 Arial;
|
|
||||||
background: var(--tag-remove-btn-bg);
|
|
||||||
color: var(--tag-remove-btn-color);
|
|
||||||
width: 14px;
|
|
||||||
height: 14px;
|
|
||||||
margin-inline: auto 4.6666666667px;
|
|
||||||
overflow: hidden;
|
|
||||||
transition: 0.2s ease-out;
|
|
||||||
}
|
|
||||||
.tagify__tag__removeBtn::after {
|
|
||||||
content: "×";
|
|
||||||
transition: 0.3s, color 0s;
|
|
||||||
}
|
|
||||||
.tagify__tag__removeBtn:hover {
|
|
||||||
color: white;
|
|
||||||
background: var(--tag-remove-btn-bg--hover);
|
|
||||||
}
|
|
||||||
.tagify__tag__removeBtn:hover + div > span {
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
.tagify__tag__removeBtn:hover + div::before {
|
|
||||||
box-shadow: 0 0 0 var(--tag-inset-shadow-size) var(--tag-remove-bg, rgba(255, 62, 29, 0.3)) inset !important;
|
|
||||||
transition: box-shadow 0.2s;
|
|
||||||
}
|
|
||||||
.tagify:not(.tagify--mix) .tagify__input br {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.tagify:not(.tagify--mix) .tagify__input * {
|
|
||||||
display: inline;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
.tagify__input {
|
|
||||||
flex-grow: 1;
|
|
||||||
display: inline-block;
|
|
||||||
min-width: 110px;
|
|
||||||
margin: 5px;
|
|
||||||
padding: var(--tag-pad);
|
|
||||||
line-height: normal;
|
|
||||||
position: relative;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
color: var(--input-color);
|
|
||||||
box-sizing: inherit;
|
|
||||||
/* Seems firefox newer versions don't need this any more
|
|
||||||
@supports ( -moz-appearance:none ){
|
|
||||||
&::before{
|
|
||||||
line-height: inherit;
|
|
||||||
position:relative;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
@-moz-document url-prefix() {}
|
|
||||||
.tagify__input:empty::before {
|
|
||||||
position: static;
|
|
||||||
}
|
|
||||||
.tagify__input:focus {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
.tagify__input:focus::before {
|
|
||||||
transition: 0.2s ease-out;
|
|
||||||
opacity: 0;
|
|
||||||
transform: translatex(6px);
|
|
||||||
/* ALL MS BROWSERS: hide placeholder (on focus) otherwise the caret is placed after it, which is weird */
|
|
||||||
/* IE Edge 12+ CSS styles go here */
|
|
||||||
}
|
|
||||||
@supports (-ms-ime-align: auto) {
|
|
||||||
.tagify__input:focus::before {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.tagify__input:focus:empty::before {
|
|
||||||
transition: 0.2s ease-out;
|
|
||||||
opacity: 1;
|
|
||||||
transform: none;
|
|
||||||
color: rgba(0, 0, 0, 0.25);
|
|
||||||
color: var(--placeholder-color-focus);
|
|
||||||
}
|
|
||||||
@-moz-document url-prefix() {
|
|
||||||
.tagify__input:focus:empty::after {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.tagify__input::before {
|
|
||||||
content: attr(data-placeholder);
|
|
||||||
height: 1em;
|
|
||||||
line-height: 1em;
|
|
||||||
margin: auto 0;
|
|
||||||
z-index: 1;
|
|
||||||
color: var(--placeholder-color);
|
|
||||||
white-space: nowrap;
|
|
||||||
pointer-events: none;
|
|
||||||
opacity: 0;
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
.tagify__input::after {
|
|
||||||
content: attr(data-suggest);
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: middle;
|
|
||||||
position: absolute;
|
|
||||||
min-width: calc(100% - 1.5em);
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: pre; /* allows spaces at the beginning */
|
|
||||||
color: var(--tag-text-color);
|
|
||||||
opacity: 0.3;
|
|
||||||
pointer-events: none;
|
|
||||||
max-width: 100px;
|
|
||||||
}
|
|
||||||
.tagify__input .tagify__tag {
|
|
||||||
margin: 0 1px;
|
|
||||||
}
|
|
||||||
.tagify--mix {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.tagify--mix .tagify__input {
|
|
||||||
padding: 5px;
|
|
||||||
margin: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
line-height: 1.5;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.tagify--mix .tagify__input::before {
|
|
||||||
height: auto;
|
|
||||||
display: none;
|
|
||||||
line-height: inherit;
|
|
||||||
}
|
|
||||||
.tagify--mix .tagify__input::after {
|
|
||||||
content: none;
|
|
||||||
}
|
|
||||||
.tagify--select::after {
|
|
||||||
content: ">";
|
|
||||||
opacity: 0.5;
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
font: 16px monospace;
|
|
||||||
line-height: 8px;
|
|
||||||
height: 8px;
|
|
||||||
pointer-events: none;
|
|
||||||
transform: translate(-150%, -50%) scaleX(1.2) rotate(90deg);
|
|
||||||
transition: 0.2s ease-in-out;
|
|
||||||
}
|
|
||||||
.tagify--select[aria-expanded=true]::after {
|
|
||||||
transform: translate(-150%, -50%) rotate(270deg) scaleY(1.2);
|
|
||||||
}
|
|
||||||
.tagify--select .tagify__tag {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 1.8em;
|
|
||||||
bottom: 0;
|
|
||||||
}
|
|
||||||
.tagify--select .tagify__tag div {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.tagify--select .tagify__input {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.tagify--empty .tagify__input::before {
|
|
||||||
transition: 0.2s ease-out;
|
|
||||||
opacity: 1;
|
|
||||||
transform: none;
|
|
||||||
display: inline-block;
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
.tagify--mix .tagify--empty .tagify__input::before {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
.tagify--focus {
|
|
||||||
--tags-border-color: var(--tags-focus-border-color);
|
|
||||||
transition: 0s;
|
|
||||||
}
|
|
||||||
.tagify--invalid {
|
|
||||||
--tags-border-color: #ff3e1d;
|
|
||||||
}
|
|
||||||
.tagify__dropdown {
|
|
||||||
position: absolute;
|
|
||||||
z-index: 9999;
|
|
||||||
transform: translateY(-1px);
|
|
||||||
border-top: 1px solid var(--tagify-dd-color-primary);
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.tagify__dropdown[dir=rtl] {
|
|
||||||
transform: translate(-100%, -1px);
|
|
||||||
}
|
|
||||||
.tagify__dropdown[placement=top] {
|
|
||||||
margin-top: 0;
|
|
||||||
transform: translateY(-100%);
|
|
||||||
}
|
|
||||||
.tagify__dropdown[placement=top] .tagify__dropdown__wrapper {
|
|
||||||
border-top-width: 1.1px;
|
|
||||||
border-bottom-width: 0;
|
|
||||||
}
|
|
||||||
.tagify__dropdown[position=text] {
|
|
||||||
box-shadow: 0 0 0 3px rgba(var(--tagify-dd-color-primary), 0.1);
|
|
||||||
font-size: 0.9em;
|
|
||||||
}
|
|
||||||
.tagify__dropdown[position=text] .tagify__dropdown__wrapper {
|
|
||||||
border-width: 1px;
|
|
||||||
}
|
|
||||||
.tagify__dropdown__wrapper {
|
|
||||||
max-height: var(--tagify-dd-max-height);
|
|
||||||
overflow: hidden;
|
|
||||||
overflow-x: hidden;
|
|
||||||
background: var(--tagify-dd-bg-color);
|
|
||||||
border: 1px solid;
|
|
||||||
border-color: var(--tagify-dd-color-primary);
|
|
||||||
border-bottom-width: 1.5px;
|
|
||||||
border-top-width: 0;
|
|
||||||
box-shadow: 0 2px 4px -2px rgba(0, 0, 0, 0.2);
|
|
||||||
transition: 0.3s cubic-bezier(0.5, 0, 0.3, 1), transform 0.15s;
|
|
||||||
animation: dd-wrapper-show 0s 0.3s forwards;
|
|
||||||
}
|
|
||||||
@keyframes dd-wrapper-show {
|
|
||||||
to {
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.tagify__dropdown__header:empty {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.tagify__dropdown__footer {
|
|
||||||
display: inline-block;
|
|
||||||
margin-top: 0.5em;
|
|
||||||
padding: var(--tagify-dd-item-pad);
|
|
||||||
font-size: 0.7em;
|
|
||||||
font-style: italic;
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
.tagify__dropdown__footer:empty {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.tagify__dropdown--initial .tagify__dropdown__wrapper {
|
|
||||||
max-height: 20px;
|
|
||||||
transform: translateY(-1em);
|
|
||||||
}
|
|
||||||
.tagify__dropdown--initial[placement=top] .tagify__dropdown__wrapper {
|
|
||||||
transform: translateY(2em);
|
|
||||||
}
|
|
||||||
.tagify__dropdown__item {
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: var(--tagify-dd-item-pad);
|
|
||||||
margin: 1px;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
cursor: pointer;
|
|
||||||
border-radius: 2px;
|
|
||||||
position: relative;
|
|
||||||
outline: none;
|
|
||||||
max-height: 60px;
|
|
||||||
max-width: 100%;
|
|
||||||
/* custom hidden transition effect is needed for horizontal-layout suggestions */
|
|
||||||
}
|
|
||||||
.tagify__dropdown__item--active {
|
|
||||||
background: var(--tagify-dd-color-primary);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
.tagify__dropdown__item:active {
|
|
||||||
filter: brightness(105%);
|
|
||||||
}
|
|
||||||
.tagify__dropdown__item--hidden {
|
|
||||||
padding-top: 0;
|
|
||||||
padding-bottom: 0;
|
|
||||||
margin: 0 1px;
|
|
||||||
pointer-events: none;
|
|
||||||
overflow: hidden;
|
|
||||||
max-height: 0;
|
|
||||||
transition: var(--tagify-dd-item--hidden-duration, 0.3s) !important;
|
|
||||||
}
|
|
||||||
.tagify__dropdown__item--hidden > * {
|
|
||||||
transform: translateY(-100%);
|
|
||||||
opacity: 0;
|
|
||||||
transition: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Suggestions items */
|
|
||||||
.tagify__dropdown.users-list {
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
.tagify__dropdown.users-list .addAll {
|
|
||||||
display: block !important;
|
|
||||||
}
|
|
||||||
.tagify__dropdown.users-list .tagify__dropdown__item {
|
|
||||||
padding: 0.5em 0.7em;
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: auto 1fr;
|
|
||||||
gap: 0 1em;
|
|
||||||
grid-template-areas: "avatar name" "avatar email";
|
|
||||||
}
|
|
||||||
.tagify__dropdown.users-list .tagify__dropdown__item__avatar-wrap {
|
|
||||||
grid-area: avatar;
|
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
border-radius: 50%;
|
|
||||||
overflow: hidden;
|
|
||||||
transition: 0.1s ease-out;
|
|
||||||
}
|
|
||||||
.tagify__dropdown.users-list img {
|
|
||||||
width: 100%;
|
|
||||||
vertical-align: top;
|
|
||||||
}
|
|
||||||
.tagify__dropdown.users-list strong {
|
|
||||||
grid-area: name;
|
|
||||||
width: 100%;
|
|
||||||
align-self: center;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
.tagify__dropdown.users-list span {
|
|
||||||
grid-area: email;
|
|
||||||
width: 100%;
|
|
||||||
font-size: 0.9em;
|
|
||||||
opacity: 0.6;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tags items */
|
|
||||||
.tagify__tag {
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
.tagify__tag .tagify__tag__avatar-wrap {
|
|
||||||
width: 22px;
|
|
||||||
height: 22px;
|
|
||||||
white-space: normal;
|
|
||||||
border-radius: 50%;
|
|
||||||
margin-right: 5px;
|
|
||||||
transition: 0.12s ease-out;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
.tagify__tag img {
|
|
||||||
width: 100%;
|
|
||||||
vertical-align: top;
|
|
||||||
}
|
|
||||||
|
|
||||||
[dir=rtl] .tagify__tag .tagify__tag__avatar-wrap {
|
|
||||||
margin-left: 5px;
|
|
||||||
margin-right: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.light-style .tagify__dropdown.users-list .tagify__dropdown__item__avatar-wrap {
|
|
||||||
background: #f5f5f9;
|
|
||||||
}
|
|
||||||
.light-style .tagify__tag .tagify__tag__avatar-wrap {
|
|
||||||
background: #f5f5f9;
|
|
||||||
}
|
|
||||||
.light-style .tagify__dropdown.users-list .addAll {
|
|
||||||
border-bottom: 1px solid #e4e6e8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark-style .tagify__dropdown.users-list .tagify__dropdown__item__avatar-wrap {
|
|
||||||
background: #232333;
|
|
||||||
}
|
|
||||||
.dark-style .tagify__tag .tagify__tag__avatar-wrap {
|
|
||||||
background: #232333;
|
|
||||||
}
|
|
||||||
.dark-style .tagify__dropdown.users-list .addAll {
|
|
||||||
border-bottom: 1px solid #4e4f6c;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tags-inline .tagify__dropdown__wrapper {
|
|
||||||
padding: 0 0.4375rem 0.4375rem 0.4375rem;
|
|
||||||
}
|
|
||||||
.tags-inline .tagify__dropdown__item {
|
|
||||||
display: inline-block;
|
|
||||||
border-radius: 3px;
|
|
||||||
padding: 0.3em 0.5em;
|
|
||||||
margin: 0.4375rem 0.4375rem 0 0;
|
|
||||||
font-size: 0.85em;
|
|
||||||
transition: 0s;
|
|
||||||
}
|
|
||||||
|
|
||||||
[dir=rtl] .tags-inline .tagify__dropdown__item {
|
|
||||||
margin: 0.4375rem 0 0 0.4375rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.light-style .tags-inline .tagify__dropdown__item {
|
|
||||||
border: 1px solid #e4e6e8;
|
|
||||||
color: #646e78;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark-style .tags-inline .tagify__dropdown__item {
|
|
||||||
border: 1px solid #4e4f6c;
|
|
||||||
color: #b2b2c4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tagify-email-list {
|
|
||||||
display: inline-block;
|
|
||||||
min-width: 0;
|
|
||||||
border: none;
|
|
||||||
/* Do not show the "remove tag" (x) button when only a single tag remains */
|
|
||||||
}
|
|
||||||
.tagify-email-list.tagify {
|
|
||||||
padding: 0 !important;
|
|
||||||
padding-bottom: calc(0.4375rem - var(--bs-border-width)) !important;
|
|
||||||
}
|
|
||||||
.tagify-email-list.tagify {
|
|
||||||
padding: 0 !important;
|
|
||||||
padding-bottom: calc(0.4375rem - var(--bs-border-width)) !important;
|
|
||||||
}
|
|
||||||
.tagify-email-list.tagify.tagify--focus {
|
|
||||||
padding-left: 0 !important;
|
|
||||||
}
|
|
||||||
.tagify-email-list .tagify__tag {
|
|
||||||
margin: 0;
|
|
||||||
margin-inline-start: 0 !important;
|
|
||||||
margin-inline-end: 0.625rem !important;
|
|
||||||
margin-bottom: 0.4375rem !important;
|
|
||||||
}
|
|
||||||
.tagify-email-list .tagify__tag > div {
|
|
||||||
padding: 0.21875rem 0.4375rem !important;
|
|
||||||
padding-inline: 0.875rem !important;
|
|
||||||
}
|
|
||||||
.tagify-email-list .tagify__tag:only-of-type > div {
|
|
||||||
padding-inline: 0.4375rem !important;
|
|
||||||
}
|
|
||||||
.tagify-email-list .tagify__tag:only-of-type .tagify__tag__removeBtn {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.tagify-email-list .tagify__tag__removeBtn {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateX(-6px) scale(0.5);
|
|
||||||
margin-left: -3ch;
|
|
||||||
transition: 0.12s;
|
|
||||||
position: absolute;
|
|
||||||
inset-inline-end: 0;
|
|
||||||
}
|
|
||||||
.tagify-email-list .tagify__tag:hover .tagify__tag__removeBtn {
|
|
||||||
transform: none;
|
|
||||||
opacity: 1;
|
|
||||||
margin-left: -1ch;
|
|
||||||
}
|
|
||||||
.tagify-email-list .tagify__input {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tagify__tag > div {
|
|
||||||
border-radius: 50rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
[dir=rtl] .tagify-email-list .tagify__tag {
|
|
||||||
margin: 0 0.4375rem 0.4375rem 0;
|
|
||||||
}
|
|
||||||
[dir=rtl] .tagify-email-list .tagify__tag:hover .tagify__tag__removeBtn {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: -1ch;
|
|
||||||
}
|
|
||||||
[dir=rtl] .tagify-email-list .tagify__tag__removeBtn {
|
|
||||||
transform: translateX(6px) scale(0.5);
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: -3ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
.light-style .tagify-email-list .tagify__tag--editable:not(.tagify--invalid) > div::before {
|
|
||||||
box-shadow: 0 0 0 2px #e4e6e8 inset !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark-style .tagify-email-list .tagify__tag--editable:not(.tagify--invalid) > div::before {
|
|
||||||
box-shadow: 0 0 0 2px #4e4f6c inset !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tagify.form-control {
|
|
||||||
transition: none;
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-end;
|
|
||||||
/* padding: calc(2px - var(--bs-border-width)) 0.4375rem 0.4231rem !important; */
|
|
||||||
padding: calc(2px - var(--bs-border-width)) 0.4375rem 0.2rem !important;
|
|
||||||
}
|
|
||||||
.fv-plugins-bootstrap5-row-invalid .tagify.form-control {
|
|
||||||
padding: 0 calc(0.4375rem - var(--bs-border-width)) calc(0.4375rem - 2px) !important;
|
|
||||||
}
|
|
||||||
.tagify.tagify--focus, .tagify.form-control:focus {
|
|
||||||
padding: 0 calc(0.4375rem - var(--bs-border-width)) 0.3606rem !important;
|
|
||||||
border-width: 2px;
|
|
||||||
}
|
|
||||||
.tagify__tag, .tagify__input {
|
|
||||||
margin: 0.1875rem 0.625rem 0 0 !important;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
.tagify__input {
|
|
||||||
line-height: 1.5rem;
|
|
||||||
}
|
|
||||||
.tagify__input:empty::before {
|
|
||||||
top: 4px;
|
|
||||||
}
|
|
||||||
.tagify__tag > div {
|
|
||||||
line-height: 1.5rem;
|
|
||||||
padding: 0 0 0 0.4375rem;
|
|
||||||
}
|
|
||||||
.tagify__tag__removeBtn {
|
|
||||||
margin-right: 0.1375rem;
|
|
||||||
margin-left: 0.21875rem;
|
|
||||||
font-family: "boxicons";
|
|
||||||
font-size: 1rem;
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
.tagify__tag__removeBtn:hover {
|
|
||||||
background: none;
|
|
||||||
color: #ff2804 !important;
|
|
||||||
}
|
|
||||||
.tagify__tag__removeBtn::after {
|
|
||||||
content: "\ef06";
|
|
||||||
}
|
|
||||||
.tagify__tag:hover:not([readonly]) div::before, .tagify__tag:focus div::before {
|
|
||||||
top: 0px;
|
|
||||||
right: 0px;
|
|
||||||
bottom: 0px;
|
|
||||||
left: 0px;
|
|
||||||
}
|
|
||||||
.tagify__dropdown {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
.tagify[readonly]:not(.tagify--mix) .tagify__tag > div {
|
|
||||||
padding: 0 0.4375rem 0 0.4375rem !important;
|
|
||||||
}
|
|
||||||
.tagify__input {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
.tagify__tag-text {
|
|
||||||
font-size: 0.8125rem;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tagify.form-control {
|
|
||||||
padding-top: 0.1412rem !important;
|
|
||||||
}
|
|
||||||
.tagify.tagify--focus, .tagify.form-control:focus {
|
|
||||||
padding-top: calc(0.1412rem - 1px) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tagify__tag__removeBtn {
|
|
||||||
margin-inline-end: 0.3rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
[dir=rtl] .tagify__tag, [dir=rtl] .tagify__input {
|
|
||||||
margin: 0.4375rem 0 0 0.4375rem;
|
|
||||||
}
|
|
||||||
[dir=rtl] .tagify + input,
|
|
||||||
[dir=rtl] .tagify + textarea {
|
|
||||||
left: 0;
|
|
||||||
right: -9999em !important;
|
|
||||||
}
|
|
||||||
[dir=rtl] .tagify__tag > div {
|
|
||||||
padding: 0 0.6875rem 0 0;
|
|
||||||
}
|
|
||||||
[dir=rtl] .tagify__tag__removeBtn {
|
|
||||||
margin-left: 0.4375rem;
|
|
||||||
margin-right: 0.21875rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.light-style .tagify__tag > div::before {
|
|
||||||
box-shadow: 0 0 0 1.3em rgba(34, 48, 62, 0.08) inset;
|
|
||||||
}
|
|
||||||
.light-style .tagify__tag .tagify__tag-text {
|
|
||||||
color: #384551;
|
|
||||||
}
|
|
||||||
.light-style .tagify__tag:hover:not([readonly]) div::before, .light-style .tagify__tag:focus div::before {
|
|
||||||
box-shadow: 0 0 0 1.3em rgba(34, 48, 62, 0.12) inset;
|
|
||||||
}
|
|
||||||
.light-style .tagify__tag__removeBtn {
|
|
||||||
color: #7a838b;
|
|
||||||
}
|
|
||||||
.light-style .tagify__tag__removeBtn:hover + div::before {
|
|
||||||
background: rgba(255, 62, 29, 0.3);
|
|
||||||
}
|
|
||||||
.light-style .tagify:hover:not([readonly]) {
|
|
||||||
border-color: #ced1d5;
|
|
||||||
}
|
|
||||||
.light-style .tagify__input::before {
|
|
||||||
color: #a7acb2 !important;
|
|
||||||
}
|
|
||||||
.light-style .tagify__dropdown {
|
|
||||||
box-shadow: 0 0.25rem 0.75rem 0 rgba(34, 48, 62, 0.14);
|
|
||||||
border-top-color: #e4e6e8;
|
|
||||||
}
|
|
||||||
.light-style .tagify__dropdown__wrapper {
|
|
||||||
background: #fff;
|
|
||||||
border-color: #e4e6e8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark-style .tagify__tag > div::before {
|
|
||||||
box-shadow: 0 0 0 1.3em rgba(230, 230, 241, 0.08) inset;
|
|
||||||
}
|
|
||||||
.dark-style .tagify__tag > div .tagify__tag-text {
|
|
||||||
color: #d5d5e2;
|
|
||||||
}
|
|
||||||
.dark-style .tagify__tag:hover:not([readonly]) div::before, .dark-style .tagify__tag:focus div::before {
|
|
||||||
box-shadow: 0 0 0 1.3em rgba(230, 230, 241, 0.12) inset;
|
|
||||||
}
|
|
||||||
.dark-style .tagify__tag__removeBtn {
|
|
||||||
color: #a1a1b5;
|
|
||||||
}
|
|
||||||
.dark-style .tagify__tag__removeBtn:hover + div::before {
|
|
||||||
background: rgba(255, 62, 29, 0.3);
|
|
||||||
}
|
|
||||||
.dark-style .tagify:hover:not([readonly]) {
|
|
||||||
border-color: #5f607b;
|
|
||||||
}
|
|
||||||
.dark-style .tagify__input::before {
|
|
||||||
color: #7e7f96 !important;
|
|
||||||
}
|
|
||||||
.dark-style .tagify[readonly]:not(.tagify--mix) .tagify__tag > div::before {
|
|
||||||
background: linear-gradient(45deg, #5f607b 25%, transparent 25%, transparent 50%, #5f607b 50%, #5f607b 75%, transparent 75%, transparent) 0/5px 5px;
|
|
||||||
}
|
|
||||||
.dark-style .tagify[readonly]:not(.tagify--mix):not(.tagify--select) .tagify__tag > div::before {
|
|
||||||
animation: none;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
.dark-style .tagify__dropdown {
|
|
||||||
box-shadow: 0 0.25rem 0.75rem 0 rgba(20, 20, 29, 0.24);
|
|
||||||
border-top-color: #4e4f6c;
|
|
||||||
}
|
|
||||||
.dark-style .tagify__dropdown__wrapper {
|
|
||||||
box-shadow: 0 0.25rem 0.75rem 0 rgba(20, 20, 29, 0.24);
|
|
||||||
background: #2b2c40;
|
|
||||||
border-color: #4e4f6c;
|
|
||||||
}
|
|
||||||
120
public/assets/vendor/libs/tagify/tagify.js
vendored
|
Before Width: | Height: | Size: 117 KiB |
BIN
public/img/avatars/1.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
public/img/avatars/5.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/img/avatars/6.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
public/img/avatars/7.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
public/img/brand/logo-1.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
public/img/brand/logo-2.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
public/img/brand/logo-3.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
public/img/brand/logo-4.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
public/img/brand/logo-5.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
public/img/brand/logo-6.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
public/img/brand/logo_1-dark.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
public/img/brand/logo_1-light.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
public/img/brand/logo_2-dark.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
public/img/brand/logo_2-light.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
public/img/brand/logo_3-dark.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
public/img/brand/logo_3-light.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
public/img/brand/logo_4-dark.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
public/img/brand/logo_4-light.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
public/img/brand/logo_5-dark.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
public/img/brand/logo_5-light.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 127 KiB |
BIN
public/img/elements/1.jpg
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/elements/11.jpg
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
public/img/elements/12.jpg
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
public/img/elements/13.jpg
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
public/img/elements/17.jpg
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
public/img/elements/18.jpg
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
public/img/elements/19.jpg
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
public/img/elements/2.jpg
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
public/img/elements/20.jpg
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/img/elements/3.jpg
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
public/img/elements/4.jpg
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
public/img/elements/5.jpg
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
public/img/elements/7.jpg
Normal file
|
After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 500 KiB |
|
Before Width: | Height: | Size: 201 KiB |
|
Before Width: | Height: | Size: 1.8 MiB |
|
Before Width: | Height: | Size: 233 KiB |
|
Before Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 19 KiB |
@ -1,5 +0,0 @@
|
|||||||
<svg width="65" height="65" viewBox="0 0 65 65" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path opacity="0.2" d="M46.5001 10.5288H32.5001L20.2251 26.5288L32.5001 56.5288L60.5001 26.5288L46.5001 10.5288Z" fill="#03C3EC"/>
|
|
||||||
<path d="M18.5 10.5288H46.5L60.5 26.5288L32.5 56.5288L4.5 26.5288L18.5 10.5288Z" stroke="#03C3EC" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M33.2934 9.92012C33.1042 9.67343 32.8109 9.52881 32.5 9.52881C32.1891 9.52881 31.8958 9.67343 31.7066 9.92012L19.7318 25.5288H4.5C3.94772 25.5288 3.5 25.9765 3.5 26.5288C3.5 27.0811 3.94772 27.5288 4.5 27.5288H19.5537L31.5745 56.9075C31.7282 57.2833 32.094 57.5288 32.5 57.5288C32.906 57.5288 33.2718 57.2833 33.4255 56.9075L45.4463 27.5288H60.5C61.0523 27.5288 61.5 27.0811 61.5 26.5288C61.5 25.9765 61.0523 25.5288 60.5 25.5288H45.2682L33.2934 9.92012ZM42.7474 25.5288L32.5 12.1717L22.2526 25.5288H42.7474ZM21.7146 27.5288L32.5 53.8881L43.2854 27.5288H21.7146Z" fill="#03C3EC"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 140 KiB |
|
Before Width: | Height: | Size: 860 KiB |
|
Before Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 225 KiB |
BIN
public/img/illustrations/man-with-laptop-light.png
Normal file
|
After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 11 KiB |
4955
public/img/illustrations/worker_01.svg
Normal file
|
After Width: | Height: | Size: 395 KiB |
BIN
public/img/illustrations/worker_02.jpg
Normal file
|
After Width: | Height: | Size: 267 KiB |
1117
public/img/illustrations/worker_02.svg
Normal file
|
After Width: | Height: | Size: 107 KiB |
BIN
public/img/illustrations/worker_03.jpg
Normal file
|
After Width: | Height: | Size: 252 KiB |
BIN
public/img/illustrations/worker_03.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 860 KiB After Width: | Height: | Size: 860 KiB |
BIN
public/img/layouts/layout-container-light.png
Normal file
|
After Width: | Height: | Size: 61 KiB |
BIN
public/img/layouts/layout-fluid-light.png
Normal file
|
After Width: | Height: | Size: 57 KiB |
BIN
public/img/layouts/layout-without-menu-light.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
public/img/layouts/layout-without-navbar-light.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
42
public/img/sneat.svg
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<svg width="25" viewBox="0 0 25 42" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<defs>
|
||||||
|
<path
|
||||||
|
d="M13.7918663,0.358365126 L3.39788168,7.44174259 C0.566865006,9.69408886 -0.379795268,12.4788597 0.557900856,15.7960551 C0.68998853,16.2305145 1.09562888,17.7872135 3.12357076,19.2293357 C3.8146334,19.7207684 5.32369333,20.3834223 7.65075054,21.2172976 L7.59773219,21.2525164 L2.63468769,24.5493413 C0.445452254,26.3002124 0.0884951797,28.5083815 1.56381646,31.1738486 C2.83770406,32.8170431 5.20850219,33.2640127 7.09180128,32.5391577 C8.347334,32.0559211 11.4559176,30.0011079 16.4175519,26.3747182 C18.0338572,24.4997857 18.6973423,22.4544883 18.4080071,20.2388261 C17.963753,17.5346866 16.1776345,15.5799961 13.0496516,14.3747546 L10.9194936,13.4715819 L18.6192054,7.984237 L13.7918663,0.358365126 Z"
|
||||||
|
id="path-1"></path>
|
||||||
|
<path
|
||||||
|
d="M5.47320593,6.00457225 C4.05321814,8.216144 4.36334763,10.0722806 6.40359441,11.5729822 C8.61520715,12.571656 10.0999176,13.2171421 10.8577257,13.5094407 L15.5088241,14.433041 L18.6192054,7.984237 C15.5364148,3.11535317 13.9273018,0.573395879 13.7918663,0.358365126 C13.5790555,0.511491653 10.8061687,2.3935607 5.47320593,6.00457225 Z"
|
||||||
|
id="path-3"></path>
|
||||||
|
<path
|
||||||
|
d="M7.50063644,21.2294429 L12.3234468,23.3159332 C14.1688022,24.7579751 14.397098,26.4880487 13.008334,28.506154 C11.6195701,30.5242593 10.3099883,31.790241 9.07958868,32.3040991 C5.78142938,33.4346997 4.13234973,34 4.13234973,34 C4.13234973,34 2.75489982,33.0538207 2.37032616e-14,31.1614621 C-0.55822714,27.8186216 -0.55822714,26.0572515 -4.05231404e-15,25.8773518 C0.83734071,25.6075023 2.77988457,22.8248993 3.3049379,22.52991 C3.65497346,22.3332504 5.05353963,21.8997614 7.50063644,21.2294429 Z"
|
||||||
|
id="path-4"></path>
|
||||||
|
<path
|
||||||
|
d="M20.6,7.13333333 L25.6,13.8 C26.2627417,14.6836556 26.0836556,15.9372583 25.2,16.6 C24.8538077,16.8596443 24.4327404,17 24,17 L14,17 C12.8954305,17 12,16.1045695 12,15 C12,14.5672596 12.1403557,14.1461923 12.4,13.8 L17.4,7.13333333 C18.0627417,6.24967773 19.3163444,6.07059163 20.2,6.73333333 C20.3516113,6.84704183 20.4862915,6.981722 20.6,7.13333333 Z"
|
||||||
|
id="path-5"></path>
|
||||||
|
</defs>
|
||||||
|
<g id="g-app-brand" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="Brand-Logo" transform="translate(-27.000000, -15.000000)">
|
||||||
|
<g id="Icon" transform="translate(27.000000, 15.000000)">
|
||||||
|
<g id="Mask" transform="translate(0.000000, 8.000000)">
|
||||||
|
<mask id="mask-2" fill="white">
|
||||||
|
<use xlink:href="#path-1"></use>
|
||||||
|
</mask>
|
||||||
|
<use fill="#696cff" xlink:href="#path-1"></use>
|
||||||
|
<g id="Path-3" mask="url(#mask-2)">
|
||||||
|
<use fill="#696cff" xlink:href="#path-3"></use>
|
||||||
|
<use fill-opacity="0.2" fill="#FFFFFF" xlink:href="#path-3"></use>
|
||||||
|
</g>
|
||||||
|
<g id="Path-4" mask="url(#mask-2)">
|
||||||
|
<use fill="#696cff" xlink:href="#path-4"></use>
|
||||||
|
<use fill-opacity="0.2" fill="#FFFFFF" xlink:href="#path-4"></use>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g id="Triangle"
|
||||||
|
transform="translate(19.000000, 11.000000) rotate(-300.000000) translate(-19.000000, -11.000000) ">
|
||||||
|
<use fill="#696cff" xlink:href="#path-5"></use>
|
||||||
|
<use fill-opacity="0.2" fill="#FFFFFF" xlink:href="#path-5"></use>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.9 KiB |
BIN
public/img/teams/team-member-1.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
BIN
public/img/teams/team-member-2.png
Normal file
|
After Width: | Height: | Size: 59 KiB |
BIN
public/img/teams/team-member-3.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
public/img/teams/team-member-4.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
@ -4,7 +4,6 @@ import { ToastContainer } from "react-toastify";
|
|||||||
import { QueryClientProvider } from '@tanstack/react-query';
|
import { QueryClientProvider } from '@tanstack/react-query';
|
||||||
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
|
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
|
||||||
import { queryClient } from "./layouts/AuthLayout";
|
import { queryClient } from "./layouts/AuthLayout";
|
||||||
import ModalProvider from "./ModalProvider";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -12,7 +11,6 @@ const App = () => {
|
|||||||
return (
|
return (
|
||||||
<div className="app">
|
<div className="app">
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<ModalProvider/>
|
|
||||||
<DireProvider>
|
<DireProvider>
|
||||||
<AppRoutes />
|
<AppRoutes />
|
||||||
</DireProvider>
|
</DireProvider>
|
||||||
|
|||||||
112
src/ModalContext.jsx
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
import React, {
|
||||||
|
createContext,
|
||||||
|
useContext,
|
||||||
|
useState,
|
||||||
|
useEffect,
|
||||||
|
useRef,
|
||||||
|
} from "react";
|
||||||
|
|
||||||
|
const ModalContext = createContext();
|
||||||
|
|
||||||
|
export const useModal = () => useContext(ModalContext);
|
||||||
|
|
||||||
|
// ModalProvider to manage modal state and expose functionality to the rest of the app
|
||||||
|
export const ModalProvider = ({ children }) => {
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
const [modalContent, setModalContent] = useState(null);
|
||||||
|
const [onSubmit, setOnSubmit] = useState(null);
|
||||||
|
const [modalSize, setModalSize] = useState("lg");
|
||||||
|
|
||||||
|
// Ref to track the modal content element
|
||||||
|
const modalRef = useRef(null);
|
||||||
|
|
||||||
|
const openModal = (content, onSubmitCallback, size = "lg") => {
|
||||||
|
setModalContent(content); // Set modal content dynamically
|
||||||
|
setOnSubmit(() => onSubmitCallback); // Set the submit handler dynamically
|
||||||
|
setIsOpen(true); // Open the modal
|
||||||
|
setModalSize(size); // Set the modal size
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to close the modal
|
||||||
|
const closeModal = () => {
|
||||||
|
setIsOpen(false); // Close the modal
|
||||||
|
setModalContent(null); // Clear modal content
|
||||||
|
setOnSubmit(null); // Clear the submit callback
|
||||||
|
setModalSize("lg"); // Reset modal size
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleEscape = (event) => {
|
||||||
|
if (event.key === "Escape") {
|
||||||
|
closeModal();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
document.addEventListener("keydown", handleEscape);
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener("keydown", handleEscape);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleClickOutside = (event) => {
|
||||||
|
if (modalRef.current && !modalRef.current.contains(event.target)) {
|
||||||
|
closeModal();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
document.addEventListener("mousedown", handleClickOutside);
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener("mousedown", handleClickOutside);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ModalContext.Provider
|
||||||
|
value={{
|
||||||
|
isOpen,
|
||||||
|
openModal,
|
||||||
|
closeModal,
|
||||||
|
modalContent,
|
||||||
|
modalSize,
|
||||||
|
onSubmit,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
|
||||||
|
{isOpen && (
|
||||||
|
<div style={overlayStyles}>
|
||||||
|
<div
|
||||||
|
ref={modalRef}
|
||||||
|
style={{
|
||||||
|
...modalStyles,
|
||||||
|
maxWidth: modalSize === "sm" ? "400px" : "800px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div>{modalContent}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</ModalContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const overlayStyles = {
|
||||||
|
position: "fixed",
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
zIndex: 1050,
|
||||||
|
};
|
||||||
|
|
||||||
|
const modalStyles = {
|
||||||
|
backgroundColor: "white",
|
||||||
|
padding: "20px",
|
||||||
|
borderRadius: "5px",
|
||||||
|
boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)",
|
||||||
|
width: "90%",
|
||||||
|
maxWidth: "800px",
|
||||||
|
};
|
||||||
@ -1,28 +0,0 @@
|
|||||||
import React, { useEffect } from "react";
|
|
||||||
import { useOrganizationModal } from "./hooks/useOrganization";
|
|
||||||
import OrganizationModal from "./components/Organization/OrganizationModal";
|
|
||||||
import { useAuthModal, useModal } from "./hooks/useAuth";
|
|
||||||
import SwitchTenant from "./pages/authentication/SwitchTenant";
|
|
||||||
import ChangePasswordPage from "./pages/authentication/ChangePassword";
|
|
||||||
import NewCollection from "./components/collections/ManageCollection";
|
|
||||||
import ServiceProjectTeamAllocation from "./components/ServiceProject/ServiceProjectTeam/ServiceProjectTeamAllocation";
|
|
||||||
|
|
||||||
const ModalProvider = () => {
|
|
||||||
const { isOpen, onClose } = useOrganizationModal();
|
|
||||||
const { isOpen: isAuthOpen } = useAuthModal();
|
|
||||||
const { isOpen: isChangePass } = useModal("ChangePassword");
|
|
||||||
const { isOpen: isCollectionNew } = useModal("newCollection");
|
|
||||||
const { isOpen: isServiceTeamAllocation } = useModal("ServiceTeamAllocation");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{isOpen && <OrganizationModal />}
|
|
||||||
{isAuthOpen && <SwitchTenant />}
|
|
||||||
{isChangePass && <ChangePasswordPage />}
|
|
||||||
{isCollectionNew && <NewCollection />}
|
|
||||||
{isServiceTeamAllocation && <ServiceProjectTeamAllocation />}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ModalProvider;
|
|
||||||
1
src/assets/react.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 4.0 KiB |
2
src/assets/vendor/css/core.css
vendored
@ -72,7 +72,7 @@
|
|||||||
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
|
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
|
||||||
--bs-root-font-size: 16px;
|
--bs-root-font-size: 16px;
|
||||||
--bs-body-font-family: var(--bs-font-sans-serif);
|
--bs-body-font-family: var(--bs-font-sans-serif);
|
||||||
--bs-body-font-size: 0.875rem;
|
--bs-body-font-size: 0.9375rem;
|
||||||
--bs-body-font-weight: 400;
|
--bs-body-font-weight: 400;
|
||||||
--bs-body-line-height: 1.375;
|
--bs-body-line-height: 1.375;
|
||||||
--bs-body-color: #646e78;
|
--bs-body-color: #646e78;
|
||||||
|
|||||||
@ -123,15 +123,12 @@ const AttendLogs = ({ Id }) => {
|
|||||||
}, []);
|
}, []);
|
||||||
return (
|
return (
|
||||||
<div className="table-responsive">
|
<div className="table-responsive">
|
||||||
<div className="mb-3">
|
<div className="text-start">
|
||||||
<h5 className="mb-4">Attendance Logs</h5>
|
|
||||||
{logs && !loading && (
|
{logs && !loading && (
|
||||||
<p className="mb-0 text-start">
|
<p>
|
||||||
Showing logs for{" "}
|
Attendance logs for{" "}
|
||||||
<strong>
|
{logs[0]?.employee?.firstName + " " + logs[0]?.employee?.lastName}{" "}
|
||||||
{logs[0]?.employee?.firstName + " " + logs[0]?.employee?.lastName}
|
on {formatUTCToLocalTime(logs[0]?.activityTime)}
|
||||||
</strong>{" "}
|
|
||||||
on <strong>{formatUTCToLocalTime(logs[0]?.activityTime)}</strong>
|
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -145,9 +142,9 @@ const AttendLogs = ({ Id }) => {
|
|||||||
<table className="table table-sm mb-0">
|
<table className="table table-sm mb-0">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Activity</th>
|
|
||||||
<th>Date</th>
|
<th>Date</th>
|
||||||
<th>Time</th>
|
<th>Time</th>
|
||||||
|
<th>Activity</th>
|
||||||
<th>Location</th>
|
<th>Location</th>
|
||||||
<th>Recored By</th>
|
<th>Recored By</th>
|
||||||
<th>Description</th>
|
<th>Description</th>
|
||||||
@ -159,16 +156,11 @@ const AttendLogs = ({ Id }) => {
|
|||||||
.sort((a, b) => b.id - a.id)
|
.sort((a, b) => b.id - a.id)
|
||||||
.map((log, index) => (
|
.map((log, index) => (
|
||||||
<tr key={index}>
|
<tr key={index}>
|
||||||
|
<td>{formatUTCToLocalTime(log.activityTime)}</td>
|
||||||
|
<td>{convertShortTime(log.activityTime)}</td>
|
||||||
<td>
|
<td>
|
||||||
{whichActivityPerform(log.activity, log.activityTime)}
|
{whichActivityPerform(log.activity, log.activityTime)}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
|
||||||
<div className="py-2">
|
|
||||||
{formatUTCToLocalTime(log.activityTime)}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>{convertShortTime(log.activityTime)}</td>
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
{log?.latitude != 0 ? (
|
{log?.latitude != 0 ? (
|
||||||
<i
|
<i
|
||||||
@ -187,8 +179,9 @@ const AttendLogs = ({ Id }) => {
|
|||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
<td className="text-wrap">
|
<td className="text-wrap">
|
||||||
{`${log?.updatedByEmployee?.firstName ?? ""} ${log?.updatedByEmployee?.lastName ?? ""
|
{`${log?.updatedByEmployee?.firstName ?? ""} ${
|
||||||
}`}
|
log?.updatedByEmployee?.lastName ?? ""
|
||||||
|
}`}
|
||||||
</td>
|
</td>
|
||||||
<td className="text-wrap" colSpan={3}>
|
<td className="text-wrap" colSpan={3}>
|
||||||
{log?.comment?.length > 50
|
{log?.comment?.length > 50
|
||||||
|
|||||||
@ -11,21 +11,23 @@ import { useSelector } from "react-redux";
|
|||||||
import { useQueryClient } from "@tanstack/react-query";
|
import { useQueryClient } from "@tanstack/react-query";
|
||||||
import eventBus from "../../services/eventBus";
|
import eventBus from "../../services/eventBus";
|
||||||
import { useSelectedProject } from "../../slices/apiDataManager";
|
import { useSelectedProject } from "../../slices/apiDataManager";
|
||||||
import { SpinnerLoader } from "../common/Loader";
|
|
||||||
|
|
||||||
const Attendance = ({ getRole, handleModalData, searchTerm, projectId, organizationId, }) => {
|
const Attendance = ({ getRole, handleModalData, searchTerm }) => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [todayDate, setTodayDate] = useState(new Date());
|
const [todayDate, setTodayDate] = useState(new Date());
|
||||||
const [ShowPending, setShowPending] = useState(false);
|
const [ShowPending, setShowPending] = useState(false);
|
||||||
|
// const selectedProject = useSelector(
|
||||||
|
// (store) => store.localVariables.projectId
|
||||||
|
// );
|
||||||
const selectedProject = useSelectedProject();
|
const selectedProject = useSelectedProject();
|
||||||
const {
|
const {
|
||||||
attendance,
|
attendance,
|
||||||
loading: attLoading,
|
loading: attLoading,
|
||||||
recall: attrecall,
|
recall: attrecall,
|
||||||
isFetching
|
isFetching
|
||||||
} = useAttendance(selectedProject, organizationId);
|
} = useAttendance(selectedProject);
|
||||||
const filteredAttendance = ShowPending
|
const filteredAttendance = ShowPending
|
||||||
? attendance?.filter(
|
? attendance?.filter(
|
||||||
(att) => att?.checkInTime !== null && att?.checkOutTime === null
|
(att) => att?.checkInTime !== null && att?.checkOutTime === null
|
||||||
@ -60,11 +62,12 @@ const Attendance = ({ getRole, handleModalData, searchTerm, projectId, organizat
|
|||||||
const role = item.jobRoleName?.toLowerCase() || "";
|
const role = item.jobRoleName?.toLowerCase() || "";
|
||||||
return (
|
return (
|
||||||
fullName.includes(lowercasedSearchTerm) ||
|
fullName.includes(lowercasedSearchTerm) ||
|
||||||
role.includes(lowercasedSearchTerm) // also search by role
|
role.includes(lowercasedSearchTerm) // ✅ also search by role
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}, [group1, group2, searchTerm]);
|
}, [group1, group2, searchTerm]);
|
||||||
|
|
||||||
|
|
||||||
const { currentPage, totalPages, currentItems, paginate } = usePagination(
|
const { currentPage, totalPages, currentItems, paginate } = usePagination(
|
||||||
finalFilteredData,
|
finalFilteredData,
|
||||||
ITEMS_PER_PAGE
|
ITEMS_PER_PAGE
|
||||||
@ -111,48 +114,34 @@ const Attendance = ({ getRole, handleModalData, searchTerm, projectId, organizat
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="d-flex justify-content-between align-items-center py-2 px-2">
|
|
||||||
{/* Left side - Date */}
|
|
||||||
<div className="text-start">
|
|
||||||
<strong>Date: {formatUTCToLocalTime(todayDate)}</strong>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Right side - Pending Attendance toggle */}
|
|
||||||
<div className="form-check form-switch m-0">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
className="form-check-input"
|
|
||||||
role="switch"
|
|
||||||
id="inactiveEmployeesCheckbox"
|
|
||||||
disabled={isFetching}
|
|
||||||
checked={ShowPending}
|
|
||||||
onChange={(e) => setShowPending(e.target.checked)}
|
|
||||||
/>
|
|
||||||
<label className="form-check-label" htmlFor="inactiveEmployeesCheckbox">
|
|
||||||
Pending Attendance
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
className="table-responsive modal-min-h text-nowrap h-100"
|
className="table-responsive text-nowrap h-100"
|
||||||
style={{ minHeight: "200px" }} // Ensures fixed height
|
style={{ minHeight: "200px" }} // 🔹 Ensures fixed height
|
||||||
>
|
>
|
||||||
{attLoading ? (
|
<div className="d-flex text-start align-items-center py-2">
|
||||||
<div
|
<strong>Date : {formatUTCToLocalTime(todayDate)}</strong>
|
||||||
className="d-flex justify-content-center align-items-center"
|
<div className="form-check form-switch text-start m-0 ms-5">
|
||||||
style={{ minHeight: "50vh" }}
|
<input
|
||||||
>
|
type="checkbox"
|
||||||
<SpinnerLoader />
|
className="form-check-input"
|
||||||
|
role="switch"
|
||||||
|
id="inactiveEmployeesCheckbox"
|
||||||
|
disabled={isFetching}
|
||||||
|
checked={ShowPending}
|
||||||
|
onChange={(e) => setShowPending(e.target.checked)}
|
||||||
|
/>
|
||||||
|
<label className="form-check-label ms-0">Show Pending</label>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
{attLoading ? (
|
||||||
|
<div>Loading...</div>
|
||||||
) : currentItems?.length > 0 ? (
|
) : currentItems?.length > 0 ? (
|
||||||
|
|
||||||
<>
|
<>
|
||||||
<table className="table ">
|
<table className="table ">
|
||||||
<thead>
|
<thead>
|
||||||
<tr className="border-top-1">
|
<tr className="border-top-1">
|
||||||
<th colSpan={2}>Name</th>
|
<th colSpan={2}>Name</th>
|
||||||
<th>Role</th>
|
<th>Role</th>
|
||||||
<th>Organization</th>
|
|
||||||
<th>
|
<th>
|
||||||
<i className="bx bxs-down-arrow-alt text-success"></i>
|
<i className="bx bxs-down-arrow-alt text-success"></i>
|
||||||
Check-In
|
Check-In
|
||||||
@ -201,8 +190,6 @@ const Attendance = ({ getRole, handleModalData, searchTerm, projectId, organizat
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>{item.jobRoleName}</td>
|
<td>{item.jobRoleName}</td>
|
||||||
<td>{item.organizationName || "--"}</td>
|
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
{item.checkInTime
|
{item.checkInTime
|
||||||
? convertShortTime(item.checkInTime)
|
? convertShortTime(item.checkInTime)
|
||||||
@ -226,17 +213,56 @@ const Attendance = ({ getRole, handleModalData, searchTerm, projectId, organizat
|
|||||||
))}
|
))}
|
||||||
{!attendance && (
|
{!attendance && (
|
||||||
<tr>
|
<tr>
|
||||||
<td
|
<td colSpan={6} className="text-center text-secondary" style={{ height: "200px" }}>
|
||||||
colSpan={7}
|
|
||||||
className="text-center text-secondary"
|
|
||||||
style={{ height: "200px" }}
|
|
||||||
>
|
|
||||||
No employees assigned to the project!
|
No employees assigned to the project!
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
)}
|
)}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
{!loading && finalFilteredData.length > ITEMS_PER_PAGE && (
|
||||||
|
<nav aria-label="Page ">
|
||||||
|
<ul className="pagination pagination-sm justify-content-end py-1">
|
||||||
|
<li
|
||||||
|
className={`page-item ${currentPage === 1 ? "disabled" : ""
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
className="page-link btn-xs"
|
||||||
|
onClick={() => paginate(currentPage - 1)}
|
||||||
|
>
|
||||||
|
«
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
{[...Array(totalPages)].map((_, index) => (
|
||||||
|
<li
|
||||||
|
key={index}
|
||||||
|
className={`page-item ${currentPage === index + 1 ? "active" : ""
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
className="page-link "
|
||||||
|
onClick={() => paginate(index + 1)}
|
||||||
|
>
|
||||||
|
{index + 1}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
<li
|
||||||
|
className={`page-item ${currentPage === totalPages ? "disabled" : ""
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
className="page-link "
|
||||||
|
onClick={() => paginate(currentPage + 1)}
|
||||||
|
>
|
||||||
|
»
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
@ -251,48 +277,6 @@ const Attendance = ({ getRole, handleModalData, searchTerm, projectId, organizat
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{!loading && finalFilteredData.length > ITEMS_PER_PAGE && (
|
|
||||||
<nav aria-label="Page ">
|
|
||||||
<ul className="pagination pagination-sm justify-content-end py-1">
|
|
||||||
<li
|
|
||||||
className={`page-item ${currentPage === 1 ? "disabled" : ""
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
className="page-link btn-xs"
|
|
||||||
onClick={() => paginate(currentPage - 1)}
|
|
||||||
>
|
|
||||||
«
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
{[...Array(totalPages)].map((_, index) => (
|
|
||||||
<li
|
|
||||||
key={index}
|
|
||||||
className={`page-item ${currentPage === index + 1 ? "active" : ""
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
className="page-link "
|
|
||||||
onClick={() => paginate(index + 1)}
|
|
||||||
>
|
|
||||||
{index + 1}
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
<li
|
|
||||||
className={`page-item ${currentPage === totalPages ? "disabled" : ""
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
className="page-link "
|
|
||||||
onClick={() => paginate(currentPage + 1)}
|
|
||||||
>
|
|
||||||
»
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,22 +1,17 @@
|
|||||||
import React, { useEffect, useState, useMemo, useCallback } from "react";
|
import React, { useEffect, useState, useMemo, useCallback } from "react";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import Avatar from "../common/Avatar";
|
import Avatar from "../common/Avatar";
|
||||||
import { convertShortTime, formatUTCToLocalTime } from "../../utils/dateUtils";
|
import { convertShortTime } from "../../utils/dateUtils";
|
||||||
import RenderAttendanceStatus from "./RenderAttendanceStatus";
|
import RenderAttendanceStatus from "./RenderAttendanceStatus";
|
||||||
import { useSelector, useDispatch } from "react-redux";
|
import { useSelector, useDispatch } from "react-redux";
|
||||||
|
import { fetchAttendanceData } from "../../slices/apiSlice/attedanceLogsSlice";
|
||||||
import DateRangePicker from "../common/DateRangePicker";
|
import DateRangePicker from "../common/DateRangePicker";
|
||||||
import {
|
import { clearCacheKey, getCachedData, useSelectedProject } from "../../slices/apiDataManager";
|
||||||
clearCacheKey,
|
|
||||||
getCachedData,
|
|
||||||
useSelectedProject,
|
|
||||||
} from "../../slices/apiDataManager";
|
|
||||||
import eventBus from "../../services/eventBus";
|
import eventBus from "../../services/eventBus";
|
||||||
import AttendanceRepository from "../../repositories/AttendanceRepository";
|
import AttendanceRepository from "../../repositories/AttendanceRepository";
|
||||||
import { useAttendancesLogs } from "../../hooks/useAttendance";
|
import { useAttendancesLogs } from "../../hooks/useAttendance";
|
||||||
import { queryClient } from "../../layouts/AuthLayout";
|
import { queryClient } from "../../layouts/AuthLayout";
|
||||||
import { ITEMS_PER_PAGE } from "../../utils/constants";
|
import { ITEMS_PER_PAGE } from "../../utils/constants";
|
||||||
import { useNavigate } from "react-router-dom";
|
|
||||||
import { SpinnerLoader } from "../common/Loader";
|
|
||||||
|
|
||||||
const usePagination = (data, itemsPerPage) => {
|
const usePagination = (data, itemsPerPage) => {
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
@ -39,14 +34,18 @@ const usePagination = (data, itemsPerPage) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const AttendanceLog = ({ handleModalData, searchTerm, organizationId }) => {
|
const AttendanceLog = ({ handleModalData, searchTerm }) => {
|
||||||
|
// const selectedProject = useSelector(
|
||||||
|
// (store) => store.localVariables.projectId
|
||||||
|
// );
|
||||||
const selectedProject = useSelectedProject();
|
const selectedProject = useSelectedProject();
|
||||||
const [dateRange, setDateRange] = useState({ startDate: "", endDate: "" });
|
const [dateRange, setDateRange] = useState({ startDate: "", endDate: "" });
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [showPending, setShowPending] = useState(false);
|
const [showPending, setShowPending] = useState(false)
|
||||||
|
|
||||||
const [isRefreshing, setIsRefreshing] = useState(false);
|
const [isRefreshing, setIsRefreshing] = useState(false);
|
||||||
const navigate = useNavigate();
|
const [processedData, setProcessedData] = useState([]);
|
||||||
|
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
today.setHours(0, 0, 0, 0);
|
today.setHours(0, 0, 0, 0);
|
||||||
@ -69,32 +68,56 @@ const AttendanceLog = ({ handleModalData, searchTerm, organizationId }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const sortByName = (a, b) => {
|
const sortByName = (a, b) => {
|
||||||
const nameA = (a.firstName + a.lastName).toLowerCase();
|
const nameA = a.firstName.toLowerCase() + a.lastName.toLowerCase();
|
||||||
const nameB = (b.firstName + b.lastName).toLowerCase();
|
const nameB = b.firstName.toLowerCase() + b.lastName.toLowerCase();
|
||||||
return nameA.localeCompare(nameB);
|
return nameA?.localeCompare(nameB);
|
||||||
};
|
};
|
||||||
|
|
||||||
const { data = [], isLoading, error, refetch, isFetching } = useAttendancesLogs(
|
const {
|
||||||
|
data = [],
|
||||||
|
isLoading,
|
||||||
|
error,
|
||||||
|
refetch,
|
||||||
|
isFetching,
|
||||||
|
} = useAttendancesLogs(
|
||||||
selectedProject,
|
selectedProject,
|
||||||
dateRange.startDate,
|
dateRange.startDate,
|
||||||
dateRange.endDate,
|
dateRange.endDate
|
||||||
organizationId
|
|
||||||
);
|
);
|
||||||
|
const filtering = (data) => {
|
||||||
const processedData = useMemo(() => {
|
|
||||||
const filteredData = showPending
|
const filteredData = showPending
|
||||||
? data.filter((item) => item.checkOutTime === null)
|
? data.filter((item) => item.checkOutTime === null)
|
||||||
: data;
|
: data;
|
||||||
|
|
||||||
const group1 = filteredData.filter((d) => d.activity === 1 && isSameDay(d.checkInTime)).sort(sortByName);
|
const group1 = filteredData
|
||||||
const group2 = filteredData.filter((d) => d.activity === 4 && isSameDay(d.checkOutTime)).sort(sortByName);
|
.filter((d) => d.activity === 1 && isSameDay(d.checkInTime))
|
||||||
const group3 = filteredData.filter((d) => d.activity === 1 && isBeforeToday(d.checkInTime)).sort(sortByName);
|
.sort(sortByName);
|
||||||
const group4 = filteredData.filter((d) => d.activity === 4 && isBeforeToday(d.checkOutTime));
|
const group2 = filteredData
|
||||||
const group5 = filteredData.filter((d) => d.activity === 2 && isBeforeToday(d.checkOutTime)).sort(sortByName);
|
.filter((d) => d.activity === 4 && isSameDay(d.checkOutTime))
|
||||||
const group6 = filteredData.filter((d) => d.activity === 5).sort(sortByName);
|
.sort(sortByName);
|
||||||
|
const group3 = filteredData
|
||||||
|
.filter((d) => d.activity === 1 && isBeforeToday(d.checkInTime))
|
||||||
|
.sort(sortByName);
|
||||||
|
const group4 = filteredData.filter(
|
||||||
|
(d) => d.activity === 4 && isBeforeToday(d.checkOutTime)
|
||||||
|
);
|
||||||
|
const group5 = filteredData
|
||||||
|
.filter((d) => d.activity === 2 && isBeforeToday(d.checkOutTime))
|
||||||
|
.sort(sortByName);
|
||||||
|
const group6 = filteredData
|
||||||
|
.filter((d) => d.activity === 5)
|
||||||
|
.sort(sortByName);
|
||||||
|
|
||||||
const sortedList = [...group1, ...group2, ...group3, ...group4, ...group5, ...group6];
|
const sortedList = [
|
||||||
|
...group1,
|
||||||
|
...group2,
|
||||||
|
...group3,
|
||||||
|
...group4,
|
||||||
|
...group5,
|
||||||
|
...group6,
|
||||||
|
];
|
||||||
|
|
||||||
|
// Group by date
|
||||||
const groupedByDate = sortedList.reduce((acc, item) => {
|
const groupedByDate = sortedList.reduce((acc, item) => {
|
||||||
const date = (item.checkInTime || item.checkOutTime)?.split("T")[0];
|
const date = (item.checkInTime || item.checkOutTime)?.split("T")[0];
|
||||||
if (date) {
|
if (date) {
|
||||||
@ -104,17 +127,28 @@ const AttendanceLog = ({ handleModalData, searchTerm, organizationId }) => {
|
|||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
const sortedDates = Object.keys(groupedByDate).sort((a, b) => new Date(b) - new Date(a));
|
const sortedDates = Object.keys(groupedByDate).sort(
|
||||||
return sortedDates.flatMap((date) => groupedByDate[date]);
|
(a, b) => new Date(b) - new Date(a)
|
||||||
|
);
|
||||||
|
|
||||||
|
const finalData = sortedDates.flatMap((date) => groupedByDate[date]);
|
||||||
|
setProcessedData(finalData);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
filtering(data);
|
||||||
}, [data, showPending]);
|
}, [data, showPending]);
|
||||||
|
|
||||||
|
// New useEffect to handle search filtering
|
||||||
const filteredSearchData = useMemo(() => {
|
const filteredSearchData = useMemo(() => {
|
||||||
if (!searchTerm) return processedData;
|
if (!searchTerm) {
|
||||||
|
return processedData;
|
||||||
const lowercased = searchTerm.toLowerCase();
|
}
|
||||||
return processedData.filter((item) =>
|
const lowercasedSearchTerm = searchTerm.toLowerCase();
|
||||||
`${item.firstName} ${item.lastName}`.toLowerCase().includes(lowercased)
|
return processedData.filter((item) => {
|
||||||
);
|
const fullName = `${item.firstName} ${item.lastName}`.toLowerCase();
|
||||||
|
return fullName.includes(lowercasedSearchTerm);
|
||||||
|
});
|
||||||
}, [processedData, searchTerm]);
|
}, [processedData, searchTerm]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -127,27 +161,34 @@ const AttendanceLog = ({ handleModalData, searchTerm, organizationId }) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
resetPage();
|
resetPage();
|
||||||
}, [filteredSearchData]);
|
}, [filteredSearchData, resetPage]);
|
||||||
|
|
||||||
const handler = useCallback(
|
const handler = useCallback(
|
||||||
(msg) => {
|
(msg) => {
|
||||||
const { startDate, endDate } = dateRange;
|
const { startDate, endDate } = dateRange;
|
||||||
const checkIn = msg.response.checkInTime.substring(0, 10);
|
const checkIn = msg.response.checkInTime.substring(0, 10);
|
||||||
|
if (
|
||||||
if (selectedProject === msg.projectId && startDate <= checkIn && checkIn <= endDate) {
|
selectedProject === msg.projectId &&
|
||||||
|
startDate <= checkIn &&
|
||||||
|
checkIn <= endDate
|
||||||
|
) {
|
||||||
queryClient.setQueriesData(["attendanceLogs"], (oldData) => {
|
queryClient.setQueriesData(["attendanceLogs"], (oldData) => {
|
||||||
if (!oldData) {
|
if (!oldData) {
|
||||||
queryClient.invalidateQueries({ queryKey: ["attendanceLogs"] });
|
queryClient.invalidateQueries({ queryKey: ["attendanceLogs"] });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return oldData.map((record) =>
|
const updatedAttendance = oldData.map((record) =>
|
||||||
record.id === msg.response.id ? { ...record, ...msg.response } : record
|
record.id === msg.response.id
|
||||||
|
? { ...record, ...msg.response }
|
||||||
|
: record
|
||||||
);
|
);
|
||||||
|
filtering(updatedAttendance);
|
||||||
|
return updatedAttendance;
|
||||||
});
|
});
|
||||||
resetPage();
|
resetPage();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[selectedProject, dateRange, resetPage]
|
[selectedProject, dateRange, filtering, resetPage]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -159,10 +200,18 @@ const AttendanceLog = ({ handleModalData, searchTerm, organizationId }) => {
|
|||||||
(msg) => {
|
(msg) => {
|
||||||
const { startDate, endDate } = dateRange;
|
const { startDate, endDate } = dateRange;
|
||||||
if (data.some((item) => item.employeeId == msg.employeeId)) {
|
if (data.some((item) => item.employeeId == msg.employeeId)) {
|
||||||
refetch();
|
// dispatch(
|
||||||
|
// fetchAttendanceData({
|
||||||
|
// ,
|
||||||
|
// fromDate: startDate,
|
||||||
|
// toDate: endDate,
|
||||||
|
// })
|
||||||
|
// );
|
||||||
|
|
||||||
|
refetch()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[data, refetch]
|
[selectedProject, dateRange, data, refetch]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -170,56 +219,45 @@ const AttendanceLog = ({ handleModalData, searchTerm, organizationId }) => {
|
|||||||
return () => eventBus.off("employee", employeeHandler);
|
return () => eventBus.off("employee", employeeHandler);
|
||||||
}, [employeeHandler]);
|
}, [employeeHandler]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
className="dataTables_length text-start py-2 d-flex flex-wrap justify-content-between align-items-center"
|
className="dataTables_length text-start py-2 d-flex justify-content-between"
|
||||||
id="DataTables_Table_0_length"
|
id="DataTables_Table_0_length"
|
||||||
>
|
>
|
||||||
{/* Left Side - Date Picker */}
|
<div className="d-flex align-items-center my-0 ">
|
||||||
<div className="d-flex align-items-center">
|
|
||||||
<DateRangePicker
|
<DateRangePicker
|
||||||
onRangeChange={setDateRange}
|
onRangeChange={setDateRange}
|
||||||
defaultStartDate={yesterday}
|
defaultStartDate={yesterday}
|
||||||
/>
|
/>
|
||||||
|
<div className="form-check form-switch text-start m-0 ms-5">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
className="form-check-input"
|
||||||
|
role="switch"
|
||||||
|
disabled={isFetching}
|
||||||
|
id="inactiveEmployeesCheckbox"
|
||||||
|
checked={showPending}
|
||||||
|
onChange={(e) => setShowPending(e.target.checked)}
|
||||||
|
/>
|
||||||
|
<label className="form-check-label ms-0">Show Pending</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="col-md-2 m-0 text-end">
|
||||||
{/* Right Side - Pending Attendance Switch */}
|
<i
|
||||||
<div className="form-check form-switch d-flex align-items-center mb-2">
|
className={`bx bx-refresh cursor-pointer fs-4 ${isFetching ? "spin" : ""
|
||||||
<input
|
}`}
|
||||||
type="checkbox"
|
title="Refresh"
|
||||||
className="form-check-input"
|
onClick={() => refetch()}
|
||||||
role="switch"
|
|
||||||
id="inactiveEmployeesCheckbox"
|
|
||||||
disabled={isFetching}
|
|
||||||
checked={showPending}
|
|
||||||
onChange={(e) => setShowPending(e.target.checked)}
|
|
||||||
/>
|
/>
|
||||||
<label
|
|
||||||
className="form-check-label ms-2"
|
|
||||||
htmlFor="inactiveEmployeesCheckbox"
|
|
||||||
>
|
|
||||||
Pending Attendance
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="table-responsive text-nowrap" style={{ minHeight: "200px" }}>
|
||||||
|
|
||||||
<div
|
|
||||||
className="table-responsive modal-min-h text-nowrap"
|
|
||||||
style={{ minHeight: "200px" }}
|
|
||||||
>
|
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<div
|
<div className="d-flex justify-content-center align-items-center" style={{ height: "200px" }}>
|
||||||
className="d-flex justify-content-center align-items-center"
|
<p className="text-secondary">Loading...</p>
|
||||||
style={{ minHeight: "50vh" }}
|
|
||||||
>
|
|
||||||
<SpinnerLoader />
|
|
||||||
</div>
|
</div>
|
||||||
) : filteredSearchData?.length > 0 ? (
|
) : filteredSearchData?.length > 0 ? (
|
||||||
|
|
||||||
<table className="table mb-0">
|
<table className="table mb-0">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@ -227,7 +265,6 @@ const AttendanceLog = ({ handleModalData, searchTerm, organizationId }) => {
|
|||||||
Name
|
Name
|
||||||
</th>
|
</th>
|
||||||
<th className="border-top-1">Date</th>
|
<th className="border-top-1">Date</th>
|
||||||
<th>Organization</th>
|
|
||||||
<th>
|
<th>
|
||||||
<i className="bx bxs-down-arrow-alt text-success"></i>{" "}
|
<i className="bx bxs-down-arrow-alt text-success"></i>{" "}
|
||||||
Check-In
|
Check-In
|
||||||
@ -257,9 +294,9 @@ const AttendanceLog = ({ handleModalData, searchTerm, organizationId }) => {
|
|||||||
key={`header-${currentDate}`}
|
key={`header-${currentDate}`}
|
||||||
className="table-row-header"
|
className="table-row-header"
|
||||||
>
|
>
|
||||||
<td colSpan={8} className="text-start">
|
<td colSpan={6} className="text-start">
|
||||||
<strong className="d-inline-block my-1 ms-2">
|
<strong>
|
||||||
{formatUTCToLocalTime(currentDate)}
|
{moment(currentDate).format("DD-MM-YYYY")}
|
||||||
</strong>
|
</strong>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -274,12 +311,7 @@ const AttendanceLog = ({ handleModalData, searchTerm, organizationId }) => {
|
|||||||
lastName={attendance.lastName}
|
lastName={attendance.lastName}
|
||||||
/>
|
/>
|
||||||
<div className="d-flex flex-column">
|
<div className="d-flex flex-column">
|
||||||
<a
|
<a href="#" className="text-heading text-truncate">
|
||||||
onClick={() =>
|
|
||||||
navigate(`/employee/${attendance.employeeId}?for=attendance`)
|
|
||||||
}
|
|
||||||
className="text-heading text-truncate cursor-pointer"
|
|
||||||
>
|
|
||||||
<span className="fw-normal">
|
<span className="fw-normal">
|
||||||
{attendance.firstName} {attendance.lastName}
|
{attendance.firstName} {attendance.lastName}
|
||||||
</span>
|
</span>
|
||||||
@ -292,7 +324,6 @@ const AttendanceLog = ({ handleModalData, searchTerm, organizationId }) => {
|
|||||||
attendance.checkInTime || attendance.checkOutTime
|
attendance.checkInTime || attendance.checkOutTime
|
||||||
).format("DD-MMM-YYYY")}
|
).format("DD-MMM-YYYY")}
|
||||||
</td>
|
</td>
|
||||||
<td>{attendance.organizationName || "--"}</td>
|
|
||||||
<td>{convertShortTime(attendance.checkInTime)}</td>
|
<td>{convertShortTime(attendance.checkInTime)}</td>
|
||||||
<td>
|
<td>
|
||||||
{attendance.checkOutTime
|
{attendance.checkOutTime
|
||||||
@ -314,11 +345,7 @@ const AttendanceLog = ({ handleModalData, searchTerm, organizationId }) => {
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
) : (
|
) : (
|
||||||
<div className="my-12">
|
<div className="my-4"><span className="text-secondary">No Record Available !</span></div>
|
||||||
<span className="text-secondary">
|
|
||||||
No attendance record found in selected date range.
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{paginatedAttendances?.length == 0 && filteredSearchData?.length > 0 && (
|
{paginatedAttendances?.length == 0 && filteredSearchData?.length > 0 && (
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { zodResolver } from "@hookform/resolvers/zod";
|
|||||||
import TimePicker from "../common/TimePicker";
|
import TimePicker from "../common/TimePicker";
|
||||||
import { usePositionTracker } from "../../hooks/usePositionTracker";
|
import { usePositionTracker } from "../../hooks/usePositionTracker";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import { markAttendance } from "../../slices/apiSlice/attedanceLogsSlice";
|
||||||
import showToast from "../../services/toastService";
|
import showToast from "../../services/toastService";
|
||||||
import { checkIfCurrentDate } from "../../utils/dateUtils";
|
import { checkIfCurrentDate } from "../../utils/dateUtils";
|
||||||
import { useMarkAttendance } from "../../hooks/useAttendance";
|
import { useMarkAttendance } from "../../hooks/useAttendance";
|
||||||
@ -33,7 +34,7 @@ const createSchema = (modeldata) => {
|
|||||||
const checkOut = new Date(checkIn);
|
const checkOut = new Date(checkIn);
|
||||||
checkOut.setHours(hour, minute, 0, 0);
|
checkOut.setHours(hour, minute, 0, 0);
|
||||||
|
|
||||||
return checkOut >= checkIn;
|
return checkOut > checkIn;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}, {
|
}, {
|
||||||
@ -96,12 +97,12 @@ const CheckInCheckOut = ({ modeldata, closeModal, handleSubmitForm }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form className="row p-2" onSubmit={handleSubmit(onSubmit)}>
|
<form className="row g-2" onSubmit={handleSubmit(onSubmit)}>
|
||||||
<div className="col-12 d-flex justify-content-center mb-4">
|
<div className="col-12 d-flex justify-content-center">
|
||||||
<label className="fs-5 tex-semibold text-center">
|
<label className="fs-5 text-dark text-center">
|
||||||
{modeldata?.checkInTime && !modeldata?.checkOutTime
|
{modeldata?.checkInTime && !modeldata?.checkOutTime
|
||||||
? "Check-Out "
|
? "Check-out :"
|
||||||
: "Check-In "}
|
: "Check-in :"}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -120,7 +121,7 @@ const CheckInCheckOut = ({ modeldata, closeModal, handleSubmitForm }) => {
|
|||||||
modeldata?.checkInTime && !modeldata?.checkOutTime
|
modeldata?.checkInTime && !modeldata?.checkOutTime
|
||||||
? formatDate(modeldata?.checkInTime?.split("T")[0]) || ""
|
? formatDate(modeldata?.checkInTime?.split("T")[0]) || ""
|
||||||
: formatDate(today)
|
: formatDate(today)
|
||||||
}
|
}
|
||||||
disabled
|
disabled
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import "../../components/Project/ProjectInfra.css";
|
import "../../components/Project/ProjectInfra.css";
|
||||||
import BuildingModel from "../Project/Infrastructure/BuildingModel";
|
import BuildingModel from "../Project/Infrastructure/BuildingModel";
|
||||||
@ -7,85 +8,64 @@ import WorkAreaModel from "../Project/Infrastructure/WorkAreaModel";
|
|||||||
import TaskModel from "../Project/Infrastructure/TaskModel";
|
import TaskModel from "../Project/Infrastructure/TaskModel";
|
||||||
import ProjectRepository from "../../repositories/ProjectRepository";
|
import ProjectRepository from "../../repositories/ProjectRepository";
|
||||||
import Breadcrumb from "../../components/common/Breadcrumb";
|
import Breadcrumb from "../../components/common/Breadcrumb";
|
||||||
import {
|
import {useProjectDetails, useProjectInfra, useProjects} from "../../hooks/useProjects";
|
||||||
useCurrentService,
|
import {useHasUserPermission} from "../../hooks/useHasUserPermission";
|
||||||
useProjectDetails,
|
import {APPROVE_TASK, ASSIGN_REPORT_TASK, MANAGE_PROJECT_INFRA} from "../../utils/constants";
|
||||||
useProjectInfra,
|
import {useDispatch, useSelector} from "react-redux";
|
||||||
useProjects,
|
import {useProfile} from "../../hooks/useProfile";
|
||||||
} from "../../hooks/useProjects";
|
import {refreshData, setProjectId} from "../../slices/localVariablesSlice";
|
||||||
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
|
|
||||||
import {
|
|
||||||
APPROVE_TASK,
|
|
||||||
ASSIGN_REPORT_TASK,
|
|
||||||
MANAGE_PROJECT_INFRA,
|
|
||||||
} from "../../utils/constants";
|
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
|
||||||
import { useProfile } from "../../hooks/useProfile";
|
|
||||||
import { refreshData, setProjectId } from "../../slices/localVariablesSlice";
|
|
||||||
import InfraTable from "../Project/Infrastructure/InfraTable";
|
import InfraTable from "../Project/Infrastructure/InfraTable";
|
||||||
import { useSelectedProject } from "../../slices/apiDataManager";
|
import { useSelectedProject } from "../../slices/apiDataManager";
|
||||||
import { SpinnerLoader } from "../common/Loader";
|
import Loader from "../common/Loader";
|
||||||
const InfraPlanning = () => {
|
|
||||||
const { profile: LoggedUser, refetch: fetchData } = useProfile();
|
|
||||||
const dispatch = useDispatch();
|
const InfraPlanning = () =>
|
||||||
|
{
|
||||||
|
const {profile: LoggedUser, refetch : fetchData} = useProfile()
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
// const selectedProject = useSelector((store)=>store.localVariables.projectId)
|
||||||
const selectedProject = useSelectedProject();
|
const selectedProject = useSelectedProject();
|
||||||
const selectedService = useCurrentService();
|
const {projectInfra, isLoading, error} = useProjectInfra( selectedProject )
|
||||||
|
|
||||||
const { projectInfra, isLoading, isError, error, isFetched } =
|
|
||||||
useProjectInfra(selectedProject, selectedService || "");
|
|
||||||
|
|
||||||
const canManageInfra = useHasUserPermission(MANAGE_PROJECT_INFRA);
|
|
||||||
const canApproveTask = useHasUserPermission(APPROVE_TASK);
|
const ManageInfra = useHasUserPermission( MANAGE_PROJECT_INFRA )
|
||||||
const canReportTask = useHasUserPermission(ASSIGN_REPORT_TASK);
|
const ApprovedTaskRights = useHasUserPermission(APPROVE_TASK)
|
||||||
|
const ReportTaskRights = useHasUserPermission(ASSIGN_REPORT_TASK)
|
||||||
|
const reloadedData = useSelector( ( store ) => store.localVariables.reload )
|
||||||
|
|
||||||
const reloadedData = useSelector((store) => store.localVariables.reload);
|
|
||||||
|
// useEffect( () =>
|
||||||
|
// {
|
||||||
|
// if (reloadedData)
|
||||||
|
// {
|
||||||
|
// refetch()
|
||||||
|
// dispatch( refreshData( false ) )
|
||||||
|
// }
|
||||||
|
|
||||||
const hasAccess = canManageInfra || canApproveTask || canReportTask;
|
// },[reloadedData])
|
||||||
|
|
||||||
if (isError) {
|
|
||||||
return <div>{error?.response?.data?.message || error?.message}</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasAccess && !isLoading) {
|
|
||||||
return (
|
|
||||||
<div className="text-center">
|
|
||||||
<i className="fa-solid fa-triangle-exclamation fs-5"></i>
|
|
||||||
<p>Access Denied: You don't have permission to perform this action.</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isLoading) {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className="d-flex justify-content-center align-items-center"
|
|
||||||
style={{ height: "60vh" }}
|
|
||||||
>
|
|
||||||
<SpinnerLoader />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isFetched && (!projectInfra || projectInfra.length === 0)) {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className="text-center d-flex justify-content-center align-items-center text-muted"
|
|
||||||
style={{ minHeight: "40vh", fontSize: "0.9rem" }}
|
|
||||||
>
|
|
||||||
<p className="my-3 m-0">No Result Found</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="col-md-12 col-lg-12 col-xl-12 order-0 mb-4">
|
<div className="col-md-12 col-lg-12 col-xl-12 order-0 mb-4">
|
||||||
|
<div className="card">
|
||||||
<div className="card-body" style={{ padding: "0.5rem" }}>
|
<div className="card-body" style={{ padding: "0.5rem" }}>
|
||||||
<div className="row">
|
{(ApprovedTaskRights || ReportTaskRights) ? (
|
||||||
<InfraTable buildings={projectInfra} projectId={selectedProject} />
|
<div className="align-items-center">
|
||||||
|
<div className="row ">
|
||||||
|
{isLoading && (<Loader/> )}
|
||||||
|
{( !isLoading && projectInfra?.length === 0 ) && ( <p>No Result Found</p> )}
|
||||||
|
{(!isLoading && projectInfra?.length > 0) && (<InfraTable buildings={projectInfra} projectId={selectedProject}/>)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="text-center">
|
||||||
|
<i className="fa-solid fa-triangle-exclamation fs-5"></i>
|
||||||
|
<p>Access Denied: You don't have permission to perform this action. !</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,46 +1,25 @@
|
|||||||
import React, { useCallback, useEffect, useState, useMemo } from "react";
|
import React, { useCallback, useEffect, useState, useMemo } from "react";
|
||||||
import Avatar from "../common/Avatar";
|
import Avatar from "../common/Avatar";
|
||||||
import { convertShortTime, formatUTCToLocalTime } from "../../utils/dateUtils";
|
import { convertShortTime } from "../../utils/dateUtils";
|
||||||
import RegularizationActions from "./RegularizationActions";
|
import RegularizationActions from "./RegularizationActions";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { useRegularizationRequests } from "../../hooks/useAttendance";
|
import { useRegularizationRequests } from "../../hooks/useAttendance";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import usePagination from "../../hooks/usePagination";
|
import usePagination from "../../hooks/usePagination";
|
||||||
import eventBus from "../../services/eventBus";
|
import eventBus from "../../services/eventBus";
|
||||||
import {
|
import { cacheData, clearCacheKey, useSelectedProject } from "../../slices/apiDataManager";
|
||||||
cacheData,
|
|
||||||
clearCacheKey,
|
|
||||||
useSelectedProject,
|
|
||||||
} from "../../slices/apiDataManager";
|
|
||||||
import { useQueryClient } from "@tanstack/react-query";
|
import { useQueryClient } from "@tanstack/react-query";
|
||||||
import Pagination from "../../components/common/Pagination";
|
|
||||||
import { useNavigate } from "react-router-dom";
|
|
||||||
import { SpinnerLoader } from "../common/Loader";
|
|
||||||
|
|
||||||
const Regularization = ({
|
const Regularization = ({ handleRequest, searchTerm }) => {
|
||||||
handleRequest,
|
|
||||||
searchTerm,
|
|
||||||
projectId,
|
|
||||||
organizationId,
|
|
||||||
IncludeInActive,
|
|
||||||
}) => {
|
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
// var selectedProject = useSelector((store) => store.localVariables.projectId);
|
// var selectedProject = useSelector((store) => store.localVariables.projectId);
|
||||||
const selectedProject = useSelectedProject();
|
const selectedProject = useSelectedProject();
|
||||||
const [regularizesList, setregularizedList] = useState([]);
|
const [regularizesList, setregularizedList] = useState([]);
|
||||||
const navigate = useNavigate();
|
const { regularizes, loading, error, refetch } =
|
||||||
const { regularizes, loading, error, refetch } = useRegularizationRequests(
|
useRegularizationRequests(selectedProject);
|
||||||
selectedProject,
|
|
||||||
organizationId,
|
|
||||||
IncludeInActive
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!regularizes) return
|
setregularizedList(regularizes);
|
||||||
if (regularizes?.length) {
|
|
||||||
setregularizedList(regularizes);
|
|
||||||
|
|
||||||
}
|
|
||||||
}, [regularizes]);
|
}, [regularizes]);
|
||||||
|
|
||||||
const sortByName = (a, b) => {
|
const sortByName = (a, b) => {
|
||||||
@ -75,15 +54,18 @@ const Regularization = ({
|
|||||||
}
|
}
|
||||||
const lowercasedSearchTerm = searchTerm.toLowerCase();
|
const lowercasedSearchTerm = searchTerm.toLowerCase();
|
||||||
return sortedList.filter((item) => {
|
return sortedList.filter((item) => {
|
||||||
const fullName = `${item?.firstName} ${item?.lastName}`.toLowerCase();
|
const fullName = `${item.firstName} ${item.lastName}`.toLowerCase();
|
||||||
return fullName.includes(lowercasedSearchTerm);
|
return fullName.includes(lowercasedSearchTerm);
|
||||||
});
|
});
|
||||||
}, [regularizesList, searchTerm]);
|
}, [regularizesList, searchTerm]);
|
||||||
|
|
||||||
const { currentPage, totalPages, currentItems, paginate } = usePagination(
|
const { currentPage, totalPages, currentItems, paginate } =
|
||||||
filteredSearchData,
|
usePagination(filteredSearchData, 20);
|
||||||
20
|
|
||||||
);
|
// Reset pagination when the search term or data changes
|
||||||
|
useEffect(() => {
|
||||||
|
|
||||||
|
}, [filteredSearchData]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
eventBus.on("regularization", handler);
|
eventBus.on("regularization", handler);
|
||||||
@ -105,114 +87,112 @@ const Regularization = ({
|
|||||||
}, [employeeHandler]);
|
}, [employeeHandler]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="table-responsive text-nowrap pb-4" style={{ minHeight: "200px" }}>
|
||||||
<div
|
{loading ? (
|
||||||
className="table-responsive modal-min-h pt-3 text-nowrap pb-4"
|
<div className="d-flex justify-content-center align-items-center" style={{ height: "200px" }}>
|
||||||
style={{ minHeight: "200px" }}
|
<p className="text-secondary">Loading...</p>
|
||||||
>
|
</div>
|
||||||
{loading ? (
|
) : currentItems?.length > 0 ? (
|
||||||
<div
|
<table className="table mb-0">
|
||||||
className="d-flex justify-content-center align-items-center"
|
<thead>
|
||||||
style={{ minHeight: "50vh" }}
|
<tr>
|
||||||
>
|
<th colSpan={2}>Name</th>
|
||||||
<SpinnerLoader />
|
<th>Date</th>
|
||||||
</div>
|
<th>
|
||||||
) : currentItems?.length > 0 ? (
|
<i className="bx bxs-down-arrow-alt text-success"></i>Check-In
|
||||||
<table className="table mb-0">
|
</th>
|
||||||
<thead>
|
<th>
|
||||||
<tr>
|
<i className="bx bxs-up-arrow-alt text-danger"></i>Check-Out
|
||||||
<th colSpan={2}>Name</th>
|
</th>
|
||||||
<th>Date</th>
|
<th>Action</th>
|
||||||
<th>Organization</th>
|
</tr>
|
||||||
<th>
|
</thead>
|
||||||
<i className="bx bxs-down-arrow-alt text-success"></i>Check-In
|
<tbody>
|
||||||
</th>
|
{currentItems?.map((att, index) => (
|
||||||
<th>
|
<tr key={index}>
|
||||||
<i className="bx bxs-up-arrow-alt text-danger"></i>Check-Out
|
<td colSpan={2}>
|
||||||
</th>
|
<div className="d-flex justify-content-start align-items-center">
|
||||||
<th colSpan={2}>
|
<Avatar
|
||||||
Requested By
|
firstName={att.firstName}
|
||||||
</th>
|
lastName={att.lastName}
|
||||||
<th >
|
></Avatar>
|
||||||
Requested At
|
<div className="d-flex flex-column">
|
||||||
</th>
|
<a href="#" className="text-heading text-truncate">
|
||||||
<th>Action</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{currentItems?.map((att, index) => (
|
|
||||||
<tr key={index}>
|
|
||||||
<td colSpan={2}>
|
|
||||||
<div className="d-flex justify-content-start align-items-center">
|
|
||||||
<Avatar firstName={att.firstName} lastName={att.lastName} />
|
|
||||||
<div className="d-flex flex-column"> <a
|
|
||||||
onClick={() =>
|
|
||||||
navigate(`/employee/${att.employeeId}?for=attendance`)
|
|
||||||
}
|
|
||||||
className="text-heading text-truncate cursor-pointer" >
|
|
||||||
<span className="fw-normal">
|
<span className="fw-normal">
|
||||||
{att.firstName} {att.lastName}
|
{att.firstName} {att.lastName}
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</div>
|
||||||
<td>{moment(att.checkOutTime).format("DD-MMM-YYYY")}</td>
|
</td>
|
||||||
|
<td>{moment(att.checkOutTime).format("DD-MMM-YYYY")}</td>
|
||||||
<td>{att.organizationName || "--"}</td>
|
<td>{convertShortTime(att.checkInTime)}</td>
|
||||||
|
<td>
|
||||||
<td>{convertShortTime(att.checkInTime)}</td>
|
{att.checkOutTime ? convertShortTime(att.checkOutTime) : "--"}
|
||||||
<td>
|
</td>
|
||||||
{att.requestedAt ? convertShortTime(att.checkOutTime) : "--"}
|
<td className="text-center ">
|
||||||
</td>
|
<RegularizationActions
|
||||||
|
attendanceData={att}
|
||||||
<td colSpan={2}>
|
handleRequest={handleRequest}
|
||||||
{att.requestedBy ? (<div className="d-flex justify-content-start align-items-center">
|
refresh={refetch}
|
||||||
<Avatar firstName={att?.requestedBy?.firstName} lastName={att?.requestedBy?.lastName} />
|
/>
|
||||||
<div className="d-flex flex-column">
|
{/* </div> */}
|
||||||
<a href="#" className="text-heading text-truncate">
|
</td>
|
||||||
<span className="fw-normal">
|
</tr>
|
||||||
{att?.requestedBy?.firstName} {att?.requestedBy?.lastName}
|
))}
|
||||||
</span>
|
</tbody>
|
||||||
</a>
|
</table>
|
||||||
</div>
|
) : (
|
||||||
</div>) : (<small>--</small>)}
|
<div
|
||||||
</td>
|
className="d-flex justify-content-center align-items-center"
|
||||||
<td>
|
style={{ height: "200px" }}
|
||||||
{att?.requestedAt ? formatUTCToLocalTime(att.requestedAt, true) : "--"}
|
>
|
||||||
</td>
|
<span className="text-secondary">
|
||||||
<td className="text-center ">
|
{searchTerm
|
||||||
<RegularizationActions
|
? "No results found for your search."
|
||||||
attendanceData={att}
|
: "No Requests Found !"}
|
||||||
handleRequest={handleRequest}
|
</span>
|
||||||
refresh={refetch}
|
</div>
|
||||||
/>
|
)}
|
||||||
</td>
|
{!loading && totalPages > 1 && (
|
||||||
</tr>
|
<nav aria-label="Page ">
|
||||||
))}
|
<ul className="pagination pagination-sm justify-content-end py-1 mt-3">
|
||||||
</tbody>
|
<li className={`page-item ${currentPage === 1 ? "disabled" : ""}`}>
|
||||||
</table>
|
<button
|
||||||
) : (
|
className="page-link btn-xs"
|
||||||
<div
|
onClick={() => paginate(currentPage - 1)}
|
||||||
className="d-flex justify-content-center align-items-center"
|
>
|
||||||
style={{ height: "200px" }}
|
«
|
||||||
>
|
</button>
|
||||||
<span className="text-secondary">
|
</li>
|
||||||
{searchTerm
|
{[...Array(totalPages)].map((_, index) => (
|
||||||
? "No results found for your search."
|
<li
|
||||||
: "No Requests Found !"}
|
key={index}
|
||||||
</span>
|
className={`page-item ${currentPage === index + 1 ? "active" : ""
|
||||||
</div>
|
}`}
|
||||||
)}
|
>
|
||||||
</div>
|
<button
|
||||||
{totalPages > 0 && (
|
className="page-link "
|
||||||
<Pagination
|
onClick={() => paginate(index + 1)}
|
||||||
currentPage={currentPage}
|
>
|
||||||
totalPages={totalPages}
|
{index + 1}
|
||||||
onPageChange={paginate}
|
</button>
|
||||||
/>
|
</li>
|
||||||
|
))}
|
||||||
|
<li
|
||||||
|
className={`page-item ${currentPage === totalPages ? "disabled" : ""
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
className="page-link "
|
||||||
|
onClick={() => paginate(currentPage + 1)}
|
||||||
|
>
|
||||||
|
»
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
import React, { act, useEffect, useState } from 'react'
|
import React, { act, useEffect, useState } from 'react'
|
||||||
import useAttendanceStatus, { ACTIONS } from '../../hooks/useAttendanceStatus';
|
import useAttendanceStatus, { ACTIONS } from '../../hooks/useAttendanceStatus';
|
||||||
|
// import AttendanceRepository from '../../repositories/AttendanceRepository';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import { usePositionTracker } from '../../hooks/usePositionTracker';
|
import { usePositionTracker } from '../../hooks/usePositionTracker';
|
||||||
|
import {markCurrentAttendance} from '../../slices/apiSlice/attendanceAllSlice';
|
||||||
import {cacheData, getCachedData, useSelectedProject} from '../../slices/apiDataManager';
|
import {cacheData, getCachedData, useSelectedProject} from '../../slices/apiDataManager';
|
||||||
import showToast from '../../services/toastService';
|
import showToast from '../../services/toastService';
|
||||||
import { useMarkAttendance } from '../../hooks/useAttendance';
|
import { useMarkAttendance } from '../../hooks/useAttendance';
|
||||||
|
|||||||
@ -77,7 +77,7 @@ export const ReportTask = ({ report, closeModal }) => {
|
|||||||
return (
|
return (
|
||||||
<div className="container m-0">
|
<div className="container m-0">
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<p className="fs-5 fw-semibold">Report Task</p>
|
<p className="fs-6 fw-semibold">Report Task</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-1 row text-start">
|
<div className="mb-1 row text-start">
|
||||||
<label htmlFor="html5-text-input" className="col-md-4 col-form-label">
|
<label htmlFor="html5-text-input" className="col-md-4 col-form-label">
|
||||||
@ -101,14 +101,16 @@ export const ReportTask = ({ report, closeModal }) => {
|
|||||||
<label htmlFor="html5-email-input" className="col-md-4 col-form-label">
|
<label htmlFor="html5-email-input" className="col-md-4 col-form-label">
|
||||||
Wrok Area :
|
Wrok Area :
|
||||||
</label>
|
</label>
|
||||||
<div className="col-md-8 text-start">
|
<div className="col-md-8 text-start text-wrap">
|
||||||
<div className="text-wrap">
|
<label className=" col-form-label">
|
||||||
{report?.workItem?.workArea?.floor?.building?.name} <i className="bx bx-chevron-right"></i>
|
{" "}
|
||||||
{report?.workItem?.workArea?.floor?.floorName} <i className="bx bx-chevron-right"></i>
|
{report?.workItem?.workArea?.floor?.building?.name}{" "}
|
||||||
{report?.workItem?.workArea?.areaName}
|
<i className="bx bx-chevron-right"></i>{" "}
|
||||||
</div>
|
{report?.workItem?.workArea?.floor?.floorName}{" "}
|
||||||
</div>
|
<i className="bx bx-chevron-right"> </i>
|
||||||
|
{report?.workItem?.workArea?.areaName}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-1 row text-start">
|
<div className="mb-1 row text-start">
|
||||||
<label htmlFor="html5-email-input" className="col-md-4 col-form-label">
|
<label htmlFor="html5-email-input" className="col-md-4 col-form-label">
|
||||||
|
|||||||
@ -110,8 +110,6 @@ const ReportTaskComments = ({
|
|||||||
approvedTask: defaultCompletedTask || 0,
|
approvedTask: defaultCompletedTask || 0,
|
||||||
});
|
});
|
||||||
}, [defaultCompletedTask]);
|
}, [defaultCompletedTask]);
|
||||||
|
|
||||||
const completed_Task = watch("approvedTask")
|
|
||||||
return (
|
return (
|
||||||
<div className="p-2 p-sm-1">
|
<div className="p-2 p-sm-1">
|
||||||
<div className="modal-body p-sm-4 p-0">
|
<div className="modal-body p-sm-4 p-0">
|
||||||
@ -341,13 +339,13 @@ const ReportTaskComments = ({
|
|||||||
<div
|
<div
|
||||||
className={` ${
|
className={` ${
|
||||||
actionAllow && !commentsData.approvedBy
|
actionAllow && !commentsData.approvedBy
|
||||||
? " d-flex justify-content-between align-items-center"
|
? " d-flex justify-content-between"
|
||||||
: "text-end"
|
: "text-end"
|
||||||
} mt-2`}
|
} mt-2`}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={`form-check ${
|
className={`form-check ${
|
||||||
!(actionAllow && !commentsData.approvedBy && defaultCompletedTask > completed_Task ) && "d-none"
|
!(actionAllow && !commentsData.approvedBy) && "d-none"
|
||||||
} `}
|
} `}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
@ -385,7 +383,7 @@ const ReportTaskComments = ({
|
|||||||
: "Comment"}
|
: "Comment"}
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<ul
|
<ul
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import { zodResolver } from "@hookform/resolvers/zod";
|
|||||||
import { string, z } from "zod";
|
import { string, z } from "zod";
|
||||||
import {
|
import {
|
||||||
useActivitiesMaster,
|
useActivitiesMaster,
|
||||||
useServices,
|
|
||||||
useWorkCategoriesMaster,
|
useWorkCategoriesMaster,
|
||||||
} from "../../hooks/masterHook/useMaster";
|
} from "../../hooks/masterHook/useMaster";
|
||||||
import showToast from "../../services/toastService";
|
import showToast from "../../services/toastService";
|
||||||
@ -26,8 +25,6 @@ const SubTask = ({ activity, onClose }) => {
|
|||||||
const { activities, loading } = useActivitiesMaster();
|
const { activities, loading } = useActivitiesMaster();
|
||||||
const { categories, categoryLoading } = useWorkCategoriesMaster();
|
const { categories, categoryLoading } = useWorkCategoriesMaster();
|
||||||
const { Task, loading: TaskLoading } = useTaskById(activity?.id);
|
const { Task, loading: TaskLoading } = useTaskById(activity?.id);
|
||||||
const {data,isError,isLoading,error} = useServices();
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
@ -100,8 +97,8 @@ const SubTask = ({ activity, onClose }) => {
|
|||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div className="container-xxl my-1">
|
<div className="container-xxl my-1">
|
||||||
<p className="fw-semibold fs-5">Create Sub Task</p>
|
<p className="fw-semibold">Create Sub Task</p>
|
||||||
<form className="row g-2 text-start" onSubmit={handleSubmit(onSubmitForm)}>
|
<form className="row g-2" onSubmit={handleSubmit(onSubmitForm)}>
|
||||||
<div className="col-6">
|
<div className="col-6">
|
||||||
<label className="form-label">Building</label>
|
<label className="form-label">Building</label>
|
||||||
<input
|
<input
|
||||||
@ -131,15 +128,27 @@ const SubTask = ({ activity, onClose }) => {
|
|||||||
disabled
|
disabled
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-12">
|
|
||||||
<label className="form-label">Service</label>
|
<div className="col-12">
|
||||||
<input
|
<label className="form-label">Work Category</label>
|
||||||
type="text"
|
<select
|
||||||
className="form-control form-control-sm"
|
className="form-select form-select-sm"
|
||||||
value={activity?.workItem?.activityMaster?.activityGroup?.service?.name || ""}
|
{...register("workCategoryId")}
|
||||||
disabled
|
onChange={handleCategoryChange}
|
||||||
/>
|
>
|
||||||
</div>
|
<option value="">
|
||||||
|
{categoryLoading ? "Loading..." : "-- Select Category --"}
|
||||||
|
</option>
|
||||||
|
{categoryData.map((category) => (
|
||||||
|
<option key={category.id} value={category.id}>
|
||||||
|
{category.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
{errors.workCategoryId && (
|
||||||
|
<div className="danger-text">{errors.workCategoryId.message}</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<label className="form-label">Select Activity</label>
|
<label className="form-label">Select Activity</label>
|
||||||
<select
|
<select
|
||||||
@ -163,27 +172,6 @@ const SubTask = ({ activity, onClose }) => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col-12">
|
|
||||||
<label className="form-label">Work Category</label>
|
|
||||||
<select
|
|
||||||
className="form-select form-select-sm"
|
|
||||||
{...register("workCategoryId")}
|
|
||||||
onChange={handleCategoryChange}
|
|
||||||
>
|
|
||||||
<option value="">
|
|
||||||
{categoryLoading ? "Loading..." : "-- Select Category --"}
|
|
||||||
</option>
|
|
||||||
{categoryData.map((category) => (
|
|
||||||
<option key={category.id} value={category.id}>
|
|
||||||
{category.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
{errors.workCategoryId && (
|
|
||||||
<div className="danger-text">{errors.workCategoryId.message}</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="col-4">
|
<div className="col-4">
|
||||||
<label className="form-label">Planned Work</label>
|
<label className="form-label">Planned Work</label>
|
||||||
<input
|
<input
|
||||||
@ -231,15 +219,7 @@ const SubTask = ({ activity, onClose }) => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="d-flex flex-row gap-3 justify-content-end py-2">
|
<div className="col-12 text-center">
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="btn btn-sm btn-label-secondary"
|
|
||||||
onClick={() => onClose()}
|
|
||||||
disabled={isPending}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="btn btn-sm btn-primary me-2"
|
className="btn btn-sm btn-primary me-2"
|
||||||
@ -247,7 +227,14 @@ const SubTask = ({ activity, onClose }) => {
|
|||||||
>
|
>
|
||||||
{isPending ? "Please wait..." : "Submit"}
|
{isPending ? "Please wait..." : "Submit"}
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-sm btn-secondary"
|
||||||
|
onClick={() => onClose()}
|
||||||
|
disabled={isPending}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,233 +0,0 @@
|
|||||||
|
|
||||||
import React, { useEffect, useMemo } from "react";
|
|
||||||
import { useExpenseAllTransactionsList, useExpenseTransactions } from "../../hooks/useExpense";
|
|
||||||
import Error from "../common/Error";
|
|
||||||
import { formatUTCToLocalTime } from "../../utils/dateUtils";
|
|
||||||
import Loader, { SpinnerLoader } from "../common/Loader";
|
|
||||||
import { useForm, useFormContext } from "react-hook-form";
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
|
||||||
import { z } from "zod";
|
|
||||||
import { employee } from "../../data/masters";
|
|
||||||
import { useAdvancePaymentContext } from "../../pages/AdvancePayment/AdvancePaymentPage";
|
|
||||||
import { formatFigure } from "../../utils/appUtils";
|
|
||||||
|
|
||||||
const AdvancePaymentList = ({ employeeId, searchString }) => {
|
|
||||||
const { setBalance } = useAdvancePaymentContext();
|
|
||||||
const { data, isError, isLoading, error, isFetching } =
|
|
||||||
useExpenseTransactions(employeeId, { enabled: !!employeeId });
|
|
||||||
const records = Array.isArray(data) ? data : [];
|
|
||||||
|
|
||||||
let currentBalance = 0;
|
|
||||||
const rowsWithBalance = records.map((r) => {
|
|
||||||
const isCredit = r.amount > 0;
|
|
||||||
const credit = isCredit ? r.amount : 0;
|
|
||||||
const debit = !isCredit ? Math.abs(r.amount) : 0;
|
|
||||||
currentBalance += credit - debit;
|
|
||||||
return {
|
|
||||||
id: r.id,
|
|
||||||
description: r.title || "-",
|
|
||||||
projectName: r.project?.name || "-",
|
|
||||||
createdAt: r.createdAt,
|
|
||||||
credit,
|
|
||||||
debit,
|
|
||||||
financeUId: r.financeUId,
|
|
||||||
balance: currentBalance,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!employeeId) {
|
|
||||||
setBalance(null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rowsWithBalance.length > 0) {
|
|
||||||
setBalance(rowsWithBalance[rowsWithBalance.length - 1].balance);
|
|
||||||
} else {
|
|
||||||
setBalance(0);
|
|
||||||
}
|
|
||||||
}, [employeeId, data, setBalance]);
|
|
||||||
|
|
||||||
if (!employeeId) {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className="d-flex justify-content-center align-items-center"
|
|
||||||
style={{ height: "200px" }}
|
|
||||||
>
|
|
||||||
<p className="text-muted m-0">Please select an employee</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isLoading || isFetching) {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className="d-flex justify-content-center align-items-center"
|
|
||||||
style={{ height: "200px" }}
|
|
||||||
>
|
|
||||||
<SpinnerLoader />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isError) {
|
|
||||||
return (
|
|
||||||
<div className="text-center py-3">
|
|
||||||
{error?.status === 404
|
|
||||||
? "No advance payment transactions found."
|
|
||||||
: <Error error={error} />}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
key: "date",
|
|
||||||
label: (
|
|
||||||
<>
|
|
||||||
Date
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
align: "text-start",
|
|
||||||
},
|
|
||||||
{ key: "description", label: "Description", align: "text-start" },
|
|
||||||
|
|
||||||
{
|
|
||||||
key: "credit",
|
|
||||||
label: (
|
|
||||||
<>
|
|
||||||
Credit <i className="bx bx-rupee text-success"></i>
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
align: "text-end",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "debit",
|
|
||||||
label: (
|
|
||||||
<>
|
|
||||||
Debit <i className="bx bx-rupee text-danger"></i>
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
align: "text-end",
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
key: "balance",
|
|
||||||
label: (
|
|
||||||
<>
|
|
||||||
Balance <i className="bi bi-currency-rupee text-primary"></i>
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
align: "text-end fw-bold",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
// Handle empty records
|
|
||||||
if (rowsWithBalance.length === 0) {
|
|
||||||
return (
|
|
||||||
<div className="text-center text-muted py-3">
|
|
||||||
No advance payment records found.
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const DecideCreditOrDebit = ({ financeUId }) => {
|
|
||||||
if (!financeUId) return null;
|
|
||||||
|
|
||||||
const prefix = financeUId?.substring(0, 2).toUpperCase();
|
|
||||||
|
|
||||||
if (prefix === "PR") return <span className="text-success">+</span>;
|
|
||||||
if (prefix === "EX") return <span className="text-danger">-</span>;
|
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="table-responsive">
|
|
||||||
<table className="table align-middle">
|
|
||||||
<thead className="table_header_border">
|
|
||||||
<tr>
|
|
||||||
{columns.map((col) => (
|
|
||||||
<th key={col.key} className={col.align}>
|
|
||||||
{col.label}
|
|
||||||
</th>
|
|
||||||
))}
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{Array.isArray(data) && data.length > 0 ? (
|
|
||||||
data.map((row) => (
|
|
||||||
<tr key={row.id}>
|
|
||||||
{columns.map((col) => (
|
|
||||||
<td key={col.key} className={`${col.align} p-2`}>
|
|
||||||
{col.key === "credit" ? (
|
|
||||||
row.amount > 0 ? (
|
|
||||||
<span>{row.amount.toLocaleString("en-IN")}</span>
|
|
||||||
) : (
|
|
||||||
"-"
|
|
||||||
)
|
|
||||||
) : col.key === "debit" ? (
|
|
||||||
row.amount < 0 ? (
|
|
||||||
<span>
|
|
||||||
{Math.abs(row.amount).toLocaleString("en-IN")}
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
"-"
|
|
||||||
)
|
|
||||||
) : col.key === "balance" ? (
|
|
||||||
<div className="d-flex align-items-center justify-content-end">
|
|
||||||
{/* <DecideCreditOrDebit financeUId={row?.financeUId} /> */}
|
|
||||||
<span className="mx-2">
|
|
||||||
{formatFigure(row.currentBalance)}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
) : col.key === "date" ? (
|
|
||||||
<small className="text-muted px-1">
|
|
||||||
{formatUTCToLocalTime(row.paidAt)}
|
|
||||||
</small>
|
|
||||||
) : (
|
|
||||||
<div className="d-flex flex-column text-start gap-1 py-1">
|
|
||||||
<small className="fw-semibold text-dark">
|
|
||||||
{row.project?.name || "-"}
|
|
||||||
</small>
|
|
||||||
<small>{row.title || "-"}</small>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</td>
|
|
||||||
))}
|
|
||||||
</tr>
|
|
||||||
))
|
|
||||||
) : (
|
|
||||||
<tr>
|
|
||||||
<td
|
|
||||||
colSpan={columns.length}
|
|
||||||
className="text-center text-muted py-3"
|
|
||||||
>
|
|
||||||
No advance payment records found.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
)}
|
|
||||||
</tbody>
|
|
||||||
|
|
||||||
<tfoot className=" fw-bold">
|
|
||||||
<tr className="tr-group text-dark py-2">
|
|
||||||
<td className="text-start">
|
|
||||||
{" "}
|
|
||||||
<div className="d-flex align-items-center px-1 py-2">
|
|
||||||
Final Balance
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td className="text-end" colSpan="4">
|
|
||||||
<div className="d-flex align-items-center justify-content-end px-1 py-2">
|
|
||||||
{currentBalance.toLocaleString("en-IN", {
|
|
||||||
style: "currency",
|
|
||||||
currency: "INR",
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AdvancePaymentList;
|
|
||||||
@ -1,100 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import Avatar from "../../components/common/Avatar"; // <-- ADD THIS
|
|
||||||
import { useExpenseAllTransactionsList } from '../../hooks/useExpense';
|
|
||||||
import { useNavigate } from 'react-router-dom';
|
|
||||||
import { formatFigure } from '../../utils/appUtils';
|
|
||||||
|
|
||||||
const AdvancePaymentList1 = ({ searchString }) => {
|
|
||||||
|
|
||||||
const { data, isError, isLoading, error } =
|
|
||||||
useExpenseAllTransactionsList(searchString);
|
|
||||||
|
|
||||||
const rows = data || [];
|
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
key: "employee",
|
|
||||||
label: "Employee Name",
|
|
||||||
align: "text-start",
|
|
||||||
customRender: (r) => (
|
|
||||||
<div className="d-flex align-items-center gap-2" onClick={() => navigate(`/advance-payment/${r.id}`)}
|
|
||||||
style={{ cursor: "pointer" }}>
|
|
||||||
<Avatar firstName={r.firstName} lastName={r.lastName} />
|
|
||||||
|
|
||||||
<span className="fw-medium">
|
|
||||||
{r.firstName} {r.lastName}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "jobRoleName",
|
|
||||||
label: "Job Role",
|
|
||||||
align: "text-start",
|
|
||||||
customRender: (r) => (
|
|
||||||
<span className="fw-semibold">
|
|
||||||
{r.jobRoleName}
|
|
||||||
</span>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "balanceAmount",
|
|
||||||
label: "Balance (₹)",
|
|
||||||
align: "text-end",
|
|
||||||
customRender: (r) => (
|
|
||||||
<span className="fw-semibold fs-6">
|
|
||||||
{formatFigure(r.balanceAmount, {
|
|
||||||
// type: "currency",
|
|
||||||
currency: "INR",
|
|
||||||
})}
|
|
||||||
</span>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
if (isLoading) return <p className="text-center py-4">Loading...</p>;
|
|
||||||
if (isError) return <p className="text-center py-4 text-danger">{error.message}</p>;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="card-datatable" id="payment-request-table">
|
|
||||||
<div className="mx-2">
|
|
||||||
<table className="table border-top dataTable text-nowrap align-middle">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
{columns.map((col) => (
|
|
||||||
<th key={col.key} className={`sorting ${col.align}`}>
|
|
||||||
{col.label}
|
|
||||||
</th>
|
|
||||||
))}
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
|
|
||||||
<tbody>
|
|
||||||
{rows.length > 0 ? (
|
|
||||||
rows.map((row) => (
|
|
||||||
<tr key={row.id} className="align-middle" style={{ height: "40px" }}>
|
|
||||||
{columns.map((col) => (
|
|
||||||
<td key={col.key} className={`d-table-cell ${col.align} py-3`}>
|
|
||||||
{col.customRender
|
|
||||||
? col.customRender(row)
|
|
||||||
: col.getValue(row)}
|
|
||||||
</td>
|
|
||||||
))}
|
|
||||||
</tr>
|
|
||||||
))
|
|
||||||
) : (
|
|
||||||
<tr>
|
|
||||||
<td colSpan={columns.length} className="text-center border-0 py-3">
|
|
||||||
No Employees Found
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
)}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AdvancePaymentList1;
|
|
||||||