Compare commits
6 Commits
bd4a3656e7
...
35eb073f46
| Author | SHA1 | Date |
|---|---|---|
|
|
35eb073f46 | |
|
|
94eedff8af | |
|
|
ac3ddf4b2b | |
|
|
a55e6ccba4 | |
|
|
f1c66c6621 | |
|
|
35fa90705b |
Binary file not shown.
|
|
@ -86,6 +86,7 @@
|
||||||
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
|
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.27.1",
|
"@babel/code-frame": "^7.27.1",
|
||||||
"@babel/generator": "^7.28.5",
|
"@babel/generator": "^7.28.5",
|
||||||
|
|
@ -2879,6 +2880,7 @@
|
||||||
"integrity": "sha512-RFA/bURkcKzx/X9oumPG9Vp3D3JUgus/d0b67KB0t5S/raciymilkOa66olh78MUI92QLbEJevO7rvqU/kjwKA==",
|
"integrity": "sha512-RFA/bURkcKzx/X9oumPG9Vp3D3JUgus/d0b67KB0t5S/raciymilkOa66olh78MUI92QLbEJevO7rvqU/kjwKA==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/prop-types": "*",
|
"@types/prop-types": "*",
|
||||||
"csstype": "^3.0.2"
|
"csstype": "^3.0.2"
|
||||||
|
|
@ -3149,6 +3151,7 @@
|
||||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fast-deep-equal": "^3.1.1",
|
"fast-deep-equal": "^3.1.1",
|
||||||
"fast-json-stable-stringify": "^2.0.0",
|
"fast-json-stable-stringify": "^2.0.0",
|
||||||
|
|
@ -3351,7 +3354,6 @@
|
||||||
"integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==",
|
"integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"archiver-utils": "^2.1.0",
|
"archiver-utils": "^2.1.0",
|
||||||
"async": "^3.2.4",
|
"async": "^3.2.4",
|
||||||
|
|
@ -3371,7 +3373,6 @@
|
||||||
"integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==",
|
"integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"glob": "^7.1.4",
|
"glob": "^7.1.4",
|
||||||
"graceful-fs": "^4.2.0",
|
"graceful-fs": "^4.2.0",
|
||||||
|
|
@ -3393,8 +3394,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||||
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/archiver-utils/node_modules/readable-stream": {
|
"node_modules/archiver-utils/node_modules/readable-stream": {
|
||||||
"version": "2.3.8",
|
"version": "2.3.8",
|
||||||
|
|
@ -3402,7 +3402,6 @@
|
||||||
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
|
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-util-is": "~1.0.0",
|
"core-util-is": "~1.0.0",
|
||||||
"inherits": "~2.0.3",
|
"inherits": "~2.0.3",
|
||||||
|
|
@ -3418,8 +3417,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/archiver-utils/node_modules/string_decoder": {
|
"node_modules/archiver-utils/node_modules/string_decoder": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
|
|
@ -3427,7 +3425,6 @@
|
||||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"safe-buffer": "~5.1.0"
|
"safe-buffer": "~5.1.0"
|
||||||
}
|
}
|
||||||
|
|
@ -3712,6 +3709,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"baseline-browser-mapping": "^2.8.25",
|
"baseline-browser-mapping": "^2.8.25",
|
||||||
"caniuse-lite": "^1.0.30001754",
|
"caniuse-lite": "^1.0.30001754",
|
||||||
|
|
@ -4329,7 +4327,6 @@
|
||||||
"integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==",
|
"integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"buffer-crc32": "^0.2.13",
|
"buffer-crc32": "^0.2.13",
|
||||||
"crc32-stream": "^4.0.2",
|
"crc32-stream": "^4.0.2",
|
||||||
|
|
@ -4531,7 +4528,6 @@
|
||||||
"integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
|
"integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"crc32": "bin/crc32.njs"
|
"crc32": "bin/crc32.njs"
|
||||||
},
|
},
|
||||||
|
|
@ -4545,7 +4541,6 @@
|
||||||
"integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==",
|
"integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"crc-32": "^1.2.0",
|
"crc-32": "^1.2.0",
|
||||||
"readable-stream": "^3.4.0"
|
"readable-stream": "^3.4.0"
|
||||||
|
|
@ -5027,6 +5022,7 @@
|
||||||
"integrity": "sha512-NoXo6Liy2heSklTI5OIZbCgXC1RzrDQsZkeEwXhdOro3FT1VBOvbubvscdPnjVuQ4AMwwv61oaH96AbiYg9EnQ==",
|
"integrity": "sha512-NoXo6Liy2heSklTI5OIZbCgXC1RzrDQsZkeEwXhdOro3FT1VBOvbubvscdPnjVuQ4AMwwv61oaH96AbiYg9EnQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"app-builder-lib": "25.1.8",
|
"app-builder-lib": "25.1.8",
|
||||||
"builder-util": "25.1.7",
|
"builder-util": "25.1.7",
|
||||||
|
|
@ -5246,7 +5242,6 @@
|
||||||
"integrity": "sha512-2ntkJ+9+0GFP6nAISiMabKt6eqBB0kX1QqHNWFWAXgi0VULKGisM46luRFpIBiU3u/TDmhZMM8tzvo2Abn3ayg==",
|
"integrity": "sha512-2ntkJ+9+0GFP6nAISiMabKt6eqBB0kX1QqHNWFWAXgi0VULKGisM46luRFpIBiU3u/TDmhZMM8tzvo2Abn3ayg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"app-builder-lib": "25.1.8",
|
"app-builder-lib": "25.1.8",
|
||||||
"archiver": "^5.3.1",
|
"archiver": "^5.3.1",
|
||||||
|
|
@ -5260,7 +5255,6 @@
|
||||||
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
|
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"graceful-fs": "^4.2.0",
|
"graceful-fs": "^4.2.0",
|
||||||
"jsonfile": "^6.0.1",
|
"jsonfile": "^6.0.1",
|
||||||
|
|
@ -5276,7 +5270,6 @@
|
||||||
"integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==",
|
"integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"universalify": "^2.0.0"
|
"universalify": "^2.0.0"
|
||||||
},
|
},
|
||||||
|
|
@ -5290,7 +5283,6 @@
|
||||||
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 10.0.0"
|
"node": ">= 10.0.0"
|
||||||
}
|
}
|
||||||
|
|
@ -6239,8 +6231,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||||
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
|
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/fs-extra": {
|
"node_modules/fs-extra": {
|
||||||
"version": "8.1.0",
|
"version": "8.1.0",
|
||||||
|
|
@ -7176,7 +7167,7 @@
|
||||||
"version": "0.6.3",
|
"version": "0.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||||
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||||
"dev": true,
|
"devOptional": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||||
|
|
@ -7927,7 +7918,6 @@
|
||||||
"integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==",
|
"integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"readable-stream": "^2.0.5"
|
"readable-stream": "^2.0.5"
|
||||||
},
|
},
|
||||||
|
|
@ -7940,8 +7930,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||||
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/lazystream/node_modules/readable-stream": {
|
"node_modules/lazystream/node_modules/readable-stream": {
|
||||||
"version": "2.3.8",
|
"version": "2.3.8",
|
||||||
|
|
@ -7949,7 +7938,6 @@
|
||||||
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
|
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-util-is": "~1.0.0",
|
"core-util-is": "~1.0.0",
|
||||||
"inherits": "~2.0.3",
|
"inherits": "~2.0.3",
|
||||||
|
|
@ -7965,8 +7953,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/lazystream/node_modules/string_decoder": {
|
"node_modules/lazystream/node_modules/string_decoder": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
|
|
@ -7974,7 +7961,6 @@
|
||||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"safe-buffer": "~5.1.0"
|
"safe-buffer": "~5.1.0"
|
||||||
}
|
}
|
||||||
|
|
@ -8279,24 +8265,21 @@
|
||||||
"resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
|
||||||
"integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==",
|
"integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/lodash.difference": {
|
"node_modules/lodash.difference": {
|
||||||
"version": "4.5.0",
|
"version": "4.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz",
|
||||||
"integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==",
|
"integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/lodash.flatten": {
|
"node_modules/lodash.flatten": {
|
||||||
"version": "4.4.0",
|
"version": "4.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
|
||||||
"integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==",
|
"integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/lodash.isequal": {
|
"node_modules/lodash.isequal": {
|
||||||
"version": "4.5.0",
|
"version": "4.5.0",
|
||||||
|
|
@ -8310,16 +8293,14 @@
|
||||||
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
|
||||||
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
|
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/lodash.union": {
|
"node_modules/lodash.union": {
|
||||||
"version": "4.6.0",
|
"version": "4.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz",
|
||||||
"integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==",
|
"integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/log-symbols": {
|
"node_modules/log-symbols": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
|
|
@ -9124,7 +9105,6 @@
|
||||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
|
|
@ -9816,8 +9796,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/progress": {
|
"node_modules/progress": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
|
|
@ -9960,6 +9939,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
||||||
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
|
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.1.0"
|
"loose-envify": "^1.1.0"
|
||||||
},
|
},
|
||||||
|
|
@ -9972,6 +9952,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
||||||
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
|
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.1.0",
|
"loose-envify": "^1.1.0",
|
||||||
"scheduler": "^0.23.2"
|
"scheduler": "^0.23.2"
|
||||||
|
|
@ -10021,6 +10002,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz",
|
||||||
"integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==",
|
"integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/use-sync-external-store": "^0.0.6",
|
"@types/use-sync-external-store": "^0.0.6",
|
||||||
"use-sync-external-store": "^1.4.0"
|
"use-sync-external-store": "^1.4.0"
|
||||||
|
|
@ -10167,7 +10149,6 @@
|
||||||
"integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==",
|
"integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"minimatch": "^5.1.0"
|
"minimatch": "^5.1.0"
|
||||||
}
|
}
|
||||||
|
|
@ -10178,7 +10159,6 @@
|
||||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0"
|
"balanced-match": "^1.0.0"
|
||||||
}
|
}
|
||||||
|
|
@ -10189,7 +10169,6 @@
|
||||||
"integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
|
"integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^2.0.1"
|
"brace-expansion": "^2.0.1"
|
||||||
},
|
},
|
||||||
|
|
@ -10233,7 +10212,8 @@
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
|
||||||
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
|
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/redux-thunk": {
|
"node_modules/redux-thunk": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
|
|
@ -11512,7 +11492,6 @@
|
||||||
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
|
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bl": "^4.0.3",
|
"bl": "^4.0.3",
|
||||||
"end-of-stream": "^1.4.1",
|
"end-of-stream": "^1.4.1",
|
||||||
|
|
@ -11983,6 +11962,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz",
|
||||||
"integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",
|
"integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.21.3",
|
"esbuild": "^0.21.3",
|
||||||
"postcss": "^8.4.43",
|
"postcss": "^8.4.43",
|
||||||
|
|
@ -12544,7 +12524,6 @@
|
||||||
"integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==",
|
"integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"archiver-utils": "^3.0.4",
|
"archiver-utils": "^3.0.4",
|
||||||
"compress-commons": "^4.1.2",
|
"compress-commons": "^4.1.2",
|
||||||
|
|
@ -12560,7 +12539,6 @@
|
||||||
"integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==",
|
"integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"glob": "^7.2.3",
|
"glob": "^7.2.3",
|
||||||
"graceful-fs": "^4.2.0",
|
"graceful-fs": "^4.2.0",
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,6 @@
|
||||||
"axios": "^1.13.2",
|
"axios": "^1.13.2",
|
||||||
"chalk": "^5.6.2",
|
"chalk": "^5.6.2",
|
||||||
"electron-store": "^11.0.2",
|
"electron-store": "^11.0.2",
|
||||||
"quill": "^2.0.3",
|
|
||||||
"react-quill-new": "^3.6.0",
|
|
||||||
"https": "^1.0.0",
|
"https": "^1.0.0",
|
||||||
"lucide-react": "^0.552.0",
|
"lucide-react": "^0.552.0",
|
||||||
"luxon": "^3.7.2",
|
"luxon": "^3.7.2",
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ const httpsAgent = new https.Agent({
|
||||||
});
|
});
|
||||||
|
|
||||||
const api: AxiosInstance = axios.create({
|
const api: AxiosInstance = axios.create({
|
||||||
baseURL: 'http://localhost:3000/api/v1/va', // 🔁 your backend
|
baseURL: 'https://quality-friendly-goldfish.ngrok-free.app/api/v1/va', // 🔁 your backend
|
||||||
httpsAgent
|
httpsAgent
|
||||||
// timeout: 10000,
|
// timeout: 10000,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -342,26 +342,44 @@ ipcMain.handle("create-timesheet", async (event, data) => {
|
||||||
|
|
||||||
ipcMain.handle("create-leave-request", async (event, payload) => {
|
ipcMain.handle("create-leave-request", async (event, payload) => {
|
||||||
try {
|
try {
|
||||||
console.log(" Leave Request Received:", payload);
|
console.log("Leave Request Received:", payload);
|
||||||
|
|
||||||
const response = await api.post("/leave/request", payload);
|
const response = await api.post("/leave/request", payload);
|
||||||
|
|
||||||
console.log(" Leave Saved:", response.data);
|
console.log("Leave Saved:", response);
|
||||||
|
|
||||||
return { success: true, data: response.data };
|
return {
|
||||||
|
success: true,
|
||||||
|
data: response.data
|
||||||
|
};
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error: any) {
|
||||||
console.error("❌ Leave Save Failed:", error);
|
console.error("❌ Leave Save Failed:");
|
||||||
|
|
||||||
|
let message = "Unknown error";
|
||||||
|
|
||||||
|
if (error.response) {
|
||||||
|
console.log("Status:", error.response.status);
|
||||||
|
console.log("Message:", error.response.statusText);
|
||||||
|
console.log("Server Response:", error.response.data);
|
||||||
|
|
||||||
|
// Extract the backend message properly
|
||||||
|
message = error.response.data?.message || error.response.statusText;
|
||||||
|
} else {
|
||||||
|
message = error.message;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
error: error || "Unknown error"
|
message
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const sendTokenExpired = () => {
|
export const sendTokenExpired = () => {
|
||||||
console.log("⚠️ Sending token-expired event to renderer");
|
console.log("⚠️ Sending token-expired event to renderer");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ app.on("ready", async () => {
|
||||||
minimizable: false,
|
minimizable: false,
|
||||||
maximizable: false,
|
maximizable: false,
|
||||||
closable: true,
|
closable: true,
|
||||||
alwaysOnTop: true,
|
// alwaysOnTop: true,
|
||||||
// skipTaskbar: true,
|
// skipTaskbar: true,
|
||||||
autoHideMenuBar: true,
|
autoHideMenuBar: true,
|
||||||
frame: true,
|
frame: true,
|
||||||
|
|
@ -101,9 +101,24 @@ app.on("ready", async () => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
win.setAlwaysOnTop(true, 'screen-saver');
|
|
||||||
win.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true });
|
|
||||||
win.setFullScreenable(false);
|
// win.setAlwaysOnTop(true, 'screen-saver');
|
||||||
|
// win.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true });
|
||||||
|
// win.setFullScreenable(false);
|
||||||
|
|
||||||
|
// Cross-platform safe always-on-top
|
||||||
|
const isMac = process.platform === "darwin";
|
||||||
|
|
||||||
|
if (isMac) {
|
||||||
|
win.setAlwaysOnTop(true, "floating"); // best for macOS
|
||||||
|
win.setVisibleOnAllWorkspaces(true); // NO fullscreen override
|
||||||
|
} else {
|
||||||
|
win.setAlwaysOnTop(true, "normal"); // safest for Windows + Zoom
|
||||||
|
win.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true });
|
||||||
|
win.setFullScreenable(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
mainWindow = win;
|
mainWindow = win;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ export const handleLogin = async (credentials: { email: string, password: string
|
||||||
try {
|
try {
|
||||||
console.log("➡️ Calling API...");
|
console.log("➡️ Calling API...");
|
||||||
const response = await axios.post(
|
const response = await axios.post(
|
||||||
'http://localhost:3000/api/v1/va/login',
|
'https://quality-friendly-goldfish.ngrok-free.app/api/v1/va/login',
|
||||||
{ userDetails: { ...credentials } },
|
{ userDetails: { ...credentials } },
|
||||||
{ headers: { "ngrok-skip-browser-warning": 69420 }, httpsAgent }
|
{ headers: { "ngrok-skip-browser-warning": 69420 }, httpsAgent }
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,7 @@ import Timesheets from "./pages/Timesheets/Timesheets";
|
||||||
import Settings from "./pages/Settings/Settings";
|
import Settings from "./pages/Settings/Settings";
|
||||||
import HelpSupport from "./pages/HelpSupport/HelpSupport";
|
import HelpSupport from "./pages/HelpSupport/HelpSupport";
|
||||||
import Vpn from "./pages/Vpn/Vpn";
|
import Vpn from "./pages/Vpn/Vpn";
|
||||||
|
import Schedule from "./pages/Schedule/Schedule";
|
||||||
|
|
||||||
|
|
||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
|
|
@ -140,6 +141,7 @@ const App: React.FC = () => {
|
||||||
<Route path="settings" element={<Settings />} />
|
<Route path="settings" element={<Settings />} />
|
||||||
<Route path="vpn" element={<Vpn />} />
|
<Route path="vpn" element={<Vpn />} />
|
||||||
<Route path="help-support" element={<HelpSupport />} />
|
<Route path="help-support" element={<HelpSupport />} />
|
||||||
|
<Route path="schedule" element={<Schedule/>} />
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
{/* Default Redirect */}
|
{/* Default Redirect */}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import {
|
||||||
Play,
|
Play,
|
||||||
ChevronUp,
|
ChevronUp,
|
||||||
GlobeLock,
|
GlobeLock,
|
||||||
|
ClipboardClock,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { useActiveAppTracker } from "../hooks/useActiveAppTracker";
|
import { useActiveAppTracker } from "../hooks/useActiveAppTracker";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
|
@ -111,6 +112,7 @@ const DashboardLayout = () => {
|
||||||
{ label: "Dashboard", path: "/dashboard", icon: <Home size={18} />, exact: true },
|
{ label: "Dashboard", path: "/dashboard", icon: <Home size={18} />, exact: true },
|
||||||
{ label: "Timesheet", path: "/dashboard/timesheet", icon: <TimerIcon size={18} /> },
|
{ label: "Timesheet", path: "/dashboard/timesheet", icon: <TimerIcon size={18} /> },
|
||||||
{ label: "Leave & Adjust", path: "/dashboard/leave-adjustments", icon: <CalendarDays size={18} /> },
|
{ label: "Leave & Adjust", path: "/dashboard/leave-adjustments", icon: <CalendarDays size={18} /> },
|
||||||
|
{ label: "Schedule", path: "/dashboard/schedule", icon: <ClipboardClock size={18} />},
|
||||||
{ label: "Settings", path: "/dashboard/settings", icon: <SettingsIcon size={18} /> },
|
{ label: "Settings", path: "/dashboard/settings", icon: <SettingsIcon size={18} /> },
|
||||||
{ label: "VPN", path: "/dashboard/vpn", icon: <GlobeLock size={18} /> },
|
{ label: "VPN", path: "/dashboard/vpn", icon: <GlobeLock size={18} /> },
|
||||||
{ label: "Help & Support", path: "/dashboard/help-support", icon: <HelpCircleIcon size={18} /> },
|
{ label: "Help & Support", path: "/dashboard/help-support", icon: <HelpCircleIcon size={18} /> },
|
||||||
|
|
|
||||||
|
|
@ -25,16 +25,19 @@ const LeaveAndAdjustments: React.FC = () => {
|
||||||
|
|
||||||
console.log("Leave /sick Payload:", payload);
|
console.log("Leave /sick Payload:", payload);
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
const response = await window.electron.createPTOAndSickLeaveRequest(payload)
|
const response = await window.electron.createPTOAndSickLeaveRequest(payload)
|
||||||
console.log("Leave Payload:" ,response)
|
console.log("Leave Payload:", response)
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
return true;
|
return { success: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: response.message
|
||||||
|
};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
return false;
|
return { success: false, message: "Request failed" };
|
||||||
} finally {
|
} finally {
|
||||||
setIsSubmitting(false);
|
setIsSubmitting(false);
|
||||||
}
|
}
|
||||||
|
|
@ -49,9 +52,8 @@ const LeaveAndAdjustments: React.FC = () => {
|
||||||
<div role="tablist" className="tabs tabs-border w-full mb-1 opacity-100">
|
<div role="tablist" className="tabs tabs-border w-full mb-1 opacity-100">
|
||||||
<a
|
<a
|
||||||
role="tab"
|
role="tab"
|
||||||
className={`tab text-xs font-semibold ${
|
className={`tab text-xs font-semibold ${activeTab === "pto" ? "tab-active text-primary" : ""
|
||||||
activeTab === "pto" ? "tab-active text-primary" : ""
|
} ${isSubmitting ? "pointer-events-none opacity-50" : ""}`}
|
||||||
} ${isSubmitting ? "pointer-events-none opacity-50" : ""}`}
|
|
||||||
onClick={() => setActiveTab("pto")}
|
onClick={() => setActiveTab("pto")}
|
||||||
>
|
>
|
||||||
PTO Leave
|
PTO Leave
|
||||||
|
|
@ -59,9 +61,8 @@ const LeaveAndAdjustments: React.FC = () => {
|
||||||
|
|
||||||
<a
|
<a
|
||||||
role="tab"
|
role="tab"
|
||||||
className={`tab text-xs font-semibold ${
|
className={`tab text-xs font-semibold ${activeTab === "sick" ? "tab-active text-primary" : ""
|
||||||
activeTab === "sick" ? "tab-active text-primary" : ""
|
} ${isSubmitting ? "pointer-events-none opacity-50" : ""}`}
|
||||||
} ${isSubmitting ? "pointer-events-none opacity-50" : ""}`}
|
|
||||||
onClick={() => setActiveTab("sick")}
|
onClick={() => setActiveTab("sick")}
|
||||||
>
|
>
|
||||||
Sick Leave
|
Sick Leave
|
||||||
|
|
@ -69,9 +70,8 @@ const LeaveAndAdjustments: React.FC = () => {
|
||||||
|
|
||||||
<a
|
<a
|
||||||
role="tab"
|
role="tab"
|
||||||
className={`tab text-xs font-semibold ${
|
className={`tab text-xs font-semibold ${activeTab === "adjustment" ? "tab-active text-primary" : ""
|
||||||
activeTab === "adjustment" ? "tab-active text-primary" : ""
|
} ${isSubmitting ? "pointer-events-none opacity-50" : ""}`}
|
||||||
} ${isSubmitting ? "pointer-events-none opacity-50" : ""}`}
|
|
||||||
onClick={() => setActiveTab("adjustment")}
|
onClick={() => setActiveTab("adjustment")}
|
||||||
>
|
>
|
||||||
Adjustment Submission
|
Adjustment Submission
|
||||||
|
|
|
||||||
|
|
@ -222,28 +222,96 @@ const AdjustmentTab: React.FC<AdjustmentTabProps> = ({ projects }) => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const editor = quillRef.current?.getEditor();
|
const editor = quillRef.current?.getEditor();
|
||||||
|
|
||||||
if (!editor) return;
|
if (!editor) return;
|
||||||
|
|
||||||
editor.getModule("clipboard").addMatcher(Node.ELEMENT_NODE, (node: any, delta: any) => {
|
// Override image handler in toolbar
|
||||||
return delta;
|
editor.getModule("toolbar").handlers.image = () => {
|
||||||
});
|
const input = document.createElement("input");
|
||||||
|
input.setAttribute("type", "file");
|
||||||
|
input.setAttribute("accept", "image/*");
|
||||||
|
input.click();
|
||||||
|
|
||||||
editor.root.addEventListener("paste", async (e: any) => {
|
input.onchange = async () => {
|
||||||
const items = e.clipboardData?.items;
|
const file = input.files?.[0];
|
||||||
|
if (file) {
|
||||||
if (!items) return;
|
|
||||||
|
|
||||||
for (const item of items) {
|
|
||||||
if (item.type.indexOf("image") === 0) {
|
|
||||||
const file = item.getAsFile();
|
|
||||||
const base64 = await convertToBase64(file);
|
const base64 = await convertToBase64(file);
|
||||||
|
|
||||||
const range = editor.getSelection();
|
const range = editor.getSelection();
|
||||||
editor.insertEmbed(range.index, "image", base64);
|
if (range) {
|
||||||
|
editor.insertEmbed(range.index, "image", base64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// COMPLETELY disable Quill's default paste behavior
|
||||||
|
const disableQuillPaste = () => {
|
||||||
|
// Remove all existing paste event listeners from Quill
|
||||||
|
const pasteListeners = (editor.root as any).__pasteHandlers || [];
|
||||||
|
pasteListeners.forEach((handler: any) => {
|
||||||
|
editor.root.removeEventListener('paste', handler);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Override the clipboard module to do nothing
|
||||||
|
const clipboard = editor.getModule('clipboard');
|
||||||
|
const originalPaste = clipboard.paste;
|
||||||
|
clipboard.paste = (e: any) => {
|
||||||
|
// Completely prevent Quill's default paste behavior
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
disableQuillPaste();
|
||||||
|
|
||||||
|
// Our custom paste handler - this is the ONLY handler that will run
|
||||||
|
const handlePaste = async (e: ClipboardEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
const items = e.clipboardData?.items;
|
||||||
|
if (!items || items.length === 0) return;
|
||||||
|
|
||||||
|
// Check for images first
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
const item = items[i];
|
||||||
|
if (item.type.startsWith("image/")) {
|
||||||
|
const file = item.getAsFile();
|
||||||
|
if (file) {
|
||||||
|
try {
|
||||||
|
const base64 = await convertToBase64(file);
|
||||||
|
const range = editor.getSelection(true);
|
||||||
|
if (range !== null) {
|
||||||
|
// Insert the image
|
||||||
|
editor.insertEmbed(range.index, "image", base64);
|
||||||
|
// Move cursor after the image
|
||||||
|
editor.setSelection(range.index + 1, 0);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error processing pasted image:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return; // Exit after handling the first image
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
// If no images found, handle text
|
||||||
|
const text = e.clipboardData?.getData('text/plain');
|
||||||
|
if (text) {
|
||||||
|
const range = editor.getSelection(true);
|
||||||
|
if (range !== null) {
|
||||||
|
editor.insertText(range.index, text);
|
||||||
|
editor.setSelection(range.index + text.length, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add our custom paste handler with high priority
|
||||||
|
editor.root.addEventListener("paste", handlePaste, true);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
editor.root.removeEventListener("paste", handlePaste, true);
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const convertToBase64 = (file: File): Promise<string> =>
|
const convertToBase64 = (file: File): Promise<string> =>
|
||||||
|
|
@ -571,14 +639,14 @@ const AdjustmentTab: React.FC<AdjustmentTabProps> = ({ projects }) => {
|
||||||
modules={quillModules}
|
modules={quillModules}
|
||||||
onChange={handleDescription}
|
onChange={handleDescription}
|
||||||
className="h-40"
|
className="h-40"
|
||||||
// placeholder="Please enter the task name or leave notes to help us better understand your request."
|
// placeholder="Please enter the task name or leave notes to help us better understand your request."
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{formErrors.comment && (
|
{formErrors.comment && (
|
||||||
<label className="label">
|
<label className="label">
|
||||||
<span className="label-text-alt text-error text-xs font-medium">{formErrors.comment}</span>
|
<span className="label-text-alt text-error text-xs font-medium">{formErrors.comment}</span>
|
||||||
</label>
|
</label>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Submit Button */}
|
{/* Submit Button */}
|
||||||
<div className="flex gap-3">
|
<div className="flex gap-3">
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import React, { useEffect, useRef, useState } from "react";
|
||||||
import { quillModules } from "../../../utils/quillConfig";
|
import { quillModules } from "../../../utils/quillConfig";
|
||||||
import ReactQuill from "react-quill-new";
|
import ReactQuill from "react-quill-new";
|
||||||
import Quill from "quill";
|
import Quill from "quill";
|
||||||
import "quill/dist/quill.snow.css"; // correct CSS
|
import "quill/dist/quill.snow.css";
|
||||||
|
|
||||||
interface LeaveFormData {
|
interface LeaveFormData {
|
||||||
fromDate: string;
|
fromDate: string;
|
||||||
|
|
@ -21,43 +21,114 @@ const PtoLeaveTab: React.FC<{
|
||||||
toDate: "",
|
toDate: "",
|
||||||
comment: "",
|
comment: "",
|
||||||
});
|
});
|
||||||
|
const [serverError, setServerError] = useState("");
|
||||||
const quillRef = useRef<any>(null);
|
const quillRef = useRef<any>(null);
|
||||||
|
|
||||||
const [errors, setErrors] = useState<Partial<LeaveFormData>>({});
|
const [errors, setErrors] = useState<Partial<LeaveFormData>>({});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const editor = quillRef.current?.getEditor();
|
const editor = quillRef.current?.getEditor();
|
||||||
|
|
||||||
if (!editor) return;
|
if (!editor) return;
|
||||||
|
|
||||||
editor.getModule("clipboard").addMatcher(Node.ELEMENT_NODE, (node: any, delta: any) => {
|
// Override image handler in toolbar
|
||||||
return delta;
|
editor.getModule("toolbar").handlers.image = () => {
|
||||||
});
|
const input = document.createElement("input");
|
||||||
|
input.setAttribute("type", "file");
|
||||||
|
input.setAttribute("accept", "image/*");
|
||||||
|
input.click();
|
||||||
|
|
||||||
editor.root.addEventListener("paste", async (e: any) => {
|
input.onchange = async () => {
|
||||||
const items = e.clipboardData?.items;
|
const file = input.files?.[0];
|
||||||
|
if (file) {
|
||||||
if (!items) return;
|
|
||||||
|
|
||||||
for (const item of items) {
|
|
||||||
if (item.type.indexOf("image") === 0) {
|
|
||||||
const file = item.getAsFile();
|
|
||||||
const base64 = await convertToBase64(file);
|
const base64 = await convertToBase64(file);
|
||||||
|
|
||||||
const range = editor.getSelection();
|
const range = editor.getSelection();
|
||||||
editor.insertEmbed(range.index, "image", base64);
|
if (range) {
|
||||||
|
editor.insertEmbed(range.index, "image", base64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// COMPLETELY disable Quill's default paste behavior
|
||||||
|
const disableQuillPaste = () => {
|
||||||
|
// Remove all existing paste event listeners from Quill
|
||||||
|
const pasteListeners = (editor.root as any).__pasteHandlers || [];
|
||||||
|
pasteListeners.forEach((handler: any) => {
|
||||||
|
editor.root.removeEventListener('paste', handler);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Override the clipboard module to do nothing
|
||||||
|
const clipboard = editor.getModule('clipboard');
|
||||||
|
const originalPaste = clipboard.paste;
|
||||||
|
clipboard.paste = (e: any) => {
|
||||||
|
// Completely prevent Quill's default paste behavior
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
disableQuillPaste();
|
||||||
|
|
||||||
|
// Our custom paste handler - this is the ONLY handler that will run
|
||||||
|
const handlePaste = async (e: ClipboardEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
const items = e.clipboardData?.items;
|
||||||
|
if (!items || items.length === 0) return;
|
||||||
|
|
||||||
|
// Check for images first
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
const item = items[i];
|
||||||
|
if (item.type.startsWith("image/")) {
|
||||||
|
const file = item.getAsFile();
|
||||||
|
if (file) {
|
||||||
|
try {
|
||||||
|
const base64 = await convertToBase64(file);
|
||||||
|
const range = editor.getSelection(true);
|
||||||
|
if (range !== null) {
|
||||||
|
// Insert the image
|
||||||
|
editor.insertEmbed(range.index, "image", base64);
|
||||||
|
// Move cursor after the image
|
||||||
|
editor.setSelection(range.index + 1, 0);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error processing pasted image:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return; // Exit after handling the first image
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
// If no images found, handle text
|
||||||
|
const text = e.clipboardData?.getData('text/plain');
|
||||||
|
if (text) {
|
||||||
|
const range = editor.getSelection(true);
|
||||||
|
if (range !== null) {
|
||||||
|
editor.insertText(range.index, text);
|
||||||
|
editor.setSelection(range.index + text.length, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add our custom paste handler with high priority
|
||||||
|
editor.root.addEventListener("paste", handlePaste, true);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
editor.root.removeEventListener("paste", handlePaste, true);
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const convertToBase64 = (file: File): Promise<string> =>
|
const convertToBase64 = (file: File): Promise<string> =>
|
||||||
new Promise((resolve) => {
|
new Promise((resolve, reject) => {
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.onload = () => resolve(reader.result as string);
|
reader.onload = () => resolve(reader.result as string);
|
||||||
|
reader.onerror = reject;
|
||||||
reader.readAsDataURL(file);
|
reader.readAsDataURL(file);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ... rest of your component code remains the same
|
||||||
const validate = () => {
|
const validate = () => {
|
||||||
const e: Partial<LeaveFormData> = {};
|
const e: Partial<LeaveFormData> = {};
|
||||||
|
|
||||||
|
|
@ -67,26 +138,22 @@ const PtoLeaveTab: React.FC<{
|
||||||
const from = ptoLeave.fromDate ? new Date(ptoLeave.fromDate) : null;
|
const from = ptoLeave.fromDate ? new Date(ptoLeave.fromDate) : null;
|
||||||
const to = ptoLeave.toDate ? new Date(ptoLeave.toDate) : null;
|
const to = ptoLeave.toDate ? new Date(ptoLeave.toDate) : null;
|
||||||
|
|
||||||
// From date required
|
|
||||||
if (!from) {
|
if (!from) {
|
||||||
e.fromDate = "From date is required";
|
e.fromDate = "From date is required";
|
||||||
} else if (from < today) {
|
} else if (from < today) {
|
||||||
e.fromDate = "From date cannot be in the past";
|
e.fromDate = "From date cannot be in the past";
|
||||||
}
|
}
|
||||||
|
|
||||||
// To date required
|
|
||||||
if (!to) {
|
if (!to) {
|
||||||
e.toDate = "To date is required";
|
e.toDate = "To date is required";
|
||||||
} else if (to < today) {
|
} else if (to < today) {
|
||||||
e.toDate = "To date cannot be in the past";
|
e.toDate = "To date cannot be in the past";
|
||||||
}
|
}
|
||||||
|
|
||||||
// To date must be same or after From date
|
|
||||||
if (from && to && to < from) {
|
if (from && to && to < from) {
|
||||||
e.toDate = "To date cannot be before From date";
|
e.toDate = "To date cannot be before From date";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comment validation
|
|
||||||
if (!ptoLeave.comment.trim()) {
|
if (!ptoLeave.comment.trim()) {
|
||||||
e.comment = "Comment required";
|
e.comment = "Comment required";
|
||||||
}
|
}
|
||||||
|
|
@ -100,14 +167,13 @@ const PtoLeaveTab: React.FC<{
|
||||||
toDate: "",
|
toDate: "",
|
||||||
comment: ""
|
comment: ""
|
||||||
};
|
};
|
||||||
|
|
||||||
setPtoLeave(emptyForm);
|
setPtoLeave(emptyForm);
|
||||||
setErrors({});
|
setErrors({});
|
||||||
|
|
||||||
// Properly reset the Quill editor
|
|
||||||
if (quillRef.current) {
|
if (quillRef.current) {
|
||||||
const editor = quillRef.current.getEditor();
|
const editor = quillRef.current.getEditor();
|
||||||
editor.setContents([]); // Clear editor contents completely
|
editor.setContents([]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -119,90 +185,100 @@ const PtoLeaveTab: React.FC<{
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
|
setServerError("")
|
||||||
const e = validate();
|
const e = validate();
|
||||||
if (Object.keys(e).length) return setErrors(e);
|
if (Object.keys(e).length) return setErrors(e);
|
||||||
|
|
||||||
const success = await submitLeave({
|
const result = await submitLeave({
|
||||||
dateFrom: ptoLeave.fromDate,
|
dateFrom: ptoLeave.fromDate,
|
||||||
dateTo: ptoLeave.toDate,
|
dateTo: ptoLeave.toDate,
|
||||||
leaveType: "PTO",
|
leaveType: "PTO",
|
||||||
comment: ptoLeave.comment,
|
comment: ptoLeave.comment,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (success) {
|
if (result.success) {
|
||||||
resetForm();
|
resetForm();
|
||||||
alert("PTO submitted!");
|
alert("PTO submitted!");
|
||||||
|
} else {
|
||||||
|
setServerError(result.message || "Something went wrong");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-4xl space-y-3 ">
|
<>
|
||||||
<div className="grid grid-cols-2 gap-4">
|
|
||||||
|
<div className="max-w-4xl space-y-3 ">
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
|
||||||
{/* From Date */}
|
|
||||||
<div className="form-control">
|
{/* From Date */}
|
||||||
<label className="label">
|
<div className="form-control">
|
||||||
<span className="label-text font-semibold text-sm">From Date</span>
|
<label className="label">
|
||||||
</label>
|
<span className="label-text font-semibold text-sm">From Date</span>
|
||||||
<input
|
</label>
|
||||||
type="date"
|
<input
|
||||||
disabled={isSubmitting}
|
type="date"
|
||||||
value={ptoLeave.fromDate}
|
disabled={isSubmitting}
|
||||||
min={new Date().toISOString().split("T")[0]}
|
value={ptoLeave.fromDate}
|
||||||
onChange={(e) => handleChange('fromDate', e.target.value)}
|
min={new Date().toISOString().split("T")[0]}
|
||||||
className={`input input-bordered input-sm ${errors.fromDate ? "input-error" : ""
|
onChange={(e) => handleChange('fromDate', e.target.value)}
|
||||||
}`}
|
className={`input input-bordered input-sm ${errors.fromDate ? "input-error" : ""
|
||||||
/>
|
}`}
|
||||||
{errors.fromDate && <p className="text-error text-xs">{errors.fromDate}</p>}
|
/>
|
||||||
|
{errors.fromDate && <p className="text-error text-xs">{errors.fromDate}</p>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* To Date */}
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text font-semibold text-sm">To Date</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="date"
|
||||||
|
disabled={isSubmitting}
|
||||||
|
value={ptoLeave.toDate}
|
||||||
|
min={new Date().toISOString().split("T")[0]}
|
||||||
|
onChange={(e) => handleChange('toDate', e.target.value)}
|
||||||
|
className={`input input-bordered input-sm ${errors.toDate ? "input-error" : ""
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
{errors.toDate && <p className="text-error text-xs">{errors.toDate}</p>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Comment */}
|
||||||
|
<div className="form-control mb-10 col-span-2">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text font-semibold text-sm">Description</span>
|
||||||
|
</label>
|
||||||
|
<ReactQuill
|
||||||
|
ref={quillRef}
|
||||||
|
theme="snow"
|
||||||
|
value={ptoLeave.comment}
|
||||||
|
modules={quillModules}
|
||||||
|
onChange={(val) => handleChange('comment', val)}
|
||||||
|
className="h-60"
|
||||||
|
/>
|
||||||
|
{errors.comment && <p className="text-error text-xs">{errors.comment}</p>}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* To Date */}
|
{serverError && (
|
||||||
<div className="form-control">
|
<p className="text-red-500 font-medium text-center text-xs">{serverError}</p>
|
||||||
<label className="label">
|
)}
|
||||||
<span className="label-text font-semibold text-sm">To Date</span>
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="date"
|
|
||||||
disabled={isSubmitting}
|
|
||||||
value={ptoLeave.toDate}
|
|
||||||
min={new Date().toISOString().split("T")[0]}
|
|
||||||
onChange={(e) => handleChange('toDate', e.target.value)}
|
|
||||||
className={`input input-bordered input-sm ${errors.toDate ? "input-error" : ""
|
|
||||||
}`}
|
|
||||||
/>
|
|
||||||
{errors.toDate && <p className="text-error text-xs">{errors.toDate}</p>}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Comment */}
|
<button
|
||||||
<div className="form-control mb-10 col-span-2">
|
onClick={handleSubmit}
|
||||||
<label className="label">
|
disabled={isSubmitting}
|
||||||
<span className="label-text font-semibold text-sm">Description</span>
|
className="btn btn-primary flex-1 w-full"
|
||||||
</label>
|
>
|
||||||
<ReactQuill
|
{isSubmitting ? (
|
||||||
ref={quillRef}
|
<span className="loading loading-spinner loading-sm"></span>
|
||||||
theme="snow"
|
) : (
|
||||||
value={ptoLeave.comment}
|
"Submit PTO Request"
|
||||||
modules={quillModules}
|
)}
|
||||||
onChange={(val) => handleChange('comment', val)}
|
</button>
|
||||||
className="h-60"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
{errors.comment && <p className="text-error text-xs">{errors.comment}</p>}
|
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
<button
|
|
||||||
onClick={handleSubmit}
|
|
||||||
disabled={isSubmitting}
|
|
||||||
className="btn btn-primary flex-1 w-full"
|
|
||||||
>
|
|
||||||
{isSubmitting ? (
|
|
||||||
<span className="loading loading-spinner loading-sm"></span>
|
|
||||||
) : (
|
|
||||||
"Submit PTO Request"
|
|
||||||
)}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,33 +19,102 @@ const SickLeaveTab: React.FC<{
|
||||||
toDate: '',
|
toDate: '',
|
||||||
comment: ''
|
comment: ''
|
||||||
});
|
});
|
||||||
|
const [serverError, setServerError] = useState("");
|
||||||
const quillRef = useRef<any>(null);
|
const quillRef = useRef<any>(null);
|
||||||
const [sickErrors, setSickErrors] = useState<Partial<LeaveFormData>>({});
|
const [sickErrors, setSickErrors] = useState<Partial<LeaveFormData>>({});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const editor = quillRef.current?.getEditor();
|
const editor = quillRef.current?.getEditor();
|
||||||
|
|
||||||
if (!editor) return;
|
if (!editor) return;
|
||||||
|
|
||||||
editor.getModule("clipboard").addMatcher(Node.ELEMENT_NODE, (node: any, delta: any) => {
|
// Override image handler in toolbar
|
||||||
return delta;
|
editor.getModule("toolbar").handlers.image = () => {
|
||||||
});
|
const input = document.createElement("input");
|
||||||
|
input.setAttribute("type", "file");
|
||||||
|
input.setAttribute("accept", "image/*");
|
||||||
|
input.click();
|
||||||
|
|
||||||
editor.root.addEventListener("paste", async (e: any) => {
|
input.onchange = async () => {
|
||||||
const items = e.clipboardData?.items;
|
const file = input.files?.[0];
|
||||||
|
if (file) {
|
||||||
if (!items) return;
|
|
||||||
|
|
||||||
for (const item of items) {
|
|
||||||
if (item.type.indexOf("image") === 0) {
|
|
||||||
const file = item.getAsFile();
|
|
||||||
const base64 = await convertToBase64(file);
|
const base64 = await convertToBase64(file);
|
||||||
|
|
||||||
const range = editor.getSelection();
|
const range = editor.getSelection();
|
||||||
editor.insertEmbed(range.index, "image", base64);
|
if (range) {
|
||||||
|
editor.insertEmbed(range.index, "image", base64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// COMPLETELY disable Quill's default paste behavior
|
||||||
|
const disableQuillPaste = () => {
|
||||||
|
// Remove all existing paste event listeners from Quill
|
||||||
|
const pasteListeners = (editor.root as any).__pasteHandlers || [];
|
||||||
|
pasteListeners.forEach((handler: any) => {
|
||||||
|
editor.root.removeEventListener('paste', handler);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Override the clipboard module to do nothing
|
||||||
|
const clipboard = editor.getModule('clipboard');
|
||||||
|
const originalPaste = clipboard.paste;
|
||||||
|
clipboard.paste = (e: any) => {
|
||||||
|
// Completely prevent Quill's default paste behavior
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
disableQuillPaste();
|
||||||
|
|
||||||
|
// Our custom paste handler - this is the ONLY handler that will run
|
||||||
|
const handlePaste = async (e: ClipboardEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
const items = e.clipboardData?.items;
|
||||||
|
if (!items || items.length === 0) return;
|
||||||
|
|
||||||
|
// Check for images first
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
const item = items[i];
|
||||||
|
if (item.type.startsWith("image/")) {
|
||||||
|
const file = item.getAsFile();
|
||||||
|
if (file) {
|
||||||
|
try {
|
||||||
|
const base64 = await convertToBase64(file);
|
||||||
|
const range = editor.getSelection(true);
|
||||||
|
if (range !== null) {
|
||||||
|
// Insert the image
|
||||||
|
editor.insertEmbed(range.index, "image", base64);
|
||||||
|
// Move cursor after the image
|
||||||
|
editor.setSelection(range.index + 1, 0);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error processing pasted image:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return; // Exit after handling the first image
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
// If no images found, handle text
|
||||||
|
const text = e.clipboardData?.getData('text/plain');
|
||||||
|
if (text) {
|
||||||
|
const range = editor.getSelection(true);
|
||||||
|
if (range !== null) {
|
||||||
|
editor.insertText(range.index, text);
|
||||||
|
editor.setSelection(range.index + text.length, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add our custom paste handler with high priority
|
||||||
|
editor.root.addEventListener("paste", handlePaste, true);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
editor.root.removeEventListener("paste", handlePaste, true);
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const convertToBase64 = (file: File): Promise<string> =>
|
const convertToBase64 = (file: File): Promise<string> =>
|
||||||
|
|
@ -90,7 +159,7 @@ const SickLeaveTab: React.FC<{
|
||||||
toDate: "",
|
toDate: "",
|
||||||
comment: ""
|
comment: ""
|
||||||
};
|
};
|
||||||
|
|
||||||
setSickLeave(emptyForm);
|
setSickLeave(emptyForm);
|
||||||
setSickErrors({});
|
setSickErrors({});
|
||||||
|
|
||||||
|
|
@ -102,6 +171,7 @@ const SickLeaveTab: React.FC<{
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
|
setServerError("")
|
||||||
const errors = validateLeaveForm(sickLeave);
|
const errors = validateLeaveForm(sickLeave);
|
||||||
|
|
||||||
if (Object.keys(errors).length > 0) {
|
if (Object.keys(errors).length > 0) {
|
||||||
|
|
@ -109,20 +179,23 @@ const SickLeaveTab: React.FC<{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const success = await submitLeave({
|
const result = await submitLeave({
|
||||||
dateFrom: sickLeave.fromDate,
|
dateFrom: sickLeave.fromDate,
|
||||||
dateTo: sickLeave.toDate,
|
dateTo: sickLeave.toDate,
|
||||||
leaveType: "SICK",
|
leaveType: "SICK",
|
||||||
comment: sickLeave.comment,
|
comment: sickLeave.comment,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (success) {
|
if (result.success) {
|
||||||
resetForm();
|
resetForm();
|
||||||
alert("SICK submitted!");
|
alert("SICK submitted!");
|
||||||
|
} else {
|
||||||
|
setServerError(result.message || "Something went wrong");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<div className="max-w-4xl">
|
<div className="max-w-4xl">
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
|
@ -182,13 +255,17 @@ const SickLeaveTab: React.FC<{
|
||||||
className="h-60"
|
className="h-60"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{sickErrors.comment && (
|
{sickErrors.comment && (
|
||||||
<label className="label">
|
<label className="label">
|
||||||
<span className="label-text-alt text-xs text-error font-medium">{sickErrors.comment}</span>
|
<span className="label-text-alt text-xs text-error font-medium">{sickErrors.comment}</span>
|
||||||
</label>
|
</label>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{serverError && (
|
||||||
|
<p className="text-red-500 font-medium text-center text-xs">{serverError}</p>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Submit Button */}
|
{/* Submit Button */}
|
||||||
<button
|
<button
|
||||||
onClick={handleSubmit}
|
onClick={handleSubmit}
|
||||||
|
|
@ -203,6 +280,7 @@ const SickLeaveTab: React.FC<{
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
const Schedule = () => {
|
||||||
|
const rows = [
|
||||||
|
{
|
||||||
|
period: "Oct 25, 2025 to Nov 07, 2025",
|
||||||
|
cutoff: "Nov 11, 2025 05:29:59 AM",
|
||||||
|
payDate: "Nov 14, 2025"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
period: "Nov 08, 2025 to Nov 21, 2025",
|
||||||
|
cutoff: "Nov 25, 2025 05:29:59 AM",
|
||||||
|
payDate: "Nov 28, 2025"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
period: "Nov 22, 2025 to Dec 05, 2025",
|
||||||
|
cutoff: "Dec 09, 2025 05:29:59 AM",
|
||||||
|
payDate: "Dec 12, 2025"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
period: "Dec 06, 2025 to Dec 19, 2025",
|
||||||
|
cutoff: "Dec 23, 2025 05:29:59 AM",
|
||||||
|
payDate: "Dec 26, 2025"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
period: "Dec 20, 2025 to Jan 02, 2026",
|
||||||
|
cutoff: "Jan 06, 2026 05:29:59 AM",
|
||||||
|
payDate: "Jan 09, 2026"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
period: "Jan 03, 2026 to Jan 16, 2026",
|
||||||
|
cutoff: "Jan 20, 2026 05:29:59 AM",
|
||||||
|
payDate: "Jan 23, 2026"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
period: "Jan 17, 2026 to Jan 30, 2026",
|
||||||
|
cutoff: "Feb 03, 2026 05:29:59 AM",
|
||||||
|
payDate: "Feb 06, 2026"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
period: "Jan 31, 2026 to Feb 13, 2026",
|
||||||
|
cutoff: "Feb 17, 2026 05:29:59 AM",
|
||||||
|
payDate: "Feb 20, 2026"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
period: "Feb 14, 2026 to Feb 27, 2026",
|
||||||
|
cutoff: "Mar 03, 2026 05:29:59 AM",
|
||||||
|
payDate: "Mar 06, 2026"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
period: "Feb 28, 2026 to Mar 13, 2026",
|
||||||
|
cutoff: "Mar 17, 2026 05:29:59 AM",
|
||||||
|
payDate: "Mar 20, 2026"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="flex flex-col gap-2 max-h-screen">
|
||||||
|
{/* Header */}
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<h2 className="text-md font-bold">Schedules</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="overflow-y-auto rounded-box border border-base-content/10 bg-base-100 shadow-md max-h-[80vh] min-h-[83vh] no-scrollbar">
|
||||||
|
|
||||||
|
{/* ⭐ FIXED: Horizontal scroll wrapper */}
|
||||||
|
<div className="overflow-x-auto w-full no-scrollbar">
|
||||||
|
<table className="table table-zebra w-full text-[12px] min-w-[600px]">
|
||||||
|
<thead className="sticky top-0 bg-base-200 z-10">
|
||||||
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
|
<th>Period</th>
|
||||||
|
<th>Cutoff Time</th>
|
||||||
|
<th>Pay Date</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{rows.map((row, index) => (
|
||||||
|
<tr key={index}>
|
||||||
|
<td>{index + 1}</td>
|
||||||
|
<td>{row.period}</td>
|
||||||
|
<td>
|
||||||
|
{row.cutoff}
|
||||||
|
<br />
|
||||||
|
<span className="text-gray-500 text-[11px]">(Asia/Calcutta)</span>
|
||||||
|
</td>
|
||||||
|
<td>{row.payDate}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Schedule;
|
||||||
Loading…
Reference in New Issue