diff --git a/.gitignore b/.gitignore
index 44300dc1f..1477cb127 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,36 +1,63 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
-# dependencies
-node_modules
-.pnp
+# Bağımlılıklar
+/node_modules
+/.pnp
.pnp.js
-# testing
-coverage
+# Test kapsama raporları
+/coverage
-# production
-.next
-.swc
-_static
-out
-dist
-build
+# Üretim derlemesi
+/build
+/dist
-# environment variables
+# Çevre değişkenleri
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
-# misc
-.DS_Store
-.vercel
-.netlify
-.unimportedrc.json
-tsconfig.tsbuildinfo
-.vscode
-
+# Günlük dosyaları
npm-debug.log*
yarn-debug.log*
yarn-error.log*
+
+# IDE ve editör dosyaları
+.idea/
+.vscode/
+*.swp
+*.swo
+.DS_Store
+*.sublime-workspace
+*.sublime-project
+
+# TypeScript derleme çıktıları
+*.tsbuildinfo
+
+# Geçici dosyalar
+.temp
+.tmp
+.cache
+
+# Sistem dosyaları
+Thumbs.db
+*.pem
+
+# Yerel SSL sertifikaları
+*.cert
+*.key
+
+# Yarn
+.yarn/*
+!.yarn/patches
+!.yarn/plugins
+!.yarn/releases
+!.yarn/sdks
+!.yarn/versions
+.pnp.*
+
+# Diğer
+*.log
+.vercel
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 000000000..13566b81b
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 000000000..03d9549ea
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 000000000..07115cdf1
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 000000000..edb1cba1a
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/prettier.xml b/.idea/prettier.xml
new file mode 100644
index 000000000..b0c1c68fb
--- /dev/null
+++ b/.idea/prettier.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/react-dashboard.iml b/.idea/react-dashboard.iml
new file mode 100644
index 000000000..d6ebd4805
--- /dev/null
+++ b/.idea/react-dashboard.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 000000000..35eb1ddfb
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/index.html b/index.html
index efb687cbc..db8ce74e0 100644
--- a/index.html
+++ b/index.html
@@ -5,7 +5,7 @@
-
Minimal UI Kit
+ Transport
diff --git a/package-lock.json b/package-lock.json
index bcd1a82ae..5f5a38f88 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,22 +14,34 @@
"@fontsource-variable/dm-sans": "^5.0.7",
"@fontsource/barlow": "^5.0.14",
"@iconify/react": "^5.0.2",
+ "@mui/icons-material": "^6.3.1",
"@mui/lab": "^5.0.0-alpha.173",
"@mui/material": "^5.16.7",
+ "@types/yup": "^0.29.14",
"apexcharts": "^3.52.0",
+ "axios": "^1.7.9",
"dayjs": "^1.11.13",
+ "formik": "^2.4.6",
"history": "^5.3.0",
+ "i18next": "^24.2.0",
+ "i18next-browser-languagedetector": "^8.0.2",
+ "i18next-http-backend": "^3.0.1",
+ "jwt-decode": "^4.0.0",
"react": "^18.3.1",
"react-apexcharts": "^1.4.1",
"react-dom": "^18.3.1",
"react-helmet-async": "^2.0.5",
+ "react-i18next": "^15.4.0",
+ "react-input-mask": "^2.0.4",
"react-router-dom": "^6.26.1",
- "simplebar-react": "^3.2.6"
+ "simplebar-react": "^3.2.6",
+ "yup": "^1.6.1"
},
"devDependencies": {
"@types/node": "^22.5.0",
"@types/react": "^18.3.4",
"@types/react-dom": "^18.3.0",
+ "@types/react-input-mask": "^3.0.6",
"@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.18.0",
"@vitejs/plugin-react-swc": "^3.7.0",
@@ -154,9 +166,9 @@
}
},
"node_modules/@babel/runtime": {
- "version": "7.25.4",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.4.tgz",
- "integrity": "sha512-DSgLeL/FNcpXuzav5wfYvHCGvynXkJbn3Zvc3823AEe9nPwW9IK4UoCSS5yGymmQzN0pCPvivtgS6/8U2kkm1w==",
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz",
+ "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==",
"license": "MIT",
"dependencies": {
"regenerator-runtime": "^0.14.0"
@@ -1084,6 +1096,32 @@
"url": "https://opencollective.com/mui-org"
}
},
+ "node_modules/@mui/icons-material": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-6.3.1.tgz",
+ "integrity": "sha512-nJmWj1PBlwS3t1PnoqcixIsftE+7xrW3Su7f0yrjPw4tVjYrgkhU0hrRp+OlURfZ3ptdSkoBkalee9Bhf1Erfw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.26.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui-org"
+ },
+ "peerDependencies": {
+ "@mui/material": "^6.3.1",
+ "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react": "^17.0.0 || ^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@mui/lab": {
"version": "5.0.0-alpha.173",
"resolved": "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.173.tgz",
@@ -1384,9 +1422,9 @@
}
},
"node_modules/@rollup/rollup-android-arm-eabi": {
- "version": "4.21.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.0.tgz",
- "integrity": "sha512-WTWD8PfoSAJ+qL87lE7votj3syLavxunWhzCnx3XFxFiI/BA/r3X7MUM8dVrH8rb2r4AiO8jJsr3ZjdaftmnfA==",
+ "version": "4.29.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.29.1.tgz",
+ "integrity": "sha512-ssKhA8RNltTZLpG6/QNkCSge+7mBQGUqJRisZ2MDQcEGaK93QESEgWK2iOpIDZ7k9zPVkG5AS3ksvD5ZWxmItw==",
"cpu": [
"arm"
],
@@ -1398,9 +1436,9 @@
]
},
"node_modules/@rollup/rollup-android-arm64": {
- "version": "4.21.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.0.tgz",
- "integrity": "sha512-a1sR2zSK1B4eYkiZu17ZUZhmUQcKjk2/j9Me2IDjk1GHW7LB5Z35LEzj9iJch6gtUfsnvZs1ZNyDW2oZSThrkA==",
+ "version": "4.29.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.29.1.tgz",
+ "integrity": "sha512-CaRfrV0cd+NIIcVVN/jx+hVLN+VRqnuzLRmfmlzpOzB87ajixsN/+9L5xNmkaUUvEbI5BmIKS+XTwXsHEb65Ew==",
"cpu": [
"arm64"
],
@@ -1412,9 +1450,9 @@
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
- "version": "4.21.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.0.tgz",
- "integrity": "sha512-zOnKWLgDld/svhKO5PD9ozmL6roy5OQ5T4ThvdYZLpiOhEGY+dp2NwUmxK0Ld91LrbjrvtNAE0ERBwjqhZTRAA==",
+ "version": "4.29.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.29.1.tgz",
+ "integrity": "sha512-2ORr7T31Y0Mnk6qNuwtyNmy14MunTAMx06VAPI6/Ju52W10zk1i7i5U3vlDRWjhOI5quBcrvhkCHyF76bI7kEw==",
"cpu": [
"arm64"
],
@@ -1426,9 +1464,9 @@
]
},
"node_modules/@rollup/rollup-darwin-x64": {
- "version": "4.21.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.0.tgz",
- "integrity": "sha512-7doS8br0xAkg48SKE2QNtMSFPFUlRdw9+votl27MvT46vo44ATBmdZdGysOevNELmZlfd+NEa0UYOA8f01WSrg==",
+ "version": "4.29.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.29.1.tgz",
+ "integrity": "sha512-j/Ej1oanzPjmN0tirRd5K2/nncAhS9W6ICzgxV+9Y5ZsP0hiGhHJXZ2JQ53iSSjj8m6cRY6oB1GMzNn2EUt6Ng==",
"cpu": [
"x64"
],
@@ -1439,10 +1477,38 @@
"darwin"
]
},
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.29.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.29.1.tgz",
+ "integrity": "sha512-91C//G6Dm/cv724tpt7nTyP+JdN12iqeXGFM1SqnljCmi5yTXriH7B1r8AD9dAZByHpKAumqP1Qy2vVNIdLZqw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.29.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.29.1.tgz",
+ "integrity": "sha512-hEioiEQ9Dec2nIRoeHUP6hr1PSkXzQaCUyqBDQ9I9ik4gCXQZjJMIVzoNLBRGet+hIUb3CISMh9KXuCcWVW/8w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
- "version": "4.21.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.0.tgz",
- "integrity": "sha512-pWJsfQjNWNGsoCq53KjMtwdJDmh/6NubwQcz52aEwLEuvx08bzcy6tOUuawAOncPnxz/3siRtd8hiQ32G1y8VA==",
+ "version": "4.29.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.29.1.tgz",
+ "integrity": "sha512-Py5vFd5HWYN9zxBv3WMrLAXY3yYJ6Q/aVERoeUFwiDGiMOWsMs7FokXihSOaT/PMWUty/Pj60XDQndK3eAfE6A==",
"cpu": [
"arm"
],
@@ -1454,9 +1520,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
- "version": "4.21.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.0.tgz",
- "integrity": "sha512-efRIANsz3UHZrnZXuEvxS9LoCOWMGD1rweciD6uJQIx2myN3a8Im1FafZBzh7zk1RJ6oKcR16dU3UPldaKd83w==",
+ "version": "4.29.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.29.1.tgz",
+ "integrity": "sha512-RiWpGgbayf7LUcuSNIbahr0ys2YnEERD4gYdISA06wa0i8RALrnzflh9Wxii7zQJEB2/Eh74dX4y/sHKLWp5uQ==",
"cpu": [
"arm"
],
@@ -1468,9 +1534,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
- "version": "4.21.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.0.tgz",
- "integrity": "sha512-ZrPhydkTVhyeGTW94WJ8pnl1uroqVHM3j3hjdquwAcWnmivjAwOYjTEAuEDeJvGX7xv3Z9GAvrBkEzCgHq9U1w==",
+ "version": "4.29.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.29.1.tgz",
+ "integrity": "sha512-Z80O+taYxTQITWMjm/YqNoe9d10OX6kDh8X5/rFCMuPqsKsSyDilvfg+vd3iXIqtfmp+cnfL1UrYirkaF8SBZA==",
"cpu": [
"arm64"
],
@@ -1482,9 +1548,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
- "version": "4.21.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.0.tgz",
- "integrity": "sha512-cfaupqd+UEFeURmqNP2eEvXqgbSox/LHOyN9/d2pSdV8xTrjdg3NgOFJCtc1vQ/jEke1qD0IejbBfxleBPHnPw==",
+ "version": "4.29.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.29.1.tgz",
+ "integrity": "sha512-fOHRtF9gahwJk3QVp01a/GqS4hBEZCV1oKglVVq13kcK3NeVlS4BwIFzOHDbmKzt3i0OuHG4zfRP0YoG5OF/rA==",
"cpu": [
"arm64"
],
@@ -1495,10 +1561,24 @@
"linux"
]
},
+ "node_modules/@rollup/rollup-linux-loongarch64-gnu": {
+ "version": "4.29.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.29.1.tgz",
+ "integrity": "sha512-5a7q3tnlbcg0OodyxcAdrrCxFi0DgXJSoOuidFUzHZ2GixZXQs6Tc3CHmlvqKAmOs5eRde+JJxeIf9DonkmYkw==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
- "version": "4.21.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.0.tgz",
- "integrity": "sha512-ZKPan1/RvAhrUylwBXC9t7B2hXdpb/ufeu22pG2psV7RN8roOfGurEghw1ySmX/CmDDHNTDDjY3lo9hRlgtaHg==",
+ "version": "4.29.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.29.1.tgz",
+ "integrity": "sha512-9b4Mg5Yfz6mRnlSPIdROcfw1BU22FQxmfjlp/CShWwO3LilKQuMISMTtAu/bxmmrE6A902W2cZJuzx8+gJ8e9w==",
"cpu": [
"ppc64"
],
@@ -1510,9 +1590,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
- "version": "4.21.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.0.tgz",
- "integrity": "sha512-H1eRaCwd5E8eS8leiS+o/NqMdljkcb1d6r2h4fKSsCXQilLKArq6WS7XBLDu80Yz+nMqHVFDquwcVrQmGr28rg==",
+ "version": "4.29.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.29.1.tgz",
+ "integrity": "sha512-G5pn0NChlbRM8OJWpJFMX4/i8OEU538uiSv0P6roZcbpe/WfhEO+AT8SHVKfp8qhDQzaz7Q+1/ixMy7hBRidnQ==",
"cpu": [
"riscv64"
],
@@ -1524,9 +1604,9 @@
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
- "version": "4.21.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.0.tgz",
- "integrity": "sha512-zJ4hA+3b5tu8u7L58CCSI0A9N1vkfwPhWd/puGXwtZlsB5bTkwDNW/+JCU84+3QYmKpLi+XvHdmrlwUwDA6kqw==",
+ "version": "4.29.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.29.1.tgz",
+ "integrity": "sha512-WM9lIkNdkhVwiArmLxFXpWndFGuOka4oJOZh8EP3Vb8q5lzdSCBuhjavJsw68Q9AKDGeOOIHYzYm4ZFvmWez5g==",
"cpu": [
"s390x"
],
@@ -1538,9 +1618,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
- "version": "4.21.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.0.tgz",
- "integrity": "sha512-e2hrvElFIh6kW/UNBQK/kzqMNY5mO+67YtEh9OA65RM5IJXYTWiXjX6fjIiPaqOkBthYF1EqgiZ6OXKcQsM0hg==",
+ "version": "4.29.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.29.1.tgz",
+ "integrity": "sha512-87xYCwb0cPGZFoGiErT1eDcssByaLX4fc0z2nRM6eMtV9njAfEE6OW3UniAoDhX4Iq5xQVpE6qO9aJbCFumKYQ==",
"cpu": [
"x64"
],
@@ -1552,9 +1632,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
- "version": "4.21.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.0.tgz",
- "integrity": "sha512-1vvmgDdUSebVGXWX2lIcgRebqfQSff0hMEkLJyakQ9JQUbLDkEaMsPTLOmyccyC6IJ/l3FZuJbmrBw/u0A0uCQ==",
+ "version": "4.29.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.29.1.tgz",
+ "integrity": "sha512-xufkSNppNOdVRCEC4WKvlR1FBDyqCSCpQeMMgv9ZyXqqtKBfkw1yfGMTUTs9Qsl6WQbJnsGboWCp7pJGkeMhKA==",
"cpu": [
"x64"
],
@@ -1566,9 +1646,9 @@
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
- "version": "4.21.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.0.tgz",
- "integrity": "sha512-s5oFkZ/hFcrlAyBTONFY1TWndfyre1wOMwU+6KCpm/iatybvrRgmZVM+vCFwxmC5ZhdlgfE0N4XorsDpi7/4XQ==",
+ "version": "4.29.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.29.1.tgz",
+ "integrity": "sha512-F2OiJ42m77lSkizZQLuC+jiZ2cgueWQL5YC9tjo3AgaEw+KJmVxHGSyQfDUoYR9cci0lAywv2Clmckzulcq6ig==",
"cpu": [
"arm64"
],
@@ -1580,9 +1660,9 @@
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
- "version": "4.21.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.0.tgz",
- "integrity": "sha512-G9+TEqRnAA6nbpqyUqgTiopmnfgnMkR3kMukFBDsiyy23LZvUCpiUwjTRx6ezYCjJODXrh52rBR9oXvm+Fp5wg==",
+ "version": "4.29.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.29.1.tgz",
+ "integrity": "sha512-rYRe5S0FcjlOBZQHgbTKNrqxCBUmgDJem/VQTCcTnA2KCabYSWQDrytOzX7avb79cAAweNmMUb/Zw18RNd4mng==",
"cpu": [
"ia32"
],
@@ -1594,9 +1674,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
- "version": "4.21.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.0.tgz",
- "integrity": "sha512-2jsCDZwtQvRhejHLfZ1JY6w6kEuEtfF9nzYsZxzSlNVKDX+DpsDJ+Rbjkm74nvg2rdx0gwBS+IMdvwJuq3S9pQ==",
+ "version": "4.29.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.29.1.tgz",
+ "integrity": "sha512-+10CMg9vt1MoHj6x1pxyjPSMjHTIlqs8/tBztXvPAx24SKs9jwVnKqHJumlH/IzhaPUaj3T6T6wfZr8okdXaIg==",
"cpu": [
"x64"
],
@@ -1834,12 +1914,22 @@
}
},
"node_modules/@types/estree": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
- "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
+ "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/hoist-non-react-statics": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.6.tgz",
+ "integrity": "sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/react": "*",
+ "hoist-non-react-statics": "^3.3.0"
+ }
+ },
"node_modules/@types/json5": {
"version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
@@ -1904,6 +1994,16 @@
"@types/react": "*"
}
},
+ "node_modules/@types/react-input-mask": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/@types/react-input-mask/-/react-input-mask-3.0.6.tgz",
+ "integrity": "sha512-+5I18WKyG3eWIj7TVPWfK1VitI9mPpS9y6jE/BfmTCe+iL27NfBw/yzKRvCFp1DRBvlvvcsiZf05bub0YC1k8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
"node_modules/@types/react-transition-group": {
"version": "4.4.11",
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.11.tgz",
@@ -1913,6 +2013,12 @@
"@types/react": "*"
}
},
+ "node_modules/@types/yup": {
+ "version": "0.29.14",
+ "resolved": "https://registry.npmjs.org/@types/yup/-/yup-0.29.14.tgz",
+ "integrity": "sha512-Ynb/CjHhE/Xp/4bhHmQC4U1Ox+I2OpfRYF3dnNgQqn1cHa6LK3H1wJMNPT02tSVZA6FYuXE2ITORfbnb6zBCSA==",
+ "license": "MIT"
+ },
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "7.18.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz",
@@ -2430,6 +2536,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "license": "MIT"
+ },
"node_modules/available-typed-arrays": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
@@ -2456,6 +2568,17 @@
"node": ">=4"
}
},
+ "node_modules/axios": {
+ "version": "1.7.9",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz",
+ "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==",
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
"node_modules/axobject-query": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz",
@@ -2638,6 +2761,18 @@
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
"license": "MIT"
},
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/commander": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
@@ -2684,10 +2819,19 @@
"node": ">=10"
}
},
+ "node_modules/cross-fetch": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz",
+ "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==",
+ "license": "MIT",
+ "dependencies": {
+ "node-fetch": "^2.6.12"
+ }
+ },
"node_modules/cross-spawn": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2825,6 +2969,15 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/deepmerge": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz",
+ "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/define-data-property": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
@@ -2861,6 +3014,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
"node_modules/dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@@ -4089,6 +4251,26 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/follow-redirects": {
+ "version": "1.15.9",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
+ "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
"node_modules/for-each": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
@@ -4099,6 +4281,51 @@
"is-callable": "^1.1.3"
}
},
+ "node_modules/form-data": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz",
+ "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==",
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/formik": {
+ "version": "2.4.6",
+ "resolved": "https://registry.npmjs.org/formik/-/formik-2.4.6.tgz",
+ "integrity": "sha512-A+2EI7U7aG296q2TLGvNapDNTZp1khVt5Vk0Q/fyfSROss0V/V6+txt2aJnwEos44IxTCW/LYAi/zgWzlevj+g==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://opencollective.com/formik"
+ }
+ ],
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/hoist-non-react-statics": "^3.3.1",
+ "deepmerge": "^2.1.1",
+ "hoist-non-react-statics": "^3.3.0",
+ "lodash": "^4.17.21",
+ "lodash-es": "^4.17.21",
+ "react-fast-compare": "^2.0.1",
+ "tiny-warning": "^1.0.2",
+ "tslib": "^2.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ }
+ },
+ "node_modules/formik/node_modules/react-fast-compare": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz",
+ "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==",
+ "license": "MIT"
+ },
"node_modules/fs-extra": {
"version": "11.1.1",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz",
@@ -4467,6 +4694,64 @@
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"license": "MIT"
},
+ "node_modules/html-parse-stringify": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
+ "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==",
+ "license": "MIT",
+ "dependencies": {
+ "void-elements": "3.1.0"
+ }
+ },
+ "node_modules/i18next": {
+ "version": "24.2.0",
+ "resolved": "https://registry.npmjs.org/i18next/-/i18next-24.2.0.tgz",
+ "integrity": "sha512-ArJJTS1lV6lgKH7yEf4EpgNZ7+THl7bsGxxougPYiXRTJ/Fe1j08/TBpV9QsXCIYVfdE/HWG/xLezJ5DOlfBOA==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://locize.com"
+ },
+ {
+ "type": "individual",
+ "url": "https://locize.com/i18next.html"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.23.2"
+ },
+ "peerDependencies": {
+ "typescript": "^5"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/i18next-browser-languagedetector": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.2.tgz",
+ "integrity": "sha512-shBvPmnIyZeD2VU5jVGIOWP7u9qNG3Lj7mpaiPFpbJ3LVfHZJvVzKR4v1Cb91wAOFpNw442N+LGPzHOHsten2g==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.23.2"
+ }
+ },
+ "node_modules/i18next-http-backend": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-3.0.1.tgz",
+ "integrity": "sha512-XT2lYSkbAtDE55c6m7CtKxxrsfuRQO3rUfHzj8ZyRtY9CkIX3aRGwXGTkUhpGWce+J8n7sfu3J0f2wTzo7Lw0A==",
+ "license": "MIT",
+ "dependencies": {
+ "cross-fetch": "4.0.0"
+ }
+ },
"node_modules/ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
@@ -5077,6 +5362,15 @@
"node": ">=4.0"
}
},
+ "node_modules/jwt-decode": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz",
+ "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/language-subtag-registry": {
"version": "0.3.23",
"resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz",
@@ -5188,6 +5482,27 @@
"node": ">=8.6"
}
},
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
@@ -5221,9 +5536,9 @@
"license": "MIT"
},
"node_modules/nanoid": {
- "version": "3.3.7",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
- "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
+ "version": "3.3.8",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
+ "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
"dev": true,
"funding": [
{
@@ -5253,6 +5568,26 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/node-fetch": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+ "license": "MIT",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@@ -5545,9 +5880,9 @@
}
},
"node_modules/picocolors": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
- "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"license": "ISC"
},
"node_modules/picomatch": {
@@ -5574,9 +5909,9 @@
}
},
"node_modules/postcss": {
- "version": "8.4.41",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz",
- "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==",
+ "version": "8.4.49",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz",
+ "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==",
"dev": true,
"funding": [
{
@@ -5595,8 +5930,8 @@
"license": "MIT",
"dependencies": {
"nanoid": "^3.3.7",
- "picocolors": "^1.0.1",
- "source-map-js": "^1.2.0"
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
},
"engines": {
"node": "^10 || ^12 || >=14"
@@ -5658,6 +5993,18 @@
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"license": "MIT"
},
+ "node_modules/property-expr": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz",
+ "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==",
+ "license": "MIT"
+ },
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "license": "MIT"
+ },
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
@@ -5747,6 +6094,42 @@
"react": "^16.6.0 || ^17.0.0 || ^18.0.0"
}
},
+ "node_modules/react-i18next": {
+ "version": "15.4.0",
+ "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.4.0.tgz",
+ "integrity": "sha512-Py6UkX3zV08RTvL6ZANRoBh9sL/ne6rQq79XlkHEdd82cZr2H9usbWpUNVadJntIZP2pu3M2rL1CN+5rQYfYFw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.25.0",
+ "html-parse-stringify": "^3.0.1"
+ },
+ "peerDependencies": {
+ "i18next": ">= 23.2.3",
+ "react": ">= 16.8.0"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ },
+ "react-native": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-input-mask": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/react-input-mask/-/react-input-mask-2.0.4.tgz",
+ "integrity": "sha512-1hwzMr/aO9tXfiroiVCx5EtKohKwLk/NT8QlJXHQ4N+yJJFyUuMT+zfTpLBwX/lK3PkuMlievIffncpMZ3HGRQ==",
+ "license": "MIT",
+ "dependencies": {
+ "invariant": "^2.2.4",
+ "warning": "^4.0.2"
+ },
+ "peerDependencies": {
+ "react": ">=0.14.0",
+ "react-dom": ">=0.14.0"
+ }
+ },
"node_modules/react-is": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
@@ -5926,13 +6309,13 @@
}
},
"node_modules/rollup": {
- "version": "4.21.0",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.0.tgz",
- "integrity": "sha512-vo+S/lfA2lMS7rZ2Qoubi6I5hwZwzXeUIctILZLbHI+laNtvhhOIon2S1JksA5UEDQ7l3vberd0fxK44lTYjbQ==",
+ "version": "4.29.1",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.29.1.tgz",
+ "integrity": "sha512-RaJ45M/kmJUzSWDs1Nnd5DdV4eerC98idtUOVr6FfKcgxqvjwHmxc5upLF9qZU9EpsVzzhleFahrT3shLuJzIw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@types/estree": "1.0.5"
+ "@types/estree": "1.0.6"
},
"bin": {
"rollup": "dist/bin/rollup"
@@ -5942,22 +6325,25 @@
"npm": ">=8.0.0"
},
"optionalDependencies": {
- "@rollup/rollup-android-arm-eabi": "4.21.0",
- "@rollup/rollup-android-arm64": "4.21.0",
- "@rollup/rollup-darwin-arm64": "4.21.0",
- "@rollup/rollup-darwin-x64": "4.21.0",
- "@rollup/rollup-linux-arm-gnueabihf": "4.21.0",
- "@rollup/rollup-linux-arm-musleabihf": "4.21.0",
- "@rollup/rollup-linux-arm64-gnu": "4.21.0",
- "@rollup/rollup-linux-arm64-musl": "4.21.0",
- "@rollup/rollup-linux-powerpc64le-gnu": "4.21.0",
- "@rollup/rollup-linux-riscv64-gnu": "4.21.0",
- "@rollup/rollup-linux-s390x-gnu": "4.21.0",
- "@rollup/rollup-linux-x64-gnu": "4.21.0",
- "@rollup/rollup-linux-x64-musl": "4.21.0",
- "@rollup/rollup-win32-arm64-msvc": "4.21.0",
- "@rollup/rollup-win32-ia32-msvc": "4.21.0",
- "@rollup/rollup-win32-x64-msvc": "4.21.0",
+ "@rollup/rollup-android-arm-eabi": "4.29.1",
+ "@rollup/rollup-android-arm64": "4.29.1",
+ "@rollup/rollup-darwin-arm64": "4.29.1",
+ "@rollup/rollup-darwin-x64": "4.29.1",
+ "@rollup/rollup-freebsd-arm64": "4.29.1",
+ "@rollup/rollup-freebsd-x64": "4.29.1",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.29.1",
+ "@rollup/rollup-linux-arm-musleabihf": "4.29.1",
+ "@rollup/rollup-linux-arm64-gnu": "4.29.1",
+ "@rollup/rollup-linux-arm64-musl": "4.29.1",
+ "@rollup/rollup-linux-loongarch64-gnu": "4.29.1",
+ "@rollup/rollup-linux-powerpc64le-gnu": "4.29.1",
+ "@rollup/rollup-linux-riscv64-gnu": "4.29.1",
+ "@rollup/rollup-linux-s390x-gnu": "4.29.1",
+ "@rollup/rollup-linux-x64-gnu": "4.29.1",
+ "@rollup/rollup-linux-x64-musl": "4.29.1",
+ "@rollup/rollup-win32-arm64-msvc": "4.29.1",
+ "@rollup/rollup-win32-ia32-msvc": "4.29.1",
+ "@rollup/rollup-win32-x64-msvc": "4.29.1",
"fsevents": "~2.3.2"
}
},
@@ -6169,9 +6555,9 @@
}
},
"node_modules/source-map-js": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
- "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
@@ -6483,6 +6869,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/tiny-case": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz",
+ "integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==",
+ "license": "MIT"
+ },
"node_modules/tiny-invariant": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz",
@@ -6490,6 +6882,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/tiny-warning": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
+ "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==",
+ "license": "MIT"
+ },
"node_modules/to-fast-properties": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
@@ -6512,6 +6910,18 @@
"node": ">=8.0"
}
},
+ "node_modules/toposort": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
+ "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==",
+ "license": "MIT"
+ },
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+ "license": "MIT"
+ },
"node_modules/ts-api-utils": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz",
@@ -6542,7 +6952,6 @@
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
"integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
- "dev": true,
"license": "0BSD"
},
"node_modules/type-check": {
@@ -6706,14 +7115,14 @@
}
},
"node_modules/vite": {
- "version": "5.4.2",
- "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.2.tgz",
- "integrity": "sha512-dDrQTRHp5C1fTFzcSaMxjk6vdpKvT+2/mIdE07Gw2ykehT49O0z/VHS3zZ8iV/Gh8BJJKHWOe5RjaNrW5xf/GA==",
+ "version": "5.4.11",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz",
+ "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"esbuild": "^0.21.3",
- "postcss": "^8.4.41",
+ "postcss": "^8.4.43",
"rollup": "^4.20.0"
},
"bin": {
@@ -6908,6 +7317,15 @@
"node": ">=8"
}
},
+ "node_modules/void-elements": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz",
+ "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/vscode-jsonrpc": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz",
@@ -7002,6 +7420,31 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/warning": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
+ "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.0.0"
+ }
+ },
+ "node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "license": "MIT",
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -7129,6 +7572,30 @@
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
+ },
+ "node_modules/yup": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/yup/-/yup-1.6.1.tgz",
+ "integrity": "sha512-JED8pB50qbA4FOkDol0bYF/p60qSEDQqBD0/qeIrUCG1KbPBIQ776fCUNb9ldbPcSTxA69g/47XTo4TqWiuXOA==",
+ "license": "MIT",
+ "dependencies": {
+ "property-expr": "^2.0.5",
+ "tiny-case": "^1.0.3",
+ "toposort": "^2.0.2",
+ "type-fest": "^2.19.0"
+ }
+ },
+ "node_modules/yup/node_modules/type-fest": {
+ "version": "2.19.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz",
+ "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==",
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=12.20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
}
}
}
diff --git a/package.json b/package.json
index 8842c7bea..e21ca2198 100644
--- a/package.json
+++ b/package.json
@@ -30,22 +30,34 @@
"@fontsource-variable/dm-sans": "^5.0.7",
"@fontsource/barlow": "^5.0.14",
"@iconify/react": "^5.0.2",
+ "@mui/icons-material": "^6.3.1",
"@mui/lab": "^5.0.0-alpha.173",
"@mui/material": "^5.16.7",
+ "@types/yup": "^0.29.14",
"apexcharts": "^3.52.0",
+ "axios": "^1.7.9",
"dayjs": "^1.11.13",
+ "formik": "^2.4.6",
"history": "^5.3.0",
+ "i18next": "^24.2.0",
+ "i18next-browser-languagedetector": "^8.0.2",
+ "i18next-http-backend": "^3.0.1",
+ "jwt-decode": "^4.0.0",
"react": "^18.3.1",
"react-apexcharts": "^1.4.1",
"react-dom": "^18.3.1",
"react-helmet-async": "^2.0.5",
+ "react-i18next": "^15.4.0",
+ "react-input-mask": "^2.0.4",
"react-router-dom": "^6.26.1",
- "simplebar-react": "^3.2.6"
+ "simplebar-react": "^3.2.6",
+ "yup": "^1.6.1"
},
"devDependencies": {
"@types/node": "^22.5.0",
"@types/react": "^18.3.4",
"@types/react-dom": "^18.3.0",
+ "@types/react-input-mask": "^3.0.6",
"@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.18.0",
"@vitejs/plugin-react-swc": "^3.7.0",
diff --git a/public/assets/icons/flags/ic-flag-en.svg b/public/assets/icons/flags/ic-flag-en.svg
index 485ad5c34..30bc3008c 100644
--- a/public/assets/icons/flags/ic-flag-en.svg
+++ b/public/assets/icons/flags/ic-flag-en.svg
@@ -1 +1,21 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/public/assets/icons/flags/ic-flag-fr.svg b/public/assets/icons/flags/ic-flag-fr.svg
deleted file mode 100644
index 2ae63a139..000000000
--- a/public/assets/icons/flags/ic-flag-fr.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/assets/icons/flags/ic-flag-tr.svg b/public/assets/icons/flags/ic-flag-tr.svg
new file mode 100644
index 000000000..6eb0e145e
--- /dev/null
+++ b/public/assets/icons/flags/ic-flag-tr.svg
@@ -0,0 +1,26 @@
+
\ No newline at end of file
diff --git a/public/assets/icons/navbar/ic-business.svg b/public/assets/icons/navbar/ic-business.svg
new file mode 100644
index 000000000..04eb9028b
--- /dev/null
+++ b/public/assets/icons/navbar/ic-business.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/public/locales/en/auth.json b/public/locales/en/auth.json
new file mode 100644
index 000000000..f7fd9e5b7
--- /dev/null
+++ b/public/locales/en/auth.json
@@ -0,0 +1,36 @@
+{
+ "signIn": {
+ "title": "Sign In",
+ "welcome": "Welcome",
+ "getStarted": "Get Started",
+ "forgotPassword": "Forgot password?",
+ "labels": {
+ "email": "Email address",
+ "password": "Password"
+ },
+ "placeholders": {
+ "email": "your@email.com",
+ "password": "••••••"
+ },
+ "buttons": {
+ "signIn": "Sign In",
+ "signingIn": "Signing in..."
+ },
+ "errors": {
+ "invalidEmail": "Please enter a valid email address.",
+ "passwordLength": "Password must be at least 6 characters long."
+ },
+ "helmet": "Sign In | Admin Panel"
+ },
+ "resetPassword": {
+ "title": "Reset Password",
+ "description": "Enter your account's email address, and we'll send you a link to reset your password.",
+ "emailLabel": "Email address",
+ "emailPlaceholder": "your@email.com",
+ "cancel": "Cancel",
+ "continue": "Continue",
+ "loading": "Loading...",
+ "successMessage": "Password reset link sent successfully!",
+ "emailErrorMessage": "Please enter a valid email address."
+ }
+}
\ No newline at end of file
diff --git a/public/locales/en/common.json b/public/locales/en/common.json
new file mode 100644
index 000000000..f32e119f7
--- /dev/null
+++ b/public/locales/en/common.json
@@ -0,0 +1,37 @@
+{
+ "welcome": "Welcome",
+ "getStarted": "Get Started",
+ "months": {
+ "short": {
+ "jan": "Jan",
+ "feb": "Feb",
+ "mar": "Mar",
+ "apr": "Apr",
+ "may": "May",
+ "jun": "Jun",
+ "jul": "Jul",
+ "aug": "Aug",
+ "sep": "Sep",
+ "oct": "Oct",
+ "nov": "Nov",
+ "dec": "Dec"
+ },
+ "long": {
+ "january": "January",
+ "february": "February",
+ "march": "March",
+ "april": "April",
+ "may": "May",
+ "june": "June",
+ "july": "July",
+ "august": "August",
+ "september": "September",
+ "october": "October",
+ "november": "November",
+ "december": "December"
+ }
+ },
+ "spinner": {
+ "pleaseWait": "Please Wait..."
+ }
+}
\ No newline at end of file
diff --git a/public/locales/en/company.json b/public/locales/en/company.json
new file mode 100644
index 000000000..1ca2bb64c
--- /dev/null
+++ b/public/locales/en/company.json
@@ -0,0 +1,82 @@
+{
+ "company": {
+ "title": "Companies",
+ "newCompany": "New Company",
+ "addCompany": "Add Company",
+ "companyName": "Company Name",
+ "phone": "Phone",
+ "email": "Email",
+ "status": "Status",
+ "active": "Active",
+ "passive": "Passive",
+ "taxNumber": "Tax Number",
+ "website": "Website",
+ "address": "Address",
+ "description": "Description",
+ "cancel": "Cancel",
+ "save": "Save",
+ "edit": "Edit",
+ "delete": "Delete",
+ "companyDetails": "Company Details",
+ "foundedYear": "Founded Year",
+ "employeeCount": "Employee Count",
+ "certifications": "Certifications",
+ "operationAreas": "Operation Areas",
+ "sections": {
+ "basicInfo": "Basic Information",
+ "companyDetails": "Company Details",
+ "insurance": "Insurance Information",
+ "bankAccounts": "Bank Accounts",
+ "description": "Description",
+ "contacts": "Contact Persons"
+ },
+ "insurance": {
+ "provider": "Insurance Provider",
+ "policyNumber": "Policy Number",
+ "coverage": "Coverage",
+ "expiryDate": "Expiry Date"
+ },
+ "bank": {
+ "name": "Bank",
+ "branch": "Branch",
+ "accountNumber": "Account Number",
+ "iban": "IBAN",
+ "currency": "Currency"
+ },
+ "contacts": {
+ "new": "New Contact",
+ "mainContact": "Main Contact",
+ "contactMethod": {
+ "phone": "Phone",
+ "email": "Email",
+ "whatsapp": "WhatsApp"
+ }
+ },
+ "tabs": {
+ "general": "General Information",
+ "contacts": "Contact Persons",
+ "contracts": "Contracts",
+ "performance": "Performance",
+ "pricing": "Pricing",
+ "analytics": "Analytics"
+ },
+ "validation": {
+ "companyNameRequired": "Company name is required",
+ "companyNameMin": "Company name must be at least 2 characters",
+ "companyNameMax": "Company name cannot exceed 100 characters",
+ "taxNumberRequired": "Tax number is required",
+ "taxNumberFormat": "Tax number must be 10 digits",
+ "phoneRequired": "Phone number is required",
+ "phoneFormat": "Please enter a valid phone number (10-11 digits)",
+ "emailRequired": "Email address is required",
+ "addressRequired": "Address is required",
+ "addressMin": "Address must be at least 10 characters",
+ "addressMax": "Address cannot exceed 500 characters",
+ "descriptionMax": "Description cannot exceed 1000 characters",
+ "statusRequired": "Status selection is required",
+ "email": "Please enter a valid email address",
+ "phone": "Please enter a valid phone number",
+ "url": "Please enter a valid website URL"
+ }
+ }
+}
\ No newline at end of file
diff --git a/public/locales/en/error.json b/public/locales/en/error.json
new file mode 100644
index 000000000..7fc17582e
--- /dev/null
+++ b/public/locales/en/error.json
@@ -0,0 +1,6 @@
+{
+ "notFound": {
+ "title": "404 page not found!",
+ "helmet": "404 page not found! | Error - {appName}"
+ }
+}
\ No newline at end of file
diff --git a/public/locales/en/overview.json b/public/locales/en/overview.json
new file mode 100644
index 000000000..ddb9f0df3
--- /dev/null
+++ b/public/locales/en/overview.json
@@ -0,0 +1,57 @@
+{
+ "welcome": "Hi, Welcome back 👋",
+ "widgets": {
+ "weeklySales": "Weekly Sales",
+ "newUsers": "New Users",
+ "purchaseOrders": "Purchase Orders",
+ "messages": "Messages"
+ },
+ "charts": {
+ "currentVisits": {
+ "title": "Current Visits",
+ "regions": {
+ "america": "America",
+ "asia": "Asia",
+ "europe": "Europe",
+ "africa": "Africa"
+ }
+ },
+ "websiteVisits": {
+ "title": "Website Visits",
+ "subheader": "(+43%) than last year",
+ "teams": {
+ "teamA": "Team A",
+ "teamB": "Team B"
+ }
+ },
+ "conversionRates": {
+ "title": "Conversion Rates",
+ "subheader": "(+43%) than last year"
+ },
+ "currentSubject": {
+ "title": "Current Subject",
+ "subjects": {
+ "english": "English",
+ "history": "History",
+ "physics": "Physics",
+ "geography": "Geography",
+ "chinese": "Chinese",
+ "math": "Math"
+ }
+ }
+ },
+ "sections": {
+ "news": {
+ "title": "News"
+ },
+ "orderTimeline": {
+ "title": "Order Timeline"
+ },
+ "trafficBySite": {
+ "title": "Traffic by Site"
+ },
+ "tasks": {
+ "title": "Tasks"
+ }
+ }
+}
\ No newline at end of file
diff --git a/public/locales/en/products.json b/public/locales/en/products.json
new file mode 100644
index 000000000..eb199d435
--- /dev/null
+++ b/public/locales/en/products.json
@@ -0,0 +1,6 @@
+{
+ "list": {
+ "title": "Products",
+ "helmet": "Products | Admin Panel"
+ }
+}
\ No newline at end of file
diff --git a/public/locales/en/profile.json b/public/locales/en/profile.json
new file mode 100644
index 000000000..1eef9240e
--- /dev/null
+++ b/public/locales/en/profile.json
@@ -0,0 +1,43 @@
+{
+ "title": "Profile",
+ "subtitle": "Update your profile information and manage security settings",
+ "tabs": {
+ "general": "General Information",
+ "security": "Security",
+ "notifications": "Notifications"
+ },
+ "name": "First Name",
+ "lastName": "Last Name",
+ "email": "Email",
+ "phone": "Phone Number",
+ "phoneFormat": "(555) 555 55 55",
+ "about": "About Me",
+ "aboutPlaceholder": "Write a short bio about yourself...",
+ "save": "Save",
+ "reset": "Reset",
+ "success": "Your profile has been updated successfully",
+ "error": {
+ "update": "Failed to update your profile"
+ },
+ "loading": "Loading...",
+ "security": {
+ "title": "Change Password",
+ "currentPassword": "Current Password",
+ "newPassword": "New Password",
+ "confirmPassword": "Confirm New Password",
+ "changePassword": "Change Password",
+ "success": "Your password has been changed successfully",
+ "error": "Failed to change your password"
+ },
+ "notifications": {
+ "title": "Notification Preferences",
+ "email": "Email Notifications",
+ "emailDesc": "Receive email notifications for important updates and information",
+ "push": "Push Notifications",
+ "pushDesc": "Receive push notifications through the application",
+ "sms": "SMS Notifications",
+ "smsDesc": "Receive SMS notifications for important updates",
+ "success": "Your notification preferences have been updated",
+ "error": "Failed to update your notification preferences"
+ }
+}
\ No newline at end of file
diff --git a/public/locales/en/validation.json b/public/locales/en/validation.json
new file mode 100644
index 000000000..aa5416bd2
--- /dev/null
+++ b/public/locales/en/validation.json
@@ -0,0 +1,35 @@
+{
+ "required": {
+ "firstName": "First name is required",
+ "lastName": "Last name is required",
+ "email": "Email is required",
+ "phone": "Phone number is required",
+ "password": "Password is required",
+ "currentPassword": "Current password is required",
+ "newPassword": "New password is required",
+ "confirmPassword": "Confirm password is required"
+ },
+ "invalid": {
+ "email": "Please enter a valid email address",
+ "phone": "Please enter a valid phone number",
+ "password": "Please enter a valid password"
+ },
+ "length": {
+ "name": {
+ "min": "Must be at least 2 characters",
+ "max": "Must be at most 50 characters"
+ },
+ "about": {
+ "max": "Must be at most 500 characters"
+ }
+ },
+ "password": {
+ "uppercase": "Must contain at least one uppercase letter",
+ "lowercase": "Must contain at least one lowercase letter",
+ "number": "Must contain at least one number",
+ "special": "Must contain at least one special character",
+ "match": "Passwords do not match",
+ "same": "New password cannot be the same as current password",
+ "min": "Must be at least {{length}} characters"
+ }
+}
\ No newline at end of file
diff --git a/public/locales/tr/auth.json b/public/locales/tr/auth.json
new file mode 100644
index 000000000..653ff74c6
--- /dev/null
+++ b/public/locales/tr/auth.json
@@ -0,0 +1,36 @@
+{
+ "signIn": {
+ "title": "Giriş Yap",
+ "welcome": "Hoş geldiniz",
+ "getStarted": "Başlayın",
+ "forgotPassword": "Şifremi Unuttum",
+ "labels": {
+ "email": "E-posta adresi",
+ "password": "Şifre"
+ },
+ "placeholders": {
+ "email": "ornek@email.com",
+ "password": "••••••"
+ },
+ "buttons": {
+ "signIn": "Giriş Yap",
+ "signingIn": "Giriş Yapılıyor..."
+ },
+ "errors": {
+ "invalidEmail": "Lütfen geçerli bir e-posta adresi girin.",
+ "passwordLength": "Şifre en az 6 karakter olmalıdır."
+ },
+ "helmet": "Giriş Yap | Yönetim Paneli"
+ },
+ "resetPassword": {
+ "title": "Şifreyi sıfırla",
+ "description": "Hesabınızın e-posta adresini girin, size şifrenizi sıfırlamak için bir bağlantı göndereceğiz.",
+ "emailLabel": "E-posta adresi",
+ "emailPlaceholder": "sizin@email.com",
+ "cancel": "İptal",
+ "continue": "Devam et",
+ "loading": "Yükleniyor...",
+ "successMessage": "Şifre sıfırlama bağlantısı başarıyla gönderildi!",
+ "emailErrorMessage": "Lütfen geçerli bir e-posta adresi girin."
+ }
+}
\ No newline at end of file
diff --git a/public/locales/tr/common.json b/public/locales/tr/common.json
new file mode 100644
index 000000000..d00832cad
--- /dev/null
+++ b/public/locales/tr/common.json
@@ -0,0 +1,8 @@
+{
+ "back": "Geri Dön",
+ "cancel": "İptal",
+ "confirm": "Tamam",
+ "unsavedChanges": "Kaydedilmemiş Değişiklikler",
+ "unsavedChangesMessage": "Kaydedilmemiş değişiklikleriniz var. Çıkmak istediğinizden emin misiniz?",
+ "pleaseWait": "Lütfen bekleyin..."
+}
\ No newline at end of file
diff --git a/public/locales/tr/company.json b/public/locales/tr/company.json
new file mode 100644
index 000000000..3fde0e1e3
--- /dev/null
+++ b/public/locales/tr/company.json
@@ -0,0 +1,82 @@
+{
+ "company": {
+ "title": "İş Ortakları",
+ "newCompany": "Yeni Şirket",
+ "addCompany": "Şirket Ekle",
+ "companyName": "Şirket Adı",
+ "phone": "Telefon",
+ "email": "E-posta",
+ "status": "Durum",
+ "active": "Aktif",
+ "passive": "Pasif",
+ "taxNumber": "Vergi Numarası",
+ "website": "Web Sitesi",
+ "address": "Adres",
+ "description": "Açıklama",
+ "cancel": "İptal",
+ "save": "Kaydet",
+ "edit": "Düzenle",
+ "delete": "Sil",
+ "companyDetails": "Şirket Detayları",
+ "foundedYear": "Kuruluş Yılı",
+ "employeeCount": "Çalışan Sayısı",
+ "certifications": "Sertifikalar",
+ "operationAreas": "Faaliyet Alanları",
+ "sections": {
+ "basicInfo": "Temel Bilgiler",
+ "companyDetails": "Şirket Detayları",
+ "insurance": "Sigorta Bilgileri",
+ "bankAccounts": "Banka Hesapları",
+ "description": "Açıklama",
+ "contacts": "İletişim Kişileri"
+ },
+ "insurance": {
+ "provider": "Sigorta Şirketi",
+ "policyNumber": "Poliçe Numarası",
+ "coverage": "Kapsam",
+ "expiryDate": "Bitiş Tarihi"
+ },
+ "bank": {
+ "name": "Banka",
+ "branch": "Şube",
+ "accountNumber": "Hesap Numarası",
+ "iban": "IBAN",
+ "currency": "Para Birimi"
+ },
+ "contacts": {
+ "new": "Yeni Kişi",
+ "mainContact": "Ana İletişim",
+ "contactMethod": {
+ "phone": "Telefon",
+ "email": "E-posta",
+ "whatsapp": "WhatsApp"
+ }
+ },
+ "tabs": {
+ "general": "Genel Bilgiler",
+ "contacts": "İletişim Kişileri",
+ "contracts": "Sözleşmeler",
+ "performance": "Performans",
+ "pricing": "Fiyatlandırma",
+ "analytics": "Analitik"
+ },
+ "validation": {
+ "companyNameRequired": "Şirket adı zorunludur",
+ "companyNameMin": "Şirket adı en az 2 karakter olmalıdır",
+ "companyNameMax": "Şirket adı en fazla 100 karakter olabilir",
+ "taxNumberRequired": "Vergi numarası zorunludur",
+ "taxNumberFormat": "Vergi numarası 10 haneli olmalıdır",
+ "phoneRequired": "Telefon numarası zorunludur",
+ "phoneFormat": "Geçerli bir telefon numarası giriniz (10-11 haneli)",
+ "emailRequired": "E-posta adresi zorunludur",
+ "addressRequired": "Adres zorunludur",
+ "addressMin": "Adres en az 10 karakter olmalıdır",
+ "addressMax": "Adres en fazla 500 karakter olabilir",
+ "descriptionMax": "Açıklama en fazla 1000 karakter olabilir",
+ "statusRequired": "Durum seçimi zorunludur",
+ "email": "Geçerli bir e-posta adresi giriniz",
+ "phone": "Geçerli bir telefon numarası giriniz",
+ "url": "Geçerli bir web sitesi adresi giriniz"
+ }
+ }
+}
\ No newline at end of file
diff --git a/public/locales/tr/error.json b/public/locales/tr/error.json
new file mode 100644
index 000000000..e395cf7d8
--- /dev/null
+++ b/public/locales/tr/error.json
@@ -0,0 +1,6 @@
+{
+ "notFound": {
+ "title": "404 sayfa bulunamadı!",
+ "helmet": "404 sayfa bulunamadı! | Hata - {appName}"
+ }
+}
\ No newline at end of file
diff --git a/public/locales/tr/overview.json b/public/locales/tr/overview.json
new file mode 100644
index 000000000..29e42f738
--- /dev/null
+++ b/public/locales/tr/overview.json
@@ -0,0 +1,57 @@
+{
+ "welcome": "Merhaba, Tekrar Hoş Geldiniz 👋",
+ "widgets": {
+ "weeklySales": "Haftalık Satışlar",
+ "newUsers": "Yeni Kullanıcılar",
+ "purchaseOrders": "Satın Alma Siparişleri",
+ "messages": "Mesajlar"
+ },
+ "charts": {
+ "currentVisits": {
+ "title": "Mevcut Ziyaretler",
+ "regions": {
+ "america": "Amerika",
+ "asia": "Asya",
+ "europe": "Avrupa",
+ "africa": "Afrika"
+ }
+ },
+ "websiteVisits": {
+ "title": "Website Ziyaretleri",
+ "subheader": "Geçen yıla göre (+%43)",
+ "teams": {
+ "teamA": "Takım A",
+ "teamB": "Takım B"
+ }
+ },
+ "conversionRates": {
+ "title": "Dönüşüm Oranları",
+ "subheader": "Geçen yıla göre (+%43)"
+ },
+ "currentSubject": {
+ "title": "Mevcut Konu",
+ "subjects": {
+ "english": "İngilizce",
+ "history": "Tarih",
+ "physics": "Fizik",
+ "geography": "Coğrafya",
+ "chinese": "Çince",
+ "math": "Matematik"
+ }
+ }
+ },
+ "sections": {
+ "news": {
+ "title": "Haberler"
+ },
+ "orderTimeline": {
+ "title": "Sipariş Zaman Çizelgesi"
+ },
+ "trafficBySite": {
+ "title": "Sitelere Göre Trafik"
+ },
+ "tasks": {
+ "title": "Görevler"
+ }
+ }
+}
\ No newline at end of file
diff --git a/public/locales/tr/products.json b/public/locales/tr/products.json
new file mode 100644
index 000000000..40d2938f4
--- /dev/null
+++ b/public/locales/tr/products.json
@@ -0,0 +1,6 @@
+{
+ "list": {
+ "title": "Ürünler",
+ "helmet": "Ürünler | Yönetim Paneli"
+ }
+}
\ No newline at end of file
diff --git a/public/locales/tr/profile.json b/public/locales/tr/profile.json
new file mode 100644
index 000000000..caaa9f36a
--- /dev/null
+++ b/public/locales/tr/profile.json
@@ -0,0 +1,53 @@
+{
+ "title": "Profil",
+ "subtitle": "Profil bilgilerinizi güncelleyin ve güvenlik ayarlarınızı yönetin",
+ "tabs": {
+ "general": "Genel Bilgiler",
+ "security": "Güvenlik",
+ "notifications": "Bildirimler"
+ },
+ "name": "Ad",
+ "lastName": "Soyad",
+ "email": "E-posta",
+ "phone": "Telefon Numarası",
+ "phoneFormat": "(___) ___ __ __",
+ "about": "Hakkımda",
+ "aboutPlaceholder": "Kendiniz hakkında kısa bir bilgi yazın...",
+ "save": "Kaydet",
+ "reset": "Sıfırla",
+ "success": "Profil bilgileriniz başarıyla güncellendi",
+ "error": {
+ "update": "Profil bilgileriniz güncellenirken bir hata oluştu"
+ },
+ "loading": "Yükleniyor...",
+ "security": {
+ "title": "Şifre Değiştir",
+ "currentPassword": "Mevcut Şifre",
+ "newPassword": "Yeni Şifre",
+ "confirmPassword": "Yeni Şifre (Tekrar)",
+ "changePassword": "Şifreyi Değiştir",
+ "passwordRules": "Şifre aşağıdaki kurallara uygun olmalıdır",
+ "success": "Şifreniz başarıyla değiştirildi",
+ "error": "Şifreniz değiştirilirken bir hata oluştu"
+ },
+ "notifications": {
+ "title": "Bildirim Tercihleri",
+ "manage": "Yönet",
+ "email": {
+ "title": "E-posta Bildirimleri",
+ "description": "Önemli güncellemeler ve bilgilendirmeler için e-posta bildirimleri alın"
+ },
+ "push": {
+ "title": "Anlık Bildirimler",
+ "description": "Uygulama üzerinden anlık bildirimler alın"
+ },
+ "monthly": {
+ "title": "Aylık Rapor",
+ "description": "Her ay sonunda aktivite özetinizi alın"
+ },
+ "news": {
+ "title": "Haberler ve Güncellemeler",
+ "description": "Yeni özellikler ve güncellemelerden haberdar olun"
+ }
+ }
+}
\ No newline at end of file
diff --git a/public/locales/tr/validation.json b/public/locales/tr/validation.json
new file mode 100644
index 000000000..5700d125e
--- /dev/null
+++ b/public/locales/tr/validation.json
@@ -0,0 +1,35 @@
+{
+ "required": {
+ "firstName": "Ad alanı zorunludur",
+ "lastName": "Soyad alanı zorunludur",
+ "email": "E-posta alanı zorunludur",
+ "phone": "Telefon numarası zorunludur",
+ "password": "Şifre alanı zorunludur",
+ "currentPassword": "Mevcut şifre alanı zorunludur",
+ "newPassword": "Yeni şifre alanı zorunludur",
+ "confirmPassword": "Şifre tekrar alanı zorunludur"
+ },
+ "invalid": {
+ "email": "Geçerli bir e-posta adresi giriniz",
+ "phone": "Geçerli bir telefon numarası giriniz",
+ "password": "Geçerli bir şifre giriniz"
+ },
+ "length": {
+ "name": {
+ "min": "En az 2 karakter olmalıdır",
+ "max": "En fazla 50 karakter olmalıdır"
+ },
+ "about": {
+ "max": "En fazla 500 karakter olmalıdır"
+ }
+ },
+ "password": {
+ "uppercase": "En az bir büyük harf içermelidir",
+ "lowercase": "En az bir küçük harf içermelidir",
+ "number": "En az bir rakam içermelidir",
+ "special": "En az bir özel karakter içermelidir",
+ "match": "Şifreler eşleşmiyor",
+ "same": "Yeni şifre mevcut şifre ile aynı olamaz",
+ "min": "En az {{length}} karakter olmalıdır"
+ }
+}
\ No newline at end of file
diff --git a/src/_mock/_data.ts b/src/_mock/_data.ts
index d6dadc0eb..0e22139ff 100644
--- a/src/_mock/_data.ts
+++ b/src/_mock/_data.ts
@@ -99,21 +99,21 @@ export const _products = [...Array(24)].map((_, index) => {
// ----------------------------------------------------------------------
export const _langs = [
+ {
+ value: 'fr',
+ label: 'Turkish',
+ icon: '/assets/icons/flags/ic-flag-tr.svg',
+ },
{
value: 'en',
label: 'English',
icon: '/assets/icons/flags/ic-flag-en.svg',
},
- {
- value: 'de',
- label: 'German',
- icon: '/assets/icons/flags/ic-flag-de.svg',
- },
- {
- value: 'fr',
- label: 'French',
- icon: '/assets/icons/flags/ic-flag-fr.svg',
- },
+ // {
+ // value: 'de',
+ // label: 'German',
+ // icon: '/assets/icons/flags/ic-flag-de.svg',
+ // }
];
// ----------------------------------------------------------------------
diff --git a/src/app.tsx b/src/app.tsx
index 68bbf1784..80df5516d 100644
--- a/src/app.tsx
+++ b/src/app.tsx
@@ -1,44 +1,19 @@
import 'src/global.css';
-import Fab from '@mui/material/Fab';
-
import { Router } from 'src/routes/sections';
import { useScrollToTop } from 'src/hooks/use-scroll-to-top';
import { ThemeProvider } from 'src/theme/theme-provider';
-import { Iconify } from 'src/components/iconify';
-
-// ----------------------------------------------------------------------
+import { LoadingScreen } from './components/loading-screen/loading-screen';
export default function App() {
useScrollToTop();
-
- const githubButton = (
-
-
-
- );
-
return (
- {githubButton}
+
);
}
diff --git a/src/components/back-button.tsx b/src/components/back-button.tsx
new file mode 100644
index 000000000..1b8af4ac6
--- /dev/null
+++ b/src/components/back-button.tsx
@@ -0,0 +1,21 @@
+import { Button } from '@mui/material';
+import { useNavigate } from 'react-router-dom';
+import { useTranslation } from 'react-i18next';
+import ArrowBackIcon from '@mui/icons-material/ArrowBack';
+
+export function BackButton() {
+ const navigate = useNavigate();
+ const { t } = useTranslation();
+
+ return (
+ }
+ onClick={() => navigate(-1)}
+ sx={{ mb: 3 }}
+ >
+ {t('common:back')}
+
+ );
+}
\ No newline at end of file
diff --git a/src/components/color-utils/color-picker.tsx b/src/components/color-utils/color-picker.tsx
index 78d79db0f..92e8016fc 100644
--- a/src/components/color-utils/color-picker.tsx
+++ b/src/components/color-utils/color-picker.tsx
@@ -89,7 +89,13 @@ export const ColorPicker = forwardRef ({
+ sx={(theme: {
+ palette: { getContrastText: (arg0: string) => any };
+ transitions: {
+ create: (arg0: string, arg1: { duration: any }) => any;
+ duration: { shortest: any };
+ };
+ }) => ({
color: theme.palette.getContrastText(color),
transition: theme.transitions.create('all', {
duration: theme.transitions.duration.shortest,
diff --git a/src/components/iconify/index.ts b/src/components/iconify/index.ts
index 111840cf0..86b67def1 100644
--- a/src/components/iconify/index.ts
+++ b/src/components/iconify/index.ts
@@ -1,7 +1,4 @@
export * from './classes';
-
-export * from './iconify';
-
export * from './flag-icon';
-
export type * from './types';
+export { Iconify } from './iconify';
diff --git a/src/components/loading-screen/loading-screen.tsx b/src/components/loading-screen/loading-screen.tsx
new file mode 100644
index 000000000..48128f7a5
--- /dev/null
+++ b/src/components/loading-screen/loading-screen.tsx
@@ -0,0 +1,38 @@
+import {useTranslation} from "react-i18next";
+
+import { Box, Backdrop, Typography, CircularProgress } from '@mui/material';
+
+import { useLoading } from 'src/contexts/loading-context';
+
+export function LoadingScreen() {
+ const { t } = useTranslation();
+ const { isLoading } = useLoading();
+
+ if (!isLoading) return null;
+
+ return (
+
+
+
+
+ {t('common:spinner.pleaseWait')}
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/components/scrollbar/index.ts b/src/components/scrollbar/index.ts
index a483df68b..871a0a108 100644
--- a/src/components/scrollbar/index.ts
+++ b/src/components/scrollbar/index.ts
@@ -1,5 +1,3 @@
export * from './classes';
-
-export * from './scrollbar';
-
export type * from './types';
+export { Scrollbar } from './scrollbar';
diff --git a/src/components/settings/context/settings-context.tsx b/src/components/settings/context/settings-context.tsx
new file mode 100644
index 000000000..2e4e20b3c
--- /dev/null
+++ b/src/components/settings/context/settings-context.tsx
@@ -0,0 +1,15 @@
+import { useContext, createContext } from 'react';
+
+export interface SettingsContextProps {
+ themeStretch: boolean;
+}
+
+export const SettingsContext = createContext({} as SettingsContextProps);
+
+export const useSettingsContext = () => {
+ const context = useContext(SettingsContext);
+
+ if (!context) throw new Error('useSettingsContext must be used inside SettingsProvider');
+
+ return context;
+};
\ No newline at end of file
diff --git a/src/config/axios-instance.ts b/src/config/axios-instance.ts
new file mode 100644
index 000000000..57c3b5ce7
--- /dev/null
+++ b/src/config/axios-instance.ts
@@ -0,0 +1,30 @@
+import axios from 'axios';
+
+// Axios instance oluştur
+const axiosInstance = axios.create({
+ baseURL: 'http://localhost:8888', // .env'den baseURL al
+ timeout: 10000, // 10 saniye zaman aşımı
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+});
+
+// Request interceptor: Token ekleme
+axiosInstance.interceptors.request.use((config) => {
+ const token: string | null = localStorage.getItem('token');
+ if (token) {
+ config.headers.Authorization = `Bearer ${token}`;
+ }
+ return config;
+});
+
+// Response interceptor: Hata yönetimi
+axiosInstance.interceptors.response.use(
+ (response) => response,
+ (error) => {
+ console.error('API Error:', error.response || error.message);
+ return Promise.reject(error?.response?.data || 'Something went wrong');
+ }
+);
+
+export default axiosInstance;
diff --git a/src/contexts/Providers.tsx b/src/contexts/Providers.tsx
new file mode 100644
index 000000000..b1ad09886
--- /dev/null
+++ b/src/contexts/Providers.tsx
@@ -0,0 +1,34 @@
+import type { ReactNode } from 'react';
+
+import { BrowserRouter } from 'react-router-dom';
+import { HelmetProvider } from 'react-helmet-async';
+
+import { AuthProvider } from './auth-context';
+import { UserProvider } from './user-context';
+import { LoadingProvider } from './loading-context';
+import { RouterGuard } from '../routes/components/router-guard';
+import { UnsavedChangesProvider } from './unsaved-changes-context';
+
+type ProvidersProps = {
+ children: ReactNode;
+};
+
+export function Providers({ children }: ProvidersProps) {
+ return (
+
+
+
+
+
+
+
+ {children}
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/contexts/auth-context.tsx b/src/contexts/auth-context.tsx
new file mode 100644
index 000000000..074846855
--- /dev/null
+++ b/src/contexts/auth-context.tsx
@@ -0,0 +1,113 @@
+import type { ReactNode } from 'react';
+
+import { jwtDecode } from 'jwt-decode';
+import React, { useMemo, useState, useEffect, useContext, createContext } from 'react';
+
+interface DecodedToken {
+ sub: string;
+ roles: string[];
+ exp: number; // Token expiration timestamp
+}
+
+interface User {
+ email: string;
+ roles: string[];
+}
+
+interface AuthContextProps {
+ isAuthenticated: boolean;
+ user: User | null;
+ isLoading: boolean;
+ login: (token: string) => void;
+ logout: () => void;
+}
+
+export const AuthContext = createContext({
+ isAuthenticated: false,
+ user: null,
+ isLoading: true,
+ login: () => {},
+ logout: () => {},
+});
+
+interface AuthProviderProps {
+ children: ReactNode;
+}
+
+export const AuthProvider: React.FC = ({ children }) => {
+ const [isAuthenticated, setIsAuthenticated] = useState(false);
+ const [user, setUser] = useState(null);
+ const [isLoading, setIsLoading] = useState(true);
+
+ // Token geçerliliğini kontrol eden yardımcı fonksiyon
+ const isTokenValid = (token: string): boolean => {
+ try {
+ const { exp } = jwtDecode(token);
+ return Date.now() < exp * 1000; // Token geçerli mi kontrol et
+ } catch (error) {
+ console.error('Invalid token:', error);
+ return false;
+ }
+ };
+
+ // Login işlemi
+ const login = (token: string) => {
+ console.log('Login fonksiyonu çağrıldı', token); // Debug için log
+ localStorage.setItem('token', token);
+ const decodedToken = jwtDecode(token);
+ setIsAuthenticated(true);
+ setUser({ email: decodedToken.sub, roles: decodedToken.roles || [] }); // sub alanını kullanıyoruz
+ };
+
+ // Logout işlemi
+ const logout = () => {
+ localStorage.removeItem('token');
+ setIsAuthenticated(false);
+ setUser(null);
+ };
+
+ useEffect(() => {
+ const checkToken = () => {
+ const token = localStorage.getItem('token');
+ if (token && isTokenValid(token)) {
+ const decodedToken = jwtDecode(token);
+ setIsAuthenticated(true);
+ setUser({ email: decodedToken.sub, roles: decodedToken.roles });
+ } else {
+ setIsAuthenticated(false);
+ setUser(null);
+ }
+ setIsLoading(false); // Yükleme tamamlandı
+ };
+
+ // İlk yüklemede token kontrolü yap
+ checkToken();
+
+ // LocalStorage değişikliklerini dinle
+ const handleStorageChange = () => {
+ checkToken();
+ };
+
+ window.addEventListener('storage', handleStorageChange);
+
+ // Cleanup listener
+ return () => {
+ window.removeEventListener('storage', handleStorageChange);
+ };
+ }, []);
+
+ const contextValue = useMemo(
+ () => ({ isAuthenticated, user, isLoading, login, logout }),
+ [isAuthenticated, user, isLoading]
+ );
+
+ return {children};
+};
+
+export const useAuth = () => {
+ const context = useContext(AuthContext);
+ if (!context) {
+ throw new Error('useAuth must be used within an AuthProvider');
+ }
+ return context;
+};
diff --git a/src/contexts/loading-context.tsx b/src/contexts/loading-context.tsx
new file mode 100644
index 000000000..62a177cec
--- /dev/null
+++ b/src/contexts/loading-context.tsx
@@ -0,0 +1,47 @@
+import { createContext, useContext, useState, useCallback, useMemo, ReactNode } from 'react';
+
+type LoadingContextType = {
+ isLoading: boolean;
+ showLoading: () => void;
+ hideLoading: () => void;
+};
+
+const LoadingContext = createContext(null);
+
+type LoadingProviderProps = {
+ children: ReactNode;
+};
+
+export function LoadingProvider({ children }: LoadingProviderProps) {
+ const [isLoading, setIsLoading] = useState(false);
+
+ const showLoading = useCallback(() => {
+ setIsLoading(true);
+ }, []);
+
+ const hideLoading = useCallback(() => {
+ setIsLoading(false);
+ }, []);
+
+ const contextValue = useMemo(() => ({
+ isLoading,
+ showLoading,
+ hideLoading,
+ }), [isLoading, showLoading, hideLoading]);
+
+ return (
+
+ {children}
+
+ );
+}
+
+export const useLoading = () => {
+ const context = useContext(LoadingContext);
+
+ if (!context) {
+ throw new Error('useLoading must be used within LoadingProvider');
+ }
+
+ return context;
+};
\ No newline at end of file
diff --git a/src/contexts/unsaved-changes-context.tsx b/src/contexts/unsaved-changes-context.tsx
new file mode 100644
index 000000000..a611dcc5d
--- /dev/null
+++ b/src/contexts/unsaved-changes-context.tsx
@@ -0,0 +1,53 @@
+import type { ReactNode} from 'react';
+
+import { useMemo, useState, useContext, useCallback, createContext } from 'react';
+
+type UnsavedChangesContextType = {
+ hasUnsavedChanges: boolean;
+ setHasUnsavedChanges: (value: boolean) => void;
+ showPrompt: () => Promise;
+};
+
+const UnsavedChangesContext = createContext(null);
+
+type UnsavedChangesProviderProps = {
+ children: ReactNode;
+};
+
+export function UnsavedChangesProvider({ children }: UnsavedChangesProviderProps) {
+ const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
+
+ const showPrompt = useCallback(() => new Promise((resolve) => {
+ if (!hasUnsavedChanges) {
+ resolve(true);
+ return;
+ }
+
+ const userWantsToLeave = window.confirm(
+ 'Kaydedilmemiş değişiklikleriniz var. Çıkmak istediğinizden emin misiniz?'
+ );
+ resolve(userWantsToLeave);
+ }), [hasUnsavedChanges]);
+
+ const value = useMemo(() => ({
+ hasUnsavedChanges,
+ setHasUnsavedChanges,
+ showPrompt,
+ }), [hasUnsavedChanges, showPrompt]);
+
+ return (
+
+ {children}
+
+ );
+}
+
+export const useUnsavedChanges = () => {
+ const context = useContext(UnsavedChangesContext);
+
+ if (!context) {
+ throw new Error('useUnsavedChanges must be used within UnsavedChangesProvider');
+ }
+
+ return context;
+};
\ No newline at end of file
diff --git a/src/contexts/user-context.tsx b/src/contexts/user-context.tsx
new file mode 100644
index 000000000..1beb52329
--- /dev/null
+++ b/src/contexts/user-context.tsx
@@ -0,0 +1,138 @@
+import type { ReactNode } from 'react';
+
+import { useMemo, useState, useEffect, useContext, useCallback, createContext } from 'react';
+
+import { useAuth } from './auth-context';
+import { userService } from '../services/user/user-service';
+
+export interface User {
+ id: string;
+ name: string;
+ firstName: string;
+ lastName: string;
+ email: string;
+ phone: string;
+ avatar?: string;
+ avatarUrl?: string;
+ role: 'admin' | 'user';
+ notifications: {
+ email: boolean;
+ push: boolean;
+ sms: boolean;
+ };
+}
+
+interface UserContextType {
+ user: User | null;
+ isLoading: boolean;
+ error: string | null;
+ updateUser: (data: Partial) => Promise;
+ updatePassword: (currentPassword: string, newPassword: string) => Promise;
+ updateAvatar: (file: File) => Promise;
+ updateNotifications: (notifications: User['notifications']) => Promise;
+ refreshUser: () => Promise;
+}
+
+const UserContext = createContext(undefined);
+
+export function UserProvider({ children }: { children: ReactNode }) {
+ const { user: authUser, isAuthenticated } = useAuth();
+ const [user, setUser] = useState(null);
+ const [isLoading, setIsLoading] = useState(true);
+ const [error, setError] = useState(null);
+
+ const fetchUser = useCallback(async () => {
+ try {
+ setIsLoading(true);
+ setError(null);
+
+ if (authUser?.email) {
+ const userData = await userService.getUserProfileByEmail(authUser.email);
+ setUser(userData);
+ }
+ } catch (err) {
+ setError('Kullanıcı bilgileri alınırken bir hata oluştu');
+ console.error('Kullanıcı bilgileri alınamadı:', err);
+ } finally {
+ setIsLoading(false);
+ }
+ }, [authUser?.email]);
+
+ const updateUser = useCallback(async (data: Partial) => {
+ try {
+ setError(null);
+ await userService.updateUserProfile(data);
+ await fetchUser();
+ } catch (err) {
+ setError('Profil güncellenirken bir hata oluştu');
+ throw err;
+ }
+ }, [fetchUser]);
+
+ const updatePassword = useCallback(async (currentPassword: string, newPassword: string) => {
+ try {
+ await userService.updatePassword(currentPassword, newPassword);
+ } catch (err) {
+ console.error('Failed to update password:', err);
+ throw err;
+ }
+ }, []);
+
+ const updateAvatar = useCallback(async (file: File) => {
+ try {
+ const avatarUrl = await userService.uploadProfilePhoto(file);
+ setUser((prev) => (prev ? { ...prev, avatarUrl } : null));
+ } catch (err) {
+ console.error('Failed to update avatar:', err);
+ throw err;
+ }
+ }, []);
+
+ const updateNotifications = useCallback(async (notifications: User['notifications']) => {
+ try {
+ await userService.updateNotifications(notifications);
+ setUser((prev) => (prev ? { ...prev, notifications } : null));
+ } catch (err) {
+ console.error('Failed to update notifications:', err);
+ throw err;
+ }
+ }, []);
+
+ useEffect(() => {
+ setIsLoading(true);
+ if (isAuthenticated && authUser?.email) {
+ fetchUser().catch((err) => {
+ console.error('Failed to fetch user:', err);
+ setIsLoading(false);
+ });
+ } else {
+ setUser(null);
+ setIsLoading(false);
+ }
+ }, [isAuthenticated, authUser?.email, fetchUser]);
+
+ const contextValue = useMemo(() => ({
+ user,
+ isLoading,
+ error,
+ updateUser,
+ updatePassword,
+ updateAvatar,
+ updateNotifications,
+ refreshUser: fetchUser,
+ }), [user, isLoading, error, updateUser, updatePassword, updateAvatar, updateNotifications, fetchUser]);
+
+ return (
+
+ {children}
+
+ );
+}
+
+export function useUser() {
+ const context = useContext(UserContext);
+ if (context === undefined) {
+ throw new Error('useUser must be used within a UserProvider');
+ }
+ return context;
+}
\ No newline at end of file
diff --git a/src/declarations.d.ts b/src/declarations.d.ts
new file mode 100644
index 000000000..34dfcc409
--- /dev/null
+++ b/src/declarations.d.ts
@@ -0,0 +1,9 @@
+declare module 'i18next-http-backend' {
+ const HttpApi: any;
+ export default HttpApi;
+}
+
+declare module 'i18next-browser-languagedetector' {
+ const LanguageDetector: any;
+ export default LanguageDetector;
+}
\ No newline at end of file
diff --git a/src/hooks/use-boolean.ts b/src/hooks/use-boolean.ts
new file mode 100644
index 000000000..c67e152c2
--- /dev/null
+++ b/src/hooks/use-boolean.ts
@@ -0,0 +1,33 @@
+import React, { useState, useCallback } from 'react';
+
+export interface ReturnType {
+ value: boolean;
+ onTrue: () => void;
+ onFalse: () => void;
+ onToggle: () => void;
+ setValue: React.Dispatch>;
+}
+
+export function useBoolean(defaultValue?: boolean): ReturnType {
+ const [value, setValue] = useState(!!defaultValue);
+
+ const onTrue = useCallback(() => {
+ setValue(true);
+ }, []);
+
+ const onFalse = useCallback(() => {
+ setValue(false);
+ }, []);
+
+ const onToggle = useCallback(() => {
+ setValue((prev) => !prev);
+ }, []);
+
+ return {
+ value,
+ onTrue,
+ onFalse,
+ onToggle,
+ setValue,
+ };
+}
\ No newline at end of file
diff --git a/src/i18n.ts b/src/i18n.ts
new file mode 100644
index 000000000..135585852
--- /dev/null
+++ b/src/i18n.ts
@@ -0,0 +1,27 @@
+import i18n from 'i18next';
+import HttpApi from 'i18next-http-backend';
+import { initReactI18next } from 'react-i18next';
+import LanguageDetector from 'i18next-browser-languagedetector';
+
+i18n
+ .use(HttpApi)
+ .use(LanguageDetector)
+ .use(initReactI18next)
+ .init({
+ fallbackLng: 'tr',
+ ns: ['common', 'auth', 'products', 'error', 'validation', 'company','profile'],
+ defaultNS: 'common',
+ debug: true,
+ interpolation: {
+ escapeValue: false,
+ },
+ backend: {
+ loadPath: '/locales/{{lng}}/{{ns}}.json',
+ },
+ detection: {
+ order: ['localStorage', 'navigator'],
+ caches: ['localStorage'],
+ },
+ });
+
+export default i18n;
\ No newline at end of file
diff --git a/src/layouts/auth/layout.tsx b/src/layouts/auth/layout.tsx
index 49bcda255..8b82e1fe6 100644
--- a/src/layouts/auth/layout.tsx
+++ b/src/layouts/auth/layout.tsx
@@ -1,10 +1,7 @@
import type { Theme, SxProps, Breakpoint } from '@mui/material/styles';
-import Link from '@mui/material/Link';
import Alert from '@mui/material/Alert';
-import { RouterLink } from 'src/routes/components';
-
import { stylesMode } from 'src/theme/styles';
import { Logo } from 'src/components/logo';
@@ -40,7 +37,6 @@ export function AuthLayout({ sx, children, header }: AuthLayoutProps) {
}}
sx={{
position: { [layoutQuery]: 'fixed' },
-
...header?.sx,
}}
slots={{
@@ -50,16 +46,6 @@ export function AuthLayout({ sx, children, header }: AuthLayoutProps) {
),
leftArea: ,
- rightArea: (
-
- Need help?
-
- ),
}}
/>
}
diff --git a/src/layouts/components/account-popover.tsx b/src/layouts/components/account-popover.tsx
index 995efce0a..b0351f0ba 100644
--- a/src/layouts/components/account-popover.tsx
+++ b/src/layouts/components/account-popover.tsx
@@ -1,6 +1,6 @@
import type { IconButtonProps } from '@mui/material/IconButton';
-import { useState, useCallback } from 'react';
+import React, {useState, useContext, useCallback} from 'react';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
@@ -16,6 +16,8 @@ import { useRouter, usePathname } from 'src/routes/hooks';
import { _myAccount } from 'src/_mock';
+import {AuthContext} from "../../contexts/auth-context";
+
// ----------------------------------------------------------------------
export type AccountPopoverProps = IconButtonProps & {
@@ -29,6 +31,7 @@ export type AccountPopoverProps = IconButtonProps & {
export function AccountPopover({ data = [], sx, ...other }: AccountPopoverProps) {
const router = useRouter();
+ const { logout } = useContext(AuthContext);
const pathname = usePathname();
@@ -129,7 +132,7 @@ export function AccountPopover({ data = [], sx, ...other }: AccountPopoverProps)
-
diff --git a/src/layouts/components/index.ts b/src/layouts/components/index.ts
new file mode 100644
index 000000000..cc78b190c
--- /dev/null
+++ b/src/layouts/components/index.ts
@@ -0,0 +1 @@
+export { LanguagePopover } from './language-popover';
\ No newline at end of file
diff --git a/src/layouts/components/language-popover.tsx b/src/layouts/components/language-popover.tsx
index d8e654136..b37df8606 100644
--- a/src/layouts/components/language-popover.tsx
+++ b/src/layouts/components/language-popover.tsx
@@ -1,6 +1,7 @@
import type { IconButtonProps } from '@mui/material/IconButton';
-import { useState, useCallback } from 'react';
+import { useTranslation } from 'react-i18next';
+import React, { useState, useCallback } from 'react';
import Box from '@mui/material/Box';
import Popover from '@mui/material/Popover';
@@ -10,16 +11,24 @@ import MenuItem, { menuItemClasses } from '@mui/material/MenuItem';
// ----------------------------------------------------------------------
-export type LanguagePopoverProps = IconButtonProps & {
- data?: {
- value: string;
- label: string;
- icon: string;
- }[];
-};
+export type LanguagePopoverProps = IconButtonProps;
-export function LanguagePopover({ data = [], sx, ...other }: LanguagePopoverProps) {
- const [locale, setLocale] = useState(data[0].value);
+const LANGUAGES = [
+ {
+ value: 'en',
+ label: 'English',
+ icon: '/assets/icons/flags/ic-flag-en.svg',
+ },
+ {
+ value: 'tr',
+ label: 'Türkçe',
+ icon: '/assets/icons/flags/ic-flag-tr.svg',
+ },
+];
+
+export function LanguagePopover({ sx, ...other }: LanguagePopoverProps) {
+ const { i18n } = useTranslation();
+ const [locale, setLocale] = useState(i18n.language || LANGUAGES[0].value);
const [openPopover, setOpenPopover] = useState(null);
@@ -32,14 +41,15 @@ export function LanguagePopover({ data = [], sx, ...other }: LanguagePopoverProp
}, []);
const handleChangeLang = useCallback(
- (newLang: string) => {
- setLocale(newLang);
- handleClosePopover();
+ async (newLang: string) => {
+ setLocale(newLang);
+ await i18n.changeLanguage(newLang);
+ handleClosePopover();
},
- [handleClosePopover]
+ [handleClosePopover, i18n]
);
- const currentLang = data.find((lang) => lang.value === locale);
+ const currentLang = LANGUAGES.find((lang) => lang.value === locale);
const renderFlag = (label?: string, icon?: string) => (
- {data?.map((option) => (
+ {LANGUAGES.map((option) => (
- );
-}
diff --git a/src/layouts/components/notifications-popover.tsx b/src/layouts/components/notifications-popover.tsx
index 68f0f81a2..f5389fe46 100644
--- a/src/layouts/components/notifications-popover.tsx
+++ b/src/layouts/components/notifications-popover.tsx
@@ -1,6 +1,6 @@
import type { IconButtonProps } from '@mui/material/IconButton';
-import { useState, useCallback } from 'react';
+import React, { useState, useCallback } from 'react';
import Box from '@mui/material/Box';
import List from '@mui/material/List';
diff --git a/src/layouts/components/workspaces-popover.tsx b/src/layouts/components/workspaces-popover.tsx
index 7d86f7ec4..2779fefc3 100644
--- a/src/layouts/components/workspaces-popover.tsx
+++ b/src/layouts/components/workspaces-popover.tsx
@@ -1,6 +1,6 @@
import type { ButtonBaseProps } from '@mui/material/ButtonBase';
-import { useState, useCallback } from 'react';
+import React, { useState, useCallback } from 'react';
import Box from '@mui/material/Box';
import Popover from '@mui/material/Popover';
diff --git a/src/layouts/config-nav-dashboard.tsx b/src/layouts/config-nav-dashboard.tsx
index 2acb80796..71737904a 100644
--- a/src/layouts/config-nav-dashboard.tsx
+++ b/src/layouts/config-nav-dashboard.tsx
@@ -18,6 +18,11 @@ export const navData = [
path: '/user',
icon: icon('ic-user'),
},
+ {
+ title: 'Companies',
+ path: '/company',
+ icon: icon('ic-business'),
+ },
{
title: 'Product',
path: '/products',
diff --git a/src/layouts/core/header-section.tsx b/src/layouts/core/header-section.tsx
index 5b8525bfb..84429c3fe 100644
--- a/src/layouts/core/header-section.tsx
+++ b/src/layouts/core/header-section.tsx
@@ -3,6 +3,8 @@ import type { AppBarProps } from '@mui/material/AppBar';
import type { ToolbarProps } from '@mui/material/Toolbar';
import type { ContainerProps } from '@mui/material/Container';
+import React from "react";
+
import Box from '@mui/material/Box';
import AppBar from '@mui/material/AppBar';
import Toolbar from '@mui/material/Toolbar';
diff --git a/src/layouts/core/layout-section.tsx b/src/layouts/core/layout-section.tsx
index 000daa4ef..c688bd02f 100644
--- a/src/layouts/core/layout-section.tsx
+++ b/src/layouts/core/layout-section.tsx
@@ -1,5 +1,7 @@
import type { Theme, SxProps, CSSObject } from '@mui/material/styles';
+import React from "react";
+
import Box from '@mui/material/Box';
import { useTheme } from '@mui/material/styles';
import GlobalStyles from '@mui/material/GlobalStyles';
diff --git a/src/layouts/dashboard/dashboard-content.tsx b/src/layouts/dashboard/dashboard-content.tsx
new file mode 100644
index 000000000..fcef7d645
--- /dev/null
+++ b/src/layouts/dashboard/dashboard-content.tsx
@@ -0,0 +1,30 @@
+import Box from '@mui/material/Box';
+import { Theme } from '@mui/material/styles';
+
+interface DashboardContentProps {
+ children: React.ReactNode;
+ maxWidth?: string | number | false;
+}
+
+export function DashboardContent({ children, maxWidth }: DashboardContentProps) {
+ return (
+
+ {children}
+
+ );
+}
\ No newline at end of file
diff --git a/src/layouts/dashboard/layout.tsx b/src/layouts/dashboard/layout.tsx
index 281305821..97fc5ef3f 100644
--- a/src/layouts/dashboard/layout.tsx
+++ b/src/layouts/dashboard/layout.tsx
@@ -1,18 +1,19 @@
import type { Theme, SxProps, Breakpoint } from '@mui/material/styles';
-import { useState } from 'react';
+import React, { useState } from 'react';
import Box from '@mui/material/Box';
import Alert from '@mui/material/Alert';
import { useTheme } from '@mui/material/styles';
-import { _langs, _notifications } from 'src/_mock';
+import { _notifications } from 'src/_mock';
import { Iconify } from 'src/components/iconify';
import { Main } from './main';
import { layoutClasses } from '../classes';
import { NavMobile, NavDesktop } from './nav';
+import { LanguagePopover } from '../components';
import { navData } from '../config-nav-dashboard';
import { Searchbar } from '../components/searchbar';
import { _workspaces } from '../config-nav-workspace';
@@ -20,7 +21,6 @@ import { MenuButton } from '../components/menu-button';
import { LayoutSection } from '../core/layout-section';
import { HeaderSection } from '../core/header-section';
import { AccountPopover } from '../components/account-popover';
-import { LanguagePopover } from '../components/language-popover';
import { NotificationsPopover } from '../components/notifications-popover';
// ----------------------------------------------------------------------
@@ -81,7 +81,7 @@ export function DashboardLayout({ sx, children, header }: DashboardLayoutProps)
rightArea: (
-
+
,
},
{
diff --git a/src/layouts/dashboard/nav.tsx b/src/layouts/dashboard/nav.tsx
index 3b19cb940..acd16f70b 100644
--- a/src/layouts/dashboard/nav.tsx
+++ b/src/layouts/dashboard/nav.tsx
@@ -16,7 +16,6 @@ import { varAlpha } from 'src/theme/styles';
import { Logo } from 'src/components/logo';
import { Scrollbar } from 'src/components/scrollbar';
-import { NavUpgrade } from '../components/nav-upgrade';
import { WorkspacesPopover } from '../components/workspaces-popover';
import type { WorkspacesPopoverProps } from '../components/workspaces-popover';
@@ -38,9 +37,37 @@ export type NavContentProps = {
sx?: SxProps;
};
+const defaultNavItems = [
+ {
+ path: '/',
+ title: 'Ana Sayfa',
+ icon: ,
+ },
+ {
+ path: '/company',
+ title: 'İş Ortakları',
+ icon: ,
+ },
+ {
+ path: '/user',
+ title: 'Kullanıcılar',
+ icon: ,
+ },
+ {
+ path: '/products',
+ title: 'Ürünler',
+ icon: ,
+ },
+ {
+ path: '/blog',
+ title: 'Blog',
+ icon: ,
+ },
+];
+
export function NavDesktop({
sx,
- data,
+ data = defaultNavItems,
slots,
workspaces,
layoutQuery,
@@ -175,8 +202,6 @@ export function NavContent({ data, slots, workspaces, sx }: NavContentProps) {
{slots?.bottomArea}
-
-
>
);
}
diff --git a/src/main.tsx b/src/main.tsx
index 890a4c1b3..76a6dc751 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -1,22 +1,16 @@
+import { StrictMode } from 'react';
import ReactDOM from 'react-dom/client';
-import { Suspense, StrictMode } from 'react';
-import { BrowserRouter } from 'react-router-dom';
-import { HelmetProvider } from 'react-helmet-async';
+import './i18n';
import App from './app';
-
-// ----------------------------------------------------------------------
+import {Providers} from "./contexts/Providers";
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(
-
-
-
-
-
-
-
-
-
-);
+
+
+
+
+
+);
\ No newline at end of file
diff --git a/src/pages/company/company-detail/company-detail.tsx b/src/pages/company/company-detail/company-detail.tsx
new file mode 100644
index 000000000..0e0262244
--- /dev/null
+++ b/src/pages/company/company-detail/company-detail.tsx
@@ -0,0 +1,19 @@
+import { Helmet } from 'react-helmet-async';
+
+import {CONFIG} from "../../../config-global";
+import {
+ CompanyDetail
+} from "../../../sections/company/company-detail.";
+
+
+export default function CompanyDetailPage() {
+ return (
+ <>
+
+ {`Şirket Detayı - ${CONFIG.appName}`}
+
+
+
+ >
+ );
+}
\ No newline at end of file
diff --git a/src/pages/company/company-list/company-list.tsx b/src/pages/company/company-list/company-list.tsx
new file mode 100644
index 000000000..a473c8679
--- /dev/null
+++ b/src/pages/company/company-list/company-list.tsx
@@ -0,0 +1,17 @@
+import { Helmet } from 'react-helmet-async';
+
+import { CONFIG } from 'src/config-global';
+
+import { CompanyList } from 'src/sections/company/company-list';
+
+export default function CompanyListPage() {
+ return (
+ <>
+
+ {`Şirketler - ${CONFIG.appName}`}
+
+
+
+ >
+ );
+}
\ No newline at end of file
diff --git a/src/pages/page-not-found.tsx b/src/pages/page-not-found.tsx
index afffe01ae..1b434211c 100644
--- a/src/pages/page-not-found.tsx
+++ b/src/pages/page-not-found.tsx
@@ -1,4 +1,5 @@
import { Helmet } from 'react-helmet-async';
+import { useTranslation } from 'react-i18next';
import { CONFIG } from 'src/config-global';
@@ -7,10 +8,12 @@ import { NotFoundView } from 'src/sections/error';
// ----------------------------------------------------------------------
export default function Page() {
+ const { t } = useTranslation('error');
+
return (
<>
- {`404 page not found! | Error - ${CONFIG.appName}`}
+ {t('notFound.helmet', { appName: CONFIG.appName })}
diff --git a/src/pages/products.tsx b/src/pages/products.tsx
index f5eb29049..1026d1cda 100644
--- a/src/pages/products.tsx
+++ b/src/pages/products.tsx
@@ -1,16 +1,17 @@
import { Helmet } from 'react-helmet-async';
-
-import { CONFIG } from 'src/config-global';
+import { useTranslation } from 'react-i18next';
import { ProductsView } from 'src/sections/product/view';
// ----------------------------------------------------------------------
-export default function Page() {
+export default function ProductsPage() {
+ const { t } = useTranslation('products');
+
return (
<>
- {`Products - ${CONFIG.appName}`}
+ {t('list.helmet')}
diff --git a/src/pages/profile.tsx b/src/pages/profile.tsx
new file mode 100644
index 000000000..6fe1a553e
--- /dev/null
+++ b/src/pages/profile.tsx
@@ -0,0 +1,15 @@
+import { Helmet } from 'react-helmet-async';
+
+import { ProfileView } from 'src/sections/profile/view';
+
+export default function ProfilePage() {
+ return (
+ <>
+
+ Profil | Lojistik Yönetim Sistemi
+
+
+
+ >
+ );
+}
\ No newline at end of file
diff --git a/src/pages/sign-in.tsx b/src/pages/sign-in.tsx
index 20f76057f..04ae52fd7 100644
--- a/src/pages/sign-in.tsx
+++ b/src/pages/sign-in.tsx
@@ -1,16 +1,17 @@
import { Helmet } from 'react-helmet-async';
-
-import { CONFIG } from 'src/config-global';
+import { useTranslation } from 'react-i18next';
import { SignInView } from 'src/sections/auth';
// ----------------------------------------------------------------------
-export default function Page() {
+export default function SignInPage() {
+ const { t } = useTranslation('auth');
+
return (
<>
- {`Sign in - ${CONFIG.appName}`}
+ {t('signIn.helmet')}
diff --git a/src/routes/components/router-guard.tsx b/src/routes/components/router-guard.tsx
new file mode 100644
index 000000000..f14dd4f18
--- /dev/null
+++ b/src/routes/components/router-guard.tsx
@@ -0,0 +1,54 @@
+import type { ReactNode } from 'react';
+
+import { useRef, useEffect } from 'react';
+import { useNavigate, useLocation } from 'react-router-dom';
+
+import { useUnsavedChanges } from 'src/contexts/unsaved-changes-context';
+
+type RouterGuardProps = {
+ children: ReactNode;
+};
+
+export function RouterGuard({ children }: RouterGuardProps) {
+ const navigate = useNavigate();
+ const location = useLocation();
+ const { hasUnsavedChanges, showPrompt, setHasUnsavedChanges } = useUnsavedChanges();
+ const lastLocation = useRef(location);
+
+ // Sayfa yenileme ve kapatma kontrolü
+ useEffect(() => {
+ const handleBeforeUnload = (e: BeforeUnloadEvent) => {
+ if (hasUnsavedChanges) {
+ e.preventDefault();
+ e.returnValue = '';
+ }
+ };
+
+ window.addEventListener('beforeunload', handleBeforeUnload);
+ return () => window.removeEventListener('beforeunload', handleBeforeUnload);
+ }, [hasUnsavedChanges]);
+
+ // Route değişikliklerini izle
+ useEffect(() => {
+ if (!hasUnsavedChanges) {
+ lastLocation.current = location;
+ return;
+ }
+
+ if (location !== lastLocation.current) {
+ const handleRouteChange = async () => {
+ const canNavigate = await showPrompt();
+ if (!canNavigate) {
+ navigate(lastLocation.current.pathname, { replace: true });
+ } else {
+ lastLocation.current = location;
+ setHasUnsavedChanges(false);
+ }
+ };
+
+ handleRouteChange();
+ }
+ }, [location, hasUnsavedChanges, navigate, showPrompt, setHasUnsavedChanges]);
+
+ return children;
+}
\ No newline at end of file
diff --git a/src/routes/hooks/index.ts b/src/routes/hooks/index.ts
index 03b735171..73350e966 100644
--- a/src/routes/hooks/index.ts
+++ b/src/routes/hooks/index.ts
@@ -1,3 +1,3 @@
-export { useRouter } from './use-router';
+export * from './use-router';
export { usePathname } from './use-pathname';
diff --git a/src/routes/hooks/use-router.ts b/src/routes/hooks/use-router.ts
index 2925a778a..f6772aea5 100644
--- a/src/routes/hooks/use-router.ts
+++ b/src/routes/hooks/use-router.ts
@@ -1,21 +1,11 @@
-import { useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
-// ----------------------------------------------------------------------
-
export function useRouter() {
const navigate = useNavigate();
- const router = useMemo(
- () => ({
- back: () => navigate(-1),
- forward: () => navigate(1),
- refresh: () => navigate(0),
- push: (href: string) => navigate(href),
- replace: (href: string) => navigate(href, { replace: true }),
- }),
- [navigate]
- );
-
- return router;
+ return {
+ push: (path: string) => navigate(path),
+ replace: (path: string) => navigate(path, { replace: true }),
+ back: () => navigate(-1),
+ };
}
diff --git a/src/routes/paths.ts b/src/routes/paths.ts
new file mode 100644
index 000000000..697a894d3
--- /dev/null
+++ b/src/routes/paths.ts
@@ -0,0 +1,33 @@
+// ----------------------------------------------------------------------
+
+function path(root: string, sublink: string): string {
+ return `${root}${sublink}`;
+}
+
+const ROOTS = {
+ AUTH: '/auth',
+ DASHBOARD: '/dashboard',
+};
+
+export const paths = {
+ auth: {
+ login: path(ROOTS.AUTH, '/login'),
+ register: path(ROOTS.AUTH, '/register'),
+ forgotPassword: path(ROOTS.AUTH, '/forgot-password'),
+ verify: path(ROOTS.AUTH, '/verify'),
+ },
+ dashboard: {
+ root: ROOTS.DASHBOARD,
+ overview: path(ROOTS.DASHBOARD, '/overview'),
+ user: path(ROOTS.DASHBOARD, '/user'),
+ products: path(ROOTS.DASHBOARD, '/products'),
+ blog: path(ROOTS.DASHBOARD, '/blog'),
+ partners: {
+ root: path(ROOTS.DASHBOARD, '/company'),
+ list: path(ROOTS.DASHBOARD, '/company'),
+ new: path(ROOTS.DASHBOARD, '/company/new'),
+ edit: (id: string) => path(ROOTS.DASHBOARD, `/company/${id}/edit`),
+ view: (id: string) => path(ROOTS.DASHBOARD, `/company/${id}`),
+ },
+ },
+} as const;
\ No newline at end of file
diff --git a/src/routes/private-route.tsx b/src/routes/private-route.tsx
new file mode 100644
index 000000000..f7514bc1e
--- /dev/null
+++ b/src/routes/private-route.tsx
@@ -0,0 +1,45 @@
+import React, { useContext } from 'react';
+import { Navigate } from 'react-router-dom';
+
+import Box from '@mui/material/Box';
+import LinearProgress, { linearProgressClasses } from '@mui/material/LinearProgress';
+
+import { AuthContext } from 'src/contexts/auth-context';
+
+import { varAlpha } from '../theme/styles';
+
+const PrivateRoute = ({ children }: { children: React.ReactNode }) => {
+ const { isAuthenticated, isLoading } = useContext(AuthContext);
+
+ if (isLoading) {
+ return (
+
+ varAlpha(theme.vars.palette.text.primaryChannel, 0.16),
+ [`& .${linearProgressClasses.bar}`]: { bgcolor: 'text.primary' },
+ }}
+ />
+
+ );
+ }
+
+
+ return <>{children}>;
+};
+
+export default PrivateRoute;
diff --git a/src/routes/sections.tsx b/src/routes/sections.tsx
index 34a673b10..d6162b275 100644
--- a/src/routes/sections.tsx
+++ b/src/routes/sections.tsx
@@ -1,4 +1,4 @@
-import { lazy, Suspense } from 'react';
+import React, {lazy, Suspense} from 'react';
import { Outlet, Navigate, useRoutes } from 'react-router-dom';
import Box from '@mui/material/Box';
@@ -8,16 +8,18 @@ import { varAlpha } from 'src/theme/styles';
import { AuthLayout } from 'src/layouts/auth';
import { DashboardLayout } from 'src/layouts/dashboard';
-// ----------------------------------------------------------------------
+import PrivateRoute from './private-route';
-export const HomePage = lazy(() => import('src/pages/home'));
-export const BlogPage = lazy(() => import('src/pages/blog'));
-export const UserPage = lazy(() => import('src/pages/user'));
-export const SignInPage = lazy(() => import('src/pages/sign-in'));
-export const ProductsPage = lazy(() => import('src/pages/products'));
-export const Page404 = lazy(() => import('src/pages/page-not-found'));
-
-// ----------------------------------------------------------------------
+// Lazy load pages
+const HomePage = lazy(() => import('src/pages/home'));
+const BlogPage = lazy(() => import('src/pages/blog'));
+const UserPage = lazy(() => import('src/pages/user'));
+const SignInPage = lazy(() => import('src/pages/sign-in'));
+const ProductsPage = lazy(() => import('src/pages/products'));
+const Page404 = lazy(() => import('src/pages/page-not-found'));
+const ProfilePage = lazy(() => import('src/pages/profile'));
+const CompanyListPage = lazy(() => import('src/pages/company/company-list/company-list'));
+const CompanyDetailPage = lazy(() => import('src/pages/company/company-detail/company-detail'));
const renderFallback = (
@@ -36,17 +38,22 @@ export function Router() {
return useRoutes([
{
element: (
-
-
-
-
-
+
+
+
+
+
+
+
),
children: [
{ element: , index: true },
{ path: 'user', element: },
{ path: 'products', element: },
{ path: 'blog', element: },
+ { path: 'profile', element: },
+ { path: 'company', element: },
+ { path: 'company/:id', element: },
],
},
{
diff --git a/src/sections/auth/forget-password.tsx b/src/sections/auth/forget-password.tsx
new file mode 100644
index 000000000..289e934f6
--- /dev/null
+++ b/src/sections/auth/forget-password.tsx
@@ -0,0 +1,130 @@
+import * as React from 'react';
+import { useState, useCallback } from 'react';
+import { useTranslation } from 'react-i18next';
+
+import Alert from '@mui/material/Alert';
+import Button from '@mui/material/Button';
+import Dialog from '@mui/material/Dialog';
+import Snackbar from '@mui/material/Snackbar';
+import TextField from '@mui/material/TextField';
+import DialogTitle from '@mui/material/DialogTitle';
+import DialogActions from '@mui/material/DialogActions';
+import DialogContent from '@mui/material/DialogContent';
+import DialogContentText from '@mui/material/DialogContentText';
+
+interface ForgotPasswordProps {
+ open: boolean;
+ handleClose: () => void;
+}
+
+export default function ForgotPassword({ open, handleClose }: ForgotPasswordProps) {
+ const { t } = useTranslation(['auth', 'common']);
+ const [emailError, setEmailError] = useState(false);
+ const [emailErrorMessage, setEmailErrorMessage] = useState('');
+ const [loading, setLoading] = useState(false);
+ const [successMessage, setSuccessMessage] = useState(false);
+
+ const validateEmail = useCallback(() => {
+ const email = document.getElementById('forgetPasswordEmail') as HTMLInputElement;
+
+ let isValid = true;
+
+ if (!email.value || !/\S+@\S+\.\S+/.test(email.value)) {
+ setEmailError(true);
+ setEmailErrorMessage(t('resetPassword.emailErrorMessage'));
+ isValid = false;
+ } else {
+ setEmailError(false);
+ setEmailErrorMessage('');
+ }
+
+ return isValid;
+ }, [t]);
+
+ const handleSubmit = useCallback(async (event: React.FormEvent) => {
+ event.preventDefault();
+ if (!validateEmail()) {
+ return;
+ }
+ const email = (document.getElementById('forgetPasswordEmail') as HTMLInputElement).value;
+ setLoading(true);
+
+ try {
+ // Simulated API call
+ await new Promise((resolve) => setTimeout(resolve, 2000));
+ setSuccessMessage(true); // Show success message
+ handleClose();
+ } catch (error) {
+ console.error('Password reset failed:', error);
+ } finally {
+ setLoading(false);
+ }
+ }, [handleClose, validateEmail]);
+
+ const handleSuccessClose = () => {
+ setSuccessMessage(false);
+ };
+
+ const handleDialogClose = () => {
+ setEmailError(false);
+ setEmailErrorMessage('');
+ handleClose();
+ };
+
+ return (
+ <>
+
+
+
+ {t('resetPassword.successMessage')}
+
+
+ >
+ );
+}
\ No newline at end of file
diff --git a/src/sections/auth/index.ts b/src/sections/auth/index.ts
index d9ccca24c..9f2179e10 100644
--- a/src/sections/auth/index.ts
+++ b/src/sections/auth/index.ts
@@ -1 +1 @@
-export * from './sign-in-view';
+export { SignInView } from './sign-in-view';
diff --git a/src/sections/auth/sign-in-view.tsx b/src/sections/auth/sign-in-view.tsx
index 52f619215..17dc5c437 100644
--- a/src/sections/auth/sign-in-view.tsx
+++ b/src/sections/auth/sign-in-view.tsx
@@ -1,8 +1,8 @@
-import { useState, useCallback } from 'react';
+import { useTranslation } from 'react-i18next';
+import React, { useState, useContext, useCallback } from 'react';
import Box from '@mui/material/Box';
import Link from '@mui/material/Link';
-import Divider from '@mui/material/Divider';
import TextField from '@mui/material/TextField';
import IconButton from '@mui/material/IconButton';
import Typography from '@mui/material/Typography';
@@ -11,39 +11,125 @@ import InputAdornment from '@mui/material/InputAdornment';
import { useRouter } from 'src/routes/hooks';
+import { LanguagePopover } from 'src/layouts/components/language-popover';
+
import { Iconify } from 'src/components/iconify';
+import ForgotPassword from './forget-password';
+import { AuthContext } from '../../contexts/auth-context';
+import { authService } from '../../services/auth/auth-service';
+
// ----------------------------------------------------------------------
export function SignInView() {
const router = useRouter();
-
+ const { t } = useTranslation(['auth', 'common']);
const [showPassword, setShowPassword] = useState(false);
+ const { login } = useContext(AuthContext);
+ const [emailError, setEmailError] = useState(false);
+ const [emailErrorMessage, setEmailErrorMessage] = useState('');
+ const [passwordError, setPasswordError] = useState(false);
+ const [passwordErrorMessage, setPasswordErrorMessage] = useState('');
+ const [loading, setLoading] = useState(false);
+ const [loginError, setLoginError] = useState(null);
+ const [forgotPasswordOpen, setForgotPasswordOpen] = useState(false);
+
+ const validateInputs = useCallback(() => {
+ const email = document.getElementById('email') as HTMLInputElement;
+ const password = document.getElementById('password') as HTMLInputElement;
+
+ let isValid = true;
+
+ if (!email.value || !/\S+@\S+\.\S+/.test(email.value)) {
+ setEmailError(true);
+ setEmailErrorMessage(t('auth:signIn.errors.invalidEmail'));
+ isValid = false;
+ } else {
+ setEmailError(false);
+ setEmailErrorMessage('');
+ }
+
+ if (!password.value || password.value.length < 6) {
+ setPasswordError(true);
+ setPasswordErrorMessage(t('auth:signIn.errors.passwordLength'));
+ isValid = false;
+ } else {
+ setPasswordError(false);
+ setPasswordErrorMessage('');
+ }
+
+ return isValid;
+ }, [t]);
+
+ const handleSubmit = useCallback(async () => {
+ if (!validateInputs()) {
+ return;
+ }
+
+ const email = (document.getElementById('email') as HTMLInputElement).value;
+ const password = (document.getElementById('password') as HTMLInputElement).value;
+
+ setLoading(true);
+ setLoginError(null);
+
+ try {
+ const response = await authService.login({ email, password });
+ login(response.token);
+ router.push('/');
+ } catch (error: any) {
+ console.error('Login failed:', error);
+ setLoginError(error?.message || 'Login failed. Please try again.');
+ } finally {
+ setLoading(false);
+ }
+ }, [login, router, validateInputs]);
+
+ const handleForgotPasswordClick = () => {
+ setForgotPasswordOpen(true);
+ };
- const handleSignIn = useCallback(() => {
- router.push('/');
- }, [router]);
+ const handleForgotPasswordClose = () => {
+ setForgotPasswordOpen(false);
+ };
+ // @ts-ignore
const renderForm = (
-
- Forgot password?
+
+ {t('auth:signIn.forgotPassword')}
),
}}
- sx={{ mb: 3 }}
+ sx={{ mb: 1.5 }}
/>
-
+ {loginError && (
+
+ {loginError}
+
+ )}
- Sign in
+ {loading ? t('auth:signIn.buttons.signingIn') : t('auth:signIn.buttons.signIn')}
);
return (
<>
+
+
+
+
- Sign in
+ {t('auth:signIn.title')}
- Don’t have an account?
+ {t('common:welcome')}
- Get started
+ {t('common:getStarted')}
{renderForm}
-
-
- OR
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
>
);
}
diff --git a/src/sections/company/company-contacts.tsx b/src/sections/company/company-contacts.tsx
new file mode 100644
index 000000000..29b7d6283
--- /dev/null
+++ b/src/sections/company/company-contacts.tsx
@@ -0,0 +1,337 @@
+import * as Yup from 'yup';
+import { useState } from 'react';
+import { useFormik } from 'formik';
+import { useTranslation } from 'react-i18next';
+
+import {
+ Box,
+ Card,
+ Grid,
+ Table,
+ Alert,
+ Stack,
+ Button,
+ Dialog,
+ Divider,
+ TableRow,
+ Snackbar,
+ TableBody,
+ TableCell,
+ TableHead,
+ TextField,
+ IconButton,
+ Typography,
+ DialogTitle,
+ DialogContent,
+ DialogActions,
+ TableContainer,
+} from '@mui/material';
+
+import { Label } from 'src/components/label';
+import { Iconify } from 'src/components/iconify';
+import { Scrollbar } from 'src/components/scrollbar';
+
+interface Contact {
+ id: number;
+ name: string;
+ position: string;
+ department: string;
+ phone: string;
+ email: string;
+}
+
+interface CompanyContactsProps {
+ companyId?: string;
+}
+
+const validationSchema = Yup.object({
+ name: Yup.string().required('Ad Soyad zorunludur'),
+ position: Yup.string().required('Pozisyon zorunludur'),
+ department: Yup.string().required('Departman zorunludur'),
+ phone: Yup.string().required('Telefon zorunludur'),
+ email: Yup.string().email('Geçerli bir e-posta adresi giriniz').required('E-posta zorunludur'),
+});
+
+export function CompanyContacts({ companyId }: CompanyContactsProps) {
+ const { t } = useTranslation();
+ const [contacts, setContacts] = useState([
+ {
+ id: 1,
+ name: 'Ahmet Yılmaz',
+ position: 'Operasyon Müdürü',
+ department: 'Operasyon',
+ phone: '0532 555 44 33',
+ email: 'ahmet.yilmaz@abclojistik.com',
+ },
+ ]);
+ const [openDialog, setOpenDialog] = useState(false);
+ const [editingId, setEditingId] = useState(null);
+ const [snackbar, setSnackbar] = useState<{
+ open: boolean;
+ message: string;
+ severity: 'success' | 'error';
+ }>({ open: false, message: '', severity: 'success' });
+
+ const formik = useFormik({
+ initialValues: {
+ name: '',
+ position: '',
+ department: '',
+ phone: '',
+ email: '',
+ },
+ validationSchema,
+ onSubmit: async (values: any, { resetForm }: { resetForm: () => void }) => {
+ try {
+ if (editingId) {
+ setContacts(contacts.map(contact =>
+ contact.id === editingId
+ ? { ...contact, ...values }
+ : contact
+ ));
+ setSnackbar({
+ open: true,
+ message: t('Kişi başarıyla güncellendi'),
+ severity: 'success',
+ });
+ } else {
+ setContacts([...contacts, { id: contacts.length + 1, ...values }]);
+ setSnackbar({
+ open: true,
+ message: t('Kişi başarıyla eklendi'),
+ severity: 'success',
+ });
+ }
+ handleCloseDialog();
+ resetForm();
+ } catch (error) {
+ setSnackbar({
+ open: true,
+ message: t('Bir hata oluştu'),
+ severity: 'error',
+ });
+ }
+ },
+ });
+
+ const handleOpenDialog = (contact?: Contact) => {
+ if (contact) {
+ setEditingId(contact.id);
+ formik.setValues({
+ name: contact.name,
+ position: contact.position,
+ department: contact.department,
+ phone: contact.phone,
+ email: contact.email,
+ });
+ } else {
+ setEditingId(null);
+ formik.resetForm();
+ }
+ setOpenDialog(true);
+ };
+
+ const handleCloseDialog = () => {
+ setOpenDialog(false);
+ setEditingId(null);
+ formik.resetForm();
+ };
+
+ const handleDelete = (id: number) => {
+ setContacts(contacts.filter(contact => contact.id !== id));
+ setSnackbar({
+ open: true,
+ message: t('Kişi başarıyla silindi'),
+ severity: 'success',
+ });
+ };
+
+ const handleCloseSnackbar = () => {
+ setSnackbar({ ...snackbar, open: false });
+ };
+
+ return (
+ <>
+
+
+
+ {t('İletişim Kişileri')}
+
+ }
+ onClick={() => handleOpenDialog()}
+ >
+ {t('Yeni Kişi')}
+
+
+
+
+
+
+
+
+
+
+ {t('Ad Soyad')}
+ {t('Departman')}
+ {t('İletişim')}
+ {t('İşlemler')}
+
+
+
+ {contacts.map((contact) => (
+
+
+
+
+
+
+
+ {contact.name}
+
+
+
+
+ {contact.department}
+
+
+ {contact.phone}
+
+
+ {contact.email}
+
+
+
+ handleOpenDialog(contact)}>
+
+
+ handleDelete(contact.id)}>
+
+
+
+
+ ))}
+
+
+
+
+
+
+
+
+
+
+ {snackbar.message}
+
+
+ >
+ );
+}
\ No newline at end of file
diff --git a/src/sections/company/company-detail..tsx b/src/sections/company/company-detail..tsx
new file mode 100644
index 000000000..a6fcbeb4b
--- /dev/null
+++ b/src/sections/company/company-detail..tsx
@@ -0,0 +1,114 @@
+import React, { useState } from 'react';
+import { useParams } from 'react-router-dom';
+import { useTranslation } from 'react-i18next';
+
+import { Box, Tab, Card, Tabs, Stack, Button, Typography } from '@mui/material';
+
+import { DashboardContent } from 'src/layouts/dashboard';
+
+import { CompanyInfo } from './company-info';
+import { Iconify } from '../../components/iconify';
+import { useBoolean } from '../../hooks/use-boolean';
+import { CompanyContacts } from './company-contacts';
+import { Scrollbar } from '../../components/scrollbar';
+import { BackButton } from '../../components/back-button';
+
+const TABS = [
+ {
+ value: 'general',
+ label: 'company.tabs.general',
+ icon: ,
+ },
+ {
+ value: 'contacts',
+ label: 'company.tabs.contacts',
+ icon: ,
+ },
+ {
+ value: 'contracts',
+ label: 'company.tabs.contracts',
+ icon: ,
+ },
+ {
+ value: 'performance',
+ label: 'company.tabs.performance',
+ icon: ,
+ },
+ {
+ value: 'pricing',
+ label: 'company.tabs.pricing',
+ icon: ,
+ },
+ {
+ value: 'analytics',
+ label: 'company.tabs.analytics',
+ icon: ,
+ },
+];
+
+export function CompanyDetail() {
+ const { t } = useTranslation('company');
+ const { id } = useParams();
+ const confirm = useBoolean();
+
+ const [currentTab, setCurrentTab] = useState('general');
+
+ const handleChangeTab = (_event: React.SyntheticEvent, newValue: string) => {
+ setCurrentTab(newValue);
+ };
+
+ const handleDelete = () => {
+ confirm.onTrue();
+ };
+
+ return (
+
+
+ {t('company.companyDetails')}
+
+
+
+
+
+
+
+ `inset 0 -2px 0 0 ${theme.palette.divider}`,
+ }}
+ >
+ {TABS.map((tab) => (
+
+ ))}
+
+
+
+
+ {currentTab === 'general' && }
+ {currentTab === 'contacts' && }
+ {currentTab === 'contracts' && Contracts}
+ {currentTab === 'performance' && Performance}
+ {currentTab === 'pricing' && Pricing}
+ {currentTab === 'analytics' && Analytics}
+
+
+
+
+ );
+}
diff --git a/src/sections/company/company-info.tsx b/src/sections/company/company-info.tsx
new file mode 100644
index 000000000..73d86e94f
--- /dev/null
+++ b/src/sections/company/company-info.tsx
@@ -0,0 +1,329 @@
+import * as Yup from 'yup';
+import { useFormik } from 'formik';
+import React, { useState } from 'react';
+import { useTranslation } from 'react-i18next';
+
+import {
+ Box,
+ Grid,
+ Card,
+ Stack,
+ Alert,
+ Button,
+ Divider,
+ Snackbar,
+ TextField,
+ Typography,
+} from '@mui/material';
+
+import { Iconify } from 'src/components/iconify';
+
+interface CompanyData {
+ id: string;
+ name: string;
+ address: string;
+ phone: string;
+ email: string;
+ taxNumber: string;
+ website: string;
+ description: string;
+}
+
+interface InfoFieldProps {
+ icon: string;
+ label: string;
+ name: keyof CompanyData;
+ value: string;
+ error?: string;
+ touched?: boolean;
+ isEditing: boolean;
+ multiline?: boolean;
+ onChange: (e: React.ChangeEvent) => void;
+ onBlur: (e: React.FocusEvent) => void;
+}
+
+const InfoField: React.FC = ({
+ icon,
+ label,
+ name,
+ value,
+ error,
+ touched,
+ isEditing,
+ multiline = false,
+ onChange,
+ onBlur,
+}) => {
+ const { t } = useTranslation();
+
+ return (
+
+ {isEditing ? (
+
+
+ {label}
+
+
+
+ ) : (
+
+
+
+
+
+
+ {label}
+
+
+ {value || '-'}
+
+
+
+ )}
+
+ );
+};
+
+const validationSchema = Yup.object({
+ name: Yup.string().required('Şirket adı zorunludur'),
+ taxNumber: Yup.string().required('Vergi numarası zorunludur'),
+ phone: Yup.string().required('Telefon zorunludur'),
+ email: Yup.string().email('Geçerli bir e-posta adresi giriniz').required('E-posta zorunludur'),
+ website: Yup.string().url('Geçerli bir website adresi giriniz'),
+ address: Yup.string().required('Adres zorunludur'),
+ description: Yup.string(),
+});
+
+export function CompanyInfo({ id }: { id?: string }) {
+ const { t } = useTranslation();
+ const [isEditing, setIsEditing] = useState(false);
+ const [snackbar, setSnackbar] = useState<{
+ open: boolean;
+ message: string;
+ severity: 'success' | 'error';
+ }>({ open: false, message: '', severity: 'success' });
+
+ const formik = useFormik({
+ initialValues: {
+ id: id || '',
+ name: 'ABC Lojistik Ltd. Şti.',
+ address: 'Ankara Cad. No:123 İstanbul',
+ phone: '0212 555 44 33',
+ email: 'info@abclojistik.com',
+ taxNumber: '1234567890',
+ website: 'www.abclojistik.com',
+ description: 'Uluslararası lojistik hizmetleri',
+ },
+ validationSchema,
+ onSubmit: async (values) => {
+ try {
+ // TODO: API call to save data
+ console.log('Saving...', values);
+ setSnackbar({
+ open: true,
+ message: t('Şirket bilgileri başarıyla güncellendi'),
+ severity: 'success',
+ });
+ setIsEditing(false);
+ } catch (error) {
+ setSnackbar({
+ open: true,
+ message: t('Bir hata oluştu'),
+ severity: 'error',
+ });
+ }
+ },
+ });
+
+ const handleEdit = () => {
+ setIsEditing(true);
+ };
+
+ const handleCancel = () => {
+ formik.resetForm();
+ setIsEditing(false);
+ };
+
+ const handleCloseSnackbar = () => {
+ setSnackbar({ ...snackbar, open: false });
+ };
+
+ return (
+
+
+
+ {t('Şirket Bilgileri')}
+
+ {!isEditing ? (
+ }
+ onClick={handleEdit}
+ size="small"
+ >
+ {t('Düzenle')}
+
+ ) : (
+
+ }
+ onClick={() => formik.handleSubmit()}
+ size="small"
+ >
+ {t('Kaydet')}
+
+ }
+ onClick={handleCancel}
+ size="small"
+ >
+ {t('İptal')}
+
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {snackbar.message}
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/sections/company/company-list.tsx b/src/sections/company/company-list.tsx
new file mode 100644
index 000000000..64991d04a
--- /dev/null
+++ b/src/sections/company/company-list.tsx
@@ -0,0 +1,519 @@
+import * as Yup from 'yup';
+import { useFormik } from 'formik';
+import { useTranslation } from 'react-i18next';
+import React, { useState, useCallback } from 'react';
+
+import {
+ Box,
+ Card,
+ Grid,
+ Table,
+ Stack,
+ Button,
+ Dialog,
+ Divider,
+ MenuItem,
+ TableBody,
+ TextField,
+ Typography,
+ DialogTitle,
+ DialogContent,
+ DialogActions,
+ TableContainer,
+ InputAdornment,
+ TablePagination,
+} from '@mui/material';
+
+import { DashboardContent } from 'src/layouts/dashboard';
+
+import { Iconify } from 'src/components/iconify';
+import { Scrollbar } from 'src/components/scrollbar';
+
+import { CompanyTableRow } from './company-table-row';
+import { CompanyTableHead } from './company-table-head';
+import { CompanyTableToolbar } from './company-table-toolbar';
+
+const COMPANY_LIST = [
+ {
+ id: '1',
+ name: 'ABC Lojistik Ltd. Şti.',
+ phone: '0212 555 44 33',
+ email: 'info@abclojistik.com',
+ status: 'active' as const,
+ verified: true,
+ },
+ {
+ id: '2',
+ name: 'XYZ Taşımacılık A.Ş.',
+ phone: '0312 666 55 44',
+ email: 'info@xyztasima.com',
+ status: 'passive' as const,
+ verified: false,
+ },
+];
+
+const PHONE_REGEX = /^[0-9]{10,11}$/; // 10 veya 11 haneli telefon numarası
+const TAX_NUMBER_REGEX = /^[0-9]{10}$/; // 10 haneli vergi numarası
+const WEBSITE_REGEX = /^(https?:\/\/)?([\da-z.-]+)\.([a-z.]{2,6})([/\w .-]*)*\/?$/;
+
+const validationSchema = Yup.object({
+ name: Yup.string()
+ .min(2, 'company.validation.companyNameMin')
+ .max(100, 'company.validation.companyNameMax')
+ .required('company.validation.companyNameRequired'),
+ phone: Yup.string()
+ .matches(PHONE_REGEX, 'company.validation.phoneFormat')
+ .required('company.validation.phoneRequired'),
+ email: Yup.string()
+ .email('company.validation.email')
+ .required('company.validation.emailRequired'),
+ status: Yup.string()
+ .oneOf(['active', 'passive'])
+ .required('company.validation.statusRequired'),
+ taxNumber: Yup.string()
+ .matches(TAX_NUMBER_REGEX, 'company.validation.taxNumberFormat')
+ .required('company.validation.taxNumberRequired'),
+ website: Yup.string()
+ .matches(WEBSITE_REGEX, 'company.validation.url')
+ .nullable(),
+ address: Yup.string()
+ .min(10, 'company.validation.addressMin')
+ .max(500, 'company.validation.addressMax')
+ .required('company.validation.addressRequired'),
+ description: Yup.string()
+ .max(1000, 'company.validation.descriptionMax'),
+});
+
+export function CompanyList() {
+ const { t } = useTranslation('company');
+ const [page, setPage] = useState(0);
+ const [order, setOrder] = useState<'asc' | 'desc'>('asc');
+ const [selected, setSelected] = useState([]);
+ const [orderBy, setOrderBy] = useState('name');
+ const [filterName, setFilterName] = useState('');
+ const [rowsPerPage, setRowsPerPage] = useState(5);
+ const [openDialog, setOpenDialog] = useState(false);
+
+ const TABLE_HEAD = [
+ { id: 'name', label: t('company.companyName'), align: 'left' },
+ { id: 'phone', label: t('company.phone'), align: 'left' },
+ { id: 'email', label: t('company.email'), align: 'left' },
+ { id: 'status', label: t('company.status'), align: 'left' },
+ { id: 'actions', label: '', align: 'right' },
+ ];
+
+ const formik = useFormik({
+ initialValues: {
+ name: '',
+ phone: '',
+ email: '',
+ status: 'active' as const,
+ taxNumber: '',
+ website: '',
+ address: '',
+ description: '',
+ },
+ validationSchema,
+ onSubmit: async (values, { resetForm }) => {
+ // TODO: API call to save data
+ console.log('Saving...', values);
+ setOpenDialog(false);
+ resetForm();
+ },
+ });
+
+ const handleSort = useCallback((id: string) => {
+ const isAsc = orderBy === id && order === 'asc';
+ if (id !== '') {
+ setOrder(isAsc ? 'desc' : 'asc');
+ setOrderBy(id);
+ }
+ }, [order, orderBy]);
+
+ const handleSelectAllRows = useCallback((checked: boolean) => {
+ if (checked) {
+ const newSelected = COMPANY_LIST.map((n) => n.id);
+ setSelected(newSelected);
+ return;
+ }
+ setSelected([]);
+ }, []);
+
+ const handleFilterByName = useCallback((event: React.ChangeEvent) => {
+ setPage(0);
+ setFilterName(event.target.value);
+ }, []);
+
+ const handleSelectRow = useCallback((id: string) => {
+ const selectedIndex = selected.indexOf(id);
+ let newSelected: string[] = [];
+
+ if (selectedIndex === -1) {
+ newSelected = newSelected.concat(selected, id);
+ } else if (selectedIndex === 0) {
+ newSelected = newSelected.concat(selected.slice(1));
+ } else if (selectedIndex === selected.length - 1) {
+ newSelected = newSelected.concat(selected.slice(0, -1));
+ } else if (selectedIndex > 0) {
+ newSelected = newSelected.concat(
+ selected.slice(0, selectedIndex),
+ selected.slice(selectedIndex + 1)
+ );
+ }
+ setSelected(newSelected);
+ }, [selected]);
+
+ const handleOpenDialog = () => {
+ setOpenDialog(true);
+ };
+
+ const handleCloseDialog = () => {
+ setOpenDialog(false);
+ formik.resetForm();
+ };
+
+ const filteredCompanies = COMPANY_LIST.filter((company) =>
+ company.name.toLowerCase().includes(filterName.toLowerCase())
+ );
+
+ return (
+
+
+ {t('company.title')}
+ }
+ onClick={handleOpenDialog}
+ sx={{
+ bgcolor: 'black',
+ color: 'white',
+ '&:hover': { bgcolor: 'black' },
+ borderRadius: '8px',
+ textTransform: 'none',
+ px: 2,
+ }}
+ >
+ {t('company.newCompany')}
+
+
+
+
+
+
+
+
+
+
+
+
+ {filteredCompanies
+ .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
+ .map((row) => (
+ handleSelectRow(row.id)}
+ />
+ ))}
+
+
+
+
+
+
+ setPage(newPage)}
+ rowsPerPageOptions={[5, 10, 25]}
+ onRowsPerPageChange={(e) => {
+ setPage(0);
+ setRowsPerPage(Number(e.target.value));
+ }}
+ />
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/sections/company/company-table-head.tsx b/src/sections/company/company-table-head.tsx
new file mode 100644
index 000000000..1691b9f09
--- /dev/null
+++ b/src/sections/company/company-table-head.tsx
@@ -0,0 +1,67 @@
+import React from "react";
+
+import Box from '@mui/material/Box';
+import TableRow from '@mui/material/TableRow';
+import Checkbox from '@mui/material/Checkbox';
+import TableHead from '@mui/material/TableHead';
+import TableCell from '@mui/material/TableCell';
+import TableSortLabel from '@mui/material/TableSortLabel';
+
+type CompanyTableHeadProps = {
+ orderBy: string;
+ rowCount: number;
+ numSelected: number;
+ order: 'asc' | 'desc';
+ onSort: (id: string) => void;
+ headLabel: Record[];
+ onSelectAllRows: (checked: boolean) => void;
+};
+
+export function CompanyTableHead({
+ order,
+ onSort,
+ orderBy,
+ rowCount,
+ headLabel,
+ numSelected,
+ onSelectAllRows,
+}: CompanyTableHeadProps) {
+ return (
+
+
+
+ 0 && numSelected < rowCount}
+ checked={rowCount > 0 && numSelected === rowCount}
+ onChange={(event: React.ChangeEvent) =>
+ onSelectAllRows(event.target.checked)
+ }
+ />
+
+
+ {headLabel.map((headCell) => (
+
+ onSort(headCell.id)}
+ >
+ {headCell.label}
+ {orderBy === headCell.id ? (
+
+ {order === 'desc' ? 'sıralama azalan' : 'sıralama artan'}
+
+ ) : null}
+
+
+ ))}
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/sections/company/company-table-row.tsx b/src/sections/company/company-table-row.tsx
new file mode 100644
index 000000000..b5d1125f8
--- /dev/null
+++ b/src/sections/company/company-table-row.tsx
@@ -0,0 +1,93 @@
+import React from 'react';
+import { useNavigate } from 'react-router-dom';
+
+import Box from '@mui/material/Box';
+import { Chip } from '@mui/material';
+import TableRow from '@mui/material/TableRow';
+import Checkbox from '@mui/material/Checkbox';
+import TableCell from '@mui/material/TableCell';
+import IconButton from '@mui/material/IconButton';
+
+import { Iconify } from 'src/components/iconify';
+
+export type CompanyProps = {
+ id: string;
+ name: string;
+ phone: string;
+ email: string;
+ status: 'active' | 'passive';
+ verified: boolean;
+};
+
+type CompanyTableRowProps = {
+ row: CompanyProps;
+ selected: boolean;
+ onSelectRow: () => void;
+};
+
+export function CompanyTableRow({ row, selected, onSelectRow }: CompanyTableRowProps) {
+ const navigate = useNavigate();
+
+ const handleNavigateToDetail = () => {
+ navigate(`/company/${row.id}`);
+ };
+
+ return (
+
+ e.stopPropagation()}>
+
+
+
+
+
+
+
+ {row.name}
+
+
+ {row.phone}
+
+ {row.email}
+
+
+
+
+
+ e.stopPropagation()}>
+ navigate(`/company/${row.id}`)}
+ >
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/sections/company/company-table-toolbar.tsx b/src/sections/company/company-table-toolbar.tsx
new file mode 100644
index 000000000..e12976d93
--- /dev/null
+++ b/src/sections/company/company-table-toolbar.tsx
@@ -0,0 +1,66 @@
+import React from "react";
+
+import Tooltip from '@mui/material/Tooltip';
+import Toolbar from '@mui/material/Toolbar';
+import Typography from '@mui/material/Typography';
+import IconButton from '@mui/material/IconButton';
+import OutlinedInput from '@mui/material/OutlinedInput';
+import InputAdornment from '@mui/material/InputAdornment';
+
+import { Iconify } from 'src/components/iconify';
+
+type CompanyTableToolbarProps = {
+ numSelected: number;
+ filterName: string;
+ onFilterName: (event: React.ChangeEvent) => void;
+};
+
+export function CompanyTableToolbar({ numSelected, filterName, onFilterName }: CompanyTableToolbarProps) {
+ return (
+ theme.spacing(0, 1, 0, 3),
+ ...(numSelected > 0 && {
+ color: 'primary.main',
+ bgcolor: 'primary.lighter',
+ }),
+ }}
+ >
+ {numSelected > 0 ? (
+
+ {numSelected} seçildi
+
+ ) : (
+
+
+
+ }
+ sx={{ maxWidth: 320 }}
+ />
+ )}
+
+ {numSelected > 0 ? (
+
+
+
+
+
+ ) : (
+
+
+
+
+
+ )}
+
+ );
+}
\ No newline at end of file
diff --git a/src/sections/overview/view/overview-analytics-view.tsx b/src/sections/overview/view/overview-analytics-view.tsx
index 2b6b6da4f..e0d0c2405 100644
--- a/src/sections/overview/view/overview-analytics-view.tsx
+++ b/src/sections/overview/view/overview-analytics-view.tsx
@@ -1,5 +1,6 @@
import Grid from '@mui/material/Unstable_Grid2';
import Typography from '@mui/material/Typography';
+import { useTranslation } from 'react-i18next';
import { _tasks, _posts, _timeline } from 'src/_mock';
import { DashboardContent } from 'src/layouts/dashboard';
@@ -17,21 +18,32 @@ import { AnalyticsConversionRates } from '../analytics-conversion-rates';
// ----------------------------------------------------------------------
export function OverviewAnalyticsView() {
+ const { t } = useTranslation(['overview', 'common']);
+
return (
- Hi, Welcome back 👋
+ {t('overview:welcome')}
}
chart={{
- categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug'],
+ categories: [
+ t('common:months.short.jan'),
+ t('common:months.short.feb'),
+ t('common:months.short.mar'),
+ t('common:months.short.apr'),
+ t('common:months.short.may'),
+ t('common:months.short.jun'),
+ t('common:months.short.jul'),
+ t('common:months.short.aug')
+ ],
series: [22, 8, 35, 50, 82, 84, 77, 12],
}}
/>
@@ -39,13 +51,22 @@ export function OverviewAnalyticsView() {
}
chart={{
- categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug'],
+ categories: [
+ t('common:months.short.jan'),
+ t('common:months.short.feb'),
+ t('common:months.short.mar'),
+ t('common:months.short.apr'),
+ t('common:months.short.may'),
+ t('common:months.short.jun'),
+ t('common:months.short.jul'),
+ t('common:months.short.aug')
+ ],
series: [56, 47, 40, 62, 73, 30, 23, 54],
}}
/>
@@ -53,13 +74,22 @@ export function OverviewAnalyticsView() {
}
chart={{
- categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug'],
+ categories: [
+ t('common:months.short.jan'),
+ t('common:months.short.feb'),
+ t('common:months.short.mar'),
+ t('common:months.short.apr'),
+ t('common:months.short.may'),
+ t('common:months.short.jun'),
+ t('common:months.short.jul'),
+ t('common:months.short.aug')
+ ],
series: [40, 70, 50, 28, 70, 75, 7, 64],
}}
/>
@@ -67,13 +97,22 @@ export function OverviewAnalyticsView() {
}
chart={{
- categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug'],
+ categories: [
+ t('common:months.short.jan'),
+ t('common:months.short.feb'),
+ t('common:months.short.mar'),
+ t('common:months.short.apr'),
+ t('common:months.short.may'),
+ t('common:months.short.jun'),
+ t('common:months.short.jul'),
+ t('common:months.short.aug')
+ ],
series: [56, 30, 23, 54, 47, 40, 62, 73],
}}
/>
@@ -81,13 +120,13 @@ export function OverviewAnalyticsView() {
@@ -95,13 +134,23 @@ export function OverviewAnalyticsView() {
diff --git a/src/sections/profile/components/notification-card.tsx b/src/sections/profile/components/notification-card.tsx
new file mode 100644
index 000000000..680b3d0a7
--- /dev/null
+++ b/src/sections/profile/components/notification-card.tsx
@@ -0,0 +1,50 @@
+import { useTranslation } from 'react-i18next';
+
+import { useTheme } from '@mui/material/styles';
+import FormControlLabel from '@mui/material/FormControlLabel';
+import { Box, Card, Stack, Switch, Typography } from '@mui/material';
+
+export type NotificationType = 'email' | 'push' | 'monthly' | 'news';
+
+interface NotificationCardProps {
+ type: NotificationType;
+ checked: boolean;
+ onChange: (checked: boolean) => void;
+}
+
+export function NotificationCard({ type, checked, onChange }: NotificationCardProps) {
+ const { t } = useTranslation();
+ const theme = useTheme();
+
+ return (
+
+
+
+
+ {t(`profile:notifications.${type}.title`)}
+
+
+ {t(`profile:notifications.${type}.description`)}
+
+
+ onChange(e.target.checked)}
+ color="primary"
+ />
+ }
+ label=""
+ />
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/sections/profile/components/password-rules.tsx b/src/sections/profile/components/password-rules.tsx
new file mode 100644
index 000000000..69e456425
--- /dev/null
+++ b/src/sections/profile/components/password-rules.tsx
@@ -0,0 +1,63 @@
+import { Box, Stack, Typography } from '@mui/material';
+import { useTranslation } from 'react-i18next';
+import { PASSWORD_RULES } from 'src/utils/validators';
+import { Iconify } from 'src/components/iconify';
+
+// Şifre kuralları kontrolü için yardımcı fonksiyon
+const checkPasswordRule = (password: string, rule: (pass: string) => boolean): boolean => {
+ if (!password) return false;
+ return rule(password);
+};
+
+interface PasswordRulesProps {
+ password: string;
+}
+
+export function PasswordRules({ password }: PasswordRulesProps) {
+ const { t } = useTranslation();
+
+ const rules = [
+ {
+ check: (pass: string) => pass.length >= PASSWORD_RULES.minLength,
+ text: t('validation:password.min', { length: PASSWORD_RULES.minLength })
+ },
+ {
+ check: (pass: string) => /[A-Z]/.test(pass),
+ text: t('validation:password.uppercase')
+ },
+ {
+ check: (pass: string) => /[a-z]/.test(pass),
+ text: t('validation:password.lowercase')
+ },
+ {
+ check: (pass: string) => /\d/.test(pass),
+ text: t('validation:password.number')
+ },
+ {
+ check: (pass: string) => /[!@#$%^&*(),.?":{}|<>]/.test(pass),
+ text: t('validation:password.special')
+ }
+ ];
+
+ return (
+
+
+ {t('profile:security.passwordRules')}:
+
+
+ {rules.map((rule, index) => (
+
+ {checkPasswordRule(password, rule.check) ? (
+
+ ) : (
+
+ )}
+
+ {rule.text}
+
+
+ ))}
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/sections/profile/components/profile-avatar.tsx b/src/sections/profile/components/profile-avatar.tsx
new file mode 100644
index 000000000..035a0049f
--- /dev/null
+++ b/src/sections/profile/components/profile-avatar.tsx
@@ -0,0 +1,80 @@
+import React, { useState } from 'react';
+
+import { useTheme } from '@mui/material/styles';
+import { Box, Badge, Avatar, IconButton } from '@mui/material';
+
+import { userService } from 'src/services/user/user-service';
+
+import { Iconify } from 'src/components/iconify';
+
+interface ProfileAvatarProps {
+ avatarUrl?: string;
+ name: string;
+}
+
+export function ProfileAvatar({ avatarUrl, name }: ProfileAvatarProps) {
+ const theme = useTheme();
+ const [uploadedPhoto, setUploadedPhoto] = useState(null);
+
+ const handlePhotoUpload = async (event: React.ChangeEvent) => {
+ const file = event.target.files?.[0];
+ if (file) {
+ try {
+ const response = await userService.uploadProfilePhoto(file);
+ setUploadedPhoto("response.filePath");
+ } catch (error) {
+ console.error('Error uploading file:', error);
+ }
+ }
+ };
+
+ return (
+
+
+
+ {/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
+
+ >
+ }
+ >
+
+
+
+ );
+}
diff --git a/src/sections/profile/hooks/use-password-form.ts b/src/sections/profile/hooks/use-password-form.ts
new file mode 100644
index 000000000..dbf532854
--- /dev/null
+++ b/src/sections/profile/hooks/use-password-form.ts
@@ -0,0 +1,57 @@
+import type React from 'react';
+
+import { useState } from 'react';
+import { useTranslation } from 'react-i18next';
+
+import { validatePasswordChange } from 'src/utils/validators';
+
+interface PasswordFormErrors {
+ currentPassword?: string;
+ newPassword?: string;
+ confirmPassword?: string;
+}
+
+export const usePasswordForm = () => {
+ const { t } = useTranslation();
+ const [currentPassword, setCurrentPassword] = useState('');
+ const [newPassword, setNewPassword] = useState('');
+ const [confirmPassword, setConfirmPassword] = useState('');
+ const [isSaving, setIsSaving] = useState(false);
+ const [successMessage, setSuccessMessage] = useState('');
+ const [formErrors, setFormErrors] = useState({});
+
+ const validateForm = (): boolean => {
+ const errors = validatePasswordChange(currentPassword, newPassword, confirmPassword, t);
+ setFormErrors(errors);
+ return !Object.values(errors).some(Boolean);
+ };
+
+ const handleSubmit = async (e: React.FormEvent) => {
+ e.preventDefault();
+ if (!validateForm()) return;
+
+ try {
+ setIsSaving(true);
+ // Şifre değiştirme API çağrısı burada yapılacak
+ setSuccessMessage(t('profile:security.success'));
+ } catch (err) {
+ console.error(t('profile:security.error'), err);
+ } finally {
+ setIsSaving(false);
+ }
+ };
+
+ return {
+ currentPassword,
+ setCurrentPassword,
+ newPassword,
+ setNewPassword,
+ confirmPassword,
+ setConfirmPassword,
+ isSaving,
+ successMessage,
+ formErrors,
+ setFormErrors,
+ handleSubmit,
+ };
+};
\ No newline at end of file
diff --git a/src/sections/profile/hooks/use-profile-form.ts b/src/sections/profile/hooks/use-profile-form.ts
new file mode 100644
index 000000000..1c90c51dd
--- /dev/null
+++ b/src/sections/profile/hooks/use-profile-form.ts
@@ -0,0 +1,107 @@
+import * as Yup from 'yup';
+import { useEffect } from 'react';
+import { useFormik } from 'formik';
+import { useTranslation } from 'react-i18next';
+
+import { useUser } from 'src/contexts/user-context';
+import { useLoading } from "src/contexts/loading-context";
+import { useUnsavedChanges } from "src/contexts/unsaved-changes-context";
+
+export const useProfileForm = () => {
+ const { t } = useTranslation();
+ const { user, updateUser } = useUser();
+ const { showLoading, hideLoading } = useLoading();
+ const { setHasUnsavedChanges } = useUnsavedChanges();
+
+ const validationSchema = Yup.object().shape({
+ firstName: Yup.string()
+ .required(t('validation:required.firstName'))
+ .min(2, t('validation:length.name.min'))
+ .max(50, t('validation:length.name.max')),
+ lastName: Yup.string()
+ .required(t('validation:required.lastName'))
+ .min(2, t('validation:length.name.min'))
+ .max(50, t('validation:length.name.max')),
+ email: Yup.string()
+ .required(t('validation:required.email'))
+ .email(t('validation:invalid.email')),
+ phone: Yup.string()
+ .required(t('validation:required.phone'))
+ .matches(/^\(\d{3}\) \d{3} \d{2} \d{2}$/, t('validation:invalid.phone')),
+ about: Yup.string()
+ .max(500, t('validation:length.about.max')),
+ });
+
+ const formik = useFormik({
+ initialValues: {
+ firstName: user?.firstName || '',
+ lastName: user?.lastName || '',
+ email: user?.email || '',
+ phone: user?.phone || '',
+ about: '',
+ countryCode: '+90',
+ },
+ enableReinitialize: true,
+ validationSchema,
+ onSubmit: async (values, { setSubmitting, setStatus }) => {
+ showLoading();
+
+ try {
+ setStatus(null);
+ setSubmitting(true);
+
+ const updatedFields: Partial = {};
+
+ if (values.firstName !== user?.firstName) updatedFields.firstName = values.firstName;
+ if (values.lastName !== user?.lastName) updatedFields.lastName = values.lastName;
+ if (values.email !== user?.email) updatedFields.email = values.email;
+ if (values.phone !== user?.phone) updatedFields.phone = values.phone;
+
+ await updateUser(updatedFields);
+ setStatus({ success: t('profile:success') });
+ setHasUnsavedChanges(false);
+ } catch (error) {
+ console.error('Form submission error:', error);
+ setStatus({ error: t('profile:error.update') });
+ } finally {
+ hideLoading();
+ setSubmitting(false);
+ }
+ },
+ });
+
+ // Form değişikliklerini takip et
+ useEffect(() => {
+ const hasChanges = Object.keys(formik.values).some((key) => {
+ const value = formik.values[key as keyof typeof formik.values];
+ const initialValue = formik.initialValues[key as keyof typeof formik.initialValues];
+ return value !== initialValue;
+ });
+
+ setHasUnsavedChanges(hasChanges);
+ }, [formik.values, formik.initialValues, setHasUnsavedChanges, formik]);
+
+ const formatPhoneNumber = (value: string) => {
+ const numbersOnly = value.replace(/\D/g, '');
+ let formatted = '';
+ if (numbersOnly.length > 0) formatted += '(';
+ if (numbersOnly.length > 0) formatted += numbersOnly.substring(0, 3);
+ if (numbersOnly.length > 3) formatted += ') ';
+ if (numbersOnly.length > 3) formatted += numbersOnly.substring(3, 6);
+ if (numbersOnly.length > 6) formatted += ' ';
+ if (numbersOnly.length > 6) formatted += numbersOnly.substring(6, 8);
+ if (numbersOnly.length > 8) formatted += ' ';
+ if (numbersOnly.length > 8) formatted += numbersOnly.substring(8, 10);
+ return formatted;
+ };
+
+ const handlePhoneChange = (e: React.ChangeEvent) => {
+ const formatted = formatPhoneNumber(e.target.value);
+ formik.setFieldValue('phone', formatted);
+ };
+
+ return {
+ ...formik,
+ handlePhoneChange,
+ };
+};
\ No newline at end of file
diff --git a/src/sections/profile/tabs/general-tab.tsx b/src/sections/profile/tabs/general-tab.tsx
new file mode 100644
index 000000000..aa3f1b957
--- /dev/null
+++ b/src/sections/profile/tabs/general-tab.tsx
@@ -0,0 +1,233 @@
+import { useTranslation } from 'react-i18next';
+
+import { LoadingButton } from '@mui/lab';
+import {
+ Box,
+ Alert,
+ Stack,
+ Button,
+ Select,
+ Divider,
+ MenuItem,
+ TextField,
+ InputAdornment,
+
+} from '@mui/material';
+
+import { Iconify } from 'src/components/iconify';
+
+import { useProfileForm } from '../hooks/use-profile-form';
+
+const COUNTRY_CODES = [
+ { code: '+90', country: 'TR', flag: '🇹🇷' },
+ { code: '+1', country: 'US', flag: '🇺🇸' },
+ { code: '+44', country: 'GB', flag: '🇬🇧' },
+ { code: '+49', country: 'DE', flag: '🇩🇪' },
+ { code: '+33', country: 'FR', flag: '🇫🇷' },
+ { code: '+39', country: 'IT', flag: '🇮🇹' },
+ { code: '+34', country: 'ES', flag: '🇪🇸' },
+ { code: '+31', country: 'NL', flag: '🇳🇱' },
+] as const;
+
+export function GeneralTab() {
+ const { t } = useTranslation(['profile', 'validation', 'common']);
+ const {
+ values,
+ errors,
+ touched,
+ isSubmitting,
+ status,
+ handleSubmit,
+ handleChange,
+ handleBlur,
+ setFieldValue,
+ resetForm,
+ handlePhoneChange,
+ } = useProfileForm();
+
+ return (
+
+ );
+}
diff --git a/src/sections/profile/tabs/notifications-tab.tsx b/src/sections/profile/tabs/notifications-tab.tsx
new file mode 100644
index 000000000..afc863a6d
--- /dev/null
+++ b/src/sections/profile/tabs/notifications-tab.tsx
@@ -0,0 +1,44 @@
+import { useState } from 'react';
+import { useTranslation } from 'react-i18next';
+
+import { Box, Stack, Typography } from '@mui/material';
+
+import { NotificationCard } from '../components/notification-card';
+
+import type { NotificationType } from '../components/notification-card';
+
+export function NotificationsTab() {
+ const { t } = useTranslation();
+ const [notifications, setNotifications] = useState>({
+ email: true,
+ push: true,
+ monthly: false,
+ news: true,
+ });
+
+ const handleNotificationChange = (type: NotificationType, checked: boolean) => {
+ setNotifications(prev => ({
+ ...prev,
+ [type]: checked,
+ }));
+ };
+
+ return (
+
+
+ {t('profile:notifications.title')}
+
+
+
+ {(['email', 'push', 'monthly', 'news'] as NotificationType[]).map((type) => (
+ handleNotificationChange(type, checked)}
+ />
+ ))}
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/sections/profile/tabs/security-tab.tsx b/src/sections/profile/tabs/security-tab.tsx
new file mode 100644
index 000000000..c6d318e20
--- /dev/null
+++ b/src/sections/profile/tabs/security-tab.tsx
@@ -0,0 +1,104 @@
+import { useTranslation } from 'react-i18next';
+
+import { LoadingButton } from '@mui/lab';
+import { Box, Alert, Stack, TextField, Typography } from '@mui/material';
+
+import { Iconify } from 'src/components/iconify';
+
+import { usePasswordForm } from '../hooks/use-password-form';
+import { PasswordRules } from '../components/password-rules';
+
+export function SecurityTab() {
+ const { t } = useTranslation();
+ const {
+ currentPassword,
+ setCurrentPassword,
+ newPassword,
+ setNewPassword,
+ confirmPassword,
+ setConfirmPassword,
+ isSaving,
+ successMessage,
+ formErrors,
+ setFormErrors,
+ handleSubmit,
+ } = usePasswordForm();
+
+ return (
+
+
+ {t('profile:security.title')}
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/sections/profile/view/index.ts b/src/sections/profile/view/index.ts
new file mode 100644
index 000000000..afa040dd7
--- /dev/null
+++ b/src/sections/profile/view/index.ts
@@ -0,0 +1 @@
+export * from './profile-view';
\ No newline at end of file
diff --git a/src/sections/profile/view/profile-view.tsx b/src/sections/profile/view/profile-view.tsx
new file mode 100644
index 000000000..af5d4b323
--- /dev/null
+++ b/src/sections/profile/view/profile-view.tsx
@@ -0,0 +1,115 @@
+import React, { useState } from 'react';
+import { useTranslation } from 'react-i18next';
+
+import { Box, Tab, Card, Tabs, Stack, Divider, Container, Typography } from '@mui/material';
+
+import { useUser } from 'src/contexts/user-context';
+import { DashboardContent } from 'src/layouts/dashboard';
+
+import { GeneralTab } from '../tabs/general-tab';
+import { SecurityTab } from '../tabs/security-tab';
+import { ProfileAvatar } from '../components/profile-avatar';
+import { NotificationsTab } from '../tabs/notifications-tab';
+
+interface TabPanelProps {
+ children?: React.ReactNode;
+ index: number;
+ value: number;
+}
+
+function TabPanel(props: TabPanelProps) {
+ const { children, value, index, ...other } = props;
+
+ return (
+
+ {value === index && {children}}
+
+ );
+}
+
+export function ProfileView() {
+ const { t } = useTranslation();
+ const { user } = useUser();
+ const [activeTab, setActiveTab] = useState(0);
+
+ const handleTabChange = (_event: React.SyntheticEvent, newValue: number) => {
+ setActiveTab(newValue);
+ };
+
+ return (
+
+
+
+ {t('profile:title')}
+
+
+ {t('profile:subtitle')}
+
+
+
+
+
+ `linear-gradient(135deg, ${theme.palette.primary.light} 0%, ${theme.palette.primary.main} 100%)`,
+ }}
+ >
+
+
+
+ {`${user?.firstName ?? ''} ${user?.lastName ?? ''}`}
+
+ {user?.email}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/services/auth/auth-service.ts b/src/services/auth/auth-service.ts
new file mode 100644
index 000000000..1f8d80a07
--- /dev/null
+++ b/src/services/auth/auth-service.ts
@@ -0,0 +1,18 @@
+import axiosInstance from '../../config/axios-instance';
+
+import type { LoginRequest, LoginResponse } from './auth-service.type';
+
+const BASE_URL = '/auth';
+
+export const authService = {
+ // Login
+ login: async (data: LoginRequest): Promise => {
+ const response = await axiosInstance.post(`${BASE_URL}/login`, data);
+ return response.data;
+ },
+
+ // Logout
+ logout: () => {
+ localStorage.removeItem('token');
+ },
+};
diff --git a/src/services/auth/auth-service.type.ts b/src/services/auth/auth-service.type.ts
new file mode 100644
index 000000000..26bfa5fc3
--- /dev/null
+++ b/src/services/auth/auth-service.type.ts
@@ -0,0 +1,9 @@
+export interface LoginRequest {
+ email: string;
+ password: string;
+}
+
+export interface LoginResponse {
+ token: string;
+}
+
diff --git a/src/services/company/company-service.ts b/src/services/company/company-service.ts
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/services/company/company-service.type.ts b/src/services/company/company-service.type.ts
new file mode 100644
index 000000000..d5edf0cc0
--- /dev/null
+++ b/src/services/company/company-service.type.ts
@@ -0,0 +1,156 @@
+export type PartnerType = 'CARRIER' | 'WAREHOUSE' | 'CUSTOMS' | 'SUPPLIER' | 'CUSTOMER';
+
+export interface BankAccount {
+ bankName: string;
+ branch: string;
+ accountNumber: string;
+ iban: string;
+ currency: string;
+}
+
+export interface InsuranceInfo {
+ provider: string;
+ policyNumber: string;
+ coverage: string;
+ expiryDate: Date;
+}
+
+export interface CompanyDetails {
+ id: string;
+ name: string;
+ type: PartnerType;
+ taxNumber: string;
+ taxOffice?: string;
+ phone: string;
+ email: string;
+ website?: string;
+ address: string;
+ status: 'active' | 'passive';
+ foundedYear?: number;
+ employeeCount?: number;
+ certifications?: string[];
+ operationAreas?: string[];
+ description?: string;
+ insuranceInfo?: InsuranceInfo;
+ bankAccounts?: BankAccount[];
+}
+
+export interface ContactAvailability {
+ workHours: string;
+ timezone: string;
+ preferredContactMethod: 'PHONE' | 'EMAIL' | 'WHATSAPP';
+}
+
+export interface ContactPerson {
+ id: string;
+ companyId: string;
+ name: string;
+ position: string;
+ department: string;
+ phone: string;
+ mobile?: string;
+ email: string;
+ isMainContact: boolean;
+ availability: ContactAvailability;
+}
+
+export type Contract = {
+ id: string;
+ companyId: string;
+ type: 'SERVICE' | 'PARTNERSHIP' | 'FRAMEWORK';
+ startDate: Date;
+ endDate: Date;
+ status: 'DRAFT' | 'ACTIVE' | 'EXPIRED' | 'TERMINATED';
+ terms: {
+ paymentTerms: string;
+ deliveryTerms: string;
+ specialConditions: string[];
+ };
+ attachments: {
+ id: string;
+ name: string;
+ type: string;
+ url: string;
+ }[];
+ history: {
+ date: Date;
+ action: string;
+ user: string;
+ notes: string;
+ }[];
+};
+
+export type Performance = {
+ partnerId: string;
+ metrics: {
+ onTimeDelivery: number;
+ qualityScore: number;
+ responseTime: number;
+ incidentCount: number;
+ };
+ reviews: {
+ date: Date;
+ score: number;
+ feedback: string;
+ reviewer: string;
+ }[];
+ incidents: {
+ date: Date;
+ type: string;
+ description: string;
+ status: 'OPEN' | 'RESOLVED' | 'CLOSED';
+ resolution?: string;
+ }[];
+};
+
+export type Pricing = {
+ partnerId: string;
+ rateCards: {
+ id: string;
+ name: string;
+ validFrom: Date;
+ validTo: Date;
+ currency: string;
+ services: {
+ serviceType: string;
+ unitPrice: number;
+ unit: string;
+ conditions: string[];
+ }[];
+ }[];
+ specialOffers: {
+ id: string;
+ description: string;
+ validFrom: Date;
+ validTo: Date;
+ discountRate: number;
+ conditions: string[];
+ }[];
+};
+
+export type Analytics = {
+ partnerId: string;
+ financials: {
+ totalRevenue: number;
+ outstandingBalance: number;
+ paymentHistory: {
+ date: Date;
+ amount: number;
+ type: 'INVOICE' | 'PAYMENT';
+ status: 'PENDING' | 'COMPLETED' | 'OVERDUE';
+ }[];
+ };
+ operationalMetrics: {
+ serviceUtilization: number;
+ incidentResolutionTime: number;
+ customerSatisfaction: number;
+ };
+ trends: {
+ period: string;
+ metrics: {
+ name: string;
+ value: number;
+ change: number;
+ }[];
+ }[];
+};
\ No newline at end of file
diff --git a/src/services/user/user-service.ts b/src/services/user/user-service.ts
new file mode 100644
index 000000000..316213cc7
--- /dev/null
+++ b/src/services/user/user-service.ts
@@ -0,0 +1,39 @@
+import type { User } from 'src/contexts/user-context';
+import axiosInstance from '../../config/axios-instance';
+
+const BASE_URL = '/user';
+
+export const userService = {
+ getUserProfileByEmail: async (email: string): Promise => {
+ const response = await axiosInstance.get(`${BASE_URL}/profile/${email}`);
+ return response.data;
+ },
+
+ updateUserProfile: async (data: Partial): Promise => {
+ const response = await axiosInstance.put(`${BASE_URL}/profile`, data);
+ return response.data;
+ },
+
+ updatePassword: async (currentPassword: string, newPassword: string): Promise => {
+ await axiosInstance.put(`${BASE_URL}/password`, {
+ currentPassword,
+ newPassword,
+ });
+ },
+
+ uploadProfilePhoto: async (file: File): Promise => {
+ const formData = new FormData();
+ formData.append('photo', file);
+
+ const response = await axiosInstance.put(`${BASE_URL}/photo`, formData, {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ });
+ return response.data.avatarUrl;
+ },
+
+ updateNotifications: async (notifications: User['notifications']): Promise => {
+ await axiosInstance.put(`${BASE_URL}/notifications`, { notifications });
+ },
+};
diff --git a/src/services/user/user-service.type.ts b/src/services/user/user-service.type.ts
new file mode 100644
index 000000000..520e2f5a2
--- /dev/null
+++ b/src/services/user/user-service.type.ts
@@ -0,0 +1,25 @@
+export interface UpdateUserProfileRequest {
+ firstName?: string;
+ lastName?: string;
+ email?: string;
+}
+
+export interface UpdateUserProfileResponse {
+ success: boolean;
+ message: string;
+}
+
+export interface UserProfileResponse {
+ id: string;
+ email: string;
+ firstName: string;
+ lastName: string;
+ avatarUrl?: string;
+}
+
+export interface UploadProfilePhotoResponse {
+ success: boolean;
+ message: string;
+ url: string;
+ filePath: string;
+}
diff --git a/src/utils/validators.ts b/src/utils/validators.ts
new file mode 100644
index 000000000..523f014ef
--- /dev/null
+++ b/src/utils/validators.ts
@@ -0,0 +1,81 @@
+import type { TFunction } from 'i18next';
+
+export const PASSWORD_RULES = {
+ minLength: 8,
+};
+
+export const validateName = (value: string, t: TFunction): string | undefined => {
+ if (!value) {
+ return t('validation.required');
+ }
+ if (value.length < 2) {
+ return t('validation.nameMinLength');
+ }
+ if (value.length > 50) {
+ return t('validation.nameMaxLength');
+ }
+ return undefined;
+};
+
+export const validateEmail = (value: string, t: TFunction): string | undefined => {
+ if (!value) {
+ return t('validation.required');
+ }
+ const emailRegex = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i;
+ if (!emailRegex.test(value)) {
+ return t('validation.invalidEmail');
+ }
+ return undefined;
+};
+
+export const validatePhone = (value: string, t: TFunction): string | undefined => {
+ if (!value) {
+ return t('validation.required');
+ }
+ const phoneRegex = /^\(\d{3}\) \d{3} \d{2} \d{2}$/;
+ if (!phoneRegex.test(value)) {
+ return t('validation.invalidPhone');
+ }
+ return undefined;
+};
+
+export const validatePasswordChange = (
+ currentPassword: string,
+ newPassword: string,
+ confirmPassword: string,
+ t: TFunction
+): { currentPassword?: string; newPassword?: string; confirmPassword?: string } => {
+ const errors: { currentPassword?: string; newPassword?: string; confirmPassword?: string } = {};
+
+ if (!currentPassword) {
+ errors.currentPassword = t('validation.required');
+ }
+
+ if (!newPassword) {
+ errors.newPassword = t('validation.required');
+ } else {
+ if (newPassword.length < PASSWORD_RULES.minLength) {
+ errors.newPassword = t('validation.passwordMinLength', { length: PASSWORD_RULES.minLength });
+ }
+ if (!/[A-Z]/.test(newPassword)) {
+ errors.newPassword = t('validation.passwordRequireUppercase');
+ }
+ if (!/[a-z]/.test(newPassword)) {
+ errors.newPassword = t('validation.passwordRequireLowercase');
+ }
+ if (!/\d/.test(newPassword)) {
+ errors.newPassword = t('validation.passwordRequireNumber');
+ }
+ if (!/[!@#$%^&*(),.?":{}|<>]/.test(newPassword)) {
+ errors.newPassword = t('validation.passwordRequireSpecialChar');
+ }
+ }
+
+ if (!confirmPassword) {
+ errors.confirmPassword = t('validation.required');
+ } else if (confirmPassword !== newPassword) {
+ errors.confirmPassword = t('validation.passwordMismatch');
+ }
+
+ return errors;
+};
\ No newline at end of file
diff --git a/yarn.lock b/yarn.lock
index eb21c020b..4dad99eab 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -60,10 +60,10 @@
dependencies:
"@babel/types" "^7.25.4"
-"@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.23.9", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.7":
- version "7.25.4"
- resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.4.tgz"
- integrity sha512-DSgLeL/FNcpXuzav5wfYvHCGvynXkJbn3Zvc3823AEe9nPwW9IK4UoCSS5yGymmQzN0pCPvivtgS6/8U2kkm1w==
+"@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.23.2", "@babel/runtime@^7.23.9", "@babel/runtime@^7.25.0", "@babel/runtime@^7.26.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.7":
+ version "7.26.0"
+ resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz"
+ integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==
dependencies:
regenerator-runtime "^0.14.0"
@@ -143,7 +143,7 @@
resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz"
integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==
-"@emotion/react@^11.0.0-rc.0", "@emotion/react@^11.13.3", "@emotion/react@^11.4.1", "@emotion/react@^11.5.0":
+"@emotion/react@^11.13.3":
version "11.13.3"
resolved "https://registry.npmjs.org/@emotion/react/-/react-11.13.3.tgz"
integrity sha512-lIsdU6JNrmYfJ5EbUCf4xW1ovy5wKQ2CkPRM4xogziOxH1nXxBSjpC9YqbFAP7circxMfYp+6x676BqWcEiixg==
@@ -173,7 +173,7 @@
resolved "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz"
integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==
-"@emotion/styled@^11.13.0", "@emotion/styled@^11.3.0":
+"@emotion/styled@^11.13.0":
version "11.13.0"
resolved "https://registry.npmjs.org/@emotion/styled/-/styled-11.13.0.tgz"
integrity sha512-tkzkY7nQhW/zC4hztlwucpT8QEZ6eUzpXDRhww/Eej4tFfO0FxQYWRyg/c5CCXa4d/f174kqeXYjuQRnhzf6dA==
@@ -205,10 +205,10 @@
resolved "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz"
integrity sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==
-"@esbuild/darwin-arm64@0.21.5":
+"@esbuild/win32-x64@0.21.5":
version "0.21.5"
- resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz"
- integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==
+ resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz"
+ integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==
"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
version "4.4.0"
@@ -360,6 +360,13 @@
resolved "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.7.tgz"
integrity sha512-RtsCt4Geed2/v74sbihWzzRs+HsIQCfclHeORh5Ynu2fS4icIKozcSubwuG7vtzq2uW3fOR1zITSP84TNt2GoQ==
+"@mui/icons-material@^6.3.1":
+ version "6.3.1"
+ resolved "https://registry.npmjs.org/@mui/icons-material/-/icons-material-6.3.1.tgz"
+ integrity sha512-nJmWj1PBlwS3t1PnoqcixIsftE+7xrW3Su7f0yrjPw4tVjYrgkhU0hrRp+OlURfZ3ptdSkoBkalee9Bhf1Erfw==
+ dependencies:
+ "@babel/runtime" "^7.26.0"
+
"@mui/lab@^5.0.0-alpha.173":
version "5.0.0-alpha.173"
resolved "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.173.tgz"
@@ -373,7 +380,7 @@
clsx "^2.1.0"
prop-types "^15.8.1"
-"@mui/material@^5.16.7", "@mui/material@>=5.15.0":
+"@mui/material@^5.16.7":
version "5.16.7"
resolved "https://registry.npmjs.org/@mui/material/-/material-5.16.7.tgz"
integrity sha512-cwwVQxBhK60OIOqZOVLFt55t01zmarKJiJUWbk0+8s/Ix5IaUzAShqlJchxsIQ4mSrWqgcKCCXKtIlG5H+/Jmg==
@@ -477,15 +484,15 @@
resolved "https://registry.npmjs.org/@remix-run/router/-/router-1.19.1.tgz"
integrity sha512-S45oynt/WH19bHbIXjtli6QmwNYvaz+vtnubvNpNDvUOoA/OWh6j1OikIP3G+v5GHdxyC6EXoChG3HgYGEUfcg==
-"@rollup/rollup-darwin-arm64@4.21.0":
- version "4.21.0"
- resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.0.tgz"
- integrity sha512-zOnKWLgDld/svhKO5PD9ozmL6roy5OQ5T4ThvdYZLpiOhEGY+dp2NwUmxK0Ld91LrbjrvtNAE0ERBwjqhZTRAA==
+"@rollup/rollup-win32-x64-msvc@4.29.1":
+ version "4.29.1"
+ resolved "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.29.1.tgz"
+ integrity sha512-+10CMg9vt1MoHj6x1pxyjPSMjHTIlqs8/tBztXvPAx24SKs9jwVnKqHJumlH/IzhaPUaj3T6T6wfZr8okdXaIg==
-"@swc/core-darwin-arm64@1.7.14":
+"@swc/core-win32-x64-msvc@1.7.14":
version "1.7.14"
- resolved "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.14.tgz"
- integrity sha512-V0OUXjOH+hdGxDYG8NkQzy25mKOpcNKFpqtZEzLe5V/CpLJPnpg1+pMz70m14s9ZFda9OxsjlvPbg1FLUwhgIQ==
+ resolved "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.14.tgz"
+ integrity sha512-NNrprQCK6d28mG436jVo2TD+vACHseUECacEBGZ9Ef0qfOIWS1XIt2MisQKG0Oea2VvLFl6tF/V4Lnx/H0Sn3Q==
"@swc/core@^1.5.7":
version "1.7.14"
@@ -518,10 +525,18 @@
dependencies:
"@swc/counter" "^0.1.3"
-"@types/estree@1.0.5":
- version "1.0.5"
- resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz"
- integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==
+"@types/estree@1.0.6":
+ version "1.0.6"
+ resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz"
+ integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==
+
+"@types/hoist-non-react-statics@^3.3.1":
+ version "3.3.6"
+ resolved "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.6.tgz"
+ integrity sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw==
+ dependencies:
+ "@types/react" "*"
+ hoist-non-react-statics "^3.3.0"
"@types/json5@^0.0.29":
version "0.0.29"
@@ -540,7 +555,7 @@
resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz"
integrity sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==
-"@types/node@^18.0.0 || >=20.0.0", "@types/node@^22.5.0":
+"@types/node@^22.5.0":
version "22.5.0"
resolved "https://registry.npmjs.org/@types/node/-/node-22.5.0.tgz"
integrity sha512-DkFrJOe+rfdHTqqMg0bSNlGlQ85hSoh2TPzZyhHsXnMtligRWpxUySiyw8FY14ITt24HVCiQPWxS3KO/QlGmWg==
@@ -564,6 +579,13 @@
dependencies:
"@types/react" "*"
+"@types/react-input-mask@^3.0.6":
+ version "3.0.6"
+ resolved "https://registry.npmjs.org/@types/react-input-mask/-/react-input-mask-3.0.6.tgz"
+ integrity sha512-+5I18WKyG3eWIj7TVPWfK1VitI9mPpS9y6jE/BfmTCe+iL27NfBw/yzKRvCFp1DRBvlvvcsiZf05bub0YC1k8A==
+ dependencies:
+ "@types/react" "*"
+
"@types/react-transition-group@^4.4.10":
version "4.4.11"
resolved "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.11.tgz"
@@ -571,7 +593,7 @@
dependencies:
"@types/react" "*"
-"@types/react@*", "@types/react@^17.0.0 || ^18.0.0", "@types/react@^18.3.4":
+"@types/react@*", "@types/react@^18.3.4":
version "18.3.4"
resolved "https://registry.npmjs.org/@types/react/-/react-18.3.4.tgz"
integrity sha512-J7W30FTdfCxDDjmfRM+/JqLHBIyl7xUIp9kwK637FGmY7+mkSFSe6L4jpZzhj5QMfLssSDP4/i75AKkrdC7/Jw==
@@ -579,7 +601,12 @@
"@types/prop-types" "*"
csstype "^3.0.2"
-"@typescript-eslint/eslint-plugin@^7.0.0", "@typescript-eslint/eslint-plugin@^7.18.0", "@typescript-eslint/eslint-plugin@6 - 7":
+"@types/yup@^0.29.14":
+ version "0.29.14"
+ resolved "https://registry.npmjs.org/@types/yup/-/yup-0.29.14.tgz"
+ integrity sha512-Ynb/CjHhE/Xp/4bhHmQC4U1Ox+I2OpfRYF3dnNgQqn1cHa6LK3H1wJMNPT02tSVZA6FYuXE2ITORfbnb6zBCSA==
+
+"@typescript-eslint/eslint-plugin@^7.18.0":
version "7.18.0"
resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz"
integrity sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==
@@ -594,7 +621,7 @@
natural-compare "^1.4.0"
ts-api-utils "^1.3.0"
-"@typescript-eslint/parser@^7.0.0", "@typescript-eslint/parser@^7.18.0":
+"@typescript-eslint/parser@^7.18.0":
version "7.18.0"
resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz"
integrity sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==
@@ -682,7 +709,7 @@ acorn-jsx@^5.3.2:
resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
-"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.9.0:
+acorn@^8.9.0:
version "8.10.0"
resolved "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz"
integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==
@@ -731,7 +758,7 @@ anymatch@~3.1.2:
normalize-path "^3.0.0"
picomatch "^2.0.4"
-apexcharts@^3.41.0, apexcharts@^3.52.0:
+apexcharts@^3.52.0:
version "3.52.0"
resolved "https://registry.npmjs.org/apexcharts/-/apexcharts-3.52.0.tgz"
integrity sha512-7dg0ADKs8AA89iYMZMe2sFDG0XK5PfqllKV9N+i3hKHm3vEtdhwz8AlXGm+/b0nJ6jKiaXsqci5LfVxNhtB+dA==
@@ -854,6 +881,11 @@ ast-types-flow@^0.0.8:
resolved "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz"
integrity sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==
+asynckit@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz"
+ integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
+
available-typed-arrays@^1.0.7:
version "1.0.7"
resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz"
@@ -866,6 +898,15 @@ axe-core@^4.9.1:
resolved "https://registry.npmjs.org/axe-core/-/axe-core-4.10.0.tgz"
integrity sha512-Mr2ZakwQ7XUAjp7pAwQWRhhK8mQQ6JAaNWSjmjxil0R8BPioMtQsTLOolGYkji1rcL++3dCqZA3zWqpT+9Ew6g==
+axios@^1.7.9:
+ version "1.7.9"
+ resolved "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz"
+ integrity sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==
+ dependencies:
+ follow-redirects "^1.15.6"
+ form-data "^4.0.0"
+ proxy-from-env "^1.1.0"
+
axobject-query@~3.1.1:
version "3.1.1"
resolved "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz"
@@ -999,6 +1040,13 @@ color-name@1.1.3:
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz"
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
+combined-stream@^1.0.8:
+ version "1.0.8"
+ resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz"
+ integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
+ dependencies:
+ delayed-stream "~1.0.0"
+
commander@^8.0.0:
version "8.3.0"
resolved "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz"
@@ -1030,10 +1078,17 @@ cosmiconfig@^7.0.0:
path-type "^4.0.0"
yaml "^1.10.0"
+cross-fetch@4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz"
+ integrity sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==
+ dependencies:
+ node-fetch "^2.6.12"
+
cross-spawn@^7.0.2:
- version "7.0.3"
- resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz"
- integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
+ version "7.0.6"
+ resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz"
+ integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
dependencies:
path-key "^3.1.0"
shebang-command "^2.0.0"
@@ -1123,6 +1178,11 @@ deep-is@^0.1.3:
resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz"
integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
+deepmerge@^2.1.1:
+ version "2.2.1"
+ resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz"
+ integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==
+
define-data-property@^1.0.1, define-data-property@^1.1.4:
version "1.1.4"
resolved "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz"
@@ -1141,6 +1201,11 @@ define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1:
has-property-descriptors "^1.0.0"
object-keys "^1.1.1"
+delayed-stream@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz"
+ integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
+
dir-glob@^3.0.1:
version "3.0.1"
resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz"
@@ -1386,7 +1451,7 @@ eslint-config-airbnb@^19.0.4:
object.assign "^4.1.2"
object.entries "^1.1.5"
-eslint-config-prettier@*, eslint-config-prettier@^9.1.0:
+eslint-config-prettier@^9.1.0:
version "9.1.0"
resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz"
integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==
@@ -1420,7 +1485,7 @@ eslint-module-utils@^2.7.4, eslint-module-utils@^2.8.0:
dependencies:
debug "^3.2.7"
-eslint-plugin-import@*, eslint-plugin-import@^2.25.2, eslint-plugin-import@^2.25.3, eslint-plugin-import@^2.29.1:
+eslint-plugin-import@^2.29.1:
version "2.29.1"
resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz"
integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==
@@ -1443,7 +1508,7 @@ eslint-plugin-import@*, eslint-plugin-import@^2.25.2, eslint-plugin-import@^2.25
semver "^6.3.1"
tsconfig-paths "^3.15.0"
-eslint-plugin-jsx-a11y@^6.5.1, eslint-plugin-jsx-a11y@^6.9.0:
+eslint-plugin-jsx-a11y@^6.9.0:
version "6.9.0"
resolved "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.9.0.tgz"
integrity sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g==
@@ -1482,12 +1547,12 @@ eslint-plugin-prettier@^5.2.1:
prettier-linter-helpers "^1.0.0"
synckit "^0.9.1"
-eslint-plugin-react-hooks@^4.3.0, eslint-plugin-react-hooks@^4.6.2:
+eslint-plugin-react-hooks@^4.6.2:
version "4.6.2"
resolved "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz"
integrity sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==
-eslint-plugin-react@^7.28.0, eslint-plugin-react@^7.35.0:
+eslint-plugin-react@^7.35.0:
version "7.35.0"
resolved "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.0.tgz"
integrity sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==
@@ -1536,7 +1601,7 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz"
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
-eslint@*, "eslint@^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7", "eslint@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^7.32.0 || ^8.2.0", eslint@^8.56.0, eslint@^8.57.0, eslint@>=7, eslint@>=7.0.0, eslint@>=8.0.0, eslint@8:
+eslint@^8.57.0:
version "8.57.0"
resolved "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz"
integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==
@@ -1691,6 +1756,11 @@ flatted@^3.1.0:
resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz"
integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==
+follow-redirects@^1.15.6:
+ version "1.15.9"
+ resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz"
+ integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==
+
for-each@^0.3.3:
version "0.3.3"
resolved "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz"
@@ -1698,6 +1768,29 @@ for-each@^0.3.3:
dependencies:
is-callable "^1.1.3"
+form-data@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz"
+ integrity sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.8"
+ mime-types "^2.1.12"
+
+formik@^2.4.6:
+ version "2.4.6"
+ resolved "https://registry.npmjs.org/formik/-/formik-2.4.6.tgz"
+ integrity sha512-A+2EI7U7aG296q2TLGvNapDNTZp1khVt5Vk0Q/fyfSROss0V/V6+txt2aJnwEos44IxTCW/LYAi/zgWzlevj+g==
+ dependencies:
+ "@types/hoist-non-react-statics" "^3.3.1"
+ deepmerge "^2.1.1"
+ hoist-non-react-statics "^3.3.0"
+ lodash "^4.17.21"
+ lodash-es "^4.17.21"
+ react-fast-compare "^2.0.1"
+ tiny-warning "^1.0.2"
+ tslib "^2.0.0"
+
fs-extra@^11.1.0:
version "11.1.1"
resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz"
@@ -1712,11 +1805,6 @@ fs.realpath@^1.0.0:
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
-fsevents@~2.3.2, fsevents@~2.3.3:
- version "2.3.3"
- resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz"
- integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
-
function-bind@^1.1.2:
version "1.1.2"
resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz"
@@ -1898,13 +1986,41 @@ history@^5.3.0:
dependencies:
"@babel/runtime" "^7.7.6"
-hoist-non-react-statics@^3.3.1:
+hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1:
version "3.3.2"
resolved "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
dependencies:
react-is "^16.7.0"
+html-parse-stringify@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz"
+ integrity sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==
+ dependencies:
+ void-elements "3.1.0"
+
+i18next-browser-languagedetector@^8.0.2:
+ version "8.0.2"
+ resolved "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.2.tgz"
+ integrity sha512-shBvPmnIyZeD2VU5jVGIOWP7u9qNG3Lj7mpaiPFpbJ3LVfHZJvVzKR4v1Cb91wAOFpNw442N+LGPzHOHsten2g==
+ dependencies:
+ "@babel/runtime" "^7.23.2"
+
+i18next-http-backend@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-3.0.1.tgz"
+ integrity sha512-XT2lYSkbAtDE55c6m7CtKxxrsfuRQO3rUfHzj8ZyRtY9CkIX3aRGwXGTkUhpGWce+J8n7sfu3J0f2wTzo7Lw0A==
+ dependencies:
+ cross-fetch "4.0.0"
+
+i18next@^24.2.0:
+ version "24.2.0"
+ resolved "https://registry.npmjs.org/i18next/-/i18next-24.2.0.tgz"
+ integrity sha512-ArJJTS1lV6lgKH7yEf4EpgNZ7+THl7bsGxxougPYiXRTJ/Fe1j08/TBpV9QsXCIYVfdE/HWG/xLezJ5DOlfBOA==
+ dependencies:
+ "@babel/runtime" "^7.23.2"
+
ignore@^5.2.0, ignore@^5.3.1:
version "5.3.2"
resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz"
@@ -2221,6 +2337,11 @@ jsonfile@^6.0.1:
object.assign "^4.1.4"
object.values "^1.1.6"
+jwt-decode@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz"
+ integrity sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==
+
language-subtag-registry@^0.3.20:
version "0.3.23"
resolved "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz"
@@ -2288,6 +2409,18 @@ micromatch@^4.0.4:
braces "^3.0.3"
picomatch "^2.3.1"
+mime-db@1.52.0:
+ version "1.52.0"
+ resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz"
+ integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
+
+mime-types@^2.1.12:
+ version "2.1.35"
+ resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz"
+ integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
+ dependencies:
+ mime-db "1.52.0"
+
minimatch@^3.0.4:
version "3.1.2"
resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz"
@@ -2334,9 +2467,9 @@ ms@^2.1.1, ms@2.1.2:
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
nanoid@^3.3.7:
- version "3.3.7"
- resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz"
- integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
+ version "3.3.8"
+ resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz"
+ integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==
natural-compare-lite@^1.4.0:
version "1.4.0"
@@ -2348,6 +2481,13 @@ natural-compare@^1.4.0:
resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz"
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
+node-fetch@^2.6.12:
+ version "2.7.0"
+ resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz"
+ integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
+ dependencies:
+ whatwg-url "^5.0.0"
+
normalize-path@^3.0.0, normalize-path@~3.0.0:
version "3.0.0"
resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz"
@@ -2438,7 +2578,7 @@ once@^1.3.0:
dependencies:
wrappy "1"
-optionator@^0.9.1, optionator@^0.9.3:
+optionator@^0.9.3:
version "0.9.3"
resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz"
integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==
@@ -2506,10 +2646,10 @@ path-type@^4.0.0:
resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz"
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
-picocolors@^1.0.0, picocolors@^1.0.1:
- version "1.0.1"
- resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz"
- integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==
+picocolors@^1.0.0, picocolors@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz"
+ integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==
picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
version "2.3.1"
@@ -2521,14 +2661,14 @@ possible-typed-array-names@^1.0.0:
resolved "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz"
integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==
-postcss@^8.4.41:
- version "8.4.41"
- resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz"
- integrity sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==
+postcss@^8.4.43:
+ version "8.4.49"
+ resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz"
+ integrity sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==
dependencies:
nanoid "^3.3.7"
- picocolors "^1.0.1"
- source-map-js "^1.2.0"
+ picocolors "^1.1.1"
+ source-map-js "^1.2.1"
prelude-ls@^1.2.1:
version "1.2.1"
@@ -2542,7 +2682,7 @@ prettier-linter-helpers@^1.0.0:
dependencies:
fast-diff "^1.1.2"
-prettier@^3.3.3, prettier@>=3.0.0:
+prettier@^3.3.3:
version "3.3.3"
resolved "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz"
integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==
@@ -2556,6 +2696,16 @@ prop-types@^15.6.2, prop-types@^15.8.1:
object-assign "^4.1.1"
react-is "^16.13.1"
+property-expr@^2.0.5:
+ version "2.0.6"
+ resolved "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz"
+ integrity sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==
+
+proxy-from-env@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz"
+ integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
+
punycode@^2.1.0:
version "2.3.1"
resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz"
@@ -2573,7 +2723,7 @@ react-apexcharts@^1.4.1:
dependencies:
prop-types "^15.8.1"
-"react-dom@^17.0.0 || ^18.0.0", react-dom@^18.3.1, react-dom@>=16.6.0, react-dom@>=16.8, react-dom@>=16.8.0:
+react-dom@^18.3.1:
version "18.3.1"
resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz"
integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==
@@ -2581,6 +2731,11 @@ react-apexcharts@^1.4.1:
loose-envify "^1.1.0"
scheduler "^0.23.2"
+react-fast-compare@^2.0.1:
+ version "2.0.4"
+ resolved "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz"
+ integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
+
react-fast-compare@^3.2.2:
version "3.2.2"
resolved "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz"
@@ -2595,6 +2750,22 @@ react-helmet-async@^2.0.5:
react-fast-compare "^3.2.2"
shallowequal "^1.1.0"
+react-i18next@^15.4.0:
+ version "15.4.0"
+ resolved "https://registry.npmjs.org/react-i18next/-/react-i18next-15.4.0.tgz"
+ integrity sha512-Py6UkX3zV08RTvL6ZANRoBh9sL/ne6rQq79XlkHEdd82cZr2H9usbWpUNVadJntIZP2pu3M2rL1CN+5rQYfYFw==
+ dependencies:
+ "@babel/runtime" "^7.25.0"
+ html-parse-stringify "^3.0.1"
+
+react-input-mask@^2.0.4:
+ version "2.0.4"
+ resolved "https://registry.npmjs.org/react-input-mask/-/react-input-mask-2.0.4.tgz"
+ integrity sha512-1hwzMr/aO9tXfiroiVCx5EtKohKwLk/NT8QlJXHQ4N+yJJFyUuMT+zfTpLBwX/lK3PkuMlievIffncpMZ3HGRQ==
+ dependencies:
+ invariant "^2.2.4"
+ warning "^4.0.2"
+
react-is@^16.13.1:
version "16.13.1"
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
@@ -2635,7 +2806,7 @@ react-transition-group@^4.4.5:
loose-envify "^1.4.0"
prop-types "^15.6.2"
-"react@^16.6.0 || ^17.0.0 || ^18.0.0", "react@^17.0.0 || ^18.0.0", react@^18.3.1, react@>=0.13, react@>=16, react@>=16.6.0, react@>=16.8, react@>=16.8.0:
+react@^18.3.1:
version "18.3.1"
resolved "https://registry.npmjs.org/react/-/react-18.3.1.tgz"
integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==
@@ -2718,28 +2889,31 @@ rimraf@^3.0.2:
glob "^7.1.3"
rollup@^4.20.0:
- version "4.21.0"
- resolved "https://registry.npmjs.org/rollup/-/rollup-4.21.0.tgz"
- integrity sha512-vo+S/lfA2lMS7rZ2Qoubi6I5hwZwzXeUIctILZLbHI+laNtvhhOIon2S1JksA5UEDQ7l3vberd0fxK44lTYjbQ==
+ version "4.29.1"
+ resolved "https://registry.npmjs.org/rollup/-/rollup-4.29.1.tgz"
+ integrity sha512-RaJ45M/kmJUzSWDs1Nnd5DdV4eerC98idtUOVr6FfKcgxqvjwHmxc5upLF9qZU9EpsVzzhleFahrT3shLuJzIw==
dependencies:
- "@types/estree" "1.0.5"
+ "@types/estree" "1.0.6"
optionalDependencies:
- "@rollup/rollup-android-arm-eabi" "4.21.0"
- "@rollup/rollup-android-arm64" "4.21.0"
- "@rollup/rollup-darwin-arm64" "4.21.0"
- "@rollup/rollup-darwin-x64" "4.21.0"
- "@rollup/rollup-linux-arm-gnueabihf" "4.21.0"
- "@rollup/rollup-linux-arm-musleabihf" "4.21.0"
- "@rollup/rollup-linux-arm64-gnu" "4.21.0"
- "@rollup/rollup-linux-arm64-musl" "4.21.0"
- "@rollup/rollup-linux-powerpc64le-gnu" "4.21.0"
- "@rollup/rollup-linux-riscv64-gnu" "4.21.0"
- "@rollup/rollup-linux-s390x-gnu" "4.21.0"
- "@rollup/rollup-linux-x64-gnu" "4.21.0"
- "@rollup/rollup-linux-x64-musl" "4.21.0"
- "@rollup/rollup-win32-arm64-msvc" "4.21.0"
- "@rollup/rollup-win32-ia32-msvc" "4.21.0"
- "@rollup/rollup-win32-x64-msvc" "4.21.0"
+ "@rollup/rollup-android-arm-eabi" "4.29.1"
+ "@rollup/rollup-android-arm64" "4.29.1"
+ "@rollup/rollup-darwin-arm64" "4.29.1"
+ "@rollup/rollup-darwin-x64" "4.29.1"
+ "@rollup/rollup-freebsd-arm64" "4.29.1"
+ "@rollup/rollup-freebsd-x64" "4.29.1"
+ "@rollup/rollup-linux-arm-gnueabihf" "4.29.1"
+ "@rollup/rollup-linux-arm-musleabihf" "4.29.1"
+ "@rollup/rollup-linux-arm64-gnu" "4.29.1"
+ "@rollup/rollup-linux-arm64-musl" "4.29.1"
+ "@rollup/rollup-linux-loongarch64-gnu" "4.29.1"
+ "@rollup/rollup-linux-powerpc64le-gnu" "4.29.1"
+ "@rollup/rollup-linux-riscv64-gnu" "4.29.1"
+ "@rollup/rollup-linux-s390x-gnu" "4.29.1"
+ "@rollup/rollup-linux-x64-gnu" "4.29.1"
+ "@rollup/rollup-linux-x64-musl" "4.29.1"
+ "@rollup/rollup-win32-arm64-msvc" "4.29.1"
+ "@rollup/rollup-win32-ia32-msvc" "4.29.1"
+ "@rollup/rollup-win32-x64-msvc" "4.29.1"
fsevents "~2.3.2"
run-parallel@^1.1.9:
@@ -2860,10 +3034,10 @@ slash@^3.0.0:
resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz"
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
-source-map-js@^1.2.0:
- version "1.2.0"
- resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz"
- integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==
+source-map-js@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz"
+ integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
source-map@^0.5.7:
version "0.5.7"
@@ -3053,11 +3227,21 @@ text-table@^0.2.0:
resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz"
integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==
+tiny-case@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz"
+ integrity sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==
+
tiny-invariant@^1.1.0:
version "1.3.1"
resolved "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz"
integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==
+tiny-warning@^1.0.2:
+ version "1.0.3"
+ resolved "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz"
+ integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
+
to-fast-properties@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz"
@@ -3070,6 +3254,16 @@ to-regex-range@^5.0.1:
dependencies:
is-number "^7.0.0"
+toposort@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz"
+ integrity sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==
+
+tr46@~0.0.3:
+ version "0.0.3"
+ resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz"
+ integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
+
ts-api-utils@^1.3.0:
version "1.3.0"
resolved "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz"
@@ -3085,7 +3279,7 @@ tsconfig-paths@^3.15.0:
minimist "^1.2.6"
strip-bom "^3.0.0"
-tslib@^2.6.2:
+tslib@^2.0.0, tslib@^2.6.2:
version "2.6.3"
resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz"
integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==
@@ -3107,6 +3301,11 @@ type-fest@^0.21.3:
resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz"
integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
+type-fest@^2.19.0:
+ version "2.19.0"
+ resolved "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz"
+ integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==
+
typed-array-buffer@^1.0.2:
version "1.0.2"
resolved "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz"
@@ -3151,7 +3350,7 @@ typed-array-length@^1.0.6:
is-typed-array "^1.1.13"
possible-typed-array-names "^1.0.0"
-typescript@*, typescript@^5.5.4, typescript@>=4.2.0:
+typescript@^5.5.4:
version "5.5.4"
resolved "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz"
integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==
@@ -3203,17 +3402,22 @@ vite-plugin-checker@^0.7.2:
vscode-languageserver-textdocument "^1.0.1"
vscode-uri "^3.0.2"
-"vite@^4 || ^5", vite@^5.4.2, vite@>=2.0.0:
- version "5.4.2"
- resolved "https://registry.npmjs.org/vite/-/vite-5.4.2.tgz"
- integrity sha512-dDrQTRHp5C1fTFzcSaMxjk6vdpKvT+2/mIdE07Gw2ykehT49O0z/VHS3zZ8iV/Gh8BJJKHWOe5RjaNrW5xf/GA==
+vite@^5.4.2:
+ version "5.4.11"
+ resolved "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz"
+ integrity sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==
dependencies:
esbuild "^0.21.3"
- postcss "^8.4.41"
+ postcss "^8.4.43"
rollup "^4.20.0"
optionalDependencies:
fsevents "~2.3.3"
+void-elements@3.1.0:
+ version "3.1.0"
+ resolved "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz"
+ integrity sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==
+
vscode-jsonrpc@6.0.0:
version "6.0.0"
resolved "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz"
@@ -3258,6 +3462,26 @@ vscode-uri@^3.0.2:
resolved "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz"
integrity sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==
+warning@^4.0.2:
+ version "4.0.3"
+ resolved "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz"
+ integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==
+ dependencies:
+ loose-envify "^1.0.0"
+
+webidl-conversions@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz"
+ integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
+
+whatwg-url@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz"
+ integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
+ dependencies:
+ tr46 "~0.0.3"
+ webidl-conversions "^3.0.0"
+
which-boxed-primitive@^1.0.2:
version "1.0.2"
resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz"
@@ -3329,3 +3553,13 @@ yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
+
+yup@^1.6.1:
+ version "1.6.1"
+ resolved "https://registry.npmjs.org/yup/-/yup-1.6.1.tgz"
+ integrity sha512-JED8pB50qbA4FOkDol0bYF/p60qSEDQqBD0/qeIrUCG1KbPBIQ776fCUNb9ldbPcSTxA69g/47XTo4TqWiuXOA==
+ dependencies:
+ property-expr "^2.0.5"
+ tiny-case "^1.0.3"
+ toposort "^2.0.2"
+ type-fest "^2.19.0"