recode and add editor config file
@@ -1,8 +1,12 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": ["./src/*"],
|
"@/*": [
|
||||||
"&/*": ["./public/*"],
|
"./src/*"
|
||||||
|
],
|
||||||
|
"&/*": [
|
||||||
|
"./public/*"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
|
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
reactStrictMode: true,
|
reactStrictMode: true,
|
||||||
i18n: {
|
i18n: {
|
||||||
defaultLocale: 'fa',
|
defaultLocale: 'fa',
|
||||||
locales: ['fa'],
|
locales: ['fa'],
|
||||||
localeDetection: false,
|
localeDetection: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = nextConfig
|
module.exports = nextConfig
|
||||||
|
|||||||
@@ -17,145 +17,153 @@ This set of fonts are used in this project under the license: (.....)
|
|||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: IRANSansFaNum;
|
font-family: IRANSansFaNum;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
src: url('./fonts/eot/IRANSansWeb(FaNum)_Black.eot');
|
src: url('./fonts/eot/IRANSansWeb(FaNum)_Black.eot');
|
||||||
src: url('./fonts/eot/IRANSansWeb(FaNum)_Black.eot?#iefix') format('embedded-opentype'),/* IE6-8 */
|
src: url('./fonts/eot/IRANSansWeb(FaNum)_Black.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
|
||||||
url('./fonts/woff2/IRANSansWeb(FaNum)_Black.woff2') format('woff2'),/* FF39+,Chrome36+, Opera24+*/
|
url('./fonts/woff2/IRANSansWeb(FaNum)_Black.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
|
||||||
url('./fonts/woff/IRANSansWeb(FaNum)_Black.woff') format('woff'),/* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
url('./fonts/woff/IRANSansWeb(FaNum)_Black.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
||||||
url('./fonts/ttf/IRANSansWeb(FaNum)_Black.ttf') format('truetype');
|
url('./fonts/ttf/IRANSansWeb(FaNum)_Black.ttf') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: IRANSansFaNum;
|
font-family: IRANSansFaNum;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
src: url('./fonts/eot/IRANSansWeb(FaNum)_Bold.eot');
|
src: url('./fonts/eot/IRANSansWeb(FaNum)_Bold.eot');
|
||||||
src: url('./fonts/eot/IRANSansWeb(FaNum)_Bold.eot?#iefix') format('embedded-opentype'),/* IE6-8 */
|
src: url('./fonts/eot/IRANSansWeb(FaNum)_Bold.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
|
||||||
url('./fonts/woff2/IRANSansWeb(FaNum)_Bold.woff2') format('woff2'),/* FF39+,Chrome36+, Opera24+*/
|
url('./fonts/woff2/IRANSansWeb(FaNum)_Bold.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
|
||||||
url('./fonts/woff/IRANSansWeb(FaNum)_Bold.woff') format('woff'),/* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
url('./fonts/woff/IRANSansWeb(FaNum)_Bold.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
||||||
url('./fonts/ttf/IRANSansWeb(FaNum)_Bold.ttf') format('truetype');
|
url('./fonts/ttf/IRANSansWeb(FaNum)_Bold.ttf') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: IRANSansFaNum;
|
font-family: IRANSansFaNum;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
src: url('./fonts/eot/IRANSansWeb(FaNum)_Medium.eot');
|
src: url('./fonts/eot/IRANSansWeb(FaNum)_Medium.eot');
|
||||||
src: url('./fonts/eot/IRANSansWeb(FaNum)_Medium.eot?#iefix') format('embedded-opentype'),/* IE6-8 */
|
src: url('./fonts/eot/IRANSansWeb(FaNum)_Medium.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
|
||||||
url('./fonts/woff2/IRANSansWeb(FaNum)_Medium.woff2') format('woff2'),/* FF39+,Chrome36+, Opera24+*/
|
url('./fonts/woff2/IRANSansWeb(FaNum)_Medium.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
|
||||||
url('./fonts/woff/IRANSansWeb(FaNum)_Medium.woff') format('woff'),/* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
url('./fonts/woff/IRANSansWeb(FaNum)_Medium.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
||||||
url('./fonts/ttf/IRANSansWeb(FaNum)_Medium.ttf') format('truetype');
|
url('./fonts/ttf/IRANSansWeb(FaNum)_Medium.ttf') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: IRANSansFaNum;
|
font-family: IRANSansFaNum;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
src: url('./fonts/eot/IRANSansWeb(FaNum)_Light.eot');
|
src: url('./fonts/eot/IRANSansWeb(FaNum)_Light.eot');
|
||||||
src: url('./fonts/eot/IRANSansWeb(FaNum)_Light.eot?#iefix') format('embedded-opentype'),/* IE6-8 */
|
src: url('./fonts/eot/IRANSansWeb(FaNum)_Light.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
|
||||||
url('./fonts/woff2/IRANSansWeb(FaNum)_Light.woff2') format('woff2'),/* FF39+,Chrome36+, Opera24+*/
|
url('./fonts/woff2/IRANSansWeb(FaNum)_Light.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
|
||||||
url('./fonts/woff/IRANSansWeb(FaNum)_Light.woff') format('woff'),/* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
url('./fonts/woff/IRANSansWeb(FaNum)_Light.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
||||||
url('./fonts/ttf/IRANSansWeb(FaNum)_Light.ttf') format('truetype');
|
url('./fonts/ttf/IRANSansWeb(FaNum)_Light.ttf') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: IRANSansFaNum;
|
font-family: IRANSansFaNum;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 200;
|
font-weight: 200;
|
||||||
src: url('./fonts/eot/IRANSansWeb(FaNum)_UltraLight.eot');
|
src: url('./fonts/eot/IRANSansWeb(FaNum)_UltraLight.eot');
|
||||||
src: url('./fonts/eot/IRANSansWeb(FaNum)_UltraLight.eot?#iefix') format('embedded-opentype'),/* IE6-8 */
|
src: url('./fonts/eot/IRANSansWeb(FaNum)_UltraLight.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
|
||||||
url('./fonts/woff2/IRANSansWeb(FaNum)_UltraLight.woff2') format('woff2'),/* FF39+,Chrome36+, Opera24+*/
|
url('./fonts/woff2/IRANSansWeb(FaNum)_UltraLight.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
|
||||||
url('./fonts/woff/IRANSansWeb(FaNum)_UltraLight.woff') format('woff'),/* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
url('./fonts/woff/IRANSansWeb(FaNum)_UltraLight.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
||||||
url('./fonts/ttf/IRANSansWeb(FaNum)_UltraLight.ttf') format('truetype');
|
url('./fonts/ttf/IRANSansWeb(FaNum)_UltraLight.ttf') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: IRANSansFaNum;
|
font-family: IRANSansFaNum;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
src: url('./fonts/eot/IRANSansWeb(FaNum).eot');
|
src: url('./fonts/eot/IRANSansWeb(FaNum).eot');
|
||||||
src: url('./fonts/eot/IRANSansWeb(FaNum).eot?#iefix') format('embedded-opentype'),/* IE6-8 */
|
src: url('./fonts/eot/IRANSansWeb(FaNum).eot?#iefix') format('embedded-opentype'), /* IE6-8 */
|
||||||
url('./fonts/woff2/IRANSansWeb(FaNum).woff2') format('woff2'),/* FF39+,Chrome36+, Opera24+*/
|
url('./fonts/woff2/IRANSansWeb(FaNum).woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
|
||||||
url('./fonts/woff/IRANSansWeb(FaNum).woff') format('woff'),/* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
url('./fonts/woff/IRANSansWeb(FaNum).woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
||||||
url('./fonts/ttf/IRANSansWeb(FaNum).ttf') format('truetype');
|
url('./fonts/ttf/IRANSansWeb(FaNum).ttf') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: IRANSans;
|
font-family: IRANSans;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
src: url('./fonts/eot/IRANSansWeb_Black.eot');
|
src: url('./fonts/eot/IRANSansWeb_Black.eot');
|
||||||
src: url('./fonts/eot/IRANSansWeb_Black.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
|
src: url('./fonts/eot/IRANSansWeb_Black.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
|
||||||
url('./fonts/woff2/IRANSansWeb_Black.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
|
url('./fonts/woff2/IRANSansWeb_Black.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
|
||||||
url('./fonts/woff/IRANSansWeb_Black.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
url('./fonts/woff/IRANSansWeb_Black.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
||||||
url('./fonts/ttf/IRANSansWeb_Black.ttf') format('truetype');
|
url('./fonts/ttf/IRANSansWeb_Black.ttf') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: IRANSans;
|
font-family: IRANSans;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
src: url('./fonts/eot/IRANSansWeb_Bold.eot');
|
src: url('./fonts/eot/IRANSansWeb_Bold.eot');
|
||||||
src: url('./fonts/eot/IRANSansWeb_Bold.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
|
src: url('./fonts/eot/IRANSansWeb_Bold.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
|
||||||
url('./fonts/woff2/IRANSansWeb_Bold.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
|
url('./fonts/woff2/IRANSansWeb_Bold.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
|
||||||
url('./fonts/woff/IRANSansWeb_Bold.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
url('./fonts/woff/IRANSansWeb_Bold.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
||||||
url('./fonts/ttf/IRANSansWeb_Bold.ttf') format('truetype');
|
url('./fonts/ttf/IRANSansWeb_Bold.ttf') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: IRANSans;
|
font-family: IRANSans;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
src: url('./fonts/eot/IRANSansWeb_Medium.eot');
|
src: url('./fonts/eot/IRANSansWeb_Medium.eot');
|
||||||
src: url('./fonts/eot/IRANSansWeb_Medium.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
|
src: url('./fonts/eot/IRANSansWeb_Medium.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
|
||||||
url('./fonts/woff2/IRANSansWeb_Medium.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
|
url('./fonts/woff2/IRANSansWeb_Medium.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
|
||||||
url('./fonts/woff/IRANSansWeb_Medium.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
url('./fonts/woff/IRANSansWeb_Medium.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
||||||
url('./fonts/ttf/IRANSansWeb_Medium.ttf') format('truetype');
|
url('./fonts/ttf/IRANSansWeb_Medium.ttf') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: IRANSans;
|
font-family: IRANSans;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
src: url('./fonts/eot/IRANSansWeb_Light.eot');
|
src: url('./fonts/eot/IRANSansWeb_Light.eot');
|
||||||
src: url('./fonts/eot/IRANSansWeb_Light.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
|
src: url('./fonts/eot/IRANSansWeb_Light.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
|
||||||
url('./fonts/woff2/IRANSansWeb_Light.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
|
url('./fonts/woff2/IRANSansWeb_Light.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
|
||||||
url('./fonts/woff/IRANSansWeb_Light.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
url('./fonts/woff/IRANSansWeb_Light.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
||||||
url('./fonts/ttf/IRANSansWeb_Light.ttf') format('truetype');
|
url('./fonts/ttf/IRANSansWeb_Light.ttf') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: IRANSans;
|
font-family: IRANSans;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 200;
|
font-weight: 200;
|
||||||
src: url('./fonts/eot/IRANSansWeb_UltraLight.eot');
|
src: url('./fonts/eot/IRANSansWeb_UltraLight.eot');
|
||||||
src: url('./fonts/eot/IRANSansWeb_UltraLight.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
|
src: url('./fonts/eot/IRANSansWeb_UltraLight.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
|
||||||
url('./fonts/woff2/IRANSansWeb_UltraLight.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
|
url('./fonts/woff2/IRANSansWeb_UltraLight.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
|
||||||
url('./fonts/woff/IRANSansWeb_UltraLight.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
url('./fonts/woff/IRANSansWeb_UltraLight.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
||||||
url('./fonts/ttf/IRANSansWeb_UltraLight.ttf') format('truetype');
|
url('./fonts/ttf/IRANSansWeb_UltraLight.ttf') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: IRANSans;
|
font-family: IRANSans;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
src: url('./fonts/eot/IRANSansWeb.eot');
|
src: url('./fonts/eot/IRANSansWeb.eot');
|
||||||
src: url('./fonts/eot/IRANSansWeb.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
|
src: url('./fonts/eot/IRANSansWeb.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
|
||||||
url('./fonts/woff2/IRANSansWeb.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
|
url('./fonts/woff2/IRANSansWeb.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
|
||||||
url('./fonts/woff/IRANSansWeb.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
url('./fonts/woff/IRANSansWeb.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
||||||
url('./fonts/ttf/IRANSansWeb.ttf') format('truetype');
|
url('./fonts/ttf/IRANSansWeb.ttf') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: Parastoo;
|
font-family: Parastoo;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
src: url('./fonts/eot/Parastoo.eot');
|
src: url('./fonts/eot/Parastoo.eot');
|
||||||
src: url('./fonts/eot/Parastoo.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
|
src: url('./fonts/eot/Parastoo.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
|
||||||
url('./fonts/woff/Parastoo.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
url('./fonts/woff/Parastoo.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
||||||
url('./fonts/ttf/Parastoo.ttf') format('truetype');
|
url('./fonts/ttf/Parastoo.ttf') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: Parastoo;
|
font-family: Parastoo;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
src: url('./fonts/eot/Parastoo-Bold.eot');
|
src: url('./fonts/eot/Parastoo-Bold.eot');
|
||||||
src: url('./fonts/eot/Parastoo-Bold.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
|
src: url('./fonts/eot/Parastoo-Bold.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
|
||||||
url('./fonts/woff/Parastoo-Bold.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
url('./fonts/woff/Parastoo-Bold.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
||||||
url('./fonts/ttf/Parastoo-Bold.ttf') format('truetype');
|
url('./fonts/ttf/Parastoo-Bold.ttf') format('truetype');
|
||||||
}
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.5 KiB |
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.5 KiB |
@@ -1,10 +1,19 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="611.781" height="634.738" viewBox="0 0 611.781 634.738">
|
<svg xmlns="http://www.w3.org/2000/svg" width="611.781" height="634.738" viewBox="0 0 611.781 634.738">
|
||||||
<g id="Group_67" data-name="Group 67" transform="translate(17717.998 5548)">
|
<g id="Group_67" data-name="Group 67" transform="translate(17717.998 5548)">
|
||||||
<g id="Group_35" data-name="Group 35" transform="translate(-18337.291 -5635.72)">
|
<g id="Group_35" data-name="Group 35" transform="translate(-18337.291 -5635.72)">
|
||||||
<path id="Path_5" data-name="Path 5" d="M126.892,461.042c-1.676-6.24-3.057-12-4.776-17.668-6.5-21.426-17.146-40.936-27.846-60.456-10.362-18.9-20.22-38.081-30.31-57.132-.389-.734-.9-1.406-1.791-2.8C36.884,364.062,18.983,407.918,1.474,451.962l-1.21-.256a8.878,8.878,0,0,1-.214-2.524c2.581-12.372,4.479-24.951,8.05-37.034a334.761,334.761,0,0,1,13.91-37.364Q35.923,342.5,51.02,310.733c3.525-7.389,1.922-13.976.051-20.991a185.716,185.716,0,0,1-6.18-54.9,183.572,183.572,0,0,1,21.089-78.7A248.249,248.249,0,0,1,132.8,75.26a320,320,0,0,1,59.11-36.67c23.209-11.317,47.033-21.1,72.336-26.513A487.808,487.808,0,0,1,314.282,3.7C333.731,1.624,353.352,1.16,372.9.018a22,22,0,0,1,3.3.145c.4.037.775.291,1.236,1.13L360.926,4.642c-26.4,5.318-52.988,9.831-79.147,16.136a295.335,295.335,0,0,0-105.32,48.21c-24.648,17.9-45.935,39.123-61.823,65.3-11.419,18.813-17.813,39.38-20.064,61.275-1.445,14.062-1.024,28.1.166,42.133a44.216,44.216,0,0,0,1,4.8c1.418-1.165,2.427-1.875,3.3-2.728,10.2-10.038,20.041-20.48,30.661-30.055,14.1-12.713,29.419-23.882,46.9-31.678,21.42-9.55,43.69-13.568,66.553-6.9,10.553,3.079,20.531,8.393,30.44,13.353,20.075,10.051,39.841,20.721,59.892,30.821a182.512,182.512,0,0,0,68.478,19.421c33.07,2.549,64.407-3.894,93.662-19.748,25.04-13.571,46.544-31.674,66.252-52.041,15.44-15.956,28.916-33.487,41.494-51.746,2.217-3.219,4.962-6.073,7.463-9.1l.983.382a15.039,15.039,0,0,1-.828,3.67c-3.9,7.643-7.67,15.361-11.911,22.812-17.8,31.272-39.019,60-64.85,85.13-26.732,26.009-56.556,47.619-90.953,62.526a162.5,162.5,0,0,1-74.241,14.106c-24.876-.775-48.015,5.5-69.742,17.063-14.861,7.91-29.333,16.559-43.879,25.049-13.773,8.039-28.189,13.431-44.484,11.949-2.667-.242-2.49,1.854-2.988,3.479-2.151,7.019-3.92,14.193-6.627,20.993-3.8,9.547-10.327,17.4-17.557,24.572-15.526,15.4-28.738,32.778-42.59,49.608-4.68,5.687-9.284,11.436-14.28,17.6M284.4,266.987c-.334-.819-.375-1.206-.591-1.393a13.8,13.8,0,0,0-1.854-1.356c-22.793-13.885-46.277-26.286-71.807-34.532-20.915-6.755-41.455-6.841-61.848,1.941-15.741,6.779-28.925,17.112-41,29.01-5.591,5.508-5.981,8.93-2.421,15.921q12.355,24.272,24.657,48.572c10.087,19.93,20.125,39.886,30.279,59.783.543,1.062,1.967,1.674,2.98,2.5a12.859,12.859,0,0,0,1.933-3.081,49.022,49.022,0,0,0-2.4-33.292c-6.476-14.911-14.075-29.337-21.275-43.93-4.967-10.065-10.144-20.026-15.07-30.112-1.63-3.338-2.558-6.917.574-10.1,10.226-10.371,22.1-18.1,36.115-22.335,3.993-1.206,5.77-.416,7.975,3.16,3.927,6.365,7.687,12.846,11.888,19.028,9.727,14.31,23.437,21.051,40.7,20.974,16.93-.075,32.491-5.033,47.273-12.854,4.715-2.495,9.282-5.27,13.894-7.9" transform="translate(619.257 87.713)" fill="#231955"/>
|
<path id="Path_5" data-name="Path 5"
|
||||||
<path id="Path_6" data-name="Path 6" d="M104.479,767.41c2.322-11.049,4.27-22.193,7.046-33.127,5.72-22.532,15.277-43.572,26.263-63.957,16.423-30.474,34.631-59.844,55.63-87.405,20.939-27.481,43.511-53.464,70.53-75.261,24.13-19.467,50.887-33.842,81.027-41.582,4.676-1.2,9.437-2.118,14.2-2.939a15,15,0,0,0,11.744-9.6c4.286-10.252,11.9-14.085,22.732-13.761a202.3,202.3,0,0,0,89.232-17.644A257.328,257.328,0,0,0,528.458,395.6c1.4-1.009,2.885-1.912,5.222-3.451-.953,3.026-1.265,5.258-2.293,7.089-14.936,26.6-31.633,51.891-54.057,72.956-18.879,17.734-40.265,31.046-65.744,36.862-15.1,3.446-30.348,6.253-45.529,9.349-18.622,3.8-37.406,6.945-55.825,11.553-27.566,6.9-51.782,20.673-73.654,38.685-23.608,19.441-42.473,43.054-59.8,68-24.96,35.939-44.814,74.717-63.24,114.278q-3.9,8.368-7.793,16.738l-1.263-.245" transform="translate(583.845 -45.198)" fill="#231955"/>
|
d="M126.892,461.042c-1.676-6.24-3.057-12-4.776-17.668-6.5-21.426-17.146-40.936-27.846-60.456-10.362-18.9-20.22-38.081-30.31-57.132-.389-.734-.9-1.406-1.791-2.8C36.884,364.062,18.983,407.918,1.474,451.962l-1.21-.256a8.878,8.878,0,0,1-.214-2.524c2.581-12.372,4.479-24.951,8.05-37.034a334.761,334.761,0,0,1,13.91-37.364Q35.923,342.5,51.02,310.733c3.525-7.389,1.922-13.976.051-20.991a185.716,185.716,0,0,1-6.18-54.9,183.572,183.572,0,0,1,21.089-78.7A248.249,248.249,0,0,1,132.8,75.26a320,320,0,0,1,59.11-36.67c23.209-11.317,47.033-21.1,72.336-26.513A487.808,487.808,0,0,1,314.282,3.7C333.731,1.624,353.352,1.16,372.9.018a22,22,0,0,1,3.3.145c.4.037.775.291,1.236,1.13L360.926,4.642c-26.4,5.318-52.988,9.831-79.147,16.136a295.335,295.335,0,0,0-105.32,48.21c-24.648,17.9-45.935,39.123-61.823,65.3-11.419,18.813-17.813,39.38-20.064,61.275-1.445,14.062-1.024,28.1.166,42.133a44.216,44.216,0,0,0,1,4.8c1.418-1.165,2.427-1.875,3.3-2.728,10.2-10.038,20.041-20.48,30.661-30.055,14.1-12.713,29.419-23.882,46.9-31.678,21.42-9.55,43.69-13.568,66.553-6.9,10.553,3.079,20.531,8.393,30.44,13.353,20.075,10.051,39.841,20.721,59.892,30.821a182.512,182.512,0,0,0,68.478,19.421c33.07,2.549,64.407-3.894,93.662-19.748,25.04-13.571,46.544-31.674,66.252-52.041,15.44-15.956,28.916-33.487,41.494-51.746,2.217-3.219,4.962-6.073,7.463-9.1l.983.382a15.039,15.039,0,0,1-.828,3.67c-3.9,7.643-7.67,15.361-11.911,22.812-17.8,31.272-39.019,60-64.85,85.13-26.732,26.009-56.556,47.619-90.953,62.526a162.5,162.5,0,0,1-74.241,14.106c-24.876-.775-48.015,5.5-69.742,17.063-14.861,7.91-29.333,16.559-43.879,25.049-13.773,8.039-28.189,13.431-44.484,11.949-2.667-.242-2.49,1.854-2.988,3.479-2.151,7.019-3.92,14.193-6.627,20.993-3.8,9.547-10.327,17.4-17.557,24.572-15.526,15.4-28.738,32.778-42.59,49.608-4.68,5.687-9.284,11.436-14.28,17.6M284.4,266.987c-.334-.819-.375-1.206-.591-1.393a13.8,13.8,0,0,0-1.854-1.356c-22.793-13.885-46.277-26.286-71.807-34.532-20.915-6.755-41.455-6.841-61.848,1.941-15.741,6.779-28.925,17.112-41,29.01-5.591,5.508-5.981,8.93-2.421,15.921q12.355,24.272,24.657,48.572c10.087,19.93,20.125,39.886,30.279,59.783.543,1.062,1.967,1.674,2.98,2.5a12.859,12.859,0,0,0,1.933-3.081,49.022,49.022,0,0,0-2.4-33.292c-6.476-14.911-14.075-29.337-21.275-43.93-4.967-10.065-10.144-20.026-15.07-30.112-1.63-3.338-2.558-6.917.574-10.1,10.226-10.371,22.1-18.1,36.115-22.335,3.993-1.206,5.77-.416,7.975,3.16,3.927,6.365,7.687,12.846,11.888,19.028,9.727,14.31,23.437,21.051,40.7,20.974,16.93-.075,32.491-5.033,47.273-12.854,4.715-2.495,9.282-5.27,13.894-7.9"
|
||||||
<path id="Path_7" data-name="Path 7" d="M405.392,690.855l-53.546,54.494-55.389-51.215,55.1-53.062L405.4,690.854" transform="translate(518.777 -129.57)" fill="#ff9100"/>
|
transform="translate(619.257 87.713)" fill="#231955"/>
|
||||||
|
<path id="Path_6" data-name="Path 6"
|
||||||
|
d="M104.479,767.41c2.322-11.049,4.27-22.193,7.046-33.127,5.72-22.532,15.277-43.572,26.263-63.957,16.423-30.474,34.631-59.844,55.63-87.405,20.939-27.481,43.511-53.464,70.53-75.261,24.13-19.467,50.887-33.842,81.027-41.582,4.676-1.2,9.437-2.118,14.2-2.939a15,15,0,0,0,11.744-9.6c4.286-10.252,11.9-14.085,22.732-13.761a202.3,202.3,0,0,0,89.232-17.644A257.328,257.328,0,0,0,528.458,395.6c1.4-1.009,2.885-1.912,5.222-3.451-.953,3.026-1.265,5.258-2.293,7.089-14.936,26.6-31.633,51.891-54.057,72.956-18.879,17.734-40.265,31.046-65.744,36.862-15.1,3.446-30.348,6.253-45.529,9.349-18.622,3.8-37.406,6.945-55.825,11.553-27.566,6.9-51.782,20.673-73.654,38.685-23.608,19.441-42.473,43.054-59.8,68-24.96,35.939-44.814,74.717-63.24,114.278q-3.9,8.368-7.793,16.738l-1.263-.245"
|
||||||
|
transform="translate(583.845 -45.198)" fill="#231955"/>
|
||||||
|
<path id="Path_7" data-name="Path 7"
|
||||||
|
d="M405.392,690.855l-53.546,54.494-55.389-51.215,55.1-53.062L405.4,690.854"
|
||||||
|
transform="translate(518.777 -129.57)" fill="#ff9100"/>
|
||||||
|
</g>
|
||||||
|
<text id="MARHABA" transform="translate(-17322 -4931)" fill="#bcbcbc" font-size="50"
|
||||||
|
font-family="Montserrat-ExtraBold, Montserrat" font-weight="800">
|
||||||
|
<tspan x="-281.35" y="0">MARHABA</tspan>
|
||||||
|
</text>
|
||||||
</g>
|
</g>
|
||||||
<text id="MARHABA" transform="translate(-17322 -4931)" fill="#bcbcbc" font-size="50" font-family="Montserrat-ExtraBold, Montserrat" font-weight="800"><tspan x="-281.35" y="0">MARHABA</tspan></text>
|
|
||||||
</g>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.2 KiB |
@@ -1,92 +1,92 @@
|
|||||||
export const FA_DATATABLE_LOCALIZATION = {
|
export const FA_DATATABLE_LOCALIZATION = {
|
||||||
actions: "عملیات",
|
actions: "عملیات",
|
||||||
and: "و",
|
and: "و",
|
||||||
cancel: "لغو",
|
cancel: "لغو",
|
||||||
changeFilterMode: "تغییر حالت فیلتر",
|
changeFilterMode: "تغییر حالت فیلتر",
|
||||||
changeSearchMode: "تغییر حالت جستجو",
|
changeSearchMode: "تغییر حالت جستجو",
|
||||||
clearFilter: "پاک کردن فیلتر",
|
clearFilter: "پاک کردن فیلتر",
|
||||||
clearSearch: "پاک کردن جستجو",
|
clearSearch: "پاک کردن جستجو",
|
||||||
clearSort: "پاک کردن مرتب سازی",
|
clearSort: "پاک کردن مرتب سازی",
|
||||||
clickToCopy: "کلیک برای کپی",
|
clickToCopy: "کلیک برای کپی",
|
||||||
collapse: "جمع شدن",
|
collapse: "جمع شدن",
|
||||||
collapseAll: "جمع شدن همه",
|
collapseAll: "جمع شدن همه",
|
||||||
columnActions: "عملیات ستون",
|
columnActions: "عملیات ستون",
|
||||||
copiedToClipboard: "کپی شد",
|
copiedToClipboard: "کپی شد",
|
||||||
dropToGroupBy: "رها کردن برای گروه بندی بر اساس {column}",
|
dropToGroupBy: "رها کردن برای گروه بندی بر اساس {column}",
|
||||||
edit: "ویرایش",
|
edit: "ویرایش",
|
||||||
expand: "باز شدن",
|
expand: "باز شدن",
|
||||||
expandAll: "باز شدن همه",
|
expandAll: "باز شدن همه",
|
||||||
filterArrIncludes: "شامل",
|
filterArrIncludes: "شامل",
|
||||||
filterArrIncludesAll: "شامل همه",
|
filterArrIncludesAll: "شامل همه",
|
||||||
filterArrIncludesSome: "شامل",
|
filterArrIncludesSome: "شامل",
|
||||||
filterBetween: "میان",
|
filterBetween: "میان",
|
||||||
filterBetweenInclusive: "میان با احتساب هر دو",
|
filterBetweenInclusive: "میان با احتساب هر دو",
|
||||||
filterByColumn: "فیلتر بر اساس {column}",
|
filterByColumn: "فیلتر بر اساس {column}",
|
||||||
filterContains: "شامل",
|
filterContains: "شامل",
|
||||||
filterEmpty: "خالی",
|
filterEmpty: "خالی",
|
||||||
filterEndsWith: "به پایان میرسد با",
|
filterEndsWith: "به پایان میرسد با",
|
||||||
filterEquals: "برابر",
|
filterEquals: "برابر",
|
||||||
filterEqualsString: "برابر",
|
filterEqualsString: "برابر",
|
||||||
filterFuzzy: "نزدیک",
|
filterFuzzy: "نزدیک",
|
||||||
filterGreaterThan: "بزرگتر از",
|
filterGreaterThan: "بزرگتر از",
|
||||||
filterGreaterThanOrEqualTo: "بزرگتر یا مساوی",
|
filterGreaterThanOrEqualTo: "بزرگتر یا مساوی",
|
||||||
filterInNumberRange: "میان",
|
filterInNumberRange: "میان",
|
||||||
filterIncludesString: "شامل",
|
filterIncludesString: "شامل",
|
||||||
filterIncludesStringSensitive: "شامل",
|
filterIncludesStringSensitive: "شامل",
|
||||||
filterLessThan: "کوچکتر از",
|
filterLessThan: "کوچکتر از",
|
||||||
filterLessThanOrEqualTo: "کوچکتر یا مساوی",
|
filterLessThanOrEqualTo: "کوچکتر یا مساوی",
|
||||||
filterMode: "حالت فیلتر: {filterType}",
|
filterMode: "حالت فیلتر: {filterType}",
|
||||||
filterNotEmpty: "غیر خالی",
|
filterNotEmpty: "غیر خالی",
|
||||||
filterNotEquals: "نا برابر",
|
filterNotEquals: "نا برابر",
|
||||||
filterStartsWith: "شروع میشود با",
|
filterStartsWith: "شروع میشود با",
|
||||||
filterWeakEquals: "برابر",
|
filterWeakEquals: "برابر",
|
||||||
filteringByColumn: "فیلتر بر اساس {column} - {filterType} {filterValue}",
|
filteringByColumn: "فیلتر بر اساس {column} - {filterType} {filterValue}",
|
||||||
goToFirstPage: "رفتن به صفحه اول",
|
goToFirstPage: "رفتن به صفحه اول",
|
||||||
goToLastPage: "رفتن به صفحه آخر",
|
goToLastPage: "رفتن به صفحه آخر",
|
||||||
goToNextPage: "رفتن به صفحه بعدی",
|
goToNextPage: "رفتن به صفحه بعدی",
|
||||||
goToPreviousPage: "رفتن به صفحه قبلی",
|
goToPreviousPage: "رفتن به صفحه قبلی",
|
||||||
grab: "گرفتن",
|
grab: "گرفتن",
|
||||||
groupByColumn: "گروه بندی بر اساس {column}",
|
groupByColumn: "گروه بندی بر اساس {column}",
|
||||||
groupedBy: "گروه بندی شده بر اساس",
|
groupedBy: "گروه بندی شده بر اساس",
|
||||||
hideAll: "پنهان کردن همه",
|
hideAll: "پنهان کردن همه",
|
||||||
hideColumn: "پنهان کردن ستون {column}",
|
hideColumn: "پنهان کردن ستون {column}",
|
||||||
max: "حداکثر",
|
max: "حداکثر",
|
||||||
min: "حداقل",
|
min: "حداقل",
|
||||||
move: "انتقال",
|
move: "انتقال",
|
||||||
noRecordsToDisplay: "هیچ رکوردی برای نمایش وجود ندارد",
|
noRecordsToDisplay: "هیچ رکوردی برای نمایش وجود ندارد",
|
||||||
noResultsFound: "نتیجهای یافت نشد",
|
noResultsFound: "نتیجهای یافت نشد",
|
||||||
of: "از",
|
of: "از",
|
||||||
or: "یا",
|
or: "یا",
|
||||||
pinToLeft: "چسباندن به سمت چپ",
|
pinToLeft: "چسباندن به سمت چپ",
|
||||||
pinToRight: "چسباندن به سمت راست",
|
pinToRight: "چسباندن به سمت راست",
|
||||||
resetColumnSize: "بازنشانی اندازه ستون",
|
resetColumnSize: "بازنشانی اندازه ستون",
|
||||||
resetOrder: "بازنشانی ترتیب",
|
resetOrder: "بازنشانی ترتیب",
|
||||||
rowActions: "عملیات ردیف",
|
rowActions: "عملیات ردیف",
|
||||||
rowNumber: "#",
|
rowNumber: "#",
|
||||||
rowNumbers: "شماره ردیف",
|
rowNumbers: "شماره ردیف",
|
||||||
rowsPerPage: "ردیف در هر صفحه",
|
rowsPerPage: "ردیف در هر صفحه",
|
||||||
save: "ذخیره",
|
save: "ذخیره",
|
||||||
search: "جستجو",
|
search: "جستجو",
|
||||||
selectedCountOfRowCountRowsSelected:
|
selectedCountOfRowCountRowsSelected:
|
||||||
"{selectedCount} از {rowCount} ردیف انتخاب شده",
|
"{selectedCount} از {rowCount} ردیف انتخاب شده",
|
||||||
select: "انتخاب",
|
select: "انتخاب",
|
||||||
showAll: "نمایش همه",
|
showAll: "نمایش همه",
|
||||||
showAllColumns: "نمایش همه ستونها",
|
showAllColumns: "نمایش همه ستونها",
|
||||||
showHideColumns: "نمایش/مخفی کردن ستونها",
|
showHideColumns: "نمایش/مخفی کردن ستونها",
|
||||||
showHideFilters: "نمایش/مخفی کردن فیلترها",
|
showHideFilters: "نمایش/مخفی کردن فیلترها",
|
||||||
showHideSearch: "نمایش/مخفی کردن جستجو",
|
showHideSearch: "نمایش/مخفی کردن جستجو",
|
||||||
sortByColumnAsc: "مرتب سازی بر اساس {column} صعودی",
|
sortByColumnAsc: "مرتب سازی بر اساس {column} صعودی",
|
||||||
sortByColumnDesc: "مرتب سازی بر اساس {column} نزولی",
|
sortByColumnDesc: "مرتب سازی بر اساس {column} نزولی",
|
||||||
sortedByColumnAsc: "مرتب شده بر اساس {column} صعودی",
|
sortedByColumnAsc: "مرتب شده بر اساس {column} صعودی",
|
||||||
sortedByColumnDesc: "مرتب شده بر اساس {column} نزولی",
|
sortedByColumnDesc: "مرتب شده بر اساس {column} نزولی",
|
||||||
thenBy: "، سپس بر اساس ",
|
thenBy: "، سپس بر اساس ",
|
||||||
toggleDensity: "تغییر تراکم",
|
toggleDensity: "تغییر تراکم",
|
||||||
toggleFullScreen: "تغییر حالت تمام صفحه",
|
toggleFullScreen: "تغییر حالت تمام صفحه",
|
||||||
toggleSelectAll: "انتخاب/عدم انتخاب همه",
|
toggleSelectAll: "انتخاب/عدم انتخاب همه",
|
||||||
toggleSelectRow: "انتخاب/عدم انتخاب ردیف",
|
toggleSelectRow: "انتخاب/عدم انتخاب ردیف",
|
||||||
toggleVisibility: "تغییر پیدا/پنهان",
|
toggleVisibility: "تغییر پیدا/پنهان",
|
||||||
ungroupByColumn: "لغو گروه بندی بر اساس {column}",
|
ungroupByColumn: "لغو گروه بندی بر اساس {column}",
|
||||||
unpin: "رها کردن",
|
unpin: "رها کردن",
|
||||||
unpinAll: "رها کردن همه",
|
unpinAll: "رها کردن همه",
|
||||||
unsorted: "بدون مرتب سازی",
|
unsorted: "بدون مرتب سازی",
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,184 +1,177 @@
|
|||||||
import CenterLayout from "@/layouts/CenterLayout";
|
import CenterLayout from "@/layouts/CenterLayout";
|
||||||
import DashboardLayouts from "@/layouts/dashboardLayouts";
|
import DashboardLayouts from "@/layouts/dashboardLayouts";
|
||||||
import {
|
import {Box, Button, Container, Paper, Stack, Typography,} from "@mui/material";
|
||||||
Button,
|
|
||||||
Typography,
|
|
||||||
Stack,
|
|
||||||
Paper,
|
|
||||||
Container,
|
|
||||||
Box,
|
|
||||||
} from "@mui/material";
|
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { Formik } from "formik";
|
import {Formik} from "formik";
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import PasswordField from "@/core/components/PasswordField";
|
import PasswordField from "@/core/components/PasswordField";
|
||||||
import StyledForm from "@/core/components/StyledForm";
|
import StyledForm from "@/core/components/StyledForm";
|
||||||
import { CHANGE_PASSWORD } from "@/core/data/apiRoutes";
|
import {CHANGE_PASSWORD} from "@/core/data/apiRoutes";
|
||||||
import useUser from "@/lib/app/hooks/useUser";
|
import useUser from "@/lib/app/hooks/useUser";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import Notifications from "@/core/components/notifications";
|
import Notifications from "@/core/components/notifications";
|
||||||
import useDirection from "@/lib/app/hooks/useDirection";
|
import useDirection from "@/lib/app/hooks/useDirection";
|
||||||
import { toast } from "react-toastify";
|
import {toast} from "react-toastify";
|
||||||
|
|
||||||
const DashboardChangePasswordComponent = () => {
|
const DashboardChangePasswordComponent = () => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const { token } = useUser();
|
const {token} = useUser();
|
||||||
const { directionApp } = useDirection();
|
const {directionApp} = useDirection();
|
||||||
|
|
||||||
const handleSubmit = (values, { setSubmitting, resetForm }) => {
|
const handleSubmit = (values, {setSubmitting, resetForm}) => {
|
||||||
toast.dismiss();
|
toast.dismiss();
|
||||||
const pendingToast = toast(t("notifications.pending"), {
|
const pendingToast = toast(t("notifications.pending"), {
|
||||||
position: directionApp === "ltr" ? "top-left" : "top-right",
|
position: directionApp === "ltr" ? "top-left" : "top-right",
|
||||||
autoClose: false,
|
autoClose: false,
|
||||||
closeOnClick: false,
|
closeOnClick: false,
|
||||||
draggable: false,
|
draggable: false,
|
||||||
|
});
|
||||||
|
axios
|
||||||
|
.post(
|
||||||
|
CHANGE_PASSWORD,
|
||||||
|
{
|
||||||
|
current_password: values.current_password,
|
||||||
|
new_password: values.new_password,
|
||||||
|
new_password_confirmation: values.new_password_confirmation,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {authorization: `Bearer ${token}`},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
toast.dismiss(pendingToast); // Dismiss the pending toast notification
|
||||||
|
Notifications(directionApp, response, t);
|
||||||
|
resetForm();
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
toast.dismiss(pendingToast); // Dismiss the pending toast notification
|
||||||
|
Notifications(directionApp, error.response, t);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setSubmitting(false); // Set `setSubmitting` to false after the API request completes
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const initialValues = {
|
||||||
|
current_password: "",
|
||||||
|
new_password: "",
|
||||||
|
new_password_confirmation: "",
|
||||||
|
};
|
||||||
|
const validationSchema = Yup.object().shape({
|
||||||
|
current_password: Yup.string().required(
|
||||||
|
t("ChangePassword.error_message_required")
|
||||||
|
),
|
||||||
|
new_password: Yup.string()
|
||||||
|
.min(8, t("ChangePassword.error_message_password_length"))
|
||||||
|
.required(t("ChangePassword.error_message_required")),
|
||||||
|
new_password_confirmation: Yup.string()
|
||||||
|
.required(t("ChangePassword.error_message_required"))
|
||||||
|
.test(
|
||||||
|
t("ChangePassword.error_message_password_match"),
|
||||||
|
t("ChangePassword.error_message_password_not_match"),
|
||||||
|
function (value) {
|
||||||
|
return this.parent.new_password === value;
|
||||||
|
}
|
||||||
|
),
|
||||||
});
|
});
|
||||||
axios
|
|
||||||
.post(
|
|
||||||
CHANGE_PASSWORD,
|
|
||||||
{
|
|
||||||
current_password: values.current_password,
|
|
||||||
new_password: values.new_password,
|
|
||||||
new_password_confirmation: values.new_password_confirmation,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
headers: { authorization: `Bearer ${token}` },
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.then((response) => {
|
|
||||||
toast.dismiss(pendingToast); // Dismiss the pending toast notification
|
|
||||||
Notifications(directionApp, response, t);
|
|
||||||
resetForm();
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
toast.dismiss(pendingToast); // Dismiss the pending toast notification
|
|
||||||
Notifications(directionApp, error.response, t);
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
setSubmitting(false); // Set `setSubmitting` to false after the API request completes
|
|
||||||
});
|
|
||||||
};
|
|
||||||
const initialValues = {
|
|
||||||
current_password: "",
|
|
||||||
new_password: "",
|
|
||||||
new_password_confirmation: "",
|
|
||||||
};
|
|
||||||
const validationSchema = Yup.object().shape({
|
|
||||||
current_password: Yup.string().required(
|
|
||||||
t("ChangePassword.error_message_required")
|
|
||||||
),
|
|
||||||
new_password: Yup.string()
|
|
||||||
.min(8, t("ChangePassword.error_message_password_length"))
|
|
||||||
.required(t("ChangePassword.error_message_required")),
|
|
||||||
new_password_confirmation: Yup.string()
|
|
||||||
.required(t("ChangePassword.error_message_required"))
|
|
||||||
.test(
|
|
||||||
t("ChangePassword.error_message_password_match"),
|
|
||||||
t("ChangePassword.error_message_password_not_match"),
|
|
||||||
function (value) {
|
|
||||||
return this.parent.new_password === value;
|
|
||||||
}
|
|
||||||
),
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardLayouts>
|
<DashboardLayouts>
|
||||||
<CenterLayout>
|
<CenterLayout>
|
||||||
<Container maxWidth="sm">
|
<Container maxWidth="sm">
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={initialValues}
|
initialValues={initialValues}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
validationSchema={validationSchema}
|
validationSchema={validationSchema}
|
||||||
>
|
|
||||||
{(props) => (
|
|
||||||
<StyledForm
|
|
||||||
onSubmit={(e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
props.handleSubmit();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Paper elevation={0}>
|
|
||||||
<Stack spacing={3} sx={{ p: 5 }} component="div">
|
|
||||||
<Box
|
|
||||||
sx={{ position: "relative", width: "100%", height: 200 }}
|
|
||||||
>
|
>
|
||||||
<Image fill src="/images/change-password.svg" alt="" />
|
{(props) => (
|
||||||
</Box>
|
<StyledForm
|
||||||
<Typography margin={2} variant="h4" textAlign="center">
|
onSubmit={(e) => {
|
||||||
{t("ChangePassword.typography_change_password")}
|
e.preventDefault();
|
||||||
</Typography>
|
props.handleSubmit();
|
||||||
<Stack spacing={1} component="div">
|
}}
|
||||||
<PasswordField
|
>
|
||||||
name="current_password"
|
<Paper elevation={0}>
|
||||||
label={t("ChangePassword.label_current_password")}
|
<Stack spacing={3} sx={{p: 5}} component="div">
|
||||||
error={
|
<Box
|
||||||
props.touched.current_password &&
|
sx={{position: "relative", width: "100%", height: 200}}
|
||||||
props.errors.current_password
|
>
|
||||||
? true
|
<Image fill src="/images/change-password.svg" alt=""/>
|
||||||
: false
|
</Box>
|
||||||
}
|
<Typography margin={2} variant="h4" textAlign="center">
|
||||||
helperText={
|
{t("ChangePassword.typography_change_password")}
|
||||||
props.touched.current_password
|
</Typography>
|
||||||
? props.errors.current_password
|
<Stack spacing={1} component="div">
|
||||||
: null
|
<PasswordField
|
||||||
}
|
name="current_password"
|
||||||
/>
|
label={t("ChangePassword.label_current_password")}
|
||||||
</Stack>
|
error={
|
||||||
<Stack spacing={1} component="div">
|
props.touched.current_password &&
|
||||||
<PasswordField
|
props.errors.current_password
|
||||||
name="new_password"
|
? true
|
||||||
label={t("ChangePassword.label_new_password")}
|
: false
|
||||||
error={
|
}
|
||||||
props.touched.new_password &&
|
helperText={
|
||||||
props.errors.new_password
|
props.touched.current_password
|
||||||
? true
|
? props.errors.current_password
|
||||||
: false
|
: null
|
||||||
}
|
}
|
||||||
helperText={
|
/>
|
||||||
props.touched.new_password
|
</Stack>
|
||||||
? props.errors.new_password
|
<Stack spacing={1} component="div">
|
||||||
: null
|
<PasswordField
|
||||||
}
|
name="new_password"
|
||||||
/>
|
label={t("ChangePassword.label_new_password")}
|
||||||
</Stack>
|
error={
|
||||||
<Stack spacing={1} component="div">
|
props.touched.new_password &&
|
||||||
<PasswordField
|
props.errors.new_password
|
||||||
name="new_password_confirmation"
|
? true
|
||||||
label={t("ChangePassword.label_confirm_password")}
|
: false
|
||||||
error={
|
}
|
||||||
props.touched.new_password_confirmation &&
|
helperText={
|
||||||
props.errors.new_password_confirmation
|
props.touched.new_password
|
||||||
? true
|
? props.errors.new_password
|
||||||
: false
|
: null
|
||||||
}
|
}
|
||||||
helperText={
|
/>
|
||||||
props.touched.new_password_confirmation
|
</Stack>
|
||||||
? props.errors.new_password_confirmation
|
<Stack spacing={1} component="div">
|
||||||
: null
|
<PasswordField
|
||||||
}
|
name="new_password_confirmation"
|
||||||
/>
|
label={t("ChangePassword.label_confirm_password")}
|
||||||
</Stack>
|
error={
|
||||||
<Button
|
props.touched.new_password_confirmation &&
|
||||||
type="submit"
|
props.errors.new_password_confirmation
|
||||||
fullWidth
|
? true
|
||||||
variant="contained"
|
: false
|
||||||
color="primary"
|
}
|
||||||
size="large"
|
helperText={
|
||||||
disabled={props.isSubmitting}
|
props.touched.new_password_confirmation
|
||||||
>
|
? props.errors.new_password_confirmation
|
||||||
{props.isSubmitting
|
: null
|
||||||
? t("SubmitButton.button_while_submit")
|
}
|
||||||
: t("SubmitButton.button_submit")}
|
/>
|
||||||
</Button>
|
</Stack>
|
||||||
</Stack>
|
<Button
|
||||||
</Paper>
|
type="submit"
|
||||||
</StyledForm>
|
fullWidth
|
||||||
)}
|
variant="contained"
|
||||||
</Formik>
|
color="primary"
|
||||||
</Container>
|
size="large"
|
||||||
</CenterLayout>
|
disabled={props.isSubmitting}
|
||||||
</DashboardLayouts>
|
>
|
||||||
);
|
{props.isSubmitting
|
||||||
|
? t("SubmitButton.button_while_submit")
|
||||||
|
: t("SubmitButton.button_submit")}
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</StyledForm>
|
||||||
|
)}
|
||||||
|
</Formik>
|
||||||
|
</Container>
|
||||||
|
</CenterLayout>
|
||||||
|
</DashboardLayouts>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
export default DashboardChangePasswordComponent;
|
export default DashboardChangePasswordComponent;
|
||||||
|
|||||||
@@ -2,277 +2,268 @@ import StyledForm from "@/core/components/StyledForm";
|
|||||||
import CenterLayout from "@/layouts/CenterLayout";
|
import CenterLayout from "@/layouts/CenterLayout";
|
||||||
import DashboardLayouts from "@/layouts/dashboardLayouts";
|
import DashboardLayouts from "@/layouts/dashboardLayouts";
|
||||||
import useUser from "@/lib/app/hooks/useUser";
|
import useUser from "@/lib/app/hooks/useUser";
|
||||||
import {
|
import {Box, Container, Grid, Paper, Stack, TextField, Typography,} from "@mui/material";
|
||||||
Box,
|
|
||||||
Button,
|
|
||||||
Container,
|
|
||||||
Grid,
|
|
||||||
Paper,
|
|
||||||
Stack,
|
|
||||||
TextField,
|
|
||||||
Typography,
|
|
||||||
} from "@mui/material";
|
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
import { Field, Formik } from "formik";
|
import {Field, Formik} from "formik";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import AvatarUpload from "@/core/components/AvatarUpload";
|
import AvatarUpload from "@/core/components/AvatarUpload";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { UPDATE_PROFILE, UPDATE_AVATAR } from "@/core/data/apiRoutes";
|
import {UPDATE_AVATAR} from "@/core/data/apiRoutes";
|
||||||
import useDirection from "@/lib/app/hooks/useDirection";
|
import useDirection from "@/lib/app/hooks/useDirection";
|
||||||
import Notifications from "@/core/components/notifications";
|
import Notifications from "@/core/components/notifications";
|
||||||
import ImageResizer from "@/core/components/ImageConvertor";
|
import ImageResizer from "@/core/components/ImageConvertor";
|
||||||
|
|
||||||
const DashboardEditProfile = () => {
|
const DashboardEditProfile = () => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const { user, token, getUser, changeUser } = useUser();
|
const {user, token, getUser, changeUser} = useUser();
|
||||||
console.log(user);
|
console.log(user);
|
||||||
const { directionApp } = useDirection();
|
const {directionApp} = useDirection();
|
||||||
|
|
||||||
const editAvatar = async (avatar) => {
|
const editAvatar = async (avatar) => {
|
||||||
try {
|
try {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
|
|
||||||
if (avatar != null) {
|
if (avatar != null) {
|
||||||
var resizedAvatar;
|
var resizedAvatar;
|
||||||
resizedAvatar = await ImageResizer(avatar);
|
resizedAvatar = await ImageResizer(avatar);
|
||||||
formData.append("avatar", resizedAvatar);
|
formData.append("avatar", resizedAvatar);
|
||||||
}
|
}
|
||||||
|
|
||||||
await axios.post(UPDATE_AVATAR, formData, {
|
await axios.post(UPDATE_AVATAR, formData, {
|
||||||
headers: {
|
headers: {
|
||||||
authorization: `Bearer ${token}`,
|
authorization: `Bearer ${token}`,
|
||||||
"Content-Type": "multipart/form-data",
|
"Content-Type": "multipart/form-data",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
Notifications(directionApp, error.response, t);
|
Notifications(directionApp, error.response, t);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleSubmit = (values, { setSubmitting }) => {
|
const handleSubmit = (values, {setSubmitting}) => {
|
||||||
// const formData = new FormData();
|
// const formData = new FormData();
|
||||||
// formData.append("email", values.expert_email);
|
// formData.append("email", values.expert_email);
|
||||||
// if (values.change_avatar !== false) {
|
// if (values.change_avatar !== false) {
|
||||||
// editAvatar(values.expert_avatar)
|
// editAvatar(values.expert_avatar)
|
||||||
// .then(() => {
|
// .then(() => {
|
||||||
// return axios.post(UPDATE_PROFILE, formData, {
|
// return axios.post(UPDATE_PROFILE, formData, {
|
||||||
// headers: {
|
// headers: {
|
||||||
// authorization: `Bearer ${token}`,
|
// authorization: `Bearer ${token}`,
|
||||||
// "Content-Type": "multipart/form-data",
|
// "Content-Type": "multipart/form-data",
|
||||||
// },
|
// },
|
||||||
// });
|
// });
|
||||||
// })
|
// })
|
||||||
// .then((response) => {
|
// .then((response) => {
|
||||||
// Notifications(directionApp, response, t);
|
// Notifications(directionApp, response, t);
|
||||||
// getUser((data) => {
|
// getUser((data) => {
|
||||||
// changeUser(data);
|
// changeUser(data);
|
||||||
// });
|
// });
|
||||||
// })
|
// })
|
||||||
// .catch((error) => {
|
// .catch((error) => {
|
||||||
// Notifications(directionApp, error.response, t);
|
// Notifications(directionApp, error.response, t);
|
||||||
// })
|
// })
|
||||||
// .finally(() => {
|
// .finally(() => {
|
||||||
// setSubmitting(false);
|
// setSubmitting(false);
|
||||||
// });
|
// });
|
||||||
// } else {
|
// } else {
|
||||||
// axios
|
// axios
|
||||||
// .post(UPDATE_PROFILE, formData, {
|
// .post(UPDATE_PROFILE, formData, {
|
||||||
// headers: {
|
// headers: {
|
||||||
// authorization: `Bearer ${token}`,
|
// authorization: `Bearer ${token}`,
|
||||||
// "Content-Type": "multipart/form-data",
|
// "Content-Type": "multipart/form-data",
|
||||||
// },
|
// },
|
||||||
// })
|
// })
|
||||||
// .then((response) => {
|
// .then((response) => {
|
||||||
// Notifications(directionApp, response, t);
|
// Notifications(directionApp, response, t);
|
||||||
// getUser((data) => {
|
// getUser((data) => {
|
||||||
// changeUser(data);
|
// changeUser(data);
|
||||||
// });
|
// });
|
||||||
// })
|
// })
|
||||||
// .catch((error) => {
|
// .catch((error) => {
|
||||||
// Notifications(directionApp, error.response, t);
|
// Notifications(directionApp, error.response, t);
|
||||||
// })
|
// })
|
||||||
// .finally(() => {
|
// .finally(() => {
|
||||||
// setSubmitting(false);
|
// setSubmitting(false);
|
||||||
// });
|
// });
|
||||||
// }
|
// }
|
||||||
};
|
};
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
expert_avatar: null,
|
expert_avatar: null,
|
||||||
username: user.username,
|
username: user.username,
|
||||||
name: user.name,
|
name: user.name,
|
||||||
email: user.email,
|
email: user.email,
|
||||||
province_name: user.province_name,
|
province_name: user.province_name,
|
||||||
position: user.position,
|
position: user.position,
|
||||||
};
|
};
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
// username: Yup.string().required(t("UpdateProfile.error_message_required")),
|
// username: Yup.string().required(t("UpdateProfile.error_message_required")),
|
||||||
// name: Yup.string().required(t("UpdateProfile.error_message_required")),
|
// name: Yup.string().required(t("UpdateProfile.error_message_required")),
|
||||||
// email: Yup.string()
|
// email: Yup.string()
|
||||||
// .email(t("UpdateProfile.error_invalid_email"))
|
// .email(t("UpdateProfile.error_invalid_email"))
|
||||||
// .required(t("UpdateProfile.error_message_required")),
|
// .required(t("UpdateProfile.error_message_required")),
|
||||||
// province_name: Yup.string().required(
|
// province_name: Yup.string().required(
|
||||||
// t("UpdateProfile.error_message_required")
|
// t("UpdateProfile.error_message_required")
|
||||||
// ),
|
// ),
|
||||||
// position: Yup.string().required(t("UpdateProfile.error_message_required")),
|
// position: Yup.string().required(t("UpdateProfile.error_message_required")),
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardLayouts>
|
<DashboardLayouts>
|
||||||
<CenterLayout>
|
<CenterLayout>
|
||||||
<Container maxWidth="sm">
|
<Container maxWidth="sm">
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={initialValues}
|
initialValues={initialValues}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
validationSchema={validationSchema}
|
validationSchema={validationSchema}
|
||||||
>
|
|
||||||
{(props) => (
|
|
||||||
<StyledForm
|
|
||||||
onSubmit={(e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
props.handleSubmit();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Paper elevation={0}>
|
|
||||||
<Stack spacing={3} sx={{ p: 5 }} component="div">
|
|
||||||
<Typography margin={2} variant="h4" textAlign="center">
|
|
||||||
{t("UpdateProfile.typography_edit_profile")}
|
|
||||||
</Typography>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<AvatarUpload
|
{(props) => (
|
||||||
user={user}
|
<StyledForm
|
||||||
setFieldValue={props.setFieldValue}
|
onSubmit={(e) => {
|
||||||
valueAvatar="expert_avatar"
|
e.preventDefault();
|
||||||
changeFlag="change_avatar"
|
props.handleSubmit();
|
||||||
/>
|
}}
|
||||||
</Box>
|
>
|
||||||
<Grid container spacing={2} sx={{ pb: 2 }}>
|
<Paper elevation={0}>
|
||||||
<Grid item xs={12} sm={6}>
|
<Stack spacing={3} sx={{p: 5}} component="div">
|
||||||
<Field
|
<Typography margin={2} variant="h4" textAlign="center">
|
||||||
as={TextField}
|
{t("UpdateProfile.typography_edit_profile")}
|
||||||
name="username"
|
</Typography>
|
||||||
label={t("UpdateProfile.text_field_username")}
|
<Box
|
||||||
variant="outlined"
|
sx={{
|
||||||
margin="normal"
|
display: "flex",
|
||||||
size="small"
|
flexDirection: "column",
|
||||||
disabled={true}
|
alignItems: "center",
|
||||||
error={
|
justifyContent: "center",
|
||||||
props.touched.username && props.errors.username
|
}}
|
||||||
? true
|
>
|
||||||
: false
|
<AvatarUpload
|
||||||
}
|
user={user}
|
||||||
helperText={
|
setFieldValue={props.setFieldValue}
|
||||||
props.touched.username
|
valueAvatar="expert_avatar"
|
||||||
? props.errors.username
|
changeFlag="change_avatar"
|
||||||
: null
|
/>
|
||||||
}
|
</Box>
|
||||||
sx={{
|
<Grid container spacing={2} sx={{pb: 2}}>
|
||||||
width: "100%",
|
<Grid item xs={12} sm={6}>
|
||||||
}}
|
<Field
|
||||||
/>
|
as={TextField}
|
||||||
</Grid>
|
name="username"
|
||||||
<Grid item xs={12} sm={6}>
|
label={t("UpdateProfile.text_field_username")}
|
||||||
<Field
|
variant="outlined"
|
||||||
as={TextField}
|
margin="normal"
|
||||||
name="name"
|
size="small"
|
||||||
label={t("UpdateProfile.text_field_name")}
|
disabled={true}
|
||||||
variant="outlined"
|
error={
|
||||||
margin="normal"
|
props.touched.username && props.errors.username
|
||||||
size="small"
|
? true
|
||||||
disabled={true}
|
: false
|
||||||
error={
|
}
|
||||||
props.touched.name && props.errors.name
|
helperText={
|
||||||
? true
|
props.touched.username
|
||||||
: false
|
? props.errors.username
|
||||||
}
|
: null
|
||||||
helperText={
|
}
|
||||||
props.touched.name ? props.errors.name : null
|
sx={{
|
||||||
}
|
width: "100%",
|
||||||
sx={{
|
}}
|
||||||
width: "100%",
|
/>
|
||||||
}}
|
</Grid>
|
||||||
/>
|
<Grid item xs={12} sm={6}>
|
||||||
</Grid>
|
<Field
|
||||||
<Grid item xs={12} sm={6}>
|
as={TextField}
|
||||||
<Field
|
name="name"
|
||||||
as={TextField}
|
label={t("UpdateProfile.text_field_name")}
|
||||||
name="email"
|
variant="outlined"
|
||||||
label={t("UpdateProfile.text_field_email")}
|
margin="normal"
|
||||||
variant="outlined"
|
size="small"
|
||||||
margin="normal"
|
disabled={true}
|
||||||
size="small"
|
error={
|
||||||
disabled={true}
|
props.touched.name && props.errors.name
|
||||||
error={
|
? true
|
||||||
props.touched.email && props.errors.email
|
: false
|
||||||
? true
|
}
|
||||||
: false
|
helperText={
|
||||||
}
|
props.touched.name ? props.errors.name : null
|
||||||
helperText={
|
}
|
||||||
props.touched.email ? props.errors.email : null
|
sx={{
|
||||||
}
|
width: "100%",
|
||||||
sx={{
|
}}
|
||||||
width: "100%",
|
/>
|
||||||
}}
|
</Grid>
|
||||||
/>
|
<Grid item xs={12} sm={6}>
|
||||||
</Grid>
|
<Field
|
||||||
|
as={TextField}
|
||||||
|
name="email"
|
||||||
|
label={t("UpdateProfile.text_field_email")}
|
||||||
|
variant="outlined"
|
||||||
|
margin="normal"
|
||||||
|
size="small"
|
||||||
|
disabled={true}
|
||||||
|
error={
|
||||||
|
props.touched.email && props.errors.email
|
||||||
|
? true
|
||||||
|
: false
|
||||||
|
}
|
||||||
|
helperText={
|
||||||
|
props.touched.email ? props.errors.email : null
|
||||||
|
}
|
||||||
|
sx={{
|
||||||
|
width: "100%",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Grid item xs={12} sm={6}>
|
<Grid item xs={12} sm={6}>
|
||||||
<Field
|
<Field
|
||||||
as={TextField}
|
as={TextField}
|
||||||
name="province_name"
|
name="province_name"
|
||||||
label={t("UpdateProfile.text_field_province_name")}
|
label={t("UpdateProfile.text_field_province_name")}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
margin="normal"
|
margin="normal"
|
||||||
size="small"
|
size="small"
|
||||||
disabled={true}
|
disabled={true}
|
||||||
error={
|
error={
|
||||||
props.touched.province_name &&
|
props.touched.province_name &&
|
||||||
props.errors.province_name
|
props.errors.province_name
|
||||||
? true
|
? true
|
||||||
: false
|
: false
|
||||||
}
|
}
|
||||||
helperText={
|
helperText={
|
||||||
props.touched.province_name
|
props.touched.province_name
|
||||||
? props.errors.province_name
|
? props.errors.province_name
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
sx={{
|
sx={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6}>
|
<Grid item xs={12} sm={6}>
|
||||||
<Field
|
<Field
|
||||||
as={TextField}
|
as={TextField}
|
||||||
name="position"
|
name="position"
|
||||||
label={t("UpdateProfile.text_field_position")}
|
label={t("UpdateProfile.text_field_position")}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
margin="normal"
|
margin="normal"
|
||||||
size="small"
|
size="small"
|
||||||
disabled={true}
|
disabled={true}
|
||||||
error={
|
error={
|
||||||
props.touched.position && props.errors.position
|
props.touched.position && props.errors.position
|
||||||
? true
|
? true
|
||||||
: false
|
: false
|
||||||
}
|
}
|
||||||
helperText={
|
helperText={
|
||||||
props.touched.position
|
props.touched.position
|
||||||
? props.errors.position
|
? props.errors.position
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
sx={{
|
sx={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
{/* <Button
|
{/* <Button
|
||||||
type="submit"
|
type="submit"
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="contained"
|
variant="contained"
|
||||||
@@ -285,15 +276,15 @@ const DashboardEditProfile = () => {
|
|||||||
? t("SubmitButton.button_while_submit")
|
? t("SubmitButton.button_while_submit")
|
||||||
: t("SubmitButton.button_submit")}
|
: t("SubmitButton.button_submit")}
|
||||||
</Button> */}
|
</Button> */}
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
</StyledForm>
|
</StyledForm>
|
||||||
)}
|
)}
|
||||||
</Formik>
|
</Formik>
|
||||||
</Container>
|
</Container>
|
||||||
</CenterLayout>
|
</CenterLayout>
|
||||||
</DashboardLayouts>
|
</DashboardLayouts>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DashboardEditProfile;
|
export default DashboardEditProfile;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import DashboardLayouts from "@/layouts/dashboardLayouts";
|
import DashboardLayouts from "@/layouts/dashboardLayouts";
|
||||||
|
|
||||||
const DashboardFirstComponent = () => {
|
const DashboardFirstComponent = () => {
|
||||||
return <DashboardLayouts></DashboardLayouts>;
|
return <DashboardLayouts></DashboardLayouts>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DashboardFirstComponent;
|
export default DashboardFirstComponent;
|
||||||
|
|||||||
@@ -1,140 +1,132 @@
|
|||||||
import { CONFIRM_MACHINARY_OFFICE } from "@/core/data/apiRoutes";
|
import {CONFIRM_MACHINARY_OFFICE} from "@/core/data/apiRoutes";
|
||||||
import {
|
import {Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, TextField,} from "@mui/material";
|
||||||
Dialog,
|
import {useTranslations} from "next-intl";
|
||||||
DialogTitle,
|
import {useState} from "react";
|
||||||
DialogContent,
|
import {useFormik} from "formik";
|
||||||
DialogContentText,
|
|
||||||
DialogActions,
|
|
||||||
Button,
|
|
||||||
TextField,
|
|
||||||
} from "@mui/material";
|
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useState } from "react";
|
|
||||||
import { useFormik } from "formik";
|
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
import UploadSystem from "@/core/components/UploadSystem";
|
import UploadSystem from "@/core/components/UploadSystem";
|
||||||
import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
|
import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
|
||||||
import useDirection from "@/lib/app/hooks/useDirection";
|
import useDirection from "@/lib/app/hooks/useDirection";
|
||||||
|
|
||||||
const ConfirmForm = ({ open, handleClose, rowId, confirmData }) => {
|
const ConfirmForm = ({open, handleClose, rowId, confirmData}) => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const { directionApp } = useDirection();
|
const {directionApp} = useDirection();
|
||||||
const [proposedAmount, setProposedAmount] = useState("");
|
const [proposedAmount, setProposedAmount] = useState("");
|
||||||
const [description, setDescription] = useState("");
|
const [description, setDescription] = useState("");
|
||||||
const [selectedImage, setSelectedImage] = useState("");
|
const [selectedImage, setSelectedImage] = useState("");
|
||||||
const [fileType, setfileType] = useState(null);
|
const [fileType, setfileType] = useState(null);
|
||||||
const [fileName, setfileName] = useState(null);
|
const [fileName, setfileName] = useState(null);
|
||||||
const [showAddIcon, setShowAddIcon] = useState(true);
|
const [showAddIcon, setShowAddIcon] = useState(true);
|
||||||
|
|
||||||
//formik
|
//formik
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
proposed_amount: Yup.string().required(t("ConfirmDialog.amount_error")),
|
proposed_amount: Yup.string().required(t("ConfirmDialog.amount_error")),
|
||||||
});
|
});
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
proposed_amount: "",
|
proposed_amount: "",
|
||||||
description: "",
|
description: "",
|
||||||
},
|
},
|
||||||
validationSchema,
|
validationSchema,
|
||||||
onSubmit: () => {
|
onSubmit: () => {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("proposed_amount", proposedAmount);
|
formData.append("proposed_amount", proposedAmount);
|
||||||
if (description != "") formData.append("expert_description", description);
|
if (description != "") formData.append("expert_description", description);
|
||||||
handleClose();
|
handleClose();
|
||||||
confirmData(CONFIRM_MACHINARY_OFFICE, rowId, formData);
|
confirmData(CONFIRM_MACHINARY_OFFICE, rowId, formData);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleDescriptionChange = (event) => {
|
const handleDescriptionChange = (event) => {
|
||||||
setDescription(event.target.value);
|
setDescription(event.target.value);
|
||||||
};
|
};
|
||||||
const handleAmountChange = (event) => {
|
const handleAmountChange = (event) => {
|
||||||
if (/^\d*$/.test(event.target.value)) {
|
if (/^\d*$/.test(event.target.value)) {
|
||||||
setProposedAmount(event.target.value);
|
setProposedAmount(event.target.value);
|
||||||
}
|
}
|
||||||
formik.handleChange(event);
|
formik.handleChange(event);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUploadChange = (event) => {
|
const handleUploadChange = (event) => {
|
||||||
const uploadedFile = event.target?.files?.[0];
|
const uploadedFile = event.target?.files?.[0];
|
||||||
if (uploadedFile) {
|
if (uploadedFile) {
|
||||||
const maxFileSize = 2 * 1024 * 1024;
|
const maxFileSize = 2 * 1024 * 1024;
|
||||||
if (uploadedFile.size > maxFileSize) {
|
if (uploadedFile.size > maxFileSize) {
|
||||||
UploadFileNotification(directionApp, t);
|
UploadFileNotification(directionApp, t);
|
||||||
event.target.value = "";
|
event.target.value = "";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const fileType = event.target?.files?.[0].type;
|
const fileType = event.target?.files?.[0].type;
|
||||||
const fileName = event.target?.files?.[0].name;
|
const fileName = event.target?.files?.[0].name;
|
||||||
setSelectedImage(URL.createObjectURL(uploadedFile));
|
setSelectedImage(URL.createObjectURL(uploadedFile));
|
||||||
setfileType(fileType);
|
setfileType(fileType);
|
||||||
setfileName(fileName);
|
setfileName(fileName);
|
||||||
formik.setFieldValue("confirm_img", uploadedFile);
|
formik.setFieldValue("confirm_img", uploadedFile);
|
||||||
setShowAddIcon(false);
|
setShowAddIcon(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Dialog open={open}>
|
<Dialog open={open}>
|
||||||
<DialogTitle>{t("ConfirmDialog.confirm")}</DialogTitle>
|
<DialogTitle>{t("ConfirmDialog.confirm")}</DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<DialogContentText>{t("ConfirmDialog.context")}</DialogContentText>
|
<DialogContentText>{t("ConfirmDialog.context")}</DialogContentText>
|
||||||
<TextField
|
<TextField
|
||||||
name="description"
|
name="description"
|
||||||
multiline
|
multiline
|
||||||
rows={8}
|
rows={8}
|
||||||
placeholder={t("ConfirmDialog.description")}
|
placeholder={t("ConfirmDialog.description")}
|
||||||
value={description}
|
value={description}
|
||||||
onChange={handleDescriptionChange}
|
onChange={handleDescriptionChange}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
sx={{ mt: 1 }}
|
sx={{mt: 1}}
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
name="proposed_amount"
|
name="proposed_amount"
|
||||||
label={t("ConfirmDialog.proposed_amount")}
|
label={t("ConfirmDialog.proposed_amount")}
|
||||||
type="number"
|
type="number"
|
||||||
inputProps={{
|
inputProps={{
|
||||||
min: 0,
|
min: 0,
|
||||||
inputMode: "numeric",
|
inputMode: "numeric",
|
||||||
pattern: "[0-9]*",
|
pattern: "[0-9]*",
|
||||||
}}
|
}}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={proposedAmount}
|
value={proposedAmount}
|
||||||
onChange={handleAmountChange}
|
onChange={handleAmountChange}
|
||||||
onBlur={formik.handleBlur("proposed_amount")}
|
onBlur={formik.handleBlur("proposed_amount")}
|
||||||
error={
|
error={
|
||||||
formik.touched.proposed_amount &&
|
formik.touched.proposed_amount &&
|
||||||
Boolean(formik.errors.proposed_amount)
|
Boolean(formik.errors.proposed_amount)
|
||||||
}
|
}
|
||||||
helperText={
|
helperText={
|
||||||
formik.touched.proposed_amount && formik.errors.proposed_amount
|
formik.touched.proposed_amount && formik.errors.proposed_amount
|
||||||
}
|
}
|
||||||
sx={{ mt: 1 }}
|
sx={{mt: 1}}
|
||||||
fullWidth
|
fullWidth
|
||||||
/>
|
/>
|
||||||
<UploadSystem
|
<UploadSystem
|
||||||
selectedImage={selectedImage}
|
selectedImage={selectedImage}
|
||||||
handleUploadChange={handleUploadChange} // Pass the updated function directly
|
handleUploadChange={handleUploadChange} // Pass the updated function directly
|
||||||
setselectedImage={setSelectedImage}
|
setselectedImage={setSelectedImage}
|
||||||
setFieldValue={formik.setFieldValue} // Remove props.setFieldValue, use formik.setFieldValue
|
setFieldValue={formik.setFieldValue} // Remove props.setFieldValue, use formik.setFieldValue
|
||||||
fieldname="confirm_img"
|
fieldname="confirm_img"
|
||||||
fileType={fileType}
|
fileType={fileType}
|
||||||
fileName={fileName}
|
fileName={fileName}
|
||||||
imageAlt={t("app_name")}
|
imageAlt={t("app_name")}
|
||||||
imageSize={[250 /*width*/, 150 /*height*/]}
|
imageSize={[250 /*width*/, 150 /*height*/]}
|
||||||
setShowAddIcon={setShowAddIcon}
|
setShowAddIcon={setShowAddIcon}
|
||||||
showAddIcon={showAddIcon}
|
showAddIcon={showAddIcon}
|
||||||
/>
|
/>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button onClick={handleClose} color="secondary" autoFocus>
|
<Button onClick={handleClose} color="secondary" autoFocus>
|
||||||
{t("ConfirmDialog.button-cancel")}
|
{t("ConfirmDialog.button-cancel")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={formik.handleSubmit} color="primary">
|
<Button onClick={formik.handleSubmit} color="primary">
|
||||||
{t("ConfirmDialog.button-confirm")}
|
{t("ConfirmDialog.button-confirm")}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default ConfirmForm;
|
export default ConfirmForm;
|
||||||
|
|||||||
@@ -1,116 +1,108 @@
|
|||||||
import { REJECT_MACHINARY_OFFICE } from "@/core/data/apiRoutes";
|
import {REJECT_MACHINARY_OFFICE} from "@/core/data/apiRoutes";
|
||||||
import {
|
import {Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, TextField,} from "@mui/material";
|
||||||
Dialog,
|
import {useTranslations} from "next-intl";
|
||||||
DialogTitle,
|
import {useFormik} from "formik";
|
||||||
DialogContent,
|
|
||||||
DialogContentText,
|
|
||||||
DialogActions,
|
|
||||||
Button,
|
|
||||||
TextField,
|
|
||||||
} from "@mui/material";
|
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useFormik } from "formik";
|
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
import { useState } from "react";
|
import {useState} from "react";
|
||||||
import UploadSystem from "@/core/components/UploadSystem";
|
import UploadSystem from "@/core/components/UploadSystem";
|
||||||
import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
|
import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
|
||||||
import useDirection from "@/lib/app/hooks/useDirection";
|
import useDirection from "@/lib/app/hooks/useDirection";
|
||||||
|
|
||||||
const RejectForm = ({ open, handleClose, rowId, rejectData }) => {
|
const RejectForm = ({open, handleClose, rowId, rejectData}) => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const { directionApp } = useDirection();
|
const {directionApp} = useDirection();
|
||||||
const [description, setDescription] = useState("");
|
const [description, setDescription] = useState("");
|
||||||
const [selectedImage, setSelectedImage] = useState("");
|
const [selectedImage, setSelectedImage] = useState("");
|
||||||
const [fileType, setfileType] = useState(null);
|
const [fileType, setfileType] = useState(null);
|
||||||
const [fileName, setfileName] = useState(null);
|
const [fileName, setfileName] = useState(null);
|
||||||
const [showAddIcon, setShowAddIcon] = useState(true);
|
const [showAddIcon, setShowAddIcon] = useState(true);
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
description: Yup.string().required(t("RejectDialog.description_error")),
|
description: Yup.string().required(t("RejectDialog.description_error")),
|
||||||
});
|
});
|
||||||
|
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
description: "",
|
description: "",
|
||||||
},
|
},
|
||||||
validationSchema,
|
validationSchema,
|
||||||
onSubmit: () => {
|
onSubmit: () => {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("expert_description", description);
|
formData.append("expert_description", description);
|
||||||
handleClose();
|
handleClose();
|
||||||
rejectData(REJECT_MACHINARY_OFFICE, rowId, formData);
|
rejectData(REJECT_MACHINARY_OFFICE, rowId, formData);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleDescriptionChange = (event) => {
|
const handleDescriptionChange = (event) => {
|
||||||
setDescription(event.target.value);
|
setDescription(event.target.value);
|
||||||
formik.handleChange(event);
|
formik.handleChange(event);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUploadChange = (event) => {
|
const handleUploadChange = (event) => {
|
||||||
const uploadedFile = event.target?.files?.[0];
|
const uploadedFile = event.target?.files?.[0];
|
||||||
if (uploadedFile) {
|
if (uploadedFile) {
|
||||||
const maxFileSize = 2 * 1024 * 1024;
|
const maxFileSize = 2 * 1024 * 1024;
|
||||||
if (uploadedFile.size > maxFileSize) {
|
if (uploadedFile.size > maxFileSize) {
|
||||||
UploadFileNotification(directionApp, t);
|
UploadFileNotification(directionApp, t);
|
||||||
event.target.value = "";
|
event.target.value = "";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const fileType = event.target?.files?.[0].type;
|
const fileType = event.target?.files?.[0].type;
|
||||||
const fileName = event.target?.files?.[0].name;
|
const fileName = event.target?.files?.[0].name;
|
||||||
setSelectedImage(URL.createObjectURL(uploadedFile));
|
setSelectedImage(URL.createObjectURL(uploadedFile));
|
||||||
setfileType(fileType);
|
setfileType(fileType);
|
||||||
setfileName(fileName);
|
setfileName(fileName);
|
||||||
formik.setFieldValue("reject_img", uploadedFile);
|
formik.setFieldValue("reject_img", uploadedFile);
|
||||||
setShowAddIcon(false);
|
setShowAddIcon(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={open}>
|
<Dialog open={open}>
|
||||||
<DialogTitle>{t("RejectDialog.reject")}</DialogTitle>
|
<DialogTitle>{t("RejectDialog.reject")}</DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<DialogContentText>{t("RejectDialog.context")}</DialogContentText>
|
<DialogContentText>{t("RejectDialog.context")}</DialogContentText>
|
||||||
<TextField
|
<TextField
|
||||||
name="description"
|
name="description"
|
||||||
multiline
|
multiline
|
||||||
rows={8}
|
rows={8}
|
||||||
placeholder={t("RejectDialog.description")}
|
placeholder={t("RejectDialog.description")}
|
||||||
value={description}
|
value={description}
|
||||||
onChange={handleDescriptionChange}
|
onChange={handleDescriptionChange}
|
||||||
onBlur={formik.handleBlur("description")}
|
onBlur={formik.handleBlur("description")}
|
||||||
error={
|
error={
|
||||||
formik.touched.description && Boolean(formik.errors.description)
|
formik.touched.description && Boolean(formik.errors.description)
|
||||||
}
|
}
|
||||||
helperText={formik.touched.description && formik.errors.description}
|
helperText={formik.touched.description && formik.errors.description}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
sx={{ mt: 1 }}
|
sx={{mt: 1}}
|
||||||
/>
|
/>
|
||||||
<UploadSystem
|
<UploadSystem
|
||||||
selectedImage={selectedImage}
|
selectedImage={selectedImage}
|
||||||
handleUploadChange={handleUploadChange} // Pass the updated function directly
|
handleUploadChange={handleUploadChange} // Pass the updated function directly
|
||||||
setselectedImage={setSelectedImage}
|
setselectedImage={setSelectedImage}
|
||||||
setFieldValue={formik.setFieldValue} // Remove props.setFieldValue, use formik.setFieldValue
|
setFieldValue={formik.setFieldValue} // Remove props.setFieldValue, use formik.setFieldValue
|
||||||
fieldname="reject_img"
|
fieldname="reject_img"
|
||||||
fileType={fileType}
|
fileType={fileType}
|
||||||
fileName={fileName}
|
fileName={fileName}
|
||||||
imageAlt={t("app_name")}
|
imageAlt={t("app_name")}
|
||||||
imageSize={[250 /*width*/, 150 /*height*/]}
|
imageSize={[250 /*width*/, 150 /*height*/]}
|
||||||
setShowAddIcon={setShowAddIcon}
|
setShowAddIcon={setShowAddIcon}
|
||||||
showAddIcon={showAddIcon}
|
showAddIcon={showAddIcon}
|
||||||
/>
|
/>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button onClick={handleClose} color="secondary" autoFocus>
|
<Button onClick={handleClose} color="secondary" autoFocus>
|
||||||
{t("RejectDialog.button-cancel")}
|
{t("RejectDialog.button-cancel")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={formik.handleSubmit} color="primary">
|
<Button onClick={formik.handleSubmit} color="primary">
|
||||||
{t("RejectDialog.button-reject")}
|
{t("RejectDialog.button-reject")}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default RejectForm;
|
export default RejectForm;
|
||||||
|
|||||||
@@ -1,60 +1,60 @@
|
|||||||
import ThumbUpAltIcon from "@mui/icons-material/ThumbUpAlt";
|
import ThumbUpAltIcon from "@mui/icons-material/ThumbUpAlt";
|
||||||
import ThumbDownIcon from "@mui/icons-material/ThumbDown";
|
import ThumbDownIcon from "@mui/icons-material/ThumbDown";
|
||||||
import { Box, IconButton, Tooltip } from "@mui/material";
|
import {Box, IconButton, Tooltip} from "@mui/material";
|
||||||
import { useContext } from "react";
|
import {useContext} from "react";
|
||||||
import ConfirmForm from "./Form/ConfirmForm";
|
import ConfirmForm from "./Form/ConfirmForm";
|
||||||
import RejectForm from "./Form/RejectForm";
|
import RejectForm from "./Form/RejectForm";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import { DataTableContext } from "@/lib/app/contexts/DatatableContext";
|
import {DataTableContext} from "@/lib/app/contexts/DatatableContext";
|
||||||
|
|
||||||
const TableRowActions = ({ row }) => {
|
const TableRowActions = ({row}) => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const {
|
const {
|
||||||
openConfirmDialog,
|
openConfirmDialog,
|
||||||
openRejectDialog,
|
openRejectDialog,
|
||||||
handleOpenConfirmDialog,
|
handleOpenConfirmDialog,
|
||||||
handleOpenRejectDialog,
|
handleOpenRejectDialog,
|
||||||
handleCloseConfirmDialog,
|
handleCloseConfirmDialog,
|
||||||
handleCloseRejectDialog,
|
handleCloseRejectDialog,
|
||||||
rowId,
|
rowId,
|
||||||
confirmData,
|
confirmData,
|
||||||
rejectData,
|
rejectData,
|
||||||
} = useContext(DataTableContext);
|
} = useContext(DataTableContext);
|
||||||
return (
|
return (
|
||||||
<Box sx={{ display: "flex", flexWrap: "nowrap", gap: "8px" }}>
|
<Box sx={{display: "flex", flexWrap: "nowrap", gap: "8px"}}>
|
||||||
<Tooltip title={t("ConfirmDialog.confirm")}>
|
<Tooltip title={t("ConfirmDialog.confirm")}>
|
||||||
<IconButton
|
<IconButton
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleOpenConfirmDialog(row);
|
handleOpenConfirmDialog(row);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ThumbUpAltIcon />
|
<ThumbUpAltIcon/>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
{openConfirmDialog && (
|
{openConfirmDialog && (
|
||||||
<ConfirmForm
|
<ConfirmForm
|
||||||
rowId={rowId}
|
rowId={rowId}
|
||||||
open={openConfirmDialog}
|
open={openConfirmDialog}
|
||||||
handleClose={handleCloseConfirmDialog}
|
handleClose={handleCloseConfirmDialog}
|
||||||
confirmData={confirmData}
|
confirmData={confirmData}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Tooltip title={t("RejectDialog.reject")}>
|
<Tooltip title={t("RejectDialog.reject")}>
|
||||||
<IconButton color="primary" onClick={() => handleOpenRejectDialog(row)}>
|
<IconButton color="primary" onClick={() => handleOpenRejectDialog(row)}>
|
||||||
<ThumbDownIcon />
|
<ThumbDownIcon/>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
{openRejectDialog && (
|
{openRejectDialog && (
|
||||||
<RejectForm
|
<RejectForm
|
||||||
rowId={rowId}
|
rowId={rowId}
|
||||||
open={openRejectDialog}
|
open={openRejectDialog}
|
||||||
handleClose={handleCloseRejectDialog}
|
handleClose={handleCloseRejectDialog}
|
||||||
rejectData={rejectData}
|
rejectData={rejectData}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TableRowActions;
|
export default TableRowActions;
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { Stack, Tooltip } from "@mui/material";
|
import {Stack, Tooltip} from "@mui/material";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
|
|
||||||
function TableToolbar() {
|
function TableToolbar() {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
return (
|
return (
|
||||||
<Stack direction={"row"} spacing={2}>
|
<Stack direction={"row"} spacing={2}>
|
||||||
<Tooltip title={t("add")} arrow placement="right"></Tooltip>
|
<Tooltip title={t("add")} arrow placement="right"></Tooltip>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default TableToolbar;
|
export default TableToolbar;
|
||||||
|
|||||||
@@ -1,244 +1,241 @@
|
|||||||
import DataTableStructure from "@/core/components/DatatableStructure";
|
import DataTableStructure from "@/core/components/DatatableStructure";
|
||||||
import DashboardLayouts from "@/layouts/dashboardLayouts";
|
import DashboardLayouts from "@/layouts/dashboardLayouts";
|
||||||
import { Box, IconButton, Typography } from "@mui/material";
|
import {Box, IconButton, Typography} from "@mui/material";
|
||||||
import ClearIcon from "@mui/icons-material/Clear";
|
import ClearIcon from "@mui/icons-material/Clear";
|
||||||
import { useMemo } from "react";
|
import {useMemo} from "react";
|
||||||
// import TableToolbar from "./TableTollbar";
|
// import TableToolbar from "./TableTollbar";
|
||||||
import { GET_MACHINARY_OFFICE } from "@/core/data/apiRoutes";
|
import {GET_MACHINARY_OFFICE} from "@/core/data/apiRoutes";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import TableRowActions from "./TableRowActions";
|
import TableRowActions from "./TableRowActions";
|
||||||
import {
|
import {LocalizationProvider, MobileDateTimePicker,} from "@mui/x-date-pickers";
|
||||||
LocalizationProvider,
|
import {AdapterDateFnsJalali} from "@mui/x-date-pickers/AdapterDateFnsJalali";
|
||||||
MobileDateTimePicker,
|
|
||||||
} from "@mui/x-date-pickers";
|
|
||||||
import { AdapterDateFnsJalali } from "@mui/x-date-pickers/AdapterDateFnsJalali";
|
|
||||||
import moment from "jalali-moment";
|
import moment from "jalali-moment";
|
||||||
import { faIR } from "@mui/x-date-pickers/locales";
|
import {faIR} from "@mui/x-date-pickers/locales";
|
||||||
|
|
||||||
function DashboardMachinaryOfficeComponent() {
|
function DashboardMachinaryOfficeComponent() {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const columns = useMemo(
|
const columns = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
accessorFn: (row) => row.id,
|
accessorFn: (row) => row.id,
|
||||||
id: "id",
|
id: "id",
|
||||||
header: t("PassengerOffice.id"),
|
header: t("PassengerOffice.id"),
|
||||||
enableColumnFilter: true,
|
enableColumnFilter: true,
|
||||||
datatype: "numeric",
|
datatype: "numeric",
|
||||||
filterFn: "equals",
|
filterFn: "equals",
|
||||||
maxSize: 100,
|
maxSize: 100,
|
||||||
columnFilterModeOptions: [
|
columnFilterModeOptions: [
|
||||||
"equals",
|
"equals",
|
||||||
"notEquals",
|
"notEquals",
|
||||||
"contains",
|
"contains",
|
||||||
"lessThan",
|
"lessThan",
|
||||||
"greaterThan",
|
"greaterThan",
|
||||||
"between",
|
"between",
|
||||||
|
],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.name,
|
||||||
|
id: "name",
|
||||||
|
header: t("MachinaryOffice.name"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "text",
|
||||||
|
filterFn: "contains",
|
||||||
|
columnFilterModeOptions: ["contains", "equals", "notEquals"],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.national_id,
|
||||||
|
id: "national_id",
|
||||||
|
header: t("MachinaryOffice.national_id"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "numeric",
|
||||||
|
filterFn: "equals",
|
||||||
|
columnFilterModeOptions: [
|
||||||
|
"equals",
|
||||||
|
"notEquals",
|
||||||
|
"contains",
|
||||||
|
"lessThan",
|
||||||
|
"greaterThan",
|
||||||
|
"between",
|
||||||
|
],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.phone_number,
|
||||||
|
id: "phone_number",
|
||||||
|
header: t("MachinaryOffice.phone_number"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "numeric",
|
||||||
|
filterFn: "equals",
|
||||||
|
columnFilterModeOptions: [
|
||||||
|
"equals",
|
||||||
|
"notEquals",
|
||||||
|
"contains",
|
||||||
|
"lessThan",
|
||||||
|
"greaterThan",
|
||||||
|
"between",
|
||||||
|
],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) =>
|
||||||
|
moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
|
||||||
|
id: "created_at",
|
||||||
|
header: t("MachinaryOffice.created_at"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "date",
|
||||||
|
filterFn: "lessThan",
|
||||||
|
minSize: 200,
|
||||||
|
columnFilterModeOptions: ["lessThan", "greaterThan"],
|
||||||
|
Cell: ({renderedCellValue}) => {
|
||||||
|
return <Typography variant="body2">{renderedCellValue}</Typography>;
|
||||||
|
},
|
||||||
|
Header: ({column}) => <em>{column.columnDef.header}</em>,
|
||||||
|
Filter: ({column}) => {
|
||||||
|
const filterFnValue = column.columnDef._filterFn;
|
||||||
|
return (
|
||||||
|
<Box sx={{display: "flex", alignItems: "start"}}>
|
||||||
|
<LocalizationProvider
|
||||||
|
dateAdapter={AdapterDateFnsJalali}
|
||||||
|
localeText={
|
||||||
|
faIR.components.MuiLocalizationProvider.defaultProps
|
||||||
|
.localeText
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<MobileDateTimePicker
|
||||||
|
ampm={false}
|
||||||
|
onChange={(newValue) => {
|
||||||
|
const date = new Date(newValue);
|
||||||
|
const formattedDate = moment(date)
|
||||||
|
.locale("en")
|
||||||
|
.format("YYYY-MM-DD HH:mm");
|
||||||
|
column.setFilterValue(formattedDate);
|
||||||
|
}}
|
||||||
|
slotProps={{
|
||||||
|
textField: {
|
||||||
|
placeholder: "تاریخ خود را وارد کنید",
|
||||||
|
helperText: `${t("filter_mode")}: ${t(filterFnValue)}`,
|
||||||
|
sx: {minWidth: "120px"},
|
||||||
|
variant: "standard",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
value={
|
||||||
|
column.getFilterValue()
|
||||||
|
? new Date(column.getFilterValue())
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</LocalizationProvider>
|
||||||
|
<IconButton
|
||||||
|
size="small"
|
||||||
|
onClick={() => {
|
||||||
|
column.setFilterValue(null);
|
||||||
|
}}
|
||||||
|
sx={{
|
||||||
|
color: column.getFilterValue()
|
||||||
|
? "rgba(0, 0, 0, 0.54)"
|
||||||
|
: "#bfbfbf",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ClearIcon/>
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) =>
|
||||||
|
moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
|
||||||
|
id: "updated_at",
|
||||||
|
header: t("MachinaryOffice.updated_at"),
|
||||||
|
enableColumnFilter: false,
|
||||||
|
datatype: "numeric",
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.navgan_id,
|
||||||
|
id: "navgan_id",
|
||||||
|
header: t("MachinaryOffice.navgan_id"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "numeric",
|
||||||
|
filterFn: "equals",
|
||||||
|
maxSize: 100,
|
||||||
|
columnFilterModeOptions: [
|
||||||
|
"equals",
|
||||||
|
"notEquals",
|
||||||
|
"contains",
|
||||||
|
"lessThan",
|
||||||
|
"greaterThan",
|
||||||
|
"between",
|
||||||
|
],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.vehicle_type,
|
||||||
|
id: "vehicle_type",
|
||||||
|
header: t("MachinaryOffice.vehicle_type"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "text",
|
||||||
|
filterFn: "contains",
|
||||||
|
columnFilterModeOptions: ["contains", "equals", "notEquals"],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.state_name,
|
||||||
|
id: "state_id",
|
||||||
|
header: t("MachinaryOffice.state_name"),
|
||||||
|
enableColumnFilter: false,
|
||||||
|
datatype: "numeric",
|
||||||
|
minSize: 300,
|
||||||
|
// filterFn: "equals",
|
||||||
|
// filterSelectOptions: [
|
||||||
|
// ],
|
||||||
|
// filterVariant: "select",
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
Cell: ({ renderedCellValue }) => (
|
[]
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
);
|
||||||
),
|
return (
|
||||||
},
|
<DashboardLayouts>
|
||||||
{
|
<Box sx={{px: 3}}>
|
||||||
accessorFn: (row) => row.name,
|
<DataTableStructure
|
||||||
id: "name",
|
tableUrl={GET_MACHINARY_OFFICE}
|
||||||
header: t("MachinaryOffice.name"),
|
columns={columns}
|
||||||
enableColumnFilter: true,
|
selectableRow={false}
|
||||||
datatype: "text",
|
enableCustomToolbar={true}
|
||||||
filterFn: "contains",
|
// CustomToolbar={<TableToolbar />}
|
||||||
columnFilterModeOptions: ["contains", "equals", "notEquals"],
|
enableLastUpdate={true}
|
||||||
Cell: ({ renderedCellValue }) => (
|
enablePinning={true}
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
enableDensityToggle={true}
|
||||||
),
|
enableColumnFilters={true}
|
||||||
},
|
enableHiding={true}
|
||||||
{
|
enableFullScreenToggle={false}
|
||||||
accessorFn: (row) => row.national_id,
|
enableGlobalFilter={false}
|
||||||
id: "national_id",
|
enableColumnResizing={false} // if you want true this you shold change renderRowActions props ** see https://www.material-react-table.com/docs/guides/row-actions
|
||||||
header: t("MachinaryOffice.national_id"),
|
enableRowActions={true}
|
||||||
enableColumnFilter: true,
|
renderRowActions={({row}) => <TableRowActions row={row}/>}
|
||||||
datatype: "numeric",
|
|
||||||
filterFn: "equals",
|
|
||||||
columnFilterModeOptions: [
|
|
||||||
"equals",
|
|
||||||
"notEquals",
|
|
||||||
"contains",
|
|
||||||
"lessThan",
|
|
||||||
"greaterThan",
|
|
||||||
"between",
|
|
||||||
],
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) => row.phone_number,
|
|
||||||
id: "phone_number",
|
|
||||||
header: t("MachinaryOffice.phone_number"),
|
|
||||||
enableColumnFilter: true,
|
|
||||||
datatype: "numeric",
|
|
||||||
filterFn: "equals",
|
|
||||||
columnFilterModeOptions: [
|
|
||||||
"equals",
|
|
||||||
"notEquals",
|
|
||||||
"contains",
|
|
||||||
"lessThan",
|
|
||||||
"greaterThan",
|
|
||||||
"between",
|
|
||||||
],
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) =>
|
|
||||||
moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
|
|
||||||
id: "created_at",
|
|
||||||
header: t("MachinaryOffice.created_at"),
|
|
||||||
enableColumnFilter: true,
|
|
||||||
datatype: "date",
|
|
||||||
filterFn: "lessThan",
|
|
||||||
minSize: 200,
|
|
||||||
columnFilterModeOptions: ["lessThan", "greaterThan"],
|
|
||||||
Cell: ({ renderedCellValue }) => {
|
|
||||||
return <Typography variant="body2">{renderedCellValue}</Typography>;
|
|
||||||
},
|
|
||||||
Header: ({ column }) => <em>{column.columnDef.header}</em>,
|
|
||||||
Filter: ({ column }) => {
|
|
||||||
const filterFnValue = column.columnDef._filterFn;
|
|
||||||
return (
|
|
||||||
<Box sx={{ display: "flex", alignItems: "start" }}>
|
|
||||||
<LocalizationProvider
|
|
||||||
dateAdapter={AdapterDateFnsJalali}
|
|
||||||
localeText={
|
|
||||||
faIR.components.MuiLocalizationProvider.defaultProps
|
|
||||||
.localeText
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<MobileDateTimePicker
|
|
||||||
ampm={false}
|
|
||||||
onChange={(newValue) => {
|
|
||||||
const date = new Date(newValue);
|
|
||||||
const formattedDate = moment(date)
|
|
||||||
.locale("en")
|
|
||||||
.format("YYYY-MM-DD HH:mm");
|
|
||||||
column.setFilterValue(formattedDate);
|
|
||||||
}}
|
|
||||||
slotProps={{
|
|
||||||
textField: {
|
|
||||||
placeholder: "تاریخ خود را وارد کنید",
|
|
||||||
helperText: `${t("filter_mode")}: ${t(filterFnValue)}`,
|
|
||||||
sx: { minWidth: "120px" },
|
|
||||||
variant: "standard",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
value={
|
|
||||||
column.getFilterValue()
|
|
||||||
? new Date(column.getFilterValue())
|
|
||||||
: null
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</LocalizationProvider>
|
|
||||||
<IconButton
|
|
||||||
size="small"
|
|
||||||
onClick={() => {
|
|
||||||
column.setFilterValue(null);
|
|
||||||
}}
|
|
||||||
sx={{
|
|
||||||
color: column.getFilterValue()
|
|
||||||
? "rgba(0, 0, 0, 0.54)"
|
|
||||||
: "#bfbfbf",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ClearIcon />
|
|
||||||
</IconButton>
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
</DashboardLayouts>
|
||||||
},
|
);
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) =>
|
|
||||||
moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
|
|
||||||
id: "updated_at",
|
|
||||||
header: t("MachinaryOffice.updated_at"),
|
|
||||||
enableColumnFilter: false,
|
|
||||||
datatype: "numeric",
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) => row.navgan_id,
|
|
||||||
id: "navgan_id",
|
|
||||||
header: t("MachinaryOffice.navgan_id"),
|
|
||||||
enableColumnFilter: true,
|
|
||||||
datatype: "numeric",
|
|
||||||
filterFn: "equals",
|
|
||||||
maxSize: 100,
|
|
||||||
columnFilterModeOptions: [
|
|
||||||
"equals",
|
|
||||||
"notEquals",
|
|
||||||
"contains",
|
|
||||||
"lessThan",
|
|
||||||
"greaterThan",
|
|
||||||
"between",
|
|
||||||
],
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) => row.vehicle_type,
|
|
||||||
id: "vehicle_type",
|
|
||||||
header: t("MachinaryOffice.vehicle_type"),
|
|
||||||
enableColumnFilter: true,
|
|
||||||
datatype: "text",
|
|
||||||
filterFn: "contains",
|
|
||||||
columnFilterModeOptions: ["contains", "equals", "notEquals"],
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) => row.state_name,
|
|
||||||
id: "state_id",
|
|
||||||
header: t("MachinaryOffice.state_name"),
|
|
||||||
enableColumnFilter: false,
|
|
||||||
datatype: "numeric",
|
|
||||||
minSize: 300,
|
|
||||||
// filterFn: "equals",
|
|
||||||
// filterSelectOptions: [
|
|
||||||
// ],
|
|
||||||
// filterVariant: "select",
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
<DashboardLayouts>
|
|
||||||
<Box sx={{ px: 3 }}>
|
|
||||||
<DataTableStructure
|
|
||||||
tableUrl={GET_MACHINARY_OFFICE}
|
|
||||||
columns={columns}
|
|
||||||
selectableRow={false}
|
|
||||||
enableCustomToolbar={true}
|
|
||||||
// CustomToolbar={<TableToolbar />}
|
|
||||||
enableLastUpdate={true}
|
|
||||||
enablePinning={true}
|
|
||||||
enableDensityToggle={true}
|
|
||||||
enableColumnFilters={true}
|
|
||||||
enableHiding={true}
|
|
||||||
enableFullScreenToggle={false}
|
|
||||||
enableGlobalFilter={false}
|
|
||||||
enableColumnResizing={false} // if you want true this you shold change renderRowActions props ** see https://www.material-react-table.com/docs/guides/row-actions
|
|
||||||
enableRowActions={true}
|
|
||||||
renderRowActions={({ row }) => <TableRowActions row={row} />}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</DashboardLayouts>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DashboardMachinaryOfficeComponent;
|
export default DashboardMachinaryOfficeComponent;
|
||||||
|
|||||||
@@ -1,142 +1,134 @@
|
|||||||
import { CONFIRM_PASSENGER_BOSS } from "@/core/data/apiRoutes";
|
import {CONFIRM_PASSENGER_BOSS} from "@/core/data/apiRoutes";
|
||||||
import {
|
import {Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, TextField,} from "@mui/material";
|
||||||
Dialog,
|
import {useTranslations} from "next-intl";
|
||||||
DialogTitle,
|
import {useState} from "react";
|
||||||
DialogContent,
|
import {useFormik} from "formik";
|
||||||
DialogContentText,
|
|
||||||
DialogActions,
|
|
||||||
Button,
|
|
||||||
TextField,
|
|
||||||
} from "@mui/material";
|
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useState } from "react";
|
|
||||||
import { useFormik } from "formik";
|
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
import UploadSystem from "@/core/components/UploadSystem";
|
import UploadSystem from "@/core/components/UploadSystem";
|
||||||
import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
|
import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
|
||||||
import useDirection from "@/lib/app/hooks/useDirection";
|
import useDirection from "@/lib/app/hooks/useDirection";
|
||||||
|
|
||||||
const ConfirmForm = ({ open, handleClose, rowId, confirmData }) => {
|
const ConfirmForm = ({open, handleClose, rowId, confirmData}) => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const { directionApp } = useDirection();
|
const {directionApp} = useDirection();
|
||||||
const [proposedAmount, setProposedAmount] = useState("");
|
const [proposedAmount, setProposedAmount] = useState("");
|
||||||
const [description, setDescription] = useState("");
|
const [description, setDescription] = useState("");
|
||||||
const [selectedImage, setSelectedImage] = useState("");
|
const [selectedImage, setSelectedImage] = useState("");
|
||||||
const [fileType, setfileType] = useState(null);
|
const [fileType, setfileType] = useState(null);
|
||||||
const [fileName, setfileName] = useState(null);
|
const [fileName, setfileName] = useState(null);
|
||||||
const [showAddIcon, setShowAddIcon] = useState(true);
|
const [showAddIcon, setShowAddIcon] = useState(true);
|
||||||
|
|
||||||
//formik
|
//formik
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
proposed_amount: Yup.string().required(
|
proposed_amount: Yup.string().required(
|
||||||
t("ConfirmDialog.approved_amount_error")
|
t("ConfirmDialog.approved_amount_error")
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
proposed_amount: "",
|
proposed_amount: "",
|
||||||
description: "",
|
description: "",
|
||||||
},
|
},
|
||||||
validationSchema,
|
validationSchema,
|
||||||
onSubmit: () => {
|
onSubmit: () => {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("approved_amount", proposedAmount);
|
formData.append("approved_amount", proposedAmount);
|
||||||
if (description != "") formData.append("expert_description", description);
|
if (description != "") formData.append("expert_description", description);
|
||||||
handleClose();
|
handleClose();
|
||||||
confirmData(CONFIRM_PASSENGER_BOSS, rowId, formData);
|
confirmData(CONFIRM_PASSENGER_BOSS, rowId, formData);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleDescriptionChange = (event) => {
|
const handleDescriptionChange = (event) => {
|
||||||
setDescription(event.target.value);
|
setDescription(event.target.value);
|
||||||
};
|
};
|
||||||
const handleAmountChange = (event) => {
|
const handleAmountChange = (event) => {
|
||||||
if (/^\d*$/.test(event.target.value)) {
|
if (/^\d*$/.test(event.target.value)) {
|
||||||
setProposedAmount(event.target.value);
|
setProposedAmount(event.target.value);
|
||||||
}
|
}
|
||||||
formik.handleChange(event);
|
formik.handleChange(event);
|
||||||
};
|
};
|
||||||
const handleUploadChange = (event) => {
|
const handleUploadChange = (event) => {
|
||||||
const uploadedFile = event.target?.files?.[0];
|
const uploadedFile = event.target?.files?.[0];
|
||||||
if (uploadedFile) {
|
if (uploadedFile) {
|
||||||
const maxFileSize = 2 * 1024 * 1024;
|
const maxFileSize = 2 * 1024 * 1024;
|
||||||
if (uploadedFile.size > maxFileSize) {
|
if (uploadedFile.size > maxFileSize) {
|
||||||
UploadFileNotification(directionApp, t);
|
UploadFileNotification(directionApp, t);
|
||||||
event.target.value = "";
|
event.target.value = "";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const fileType = event.target?.files?.[0].type;
|
const fileType = event.target?.files?.[0].type;
|
||||||
const fileName = event.target?.files?.[0].name;
|
const fileName = event.target?.files?.[0].name;
|
||||||
setSelectedImage(URL.createObjectURL(uploadedFile));
|
setSelectedImage(URL.createObjectURL(uploadedFile));
|
||||||
setfileType(fileType);
|
setfileType(fileType);
|
||||||
setfileName(fileName);
|
setfileName(fileName);
|
||||||
formik.setFieldValue("confirm_img", uploadedFile);
|
formik.setFieldValue("confirm_img", uploadedFile);
|
||||||
setShowAddIcon(false);
|
setShowAddIcon(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={open}>
|
<Dialog open={open}>
|
||||||
<DialogTitle>{t("ConfirmDialog.confirm")}</DialogTitle>
|
<DialogTitle>{t("ConfirmDialog.confirm")}</DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<DialogContentText>{t("ConfirmDialog.context")}</DialogContentText>
|
<DialogContentText>{t("ConfirmDialog.context")}</DialogContentText>
|
||||||
<TextField
|
<TextField
|
||||||
name="description"
|
name="description"
|
||||||
multiline
|
multiline
|
||||||
rows={8}
|
rows={8}
|
||||||
placeholder={t("ConfirmDialog.description")}
|
placeholder={t("ConfirmDialog.description")}
|
||||||
value={description}
|
value={description}
|
||||||
onChange={handleDescriptionChange}
|
onChange={handleDescriptionChange}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
sx={{ mt: 1 }}
|
sx={{mt: 1}}
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
name="proposed_amount"
|
name="proposed_amount"
|
||||||
label={t("ConfirmDialog.approved_amount")}
|
label={t("ConfirmDialog.approved_amount")}
|
||||||
type="number"
|
type="number"
|
||||||
inputProps={{
|
inputProps={{
|
||||||
min: 0,
|
min: 0,
|
||||||
inputMode: "numeric",
|
inputMode: "numeric",
|
||||||
pattern: "[0-9]*",
|
pattern: "[0-9]*",
|
||||||
}}
|
}}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={proposedAmount}
|
value={proposedAmount}
|
||||||
onChange={handleAmountChange}
|
onChange={handleAmountChange}
|
||||||
onBlur={formik.handleBlur("proposed_amount")}
|
onBlur={formik.handleBlur("proposed_amount")}
|
||||||
error={
|
error={
|
||||||
formik.touched.proposed_amount &&
|
formik.touched.proposed_amount &&
|
||||||
Boolean(formik.errors.proposed_amount)
|
Boolean(formik.errors.proposed_amount)
|
||||||
}
|
}
|
||||||
helperText={
|
helperText={
|
||||||
formik.touched.proposed_amount && formik.errors.proposed_amount
|
formik.touched.proposed_amount && formik.errors.proposed_amount
|
||||||
}
|
}
|
||||||
sx={{ mt: 1 }}
|
sx={{mt: 1}}
|
||||||
fullWidth
|
fullWidth
|
||||||
/>
|
/>
|
||||||
<UploadSystem
|
<UploadSystem
|
||||||
selectedImage={selectedImage}
|
selectedImage={selectedImage}
|
||||||
handleUploadChange={handleUploadChange} // Pass the updated function directly
|
handleUploadChange={handleUploadChange} // Pass the updated function directly
|
||||||
setselectedImage={setSelectedImage}
|
setselectedImage={setSelectedImage}
|
||||||
setFieldValue={formik.setFieldValue} // Remove props.setFieldValue, use formik.setFieldValue
|
setFieldValue={formik.setFieldValue} // Remove props.setFieldValue, use formik.setFieldValue
|
||||||
fieldname="confirm_img"
|
fieldname="confirm_img"
|
||||||
fileType={fileType}
|
fileType={fileType}
|
||||||
fileName={fileName}
|
fileName={fileName}
|
||||||
imageAlt={t("app_name")}
|
imageAlt={t("app_name")}
|
||||||
imageSize={[250 /*width*/, 150 /*height*/]}
|
imageSize={[250 /*width*/, 150 /*height*/]}
|
||||||
setShowAddIcon={setShowAddIcon}
|
setShowAddIcon={setShowAddIcon}
|
||||||
showAddIcon={showAddIcon}
|
showAddIcon={showAddIcon}
|
||||||
/>
|
/>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button onClick={handleClose} color="secondary" autoFocus>
|
<Button onClick={handleClose} color="secondary" autoFocus>
|
||||||
{t("ConfirmDialog.button-cancel")}
|
{t("ConfirmDialog.button-cancel")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={formik.handleSubmit} color="primary">
|
<Button onClick={formik.handleSubmit} color="primary">
|
||||||
{t("ConfirmDialog.button-confirm")}
|
{t("ConfirmDialog.button-confirm")}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default ConfirmForm;
|
export default ConfirmForm;
|
||||||
|
|||||||
@@ -1,116 +1,108 @@
|
|||||||
import { REJECT_PASSENGER_BOSS } from "@/core/data/apiRoutes";
|
import {REJECT_PASSENGER_BOSS} from "@/core/data/apiRoutes";
|
||||||
import {
|
import {Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, TextField,} from "@mui/material";
|
||||||
Dialog,
|
import {useTranslations} from "next-intl";
|
||||||
DialogTitle,
|
import {useFormik} from "formik";
|
||||||
DialogContent,
|
|
||||||
DialogContentText,
|
|
||||||
DialogActions,
|
|
||||||
Button,
|
|
||||||
TextField,
|
|
||||||
} from "@mui/material";
|
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useFormik } from "formik";
|
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
import { useState } from "react";
|
import {useState} from "react";
|
||||||
import UploadSystem from "@/core/components/UploadSystem";
|
import UploadSystem from "@/core/components/UploadSystem";
|
||||||
import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
|
import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
|
||||||
import useDirection from "@/lib/app/hooks/useDirection";
|
import useDirection from "@/lib/app/hooks/useDirection";
|
||||||
|
|
||||||
const RejectForm = ({ open, handleClose, rowId, rejectData }) => {
|
const RejectForm = ({open, handleClose, rowId, rejectData}) => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const { directionApp } = useDirection();
|
const {directionApp} = useDirection();
|
||||||
const [description, setDescription] = useState("");
|
const [description, setDescription] = useState("");
|
||||||
const [selectedImage, setSelectedImage] = useState("");
|
const [selectedImage, setSelectedImage] = useState("");
|
||||||
const [fileType, setfileType] = useState(null);
|
const [fileType, setfileType] = useState(null);
|
||||||
const [fileName, setfileName] = useState(null);
|
const [fileName, setfileName] = useState(null);
|
||||||
const [showAddIcon, setShowAddIcon] = useState(true);
|
const [showAddIcon, setShowAddIcon] = useState(true);
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
description: Yup.string().required(t("RejectDialog.description_error")),
|
description: Yup.string().required(t("RejectDialog.description_error")),
|
||||||
});
|
});
|
||||||
|
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
description: "",
|
description: "",
|
||||||
},
|
},
|
||||||
validationSchema,
|
validationSchema,
|
||||||
onSubmit: () => {
|
onSubmit: () => {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("expert_description", description);
|
formData.append("expert_description", description);
|
||||||
handleClose();
|
handleClose();
|
||||||
rejectData(REJECT_PASSENGER_BOSS, rowId, formData);
|
rejectData(REJECT_PASSENGER_BOSS, rowId, formData);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleDescriptionChange = (event) => {
|
const handleDescriptionChange = (event) => {
|
||||||
setDescription(event.target.value);
|
setDescription(event.target.value);
|
||||||
formik.handleChange(event);
|
formik.handleChange(event);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUploadChange = (event) => {
|
const handleUploadChange = (event) => {
|
||||||
const uploadedFile = event.target?.files?.[0];
|
const uploadedFile = event.target?.files?.[0];
|
||||||
if (uploadedFile) {
|
if (uploadedFile) {
|
||||||
const maxFileSize = 2 * 1024 * 1024;
|
const maxFileSize = 2 * 1024 * 1024;
|
||||||
if (uploadedFile.size > maxFileSize) {
|
if (uploadedFile.size > maxFileSize) {
|
||||||
UploadFileNotification(directionApp, t);
|
UploadFileNotification(directionApp, t);
|
||||||
event.target.value = "";
|
event.target.value = "";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const fileType = event.target?.files?.[0].type;
|
const fileType = event.target?.files?.[0].type;
|
||||||
const fileName = event.target?.files?.[0].name;
|
const fileName = event.target?.files?.[0].name;
|
||||||
setSelectedImage(URL.createObjectURL(uploadedFile));
|
setSelectedImage(URL.createObjectURL(uploadedFile));
|
||||||
setfileType(fileType);
|
setfileType(fileType);
|
||||||
setfileName(fileName);
|
setfileName(fileName);
|
||||||
formik.setFieldValue("reject_img", uploadedFile);
|
formik.setFieldValue("reject_img", uploadedFile);
|
||||||
setShowAddIcon(false);
|
setShowAddIcon(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={open}>
|
<Dialog open={open}>
|
||||||
<DialogTitle>{t("RejectDialog.reject")}</DialogTitle>
|
<DialogTitle>{t("RejectDialog.reject")}</DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<DialogContentText>{t("RejectDialog.context")}</DialogContentText>
|
<DialogContentText>{t("RejectDialog.context")}</DialogContentText>
|
||||||
<TextField
|
<TextField
|
||||||
name="description"
|
name="description"
|
||||||
multiline
|
multiline
|
||||||
rows={8}
|
rows={8}
|
||||||
placeholder={t("RejectDialog.description")}
|
placeholder={t("RejectDialog.description")}
|
||||||
value={description}
|
value={description}
|
||||||
onChange={handleDescriptionChange}
|
onChange={handleDescriptionChange}
|
||||||
onBlur={formik.handleBlur("description")}
|
onBlur={formik.handleBlur("description")}
|
||||||
error={
|
error={
|
||||||
formik.touched.description && Boolean(formik.errors.description)
|
formik.touched.description && Boolean(formik.errors.description)
|
||||||
}
|
}
|
||||||
helperText={formik.touched.description && formik.errors.description}
|
helperText={formik.touched.description && formik.errors.description}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
sx={{ mt: 1 }}
|
sx={{mt: 1}}
|
||||||
/>
|
/>
|
||||||
<UploadSystem
|
<UploadSystem
|
||||||
selectedImage={selectedImage}
|
selectedImage={selectedImage}
|
||||||
handleUploadChange={handleUploadChange} // Pass the updated function directly
|
handleUploadChange={handleUploadChange} // Pass the updated function directly
|
||||||
setselectedImage={setSelectedImage}
|
setselectedImage={setSelectedImage}
|
||||||
setFieldValue={formik.setFieldValue} // Remove props.setFieldValue, use formik.setFieldValue
|
setFieldValue={formik.setFieldValue} // Remove props.setFieldValue, use formik.setFieldValue
|
||||||
fieldname="reject_img"
|
fieldname="reject_img"
|
||||||
fileType={fileType}
|
fileType={fileType}
|
||||||
fileName={fileName}
|
fileName={fileName}
|
||||||
imageAlt={t("app_name")}
|
imageAlt={t("app_name")}
|
||||||
imageSize={[250 /*width*/, 150 /*height*/]}
|
imageSize={[250 /*width*/, 150 /*height*/]}
|
||||||
setShowAddIcon={setShowAddIcon}
|
setShowAddIcon={setShowAddIcon}
|
||||||
showAddIcon={showAddIcon}
|
showAddIcon={showAddIcon}
|
||||||
/>
|
/>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button onClick={handleClose} color="secondary" autoFocus>
|
<Button onClick={handleClose} color="secondary" autoFocus>
|
||||||
{t("RejectDialog.button-cancel")}
|
{t("RejectDialog.button-cancel")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={formik.handleSubmit} color="primary">
|
<Button onClick={formik.handleSubmit} color="primary">
|
||||||
{t("RejectDialog.button-reject")}
|
{t("RejectDialog.button-reject")}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default RejectForm;
|
export default RejectForm;
|
||||||
|
|||||||
@@ -1,60 +1,60 @@
|
|||||||
import ThumbUpAltIcon from "@mui/icons-material/ThumbUpAlt";
|
import ThumbUpAltIcon from "@mui/icons-material/ThumbUpAlt";
|
||||||
import ThumbDownIcon from "@mui/icons-material/ThumbDown";
|
import ThumbDownIcon from "@mui/icons-material/ThumbDown";
|
||||||
import { Box, IconButton, Tooltip } from "@mui/material";
|
import {Box, IconButton, Tooltip} from "@mui/material";
|
||||||
import { useContext } from "react";
|
import {useContext} from "react";
|
||||||
import ConfirmForm from "./Form/ConfirmForm";
|
import ConfirmForm from "./Form/ConfirmForm";
|
||||||
import RejectForm from "./Form/RejectForm";
|
import RejectForm from "./Form/RejectForm";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import { DataTableContext } from "@/lib/app/contexts/DatatableContext";
|
import {DataTableContext} from "@/lib/app/contexts/DatatableContext";
|
||||||
|
|
||||||
const TableRowActions = ({ row }) => {
|
const TableRowActions = ({row}) => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const {
|
const {
|
||||||
openConfirmDialog,
|
openConfirmDialog,
|
||||||
openRejectDialog,
|
openRejectDialog,
|
||||||
handleOpenConfirmDialog,
|
handleOpenConfirmDialog,
|
||||||
handleOpenRejectDialog,
|
handleOpenRejectDialog,
|
||||||
handleCloseConfirmDialog,
|
handleCloseConfirmDialog,
|
||||||
handleCloseRejectDialog,
|
handleCloseRejectDialog,
|
||||||
rowId,
|
rowId,
|
||||||
confirmData,
|
confirmData,
|
||||||
rejectData,
|
rejectData,
|
||||||
} = useContext(DataTableContext);
|
} = useContext(DataTableContext);
|
||||||
return (
|
return (
|
||||||
<Box sx={{ display: "flex", flexWrap: "nowrap", gap: "8px" }}>
|
<Box sx={{display: "flex", flexWrap: "nowrap", gap: "8px"}}>
|
||||||
<Tooltip title={t("ConfirmDialog.confirm")}>
|
<Tooltip title={t("ConfirmDialog.confirm")}>
|
||||||
<IconButton
|
<IconButton
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleOpenConfirmDialog(row);
|
handleOpenConfirmDialog(row);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ThumbUpAltIcon />
|
<ThumbUpAltIcon/>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
{openConfirmDialog && (
|
{openConfirmDialog && (
|
||||||
<ConfirmForm
|
<ConfirmForm
|
||||||
rowId={rowId}
|
rowId={rowId}
|
||||||
open={openConfirmDialog}
|
open={openConfirmDialog}
|
||||||
handleClose={handleCloseConfirmDialog}
|
handleClose={handleCloseConfirmDialog}
|
||||||
confirmData={confirmData}
|
confirmData={confirmData}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Tooltip title={t("RejectDialog.reject")}>
|
<Tooltip title={t("RejectDialog.reject")}>
|
||||||
<IconButton color="primary" onClick={() => handleOpenRejectDialog(row)}>
|
<IconButton color="primary" onClick={() => handleOpenRejectDialog(row)}>
|
||||||
<ThumbDownIcon />
|
<ThumbDownIcon/>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
{openRejectDialog && (
|
{openRejectDialog && (
|
||||||
<RejectForm
|
<RejectForm
|
||||||
rowId={rowId}
|
rowId={rowId}
|
||||||
open={openRejectDialog}
|
open={openRejectDialog}
|
||||||
handleClose={handleCloseRejectDialog}
|
handleClose={handleCloseRejectDialog}
|
||||||
rejectData={rejectData}
|
rejectData={rejectData}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TableRowActions;
|
export default TableRowActions;
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { Stack, Tooltip } from "@mui/material";
|
import {Stack, Tooltip} from "@mui/material";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
|
|
||||||
function TableToolbar() {
|
function TableToolbar() {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
return (
|
return (
|
||||||
<Stack direction={"row"} spacing={2}>
|
<Stack direction={"row"} spacing={2}>
|
||||||
<Tooltip title={t("add")} arrow placement="right"></Tooltip>
|
<Tooltip title={t("add")} arrow placement="right"></Tooltip>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default TableToolbar;
|
export default TableToolbar;
|
||||||
|
|||||||
@@ -1,245 +1,242 @@
|
|||||||
import DataTableStructure from "@/core/components/DatatableStructure";
|
import DataTableStructure from "@/core/components/DatatableStructure";
|
||||||
import DashboardLayouts from "@/layouts/dashboardLayouts";
|
import DashboardLayouts from "@/layouts/dashboardLayouts";
|
||||||
import { Box, IconButton, Typography } from "@mui/material";
|
import {Box, IconButton, Typography} from "@mui/material";
|
||||||
import ClearIcon from "@mui/icons-material/Clear";
|
import ClearIcon from "@mui/icons-material/Clear";
|
||||||
import { useMemo } from "react";
|
import {useMemo} from "react";
|
||||||
// import TableToolbar from "./TableTollbar";
|
// import TableToolbar from "./TableTollbar";
|
||||||
import { GET_PASSENGER_BOSS } from "@/core/data/apiRoutes";
|
import {GET_PASSENGER_BOSS} from "@/core/data/apiRoutes";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import TableRowActions from "./TableRowActions";
|
import TableRowActions from "./TableRowActions";
|
||||||
import {
|
import {LocalizationProvider, MobileDateTimePicker,} from "@mui/x-date-pickers";
|
||||||
LocalizationProvider,
|
import {AdapterDateFnsJalali} from "@mui/x-date-pickers/AdapterDateFnsJalali";
|
||||||
MobileDateTimePicker,
|
|
||||||
} from "@mui/x-date-pickers";
|
|
||||||
import { AdapterDateFnsJalali } from "@mui/x-date-pickers/AdapterDateFnsJalali";
|
|
||||||
import moment from "jalali-moment";
|
import moment from "jalali-moment";
|
||||||
import { faIR } from "@mui/x-date-pickers/locales";
|
import {faIR} from "@mui/x-date-pickers/locales";
|
||||||
|
|
||||||
function DashboardPassengerOfficeComponent() {
|
function DashboardPassengerOfficeComponent() {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
|
|
||||||
const columns = useMemo(
|
const columns = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
accessorFn: (row) => row.id,
|
accessorFn: (row) => row.id,
|
||||||
id: "id",
|
id: "id",
|
||||||
header: t("PassengerBoss.id"),
|
header: t("PassengerBoss.id"),
|
||||||
enableColumnFilter: true,
|
enableColumnFilter: true,
|
||||||
datatype: "numeric",
|
datatype: "numeric",
|
||||||
filterFn: "equals",
|
filterFn: "equals",
|
||||||
maxSize: 100,
|
maxSize: 100,
|
||||||
columnFilterModeOptions: [
|
columnFilterModeOptions: [
|
||||||
"equals",
|
"equals",
|
||||||
"notEquals",
|
"notEquals",
|
||||||
"contains",
|
"contains",
|
||||||
"lessThan",
|
"lessThan",
|
||||||
"greaterThan",
|
"greaterThan",
|
||||||
"between",
|
"between",
|
||||||
|
],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.name,
|
||||||
|
id: "name",
|
||||||
|
header: t("PassengerBoss.name"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "text",
|
||||||
|
filterFn: "contains",
|
||||||
|
columnFilterModeOptions: ["contains", "equals", "notEquals"],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.national_id,
|
||||||
|
id: "national_id",
|
||||||
|
header: t("PassengerBoss.national_id"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "numeric",
|
||||||
|
filterFn: "equals",
|
||||||
|
columnFilterModeOptions: [
|
||||||
|
"equals",
|
||||||
|
"notEquals",
|
||||||
|
"contains",
|
||||||
|
"lessThan",
|
||||||
|
"greaterThan",
|
||||||
|
"between",
|
||||||
|
],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.phone_number,
|
||||||
|
id: "phone_number",
|
||||||
|
header: t("PassengerBoss.phone_number"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "numeric",
|
||||||
|
filterFn: "equals",
|
||||||
|
columnFilterModeOptions: [
|
||||||
|
"equals",
|
||||||
|
"notEquals",
|
||||||
|
"contains",
|
||||||
|
"lessThan",
|
||||||
|
"greaterThan",
|
||||||
|
"between",
|
||||||
|
],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) =>
|
||||||
|
moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
|
||||||
|
id: "created_at",
|
||||||
|
header: t("PassengerBoss.created_at"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "date",
|
||||||
|
filterFn: "lessThan",
|
||||||
|
minSize: 200,
|
||||||
|
columnFilterModeOptions: ["lessThan", "greaterThan"],
|
||||||
|
Cell: ({renderedCellValue}) => {
|
||||||
|
return <Typography variant="body2">{renderedCellValue}</Typography>;
|
||||||
|
},
|
||||||
|
Header: ({column}) => <em>{column.columnDef.header}</em>,
|
||||||
|
Filter: ({column}) => {
|
||||||
|
const filterFnValue = column.columnDef._filterFn;
|
||||||
|
return (
|
||||||
|
<Box sx={{display: "flex", alignItems: "start"}}>
|
||||||
|
<LocalizationProvider
|
||||||
|
dateAdapter={AdapterDateFnsJalali}
|
||||||
|
localeText={
|
||||||
|
faIR.components.MuiLocalizationProvider.defaultProps
|
||||||
|
.localeText
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<MobileDateTimePicker
|
||||||
|
ampm={false}
|
||||||
|
onChange={(newValue) => {
|
||||||
|
const date = new Date(newValue);
|
||||||
|
const formattedDate = moment(date)
|
||||||
|
.locale("en")
|
||||||
|
.format("YYYY-MM-DD HH:mm");
|
||||||
|
column.setFilterValue(formattedDate);
|
||||||
|
}}
|
||||||
|
slotProps={{
|
||||||
|
textField: {
|
||||||
|
placeholder: "تاریخ خود را وارد کنید",
|
||||||
|
helperText: `${t("filter_mode")}: ${t(filterFnValue)}`,
|
||||||
|
sx: {minWidth: "120px"},
|
||||||
|
variant: "standard",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
value={
|
||||||
|
column.getFilterValue()
|
||||||
|
? new Date(column.getFilterValue())
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</LocalizationProvider>
|
||||||
|
<IconButton
|
||||||
|
size="small"
|
||||||
|
onClick={() => {
|
||||||
|
column.setFilterValue(null);
|
||||||
|
}}
|
||||||
|
sx={{
|
||||||
|
color: column.getFilterValue()
|
||||||
|
? "rgba(0, 0, 0, 0.54)"
|
||||||
|
: "#bfbfbf",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ClearIcon/>
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) =>
|
||||||
|
moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
|
||||||
|
id: "updated_at",
|
||||||
|
header: t("PassengerBoss.updated_at"),
|
||||||
|
enableColumnFilter: false,
|
||||||
|
datatype: "numeric",
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.navgan_id,
|
||||||
|
id: "navgan_id",
|
||||||
|
header: t("PassengerBoss.navgan_id"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "numeric",
|
||||||
|
filterFn: "equals",
|
||||||
|
maxSize: 100,
|
||||||
|
columnFilterModeOptions: [
|
||||||
|
"equals",
|
||||||
|
"notEquals",
|
||||||
|
"contains",
|
||||||
|
"lessThan",
|
||||||
|
"greaterThan",
|
||||||
|
"between",
|
||||||
|
],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.vehicle_type,
|
||||||
|
id: "vehicle_type",
|
||||||
|
header: t("PassengerBoss.vehicle_type"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "text",
|
||||||
|
filterFn: "contains",
|
||||||
|
columnFilterModeOptions: ["contains", "equals", "notEquals"],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.state_name,
|
||||||
|
id: "state_id",
|
||||||
|
header: t("PassengerBoss.state_name"),
|
||||||
|
enableColumnFilter: false,
|
||||||
|
datatype: "numeric",
|
||||||
|
minSize: 300,
|
||||||
|
// filterFn: "equals",
|
||||||
|
// filterSelectOptions: [
|
||||||
|
// ],
|
||||||
|
// filterVariant: "select",
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
Cell: ({ renderedCellValue }) => (
|
[]
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
);
|
||||||
),
|
return (
|
||||||
},
|
<DashboardLayouts>
|
||||||
{
|
<Box sx={{px: 3}}>
|
||||||
accessorFn: (row) => row.name,
|
<DataTableStructure
|
||||||
id: "name",
|
tableUrl={GET_PASSENGER_BOSS}
|
||||||
header: t("PassengerBoss.name"),
|
columns={columns}
|
||||||
enableColumnFilter: true,
|
selectableRow={false}
|
||||||
datatype: "text",
|
enableCustomToolbar={true}
|
||||||
filterFn: "contains",
|
// CustomToolbar={<TableToolbar />}
|
||||||
columnFilterModeOptions: ["contains", "equals", "notEquals"],
|
enableLastUpdate={true}
|
||||||
Cell: ({ renderedCellValue }) => (
|
enablePinning={true}
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
enableDensityToggle={true}
|
||||||
),
|
enableColumnFilters={true}
|
||||||
},
|
enableHiding={true}
|
||||||
{
|
enableFullScreenToggle={false}
|
||||||
accessorFn: (row) => row.national_id,
|
enableGlobalFilter={false}
|
||||||
id: "national_id",
|
enableColumnResizing={false} // if you want true this you shold change renderRowActions props ** see https://www.material-react-table.com/docs/guides/row-actions
|
||||||
header: t("PassengerBoss.national_id"),
|
enableRowActions={true}
|
||||||
enableColumnFilter: true,
|
renderRowActions={({row}) => <TableRowActions row={row}/>}
|
||||||
datatype: "numeric",
|
|
||||||
filterFn: "equals",
|
|
||||||
columnFilterModeOptions: [
|
|
||||||
"equals",
|
|
||||||
"notEquals",
|
|
||||||
"contains",
|
|
||||||
"lessThan",
|
|
||||||
"greaterThan",
|
|
||||||
"between",
|
|
||||||
],
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) => row.phone_number,
|
|
||||||
id: "phone_number",
|
|
||||||
header: t("PassengerBoss.phone_number"),
|
|
||||||
enableColumnFilter: true,
|
|
||||||
datatype: "numeric",
|
|
||||||
filterFn: "equals",
|
|
||||||
columnFilterModeOptions: [
|
|
||||||
"equals",
|
|
||||||
"notEquals",
|
|
||||||
"contains",
|
|
||||||
"lessThan",
|
|
||||||
"greaterThan",
|
|
||||||
"between",
|
|
||||||
],
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) =>
|
|
||||||
moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
|
|
||||||
id: "created_at",
|
|
||||||
header: t("PassengerBoss.created_at"),
|
|
||||||
enableColumnFilter: true,
|
|
||||||
datatype: "date",
|
|
||||||
filterFn: "lessThan",
|
|
||||||
minSize: 200,
|
|
||||||
columnFilterModeOptions: ["lessThan", "greaterThan"],
|
|
||||||
Cell: ({ renderedCellValue }) => {
|
|
||||||
return <Typography variant="body2">{renderedCellValue}</Typography>;
|
|
||||||
},
|
|
||||||
Header: ({ column }) => <em>{column.columnDef.header}</em>,
|
|
||||||
Filter: ({ column }) => {
|
|
||||||
const filterFnValue = column.columnDef._filterFn;
|
|
||||||
return (
|
|
||||||
<Box sx={{ display: "flex", alignItems: "start" }}>
|
|
||||||
<LocalizationProvider
|
|
||||||
dateAdapter={AdapterDateFnsJalali}
|
|
||||||
localeText={
|
|
||||||
faIR.components.MuiLocalizationProvider.defaultProps
|
|
||||||
.localeText
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<MobileDateTimePicker
|
|
||||||
ampm={false}
|
|
||||||
onChange={(newValue) => {
|
|
||||||
const date = new Date(newValue);
|
|
||||||
const formattedDate = moment(date)
|
|
||||||
.locale("en")
|
|
||||||
.format("YYYY-MM-DD HH:mm");
|
|
||||||
column.setFilterValue(formattedDate);
|
|
||||||
}}
|
|
||||||
slotProps={{
|
|
||||||
textField: {
|
|
||||||
placeholder: "تاریخ خود را وارد کنید",
|
|
||||||
helperText: `${t("filter_mode")}: ${t(filterFnValue)}`,
|
|
||||||
sx: { minWidth: "120px" },
|
|
||||||
variant: "standard",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
value={
|
|
||||||
column.getFilterValue()
|
|
||||||
? new Date(column.getFilterValue())
|
|
||||||
: null
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</LocalizationProvider>
|
|
||||||
<IconButton
|
|
||||||
size="small"
|
|
||||||
onClick={() => {
|
|
||||||
column.setFilterValue(null);
|
|
||||||
}}
|
|
||||||
sx={{
|
|
||||||
color: column.getFilterValue()
|
|
||||||
? "rgba(0, 0, 0, 0.54)"
|
|
||||||
: "#bfbfbf",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ClearIcon />
|
|
||||||
</IconButton>
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
</DashboardLayouts>
|
||||||
},
|
);
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) =>
|
|
||||||
moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
|
|
||||||
id: "updated_at",
|
|
||||||
header: t("PassengerBoss.updated_at"),
|
|
||||||
enableColumnFilter: false,
|
|
||||||
datatype: "numeric",
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) => row.navgan_id,
|
|
||||||
id: "navgan_id",
|
|
||||||
header: t("PassengerBoss.navgan_id"),
|
|
||||||
enableColumnFilter: true,
|
|
||||||
datatype: "numeric",
|
|
||||||
filterFn: "equals",
|
|
||||||
maxSize: 100,
|
|
||||||
columnFilterModeOptions: [
|
|
||||||
"equals",
|
|
||||||
"notEquals",
|
|
||||||
"contains",
|
|
||||||
"lessThan",
|
|
||||||
"greaterThan",
|
|
||||||
"between",
|
|
||||||
],
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) => row.vehicle_type,
|
|
||||||
id: "vehicle_type",
|
|
||||||
header: t("PassengerBoss.vehicle_type"),
|
|
||||||
enableColumnFilter: true,
|
|
||||||
datatype: "text",
|
|
||||||
filterFn: "contains",
|
|
||||||
columnFilterModeOptions: ["contains", "equals", "notEquals"],
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) => row.state_name,
|
|
||||||
id: "state_id",
|
|
||||||
header: t("PassengerBoss.state_name"),
|
|
||||||
enableColumnFilter: false,
|
|
||||||
datatype: "numeric",
|
|
||||||
minSize: 300,
|
|
||||||
// filterFn: "equals",
|
|
||||||
// filterSelectOptions: [
|
|
||||||
// ],
|
|
||||||
// filterVariant: "select",
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
<DashboardLayouts>
|
|
||||||
<Box sx={{ px: 3 }}>
|
|
||||||
<DataTableStructure
|
|
||||||
tableUrl={GET_PASSENGER_BOSS}
|
|
||||||
columns={columns}
|
|
||||||
selectableRow={false}
|
|
||||||
enableCustomToolbar={true}
|
|
||||||
// CustomToolbar={<TableToolbar />}
|
|
||||||
enableLastUpdate={true}
|
|
||||||
enablePinning={true}
|
|
||||||
enableDensityToggle={true}
|
|
||||||
enableColumnFilters={true}
|
|
||||||
enableHiding={true}
|
|
||||||
enableFullScreenToggle={false}
|
|
||||||
enableGlobalFilter={false}
|
|
||||||
enableColumnResizing={false} // if you want true this you shold change renderRowActions props ** see https://www.material-react-table.com/docs/guides/row-actions
|
|
||||||
enableRowActions={true}
|
|
||||||
renderRowActions={({ row }) => <TableRowActions row={row} />}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</DashboardLayouts>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DashboardPassengerOfficeComponent;
|
export default DashboardPassengerOfficeComponent;
|
||||||
|
|||||||
@@ -1,106 +1,98 @@
|
|||||||
import UploadSystem from "@/core/components/UploadSystem";
|
import UploadSystem from "@/core/components/UploadSystem";
|
||||||
import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
|
import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
|
||||||
import { CONFIRM_PASSENGER_OFFICE } from "@/core/data/apiRoutes";
|
import {CONFIRM_PASSENGER_OFFICE} from "@/core/data/apiRoutes";
|
||||||
import useDirection from "@/lib/app/hooks/useDirection";
|
import useDirection from "@/lib/app/hooks/useDirection";
|
||||||
import {
|
import {Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, TextField,} from "@mui/material";
|
||||||
Dialog,
|
import {useFormik} from "formik";
|
||||||
DialogTitle,
|
import {useTranslations} from "next-intl";
|
||||||
DialogContent,
|
import {useState} from "react";
|
||||||
DialogContentText,
|
|
||||||
DialogActions,
|
|
||||||
Button,
|
|
||||||
TextField,
|
|
||||||
} from "@mui/material";
|
|
||||||
import { useFormik } from "formik";
|
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useRef, useState } from "react";
|
|
||||||
|
|
||||||
const ConfirmForm = ({ open, handleClose, rowId, confirmData }) => {
|
const ConfirmForm = ({open, handleClose, rowId, confirmData}) => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const { directionApp } = useDirection();
|
const {directionApp} = useDirection();
|
||||||
const [description, setDescription] = useState("");
|
const [description, setDescription] = useState("");
|
||||||
const [selectedImage, setSelectedImage] = useState("");
|
const [selectedImage, setSelectedImage] = useState("");
|
||||||
const [fileType, setfileType] = useState(null);
|
const [fileType, setfileType] = useState(null);
|
||||||
const [fileName, setfileName] = useState(null);
|
const [fileName, setfileName] = useState(null);
|
||||||
const [showAddIcon, setShowAddIcon] = useState(true);
|
const [showAddIcon, setShowAddIcon] = useState(true);
|
||||||
|
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
description: "",
|
description: "",
|
||||||
},
|
},
|
||||||
onSubmit: () => {
|
onSubmit: () => {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
if (description !== "")
|
if (description !== "")
|
||||||
formData.append("expert_description", description);
|
formData.append("expert_description", description);
|
||||||
handleClose();
|
handleClose();
|
||||||
confirmData(CONFIRM_PASSENGER_OFFICE, rowId, formData);
|
confirmData(CONFIRM_PASSENGER_OFFICE, rowId, formData);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleDescriptionChange = (event) => {
|
const handleDescriptionChange = (event) => {
|
||||||
setDescription(event.target.value);
|
setDescription(event.target.value);
|
||||||
formik.handleChange(event);
|
formik.handleChange(event);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUploadChange = (event) => {
|
const handleUploadChange = (event) => {
|
||||||
const uploadedFile = event.target?.files?.[0];
|
const uploadedFile = event.target?.files?.[0];
|
||||||
if (uploadedFile) {
|
if (uploadedFile) {
|
||||||
const maxFileSize = 2 * 1024 * 1024;
|
const maxFileSize = 2 * 1024 * 1024;
|
||||||
if (uploadedFile.size > maxFileSize) {
|
if (uploadedFile.size > maxFileSize) {
|
||||||
UploadFileNotification(directionApp, t);
|
UploadFileNotification(directionApp, t);
|
||||||
event.target.value = "";
|
event.target.value = "";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const fileType = event.target?.files?.[0].type;
|
const fileType = event.target?.files?.[0].type;
|
||||||
const fileName = event.target?.files?.[0].name;
|
const fileName = event.target?.files?.[0].name;
|
||||||
setSelectedImage(URL.createObjectURL(uploadedFile));
|
setSelectedImage(URL.createObjectURL(uploadedFile));
|
||||||
setfileType(fileType);
|
setfileType(fileType);
|
||||||
setfileName(fileName);
|
setfileName(fileName);
|
||||||
formik.setFieldValue("confirm_img", uploadedFile);
|
formik.setFieldValue("confirm_img", uploadedFile);
|
||||||
setShowAddIcon(false);
|
setShowAddIcon(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={open}>
|
<Dialog open={open}>
|
||||||
<DialogTitle>{t("ConfirmDialog.confirm")}</DialogTitle>
|
<DialogTitle>{t("ConfirmDialog.confirm")}</DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<DialogContentText>{t("ConfirmDialog.context")}</DialogContentText>
|
<DialogContentText>{t("ConfirmDialog.context")}</DialogContentText>
|
||||||
<TextField
|
<TextField
|
||||||
name="description"
|
name="description"
|
||||||
multiline
|
multiline
|
||||||
rows={8}
|
rows={8}
|
||||||
placeholder={t("ConfirmDialog.description")}
|
placeholder={t("ConfirmDialog.description")}
|
||||||
value={description}
|
value={description}
|
||||||
onChange={handleDescriptionChange}
|
onChange={handleDescriptionChange}
|
||||||
onBlur={formik.handleBlur("description")}
|
onBlur={formik.handleBlur("description")}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
sx={{ mt: 1 }}
|
sx={{mt: 1}}
|
||||||
/>
|
/>
|
||||||
<UploadSystem
|
<UploadSystem
|
||||||
selectedImage={selectedImage}
|
selectedImage={selectedImage}
|
||||||
handleUploadChange={handleUploadChange} // Pass the updated function directly
|
handleUploadChange={handleUploadChange} // Pass the updated function directly
|
||||||
setselectedImage={setSelectedImage}
|
setselectedImage={setSelectedImage}
|
||||||
setFieldValue={formik.setFieldValue} // Remove props.setFieldValue, use formik.setFieldValue
|
setFieldValue={formik.setFieldValue} // Remove props.setFieldValue, use formik.setFieldValue
|
||||||
fieldname="confirm_img"
|
fieldname="confirm_img"
|
||||||
fileType={fileType}
|
fileType={fileType}
|
||||||
fileName={fileName}
|
fileName={fileName}
|
||||||
imageAlt={t("app_name")}
|
imageAlt={t("app_name")}
|
||||||
imageSize={[250 /*width*/, 150 /*height*/]}
|
imageSize={[250 /*width*/, 150 /*height*/]}
|
||||||
setShowAddIcon={setShowAddIcon}
|
setShowAddIcon={setShowAddIcon}
|
||||||
showAddIcon={showAddIcon}
|
showAddIcon={showAddIcon}
|
||||||
/>
|
/>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button onClick={handleClose} color="secondary" autoFocus>
|
<Button onClick={handleClose} color="secondary" autoFocus>
|
||||||
{t("ConfirmDialog.button-cancel")}
|
{t("ConfirmDialog.button-cancel")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={formik.handleSubmit} color="primary">
|
<Button onClick={formik.handleSubmit} color="primary">
|
||||||
{t("ConfirmDialog.button-confirm")}
|
{t("ConfirmDialog.button-confirm")}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default ConfirmForm;
|
export default ConfirmForm;
|
||||||
|
|||||||
@@ -1,114 +1,106 @@
|
|||||||
import { REJECT_PASSENGER_OFFICE } from "@/core/data/apiRoutes";
|
import {REJECT_PASSENGER_OFFICE} from "@/core/data/apiRoutes";
|
||||||
import {
|
import {Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, TextField,} from "@mui/material";
|
||||||
Dialog,
|
import {useTranslations} from "next-intl";
|
||||||
DialogTitle,
|
import {useFormik} from "formik";
|
||||||
DialogContent,
|
|
||||||
DialogContentText,
|
|
||||||
DialogActions,
|
|
||||||
Button,
|
|
||||||
TextField,
|
|
||||||
} from "@mui/material";
|
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useFormik } from "formik";
|
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
import { useState } from "react";
|
import {useState} from "react";
|
||||||
import UploadSystem from "@/core/components/UploadSystem";
|
import UploadSystem from "@/core/components/UploadSystem";
|
||||||
import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
|
import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
|
||||||
import useDirection from "@/lib/app/hooks/useDirection";
|
import useDirection from "@/lib/app/hooks/useDirection";
|
||||||
|
|
||||||
const RejectForm = ({ open, handleClose, rowId, rejectData }) => {
|
const RejectForm = ({open, handleClose, rowId, rejectData}) => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const { directionApp } = useDirection();
|
const {directionApp} = useDirection();
|
||||||
const [description, setDescription] = useState("");
|
const [description, setDescription] = useState("");
|
||||||
const [selectedImage, setSelectedImage] = useState("");
|
const [selectedImage, setSelectedImage] = useState("");
|
||||||
const [fileType, setfileType] = useState(null);
|
const [fileType, setfileType] = useState(null);
|
||||||
const [fileName, setfileName] = useState(null);
|
const [fileName, setfileName] = useState(null);
|
||||||
const [showAddIcon, setShowAddIcon] = useState(true);
|
const [showAddIcon, setShowAddIcon] = useState(true);
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
description: Yup.string().required(t("RejectDialog.description_error")),
|
description: Yup.string().required(t("RejectDialog.description_error")),
|
||||||
});
|
});
|
||||||
|
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
description: "",
|
description: "",
|
||||||
},
|
},
|
||||||
validationSchema,
|
validationSchema,
|
||||||
onSubmit: () => {
|
onSubmit: () => {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("expert_description", description);
|
formData.append("expert_description", description);
|
||||||
handleClose();
|
handleClose();
|
||||||
rejectData(REJECT_PASSENGER_OFFICE, rowId, formData);
|
rejectData(REJECT_PASSENGER_OFFICE, rowId, formData);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleDescriptionChange = (event) => {
|
const handleDescriptionChange = (event) => {
|
||||||
setDescription(event.target.value);
|
setDescription(event.target.value);
|
||||||
formik.handleChange(event);
|
formik.handleChange(event);
|
||||||
};
|
};
|
||||||
const handleUploadChange = (event) => {
|
const handleUploadChange = (event) => {
|
||||||
const uploadedFile = event.target?.files?.[0];
|
const uploadedFile = event.target?.files?.[0];
|
||||||
if (uploadedFile) {
|
if (uploadedFile) {
|
||||||
const maxFileSize = 2 * 1024 * 1024;
|
const maxFileSize = 2 * 1024 * 1024;
|
||||||
if (uploadedFile.size > maxFileSize) {
|
if (uploadedFile.size > maxFileSize) {
|
||||||
UploadFileNotification(directionApp, t);
|
UploadFileNotification(directionApp, t);
|
||||||
event.target.value = "";
|
event.target.value = "";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const fileType = event.target?.files?.[0].type;
|
const fileType = event.target?.files?.[0].type;
|
||||||
const fileName = event.target?.files?.[0].name;
|
const fileName = event.target?.files?.[0].name;
|
||||||
setSelectedImage(URL.createObjectURL(uploadedFile));
|
setSelectedImage(URL.createObjectURL(uploadedFile));
|
||||||
setfileType(fileType);
|
setfileType(fileType);
|
||||||
setfileName(fileName);
|
setfileName(fileName);
|
||||||
formik.setFieldValue("reject_img", uploadedFile);
|
formik.setFieldValue("reject_img", uploadedFile);
|
||||||
setShowAddIcon(false);
|
setShowAddIcon(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Dialog open={open}>
|
<Dialog open={open}>
|
||||||
<DialogTitle>{t("RejectDialog.reject")}</DialogTitle>
|
<DialogTitle>{t("RejectDialog.reject")}</DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<DialogContentText>{t("RejectDialog.context")}</DialogContentText>
|
<DialogContentText>{t("RejectDialog.context")}</DialogContentText>
|
||||||
<TextField
|
<TextField
|
||||||
name="description"
|
name="description"
|
||||||
multiline
|
multiline
|
||||||
rows={8}
|
rows={8}
|
||||||
placeholder={t("RejectDialog.description")}
|
placeholder={t("RejectDialog.description")}
|
||||||
value={description}
|
value={description}
|
||||||
onChange={handleDescriptionChange}
|
onChange={handleDescriptionChange}
|
||||||
onBlur={formik.handleBlur("description")}
|
onBlur={formik.handleBlur("description")}
|
||||||
error={
|
error={
|
||||||
formik.touched.description && Boolean(formik.errors.description)
|
formik.touched.description && Boolean(formik.errors.description)
|
||||||
}
|
}
|
||||||
helperText={formik.touched.description && formik.errors.description}
|
helperText={formik.touched.description && formik.errors.description}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
sx={{ mt: 1 }}
|
sx={{mt: 1}}
|
||||||
/>
|
/>
|
||||||
<UploadSystem
|
<UploadSystem
|
||||||
selectedImage={selectedImage}
|
selectedImage={selectedImage}
|
||||||
handleUploadChange={handleUploadChange} // Pass the updated function directly
|
handleUploadChange={handleUploadChange} // Pass the updated function directly
|
||||||
setselectedImage={setSelectedImage}
|
setselectedImage={setSelectedImage}
|
||||||
setFieldValue={formik.setFieldValue} // Remove props.setFieldValue, use formik.setFieldValue
|
setFieldValue={formik.setFieldValue} // Remove props.setFieldValue, use formik.setFieldValue
|
||||||
fieldname="reject_img"
|
fieldname="reject_img"
|
||||||
fileType={fileType}
|
fileType={fileType}
|
||||||
fileName={fileName}
|
fileName={fileName}
|
||||||
imageAlt={t("app_name")}
|
imageAlt={t("app_name")}
|
||||||
imageSize={[250 /*width*/, 150 /*height*/]}
|
imageSize={[250 /*width*/, 150 /*height*/]}
|
||||||
setShowAddIcon={setShowAddIcon}
|
setShowAddIcon={setShowAddIcon}
|
||||||
showAddIcon={showAddIcon}
|
showAddIcon={showAddIcon}
|
||||||
/>
|
/>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button onClick={handleClose} color="secondary" autoFocus>
|
<Button onClick={handleClose} color="secondary" autoFocus>
|
||||||
{t("RejectDialog.button-cancel")}
|
{t("RejectDialog.button-cancel")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={formik.handleSubmit} color="primary">
|
<Button onClick={formik.handleSubmit} color="primary">
|
||||||
{t("RejectDialog.button-reject")}
|
{t("RejectDialog.button-reject")}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default RejectForm;
|
export default RejectForm;
|
||||||
|
|||||||
@@ -1,60 +1,60 @@
|
|||||||
import ThumbUpAltIcon from "@mui/icons-material/ThumbUpAlt";
|
import ThumbUpAltIcon from "@mui/icons-material/ThumbUpAlt";
|
||||||
import ThumbDownIcon from "@mui/icons-material/ThumbDown";
|
import ThumbDownIcon from "@mui/icons-material/ThumbDown";
|
||||||
import { Box, IconButton, Tooltip } from "@mui/material";
|
import {Box, IconButton, Tooltip} from "@mui/material";
|
||||||
import { useContext } from "react";
|
import {useContext} from "react";
|
||||||
import ConfirmForm from "./Form/ConfirmForm";
|
import ConfirmForm from "./Form/ConfirmForm";
|
||||||
import RejectForm from "./Form/RejectForm";
|
import RejectForm from "./Form/RejectForm";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import { DataTableContext } from "@/lib/app/contexts/DatatableContext";
|
import {DataTableContext} from "@/lib/app/contexts/DatatableContext";
|
||||||
|
|
||||||
const TableRowActions = ({ row }) => {
|
const TableRowActions = ({row}) => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const {
|
const {
|
||||||
openConfirmDialog,
|
openConfirmDialog,
|
||||||
openRejectDialog,
|
openRejectDialog,
|
||||||
handleOpenConfirmDialog,
|
handleOpenConfirmDialog,
|
||||||
handleOpenRejectDialog,
|
handleOpenRejectDialog,
|
||||||
handleCloseConfirmDialog,
|
handleCloseConfirmDialog,
|
||||||
handleCloseRejectDialog,
|
handleCloseRejectDialog,
|
||||||
rowId,
|
rowId,
|
||||||
confirmData,
|
confirmData,
|
||||||
rejectData,
|
rejectData,
|
||||||
} = useContext(DataTableContext);
|
} = useContext(DataTableContext);
|
||||||
return (
|
return (
|
||||||
<Box sx={{ display: "flex", flexWrap: "nowrap", gap: "8px" }}>
|
<Box sx={{display: "flex", flexWrap: "nowrap", gap: "8px"}}>
|
||||||
<Tooltip title={t("ConfirmDialog.confirm")}>
|
<Tooltip title={t("ConfirmDialog.confirm")}>
|
||||||
<IconButton
|
<IconButton
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleOpenConfirmDialog(row);
|
handleOpenConfirmDialog(row);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ThumbUpAltIcon />
|
<ThumbUpAltIcon/>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
{openConfirmDialog && (
|
{openConfirmDialog && (
|
||||||
<ConfirmForm
|
<ConfirmForm
|
||||||
rowId={rowId}
|
rowId={rowId}
|
||||||
open={openConfirmDialog}
|
open={openConfirmDialog}
|
||||||
handleClose={handleCloseConfirmDialog}
|
handleClose={handleCloseConfirmDialog}
|
||||||
confirmData={confirmData}
|
confirmData={confirmData}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Tooltip title={t("RejectDialog.reject")}>
|
<Tooltip title={t("RejectDialog.reject")}>
|
||||||
<IconButton color="primary" onClick={() => handleOpenRejectDialog(row)}>
|
<IconButton color="primary" onClick={() => handleOpenRejectDialog(row)}>
|
||||||
<ThumbDownIcon />
|
<ThumbDownIcon/>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
{openRejectDialog && (
|
{openRejectDialog && (
|
||||||
<RejectForm
|
<RejectForm
|
||||||
rowId={rowId}
|
rowId={rowId}
|
||||||
open={openRejectDialog}
|
open={openRejectDialog}
|
||||||
handleClose={handleCloseRejectDialog}
|
handleClose={handleCloseRejectDialog}
|
||||||
rejectData={rejectData}
|
rejectData={rejectData}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TableRowActions;
|
export default TableRowActions;
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { Stack, Tooltip } from "@mui/material";
|
import {Stack, Tooltip} from "@mui/material";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
|
|
||||||
function TableToolbar() {
|
function TableToolbar() {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
return (
|
return (
|
||||||
<Stack direction={"row"} spacing={2}>
|
<Stack direction={"row"} spacing={2}>
|
||||||
<Tooltip title={t("add")} arrow placement="right"></Tooltip>
|
<Tooltip title={t("add")} arrow placement="right"></Tooltip>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default TableToolbar;
|
export default TableToolbar;
|
||||||
|
|||||||
@@ -1,247 +1,243 @@
|
|||||||
import DataTableStructure from "@/core/components/DatatableStructure";
|
import DataTableStructure from "@/core/components/DatatableStructure";
|
||||||
import DashboardLayouts from "@/layouts/dashboardLayouts";
|
import DashboardLayouts from "@/layouts/dashboardLayouts";
|
||||||
import { Box, IconButton, Typography } from "@mui/material";
|
import {Box, IconButton, Typography} from "@mui/material";
|
||||||
import ClearIcon from "@mui/icons-material/Clear";
|
import ClearIcon from "@mui/icons-material/Clear";
|
||||||
import { useMemo } from "react";
|
import {useMemo} from "react";
|
||||||
import { faIR } from "@mui/x-date-pickers/locales";
|
import {faIR} from "@mui/x-date-pickers/locales";
|
||||||
// import TableToolbar from "./TableTollbar";
|
// import TableToolbar from "./TableTollbar";
|
||||||
import { GET_PASSENGER_OFFICE } from "@/core/data/apiRoutes";
|
import {GET_PASSENGER_OFFICE} from "@/core/data/apiRoutes";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import TableRowActions from "./TableRowActions";
|
import TableRowActions from "./TableRowActions";
|
||||||
import {
|
import {LocalizationProvider, MobileDateTimePicker,} from "@mui/x-date-pickers";
|
||||||
LocalizationProvider,
|
import {AdapterDateFnsJalali} from "@mui/x-date-pickers/AdapterDateFnsJalali";
|
||||||
MobileDateTimePicker,
|
|
||||||
} from "@mui/x-date-pickers";
|
|
||||||
import { AdapterDateFnsJalali } from "@mui/x-date-pickers/AdapterDateFnsJalali";
|
|
||||||
import moment from "jalali-moment";
|
import moment from "jalali-moment";
|
||||||
import dayjs from "dayjs";
|
|
||||||
|
|
||||||
function DashboardPassengerOfficeComponent() {
|
function DashboardPassengerOfficeComponent() {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
|
|
||||||
const columns = useMemo(
|
const columns = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
accessorFn: (row) => row.id,
|
accessorFn: (row) => row.id,
|
||||||
id: "id",
|
id: "id",
|
||||||
header: t("PassengerOffice.id"),
|
header: t("PassengerOffice.id"),
|
||||||
enableColumnFilter: true,
|
enableColumnFilter: true,
|
||||||
datatype: "numeric",
|
datatype: "numeric",
|
||||||
maxSize: 100,
|
maxSize: 100,
|
||||||
filterFn: "equals",
|
filterFn: "equals",
|
||||||
columnFilterModeOptions: [
|
columnFilterModeOptions: [
|
||||||
"equals",
|
"equals",
|
||||||
"notEquals",
|
"notEquals",
|
||||||
"contains",
|
"contains",
|
||||||
"lessThan",
|
"lessThan",
|
||||||
"greaterThan",
|
"greaterThan",
|
||||||
"between",
|
"between",
|
||||||
|
],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.name,
|
||||||
|
id: "name",
|
||||||
|
header: t("PassengerOffice.name"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "text",
|
||||||
|
filterFn: "contains",
|
||||||
|
columnFilterModeOptions: ["contains", "equals", "notEquals"],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.national_id,
|
||||||
|
id: "national_id",
|
||||||
|
header: t("PassengerOffice.national_id"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "numeric",
|
||||||
|
filterFn: "equals",
|
||||||
|
columnFilterModeOptions: [
|
||||||
|
"equals",
|
||||||
|
"notEquals",
|
||||||
|
"contains",
|
||||||
|
"lessThan",
|
||||||
|
"greaterThan",
|
||||||
|
"between",
|
||||||
|
],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.phone_number,
|
||||||
|
id: "phone_number",
|
||||||
|
header: t("PassengerOffice.phone_number"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "numeric",
|
||||||
|
filterFn: "equals",
|
||||||
|
columnFilterModeOptions: [
|
||||||
|
"equals",
|
||||||
|
"notEquals",
|
||||||
|
"contains",
|
||||||
|
"lessThan",
|
||||||
|
"greaterThan",
|
||||||
|
"between",
|
||||||
|
],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) =>
|
||||||
|
moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
|
||||||
|
id: "created_at",
|
||||||
|
header: t("PassengerOffice.created_at"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "date",
|
||||||
|
filterFn: "lessThan",
|
||||||
|
minSize: 200,
|
||||||
|
columnFilterModeOptions: ["lessThan", "greaterThan"],
|
||||||
|
Cell: ({renderedCellValue}) => {
|
||||||
|
return <Typography variant="body2">{renderedCellValue}</Typography>;
|
||||||
|
},
|
||||||
|
Header: ({column}) => <em>{column.columnDef.header}</em>,
|
||||||
|
Filter: ({column}) => {
|
||||||
|
const filterFnValue = column.columnDef._filterFn;
|
||||||
|
return (
|
||||||
|
<Box sx={{display: "flex", alignItems: "start"}}>
|
||||||
|
<LocalizationProvider
|
||||||
|
dateAdapter={AdapterDateFnsJalali}
|
||||||
|
localeText={
|
||||||
|
faIR.components.MuiLocalizationProvider.defaultProps
|
||||||
|
.localeText
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<MobileDateTimePicker
|
||||||
|
ampm={false}
|
||||||
|
onChange={(newValue) => {
|
||||||
|
const date = new Date(newValue);
|
||||||
|
const formattedDate = moment(date)
|
||||||
|
.locale("en")
|
||||||
|
.format("YYYY-MM-DD HH:mm");
|
||||||
|
column.setFilterValue(formattedDate);
|
||||||
|
}}
|
||||||
|
slotProps={{
|
||||||
|
textField: {
|
||||||
|
placeholder: "تاریخ خود را وارد کنید",
|
||||||
|
helperText: `${t("filter_mode")}: ${t(filterFnValue)}`,
|
||||||
|
sx: {minWidth: "120px"},
|
||||||
|
variant: "standard",
|
||||||
|
actionBar: {actions: ["accept", "today"]},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
value={
|
||||||
|
column.getFilterValue()
|
||||||
|
? new Date(column.getFilterValue())
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</LocalizationProvider>
|
||||||
|
<IconButton
|
||||||
|
size="small"
|
||||||
|
onClick={() => {
|
||||||
|
column.setFilterValue(null);
|
||||||
|
}}
|
||||||
|
sx={{
|
||||||
|
color: column.getFilterValue()
|
||||||
|
? "rgba(0, 0, 0, 0.54)"
|
||||||
|
: "#bfbfbf",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ClearIcon/>
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) =>
|
||||||
|
moment(row.updated_at).locale("fa").format("HH:mm | YYYY/MM/DD"),
|
||||||
|
id: "updated_at",
|
||||||
|
header: t("PassengerOffice.updated_at"),
|
||||||
|
enableColumnFilter: false,
|
||||||
|
datatype: "numeric",
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.navgan_id,
|
||||||
|
id: "navgan_id",
|
||||||
|
header: t("PassengerOffice.navgan_id"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "numeric",
|
||||||
|
maxSize: 100,
|
||||||
|
filterFn: "equals",
|
||||||
|
columnFilterModeOptions: [
|
||||||
|
"equals",
|
||||||
|
"notEquals",
|
||||||
|
"contains",
|
||||||
|
"lessThan",
|
||||||
|
"greaterThan",
|
||||||
|
"between",
|
||||||
|
],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.vehicle_type,
|
||||||
|
id: "vehicle_type",
|
||||||
|
header: t("PassengerOffice.vehicle_type"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "text",
|
||||||
|
filterFn: "contains",
|
||||||
|
columnFilterModeOptions: ["contains", "equals", "notEquals"],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.state_name,
|
||||||
|
id: "state_id",
|
||||||
|
header: t("PassengerOffice.state_name"),
|
||||||
|
enableColumnFilter: false,
|
||||||
|
datatype: "numeric",
|
||||||
|
minSize: 300,
|
||||||
|
// filterFn: "equals",
|
||||||
|
// filterSelectOptions: [
|
||||||
|
// ],
|
||||||
|
// filterVariant: "select",
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
Cell: ({ renderedCellValue }) => (
|
[]
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
);
|
||||||
),
|
return (
|
||||||
},
|
<DashboardLayouts>
|
||||||
{
|
<Box sx={{px: 3}}>
|
||||||
accessorFn: (row) => row.name,
|
<DataTableStructure
|
||||||
id: "name",
|
tableUrl={GET_PASSENGER_OFFICE}
|
||||||
header: t("PassengerOffice.name"),
|
columns={columns}
|
||||||
enableColumnFilter: true,
|
selectableRow={false}
|
||||||
datatype: "text",
|
enableCustomToolbar={true}
|
||||||
filterFn: "contains",
|
// CustomToolbar={<TableToolbar />}
|
||||||
columnFilterModeOptions: ["contains", "equals", "notEquals"],
|
enableLastUpdate={true}
|
||||||
Cell: ({ renderedCellValue }) => (
|
enablePinning={true}
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
enableDensityToggle={true}
|
||||||
),
|
enableColumnFilters={true}
|
||||||
},
|
enableHiding={true}
|
||||||
{
|
enableFullScreenToggle={false}
|
||||||
accessorFn: (row) => row.national_id,
|
enableGlobalFilter={false}
|
||||||
id: "national_id",
|
enableColumnResizing={false} // if you want true this you shold change renderRowActions props ** see https://www.material-react-table.com/docs/guides/row-actions
|
||||||
header: t("PassengerOffice.national_id"),
|
enableRowActions={true}
|
||||||
enableColumnFilter: true,
|
renderRowActions={({row}) => <TableRowActions row={row}/>}
|
||||||
datatype: "numeric",
|
|
||||||
filterFn: "equals",
|
|
||||||
columnFilterModeOptions: [
|
|
||||||
"equals",
|
|
||||||
"notEquals",
|
|
||||||
"contains",
|
|
||||||
"lessThan",
|
|
||||||
"greaterThan",
|
|
||||||
"between",
|
|
||||||
],
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) => row.phone_number,
|
|
||||||
id: "phone_number",
|
|
||||||
header: t("PassengerOffice.phone_number"),
|
|
||||||
enableColumnFilter: true,
|
|
||||||
datatype: "numeric",
|
|
||||||
filterFn: "equals",
|
|
||||||
columnFilterModeOptions: [
|
|
||||||
"equals",
|
|
||||||
"notEquals",
|
|
||||||
"contains",
|
|
||||||
"lessThan",
|
|
||||||
"greaterThan",
|
|
||||||
"between",
|
|
||||||
],
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) =>
|
|
||||||
moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
|
|
||||||
id: "created_at",
|
|
||||||
header: t("PassengerOffice.created_at"),
|
|
||||||
enableColumnFilter: true,
|
|
||||||
datatype: "date",
|
|
||||||
filterFn: "lessThan",
|
|
||||||
minSize: 200,
|
|
||||||
columnFilterModeOptions: ["lessThan", "greaterThan"],
|
|
||||||
Cell: ({ renderedCellValue }) => {
|
|
||||||
return <Typography variant="body2">{renderedCellValue}</Typography>;
|
|
||||||
},
|
|
||||||
Header: ({ column }) => <em>{column.columnDef.header}</em>,
|
|
||||||
Filter: ({ column }) => {
|
|
||||||
const filterFnValue = column.columnDef._filterFn;
|
|
||||||
return (
|
|
||||||
<Box sx={{ display: "flex", alignItems: "start" }}>
|
|
||||||
<LocalizationProvider
|
|
||||||
dateAdapter={AdapterDateFnsJalali}
|
|
||||||
localeText={
|
|
||||||
faIR.components.MuiLocalizationProvider.defaultProps
|
|
||||||
.localeText
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<MobileDateTimePicker
|
|
||||||
ampm={false}
|
|
||||||
onChange={(newValue) => {
|
|
||||||
const date = new Date(newValue);
|
|
||||||
const formattedDate = moment(date)
|
|
||||||
.locale("en")
|
|
||||||
.format("YYYY-MM-DD HH:mm");
|
|
||||||
column.setFilterValue(formattedDate);
|
|
||||||
}}
|
|
||||||
slotProps={{
|
|
||||||
textField: {
|
|
||||||
placeholder: "تاریخ خود را وارد کنید",
|
|
||||||
helperText: `${t("filter_mode")}: ${t(filterFnValue)}`,
|
|
||||||
sx: { minWidth: "120px" },
|
|
||||||
variant: "standard",
|
|
||||||
actionBar: { actions: ["accept", "today"] },
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
value={
|
|
||||||
column.getFilterValue()
|
|
||||||
? new Date(column.getFilterValue())
|
|
||||||
: null
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</LocalizationProvider>
|
|
||||||
<IconButton
|
|
||||||
size="small"
|
|
||||||
onClick={() => {
|
|
||||||
column.setFilterValue(null);
|
|
||||||
}}
|
|
||||||
sx={{
|
|
||||||
color: column.getFilterValue()
|
|
||||||
? "rgba(0, 0, 0, 0.54)"
|
|
||||||
: "#bfbfbf",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ClearIcon />
|
|
||||||
</IconButton>
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
</DashboardLayouts>
|
||||||
},
|
);
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) =>
|
|
||||||
moment(row.updated_at).locale("fa").format("HH:mm | YYYY/MM/DD"),
|
|
||||||
id: "updated_at",
|
|
||||||
header: t("PassengerOffice.updated_at"),
|
|
||||||
enableColumnFilter: false,
|
|
||||||
datatype: "numeric",
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) => row.navgan_id,
|
|
||||||
id: "navgan_id",
|
|
||||||
header: t("PassengerOffice.navgan_id"),
|
|
||||||
enableColumnFilter: true,
|
|
||||||
datatype: "numeric",
|
|
||||||
maxSize: 100,
|
|
||||||
filterFn: "equals",
|
|
||||||
columnFilterModeOptions: [
|
|
||||||
"equals",
|
|
||||||
"notEquals",
|
|
||||||
"contains",
|
|
||||||
"lessThan",
|
|
||||||
"greaterThan",
|
|
||||||
"between",
|
|
||||||
],
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) => row.vehicle_type,
|
|
||||||
id: "vehicle_type",
|
|
||||||
header: t("PassengerOffice.vehicle_type"),
|
|
||||||
enableColumnFilter: true,
|
|
||||||
datatype: "text",
|
|
||||||
filterFn: "contains",
|
|
||||||
columnFilterModeOptions: ["contains", "equals", "notEquals"],
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) => row.state_name,
|
|
||||||
id: "state_id",
|
|
||||||
header: t("PassengerOffice.state_name"),
|
|
||||||
enableColumnFilter: false,
|
|
||||||
datatype: "numeric",
|
|
||||||
minSize: 300,
|
|
||||||
// filterFn: "equals",
|
|
||||||
// filterSelectOptions: [
|
|
||||||
// ],
|
|
||||||
// filterVariant: "select",
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
<DashboardLayouts>
|
|
||||||
<Box sx={{ px: 3 }}>
|
|
||||||
<DataTableStructure
|
|
||||||
tableUrl={GET_PASSENGER_OFFICE}
|
|
||||||
columns={columns}
|
|
||||||
selectableRow={false}
|
|
||||||
enableCustomToolbar={true}
|
|
||||||
// CustomToolbar={<TableToolbar />}
|
|
||||||
enableLastUpdate={true}
|
|
||||||
enablePinning={true}
|
|
||||||
enableDensityToggle={true}
|
|
||||||
enableColumnFilters={true}
|
|
||||||
enableHiding={true}
|
|
||||||
enableFullScreenToggle={false}
|
|
||||||
enableGlobalFilter={false}
|
|
||||||
enableColumnResizing={false} // if you want true this you shold change renderRowActions props ** see https://www.material-react-table.com/docs/guides/row-actions
|
|
||||||
enableRowActions={true}
|
|
||||||
renderRowActions={({ row }) => <TableRowActions row={row} />}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</DashboardLayouts>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DashboardPassengerOfficeComponent;
|
export default DashboardPassengerOfficeComponent;
|
||||||
|
|||||||
@@ -1,106 +1,98 @@
|
|||||||
import UploadSystem from "@/core/components/UploadSystem";
|
import UploadSystem from "@/core/components/UploadSystem";
|
||||||
import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
|
import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
|
||||||
import { CONFIRM_PROVINCE_MANAGER } from "@/core/data/apiRoutes";
|
import {CONFIRM_PROVINCE_MANAGER} from "@/core/data/apiRoutes";
|
||||||
import useDirection from "@/lib/app/hooks/useDirection";
|
import useDirection from "@/lib/app/hooks/useDirection";
|
||||||
import {
|
import {Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, TextField,} from "@mui/material";
|
||||||
Dialog,
|
import {useFormik} from "formik";
|
||||||
DialogTitle,
|
import {useTranslations} from "next-intl";
|
||||||
DialogContent,
|
import {useState} from "react";
|
||||||
DialogContentText,
|
|
||||||
DialogActions,
|
|
||||||
Button,
|
|
||||||
TextField,
|
|
||||||
} from "@mui/material";
|
|
||||||
import { useFormik } from "formik";
|
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useRef, useState } from "react";
|
|
||||||
|
|
||||||
const ConfirmForm = ({ open, handleClose, rowId, confirmData }) => {
|
const ConfirmForm = ({open, handleClose, rowId, confirmData}) => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const { directionApp } = useDirection();
|
const {directionApp} = useDirection();
|
||||||
const [description, setDescription] = useState("");
|
const [description, setDescription] = useState("");
|
||||||
const [selectedImage, setSelectedImage] = useState("");
|
const [selectedImage, setSelectedImage] = useState("");
|
||||||
const [fileType, setfileType] = useState(null);
|
const [fileType, setfileType] = useState(null);
|
||||||
const [fileName, setfileName] = useState(null);
|
const [fileName, setfileName] = useState(null);
|
||||||
const [showAddIcon, setShowAddIcon] = useState(true);
|
const [showAddIcon, setShowAddIcon] = useState(true);
|
||||||
|
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
description: "",
|
description: "",
|
||||||
},
|
},
|
||||||
onSubmit: () => {
|
onSubmit: () => {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
if (description !== "")
|
if (description !== "")
|
||||||
formData.append("expert_description", description);
|
formData.append("expert_description", description);
|
||||||
handleClose();
|
handleClose();
|
||||||
confirmData(CONFIRM_PROVINCE_MANAGER, rowId, formData);
|
confirmData(CONFIRM_PROVINCE_MANAGER, rowId, formData);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleDescriptionChange = (event) => {
|
const handleDescriptionChange = (event) => {
|
||||||
setDescription(event.target.value);
|
setDescription(event.target.value);
|
||||||
formik.handleChange(event);
|
formik.handleChange(event);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUploadChange = (event) => {
|
const handleUploadChange = (event) => {
|
||||||
const uploadedFile = event.target?.files?.[0];
|
const uploadedFile = event.target?.files?.[0];
|
||||||
if (uploadedFile) {
|
if (uploadedFile) {
|
||||||
const maxFileSize = 2 * 1024 * 1024;
|
const maxFileSize = 2 * 1024 * 1024;
|
||||||
if (uploadedFile.size > maxFileSize) {
|
if (uploadedFile.size > maxFileSize) {
|
||||||
UploadFileNotification(directionApp, t);
|
UploadFileNotification(directionApp, t);
|
||||||
event.target.value = "";
|
event.target.value = "";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const fileType = event.target?.files?.[0].type;
|
const fileType = event.target?.files?.[0].type;
|
||||||
const fileName = event.target?.files?.[0].name;
|
const fileName = event.target?.files?.[0].name;
|
||||||
setSelectedImage(URL.createObjectURL(uploadedFile));
|
setSelectedImage(URL.createObjectURL(uploadedFile));
|
||||||
setfileType(fileType);
|
setfileType(fileType);
|
||||||
setfileName(fileName);
|
setfileName(fileName);
|
||||||
formik.setFieldValue("confirm_img", uploadedFile);
|
formik.setFieldValue("confirm_img", uploadedFile);
|
||||||
setShowAddIcon(false);
|
setShowAddIcon(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={open}>
|
<Dialog open={open}>
|
||||||
<DialogTitle>{t("ConfirmDialog.confirm")}</DialogTitle>
|
<DialogTitle>{t("ConfirmDialog.confirm")}</DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<DialogContentText>{t("ConfirmDialog.context")}</DialogContentText>
|
<DialogContentText>{t("ConfirmDialog.context")}</DialogContentText>
|
||||||
<TextField
|
<TextField
|
||||||
name="description"
|
name="description"
|
||||||
multiline
|
multiline
|
||||||
rows={8}
|
rows={8}
|
||||||
placeholder={t("ConfirmDialog.description")}
|
placeholder={t("ConfirmDialog.description")}
|
||||||
value={description}
|
value={description}
|
||||||
onChange={handleDescriptionChange}
|
onChange={handleDescriptionChange}
|
||||||
onBlur={formik.handleBlur("description")}
|
onBlur={formik.handleBlur("description")}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
sx={{ mt: 1 }}
|
sx={{mt: 1}}
|
||||||
/>
|
/>
|
||||||
<UploadSystem
|
<UploadSystem
|
||||||
selectedImage={selectedImage}
|
selectedImage={selectedImage}
|
||||||
handleUploadChange={handleUploadChange} // Pass the updated function directly
|
handleUploadChange={handleUploadChange} // Pass the updated function directly
|
||||||
setselectedImage={setSelectedImage}
|
setselectedImage={setSelectedImage}
|
||||||
setFieldValue={formik.setFieldValue} // Remove props.setFieldValue, use formik.setFieldValue
|
setFieldValue={formik.setFieldValue} // Remove props.setFieldValue, use formik.setFieldValue
|
||||||
fieldname="confirm_img"
|
fieldname="confirm_img"
|
||||||
fileType={fileType}
|
fileType={fileType}
|
||||||
fileName={fileName}
|
fileName={fileName}
|
||||||
imageAlt={t("app_name")}
|
imageAlt={t("app_name")}
|
||||||
imageSize={[250 /*width*/, 150 /*height*/]}
|
imageSize={[250 /*width*/, 150 /*height*/]}
|
||||||
setShowAddIcon={setShowAddIcon}
|
setShowAddIcon={setShowAddIcon}
|
||||||
showAddIcon={showAddIcon}
|
showAddIcon={showAddIcon}
|
||||||
/>
|
/>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button onClick={handleClose} color="secondary" autoFocus>
|
<Button onClick={handleClose} color="secondary" autoFocus>
|
||||||
{t("ConfirmDialog.button-cancel")}
|
{t("ConfirmDialog.button-cancel")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={formik.handleSubmit} color="primary">
|
<Button onClick={formik.handleSubmit} color="primary">
|
||||||
{t("ConfirmDialog.button-confirm")}
|
{t("ConfirmDialog.button-confirm")}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default ConfirmForm;
|
export default ConfirmForm;
|
||||||
|
|||||||
@@ -1,115 +1,107 @@
|
|||||||
import { REJECT_PROVINCE_MANAGER } from "@/core/data/apiRoutes";
|
import {REJECT_PROVINCE_MANAGER} from "@/core/data/apiRoutes";
|
||||||
import {
|
import {Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, TextField,} from "@mui/material";
|
||||||
Dialog,
|
import {useTranslations} from "next-intl";
|
||||||
DialogTitle,
|
import {useFormik} from "formik";
|
||||||
DialogContent,
|
|
||||||
DialogContentText,
|
|
||||||
DialogActions,
|
|
||||||
Button,
|
|
||||||
TextField,
|
|
||||||
} from "@mui/material";
|
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useFormik } from "formik";
|
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
import { useState } from "react";
|
import {useState} from "react";
|
||||||
import UploadSystem from "@/core/components/UploadSystem";
|
import UploadSystem from "@/core/components/UploadSystem";
|
||||||
import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
|
import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
|
||||||
import useDirection from "@/lib/app/hooks/useDirection";
|
import useDirection from "@/lib/app/hooks/useDirection";
|
||||||
|
|
||||||
const RejectForm = ({ open, handleClose, rowId, rejectData }) => {
|
const RejectForm = ({open, handleClose, rowId, rejectData}) => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const { directionApp } = useDirection();
|
const {directionApp} = useDirection();
|
||||||
const [description, setDescription] = useState("");
|
const [description, setDescription] = useState("");
|
||||||
const [selectedImage, setSelectedImage] = useState("");
|
const [selectedImage, setSelectedImage] = useState("");
|
||||||
const [fileType, setfileType] = useState(null);
|
const [fileType, setfileType] = useState(null);
|
||||||
const [fileName, setfileName] = useState(null);
|
const [fileName, setfileName] = useState(null);
|
||||||
const [showAddIcon, setShowAddIcon] = useState(true);
|
const [showAddIcon, setShowAddIcon] = useState(true);
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
description: Yup.string().required(t("RejectDialog.description_error")),
|
description: Yup.string().required(t("RejectDialog.description_error")),
|
||||||
});
|
});
|
||||||
|
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
description: "",
|
description: "",
|
||||||
},
|
},
|
||||||
validationSchema,
|
validationSchema,
|
||||||
onSubmit: () => {
|
onSubmit: () => {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("expert_description", description);
|
formData.append("expert_description", description);
|
||||||
handleClose();
|
handleClose();
|
||||||
rejectData(REJECT_PROVINCE_MANAGER, rowId, formData);
|
rejectData(REJECT_PROVINCE_MANAGER, rowId, formData);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleDescriptionChange = (event) => {
|
const handleDescriptionChange = (event) => {
|
||||||
setDescription(event.target.value);
|
setDescription(event.target.value);
|
||||||
formik.handleChange(event);
|
formik.handleChange(event);
|
||||||
};
|
};
|
||||||
const handleUploadChange = (event) => {
|
const handleUploadChange = (event) => {
|
||||||
const uploadedFile = event.target?.files?.[0];
|
const uploadedFile = event.target?.files?.[0];
|
||||||
if (uploadedFile) {
|
if (uploadedFile) {
|
||||||
const maxFileSize = 2 * 1024 * 1024;
|
const maxFileSize = 2 * 1024 * 1024;
|
||||||
if (uploadedFile.size > maxFileSize) {
|
if (uploadedFile.size > maxFileSize) {
|
||||||
UploadFileNotification(directionApp, t);
|
UploadFileNotification(directionApp, t);
|
||||||
event.target.value = "";
|
event.target.value = "";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const fileType = event.target?.files?.[0].type;
|
const fileType = event.target?.files?.[0].type;
|
||||||
const fileName = event.target?.files?.[0].name;
|
const fileName = event.target?.files?.[0].name;
|
||||||
setSelectedImage(URL.createObjectURL(uploadedFile));
|
setSelectedImage(URL.createObjectURL(uploadedFile));
|
||||||
setfileType(fileType);
|
setfileType(fileType);
|
||||||
setfileName(fileName);
|
setfileName(fileName);
|
||||||
formik.setFieldValue("reject_img", uploadedFile);
|
formik.setFieldValue("reject_img", uploadedFile);
|
||||||
setShowAddIcon(false);
|
setShowAddIcon(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={open}>
|
<Dialog open={open}>
|
||||||
<DialogTitle>{t("RejectDialog.reject")}</DialogTitle>
|
<DialogTitle>{t("RejectDialog.reject")}</DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<DialogContentText>{t("RejectDialog.context")}</DialogContentText>
|
<DialogContentText>{t("RejectDialog.context")}</DialogContentText>
|
||||||
<TextField
|
<TextField
|
||||||
name="description"
|
name="description"
|
||||||
multiline
|
multiline
|
||||||
rows={8}
|
rows={8}
|
||||||
placeholder={t("RejectDialog.description")}
|
placeholder={t("RejectDialog.description")}
|
||||||
value={description}
|
value={description}
|
||||||
onChange={handleDescriptionChange}
|
onChange={handleDescriptionChange}
|
||||||
onBlur={formik.handleBlur("description")}
|
onBlur={formik.handleBlur("description")}
|
||||||
error={
|
error={
|
||||||
formik.touched.description && Boolean(formik.errors.description)
|
formik.touched.description && Boolean(formik.errors.description)
|
||||||
}
|
}
|
||||||
helperText={formik.touched.description && formik.errors.description}
|
helperText={formik.touched.description && formik.errors.description}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
sx={{ mt: 1 }}
|
sx={{mt: 1}}
|
||||||
/>
|
/>
|
||||||
<UploadSystem
|
<UploadSystem
|
||||||
selectedImage={selectedImage}
|
selectedImage={selectedImage}
|
||||||
handleUploadChange={handleUploadChange} // Pass the updated function directly
|
handleUploadChange={handleUploadChange} // Pass the updated function directly
|
||||||
setselectedImage={setSelectedImage}
|
setselectedImage={setSelectedImage}
|
||||||
setFieldValue={formik.setFieldValue} // Remove props.setFieldValue, use formik.setFieldValue
|
setFieldValue={formik.setFieldValue} // Remove props.setFieldValue, use formik.setFieldValue
|
||||||
fieldname="reject_img"
|
fieldname="reject_img"
|
||||||
fileType={fileType}
|
fileType={fileType}
|
||||||
fileName={fileName}
|
fileName={fileName}
|
||||||
imageAlt={t("app_name")}
|
imageAlt={t("app_name")}
|
||||||
imageSize={[250 /*width*/, 150 /*height*/]}
|
imageSize={[250 /*width*/, 150 /*height*/]}
|
||||||
setShowAddIcon={setShowAddIcon}
|
setShowAddIcon={setShowAddIcon}
|
||||||
showAddIcon={showAddIcon}
|
showAddIcon={showAddIcon}
|
||||||
/>
|
/>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button onClick={handleClose} color="secondary" autoFocus>
|
<Button onClick={handleClose} color="secondary" autoFocus>
|
||||||
{t("RejectDialog.button-cancel")}
|
{t("RejectDialog.button-cancel")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={formik.handleSubmit} color="primary">
|
<Button onClick={formik.handleSubmit} color="primary">
|
||||||
{t("RejectDialog.button-reject")}
|
{t("RejectDialog.button-reject")}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default RejectForm;
|
export default RejectForm;
|
||||||
|
|||||||
@@ -1,60 +1,60 @@
|
|||||||
import ThumbUpAltIcon from "@mui/icons-material/ThumbUpAlt";
|
import ThumbUpAltIcon from "@mui/icons-material/ThumbUpAlt";
|
||||||
import ThumbDownIcon from "@mui/icons-material/ThumbDown";
|
import ThumbDownIcon from "@mui/icons-material/ThumbDown";
|
||||||
import { Box, IconButton, Tooltip } from "@mui/material";
|
import {Box, IconButton, Tooltip} from "@mui/material";
|
||||||
import { useContext } from "react";
|
import {useContext} from "react";
|
||||||
import ConfirmForm from "./Form/ConfirmForm";
|
import ConfirmForm from "./Form/ConfirmForm";
|
||||||
import RejectForm from "./Form/RejectForm";
|
import RejectForm from "./Form/RejectForm";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import { DataTableContext } from "@/lib/app/contexts/DatatableContext";
|
import {DataTableContext} from "@/lib/app/contexts/DatatableContext";
|
||||||
|
|
||||||
const TableRowActions = ({ row }) => {
|
const TableRowActions = ({row}) => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const {
|
const {
|
||||||
openConfirmDialog,
|
openConfirmDialog,
|
||||||
openRejectDialog,
|
openRejectDialog,
|
||||||
handleOpenConfirmDialog,
|
handleOpenConfirmDialog,
|
||||||
handleOpenRejectDialog,
|
handleOpenRejectDialog,
|
||||||
handleCloseConfirmDialog,
|
handleCloseConfirmDialog,
|
||||||
handleCloseRejectDialog,
|
handleCloseRejectDialog,
|
||||||
rowId,
|
rowId,
|
||||||
confirmData,
|
confirmData,
|
||||||
rejectData,
|
rejectData,
|
||||||
} = useContext(DataTableContext);
|
} = useContext(DataTableContext);
|
||||||
return (
|
return (
|
||||||
<Box sx={{ display: "flex", flexWrap: "nowrap", gap: "8px" }}>
|
<Box sx={{display: "flex", flexWrap: "nowrap", gap: "8px"}}>
|
||||||
<Tooltip title={t("ConfirmDialog.confirm")}>
|
<Tooltip title={t("ConfirmDialog.confirm")}>
|
||||||
<IconButton
|
<IconButton
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleOpenConfirmDialog(row);
|
handleOpenConfirmDialog(row);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ThumbUpAltIcon />
|
<ThumbUpAltIcon/>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
{openConfirmDialog && (
|
{openConfirmDialog && (
|
||||||
<ConfirmForm
|
<ConfirmForm
|
||||||
rowId={rowId}
|
rowId={rowId}
|
||||||
open={openConfirmDialog}
|
open={openConfirmDialog}
|
||||||
handleClose={handleCloseConfirmDialog}
|
handleClose={handleCloseConfirmDialog}
|
||||||
confirmData={confirmData}
|
confirmData={confirmData}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Tooltip title={t("RejectDialog.reject")}>
|
<Tooltip title={t("RejectDialog.reject")}>
|
||||||
<IconButton color="primary" onClick={() => handleOpenRejectDialog(row)}>
|
<IconButton color="primary" onClick={() => handleOpenRejectDialog(row)}>
|
||||||
<ThumbDownIcon />
|
<ThumbDownIcon/>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
{openRejectDialog && (
|
{openRejectDialog && (
|
||||||
<RejectForm
|
<RejectForm
|
||||||
rowId={rowId}
|
rowId={rowId}
|
||||||
open={openRejectDialog}
|
open={openRejectDialog}
|
||||||
handleClose={handleCloseRejectDialog}
|
handleClose={handleCloseRejectDialog}
|
||||||
rejectData={rejectData}
|
rejectData={rejectData}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TableRowActions;
|
export default TableRowActions;
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { Stack, Tooltip } from "@mui/material";
|
import {Stack, Tooltip} from "@mui/material";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
|
|
||||||
function TableToolbar() {
|
function TableToolbar() {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
return (
|
return (
|
||||||
<Stack direction={"row"} spacing={2}>
|
<Stack direction={"row"} spacing={2}>
|
||||||
<Tooltip title={t("add")} arrow placement="right"></Tooltip>
|
<Tooltip title={t("add")} arrow placement="right"></Tooltip>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default TableToolbar;
|
export default TableToolbar;
|
||||||
|
|||||||
@@ -1,245 +1,242 @@
|
|||||||
import DataTableStructure from "@/core/components/DatatableStructure";
|
import DataTableStructure from "@/core/components/DatatableStructure";
|
||||||
import DashboardLayouts from "@/layouts/dashboardLayouts";
|
import DashboardLayouts from "@/layouts/dashboardLayouts";
|
||||||
import { Box, IconButton, Typography } from "@mui/material";
|
import {Box, IconButton, Typography} from "@mui/material";
|
||||||
import ClearIcon from "@mui/icons-material/Clear";
|
import ClearIcon from "@mui/icons-material/Clear";
|
||||||
import { useMemo } from "react";
|
import {useMemo} from "react";
|
||||||
// import TableToolbar from "./TableTollbar";
|
// import TableToolbar from "./TableTollbar";
|
||||||
import { GET_PROVINCE_MANAGER } from "@/core/data/apiRoutes";
|
import {GET_PROVINCE_MANAGER} from "@/core/data/apiRoutes";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import TableRowActions from "./TableRowActions";
|
import TableRowActions from "./TableRowActions";
|
||||||
import {
|
import {LocalizationProvider, MobileDateTimePicker,} from "@mui/x-date-pickers";
|
||||||
LocalizationProvider,
|
import {AdapterDateFnsJalali} from "@mui/x-date-pickers/AdapterDateFnsJalali";
|
||||||
MobileDateTimePicker,
|
|
||||||
} from "@mui/x-date-pickers";
|
|
||||||
import { AdapterDateFnsJalali } from "@mui/x-date-pickers/AdapterDateFnsJalali";
|
|
||||||
import moment from "jalali-moment";
|
import moment from "jalali-moment";
|
||||||
import { faIR } from "@mui/x-date-pickers/locales";
|
import {faIR} from "@mui/x-date-pickers/locales";
|
||||||
|
|
||||||
function DashboardProvinceManagerComponent() {
|
function DashboardProvinceManagerComponent() {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
|
|
||||||
const columns = useMemo(
|
const columns = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
accessorFn: (row) => row.id,
|
accessorFn: (row) => row.id,
|
||||||
id: "id",
|
id: "id",
|
||||||
header: t("ProvinceManager.id"),
|
header: t("ProvinceManager.id"),
|
||||||
enableColumnFilter: true,
|
enableColumnFilter: true,
|
||||||
datatype: "numeric",
|
datatype: "numeric",
|
||||||
filterFn: "equals",
|
filterFn: "equals",
|
||||||
maxSize: 100,
|
maxSize: 100,
|
||||||
columnFilterModeOptions: [
|
columnFilterModeOptions: [
|
||||||
"equals",
|
"equals",
|
||||||
"notEquals",
|
"notEquals",
|
||||||
"contains",
|
"contains",
|
||||||
"lessThan",
|
"lessThan",
|
||||||
"greaterThan",
|
"greaterThan",
|
||||||
"between",
|
"between",
|
||||||
|
],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.name,
|
||||||
|
id: "name",
|
||||||
|
header: t("ProvinceManager.name"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "text",
|
||||||
|
filterFn: "contains",
|
||||||
|
columnFilterModeOptions: ["contains", "equals", "notEquals"],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.national_id,
|
||||||
|
id: "national_id",
|
||||||
|
header: t("ProvinceManager.national_id"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "numeric",
|
||||||
|
filterFn: "equals",
|
||||||
|
columnFilterModeOptions: [
|
||||||
|
"equals",
|
||||||
|
"notEquals",
|
||||||
|
"contains",
|
||||||
|
"lessThan",
|
||||||
|
"greaterThan",
|
||||||
|
"between",
|
||||||
|
],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.phone_number,
|
||||||
|
id: "phone_number",
|
||||||
|
header: t("ProvinceManager.phone_number"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "numeric",
|
||||||
|
filterFn: "equals",
|
||||||
|
columnFilterModeOptions: [
|
||||||
|
"equals",
|
||||||
|
"notEquals",
|
||||||
|
"contains",
|
||||||
|
"lessThan",
|
||||||
|
"greaterThan",
|
||||||
|
"between",
|
||||||
|
],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) =>
|
||||||
|
moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
|
||||||
|
id: "created_at",
|
||||||
|
header: t("ProvinceManager.created_at"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "date",
|
||||||
|
filterFn: "lessThan",
|
||||||
|
minSize: 200,
|
||||||
|
columnFilterModeOptions: ["lessThan", "greaterThan"],
|
||||||
|
Cell: ({renderedCellValue}) => {
|
||||||
|
return <Typography variant="body2">{renderedCellValue}</Typography>;
|
||||||
|
},
|
||||||
|
Header: ({column}) => <em>{column.columnDef.header}</em>,
|
||||||
|
Filter: ({column}) => {
|
||||||
|
const filterFnValue = column.columnDef._filterFn;
|
||||||
|
return (
|
||||||
|
<Box sx={{display: "flex", alignItems: "start"}}>
|
||||||
|
<LocalizationProvider
|
||||||
|
dateAdapter={AdapterDateFnsJalali}
|
||||||
|
localeText={
|
||||||
|
faIR.components.MuiLocalizationProvider.defaultProps
|
||||||
|
.localeText
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<MobileDateTimePicker
|
||||||
|
ampm={false}
|
||||||
|
onChange={(newValue) => {
|
||||||
|
const date = new Date(newValue);
|
||||||
|
const formattedDate = moment(date)
|
||||||
|
.locale("en")
|
||||||
|
.format("YYYY-MM-DD HH:mm");
|
||||||
|
column.setFilterValue(formattedDate);
|
||||||
|
}}
|
||||||
|
slotProps={{
|
||||||
|
textField: {
|
||||||
|
placeholder: "تاریخ خود را وارد کنید",
|
||||||
|
helperText: `${t("filter_mode")}: ${t(filterFnValue)}`,
|
||||||
|
sx: {minWidth: "120px"},
|
||||||
|
variant: "standard",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
value={
|
||||||
|
column.getFilterValue()
|
||||||
|
? new Date(column.getFilterValue())
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</LocalizationProvider>
|
||||||
|
<IconButton
|
||||||
|
size="small"
|
||||||
|
onClick={() => {
|
||||||
|
column.setFilterValue(null);
|
||||||
|
}}
|
||||||
|
sx={{
|
||||||
|
color: column.getFilterValue()
|
||||||
|
? "rgba(0, 0, 0, 0.54)"
|
||||||
|
: "#bfbfbf",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ClearIcon/>
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) =>
|
||||||
|
moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
|
||||||
|
id: "updated_at",
|
||||||
|
header: t("ProvinceManager.updated_at"),
|
||||||
|
enableColumnFilter: false,
|
||||||
|
datatype: "numeric",
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.navgan_id,
|
||||||
|
id: "navgan_id",
|
||||||
|
header: t("ProvinceManager.navgan_id"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "numeric",
|
||||||
|
filterFn: "equals",
|
||||||
|
maxSize: 100,
|
||||||
|
columnFilterModeOptions: [
|
||||||
|
"equals",
|
||||||
|
"notEquals",
|
||||||
|
"contains",
|
||||||
|
"lessThan",
|
||||||
|
"greaterThan",
|
||||||
|
"between",
|
||||||
|
],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.vehicle_type,
|
||||||
|
id: "vehicle_type",
|
||||||
|
header: t("ProvinceManager.vehicle_type"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "text",
|
||||||
|
filterFn: "contains",
|
||||||
|
columnFilterModeOptions: ["contains", "equals", "notEquals"],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.state_name,
|
||||||
|
id: "state_id",
|
||||||
|
header: t("ProvinceManager.state_name"),
|
||||||
|
enableColumnFilter: false,
|
||||||
|
datatype: "numeric",
|
||||||
|
minSize: 300,
|
||||||
|
// filterFn: "equals",
|
||||||
|
// filterSelectOptions: [
|
||||||
|
// ],
|
||||||
|
// filterVariant: "select",
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
Cell: ({ renderedCellValue }) => (
|
[]
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
);
|
||||||
),
|
return (
|
||||||
},
|
<DashboardLayouts>
|
||||||
{
|
<Box sx={{px: 3}}>
|
||||||
accessorFn: (row) => row.name,
|
<DataTableStructure
|
||||||
id: "name",
|
tableUrl={GET_PROVINCE_MANAGER}
|
||||||
header: t("ProvinceManager.name"),
|
columns={columns}
|
||||||
enableColumnFilter: true,
|
selectableRow={false}
|
||||||
datatype: "text",
|
enableCustomToolbar={true}
|
||||||
filterFn: "contains",
|
// CustomToolbar={<TableToolbar />}
|
||||||
columnFilterModeOptions: ["contains", "equals", "notEquals"],
|
enableLastUpdate={true}
|
||||||
Cell: ({ renderedCellValue }) => (
|
enablePinning={true}
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
enableDensityToggle={true}
|
||||||
),
|
enableColumnFilters={true}
|
||||||
},
|
enableHiding={true}
|
||||||
{
|
enableFullScreenToggle={false}
|
||||||
accessorFn: (row) => row.national_id,
|
enableGlobalFilter={false}
|
||||||
id: "national_id",
|
enableColumnResizing={false} // if you want true this you shold change renderRowActions props ** see https://www.material-react-table.com/docs/guides/row-actions
|
||||||
header: t("ProvinceManager.national_id"),
|
enableRowActions={true}
|
||||||
enableColumnFilter: true,
|
renderRowActions={({row}) => <TableRowActions row={row}/>}
|
||||||
datatype: "numeric",
|
|
||||||
filterFn: "equals",
|
|
||||||
columnFilterModeOptions: [
|
|
||||||
"equals",
|
|
||||||
"notEquals",
|
|
||||||
"contains",
|
|
||||||
"lessThan",
|
|
||||||
"greaterThan",
|
|
||||||
"between",
|
|
||||||
],
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) => row.phone_number,
|
|
||||||
id: "phone_number",
|
|
||||||
header: t("ProvinceManager.phone_number"),
|
|
||||||
enableColumnFilter: true,
|
|
||||||
datatype: "numeric",
|
|
||||||
filterFn: "equals",
|
|
||||||
columnFilterModeOptions: [
|
|
||||||
"equals",
|
|
||||||
"notEquals",
|
|
||||||
"contains",
|
|
||||||
"lessThan",
|
|
||||||
"greaterThan",
|
|
||||||
"between",
|
|
||||||
],
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) =>
|
|
||||||
moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
|
|
||||||
id: "created_at",
|
|
||||||
header: t("ProvinceManager.created_at"),
|
|
||||||
enableColumnFilter: true,
|
|
||||||
datatype: "date",
|
|
||||||
filterFn: "lessThan",
|
|
||||||
minSize: 200,
|
|
||||||
columnFilterModeOptions: ["lessThan", "greaterThan"],
|
|
||||||
Cell: ({ renderedCellValue }) => {
|
|
||||||
return <Typography variant="body2">{renderedCellValue}</Typography>;
|
|
||||||
},
|
|
||||||
Header: ({ column }) => <em>{column.columnDef.header}</em>,
|
|
||||||
Filter: ({ column }) => {
|
|
||||||
const filterFnValue = column.columnDef._filterFn;
|
|
||||||
return (
|
|
||||||
<Box sx={{ display: "flex", alignItems: "start" }}>
|
|
||||||
<LocalizationProvider
|
|
||||||
dateAdapter={AdapterDateFnsJalali}
|
|
||||||
localeText={
|
|
||||||
faIR.components.MuiLocalizationProvider.defaultProps
|
|
||||||
.localeText
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<MobileDateTimePicker
|
|
||||||
ampm={false}
|
|
||||||
onChange={(newValue) => {
|
|
||||||
const date = new Date(newValue);
|
|
||||||
const formattedDate = moment(date)
|
|
||||||
.locale("en")
|
|
||||||
.format("YYYY-MM-DD HH:mm");
|
|
||||||
column.setFilterValue(formattedDate);
|
|
||||||
}}
|
|
||||||
slotProps={{
|
|
||||||
textField: {
|
|
||||||
placeholder: "تاریخ خود را وارد کنید",
|
|
||||||
helperText: `${t("filter_mode")}: ${t(filterFnValue)}`,
|
|
||||||
sx: { minWidth: "120px" },
|
|
||||||
variant: "standard",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
value={
|
|
||||||
column.getFilterValue()
|
|
||||||
? new Date(column.getFilterValue())
|
|
||||||
: null
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</LocalizationProvider>
|
|
||||||
<IconButton
|
|
||||||
size="small"
|
|
||||||
onClick={() => {
|
|
||||||
column.setFilterValue(null);
|
|
||||||
}}
|
|
||||||
sx={{
|
|
||||||
color: column.getFilterValue()
|
|
||||||
? "rgba(0, 0, 0, 0.54)"
|
|
||||||
: "#bfbfbf",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ClearIcon />
|
|
||||||
</IconButton>
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
</DashboardLayouts>
|
||||||
},
|
);
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) =>
|
|
||||||
moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
|
|
||||||
id: "updated_at",
|
|
||||||
header: t("ProvinceManager.updated_at"),
|
|
||||||
enableColumnFilter: false,
|
|
||||||
datatype: "numeric",
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) => row.navgan_id,
|
|
||||||
id: "navgan_id",
|
|
||||||
header: t("ProvinceManager.navgan_id"),
|
|
||||||
enableColumnFilter: true,
|
|
||||||
datatype: "numeric",
|
|
||||||
filterFn: "equals",
|
|
||||||
maxSize: 100,
|
|
||||||
columnFilterModeOptions: [
|
|
||||||
"equals",
|
|
||||||
"notEquals",
|
|
||||||
"contains",
|
|
||||||
"lessThan",
|
|
||||||
"greaterThan",
|
|
||||||
"between",
|
|
||||||
],
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) => row.vehicle_type,
|
|
||||||
id: "vehicle_type",
|
|
||||||
header: t("ProvinceManager.vehicle_type"),
|
|
||||||
enableColumnFilter: true,
|
|
||||||
datatype: "text",
|
|
||||||
filterFn: "contains",
|
|
||||||
columnFilterModeOptions: ["contains", "equals", "notEquals"],
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) => row.state_name,
|
|
||||||
id: "state_id",
|
|
||||||
header: t("ProvinceManager.state_name"),
|
|
||||||
enableColumnFilter: false,
|
|
||||||
datatype: "numeric",
|
|
||||||
minSize: 300,
|
|
||||||
// filterFn: "equals",
|
|
||||||
// filterSelectOptions: [
|
|
||||||
// ],
|
|
||||||
// filterVariant: "select",
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
<DashboardLayouts>
|
|
||||||
<Box sx={{ px: 3 }}>
|
|
||||||
<DataTableStructure
|
|
||||||
tableUrl={GET_PROVINCE_MANAGER}
|
|
||||||
columns={columns}
|
|
||||||
selectableRow={false}
|
|
||||||
enableCustomToolbar={true}
|
|
||||||
// CustomToolbar={<TableToolbar />}
|
|
||||||
enableLastUpdate={true}
|
|
||||||
enablePinning={true}
|
|
||||||
enableDensityToggle={true}
|
|
||||||
enableColumnFilters={true}
|
|
||||||
enableHiding={true}
|
|
||||||
enableFullScreenToggle={false}
|
|
||||||
enableGlobalFilter={false}
|
|
||||||
enableColumnResizing={false} // if you want true this you shold change renderRowActions props ** see https://www.material-react-table.com/docs/guides/row-actions
|
|
||||||
enableRowActions={true}
|
|
||||||
renderRowActions={({ row }) => <TableRowActions row={row} />}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</DashboardLayouts>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DashboardProvinceManagerComponent;
|
export default DashboardProvinceManagerComponent;
|
||||||
|
|||||||
@@ -1,102 +1,94 @@
|
|||||||
import UploadSystem from "@/core/components/UploadSystem";
|
import UploadSystem from "@/core/components/UploadSystem";
|
||||||
import { CONFIRM_TRANSPORTATION_ASSISTANCE } from "@/core/data/apiRoutes";
|
import {CONFIRM_TRANSPORTATION_ASSISTANCE} from "@/core/data/apiRoutes";
|
||||||
import useDirection from "@/lib/app/hooks/useDirection";
|
import useDirection from "@/lib/app/hooks/useDirection";
|
||||||
import {
|
import {Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, TextField,} from "@mui/material";
|
||||||
Dialog,
|
import {useFormik} from "formik";
|
||||||
DialogTitle,
|
import {useTranslations} from "next-intl";
|
||||||
DialogContent,
|
import {useState} from "react";
|
||||||
DialogContentText,
|
|
||||||
DialogActions,
|
|
||||||
Button,
|
|
||||||
TextField,
|
|
||||||
} from "@mui/material";
|
|
||||||
import { useFormik } from "formik";
|
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useState } from "react";
|
|
||||||
import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
|
import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
|
||||||
|
|
||||||
const ConfirmForm = ({ open, handleClose, rowId, confirmData }) => {
|
const ConfirmForm = ({open, handleClose, rowId, confirmData}) => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const { directionApp } = useDirection();
|
const {directionApp} = useDirection();
|
||||||
const [description, setDescription] = useState("");
|
const [description, setDescription] = useState("");
|
||||||
const [selectedImage, setSelectedImage] = useState("");
|
const [selectedImage, setSelectedImage] = useState("");
|
||||||
const [fileType, setfileType] = useState(null);
|
const [fileType, setfileType] = useState(null);
|
||||||
const [fileName, setfileName] = useState(null);
|
const [fileName, setfileName] = useState(null);
|
||||||
const [showAddIcon, setShowAddIcon] = useState(true);
|
const [showAddIcon, setShowAddIcon] = useState(true);
|
||||||
|
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
description: "",
|
description: "",
|
||||||
},
|
},
|
||||||
onSubmit: () => {
|
onSubmit: () => {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
if (description != "") formData.append("expert_description", description);
|
if (description != "") formData.append("expert_description", description);
|
||||||
handleClose();
|
handleClose();
|
||||||
confirmData(CONFIRM_TRANSPORTATION_ASSISTANCE, rowId, formData);
|
confirmData(CONFIRM_TRANSPORTATION_ASSISTANCE, rowId, formData);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleDescriptionChange = (event) => {
|
const handleDescriptionChange = (event) => {
|
||||||
setDescription(event.target.value);
|
setDescription(event.target.value);
|
||||||
};
|
};
|
||||||
const handleUploadChange = (event) => {
|
const handleUploadChange = (event) => {
|
||||||
const uploadedFile = event.target?.files?.[0];
|
const uploadedFile = event.target?.files?.[0];
|
||||||
if (uploadedFile) {
|
if (uploadedFile) {
|
||||||
const maxFileSize = 2 * 1024 * 1024;
|
const maxFileSize = 2 * 1024 * 1024;
|
||||||
if (uploadedFile.size > maxFileSize) {
|
if (uploadedFile.size > maxFileSize) {
|
||||||
UploadFileNotification(directionApp, t);
|
UploadFileNotification(directionApp, t);
|
||||||
event.target.value = "";
|
event.target.value = "";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fileType = event.target?.files?.[0].type;
|
const fileType = event.target?.files?.[0].type;
|
||||||
const fileName = event.target?.files?.[0].name;
|
const fileName = event.target?.files?.[0].name;
|
||||||
setSelectedImage(URL.createObjectURL(uploadedFile));
|
setSelectedImage(URL.createObjectURL(uploadedFile));
|
||||||
setfileType(fileType);
|
setfileType(fileType);
|
||||||
setfileName(fileName);
|
setfileName(fileName);
|
||||||
formik.setFieldValue("confirm_img", uploadedFile);
|
formik.setFieldValue("confirm_img", uploadedFile);
|
||||||
setShowAddIcon(false);
|
setShowAddIcon(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Dialog open={open}>
|
<Dialog open={open}>
|
||||||
<DialogTitle>{t("ConfirmDialog.confirm")}</DialogTitle>
|
<DialogTitle>{t("ConfirmDialog.confirm")}</DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<DialogContentText>{t("ConfirmDialog.context")}</DialogContentText>
|
<DialogContentText>{t("ConfirmDialog.context")}</DialogContentText>
|
||||||
<TextField
|
<TextField
|
||||||
name="description"
|
name="description"
|
||||||
multiline
|
multiline
|
||||||
rows={8}
|
rows={8}
|
||||||
placeholder={t("ConfirmDialog.description")}
|
placeholder={t("ConfirmDialog.description")}
|
||||||
value={description}
|
value={description}
|
||||||
onChange={handleDescriptionChange}
|
onChange={handleDescriptionChange}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
sx={{ mt: 1 }}
|
sx={{mt: 1}}
|
||||||
/>
|
/>
|
||||||
<UploadSystem
|
<UploadSystem
|
||||||
selectedImage={selectedImage}
|
selectedImage={selectedImage}
|
||||||
handleUploadChange={handleUploadChange} // Pass the updated function directly
|
handleUploadChange={handleUploadChange} // Pass the updated function directly
|
||||||
setselectedImage={setSelectedImage}
|
setselectedImage={setSelectedImage}
|
||||||
setFieldValue={formik.setFieldValue} // Remove props.setFieldValue, use formik.setFieldValue
|
setFieldValue={formik.setFieldValue} // Remove props.setFieldValue, use formik.setFieldValue
|
||||||
fieldname="confirm_img"
|
fieldname="confirm_img"
|
||||||
fileType={fileType}
|
fileType={fileType}
|
||||||
fileName={fileName}
|
fileName={fileName}
|
||||||
imageAlt={t("app_name")}
|
imageAlt={t("app_name")}
|
||||||
imageSize={[250 /*width*/, 150 /*height*/]}
|
imageSize={[250 /*width*/, 150 /*height*/]}
|
||||||
setShowAddIcon={setShowAddIcon}
|
setShowAddIcon={setShowAddIcon}
|
||||||
showAddIcon={showAddIcon}
|
showAddIcon={showAddIcon}
|
||||||
/>
|
/>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button onClick={handleClose} color="secondary" autoFocus>
|
<Button onClick={handleClose} color="secondary" autoFocus>
|
||||||
{t("ConfirmDialog.button-cancel")}
|
{t("ConfirmDialog.button-cancel")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={formik.handleSubmit} color="primary">
|
<Button onClick={formik.handleSubmit} color="primary">
|
||||||
{t("ConfirmDialog.button-confirm")}
|
{t("ConfirmDialog.button-confirm")}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default ConfirmForm;
|
export default ConfirmForm;
|
||||||
|
|||||||
@@ -1,113 +1,105 @@
|
|||||||
import { REJECT_TRANSPORTATION_ASSISTANCE } from "@/core/data/apiRoutes";
|
import {REJECT_TRANSPORTATION_ASSISTANCE} from "@/core/data/apiRoutes";
|
||||||
import {
|
import {Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, TextField,} from "@mui/material";
|
||||||
Dialog,
|
import {useTranslations} from "next-intl";
|
||||||
DialogTitle,
|
import {useFormik} from "formik";
|
||||||
DialogContent,
|
|
||||||
DialogContentText,
|
|
||||||
DialogActions,
|
|
||||||
Button,
|
|
||||||
TextField,
|
|
||||||
} from "@mui/material";
|
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useFormik } from "formik";
|
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
import { useState } from "react";
|
import {useState} from "react";
|
||||||
import UploadSystem from "@/core/components/UploadSystem";
|
import UploadSystem from "@/core/components/UploadSystem";
|
||||||
import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
|
import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
|
||||||
import useDirection from "@/lib/app/hooks/useDirection";
|
import useDirection from "@/lib/app/hooks/useDirection";
|
||||||
|
|
||||||
const RejectForm = ({ open, handleClose, rowId, rejectData }) => {
|
const RejectForm = ({open, handleClose, rowId, rejectData}) => {
|
||||||
const [description, setDescription] = useState("");
|
const [description, setDescription] = useState("");
|
||||||
const [selectedImage, setSelectedImage] = useState("");
|
const [selectedImage, setSelectedImage] = useState("");
|
||||||
const [fileType, setfileType] = useState(null);
|
const [fileType, setfileType] = useState(null);
|
||||||
const [fileName, setfileName] = useState(null);
|
const [fileName, setfileName] = useState(null);
|
||||||
const [showAddIcon, setShowAddIcon] = useState(true);
|
const [showAddIcon, setShowAddIcon] = useState(true);
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const { directionApp } = useDirection();
|
const {directionApp} = useDirection();
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
description: Yup.string().required(t("RejectDialog.description_error")),
|
description: Yup.string().required(t("RejectDialog.description_error")),
|
||||||
});
|
});
|
||||||
|
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
description: "",
|
description: "",
|
||||||
},
|
},
|
||||||
validationSchema,
|
validationSchema,
|
||||||
onSubmit: () => {
|
onSubmit: () => {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("expert_description", description);
|
formData.append("expert_description", description);
|
||||||
handleClose();
|
handleClose();
|
||||||
rejectData(REJECT_TRANSPORTATION_ASSISTANCE, rowId, formData);
|
rejectData(REJECT_TRANSPORTATION_ASSISTANCE, rowId, formData);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleDescriptionChange = (event) => {
|
const handleDescriptionChange = (event) => {
|
||||||
setDescription(event.target.value);
|
setDescription(event.target.value);
|
||||||
formik.handleChange(event);
|
formik.handleChange(event);
|
||||||
};
|
};
|
||||||
const handleUploadChange = (event) => {
|
const handleUploadChange = (event) => {
|
||||||
const uploadedFile = event.target?.files?.[0];
|
const uploadedFile = event.target?.files?.[0];
|
||||||
if (uploadedFile) {
|
if (uploadedFile) {
|
||||||
const maxFileSize = 2 * 1024 * 1024;
|
const maxFileSize = 2 * 1024 * 1024;
|
||||||
if (uploadedFile.size > maxFileSize) {
|
if (uploadedFile.size > maxFileSize) {
|
||||||
UploadFileNotification(directionApp, t);
|
UploadFileNotification(directionApp, t);
|
||||||
event.target.value = "";
|
event.target.value = "";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const fileType = event.target?.files?.[0].type;
|
const fileType = event.target?.files?.[0].type;
|
||||||
const fileName = event.target?.files?.[0].name;
|
const fileName = event.target?.files?.[0].name;
|
||||||
setSelectedImage(URL.createObjectURL(uploadedFile));
|
setSelectedImage(URL.createObjectURL(uploadedFile));
|
||||||
setfileType(fileType);
|
setfileType(fileType);
|
||||||
setfileName(fileName);
|
setfileName(fileName);
|
||||||
formik.setFieldValue("reject_img", uploadedFile);
|
formik.setFieldValue("reject_img", uploadedFile);
|
||||||
setShowAddIcon(false);
|
setShowAddIcon(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Dialog open={open}>
|
<Dialog open={open}>
|
||||||
<DialogTitle>{t("RejectDialog.reject")}</DialogTitle>
|
<DialogTitle>{t("RejectDialog.reject")}</DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<DialogContentText>{t("RejectDialog.context")}</DialogContentText>
|
<DialogContentText>{t("RejectDialog.context")}</DialogContentText>
|
||||||
<TextField
|
<TextField
|
||||||
name="description"
|
name="description"
|
||||||
multiline
|
multiline
|
||||||
rows={8}
|
rows={8}
|
||||||
placeholder={t("RejectDialog.description")}
|
placeholder={t("RejectDialog.description")}
|
||||||
value={description}
|
value={description}
|
||||||
onChange={handleDescriptionChange}
|
onChange={handleDescriptionChange}
|
||||||
onBlur={formik.handleBlur("description")}
|
onBlur={formik.handleBlur("description")}
|
||||||
error={
|
error={
|
||||||
formik.touched.description && Boolean(formik.errors.description)
|
formik.touched.description && Boolean(formik.errors.description)
|
||||||
}
|
}
|
||||||
helperText={formik.touched.description && formik.errors.description}
|
helperText={formik.touched.description && formik.errors.description}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
sx={{ mt: 1 }}
|
sx={{mt: 1}}
|
||||||
/>
|
/>
|
||||||
<UploadSystem
|
<UploadSystem
|
||||||
selectedImage={selectedImage}
|
selectedImage={selectedImage}
|
||||||
handleUploadChange={handleUploadChange} // Pass the updated function directly
|
handleUploadChange={handleUploadChange} // Pass the updated function directly
|
||||||
setselectedImage={setSelectedImage}
|
setselectedImage={setSelectedImage}
|
||||||
setFieldValue={formik.setFieldValue} // Remove props.setFieldValue, use formik.setFieldValue
|
setFieldValue={formik.setFieldValue} // Remove props.setFieldValue, use formik.setFieldValue
|
||||||
fieldname="reject_img"
|
fieldname="reject_img"
|
||||||
fileType={fileType}
|
fileType={fileType}
|
||||||
fileName={fileName}
|
fileName={fileName}
|
||||||
imageAlt={t("app_name")}
|
imageAlt={t("app_name")}
|
||||||
imageSize={[250 /*width*/, 150 /*height*/]}
|
imageSize={[250 /*width*/, 150 /*height*/]}
|
||||||
setShowAddIcon={setShowAddIcon}
|
setShowAddIcon={setShowAddIcon}
|
||||||
showAddIcon={showAddIcon}
|
showAddIcon={showAddIcon}
|
||||||
/>
|
/>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button onClick={handleClose} color="secondary" autoFocus>
|
<Button onClick={handleClose} color="secondary" autoFocus>
|
||||||
{t("RejectDialog.button-cancel")}
|
{t("RejectDialog.button-cancel")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={formik.handleSubmit} color="primary">
|
<Button onClick={formik.handleSubmit} color="primary">
|
||||||
{t("RejectDialog.button-reject")}
|
{t("RejectDialog.button-reject")}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default RejectForm;
|
export default RejectForm;
|
||||||
|
|||||||
@@ -1,61 +1,61 @@
|
|||||||
import ThumbUpAltIcon from "@mui/icons-material/ThumbUpAlt";
|
import ThumbUpAltIcon from "@mui/icons-material/ThumbUpAlt";
|
||||||
import ThumbDownIcon from "@mui/icons-material/ThumbDown";
|
import ThumbDownIcon from "@mui/icons-material/ThumbDown";
|
||||||
import { Box, IconButton, Tooltip } from "@mui/material";
|
import {Box, IconButton, Tooltip} from "@mui/material";
|
||||||
import { useContext } from "react";
|
import {useContext} from "react";
|
||||||
import ConfirmForm from "./Form/ConfirmForm";
|
import ConfirmForm from "./Form/ConfirmForm";
|
||||||
import RejectForm from "./Form/RejectForm";
|
import RejectForm from "./Form/RejectForm";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import { DataTableContext } from "@/lib/app/contexts/DatatableContext";
|
import {DataTableContext} from "@/lib/app/contexts/DatatableContext";
|
||||||
|
|
||||||
const TableRowActions = ({ row }) => {
|
const TableRowActions = ({row}) => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
openConfirmDialog,
|
openConfirmDialog,
|
||||||
openRejectDialog,
|
openRejectDialog,
|
||||||
handleOpenConfirmDialog,
|
handleOpenConfirmDialog,
|
||||||
handleOpenRejectDialog,
|
handleOpenRejectDialog,
|
||||||
handleCloseConfirmDialog,
|
handleCloseConfirmDialog,
|
||||||
handleCloseRejectDialog,
|
handleCloseRejectDialog,
|
||||||
rowId,
|
rowId,
|
||||||
confirmData,
|
confirmData,
|
||||||
rejectData,
|
rejectData,
|
||||||
} = useContext(DataTableContext);
|
} = useContext(DataTableContext);
|
||||||
return (
|
return (
|
||||||
<Box sx={{ display: "flex", flexWrap: "nowrap", gap: "8px" }}>
|
<Box sx={{display: "flex", flexWrap: "nowrap", gap: "8px"}}>
|
||||||
<Tooltip title={t("ConfirmDialog.confirm")}>
|
<Tooltip title={t("ConfirmDialog.confirm")}>
|
||||||
<IconButton
|
<IconButton
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleOpenConfirmDialog(row);
|
handleOpenConfirmDialog(row);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ThumbUpAltIcon />
|
<ThumbUpAltIcon/>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
{openConfirmDialog && (
|
{openConfirmDialog && (
|
||||||
<ConfirmForm
|
<ConfirmForm
|
||||||
rowId={rowId}
|
rowId={rowId}
|
||||||
open={openConfirmDialog}
|
open={openConfirmDialog}
|
||||||
handleClose={handleCloseConfirmDialog}
|
handleClose={handleCloseConfirmDialog}
|
||||||
confirmData={confirmData}
|
confirmData={confirmData}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Tooltip title={t("RejectDialog.reject")}>
|
<Tooltip title={t("RejectDialog.reject")}>
|
||||||
<IconButton color="primary" onClick={() => handleOpenRejectDialog(row)}>
|
<IconButton color="primary" onClick={() => handleOpenRejectDialog(row)}>
|
||||||
<ThumbDownIcon />
|
<ThumbDownIcon/>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
{openRejectDialog && (
|
{openRejectDialog && (
|
||||||
<RejectForm
|
<RejectForm
|
||||||
rowId={rowId}
|
rowId={rowId}
|
||||||
open={openRejectDialog}
|
open={openRejectDialog}
|
||||||
handleClose={handleCloseRejectDialog}
|
handleClose={handleCloseRejectDialog}
|
||||||
rejectData={rejectData}
|
rejectData={rejectData}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TableRowActions;
|
export default TableRowActions;
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { Stack, Tooltip } from "@mui/material";
|
import {Stack, Tooltip} from "@mui/material";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
|
|
||||||
function TableToolbar() {
|
function TableToolbar() {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
return (
|
return (
|
||||||
<Stack direction={"row"} spacing={2}>
|
<Stack direction={"row"} spacing={2}>
|
||||||
<Tooltip title={t("add")} arrow placement="right"></Tooltip>
|
<Tooltip title={t("add")} arrow placement="right"></Tooltip>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default TableToolbar;
|
export default TableToolbar;
|
||||||
|
|||||||
@@ -1,245 +1,242 @@
|
|||||||
import DataTableStructure from "@/core/components/DatatableStructure";
|
import DataTableStructure from "@/core/components/DatatableStructure";
|
||||||
import DashboardLayouts from "@/layouts/dashboardLayouts";
|
import DashboardLayouts from "@/layouts/dashboardLayouts";
|
||||||
import { Box, IconButton, Typography } from "@mui/material";
|
import {Box, IconButton, Typography} from "@mui/material";
|
||||||
import ClearIcon from "@mui/icons-material/Clear";
|
import ClearIcon from "@mui/icons-material/Clear";
|
||||||
import { useMemo } from "react";
|
import {useMemo} from "react";
|
||||||
// import TableToolbar from "./TableTollbar";
|
// import TableToolbar from "./TableTollbar";
|
||||||
import { GET_TRANSPORTATION_ASSISTANCE } from "@/core/data/apiRoutes";
|
import {GET_TRANSPORTATION_ASSISTANCE} from "@/core/data/apiRoutes";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import TableRowActions from "./TableRowActions";
|
import TableRowActions from "./TableRowActions";
|
||||||
import {
|
import {LocalizationProvider, MobileDateTimePicker,} from "@mui/x-date-pickers";
|
||||||
LocalizationProvider,
|
import {AdapterDateFnsJalali} from "@mui/x-date-pickers/AdapterDateFnsJalali";
|
||||||
MobileDateTimePicker,
|
import {faIR} from "@mui/x-date-pickers/locales";
|
||||||
} from "@mui/x-date-pickers";
|
|
||||||
import { AdapterDateFnsJalali } from "@mui/x-date-pickers/AdapterDateFnsJalali";
|
|
||||||
import { faIR } from "@mui/x-date-pickers/locales";
|
|
||||||
import moment from "jalali-moment";
|
import moment from "jalali-moment";
|
||||||
|
|
||||||
function DashboardTransportationAssistanceComponent() {
|
function DashboardTransportationAssistanceComponent() {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const columns = useMemo(
|
const columns = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
accessorFn: (row) => row.id,
|
accessorFn: (row) => row.id,
|
||||||
id: "id",
|
id: "id",
|
||||||
header: t("TransportationAssistance.id"),
|
header: t("TransportationAssistance.id"),
|
||||||
enableColumnFilter: true,
|
enableColumnFilter: true,
|
||||||
datatype: "numeric",
|
datatype: "numeric",
|
||||||
filterFn: "equals",
|
filterFn: "equals",
|
||||||
maxSize: 100,
|
maxSize: 100,
|
||||||
columnFilterModeOptions: [
|
columnFilterModeOptions: [
|
||||||
"equals",
|
"equals",
|
||||||
"notEquals",
|
"notEquals",
|
||||||
"contains",
|
"contains",
|
||||||
"lessThan",
|
"lessThan",
|
||||||
"greaterThan",
|
"greaterThan",
|
||||||
"between",
|
"between",
|
||||||
],
|
],
|
||||||
Cell: ({ renderedCellValue }) => (
|
Cell: ({renderedCellValue}) => (
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorFn: (row) => row.name,
|
accessorFn: (row) => row.name,
|
||||||
id: "name",
|
id: "name",
|
||||||
header: t("TransportationAssistance.name"),
|
header: t("TransportationAssistance.name"),
|
||||||
enableColumnFilter: true,
|
enableColumnFilter: true,
|
||||||
datatype: "text",
|
datatype: "text",
|
||||||
filterFn: "contains",
|
filterFn: "contains",
|
||||||
columnFilterModeOptions: ["contains", "equals", "notEquals"],
|
columnFilterModeOptions: ["contains", "equals", "notEquals"],
|
||||||
Cell: ({ renderedCellValue }) => (
|
Cell: ({renderedCellValue}) => (
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
accessorFn: (row) => row.national_id,
|
accessorFn: (row) => row.national_id,
|
||||||
id: "national_id",
|
id: "national_id",
|
||||||
header: t("TransportationAssistance.national_id"),
|
header: t("TransportationAssistance.national_id"),
|
||||||
enableColumnFilter: true,
|
enableColumnFilter: true,
|
||||||
datatype: "numeric",
|
datatype: "numeric",
|
||||||
filterFn: "equals",
|
filterFn: "equals",
|
||||||
columnFilterModeOptions: [
|
columnFilterModeOptions: [
|
||||||
"equals",
|
"equals",
|
||||||
"notEquals",
|
"notEquals",
|
||||||
"contains",
|
"contains",
|
||||||
"lessThan",
|
"lessThan",
|
||||||
"greaterThan",
|
"greaterThan",
|
||||||
"between",
|
"between",
|
||||||
|
],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.phone_number,
|
||||||
|
id: "phone_number",
|
||||||
|
header: t("TransportationAssistance.phone_number"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "numeric",
|
||||||
|
filterFn: "equals",
|
||||||
|
columnFilterModeOptions: [
|
||||||
|
"equals",
|
||||||
|
"notEquals",
|
||||||
|
"contains",
|
||||||
|
"lessThan",
|
||||||
|
"greaterThan",
|
||||||
|
"between",
|
||||||
|
],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) =>
|
||||||
|
moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
|
||||||
|
id: "created_at",
|
||||||
|
header: t("TransportationAssistance.created_at"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "date",
|
||||||
|
minSize: 200,
|
||||||
|
filterFn: "lessThan",
|
||||||
|
columnFilterModeOptions: ["lessThan", "greaterThan"],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
Header: ({column}) => <em>{column.columnDef.header}</em>,
|
||||||
|
Filter: ({column}) => {
|
||||||
|
const filterFnValue = column.columnDef._filterFn;
|
||||||
|
return (
|
||||||
|
<Box sx={{display: "flex", alignItems: "start"}}>
|
||||||
|
<LocalizationProvider
|
||||||
|
dateAdapter={AdapterDateFnsJalali}
|
||||||
|
localeText={
|
||||||
|
faIR.components.MuiLocalizationProvider.defaultProps
|
||||||
|
.localeText
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<MobileDateTimePicker
|
||||||
|
ampm={false}
|
||||||
|
onChange={(newValue) => {
|
||||||
|
const date = new Date(newValue);
|
||||||
|
const formattedDate = moment(date)
|
||||||
|
.locale("en")
|
||||||
|
.format("YYYY-MM-DD HH:mm");
|
||||||
|
column.setFilterValue(formattedDate);
|
||||||
|
}}
|
||||||
|
slotProps={{
|
||||||
|
textField: {
|
||||||
|
placeholder: "تاریخ خود را وارد کنید",
|
||||||
|
helperText: `${t("filter_mode")}: ${t(filterFnValue)}`,
|
||||||
|
sx: {minWidth: "120px"},
|
||||||
|
variant: "standard",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
value={
|
||||||
|
column.getFilterValue()
|
||||||
|
? new Date(column.getFilterValue())
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</LocalizationProvider>
|
||||||
|
<IconButton
|
||||||
|
size="small"
|
||||||
|
onClick={() => {
|
||||||
|
column.setFilterValue(null);
|
||||||
|
}}
|
||||||
|
sx={{
|
||||||
|
color: column.getFilterValue()
|
||||||
|
? "rgba(0, 0, 0, 0.54)"
|
||||||
|
: "#bfbfbf",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ClearIcon/>
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) =>
|
||||||
|
moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
|
||||||
|
id: "updated_at",
|
||||||
|
header: t("TransportationAssistance.updated_at"),
|
||||||
|
enableColumnFilter: false,
|
||||||
|
datatype: "numeric",
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.navgan_id,
|
||||||
|
id: "navgan_id",
|
||||||
|
header: t("TransportationAssistance.navgan_id"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "numeric",
|
||||||
|
filterFn: "equals",
|
||||||
|
maxSize: 100,
|
||||||
|
columnFilterModeOptions: [
|
||||||
|
"equals",
|
||||||
|
"notEquals",
|
||||||
|
"contains",
|
||||||
|
"lessThan",
|
||||||
|
"greaterThan",
|
||||||
|
"between",
|
||||||
|
],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.vehicle_type,
|
||||||
|
id: "vehicle_type",
|
||||||
|
header: t("TransportationAssistance.vehicle_type"),
|
||||||
|
enableColumnFilter: true,
|
||||||
|
datatype: "text",
|
||||||
|
filterFn: "contains",
|
||||||
|
columnFilterModeOptions: ["contains", "equals", "notEquals"],
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.state_name,
|
||||||
|
id: "state_id",
|
||||||
|
header: t("TransportationAssistance.state_name"),
|
||||||
|
enableColumnFilter: false,
|
||||||
|
datatype: "numeric",
|
||||||
|
minSize: 300,
|
||||||
|
// filterFn: "equals",
|
||||||
|
// filterSelectOptions: [
|
||||||
|
// ],
|
||||||
|
// filterVariant: "select",
|
||||||
|
Cell: ({renderedCellValue}) => (
|
||||||
|
<Typography variant="body2">{renderedCellValue}</Typography>
|
||||||
|
),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
Cell: ({ renderedCellValue }) => (
|
[]
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
);
|
||||||
),
|
return (
|
||||||
},
|
<DashboardLayouts>
|
||||||
{
|
<Box sx={{px: 3}}>
|
||||||
accessorFn: (row) => row.phone_number,
|
<DataTableStructure
|
||||||
id: "phone_number",
|
tableUrl={GET_TRANSPORTATION_ASSISTANCE}
|
||||||
header: t("TransportationAssistance.phone_number"),
|
columns={columns}
|
||||||
enableColumnFilter: true,
|
selectableRow={false}
|
||||||
datatype: "numeric",
|
enableCustomToolbar={true}
|
||||||
filterFn: "equals",
|
// CustomToolbar={<TableToolbar />}
|
||||||
columnFilterModeOptions: [
|
enableLastUpdate={true}
|
||||||
"equals",
|
enablePinning={true}
|
||||||
"notEquals",
|
enableDensityToggle={true}
|
||||||
"contains",
|
enableColumnFilters={true}
|
||||||
"lessThan",
|
enableHiding={true}
|
||||||
"greaterThan",
|
enableFullScreenToggle={false}
|
||||||
"between",
|
enableGlobalFilter={false}
|
||||||
],
|
enableColumnResizing={false} // if you want true this you shold change renderRowActions props ** see https://www.material-react-table.com/docs/guides/row-actions
|
||||||
Cell: ({ renderedCellValue }) => (
|
enableRowActions={true}
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
renderRowActions={({row}) => <TableRowActions row={row}/>}
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) =>
|
|
||||||
moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
|
|
||||||
id: "created_at",
|
|
||||||
header: t("TransportationAssistance.created_at"),
|
|
||||||
enableColumnFilter: true,
|
|
||||||
datatype: "date",
|
|
||||||
minSize: 200,
|
|
||||||
filterFn: "lessThan",
|
|
||||||
columnFilterModeOptions: ["lessThan", "greaterThan"],
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
Header: ({ column }) => <em>{column.columnDef.header}</em>,
|
|
||||||
Filter: ({ column }) => {
|
|
||||||
const filterFnValue = column.columnDef._filterFn;
|
|
||||||
return (
|
|
||||||
<Box sx={{ display: "flex", alignItems: "start" }}>
|
|
||||||
<LocalizationProvider
|
|
||||||
dateAdapter={AdapterDateFnsJalali}
|
|
||||||
localeText={
|
|
||||||
faIR.components.MuiLocalizationProvider.defaultProps
|
|
||||||
.localeText
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<MobileDateTimePicker
|
|
||||||
ampm={false}
|
|
||||||
onChange={(newValue) => {
|
|
||||||
const date = new Date(newValue);
|
|
||||||
const formattedDate = moment(date)
|
|
||||||
.locale("en")
|
|
||||||
.format("YYYY-MM-DD HH:mm");
|
|
||||||
column.setFilterValue(formattedDate);
|
|
||||||
}}
|
|
||||||
slotProps={{
|
|
||||||
textField: {
|
|
||||||
placeholder: "تاریخ خود را وارد کنید",
|
|
||||||
helperText: `${t("filter_mode")}: ${t(filterFnValue)}`,
|
|
||||||
sx: { minWidth: "120px" },
|
|
||||||
variant: "standard",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
value={
|
|
||||||
column.getFilterValue()
|
|
||||||
? new Date(column.getFilterValue())
|
|
||||||
: null
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</LocalizationProvider>
|
|
||||||
<IconButton
|
|
||||||
size="small"
|
|
||||||
onClick={() => {
|
|
||||||
column.setFilterValue(null);
|
|
||||||
}}
|
|
||||||
sx={{
|
|
||||||
color: column.getFilterValue()
|
|
||||||
? "rgba(0, 0, 0, 0.54)"
|
|
||||||
: "#bfbfbf",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ClearIcon />
|
|
||||||
</IconButton>
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
</DashboardLayouts>
|
||||||
},
|
);
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) =>
|
|
||||||
moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
|
|
||||||
id: "updated_at",
|
|
||||||
header: t("TransportationAssistance.updated_at"),
|
|
||||||
enableColumnFilter: false,
|
|
||||||
datatype: "numeric",
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) => row.navgan_id,
|
|
||||||
id: "navgan_id",
|
|
||||||
header: t("TransportationAssistance.navgan_id"),
|
|
||||||
enableColumnFilter: true,
|
|
||||||
datatype: "numeric",
|
|
||||||
filterFn: "equals",
|
|
||||||
maxSize: 100,
|
|
||||||
columnFilterModeOptions: [
|
|
||||||
"equals",
|
|
||||||
"notEquals",
|
|
||||||
"contains",
|
|
||||||
"lessThan",
|
|
||||||
"greaterThan",
|
|
||||||
"between",
|
|
||||||
],
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) => row.vehicle_type,
|
|
||||||
id: "vehicle_type",
|
|
||||||
header: t("TransportationAssistance.vehicle_type"),
|
|
||||||
enableColumnFilter: true,
|
|
||||||
datatype: "text",
|
|
||||||
filterFn: "contains",
|
|
||||||
columnFilterModeOptions: ["contains", "equals", "notEquals"],
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: (row) => row.state_name,
|
|
||||||
id: "state_id",
|
|
||||||
header: t("TransportationAssistance.state_name"),
|
|
||||||
enableColumnFilter: false,
|
|
||||||
datatype: "numeric",
|
|
||||||
minSize: 300,
|
|
||||||
// filterFn: "equals",
|
|
||||||
// filterSelectOptions: [
|
|
||||||
// ],
|
|
||||||
// filterVariant: "select",
|
|
||||||
Cell: ({ renderedCellValue }) => (
|
|
||||||
<Typography variant="body2">{renderedCellValue}</Typography>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
<DashboardLayouts>
|
|
||||||
<Box sx={{ px: 3 }}>
|
|
||||||
<DataTableStructure
|
|
||||||
tableUrl={GET_TRANSPORTATION_ASSISTANCE}
|
|
||||||
columns={columns}
|
|
||||||
selectableRow={false}
|
|
||||||
enableCustomToolbar={true}
|
|
||||||
// CustomToolbar={<TableToolbar />}
|
|
||||||
enableLastUpdate={true}
|
|
||||||
enablePinning={true}
|
|
||||||
enableDensityToggle={true}
|
|
||||||
enableColumnFilters={true}
|
|
||||||
enableHiding={true}
|
|
||||||
enableFullScreenToggle={false}
|
|
||||||
enableGlobalFilter={false}
|
|
||||||
enableColumnResizing={false} // if you want true this you shold change renderRowActions props ** see https://www.material-react-table.com/docs/guides/row-actions
|
|
||||||
enableRowActions={true}
|
|
||||||
renderRowActions={({ row }) => <TableRowActions row={row} />}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</DashboardLayouts>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DashboardTransportationAssistanceComponent;
|
export default DashboardTransportationAssistanceComponent;
|
||||||
|
|||||||
@@ -1,53 +1,53 @@
|
|||||||
import dahsboardImage from "&/images/dashboard.svg";
|
import dahsboardImage from "&/images/dashboard.svg";
|
||||||
import { NextLinkComposed } from "@/core/components/LinkRouting";
|
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
||||||
import StyledImage from "@/core/components/StyledImage";
|
import StyledImage from "@/core/components/StyledImage";
|
||||||
import CenterLayout from "@/layouts/CenterLayout";
|
import CenterLayout from "@/layouts/CenterLayout";
|
||||||
import FullPageLayout from "@/layouts/FullPageLayout";
|
import FullPageLayout from "@/layouts/FullPageLayout";
|
||||||
import useUser from "@/lib/app/hooks/useUser";
|
import useUser from "@/lib/app/hooks/useUser";
|
||||||
import { Button, Typography } from "@mui/material";
|
import {Button, Typography} from "@mui/material";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
|
|
||||||
const FirstComponent = () => {
|
const FirstComponent = () => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const { isAuth } = useUser();
|
const {isAuth} = useUser();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FullPageLayout sx={{ p: 1 }}>
|
<FullPageLayout sx={{p: 1}}>
|
||||||
<CenterLayout spacing={3}>
|
<CenterLayout spacing={3}>
|
||||||
<StyledImage
|
<StyledImage
|
||||||
src={dahsboardImage}
|
src={dahsboardImage}
|
||||||
alt={t("app_name")}
|
alt={t("app_name")}
|
||||||
width={300}
|
width={300}
|
||||||
height={200}
|
height={200}
|
||||||
/>
|
/>
|
||||||
<Typography variant="h5" sx={{ textAlign: "center" }}>
|
<Typography variant="h5" sx={{textAlign: "center"}}>
|
||||||
{t("app_name")}
|
{t("app_name")}
|
||||||
</Typography>
|
</Typography>
|
||||||
{isAuth ? (
|
{isAuth ? (
|
||||||
<Button
|
<Button
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
component={NextLinkComposed}
|
component={NextLinkComposed}
|
||||||
to={{
|
to={{
|
||||||
pathname: "/dashboard",
|
pathname: "/dashboard",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t("dashboard")}
|
{t("dashboard")}
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<Button
|
<Button
|
||||||
sx={{ mx: 2 }}
|
sx={{mx: 2}}
|
||||||
variant="contained"
|
variant="contained"
|
||||||
component={NextLinkComposed}
|
component={NextLinkComposed}
|
||||||
to={{
|
to={{
|
||||||
pathname: "/login-expert",
|
pathname: "/login-expert",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t("login_expert")}
|
{t("login_expert")}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</CenterLayout>
|
</CenterLayout>
|
||||||
</FullPageLayout>
|
</FullPageLayout>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default FirstComponent;
|
export default FirstComponent;
|
||||||
|
|||||||
@@ -2,158 +2,149 @@ import LinkRouting from "@/core/components/LinkRouting";
|
|||||||
// import Notifications from "@/core/components/notifications";
|
// import Notifications from "@/core/components/notifications";
|
||||||
import PasswordField from "@/core/components/PasswordField";
|
import PasswordField from "@/core/components/PasswordField";
|
||||||
import StyledForm from "@/core/components/StyledForm";
|
import StyledForm from "@/core/components/StyledForm";
|
||||||
import { GET_USER_TOKEN } from "@/core/data/apiRoutes";
|
import {GET_USER_TOKEN} from "@/core/data/apiRoutes";
|
||||||
import CenterLayout from "@/layouts/CenterLayout";
|
import CenterLayout from "@/layouts/CenterLayout";
|
||||||
import FullPageLayout from "@/layouts/FullPageLayout";
|
import FullPageLayout from "@/layouts/FullPageLayout";
|
||||||
import useDirection from "@/lib/app/hooks/useDirection";
|
|
||||||
import useUser from "@/lib/app/hooks/useUser";
|
import useUser from "@/lib/app/hooks/useUser";
|
||||||
import LoginIcon from "@mui/icons-material/Login";
|
import LoginIcon from "@mui/icons-material/Login";
|
||||||
import {
|
import {Box, Button, Container, Paper, Stack, TextField, Typography,} from "@mui/material";
|
||||||
Box,
|
|
||||||
Button,
|
|
||||||
Container,
|
|
||||||
Paper,
|
|
||||||
Stack,
|
|
||||||
TextField,
|
|
||||||
Typography,
|
|
||||||
} from "@mui/material";
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { Field, Formik } from "formik";
|
import {Field, Formik} from "formik";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { useSearchParams } from "next/navigation";
|
import {useSearchParams} from "next/navigation";
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
|
|
||||||
const LoginComponent = () => {
|
const LoginComponent = () => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
// const { directionApp } = useDirection(); // should delete because we dont have direction anymore
|
// const { directionApp } = useDirection(); // should delete because we dont have direction anymore
|
||||||
const { setToken } = useUser(); // pass token to set token
|
const {setToken} = useUser(); // pass token to set token
|
||||||
|
|
||||||
// gettin url query
|
// gettin url query
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const backUrlDecodedPath = searchParams.get("back_url");
|
const backUrlDecodedPath = searchParams.get("back_url");
|
||||||
|
|
||||||
//formik properties
|
//formik properties
|
||||||
const handleSubmit = async (values, props) => {
|
const handleSubmit = async (values, props) => {
|
||||||
await axios
|
await axios
|
||||||
.post(GET_USER_TOKEN, {
|
.post(GET_USER_TOKEN, {
|
||||||
username: values.username,
|
username: values.username,
|
||||||
password: values.password,
|
password: values.password,
|
||||||
})
|
})
|
||||||
.then(function (response) {
|
.then(function (response) {
|
||||||
setToken(response.data.token);
|
setToken(response.data.token);
|
||||||
})
|
})
|
||||||
.catch(function (error) {
|
.catch(function (error) {
|
||||||
// Notifications(directionApp, error.response, t);
|
// Notifications(directionApp, error.response, t);
|
||||||
props.setSubmitting(false);
|
props.setSubmitting(false);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
username: "",
|
username: "",
|
||||||
password: "",
|
password: "",
|
||||||
};
|
};
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
username: Yup.string().required(t("LoginPage.error_message_required")),
|
username: Yup.string().required(t("LoginPage.error_message_required")),
|
||||||
password: Yup.string().required(t("LoginPage.error_message_required")),
|
password: Yup.string().required(t("LoginPage.error_message_required")),
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FullPageLayout sx={{ p: 1 }}>
|
<FullPageLayout sx={{p: 1}}>
|
||||||
<CenterLayout>
|
<CenterLayout>
|
||||||
<Container maxWidth="sm">
|
<Container maxWidth="sm">
|
||||||
<Paper elevation={0}>
|
<Paper elevation={0}>
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={initialValues}
|
initialValues={initialValues}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
validationSchema={validationSchema}
|
validationSchema={validationSchema}
|
||||||
>
|
|
||||||
{(props) => (
|
|
||||||
<Stack spacing={2} sx={{ p: 2 }}>
|
|
||||||
<Box
|
|
||||||
sx={{ position: "relative", width: "100%", height: 200 }}
|
|
||||||
>
|
|
||||||
<Image fill src="/images/login.svg" alt={t("app_name")} />
|
|
||||||
</Box>
|
|
||||||
<Typography margin={2} variant="h4" textAlign="center">
|
|
||||||
{t("login_expert")}
|
|
||||||
</Typography>
|
|
||||||
<StyledForm sx={{ width: "100%" }}>
|
|
||||||
<Stack spacing={3} sx={{ p: 2 }}>
|
|
||||||
<Field
|
|
||||||
as={TextField}
|
|
||||||
name="username"
|
|
||||||
variant="outlined"
|
|
||||||
label={t("LoginPage.text_field_user_name")}
|
|
||||||
placeholder={t(
|
|
||||||
"LoginPage.text_field_enter_your_username"
|
|
||||||
)}
|
|
||||||
type={"text"}
|
|
||||||
error={
|
|
||||||
props.touched.username && props.errors.username
|
|
||||||
? true
|
|
||||||
: false
|
|
||||||
}
|
|
||||||
fullWidth
|
|
||||||
helperText={
|
|
||||||
props.touched.username ? props.errors.username : null
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<PasswordField
|
|
||||||
name="password"
|
|
||||||
label={t("LoginPage.text_field_password")}
|
|
||||||
error={
|
|
||||||
props.touched.password && props.errors.password
|
|
||||||
? true
|
|
||||||
: false
|
|
||||||
}
|
|
||||||
helperText={
|
|
||||||
props.touched.password ? props.errors.password : null
|
|
||||||
}
|
|
||||||
placeholder={t(
|
|
||||||
"LoginPage.text_field_enter_your_password"
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
variant="contained"
|
|
||||||
fullWidth
|
|
||||||
size="medium"
|
|
||||||
endIcon={<LoginIcon />}
|
|
||||||
disabled={props.isSubmitting ? true : false}
|
|
||||||
>
|
>
|
||||||
{t("LoginPage.button_submit")}
|
{(props) => (
|
||||||
</Button>
|
<Stack spacing={2} sx={{p: 2}}>
|
||||||
</Box>
|
<Box
|
||||||
</Stack>
|
sx={{position: "relative", width: "100%", height: 200}}
|
||||||
</StyledForm>
|
>
|
||||||
</Stack>
|
<Image fill src="/images/login.svg" alt={t("app_name")}/>
|
||||||
)}
|
</Box>
|
||||||
</Formik>
|
<Typography margin={2} variant="h4" textAlign="center">
|
||||||
</Paper>
|
{t("login_expert")}
|
||||||
</Container>
|
</Typography>
|
||||||
</CenterLayout>
|
<StyledForm sx={{width: "100%"}}>
|
||||||
<Stack direction="row" alignItems="center" justifyContent="center">
|
<Stack spacing={3} sx={{p: 2}}>
|
||||||
<LinkRouting
|
<Field
|
||||||
sx={{ margin: 2 }}
|
as={TextField}
|
||||||
href={
|
name="username"
|
||||||
backUrlDecodedPath ? decodeURIComponent(backUrlDecodedPath) : "/"
|
variant="outlined"
|
||||||
}
|
label={t("LoginPage.text_field_user_name")}
|
||||||
>
|
placeholder={t(
|
||||||
{t("LoginPage.link_routing_back_to")}{" "}
|
"LoginPage.text_field_enter_your_username"
|
||||||
{backUrlDecodedPath
|
)}
|
||||||
? t("LoginPage.link_routing_previuos_page")
|
type={"text"}
|
||||||
: t("LoginPage.link_routing_main_page")}
|
error={
|
||||||
</LinkRouting>
|
props.touched.username && props.errors.username
|
||||||
</Stack>
|
? true
|
||||||
</FullPageLayout>
|
: false
|
||||||
);
|
}
|
||||||
|
fullWidth
|
||||||
|
helperText={
|
||||||
|
props.touched.username ? props.errors.username : null
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<PasswordField
|
||||||
|
name="password"
|
||||||
|
label={t("LoginPage.text_field_password")}
|
||||||
|
error={
|
||||||
|
props.touched.password && props.errors.password
|
||||||
|
? true
|
||||||
|
: false
|
||||||
|
}
|
||||||
|
helperText={
|
||||||
|
props.touched.password ? props.errors.password : null
|
||||||
|
}
|
||||||
|
placeholder={t(
|
||||||
|
"LoginPage.text_field_enter_your_password"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
variant="contained"
|
||||||
|
fullWidth
|
||||||
|
size="medium"
|
||||||
|
endIcon={<LoginIcon/>}
|
||||||
|
disabled={props.isSubmitting ? true : false}
|
||||||
|
>
|
||||||
|
{t("LoginPage.button_submit")}
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Stack>
|
||||||
|
</StyledForm>
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
</Formik>
|
||||||
|
</Paper>
|
||||||
|
</Container>
|
||||||
|
</CenterLayout>
|
||||||
|
<Stack direction="row" alignItems="center" justifyContent="center">
|
||||||
|
<LinkRouting
|
||||||
|
sx={{margin: 2}}
|
||||||
|
href={
|
||||||
|
backUrlDecodedPath ? decodeURIComponent(backUrlDecodedPath) : "/"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{t("LoginPage.link_routing_back_to")}{" "}
|
||||||
|
{backUrlDecodedPath
|
||||||
|
? t("LoginPage.link_routing_previuos_page")
|
||||||
|
: t("LoginPage.link_routing_main_page")}
|
||||||
|
</LinkRouting>
|
||||||
|
</Stack>
|
||||||
|
</FullPageLayout>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LoginComponent;
|
export default LoginComponent;
|
||||||
|
|||||||
@@ -1,128 +1,128 @@
|
|||||||
import { Avatar, Box, TextField } from "@mui/material";
|
import {Avatar, Box, TextField} from "@mui/material";
|
||||||
import { useState } from "react";
|
import {useState} from "react";
|
||||||
import DeleteIcon from "@mui/icons-material/Delete";
|
import DeleteIcon from "@mui/icons-material/Delete";
|
||||||
import AddIcon from "@mui/icons-material/Add";
|
import AddIcon from "@mui/icons-material/Add";
|
||||||
|
|
||||||
const AvatarUpload = ({ user, setFieldValue, valueAvatar, changeFlag }) => {
|
const AvatarUpload = ({user, setFieldValue, valueAvatar, changeFlag}) => {
|
||||||
const [selectedImage, setSelectedImage] = useState(user.expert_avatar);
|
const [selectedImage, setSelectedImage] = useState(user.expert_avatar);
|
||||||
const [isHovered, setIsHovered] = useState(false);
|
const [isHovered, setIsHovered] = useState(false);
|
||||||
|
|
||||||
const handleImageChange = (event) => {
|
const handleImageChange = (event) => {
|
||||||
const newImage = event.target?.files?.[0];
|
const newImage = event.target?.files?.[0];
|
||||||
if (newImage) {
|
if (newImage) {
|
||||||
setSelectedImage(URL.createObjectURL(newImage));
|
setSelectedImage(URL.createObjectURL(newImage));
|
||||||
setFieldValue(valueAvatar, newImage);
|
setFieldValue(valueAvatar, newImage);
|
||||||
setFieldValue(changeFlag, true);
|
setFieldValue(changeFlag, true);
|
||||||
} else {
|
} else {
|
||||||
setSelectedImage("");
|
setSelectedImage("");
|
||||||
setFieldValue(valueAvatar, null);
|
setFieldValue(valueAvatar, null);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDeleteImage = () => {
|
const handleDeleteImage = () => {
|
||||||
setSelectedImage("");
|
setSelectedImage("");
|
||||||
setFieldValue(valueAvatar, null);
|
setFieldValue(valueAvatar, null);
|
||||||
setFieldValue(changeFlag, true);
|
setFieldValue(changeFlag, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMouseEnter = () => {
|
const handleMouseEnter = () => {
|
||||||
setIsHovered(true);
|
setIsHovered(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMouseLeave = () => {
|
const handleMouseLeave = () => {
|
||||||
setIsHovered(false);
|
setIsHovered(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "inline-block",
|
|
||||||
position: "relative",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
component="label"
|
|
||||||
htmlFor="avatar-upload"
|
|
||||||
sx={{
|
|
||||||
display: "inline-block",
|
|
||||||
width: "fit-content",
|
|
||||||
height: "fit-content",
|
|
||||||
cursor: "pointer",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
<Box
|
||||||
component="div"
|
|
||||||
className={`avatar-container ${isHovered ? "hovered" : ""}`}
|
|
||||||
onMouseEnter={handleMouseEnter}
|
|
||||||
onMouseLeave={handleMouseLeave}
|
|
||||||
sx={{
|
|
||||||
position: "relative",
|
|
||||||
width: 150,
|
|
||||||
height: 150,
|
|
||||||
borderRadius: "50%",
|
|
||||||
overflow: "hidden",
|
|
||||||
transition: "transform 0.3s ease-in-out",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Avatar
|
|
||||||
alt="User Avatar"
|
|
||||||
src={selectedImage}
|
|
||||||
sx={{
|
sx={{
|
||||||
width: 150,
|
display: "inline-block",
|
||||||
height: 150,
|
position: "relative",
|
||||||
cursor: "pointer",
|
|
||||||
position: "relative",
|
|
||||||
}}
|
}}
|
||||||
/>
|
>
|
||||||
{isHovered && (
|
|
||||||
<Box
|
<Box
|
||||||
component="div"
|
component="label"
|
||||||
className="avatar-overlay"
|
htmlFor="avatar-upload"
|
||||||
sx={{
|
sx={{
|
||||||
position: "absolute",
|
display: "inline-block",
|
||||||
top: 0,
|
width: "fit-content",
|
||||||
left: 0,
|
height: "fit-content",
|
||||||
width: "100%",
|
cursor: "pointer",
|
||||||
height: "100%",
|
}}
|
||||||
backgroundColor: "rgba(0, 0, 0, 0.6)",
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
transition: "transform 0.3s ease-in-out",
|
|
||||||
transform: `scale(${isHovered ? 1 : 0})`,
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{selectedImage ? (
|
<Box
|
||||||
<DeleteIcon
|
component="div"
|
||||||
sx={{
|
className={`avatar-container ${isHovered ? "hovered" : ""}`}
|
||||||
color: "#fff",
|
onMouseEnter={handleMouseEnter}
|
||||||
width: 35,
|
onMouseLeave={handleMouseLeave}
|
||||||
height: 35,
|
sx={{
|
||||||
}}
|
position: "relative",
|
||||||
onClick={handleDeleteImage}
|
width: 150,
|
||||||
/>
|
height: 150,
|
||||||
) : (
|
borderRadius: "50%",
|
||||||
<AddIcon
|
overflow: "hidden",
|
||||||
sx={{
|
transition: "transform 0.3s ease-in-out",
|
||||||
color: "#fff",
|
}}
|
||||||
width: 35,
|
>
|
||||||
height: 35,
|
<Avatar
|
||||||
}}
|
alt="User Avatar"
|
||||||
/>
|
src={selectedImage}
|
||||||
)}
|
sx={{
|
||||||
|
width: 150,
|
||||||
|
height: 150,
|
||||||
|
cursor: "pointer",
|
||||||
|
position: "relative",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{isHovered && (
|
||||||
|
<Box
|
||||||
|
component="div"
|
||||||
|
className="avatar-overlay"
|
||||||
|
sx={{
|
||||||
|
position: "absolute",
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
backgroundColor: "rgba(0, 0, 0, 0.6)",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
transition: "transform 0.3s ease-in-out",
|
||||||
|
transform: `scale(${isHovered ? 1 : 0})`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{selectedImage ? (
|
||||||
|
<DeleteIcon
|
||||||
|
sx={{
|
||||||
|
color: "#fff",
|
||||||
|
width: 35,
|
||||||
|
height: 35,
|
||||||
|
}}
|
||||||
|
onClick={handleDeleteImage}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<AddIcon
|
||||||
|
sx={{
|
||||||
|
color: "#fff",
|
||||||
|
width: 35,
|
||||||
|
height: 35,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
<TextField
|
||||||
|
id="avatar-upload"
|
||||||
|
type="file"
|
||||||
|
accept="image/*"
|
||||||
|
sx={{display: "none"}}
|
||||||
|
onChange={handleImageChange}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
);
|
||||||
<TextField
|
|
||||||
id="avatar-upload"
|
|
||||||
type="file"
|
|
||||||
accept="image/*"
|
|
||||||
sx={{ display: "none" }}
|
|
||||||
onChange={handleImageChange}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default AvatarUpload;
|
export default AvatarUpload;
|
||||||
|
|||||||
@@ -1,174 +1,174 @@
|
|||||||
import { ReloadDataTableContext } from "@/lib/app/contexts/ReloadDatatableContext";
|
import {ReloadDataTableContext} from "@/lib/app/contexts/ReloadDatatableContext";
|
||||||
import useLanguage from "@/lib/app/hooks/useLanguage";
|
import useLanguage from "@/lib/app/hooks/useLanguage";
|
||||||
import { Typography } from "@mui/material";
|
import {Typography} from "@mui/material";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import MaterialReactTable from "material-react-table";
|
import MaterialReactTable from "material-react-table";
|
||||||
import moment from "moment-jalaali";
|
import moment from "moment-jalaali";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import { useContext, useEffect, useMemo, useState } from "react";
|
import {useContext, useEffect, useMemo, useState} from "react";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
|
||||||
const DataTable = (props) => {
|
const DataTable = (props) => {
|
||||||
const { reloadDataTable, setReloadDataTable } = useContext(
|
const {reloadDataTable, setReloadDataTable} = useContext(
|
||||||
ReloadDataTableContext
|
ReloadDataTableContext
|
||||||
);
|
|
||||||
|
|
||||||
const fetcher = (...args) => {
|
|
||||||
return axios
|
|
||||||
.get(args, {
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${props.token}`,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then((res) => {
|
|
||||||
setRowCount(res.data.meta.totalRowCount);
|
|
||||||
return res.data.data;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
const t = useTranslations();
|
|
||||||
const { languageApp, languageList } = useLanguage();
|
|
||||||
const [columnFilters, setColumnFilters] = useState([]);
|
|
||||||
const [columnFilterFns, setColumnFilterFns] = useState(() => {
|
|
||||||
let output = {};
|
|
||||||
const list = props.columns.map((item) =>
|
|
||||||
item.enableColumnFilter ? { [item.id]: item.filterFn } : { [item.id]: "" }
|
|
||||||
);
|
);
|
||||||
for (var key in list) {
|
|
||||||
var nestedObj = list[key];
|
|
||||||
for (var nestedKey in nestedObj) {
|
|
||||||
output[nestedKey] = nestedObj[nestedKey];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
});
|
|
||||||
const [sorting, setSorting] = useState([]);
|
|
||||||
const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 });
|
|
||||||
const [rowCount, setRowCount] = useState(0);
|
|
||||||
const [updateTime, setupdateTime] = useState(
|
|
||||||
moment().format("HH:mm | jYYYY/jM/jD")
|
|
||||||
);
|
|
||||||
|
|
||||||
const tableLocalization = useMemo(
|
const fetcher = (...args) => {
|
||||||
() =>
|
return axios
|
||||||
languageList.find((item) => item.key == languageApp).tableLocalization,
|
.get(args, {
|
||||||
[languageApp, languageList]
|
headers: {
|
||||||
);
|
Authorization: `Bearer ${props.token}`,
|
||||||
|
},
|
||||||
const fetchUrl = useMemo(() => {
|
})
|
||||||
const url = new URL(props.tableUrl /* send your api */);
|
.then((res) => {
|
||||||
url.searchParams.set(
|
setRowCount(res.data.meta.totalRowCount);
|
||||||
"start",
|
return res.data.data;
|
||||||
`${pagination.pageIndex * pagination.pageSize}`
|
});
|
||||||
);
|
};
|
||||||
const filters = columnFilters.map((filter) => {
|
const t = useTranslations();
|
||||||
let datatype;
|
const {languageApp, languageList} = useLanguage();
|
||||||
for (const i in props.columns) {
|
const [columnFilters, setColumnFilters] = useState([]);
|
||||||
if (props.columns[i].id == filter.id) {
|
const [columnFilterFns, setColumnFilterFns] = useState(() => {
|
||||||
datatype = props.columns[i].datatype;
|
let output = {};
|
||||||
|
const list = props.columns.map((item) =>
|
||||||
|
item.enableColumnFilter ? {[item.id]: item.filterFn} : {[item.id]: ""}
|
||||||
|
);
|
||||||
|
for (var key in list) {
|
||||||
|
var nestedObj = list[key];
|
||||||
|
for (var nestedKey in nestedObj) {
|
||||||
|
output[nestedKey] = nestedObj[nestedKey];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
return output;
|
||||||
return {
|
|
||||||
...filter,
|
|
||||||
fn: columnFilterFns[filter.id],
|
|
||||||
datatype: datatype,
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
url.searchParams.set("size", pagination.pageSize);
|
const [sorting, setSorting] = useState([]);
|
||||||
url.searchParams.set("filters", JSON.stringify(filters ?? []));
|
const [pagination, setPagination] = useState({pageIndex: 0, pageSize: 10});
|
||||||
url.searchParams.set("sorting", JSON.stringify(sorting ?? []));
|
const [rowCount, setRowCount] = useState(0);
|
||||||
return url;
|
const [updateTime, setupdateTime] = useState(
|
||||||
}, [
|
moment().format("HH:mm | jYYYY/jM/jD")
|
||||||
props.tableUrl,
|
);
|
||||||
columnFilters,
|
|
||||||
columnFilterFns,
|
|
||||||
pagination,
|
|
||||||
sorting,
|
|
||||||
props.columns,
|
|
||||||
]);
|
|
||||||
const { data, isLoading, isValidating, mutate } = useSWR(fetchUrl, fetcher, {
|
|
||||||
revalidateOnFocus: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
const tableLocalization = useMemo(
|
||||||
if (reloadDataTable) {
|
() =>
|
||||||
mutate(fetchUrl).then(() => {
|
languageList.find((item) => item.key == languageApp).tableLocalization,
|
||||||
setReloadDataTable(false); // Set reloadDataTable to false after mutation is complete
|
[languageApp, languageList]
|
||||||
});
|
);
|
||||||
}
|
|
||||||
}, [reloadDataTable, setReloadDataTable]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
const fetchUrl = useMemo(() => {
|
||||||
setupdateTime(moment().format("HH:mm | jYYYY/jM/jD"));
|
const url = new URL(props.tableUrl /* send your api */);
|
||||||
}, [isValidating, languageApp]);
|
url.searchParams.set(
|
||||||
|
"start",
|
||||||
return (
|
`${pagination.pageIndex * pagination.pageSize}`
|
||||||
<MaterialReactTable
|
);
|
||||||
localization={tableLocalization}
|
const filters = columnFilters.map((filter) => {
|
||||||
columns={props.columns} /* columns you send */
|
let datatype;
|
||||||
data={data ?? []}
|
for (const i in props.columns) {
|
||||||
manualFiltering
|
if (props.columns[i].id == filter.id) {
|
||||||
manualPagination
|
datatype = props.columns[i].datatype;
|
||||||
manualSorting
|
}
|
||||||
enableRowSelection={props.selectableRow} /* send condition */
|
}
|
||||||
enablePinning={props.enablePinning} /* send condition */
|
return {
|
||||||
enableColumnFilters={props.enableColumnFilters} /* send condition */
|
...filter,
|
||||||
enableDensityToggle={props.enableDensityToggle} /* send condition */
|
fn: columnFilterFns[filter.id],
|
||||||
enableHiding={props.enableHiding} /* send condition */
|
datatype: datatype,
|
||||||
enableFullScreenToggle={props.enableFullScreenToggle} /* send condition */
|
};
|
||||||
enableColumnResizing={props.enableColumnResizing}
|
});
|
||||||
muiTableHeadCellProps={{
|
url.searchParams.set("size", pagination.pageSize);
|
||||||
sx: {
|
url.searchParams.set("filters", JSON.stringify(filters ?? []));
|
||||||
color: "primary.main",
|
url.searchParams.set("sorting", JSON.stringify(sorting ?? []));
|
||||||
"& .Mui-TableHeadCell-Content": { justifyContent: "space-between" },
|
return url;
|
||||||
},
|
}, [
|
||||||
}}
|
props.tableUrl,
|
||||||
enableColumnFilterModes
|
|
||||||
muiTablePaperProps={{ elevation: 0 }}
|
|
||||||
rowCount={rowCount}
|
|
||||||
onColumnFilterFnsChange={setColumnFilterFns}
|
|
||||||
onColumnFiltersChange={setColumnFilters}
|
|
||||||
onPaginationChange={setPagination}
|
|
||||||
onSortingChange={setSorting}
|
|
||||||
positionToolbarAlertBanner="bottom"
|
|
||||||
renderTopToolbarCustomActions={({ table }) => (
|
|
||||||
<>
|
|
||||||
{props.enableCustomToolbar /* send condition */
|
|
||||||
? props.CustomToolbar /* send component */
|
|
||||||
: ""}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
renderBottomToolbarCustomActions={({ table }) => (
|
|
||||||
<>
|
|
||||||
{props.enableLastUpdate /* send condition */ ? (
|
|
||||||
<Typography
|
|
||||||
sx={{
|
|
||||||
color: "primary.main",
|
|
||||||
alignSelf: "center",
|
|
||||||
whiteSpace: "nowrap",
|
|
||||||
maxWidth: { xs: 100, sm: "100%" },
|
|
||||||
overflowX: "scroll",
|
|
||||||
}}
|
|
||||||
variant="caption"
|
|
||||||
>
|
|
||||||
{t("last_updated_at")}: {updateTime}
|
|
||||||
</Typography>
|
|
||||||
) : (
|
|
||||||
""
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
state={{
|
|
||||||
isLoading,
|
|
||||||
columnFilters,
|
columnFilters,
|
||||||
columnFilterFns,
|
columnFilterFns,
|
||||||
pagination,
|
pagination,
|
||||||
sorting,
|
sorting,
|
||||||
}}
|
props.columns,
|
||||||
positionActionsColumn={"last"}
|
]);
|
||||||
enableRowActions={props.enableRowActions}
|
const {data, isLoading, isValidating, mutate} = useSWR(fetchUrl, fetcher, {
|
||||||
{...props}
|
revalidateOnFocus: false,
|
||||||
/>
|
});
|
||||||
);
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (reloadDataTable) {
|
||||||
|
mutate(fetchUrl).then(() => {
|
||||||
|
setReloadDataTable(false); // Set reloadDataTable to false after mutation is complete
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [reloadDataTable, setReloadDataTable]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setupdateTime(moment().format("HH:mm | jYYYY/jM/jD"));
|
||||||
|
}, [isValidating, languageApp]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MaterialReactTable
|
||||||
|
localization={tableLocalization}
|
||||||
|
columns={props.columns} /* columns you send */
|
||||||
|
data={data ?? []}
|
||||||
|
manualFiltering
|
||||||
|
manualPagination
|
||||||
|
manualSorting
|
||||||
|
enableRowSelection={props.selectableRow} /* send condition */
|
||||||
|
enablePinning={props.enablePinning} /* send condition */
|
||||||
|
enableColumnFilters={props.enableColumnFilters} /* send condition */
|
||||||
|
enableDensityToggle={props.enableDensityToggle} /* send condition */
|
||||||
|
enableHiding={props.enableHiding} /* send condition */
|
||||||
|
enableFullScreenToggle={props.enableFullScreenToggle} /* send condition */
|
||||||
|
enableColumnResizing={props.enableColumnResizing}
|
||||||
|
muiTableHeadCellProps={{
|
||||||
|
sx: {
|
||||||
|
color: "primary.main",
|
||||||
|
"& .Mui-TableHeadCell-Content": {justifyContent: "space-between"},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
enableColumnFilterModes
|
||||||
|
muiTablePaperProps={{elevation: 0}}
|
||||||
|
rowCount={rowCount}
|
||||||
|
onColumnFilterFnsChange={setColumnFilterFns}
|
||||||
|
onColumnFiltersChange={setColumnFilters}
|
||||||
|
onPaginationChange={setPagination}
|
||||||
|
onSortingChange={setSorting}
|
||||||
|
positionToolbarAlertBanner="bottom"
|
||||||
|
renderTopToolbarCustomActions={({table}) => (
|
||||||
|
<>
|
||||||
|
{props.enableCustomToolbar /* send condition */
|
||||||
|
? props.CustomToolbar /* send component */
|
||||||
|
: ""}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
renderBottomToolbarCustomActions={({table}) => (
|
||||||
|
<>
|
||||||
|
{props.enableLastUpdate /* send condition */ ? (
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
color: "primary.main",
|
||||||
|
alignSelf: "center",
|
||||||
|
whiteSpace: "nowrap",
|
||||||
|
maxWidth: {xs: 100, sm: "100%"},
|
||||||
|
overflowX: "scroll",
|
||||||
|
}}
|
||||||
|
variant="caption"
|
||||||
|
>
|
||||||
|
{t("last_updated_at")}: {updateTime}
|
||||||
|
</Typography>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
state={{
|
||||||
|
isLoading,
|
||||||
|
columnFilters,
|
||||||
|
columnFilterFns,
|
||||||
|
pagination,
|
||||||
|
sorting,
|
||||||
|
}}
|
||||||
|
positionActionsColumn={"last"}
|
||||||
|
enableRowActions={props.enableRowActions}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DataTable;
|
export default DataTable;
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import { DataTableProvider } from "@/lib/app/contexts/DatatableContext";
|
import {DataTableProvider} from "@/lib/app/contexts/DatatableContext";
|
||||||
import DataTable from "./Datatable";
|
import DataTable from "./Datatable";
|
||||||
import { ReloadDataTableProvider } from "@/lib/app/contexts/ReloadDatatableContext";
|
import {ReloadDataTableProvider} from "@/lib/app/contexts/ReloadDatatableContext";
|
||||||
|
|
||||||
function DataTableStructure(props) {
|
function DataTableStructure(props) {
|
||||||
return (
|
return (
|
||||||
<ReloadDataTableProvider>
|
<ReloadDataTableProvider>
|
||||||
<DataTableProvider>
|
<DataTableProvider>
|
||||||
<DataTable {...props} token={localStorage.getItem("_token")} />
|
<DataTable {...props} token={localStorage.getItem("_token")}/>
|
||||||
</DataTableProvider>
|
</DataTableProvider>
|
||||||
</ReloadDataTableProvider>
|
</ReloadDataTableProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DataTableStructure;
|
export default DataTableStructure;
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import { Typography } from "@mui/material";
|
import {Typography} from "@mui/material";
|
||||||
|
|
||||||
const FormErrorMessage = (props) => {
|
const FormErrorMessage = (props) => {
|
||||||
return (
|
return (
|
||||||
<Typography variant="body2" color="error">
|
<Typography variant="body2" color="error">
|
||||||
{props.children}
|
{props.children}
|
||||||
</Typography>
|
</Typography>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default FormErrorMessage;
|
export default FormErrorMessage;
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
import ImageResize from "image-resize";
|
import ImageResize from "image-resize";
|
||||||
|
|
||||||
const ImageResizer = async (image) => {
|
const ImageResizer = async (image) => {
|
||||||
const imageResize = new ImageResize({
|
const imageResize = new ImageResize({
|
||||||
quality: 1,
|
quality: 1,
|
||||||
format: "jpg",
|
format: "jpg",
|
||||||
outputType: "base64",
|
outputType: "base64",
|
||||||
width: 400,
|
width: 400,
|
||||||
});
|
});
|
||||||
|
|
||||||
const get = await imageResize.get(image);
|
const get = await imageResize.get(image);
|
||||||
const resize = await imageResize.resize(get).then();
|
const resize = await imageResize.resize(get).then();
|
||||||
const output = await imageResize.output(resize).then();
|
const output = await imageResize.output(resize).then();
|
||||||
|
|
||||||
const avatar = await (await import("image-to-file-converter"))
|
const avatar = await (await import("image-to-file-converter"))
|
||||||
.base64ToFile(output)
|
.base64ToFile(output)
|
||||||
.then();
|
.then();
|
||||||
|
|
||||||
return avatar;
|
return avatar;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ImageResizer;
|
export default ImageResizer;
|
||||||
|
|||||||
@@ -1,116 +1,116 @@
|
|||||||
import MuiLink from "@mui/material/Link";
|
import MuiLink from "@mui/material/Link";
|
||||||
import { styled } from "@mui/material/styles";
|
import {styled} from "@mui/material/styles";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import NextLink from "next/link";
|
import NextLink from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import {useRouter} from "next/router";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
|
||||||
// Add support for the sx prop for consistency with the other branches.
|
// Add support for the sx prop for consistency with the other branches.
|
||||||
const Anchor = styled("a")({});
|
const Anchor = styled("a")({});
|
||||||
|
|
||||||
export const NextLinkComposed = React.forwardRef(function NextLinkComposed(
|
export const NextLinkComposed = React.forwardRef(function NextLinkComposed(
|
||||||
props,
|
props,
|
||||||
ref
|
ref
|
||||||
) {
|
) {
|
||||||
const {
|
const {
|
||||||
to,
|
to,
|
||||||
linkAs,
|
linkAs,
|
||||||
replace,
|
replace,
|
||||||
scroll,
|
scroll,
|
||||||
shallow,
|
shallow,
|
||||||
prefetch,
|
prefetch,
|
||||||
legacyBehavior = true,
|
legacyBehavior = true,
|
||||||
locale,
|
locale,
|
||||||
...other
|
...other
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NextLink
|
<NextLink
|
||||||
href={to}
|
href={to}
|
||||||
prefetch={prefetch}
|
prefetch={prefetch}
|
||||||
as={linkAs}
|
as={linkAs}
|
||||||
replace={replace}
|
replace={replace}
|
||||||
scroll={scroll}
|
scroll={scroll}
|
||||||
shallow={shallow}
|
shallow={shallow}
|
||||||
passHref
|
passHref
|
||||||
locale={locale}
|
locale={locale}
|
||||||
legacyBehavior={legacyBehavior}
|
legacyBehavior={legacyBehavior}
|
||||||
>
|
>
|
||||||
<Anchor ref={ref} {...other} />
|
<Anchor ref={ref} {...other} />
|
||||||
</NextLink>
|
</NextLink>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// A styled version of the Next.js Link component:
|
// A styled version of the Next.js Link component:
|
||||||
// https://nextjs.org/docs/api-reference/next/link
|
// https://nextjs.org/docs/api-reference/next/link
|
||||||
const LinkRouting = React.forwardRef(function Link(props, ref) {
|
const LinkRouting = React.forwardRef(function Link(props, ref) {
|
||||||
const {
|
const {
|
||||||
activeClassName = "active",
|
activeClassName = "active",
|
||||||
as,
|
as,
|
||||||
className: classNameProps,
|
className: classNameProps,
|
||||||
href,
|
href,
|
||||||
legacyBehavior,
|
legacyBehavior,
|
||||||
linkAs: linkAsProp,
|
linkAs: linkAsProp,
|
||||||
locale,
|
locale,
|
||||||
noLinkStyle,
|
noLinkStyle,
|
||||||
prefetch,
|
prefetch,
|
||||||
replace,
|
replace,
|
||||||
role, // Link don't have roles.
|
role, // Link don't have roles.
|
||||||
scroll,
|
scroll,
|
||||||
shallow,
|
shallow,
|
||||||
...other
|
...other
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const pathname = typeof href === "string" ? href : href.pathname;
|
const pathname = typeof href === "string" ? href : href.pathname;
|
||||||
const className = clsx(classNameProps, {
|
const className = clsx(classNameProps, {
|
||||||
[activeClassName]: router.pathname === pathname && activeClassName,
|
[activeClassName]: router.pathname === pathname && activeClassName,
|
||||||
});
|
});
|
||||||
|
|
||||||
const isExternal =
|
const isExternal =
|
||||||
typeof href === "string" &&
|
typeof href === "string" &&
|
||||||
(href.indexOf("http") === 0 || href.indexOf("mailto:") === 0);
|
(href.indexOf("http") === 0 || href.indexOf("mailto:") === 0);
|
||||||
|
|
||||||
if (isExternal) {
|
if (isExternal) {
|
||||||
if (noLinkStyle) {
|
if (noLinkStyle) {
|
||||||
return <Anchor className={className} href={href} ref={ref} {...other} />;
|
return <Anchor className={className} href={href} ref={ref} {...other} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <MuiLink className={className} href={href} ref={ref} {...other} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <MuiLink className={className} href={href} ref={ref} {...other} />;
|
const linkAs = linkAsProp || as;
|
||||||
}
|
const nextjsProps = {
|
||||||
|
to: href,
|
||||||
|
linkAs,
|
||||||
|
replace,
|
||||||
|
scroll,
|
||||||
|
shallow,
|
||||||
|
prefetch,
|
||||||
|
legacyBehavior,
|
||||||
|
locale,
|
||||||
|
};
|
||||||
|
|
||||||
const linkAs = linkAsProp || as;
|
if (noLinkStyle) {
|
||||||
const nextjsProps = {
|
return (
|
||||||
to: href,
|
<NextLinkComposed
|
||||||
linkAs,
|
className={className}
|
||||||
replace,
|
ref={ref}
|
||||||
scroll,
|
{...nextjsProps}
|
||||||
shallow,
|
{...other}
|
||||||
prefetch,
|
/>
|
||||||
legacyBehavior,
|
);
|
||||||
locale,
|
}
|
||||||
};
|
|
||||||
|
|
||||||
if (noLinkStyle) {
|
|
||||||
return (
|
return (
|
||||||
<NextLinkComposed
|
<MuiLink
|
||||||
className={className}
|
component={NextLinkComposed}
|
||||||
ref={ref}
|
className={className}
|
||||||
{...nextjsProps}
|
ref={ref}
|
||||||
{...other}
|
{...nextjsProps}
|
||||||
/>
|
{...other}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<MuiLink
|
|
||||||
component={NextLinkComposed}
|
|
||||||
className={className}
|
|
||||||
ref={ref}
|
|
||||||
{...nextjsProps}
|
|
||||||
{...other}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default LinkRouting;
|
export default LinkRouting;
|
||||||
|
|||||||
@@ -1,44 +1,44 @@
|
|||||||
import { Backdrop, Fade, styled } from "@mui/material";
|
import {Backdrop, Fade, styled} from "@mui/material";
|
||||||
import StyledImage from "./StyledImage";
|
import StyledImage from "./StyledImage";
|
||||||
|
|
||||||
const LoadingImage = styled(StyledImage)({
|
const LoadingImage = styled(StyledImage)({
|
||||||
"@keyframes load": {
|
"@keyframes load": {
|
||||||
"0%": {
|
"0%": {
|
||||||
// opacity: 0,
|
// opacity: 0,
|
||||||
transform: "scale(1)",
|
transform: "scale(1)",
|
||||||
|
},
|
||||||
|
"50%": {
|
||||||
|
// opacity: 1,
|
||||||
|
transform: "scale(2)",
|
||||||
|
},
|
||||||
|
"100%": {
|
||||||
|
// opacity: 0,
|
||||||
|
transform: "scale(1)",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"50%": {
|
animation: "load 2s infinite",
|
||||||
// opacity: 1,
|
|
||||||
transform: "scale(2)",
|
|
||||||
},
|
|
||||||
"100%": {
|
|
||||||
// opacity: 0,
|
|
||||||
transform: "scale(1)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
animation: "load 2s infinite",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const LoadingHardPage = ({ children, loading }) => {
|
const LoadingHardPage = ({children, loading}) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Backdrop
|
<Backdrop
|
||||||
sx={{ bgcolor: "#fff", zIndex: (theme) => theme.zIndex.drawer + 1 }}
|
sx={{bgcolor: "#fff", zIndex: (theme) => theme.zIndex.drawer + 1}}
|
||||||
open={loading}
|
open={loading}
|
||||||
>
|
>
|
||||||
<Fade in={true}>
|
<Fade in={true}>
|
||||||
<LoadingImage
|
<LoadingImage
|
||||||
src={"/images/loading_logo.svg"}
|
src={"/images/loading_logo.svg"}
|
||||||
alt="loading marhaba"
|
alt="loading marhaba"
|
||||||
priority
|
priority
|
||||||
width={100}
|
width={100}
|
||||||
height={100}
|
height={100}
|
||||||
/>
|
/>
|
||||||
</Fade>
|
</Fade>
|
||||||
</Backdrop>
|
</Backdrop>
|
||||||
{children}
|
{children}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LoadingHardPage;
|
export default LoadingHardPage;
|
||||||
|
|||||||
@@ -2,21 +2,21 @@ import CenterLayout from "@/layouts/CenterLayout";
|
|||||||
import FullPageLayout from "@/layouts/FullPageLayout";
|
import FullPageLayout from "@/layouts/FullPageLayout";
|
||||||
import StyledImage from "./StyledImage";
|
import StyledImage from "./StyledImage";
|
||||||
|
|
||||||
const Message = ({ text, actions }) => {
|
const Message = ({text, actions}) => {
|
||||||
return (
|
return (
|
||||||
<FullPageLayout sx={{ p: 1 }}>
|
<FullPageLayout sx={{p: 1}}>
|
||||||
<CenterLayout spacing={3}>
|
<CenterLayout spacing={3}>
|
||||||
<StyledImage
|
<StyledImage
|
||||||
src={"/images/loading_logo.svg"}
|
src={"/images/loading_logo.svg"}
|
||||||
alt="loading loan facilities"
|
alt="loading loan facilities"
|
||||||
width={100}
|
width={100}
|
||||||
height={100}
|
height={100}
|
||||||
/>
|
/>
|
||||||
{text}
|
{text}
|
||||||
{actions}
|
{actions}
|
||||||
</CenterLayout>
|
</CenterLayout>
|
||||||
</FullPageLayout>
|
</FullPageLayout>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Message;
|
export default Message;
|
||||||
|
|||||||
@@ -1,35 +1,35 @@
|
|||||||
import { LocalizationProvider, DatePicker } from "@mui/x-date-pickers";
|
import {DatePicker, LocalizationProvider} from "@mui/x-date-pickers";
|
||||||
import { AdapterDateFnsJalali } from "@mui/x-date-pickers/AdapterDateFnsJalali";
|
import {AdapterDateFnsJalali} from "@mui/x-date-pickers/AdapterDateFnsJalali";
|
||||||
import moment from "jalali-moment";
|
import moment from "jalali-moment";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
|
|
||||||
export default function MuiDatePicker({
|
export default function MuiDatePicker({
|
||||||
setFieldValue,
|
setFieldValue,
|
||||||
selectType,
|
selectType,
|
||||||
error,
|
error,
|
||||||
helperText,
|
helperText,
|
||||||
}) {
|
}) {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
|
|
||||||
const handleDateChange = (date) => {
|
const handleDateChange = (date) => {
|
||||||
const selectedDate = moment(date).locale("fa"); // should add .format() at the end to format the data
|
const selectedDate = moment(date).locale("fa"); // should add .format() at the end to format the data
|
||||||
setFieldValue(selectType, selectedDate);
|
setFieldValue(selectType, selectedDate);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LocalizationProvider dateAdapter={AdapterDateFnsJalali}>
|
<LocalizationProvider dateAdapter={AdapterDateFnsJalali}>
|
||||||
<DatePicker
|
<DatePicker
|
||||||
sx={{ width: "100%" }}
|
sx={{width: "100%"}}
|
||||||
label={t("MuiDatePicker.date_picker_birthday")}
|
label={t("MuiDatePicker.date_picker_birthday")}
|
||||||
slotProps={{
|
slotProps={{
|
||||||
textField: {
|
textField: {
|
||||||
size: "small",
|
size: "small",
|
||||||
helperText: helperText ? `${helperText}` : "YYYY-MM-DD",
|
helperText: helperText ? `${helperText}` : "YYYY-MM-DD",
|
||||||
error: error ? true : false,
|
error: error ? true : false,
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
onChange={handleDateChange}
|
onChange={handleDateChange}
|
||||||
/>
|
/>
|
||||||
</LocalizationProvider>
|
</LocalizationProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +1,33 @@
|
|||||||
import { useState } from "react";
|
import {useState} from "react";
|
||||||
import { IconButton, InputAdornment, TextField } from "@mui/material";
|
import {IconButton, InputAdornment, TextField} from "@mui/material";
|
||||||
import { Visibility, VisibilityOff } from "@mui/icons-material";
|
import {Visibility, VisibilityOff} from "@mui/icons-material";
|
||||||
import { Field } from "formik";
|
import {Field} from "formik";
|
||||||
|
|
||||||
const PasswordField = (props) => {
|
const PasswordField = (props) => {
|
||||||
const [showPassword, setShowPassword] = useState(false);
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
|
|
||||||
const handleClickShowPassword = () => {
|
const handleClickShowPassword = () => {
|
||||||
setShowPassword(!showPassword);
|
setShowPassword(!showPassword);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Field
|
<Field
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
fullWidth
|
fullWidth
|
||||||
as={TextField}
|
as={TextField}
|
||||||
{...props}
|
{...props}
|
||||||
type={showPassword ? "text" : "password"}
|
type={showPassword ? "text" : "password"}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
endAdornment: (
|
endAdornment: (
|
||||||
<InputAdornment position="end">
|
<InputAdornment position="end">
|
||||||
<IconButton onClick={handleClickShowPassword}>
|
<IconButton onClick={handleClickShowPassword}>
|
||||||
{showPassword ? <Visibility /> : <VisibilityOff />}
|
{showPassword ? <Visibility/> : <VisibilityOff/>}
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</InputAdornment>
|
</InputAdornment>
|
||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default PasswordField;
|
export default PasswordField;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { styled } from "@mui/material";
|
import {styled} from "@mui/material";
|
||||||
import { Form } from "formik";
|
import {Form} from "formik";
|
||||||
|
|
||||||
const StyledForm = styled(Form)``;
|
const StyledForm = styled(Form)``;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { styled } from "@mui/material";
|
import {styled} from "@mui/material";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
|
|
||||||
const StyledImage = styled(Image)``;
|
const StyledImage = styled(Image)``;
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
|
|
||||||
const TitlePage = ({ text }) => {
|
const TitlePage = ({text}) => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
return (
|
return (
|
||||||
<Head>
|
<Head>
|
||||||
<title>
|
<title>
|
||||||
{text ? `${t("app_short_name")} | ${t(text)}` : t("app_short_name")}
|
{text ? `${t("app_short_name")} | ${t(text)}` : t("app_short_name")}
|
||||||
</title>
|
</title>
|
||||||
</Head>
|
</Head>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TitlePage;
|
export default TitlePage;
|
||||||
|
|||||||
@@ -1,176 +1,175 @@
|
|||||||
import { Box, Button, Paper, Typography } from "@mui/material";
|
import {Box, Button, Paper, Typography} from "@mui/material";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import Image from "next/image";
|
|
||||||
import AddIcon from "@mui/icons-material/Add";
|
import AddIcon from "@mui/icons-material/Add";
|
||||||
import DeleteForeverIcon from "@mui/icons-material/DeleteForever";
|
import DeleteForeverIcon from "@mui/icons-material/DeleteForever";
|
||||||
import { useRef } from "react";
|
import {useRef} from "react";
|
||||||
|
|
||||||
const UploadSystem = ({
|
const UploadSystem = ({
|
||||||
selectedImage,
|
selectedImage,
|
||||||
setselectedImage,
|
setselectedImage,
|
||||||
handleUploadChange,
|
handleUploadChange,
|
||||||
fieldname,
|
fieldname,
|
||||||
setFieldValue,
|
setFieldValue,
|
||||||
imageAlt,
|
imageAlt,
|
||||||
imageSize,
|
imageSize,
|
||||||
fileType,
|
fileType,
|
||||||
fileName,
|
fileName,
|
||||||
setShowAddIcon,
|
setShowAddIcon,
|
||||||
showAddIcon,
|
showAddIcon,
|
||||||
}) => {
|
}) => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const fileInputRef = useRef(null);
|
const fileInputRef = useRef(null);
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
fileInputRef.current.click();
|
fileInputRef.current.click();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDeleteImage = () => {
|
const handleDeleteImage = () => {
|
||||||
setselectedImage(null);
|
setselectedImage(null);
|
||||||
setFieldValue(fieldname, null);
|
setFieldValue(fieldname, null);
|
||||||
setShowAddIcon(true);
|
setShowAddIcon(true);
|
||||||
if (fileInputRef.current) {
|
if (fileInputRef.current) {
|
||||||
fileInputRef.current.value = "";
|
fileInputRef.current.value = "";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const isDocumentFormat = (fileType) => {
|
const isDocumentFormat = (fileType) => {
|
||||||
const documentFormats = [
|
const documentFormats = [
|
||||||
"application/pdf",
|
"application/pdf",
|
||||||
"application/msword",
|
"application/msword",
|
||||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||||
"application/vnd.ms-excel",
|
"application/vnd.ms-excel",
|
||||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||||
];
|
];
|
||||||
return documentFormats.includes(fileType);
|
return documentFormats.includes(fileType);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ width: "100%", my: 1 }}>
|
<Box sx={{width: "100%", my: 1}}>
|
||||||
{showAddIcon ? (
|
{showAddIcon ? (
|
||||||
// Show the add icon and "Upload File" text when no image is selected
|
// Show the add icon and "Upload File" text when no image is selected
|
||||||
<>
|
<>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
border: "1px solid #b3b3b3",
|
border: "1px solid #b3b3b3",
|
||||||
borderRadius: "10px",
|
borderRadius: "10px",
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
padding: "5px",
|
padding: "5px",
|
||||||
|
|
||||||
height: imageSize[1],
|
height: imageSize[1],
|
||||||
}}
|
}}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
>
|
>
|
||||||
<AddIcon sx={{ fontSize: "2rem", color: "#a19d9d" }} />
|
<AddIcon sx={{fontSize: "2rem", color: "#a19d9d"}}/>
|
||||||
<Typography
|
<Typography
|
||||||
variant="subtitle2"
|
variant="subtitle2"
|
||||||
sx={{
|
sx={{
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
fontSize: "1rem",
|
fontSize: "1rem",
|
||||||
color: "#a19d9d",
|
color: "#a19d9d",
|
||||||
mt: 1,
|
mt: 1,
|
||||||
}}
|
}}
|
||||||
textAlign="center"
|
textAlign="center"
|
||||||
>
|
>
|
||||||
{t("UploadSystem.upload_file")}
|
{t("UploadSystem.upload_file")}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
// Show the uploaded content along with the delete button when an image or document is selected
|
// Show the uploaded content along with the delete button when an image or document is selected
|
||||||
<>
|
<>
|
||||||
{fileType && fileType.startsWith("image/") ? (
|
{fileType && fileType.startsWith("image/") ? (
|
||||||
<Box
|
<Box
|
||||||
width="100%"
|
width="100%"
|
||||||
height={imageSize[1]}
|
height={imageSize[1]}
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
objectFit: "contain",
|
objectFit: "contain",
|
||||||
border: "1px solid #b3b3b3",
|
border: "1px solid #b3b3b3",
|
||||||
borderTopRightRadius: "10px",
|
borderTopRightRadius: "10px",
|
||||||
borderTopLeftRadius: "10px",
|
borderTopLeftRadius: "10px",
|
||||||
borderBottom: "unset",
|
borderBottom: "unset",
|
||||||
padding: "5px",
|
padding: "5px",
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
}}
|
}}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
>
|
>
|
||||||
<Paper
|
<Paper
|
||||||
elevation={0}
|
elevation={0}
|
||||||
sx={{
|
sx={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: "100%",
|
height: "100%",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
backgroundSize: "contain",
|
backgroundSize: "contain",
|
||||||
backgroundRepeat: "no-repeat",
|
backgroundRepeat: "no-repeat",
|
||||||
backgroundPosition: "center",
|
backgroundPosition: "center",
|
||||||
backgroundImage: `url(${selectedImage})`,
|
backgroundImage: `url(${selectedImage})`,
|
||||||
}}
|
}}
|
||||||
></Paper>
|
></Paper>
|
||||||
</Box>
|
</Box>
|
||||||
) : (
|
) : (
|
||||||
fileType &&
|
fileType &&
|
||||||
isDocumentFormat(fileType) && (
|
isDocumentFormat(fileType) && (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
height: imageSize[1],
|
height: imageSize[1],
|
||||||
display: "flex",
|
display: "flex",
|
||||||
border: "1px solid #b3b3b3",
|
border: "1px solid #b3b3b3",
|
||||||
borderTopRightRadius: "10px",
|
borderTopRightRadius: "10px",
|
||||||
borderTopLeftRadius: "10px",
|
borderTopLeftRadius: "10px",
|
||||||
borderBottom: "unset",
|
borderBottom: "unset",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
}}
|
}}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
>
|
>
|
||||||
<Typography
|
<Typography
|
||||||
margin={2}
|
margin={2}
|
||||||
sx={{
|
sx={{
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
fontSize: "1rem",
|
fontSize: "1rem",
|
||||||
color: "#a19d9d",
|
color: "#a19d9d",
|
||||||
}}
|
}}
|
||||||
textAlign="center"
|
textAlign="center"
|
||||||
>
|
>
|
||||||
{fileName}
|
{fileName}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
<Button
|
<Button
|
||||||
sx={{
|
sx={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
}}
|
}}
|
||||||
color="error"
|
color="error"
|
||||||
endIcon={<DeleteForeverIcon />}
|
endIcon={<DeleteForeverIcon/>}
|
||||||
variant="contained"
|
variant="contained"
|
||||||
onClick={handleDeleteImage}
|
onClick={handleDeleteImage}
|
||||||
>
|
>
|
||||||
{t("UploadSystem.delete")}
|
{t("UploadSystem.delete")}
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<input
|
<input
|
||||||
type="file"
|
type="file"
|
||||||
accept="image/*, .pdf, .doc, .docx, .xls, .xlsx"
|
accept="image/*, .pdf, .doc, .docx, .xls, .xlsx"
|
||||||
style={{ display: "none" }}
|
style={{display: "none"}}
|
||||||
onChange={handleUploadChange}
|
onChange={handleUploadChange}
|
||||||
ref={fileInputRef}
|
ref={fileInputRef}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default UploadSystem;
|
export default UploadSystem;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { NoSsr } from "@mui/material";
|
import {NoSsr} from "@mui/material";
|
||||||
|
|
||||||
const NoSsrHandler = ({ isBot, children }) => {
|
const NoSsrHandler = ({isBot, children}) => {
|
||||||
if (isBot) return children;
|
if (isBot) return children;
|
||||||
return <NoSsr>{children}</NoSsr>;
|
return <NoSsr>{children}</NoSsr>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default NoSsrHandler;
|
export default NoSsrHandler;
|
||||||
|
|||||||
@@ -1,40 +1,40 @@
|
|||||||
import DangerousIcon from "@mui/icons-material/Dangerous";
|
import DangerousIcon from "@mui/icons-material/Dangerous";
|
||||||
import { Box, Typography } from "@mui/material";
|
import {Box, Typography} from "@mui/material";
|
||||||
import { toast } from "react-toastify";
|
import {toast} from "react-toastify";
|
||||||
|
|
||||||
const ErrorNotification = (directionApp, status, t, message) => {
|
const ErrorNotification = (directionApp, status, t, message) => {
|
||||||
toast(
|
toast(
|
||||||
() => (
|
() => (
|
||||||
<>
|
<>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
alignItems: "start",
|
alignItems: "start",
|
||||||
justifyContent: "start",
|
justifyContent: "start",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box sx={{ display: "flex", alignItems: "center" }}>
|
<Box sx={{display: "flex", alignItems: "center"}}>
|
||||||
<DangerousIcon color="error" sx={{ mr: 1.6 }} />
|
<DangerousIcon color="error" sx={{mr: 1.6}}/>
|
||||||
<Box sx={{ display: "flex", flexDirection: "column" }}>
|
<Box sx={{display: "flex", flexDirection: "column"}}>
|
||||||
<Typography color="error" variant="button">
|
<Typography color="error" variant="button">
|
||||||
{t("notifications.error")} ({t("notifications.code")}: {status})
|
{t("notifications.error")} ({t("notifications.code")}: {status})
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="caption">
|
<Typography variant="caption">
|
||||||
{message || t("notifications.error_static_text")}
|
{message || t("notifications.error_static_text")}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
{
|
{
|
||||||
position: directionApp === "ltr" ? "top-left" : "top-right",
|
position: directionApp === "ltr" ? "top-left" : "top-right",
|
||||||
autoClose: false,
|
autoClose: false,
|
||||||
closeOnClick: false,
|
closeOnClick: false,
|
||||||
draggable: false,
|
draggable: false,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ErrorNotification;
|
export default ErrorNotification;
|
||||||
|
|||||||
@@ -1,43 +1,43 @@
|
|||||||
import BeenhereIcon from "@mui/icons-material/Beenhere";
|
import BeenhereIcon from "@mui/icons-material/Beenhere";
|
||||||
import { Box, Typography } from "@mui/material";
|
import {Box, Typography} from "@mui/material";
|
||||||
import { toast } from "react-toastify";
|
import {toast} from "react-toastify";
|
||||||
|
|
||||||
const SuccessNotification = (directionApp, status, t) => {
|
const SuccessNotification = (directionApp, status, t) => {
|
||||||
toast(
|
toast(
|
||||||
() => (
|
() => (
|
||||||
<>
|
<>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
alignItems: "start",
|
alignItems: "start",
|
||||||
justifyContent: "start",
|
justifyContent: "start",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box sx={{ display: "flex", alignItems: "center" }}>
|
<Box sx={{display: "flex", alignItems: "center"}}>
|
||||||
<BeenhereIcon color="success" sx={{ mr: 1.6 }} />
|
<BeenhereIcon color="success" sx={{mr: 1.6}}/>
|
||||||
<Box sx={{ display: "flex", flexDirection: "column" }}>
|
<Box sx={{display: "flex", flexDirection: "column"}}>
|
||||||
<Typography color="success.main" variant="button">
|
<Typography color="success.main" variant="button">
|
||||||
{t("notifications.success")} ({t("notifications.code")}:{" "}
|
{t("notifications.success")} ({t("notifications.code")}:{" "}
|
||||||
{status})
|
{status})
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="caption">
|
<Typography variant="caption">
|
||||||
{t("notifications.success_static_text")}
|
{t("notifications.success_static_text")}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
{
|
{
|
||||||
position: directionApp === "ltr" ? "top-left" : "top-right",
|
position: directionApp === "ltr" ? "top-left" : "top-right",
|
||||||
autoClose: 3000,
|
autoClose: 3000,
|
||||||
hideProgressBar: true,
|
hideProgressBar: true,
|
||||||
pauseOnHover: true,
|
pauseOnHover: true,
|
||||||
closeOnClick: false,
|
closeOnClick: false,
|
||||||
draggable: true,
|
draggable: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SuccessNotification;
|
export default SuccessNotification;
|
||||||
|
|||||||
@@ -1,37 +1,37 @@
|
|||||||
import DangerousIcon from "@mui/icons-material/Dangerous";
|
import DangerousIcon from "@mui/icons-material/Dangerous";
|
||||||
import { Box, Typography } from "@mui/material";
|
import {Box, Typography} from "@mui/material";
|
||||||
import { toast } from "react-toastify";
|
import {toast} from "react-toastify";
|
||||||
|
|
||||||
const UploadFileNotification = (directionApp, t) => {
|
const UploadFileNotification = (directionApp, t) => {
|
||||||
toast(
|
toast(
|
||||||
({ closeToast }) => (
|
({closeToast}) => (
|
||||||
<>
|
<>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
alignItems: "start",
|
alignItems: "start",
|
||||||
justifyContent: "start",
|
justifyContent: "start",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box sx={{ display: "flex", alignItems: "center" }}>
|
<Box sx={{display: "flex", alignItems: "center"}}>
|
||||||
<DangerousIcon color="error" sx={{ mr: 1.6 }} />
|
<DangerousIcon color="error" sx={{mr: 1.6}}/>
|
||||||
<Box sx={{ display: "flex", flexDirection: "column" }}>
|
<Box sx={{display: "flex", flexDirection: "column"}}>
|
||||||
<Typography color="error" variant="button">
|
<Typography color="error" variant="button">
|
||||||
{t("UploadSystem.uploadfile_error")}
|
{t("UploadSystem.uploadfile_error")}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
{
|
{
|
||||||
position: directionApp === "ltr" ? "top-left" : "top-right",
|
position: directionApp === "ltr" ? "top-left" : "top-right",
|
||||||
autoClose: false,
|
autoClose: false,
|
||||||
closeOnClick: false,
|
closeOnClick: false,
|
||||||
draggable: false,
|
draggable: false,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default UploadFileNotification;
|
export default UploadFileNotification;
|
||||||
|
|||||||
@@ -1,41 +1,41 @@
|
|||||||
import ReportIcon from "@mui/icons-material/Report";
|
import ReportIcon from "@mui/icons-material/Report";
|
||||||
import { Box, Typography } from "@mui/material";
|
import {Box, Typography} from "@mui/material";
|
||||||
import { toast } from "react-toastify";
|
import {toast} from "react-toastify";
|
||||||
|
|
||||||
const WarningNotification = (directionApp, status, t) => {
|
const WarningNotification = (directionApp, status, t) => {
|
||||||
toast(
|
toast(
|
||||||
() => (
|
() => (
|
||||||
<>
|
<>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
alignItems: "start",
|
alignItems: "start",
|
||||||
justifyContent: "start",
|
justifyContent: "start",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box sx={{ display: "flex", alignItems: "center" }}>
|
<Box sx={{display: "flex", alignItems: "center"}}>
|
||||||
<ReportIcon color="warning" sx={{ mr: 1.6 }} />
|
<ReportIcon color="warning" sx={{mr: 1.6}}/>
|
||||||
<Box sx={{ display: "flex", flexDirection: "column" }}>
|
<Box sx={{display: "flex", flexDirection: "column"}}>
|
||||||
<Typography color="warning.main" variant="button">
|
<Typography color="warning.main" variant="button">
|
||||||
{t("notifications.warning")} ({t("notifications.code")}:{" "}
|
{t("notifications.warning")} ({t("notifications.code")}:{" "}
|
||||||
{status})
|
{status})
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="caption">
|
<Typography variant="caption">
|
||||||
{t("notifications.warning_static_text")}
|
{t("notifications.warning_static_text")}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
{
|
{
|
||||||
position: directionApp === "ltr" ? "top-left" : "top-right",
|
position: directionApp === "ltr" ? "top-left" : "top-right",
|
||||||
autoClose: false,
|
autoClose: false,
|
||||||
closeOnClick: false,
|
closeOnClick: false,
|
||||||
draggable: false,
|
draggable: false,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default WarningNotification;
|
export default WarningNotification;
|
||||||
|
|||||||
@@ -3,37 +3,37 @@ import WarningNotification from "./WarningNotification";
|
|||||||
import SuccessNotification from "./SuccessNotification";
|
import SuccessNotification from "./SuccessNotification";
|
||||||
|
|
||||||
const Notifications = async (directionApp, response, t) => {
|
const Notifications = async (directionApp, response, t) => {
|
||||||
const { status, data } = response;
|
const {status, data} = response;
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case 200:
|
case 200:
|
||||||
SuccessNotification(directionApp, status, t);
|
SuccessNotification(directionApp, status, t);
|
||||||
break;
|
break;
|
||||||
case 400:
|
case 400:
|
||||||
ErrorNotification(directionApp, status, t);
|
ErrorNotification(directionApp, status, t);
|
||||||
break;
|
break;
|
||||||
case 401:
|
case 401:
|
||||||
ErrorNotification(directionApp, status, t);
|
ErrorNotification(directionApp, status, t);
|
||||||
break;
|
break;
|
||||||
case 403:
|
case 403:
|
||||||
ErrorNotification(directionApp, status, t);
|
ErrorNotification(directionApp, status, t);
|
||||||
break;
|
break;
|
||||||
case 422:
|
case 422:
|
||||||
ErrorNotification(directionApp, status, t, data.message);
|
ErrorNotification(directionApp, status, t, data.message);
|
||||||
break;
|
break;
|
||||||
case 500:
|
case 500:
|
||||||
WarningNotification(directionApp, status, t);
|
WarningNotification(directionApp, status, t);
|
||||||
break;
|
break;
|
||||||
case 503:
|
case 503:
|
||||||
WarningNotification(directionApp, status, t);
|
WarningNotification(directionApp, status, t);
|
||||||
break;
|
break;
|
||||||
case 504:
|
case 504:
|
||||||
WarningNotification(directionApp, status, t);
|
WarningNotification(directionApp, status, t);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// Handle other cases if needed
|
// Handle other cases if needed
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Notifications;
|
export default Notifications;
|
||||||
|
|||||||
@@ -14,55 +14,55 @@ export const GET_USER_ROUTE = BASE_URL + "/dashboard/profile/info";
|
|||||||
|
|
||||||
//passenger office
|
//passenger office
|
||||||
export const GET_PASSENGER_OFFICE =
|
export const GET_PASSENGER_OFFICE =
|
||||||
BASE_URL + "/dashboard/passenger_office_chief/show";
|
BASE_URL + "/dashboard/passenger_office_chief/show";
|
||||||
|
|
||||||
export const CONFIRM_PASSENGER_OFFICE =
|
export const CONFIRM_PASSENGER_OFFICE =
|
||||||
BASE_URL + "/dashboard/passenger_office_chief/confirm";
|
BASE_URL + "/dashboard/passenger_office_chief/confirm";
|
||||||
|
|
||||||
export const REJECT_PASSENGER_OFFICE =
|
export const REJECT_PASSENGER_OFFICE =
|
||||||
BASE_URL + "/dashboard/passenger_office_chief/reject";
|
BASE_URL + "/dashboard/passenger_office_chief/reject";
|
||||||
//passenger office
|
//passenger office
|
||||||
|
|
||||||
//passenger boss
|
//passenger boss
|
||||||
export const GET_PASSENGER_BOSS =
|
export const GET_PASSENGER_BOSS =
|
||||||
BASE_URL + "/dashboard/province_working_group/show";
|
BASE_URL + "/dashboard/province_working_group/show";
|
||||||
|
|
||||||
export const CONFIRM_PASSENGER_BOSS =
|
export const CONFIRM_PASSENGER_BOSS =
|
||||||
BASE_URL + "/dashboard/province_working_group/confirm";
|
BASE_URL + "/dashboard/province_working_group/confirm";
|
||||||
|
|
||||||
export const REJECT_PASSENGER_BOSS =
|
export const REJECT_PASSENGER_BOSS =
|
||||||
BASE_URL + "/dashboard/province_working_group/reject";
|
BASE_URL + "/dashboard/province_working_group/reject";
|
||||||
//passenger boss
|
//passenger boss
|
||||||
|
|
||||||
//transportation assistance
|
//transportation assistance
|
||||||
export const GET_TRANSPORTATION_ASSISTANCE =
|
export const GET_TRANSPORTATION_ASSISTANCE =
|
||||||
BASE_URL + "/dashboard/transportation_assistant/show";
|
BASE_URL + "/dashboard/transportation_assistant/show";
|
||||||
|
|
||||||
export const CONFIRM_TRANSPORTATION_ASSISTANCE =
|
export const CONFIRM_TRANSPORTATION_ASSISTANCE =
|
||||||
BASE_URL + "/dashboard/transportation_assistant/confirm";
|
BASE_URL + "/dashboard/transportation_assistant/confirm";
|
||||||
|
|
||||||
export const REJECT_TRANSPORTATION_ASSISTANCE =
|
export const REJECT_TRANSPORTATION_ASSISTANCE =
|
||||||
BASE_URL + "/dashboard/transportation_assistant/reject";
|
BASE_URL + "/dashboard/transportation_assistant/reject";
|
||||||
//transportation assistance
|
//transportation assistance
|
||||||
|
|
||||||
//machinary office
|
//machinary office
|
||||||
export const GET_MACHINARY_OFFICE =
|
export const GET_MACHINARY_OFFICE =
|
||||||
BASE_URL + "/dashboard/machinery_expert/show";
|
BASE_URL + "/dashboard/machinery_expert/show";
|
||||||
|
|
||||||
export const CONFIRM_MACHINARY_OFFICE =
|
export const CONFIRM_MACHINARY_OFFICE =
|
||||||
BASE_URL + "/dashboard/machinery_expert/confirm";
|
BASE_URL + "/dashboard/machinery_expert/confirm";
|
||||||
|
|
||||||
export const REJECT_MACHINARY_OFFICE =
|
export const REJECT_MACHINARY_OFFICE =
|
||||||
BASE_URL + "/dashboard/machinery_expert/reject";
|
BASE_URL + "/dashboard/machinery_expert/reject";
|
||||||
//passenger office
|
//passenger office
|
||||||
|
|
||||||
//province manager
|
//province manager
|
||||||
export const GET_PROVINCE_MANAGER =
|
export const GET_PROVINCE_MANAGER =
|
||||||
BASE_URL + "/dashboard/province_manager/show";
|
BASE_URL + "/dashboard/province_manager/show";
|
||||||
|
|
||||||
export const CONFIRM_PROVINCE_MANAGER =
|
export const CONFIRM_PROVINCE_MANAGER =
|
||||||
BASE_URL + "/dashboard/province_manager/confirm";
|
BASE_URL + "/dashboard/province_manager/confirm";
|
||||||
|
|
||||||
export const REJECT_PROVINCE_MANAGER =
|
export const REJECT_PROVINCE_MANAGER =
|
||||||
BASE_URL + "/dashboard/province_manager/reject";
|
BASE_URL + "/dashboard/province_manager/reject";
|
||||||
//province manager
|
//province manager
|
||||||
|
|||||||
@@ -2,18 +2,18 @@ import BorderColorIcon from "@mui/icons-material/BorderColor";
|
|||||||
import PasswordIcon from "@mui/icons-material/Password";
|
import PasswordIcon from "@mui/icons-material/Password";
|
||||||
|
|
||||||
const headerProfileItems = [
|
const headerProfileItems = [
|
||||||
{
|
{
|
||||||
key: 0,
|
key: 0,
|
||||||
name: "header.edit_profile",
|
name: "header.edit_profile",
|
||||||
route: "/dashboard/edit-profile",
|
route: "/dashboard/edit-profile",
|
||||||
icon: <BorderColorIcon />,
|
icon: <BorderColorIcon/>,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 1,
|
key: 1,
|
||||||
name: "header.change_password",
|
name: "header.change_password",
|
||||||
route: "/dashboard/change-password",
|
route: "/dashboard/change-password",
|
||||||
icon: <PasswordIcon />,
|
icon: <PasswordIcon/>,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export default headerProfileItems;
|
export default headerProfileItems;
|
||||||
|
|||||||
@@ -6,58 +6,58 @@ import AssignmentIndIcon from "@mui/icons-material/AssignmentInd";
|
|||||||
import DesktopWindowsIcon from "@mui/icons-material/DesktopWindows";
|
import DesktopWindowsIcon from "@mui/icons-material/DesktopWindows";
|
||||||
|
|
||||||
const sidebarMenu = [
|
const sidebarMenu = [
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
key: "sidebar.dashboard",
|
key: "sidebar.dashboard",
|
||||||
type: "page",
|
type: "page",
|
||||||
route: "/dashboard",
|
route: "/dashboard",
|
||||||
icon: <SpaceDashboardIcon />,
|
icon: <SpaceDashboardIcon/>,
|
||||||
selected: false,
|
selected: false,
|
||||||
role: "all",
|
role: "all",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "sidebar.passenger-office-chief",
|
key: "sidebar.passenger-office-chief",
|
||||||
secondary: "secondary.passenger-office",
|
secondary: "secondary.passenger-office",
|
||||||
type: "page",
|
type: "page",
|
||||||
route: "/dashboard/passenger-office-chief",
|
route: "/dashboard/passenger-office-chief",
|
||||||
icon: <AirlineSeatReclineNormalIcon />,
|
icon: <AirlineSeatReclineNormalIcon/>,
|
||||||
selected: false,
|
selected: false,
|
||||||
role: "passenger_office_chief",
|
role: "passenger_office_chief",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "sidebar.machinary-expert",
|
key: "sidebar.machinary-expert",
|
||||||
type: "page",
|
type: "page",
|
||||||
route: "/dashboard/machinary-expert",
|
route: "/dashboard/machinary-expert",
|
||||||
icon: <DirectionsCarFilledIcon />,
|
icon: <DirectionsCarFilledIcon/>,
|
||||||
selected: false,
|
selected: false,
|
||||||
role: "machinery_expert",
|
role: "machinery_expert",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "sidebar.passenger-boss",
|
key: "sidebar.passenger-boss",
|
||||||
secondary: "secondary.passenger-boss",
|
secondary: "secondary.passenger-boss",
|
||||||
type: "page",
|
type: "page",
|
||||||
route: "/dashboard/passenger-boss",
|
route: "/dashboard/passenger-boss",
|
||||||
icon: <AssignmentIndIcon />,
|
icon: <AssignmentIndIcon/>,
|
||||||
selected: false,
|
selected: false,
|
||||||
role: "passenger_office_chief",
|
role: "passenger_office_chief",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "sidebar.transportation-assistant",
|
key: "sidebar.transportation-assistant",
|
||||||
type: "page",
|
type: "page",
|
||||||
route: "/dashboard/transportation-assistant",
|
route: "/dashboard/transportation-assistant",
|
||||||
icon: <DirectionsRailwayIcon />,
|
icon: <DirectionsRailwayIcon/>,
|
||||||
selected: false,
|
selected: false,
|
||||||
role: "transportation_assistant",
|
role: "transportation_assistant",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "sidebar.province-manager",
|
key: "sidebar.province-manager",
|
||||||
type: "page",
|
type: "page",
|
||||||
route: "/dashboard/province-manager",
|
route: "/dashboard/province-manager",
|
||||||
icon: <DesktopWindowsIcon />,
|
icon: <DesktopWindowsIcon/>,
|
||||||
selected: false,
|
selected: false,
|
||||||
role: "province_manager",
|
role: "province_manager",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
export default sidebarMenu;
|
export default sidebarMenu;
|
||||||
|
|||||||
@@ -1,38 +1,38 @@
|
|||||||
import createCache from "@emotion/cache";
|
import createCache from "@emotion/cache";
|
||||||
import { prefixer } from "stylis";
|
import {prefixer} from "stylis";
|
||||||
import stylisRTLPlugin from "stylis-plugin-rtl";
|
import stylisRTLPlugin from "stylis-plugin-rtl";
|
||||||
|
|
||||||
const isBrowser = typeof document !== "undefined";
|
const isBrowser = typeof document !== "undefined";
|
||||||
|
|
||||||
export const createEmotionCacheLtr = () => {
|
export const createEmotionCacheLtr = () => {
|
||||||
let insertionPoint;
|
let insertionPoint;
|
||||||
|
|
||||||
if (isBrowser) {
|
if (isBrowser) {
|
||||||
const emotionInsertionPoint = document.querySelector(
|
const emotionInsertionPoint = document.querySelector(
|
||||||
'meta[name="emotion-insertion-point"]'
|
'meta[name="emotion-insertion-point"]'
|
||||||
);
|
);
|
||||||
insertionPoint = emotionInsertionPoint ?? undefined;
|
insertionPoint = emotionInsertionPoint ?? undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return createCache({
|
return createCache({
|
||||||
key: "mui-style",
|
key: "mui-style",
|
||||||
insertionPoint,
|
insertionPoint,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createEmotionCacheRtl = () => {
|
export const createEmotionCacheRtl = () => {
|
||||||
let insertionPoint;
|
let insertionPoint;
|
||||||
|
|
||||||
if (isBrowser) {
|
if (isBrowser) {
|
||||||
const emotionInsertionPoint = document.querySelector(
|
const emotionInsertionPoint = document.querySelector(
|
||||||
'meta[name="emotion-insertion-point"]'
|
'meta[name="emotion-insertion-point"]'
|
||||||
);
|
);
|
||||||
insertionPoint = emotionInsertionPoint ?? undefined;
|
insertionPoint = emotionInsertionPoint ?? undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return createCache({
|
return createCache({
|
||||||
key: "muirtl",
|
key: "muirtl",
|
||||||
stylisPlugins: [prefixer, stylisRTLPlugin],
|
stylisPlugins: [prefixer, stylisRTLPlugin],
|
||||||
insertionPoint,
|
insertionPoint,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { createTheme } from "@mui/material/styles";
|
import {createTheme} from "@mui/material/styles";
|
||||||
import theme from "./theme";
|
import theme from "./theme";
|
||||||
|
|
||||||
const themeRtl = createTheme({
|
const themeRtl = createTheme({
|
||||||
direction: "rtl",
|
direction: "rtl",
|
||||||
typography: {
|
typography: {
|
||||||
fontFamily: `IRANSansFaNum, sans-serif`,
|
fontFamily: `IRANSansFaNum, sans-serif`,
|
||||||
},
|
},
|
||||||
...theme,
|
...theme,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default themeRtl;
|
export default themeRtl;
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
import { faIR } from "@mui/x-date-pickers/locales";
|
import {faIR} from "@mui/x-date-pickers/locales";
|
||||||
|
|
||||||
const theme = {
|
const theme = {
|
||||||
palette: {
|
palette: {
|
||||||
primary: {
|
primary: {
|
||||||
main: "#084070",
|
main: "#084070",
|
||||||
contrastText: "#fff",
|
contrastText: "#fff",
|
||||||
light: "#2c6291",
|
light: "#2c6291",
|
||||||
dark: "#11293e",
|
dark: "#11293e",
|
||||||
},
|
},
|
||||||
secondary: {
|
secondary: {
|
||||||
main: "#FF4E00",
|
main: "#FF4E00",
|
||||||
contrastText: "#fff",
|
contrastText: "#fff",
|
||||||
light: "#ed743e",
|
light: "#ed743e",
|
||||||
dark: "#ad3a07",
|
dark: "#ad3a07",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
faIR,
|
faIR,
|
||||||
components: {
|
components: {
|
||||||
MuiBackdrop: {
|
MuiBackdrop: {
|
||||||
styleOverrides: {
|
styleOverrides: {
|
||||||
root: {
|
root: {
|
||||||
backgroundColor: "#02020226", // Replace with your desired backdrop color and opacity
|
backgroundColor: "#02020226", // Replace with your desired backdrop color and opacity
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default theme;
|
export default theme;
|
||||||
|
|||||||
@@ -4,96 +4,96 @@ import useLoading from "@/lib/app/hooks/useLoading";
|
|||||||
import useUser from "@/lib/app/hooks/useUser";
|
import useUser from "@/lib/app/hooks/useUser";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import NextNProgress from "nextjs-progressbar";
|
import NextNProgress from "nextjs-progressbar";
|
||||||
import { useEffect } from "react";
|
import {useEffect} from "react";
|
||||||
|
|
||||||
function AppLayout({ children, isBot }) {
|
function AppLayout({children, isBot}) {
|
||||||
const { languageIsReady } = useLanguage();
|
const {languageIsReady} = useLanguage();
|
||||||
const { setLoadingPage } = useLoading();
|
const {setLoadingPage} = useLoading();
|
||||||
const { userChangedLanguage, token, isAuth } = useUser();
|
const {userChangedLanguage, token, isAuth} = useUser();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (languageIsReady) {
|
if (languageIsReady) {
|
||||||
if (token) {
|
if (token) {
|
||||||
if (isAuth) {
|
if (isAuth) {
|
||||||
if (userChangedLanguage) {
|
if (userChangedLanguage) {
|
||||||
setLoadingPage(true);
|
setLoadingPage(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setLoadingPage(false);
|
setLoadingPage(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setLoadingPage(true);
|
setLoadingPage(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setLoadingPage(false);
|
setLoadingPage(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setLoadingPage(true);
|
setLoadingPage(true);
|
||||||
}, [languageIsReady, token, isAuth, userChangedLanguage]);
|
}, [languageIsReady, token, isAuth, userChangedLanguage]);
|
||||||
|
|
||||||
if (!isBot) {
|
if (!isBot) {
|
||||||
if (userChangedLanguage) return;
|
if (userChangedLanguage) return;
|
||||||
if (!languageIsReady) return;
|
if (!languageIsReady) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Head>
|
<Head>
|
||||||
<meta
|
<meta
|
||||||
name="application-name"
|
name="application-name"
|
||||||
content={process.env.NEXT_PUBLIC_API_NAME}
|
content={process.env.NEXT_PUBLIC_API_NAME}
|
||||||
/>
|
/>
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
<meta name="apple-mobile-web-app-capable" content="yes"/>
|
||||||
<meta
|
<meta
|
||||||
name="apple-mobile-web-app-status-bar-style"
|
name="apple-mobile-web-app-status-bar-style"
|
||||||
content="black-translucent"
|
content="black-translucent"
|
||||||
/>
|
/>
|
||||||
<meta
|
<meta
|
||||||
name="apple-mobile-web-app-title"
|
name="apple-mobile-web-app-title"
|
||||||
content={process.env.NEXT_PUBLIC_API_NAME}
|
content={process.env.NEXT_PUBLIC_API_NAME}
|
||||||
/>
|
/>
|
||||||
<meta name="description" content="Marhaba does it for you" />
|
<meta name="description" content="Marhaba does it for you"/>
|
||||||
<meta name="format-detection" content="telephone=no" />
|
<meta name="format-detection" content="telephone=no"/>
|
||||||
<meta name="format-detection" content="date=no" />
|
<meta name="format-detection" content="date=no"/>
|
||||||
<meta name="format-detection" content="address=no" />
|
<meta name="format-detection" content="address=no"/>
|
||||||
<meta name="format-detection" content="email=no" />
|
<meta name="format-detection" content="email=no"/>
|
||||||
<meta name="mobile-web-app-capable" content="yes" />
|
<meta name="mobile-web-app-capable" content="yes"/>
|
||||||
<link rel="apple-touch-icon" href="/icons/maskable_icon_x512.png" />
|
<link rel="apple-touch-icon" href="/icons/maskable_icon_x512.png"/>
|
||||||
<link
|
<link
|
||||||
rel="apple-touch-icon"
|
rel="apple-touch-icon"
|
||||||
sizes="120x120"
|
sizes="120x120"
|
||||||
href="/icons/maskable_icon_x128.png"
|
href="/icons/maskable_icon_x128.png"
|
||||||
/>
|
/>
|
||||||
<link
|
<link
|
||||||
rel="apple-touch-icon"
|
rel="apple-touch-icon"
|
||||||
sizes="180x180"
|
sizes="180x180"
|
||||||
href="/icons/maskable_icon_x192.png"
|
href="/icons/maskable_icon_x192.png"
|
||||||
/>
|
/>
|
||||||
<meta name="google" content="notranslate" />
|
<meta name="google" content="notranslate"/>
|
||||||
<meta name="robots" content="noindex" />
|
<meta name="robots" content="noindex"/>
|
||||||
<meta
|
<meta
|
||||||
name="viewport"
|
name="viewport"
|
||||||
content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no, user-scalable=no, viewport-fit=cover"
|
content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no, user-scalable=no, viewport-fit=cover"
|
||||||
/>
|
/>
|
||||||
<link
|
<link
|
||||||
rel="icon"
|
rel="icon"
|
||||||
type="image/svg"
|
type="image/svg"
|
||||||
sizes="32x32"
|
sizes="32x32"
|
||||||
href="/images/logo.png"
|
href="/images/logo.png"
|
||||||
/>
|
/>
|
||||||
<link
|
<link
|
||||||
rel="icon"
|
rel="icon"
|
||||||
type="image/svg"
|
type="image/svg"
|
||||||
sizes="16x16"
|
sizes="16x16"
|
||||||
href="/images/logo.png"
|
href="/images/logo.png"
|
||||||
/>
|
/>
|
||||||
</Head>
|
</Head>
|
||||||
<NextNProgress
|
<NextNProgress
|
||||||
color={theme.palette.secondary.dark}
|
color={theme.palette.secondary.dark}
|
||||||
options={{ showSpinner: false }}
|
options={{showSpinner: false}}
|
||||||
/>
|
/>
|
||||||
{children}
|
{children}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AppLayout;
|
export default AppLayout;
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import { Fade, Stack } from "@mui/material";
|
import {Fade, Stack} from "@mui/material";
|
||||||
|
|
||||||
const CenterLayout = (props) => {
|
const CenterLayout = (props) => {
|
||||||
return (
|
return (
|
||||||
<Fade in={true}>
|
<Fade in={true}>
|
||||||
<Stack
|
<Stack
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
justifyContent="center"
|
justifyContent="center"
|
||||||
spacing={props?.spacing}
|
spacing={props?.spacing}
|
||||||
sx={{ flex: 1, ...props?.sx, py: 3 }}
|
sx={{flex: 1, ...props?.sx, py: 3}}
|
||||||
>
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
</Stack>
|
</Stack>
|
||||||
</Fade>
|
</Fade>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CenterLayout;
|
export default CenterLayout;
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
import { Stack } from "@mui/material";
|
import {Stack} from "@mui/material";
|
||||||
|
|
||||||
const FullPageLayout = (props) => {
|
const FullPageLayout = (props) => {
|
||||||
return (
|
return (
|
||||||
<Stack
|
<Stack
|
||||||
spacing={props?.spacing}
|
spacing={props?.spacing}
|
||||||
direction={props?.direction}
|
direction={props?.direction}
|
||||||
sx={{
|
sx={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: "100%",
|
height: "100%",
|
||||||
overflowY: "scroll",
|
overflowY: "scroll",
|
||||||
overflowX: "scroll",
|
overflowX: "scroll",
|
||||||
...props?.sx,
|
...props?.sx,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default FullPageLayout;
|
export default FullPageLayout;
|
||||||
|
|||||||
@@ -1,76 +1,74 @@
|
|||||||
import NoSsrHandler from "@/core/components/isBotHandler";
|
import NoSsrHandler from "@/core/components/isBotHandler";
|
||||||
import {
|
import {createEmotionCacheRtl} from "@/core/utils/createEmotionCache";
|
||||||
createEmotionCacheRtl
|
|
||||||
} from "@/core/utils/createEmotionCache";
|
|
||||||
import themeRtl from "@/core/utils/theme-rtl";
|
import themeRtl from "@/core/utils/theme-rtl";
|
||||||
import { CacheProvider } from "@emotion/react";
|
import {CacheProvider} from "@emotion/react";
|
||||||
import { GlobalStyles } from "@mui/material";
|
import {GlobalStyles} from "@mui/material";
|
||||||
import CssBaseline from "@mui/material/CssBaseline";
|
import CssBaseline from "@mui/material/CssBaseline";
|
||||||
import { ThemeProvider } from "@mui/material/styles";
|
import {ThemeProvider} from "@mui/material/styles";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
|
|
||||||
const clientSideEmotionCacheRtl = createEmotionCacheRtl();
|
const clientSideEmotionCacheRtl = createEmotionCacheRtl();
|
||||||
|
|
||||||
const MuiLayout = ({ children, isBot }) => {
|
const MuiLayout = ({children, isBot}) => {
|
||||||
|
|
||||||
const emotionCache = clientSideEmotionCacheRtl;
|
const emotionCache = clientSideEmotionCacheRtl;
|
||||||
|
|
||||||
const theme = themeRtl;
|
const theme = themeRtl;
|
||||||
return (
|
return (
|
||||||
<NoSsrHandler isBot={isBot}>
|
<NoSsrHandler isBot={isBot}>
|
||||||
<CacheProvider value={emotionCache}>
|
<CacheProvider value={emotionCache}>
|
||||||
<Head>
|
<Head>
|
||||||
<meta name="viewport" content="initial-scale=1, width=device-width" />
|
<meta name="viewport" content="initial-scale=1, width=device-width"/>
|
||||||
</Head>
|
</Head>
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
<GlobalStyles
|
<GlobalStyles
|
||||||
styles={{
|
styles={{
|
||||||
"*:not(.MuiTableContainer-root)::-webkit-scrollbar": {
|
"*:not(.MuiTableContainer-root)::-webkit-scrollbar": {
|
||||||
display: "none",
|
display: "none",
|
||||||
},
|
},
|
||||||
"*::-webkit-scrollbar": {
|
"*::-webkit-scrollbar": {
|
||||||
height: "8px",
|
height: "8px",
|
||||||
},
|
},
|
||||||
"*::-webkit-scrollbar-thumb": {
|
"*::-webkit-scrollbar-thumb": {
|
||||||
background: "#e1e1e1",
|
background: "#e1e1e1",
|
||||||
borderRadius: "3px",
|
borderRadius: "3px",
|
||||||
},
|
},
|
||||||
"*:not(.MuiTableContainer-root)": {
|
"*:not(.MuiTableContainer-root)": {
|
||||||
scrollbarWidth: "thin",
|
scrollbarWidth: "thin",
|
||||||
scrollbarColor: "transparent transparent",
|
scrollbarColor: "transparent transparent",
|
||||||
},
|
},
|
||||||
|
|
||||||
"*": {
|
"*": {
|
||||||
scrollbarWidth: "thin",
|
scrollbarWidth: "thin",
|
||||||
scrollbarColor: "#e1e1e1 transparent",
|
scrollbarColor: "#e1e1e1 transparent",
|
||||||
},
|
},
|
||||||
|
|
||||||
"*::-moz-scrollbar-thumb": {
|
"*::-moz-scrollbar-thumb": {
|
||||||
backgroundColor: "#e1e1e1",
|
backgroundColor: "#e1e1e1",
|
||||||
},
|
},
|
||||||
[`@media (max-width: ${theme.breakpoints.values.sm}px)`]: {
|
[`@media (max-width: ${theme.breakpoints.values.sm}px)`]: {
|
||||||
"*::-webkit-scrollbar": {
|
"*::-webkit-scrollbar": {
|
||||||
height: "4px",
|
height: "4px",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
body: {
|
body: {
|
||||||
width: "100vw",
|
width: "100vw",
|
||||||
height: "100vh",
|
height: "100vh",
|
||||||
},
|
},
|
||||||
"#__next": {
|
"#__next": {
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: "100%",
|
height: "100%",
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<CssBaseline />
|
<CssBaseline/>
|
||||||
{children}
|
{children}
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</CacheProvider>
|
</CacheProvider>
|
||||||
</NoSsrHandler>
|
</NoSsrHandler>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MuiLayout;
|
export default MuiLayout;
|
||||||
|
|||||||
@@ -1,25 +1,25 @@
|
|||||||
import { Box, Fade } from "@mui/material";
|
import {Box, Fade} from "@mui/material";
|
||||||
|
|
||||||
const ScrollableLayout = (props) => {
|
const ScrollableLayout = (props) => {
|
||||||
const overflowY = props?.y || "hidden";
|
const overflowY = props?.y || "hidden";
|
||||||
const overflowX = props?.x || "hidden";
|
const overflowX = props?.x || "hidden";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fade in={true}>
|
<Fade in={true}>
|
||||||
<Box
|
<Box
|
||||||
spacing={props?.spacing}
|
spacing={props?.spacing}
|
||||||
sx={{
|
sx={{
|
||||||
width: "auto",
|
width: "auto",
|
||||||
height: "auto",
|
height: "auto",
|
||||||
overflowY: overflowY,
|
overflowY: overflowY,
|
||||||
overflowX: overflowX,
|
overflowX: overflowX,
|
||||||
...props?.sx,
|
...props?.sx,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
</Box>
|
</Box>
|
||||||
</Fade>
|
</Fade>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ScrollableLayout;
|
export default ScrollableLayout;
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
import LinkRouting from "@/core/components/LinkRouting";
|
import LinkRouting from "@/core/components/LinkRouting";
|
||||||
import { Typography } from "@mui/material";
|
import {Typography} from "@mui/material";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
|
|
||||||
export default function BreadcrumbItem(props) {
|
export default function BreadcrumbItem(props) {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const isLast = props.index === props.RouterArray.length - 1;
|
const isLast = props.index === props.RouterArray.length - 1;
|
||||||
const url = `/${props.RouterArray.slice(0, props.index + 1).join("/")}`;
|
const url = `/${props.RouterArray.slice(0, props.index + 1).join("/")}`;
|
||||||
|
|
||||||
return isLast ? (
|
return isLast ? (
|
||||||
<Typography variant="body2" color="primary">
|
<Typography variant="body2" color="primary">
|
||||||
{t("sidebar." + props.label)}
|
{t("sidebar." + props.label)}
|
||||||
</Typography>
|
</Typography>
|
||||||
) : (
|
) : (
|
||||||
<LinkRouting underline="hover" color="inherit" passHref href={url}>
|
<LinkRouting underline="hover" color="inherit" passHref href={url}>
|
||||||
<Typography variant="body2">{t("sidebar." + props.label)}</Typography>
|
<Typography variant="body2">{t("sidebar." + props.label)}</Typography>
|
||||||
</LinkRouting>
|
</LinkRouting>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,49 +1,49 @@
|
|||||||
import { useRouter } from "next/router";
|
import {useRouter} from "next/router";
|
||||||
import { Box, Breadcrumbs } from "@mui/material";
|
import {Box, Breadcrumbs} from "@mui/material";
|
||||||
import { useTheme } from "@mui/material/styles";
|
import {useTheme} from "@mui/material/styles";
|
||||||
import { NavigateBefore, NavigateNext } from "@mui/icons-material";
|
import {NavigateBefore, NavigateNext} from "@mui/icons-material";
|
||||||
import BreadcrumbItem from "./BreadcrumbItem";
|
import BreadcrumbItem from "./BreadcrumbItem";
|
||||||
|
|
||||||
const BreadCrumbs = (props) => {
|
const BreadCrumbs = (props) => {
|
||||||
const { isVisible } = props;
|
const {isVisible} = props;
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
if (!isVisible) {
|
if (!isVisible) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { pathname } = router;
|
const {pathname} = router;
|
||||||
const RouterArray = pathname.split("/").filter((segment) => segment !== "");
|
const RouterArray = pathname.split("/").filter((segment) => segment !== "");
|
||||||
|
|
||||||
if (RouterArray.length === 1) {
|
if (RouterArray.length === 1) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box p={3} component="span">
|
<Box p={3} component="span">
|
||||||
<Breadcrumbs
|
<Breadcrumbs
|
||||||
maxItems={2}
|
maxItems={2}
|
||||||
separator={
|
separator={
|
||||||
theme.direction === "ltr" ? (
|
theme.direction === "ltr" ? (
|
||||||
<NavigateNext fontSize="small" />
|
<NavigateNext fontSize="small"/>
|
||||||
) : (
|
) : (
|
||||||
<NavigateBefore fontSize="small" />
|
<NavigateBefore fontSize="small"/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
aria-label="breadcrumb"
|
aria-label="breadcrumb"
|
||||||
>
|
>
|
||||||
{RouterArray.map((segment, index) => (
|
{RouterArray.map((segment, index) => (
|
||||||
<BreadcrumbItem
|
<BreadcrumbItem
|
||||||
RouterArray={RouterArray}
|
RouterArray={RouterArray}
|
||||||
label={segment}
|
label={segment}
|
||||||
key={segment}
|
key={segment}
|
||||||
index={index}
|
index={index}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default BreadCrumbs;
|
export default BreadCrumbs;
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import { Avatar, Stack, Typography } from "@mui/material";
|
import {Avatar, Stack, Typography} from "@mui/material";
|
||||||
import useUser from "@/lib/app/hooks/useUser";
|
import useUser from "@/lib/app/hooks/useUser";
|
||||||
|
|
||||||
export default function ProfileData() {
|
export default function ProfileData() {
|
||||||
const { user } = useUser();
|
const {user} = useUser();
|
||||||
return (
|
return (
|
||||||
<Stack alignItems="center" spacing={2} sx={{ p: 3 }}>
|
<Stack alignItems="center" spacing={2} sx={{p: 3}}>
|
||||||
<Avatar
|
<Avatar
|
||||||
sx={{ width: "80px", height: "80px" }}
|
sx={{width: "80px", height: "80px"}}
|
||||||
alt="User Image"
|
alt="User Image"
|
||||||
src={user.avatar}
|
src={user.avatar}
|
||||||
/>
|
/>
|
||||||
<Typography sx={{ fontSize: 15, fontWeight: 600 }} textAlign="center">
|
<Typography sx={{fontSize: 15, fontWeight: 600}} textAlign="center">
|
||||||
{user.username}
|
{user.username}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,61 +1,62 @@
|
|||||||
import { Avatar, Menu, IconButton, Tooltip } from "@mui/material";
|
import {Avatar, IconButton, Menu, Tooltip} from "@mui/material";
|
||||||
import { useState } from "react";
|
import {useState} from "react";
|
||||||
import ProfileData from "./ProfileData";
|
import ProfileData from "./ProfileData";
|
||||||
import ProfileOptions from "./ProfileOptions";
|
import ProfileOptions from "./ProfileOptions";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import useUser from "@/lib/app/hooks/useUser";
|
import useUser from "@/lib/app/hooks/useUser";
|
||||||
|
|
||||||
function ProfileMenu() {
|
function ProfileMenu() {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const [anchorElUser, setAnchorElUser] = useState(null);
|
const [anchorElUser, setAnchorElUser] = useState(null);
|
||||||
const { user } = useUser();
|
const {user} = useUser();
|
||||||
|
|
||||||
const handleOpenUserMenu = (event) => {
|
const handleOpenUserMenu = (event) => {
|
||||||
setAnchorElUser(event.currentTarget);
|
setAnchorElUser(event.currentTarget);
|
||||||
};
|
};
|
||||||
const handleCloseUserMenu = () => {
|
const handleCloseUserMenu = () => {
|
||||||
setAnchorElUser(null);
|
setAnchorElUser(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Tooltip title={t("header.open_profile")} arrow>
|
<Tooltip title={t("header.open_profile")} arrow>
|
||||||
<IconButton onClick={handleOpenUserMenu} sx={{ p: 0 }}>
|
<IconButton onClick={handleOpenUserMenu} sx={{p: 0}}>
|
||||||
<Avatar
|
<Avatar
|
||||||
sx={{
|
sx={{
|
||||||
width: 24,
|
width: 24,
|
||||||
height: 24,
|
height: 24,
|
||||||
backgroundColor: "#fff",
|
backgroundColor: "#fff",
|
||||||
color: "primary.main",
|
color: "primary.main",
|
||||||
}}
|
}}
|
||||||
alt="User Image"
|
alt="User Image"
|
||||||
src={user.avatar}
|
src={user.avatar}
|
||||||
/>
|
/>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Menu
|
<Menu
|
||||||
MenuListProps={{ sx: { py: 0 } }}
|
MenuListProps={{sx: {py: 0}}}
|
||||||
sx={{
|
sx={{
|
||||||
mt: 6,
|
mt: 6,
|
||||||
}}
|
}}
|
||||||
id="menu-appbar"
|
id="menu-appbar"
|
||||||
anchorEl={anchorElUser}
|
anchorEl={anchorElUser}
|
||||||
anchorOrigin={{
|
anchorOrigin={{
|
||||||
vertical: "top",
|
vertical: "top",
|
||||||
horizontal: "right",
|
horizontal: "right",
|
||||||
}}
|
}}
|
||||||
keepMounted
|
keepMounted
|
||||||
transformOrigin={{
|
transformOrigin={{
|
||||||
vertical: "top",
|
vertical: "top",
|
||||||
horizontal: "right",
|
horizontal: "right",
|
||||||
}}
|
}}
|
||||||
open={Boolean(anchorElUser)}
|
open={Boolean(anchorElUser)}
|
||||||
onClose={handleCloseUserMenu}
|
onClose={handleCloseUserMenu}
|
||||||
>
|
>
|
||||||
<ProfileData />
|
<ProfileData/>
|
||||||
<ProfileOptions handleCloseUserMenu={handleCloseUserMenu} />
|
<ProfileOptions handleCloseUserMenu={handleCloseUserMenu}/>
|
||||||
</Menu>
|
</Menu>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ProfileMenu;
|
export default ProfileMenu;
|
||||||
|
|||||||
@@ -1,49 +1,49 @@
|
|||||||
import { Box, Button, MenuItem, Typography } from "@mui/material";
|
import {Box, Button, MenuItem, Typography} from "@mui/material";
|
||||||
import MeetingRoomIcon from "@mui/icons-material/MeetingRoom";
|
import MeetingRoomIcon from "@mui/icons-material/MeetingRoom";
|
||||||
import useUser from "@/lib/app/hooks/useUser";
|
import useUser from "@/lib/app/hooks/useUser";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
|
|
||||||
export default function ProfileOptionLogOut({ handleCloseUserMenu }) {
|
export default function ProfileOptionLogOut({handleCloseUserMenu}) {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const { clearToken } = useUser();
|
const {clearToken} = useUser();
|
||||||
const handleClickLogOut = () => {
|
const handleClickLogOut = () => {
|
||||||
handleCloseUserMenu();
|
handleCloseUserMenu();
|
||||||
clearToken();
|
clearToken();
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
component={Button}
|
component={Button}
|
||||||
to={{
|
to={{
|
||||||
pathname: "/dashboard/logout",
|
pathname: "/dashboard/logout",
|
||||||
}}
|
}}
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
borderTop: 1,
|
borderTop: 1,
|
||||||
px: 3,
|
px: 3,
|
||||||
py: 1.5,
|
py: 1.5,
|
||||||
borderColor: "#e1e1e1",
|
borderColor: "#e1e1e1",
|
||||||
textTransform: "unset",
|
textTransform: "unset",
|
||||||
}}
|
}}
|
||||||
onClick={handleClickLogOut}
|
onClick={handleClickLogOut}
|
||||||
>
|
>
|
||||||
<Box sx={{ display: "flex", alignItems: "center", flex: 1 }}>
|
<Box sx={{display: "flex", alignItems: "center", flex: 1}}>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
color: "primary.main",
|
color: "primary.main",
|
||||||
pr: 2,
|
pr: 2,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MeetingRoomIcon />
|
<MeetingRoomIcon/>
|
||||||
</Box>
|
</Box>
|
||||||
<Typography sx={{ flex: 1 }} textAlign="start">
|
<Typography sx={{flex: 1}} textAlign="start">
|
||||||
{t("header.logout")}
|
{t("header.logout")}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,49 +1,49 @@
|
|||||||
import { Box, MenuItem, Typography } from "@mui/material";
|
import {Box, MenuItem, Typography} from "@mui/material";
|
||||||
import { NextLinkComposed } from "@/core/components/LinkRouting";
|
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import headerProfileItems from "@/core/data/headerProfileItems";
|
import headerProfileItems from "@/core/data/headerProfileItems";
|
||||||
import ProfileOptionLogOut from "./ProfileOptionLogOut";
|
import ProfileOptionLogOut from "./ProfileOptionLogOut";
|
||||||
|
|
||||||
export default function ProfileOptions({ handleCloseUserMenu }) {
|
export default function ProfileOptions({handleCloseUserMenu}) {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{headerProfileItems.map((profile_item) => (
|
{headerProfileItems.map((profile_item) => (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
component={NextLinkComposed}
|
component={NextLinkComposed}
|
||||||
to={{
|
to={{
|
||||||
pathname: profile_item.route,
|
pathname: profile_item.route,
|
||||||
}}
|
}}
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
borderTop: 1,
|
borderTop: 1,
|
||||||
px: 3,
|
px: 3,
|
||||||
py: 1.5,
|
py: 1.5,
|
||||||
borderColor: "#e1e1e1",
|
borderColor: "#e1e1e1",
|
||||||
}}
|
}}
|
||||||
key={profile_item.key}
|
key={profile_item.key}
|
||||||
onClick={handleCloseUserMenu}
|
onClick={handleCloseUserMenu}
|
||||||
>
|
>
|
||||||
<Box sx={{ display: "flex", alignItems: "center", flex: 1 }}>
|
<Box sx={{display: "flex", alignItems: "center", flex: 1}}>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
color: "primary.main",
|
color: "primary.main",
|
||||||
pr: 2,
|
pr: 2,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{profile_item.icon}
|
{profile_item.icon}
|
||||||
</Box>
|
</Box>
|
||||||
<Typography sx={{ flex: 1 }} textAlign="start">
|
<Typography sx={{flex: 1}} textAlign="start">
|
||||||
{t(profile_item.name)}
|
{t(profile_item.name)}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
))}
|
||||||
<ProfileOptionLogOut handleCloseUserMenu={handleCloseUserMenu} />
|
<ProfileOptionLogOut handleCloseUserMenu={handleCloseUserMenu}/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,80 +1,72 @@
|
|||||||
import MenuIcon from "@mui/icons-material/Menu";
|
import MenuIcon from "@mui/icons-material/Menu";
|
||||||
import {
|
import {AppBar, Box, Container, CssBaseline, IconButton, Stack, Toolbar, useTheme} from "@mui/material";
|
||||||
AppBar,
|
|
||||||
Box,
|
|
||||||
Container,
|
|
||||||
CssBaseline,
|
|
||||||
IconButton,
|
|
||||||
Stack,
|
|
||||||
Toolbar,
|
|
||||||
useTheme
|
|
||||||
} from "@mui/material";
|
|
||||||
import ProfileMenu from "./ProfileMenu";
|
import ProfileMenu from "./ProfileMenu";
|
||||||
|
|
||||||
function Header({ drawerWidth, handleDrawerToggle }) {
|
function Header({drawerWidth, handleDrawerToggle}) {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<CssBaseline />
|
<CssBaseline/>
|
||||||
<AppBar
|
<AppBar
|
||||||
position="fixed"
|
position="fixed"
|
||||||
sx={{
|
|
||||||
width: { md: `calc(100% - ${drawerWidth}px)` },
|
|
||||||
ml: { md: `${drawerWidth}px` },
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Container maxWidth="xxl">
|
|
||||||
<Toolbar
|
|
||||||
disableGutters
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Stack direction="row" justifyContent="flex-start" sx={{ flex: 1 }}>
|
|
||||||
<IconButton
|
|
||||||
color="inherit"
|
|
||||||
aria-label="open drawer"
|
|
||||||
onClick={handleDrawerToggle}
|
|
||||||
edge="start"
|
|
||||||
sx={{ display: { md: "none" }, m: 0 }}
|
|
||||||
>
|
|
||||||
<MenuIcon />
|
|
||||||
</IconButton>
|
|
||||||
</Stack>
|
|
||||||
<Stack
|
|
||||||
direction="row"
|
|
||||||
justifyContent="center"
|
|
||||||
sx={{
|
|
||||||
flex: 1,
|
|
||||||
position: "relative",
|
|
||||||
...theme.mixins.toolbar,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
sx={{
|
||||||
position: "relative",
|
width: {md: `calc(100% - ${drawerWidth}px)`},
|
||||||
my: 1,
|
ml: {md: `${drawerWidth}px`},
|
||||||
width: 56,
|
|
||||||
height: 56,
|
|
||||||
"@media (min-width:600px)": { maxWidth: 64, maxHeight: 64 },
|
|
||||||
"@media (min-width:0px)": {
|
|
||||||
"@media (orientation: landscape)": {
|
|
||||||
width: 48,
|
|
||||||
height: 48,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
</Box>
|
<Container maxWidth="xxl">
|
||||||
</Stack>
|
<Toolbar
|
||||||
<Stack direction="row" justifyContent="flex-end" sx={{ flex: 1 }}>
|
disableGutters
|
||||||
<ProfileMenu />
|
sx={{
|
||||||
</Stack>
|
display: "flex",
|
||||||
</Toolbar>
|
}}
|
||||||
</Container>
|
>
|
||||||
</AppBar>
|
<Stack direction="row" justifyContent="flex-start" sx={{flex: 1}}>
|
||||||
</>
|
<IconButton
|
||||||
);
|
color="inherit"
|
||||||
|
aria-label="open drawer"
|
||||||
|
onClick={handleDrawerToggle}
|
||||||
|
edge="start"
|
||||||
|
sx={{display: {md: "none"}, m: 0}}
|
||||||
|
>
|
||||||
|
<MenuIcon/>
|
||||||
|
</IconButton>
|
||||||
|
</Stack>
|
||||||
|
<Stack
|
||||||
|
direction="row"
|
||||||
|
justifyContent="center"
|
||||||
|
sx={{
|
||||||
|
flex: 1,
|
||||||
|
position: "relative",
|
||||||
|
...theme.mixins.toolbar,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
position: "relative",
|
||||||
|
my: 1,
|
||||||
|
width: 56,
|
||||||
|
height: 56,
|
||||||
|
"@media (min-width:600px)": {maxWidth: 64, maxHeight: 64},
|
||||||
|
"@media (min-width:0px)": {
|
||||||
|
"@media (orientation: landscape)": {
|
||||||
|
width: 48,
|
||||||
|
height: 48,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
</Box>
|
||||||
|
</Stack>
|
||||||
|
<Stack direction="row" justifyContent="flex-end" sx={{flex: 1}}>
|
||||||
|
<ProfileMenu/>
|
||||||
|
</Stack>
|
||||||
|
</Toolbar>
|
||||||
|
</Container>
|
||||||
|
</AppBar>
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Header;
|
export default Header;
|
||||||
|
|||||||
@@ -1,50 +1,50 @@
|
|||||||
import { useState } from "react";
|
import {useState} from "react";
|
||||||
import FullPageLayout from "../FullPageLayout";
|
import FullPageLayout from "../FullPageLayout";
|
||||||
import Header from "./header";
|
import Header from "./header";
|
||||||
import Sidebar from "./sidebar";
|
import Sidebar from "./sidebar";
|
||||||
import { Toolbar } from "@mui/material";
|
import {Toolbar} from "@mui/material";
|
||||||
import BreadCrumbs from "./breadcrumbs";
|
import BreadCrumbs from "./breadcrumbs";
|
||||||
import { ToastContainer } from "react-toastify";
|
import {ToastContainer} from "react-toastify";
|
||||||
import "react-toastify/dist/ReactToastify.css";
|
import "react-toastify/dist/ReactToastify.css";
|
||||||
import useDirection from "@/lib/app/hooks/useDirection";
|
import useDirection from "@/lib/app/hooks/useDirection";
|
||||||
|
|
||||||
const drawerWidth = 240;
|
const drawerWidth = 240;
|
||||||
|
|
||||||
const DashboardLayouts = (props) => {
|
const DashboardLayouts = (props) => {
|
||||||
const { directionApp } = useDirection();
|
const {directionApp} = useDirection();
|
||||||
const { window } = props;
|
const {window} = props;
|
||||||
const [mobileOpen, setMobileOpen] = useState(false);
|
const [mobileOpen, setMobileOpen] = useState(false);
|
||||||
const container =
|
const container =
|
||||||
window !== undefined ? () => window().document.body : undefined;
|
window !== undefined ? () => window().document.body : undefined;
|
||||||
|
|
||||||
const handleDrawerToggle = () => {
|
const handleDrawerToggle = () => {
|
||||||
setMobileOpen(!mobileOpen);
|
setMobileOpen(!mobileOpen);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<FullPageLayout direction="row">
|
<FullPageLayout direction="row">
|
||||||
<Header
|
<Header
|
||||||
handleDrawerToggle={handleDrawerToggle}
|
handleDrawerToggle={handleDrawerToggle}
|
||||||
drawerWidth={drawerWidth}
|
drawerWidth={drawerWidth}
|
||||||
/>
|
/>
|
||||||
<Sidebar
|
<Sidebar
|
||||||
container={container}
|
container={container}
|
||||||
mobileOpen={mobileOpen}
|
mobileOpen={mobileOpen}
|
||||||
handleDrawerToggle={handleDrawerToggle}
|
handleDrawerToggle={handleDrawerToggle}
|
||||||
drawerWidth={drawerWidth}
|
drawerWidth={drawerWidth}
|
||||||
/>
|
/>
|
||||||
<FullPageLayout
|
<FullPageLayout
|
||||||
component="main"
|
component="main"
|
||||||
sx={{ flexGrow: 1, width: { sm: `calc(100% - ${drawerWidth}px)` } }}
|
sx={{flexGrow: 1, width: {sm: `calc(100% - ${drawerWidth}px)`}}}
|
||||||
>
|
>
|
||||||
<Toolbar />
|
<Toolbar/>
|
||||||
<FullPageLayout sx={{ mt: 3 }}>
|
<FullPageLayout sx={{mt: 3}}>
|
||||||
<BreadCrumbs isVisible={true} />
|
<BreadCrumbs isVisible={true}/>
|
||||||
{props.children}
|
{props.children}
|
||||||
|
</FullPageLayout>
|
||||||
|
</FullPageLayout>
|
||||||
|
{directionApp === "rtl" ? <ToastContainer rtl/> : <ToastContainer ltr/>}
|
||||||
</FullPageLayout>
|
</FullPageLayout>
|
||||||
</FullPageLayout>
|
);
|
||||||
{directionApp === "rtl" ? <ToastContainer rtl /> : <ToastContainer ltr />}
|
|
||||||
</FullPageLayout>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DashboardLayouts;
|
export default DashboardLayouts;
|
||||||
|
|||||||
@@ -1,29 +1,28 @@
|
|||||||
import { Divider, Stack, Toolbar, Typography } from "@mui/material";
|
import {Divider, Stack, Toolbar, Typography} from "@mui/material";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import SidebarList from "./SidebarList";
|
import SidebarList from "./SidebarList";
|
||||||
import StyledImage from "@/core/components/StyledImage";
|
|
||||||
|
|
||||||
const SidebarDrawer = ({ handleDrawerToggle }) => {
|
const SidebarDrawer = ({handleDrawerToggle}) => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<Stack>
|
<Stack>
|
||||||
<Typography variant="h6" sx={{ color: "primary.main" }}>
|
<Typography variant="h6" sx={{color: "primary.main"}}>
|
||||||
{t("app_short_name")}
|
{t("app_short_name")}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="caption">
|
<Typography variant="caption">
|
||||||
{
|
{
|
||||||
t("expert") /* make if on thease t("user_welfare_services")
|
t("expert") /* make if on thease t("user_welfare_services")
|
||||||
t("user_navy") */
|
t("user_navy") */
|
||||||
}
|
}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
<Divider />
|
<Divider/>
|
||||||
<SidebarList handleDrawerToggle={handleDrawerToggle} />
|
<SidebarList handleDrawerToggle={handleDrawerToggle}/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SidebarDrawer;
|
export default SidebarDrawer;
|
||||||
|
|||||||
@@ -1,57 +1,57 @@
|
|||||||
import { Divider, List } from "@mui/material";
|
import {Divider, List} from "@mui/material";
|
||||||
import { useEffect, useReducer } from "react";
|
import {useEffect, useReducer} from "react";
|
||||||
import SidebarListItem from "./SidebarListItem";
|
import SidebarListItem from "./SidebarListItem";
|
||||||
import sidebarMenu from "@/core/data/sidebarMenu";
|
import sidebarMenu from "@/core/data/sidebarMenu";
|
||||||
import { useRouter } from "next/router";
|
import {useRouter} from "next/router";
|
||||||
import useUser from "@/lib/app/hooks/useUser";
|
import useUser from "@/lib/app/hooks/useUser";
|
||||||
|
|
||||||
function reducer(state, action) {
|
function reducer(state, action) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case "COLLAPSE_MENU":
|
case "COLLAPSE_MENU":
|
||||||
return state.map((itemsArr) =>
|
return state.map((itemsArr) =>
|
||||||
itemsArr.map((item) =>
|
itemsArr.map((item) =>
|
||||||
action.key == item.key
|
action.key == item.key
|
||||||
? { ...item, showSubItem: !item.showSubItem }
|
? {...item, showSubItem: !item.showSubItem}
|
||||||
: item
|
: item
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
case "SELECTED":
|
case "SELECTED":
|
||||||
return state.map((itemsArr) =>
|
return state.map((itemsArr) =>
|
||||||
itemsArr.map((item) =>
|
itemsArr.map((item) =>
|
||||||
action.route == item.route
|
action.route == item.route
|
||||||
? { ...item, selected: true }
|
? {...item, selected: true}
|
||||||
: { ...item, selected: false }
|
: {...item, selected: false}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function SidebarList({ handleDrawerToggle }) {
|
export default function SidebarList({handleDrawerToggle}) {
|
||||||
const [itemMenu, dispatch] = useReducer(reducer, sidebarMenu);
|
const [itemMenu, dispatch] = useReducer(reducer, sidebarMenu);
|
||||||
const { user } = useUser();
|
const {user} = useUser();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch({ type: "SELECTED", route: router.pathname });
|
dispatch({type: "SELECTED", route: router.pathname});
|
||||||
}, [router.pathname]);
|
}, [router.pathname]);
|
||||||
|
|
||||||
const filteredItemMenu = itemMenu[0].filter(
|
const filteredItemMenu = itemMenu[0].filter(
|
||||||
(item) => user.role.includes(item.role) || item.role === "all"
|
(item) => user.role.includes(item.role) || item.role === "all"
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<List>
|
<List>
|
||||||
{filteredItemMenu.map((item, index) => (
|
{filteredItemMenu.map((item, index) => (
|
||||||
<SidebarListItem
|
<SidebarListItem
|
||||||
item={item}
|
item={item}
|
||||||
dispatch={dispatch}
|
dispatch={dispatch}
|
||||||
key={item.key}
|
key={item.key}
|
||||||
handleDrawerToggle={handleDrawerToggle}
|
handleDrawerToggle={handleDrawerToggle}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{filteredItemMenu.length > 0 && <Divider />}
|
{filteredItemMenu.length > 0 && <Divider/>}
|
||||||
</List>
|
</List>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,84 +1,77 @@
|
|||||||
import { NextLinkComposed } from "@/core/components/LinkRouting";
|
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
||||||
import ExpandLess from "@mui/icons-material/ExpandLess";
|
import ExpandLess from "@mui/icons-material/ExpandLess";
|
||||||
import ExpandMore from "@mui/icons-material/ExpandMore";
|
import ExpandMore from "@mui/icons-material/ExpandMore";
|
||||||
import {
|
import {Badge, ListItem, ListItemButton, ListItemIcon, ListItemText, Typography,} from "@mui/material";
|
||||||
Badge,
|
import {useTranslations} from "next-intl";
|
||||||
ListItem,
|
import {Fragment} from "react";
|
||||||
ListItemButton,
|
|
||||||
ListItemIcon,
|
|
||||||
ListItemText,
|
|
||||||
Typography,
|
|
||||||
} from "@mui/material";
|
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { Fragment } from "react";
|
|
||||||
import SidebarListSubItem from "./SidebarListSubItem";
|
import SidebarListSubItem from "./SidebarListSubItem";
|
||||||
|
|
||||||
const SidebarListItem = ({ item, dispatch, handleDrawerToggle }) => {
|
const SidebarListItem = ({item, dispatch, handleDrawerToggle}) => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment key={item.key}>
|
<Fragment key={item.key}>
|
||||||
<ListItem disablePadding sx={{ display: "block" }}>
|
<ListItem disablePadding sx={{display: "block"}}>
|
||||||
<ListItemButton
|
<ListItemButton
|
||||||
selected={item.selected}
|
selected={item.selected}
|
||||||
{...(item.type == "page" && {
|
{...(item.type == "page" && {
|
||||||
component: NextLinkComposed,
|
component: NextLinkComposed,
|
||||||
to: {
|
to: {
|
||||||
pathname: item.route,
|
pathname: item.route,
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (item.type == "menu") {
|
if (item.type == "menu") {
|
||||||
dispatch({ type: "COLLAPSE_MENU", key: item.key });
|
dispatch({type: "COLLAPSE_MENU", key: item.key});
|
||||||
}
|
}
|
||||||
handleDrawerToggle();
|
handleDrawerToggle();
|
||||||
}}
|
}}
|
||||||
sx={{
|
sx={{
|
||||||
minHeight: 48,
|
minHeight: 48,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ListItemIcon
|
<ListItemIcon
|
||||||
sx={{
|
sx={{
|
||||||
minWidth: 0,
|
minWidth: 0,
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
color: "primary.main",
|
color: "primary.main",
|
||||||
pr: 2,
|
pr: 2,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{item.icon}
|
{item.icon}
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<ListItemText
|
<ListItemText
|
||||||
primary={t(item.key)}
|
primary={t(item.key)}
|
||||||
secondary={
|
secondary={
|
||||||
item.secondary !== undefined ? (
|
item.secondary !== undefined ? (
|
||||||
<Typography variant="caption" color="textSecondary">
|
<Typography variant="caption" color="textSecondary">
|
||||||
{t(item.secondary)}
|
{t(item.secondary)}
|
||||||
</Typography>
|
</Typography>
|
||||||
) : null
|
) : null
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{item.type == "menu" &&
|
{item.type == "menu" &&
|
||||||
(item.showSubItem ? <ExpandLess /> : <ExpandMore />)}
|
(item.showSubItem ? <ExpandLess/> : <ExpandMore/>)}
|
||||||
<Badge
|
<Badge
|
||||||
badgeContent="21"
|
badgeContent="21"
|
||||||
color="error"
|
color="error"
|
||||||
variant="standard"
|
variant="standard"
|
||||||
anchorOrigin={{
|
anchorOrigin={{
|
||||||
vertical: "top",
|
vertical: "top",
|
||||||
horizontal: "right",
|
horizontal: "right",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
{item.subItem && (
|
{item.subItem && (
|
||||||
<SidebarListSubItem
|
<SidebarListSubItem
|
||||||
item={item}
|
item={item}
|
||||||
handleDrawerToggle={handleDrawerToggle}
|
handleDrawerToggle={handleDrawerToggle}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SidebarListItem;
|
export default SidebarListItem;
|
||||||
|
|||||||
@@ -1,54 +1,48 @@
|
|||||||
import { NextLinkComposed } from "@/core/components/LinkRouting";
|
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
||||||
import InboxIcon from "@mui/icons-material/MoveToInbox";
|
import InboxIcon from "@mui/icons-material/MoveToInbox";
|
||||||
import {
|
import {Collapse, List, ListItemButton, ListItemIcon, ListItemText,} from "@mui/material";
|
||||||
Collapse,
|
import {useTranslations} from "next-intl";
|
||||||
List,
|
import {Fragment} from "react";
|
||||||
ListItemButton,
|
|
||||||
ListItemIcon,
|
|
||||||
ListItemText,
|
|
||||||
} from "@mui/material";
|
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { Fragment } from "react";
|
|
||||||
|
|
||||||
const SidebarListSubItem = ({ item, handleDrawerToggle }) => {
|
const SidebarListSubItem = ({item, handleDrawerToggle}) => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Collapse in={item.showSubItem} timeout="auto" unmountOnExit>
|
<Collapse in={item.showSubItem} timeout="auto" unmountOnExit>
|
||||||
<List component="div" disablePadding sx={{ bgcolor: "#f6f6f6" }}>
|
<List component="div" disablePadding sx={{bgcolor: "#f6f6f6"}}>
|
||||||
{item.subItem.map((subitem, index) => (
|
{item.subItem.map((subitem, index) => (
|
||||||
<Fragment key={subitem.key}>
|
<Fragment key={subitem.key}>
|
||||||
<ListItemButton
|
<ListItemButton
|
||||||
component={NextLinkComposed}
|
component={NextLinkComposed}
|
||||||
to={{
|
to={{
|
||||||
pathname: subitem.route,
|
pathname: subitem.route,
|
||||||
}}
|
}}
|
||||||
sx={{
|
sx={{
|
||||||
minHeight: 48,
|
minHeight: 48,
|
||||||
}}
|
}}
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
if (item.type == "menu") {
|
if (item.type == "menu") {
|
||||||
dispatch({ type: "COLLAPSE_MENU", key: item.key });
|
dispatch({type: "COLLAPSE_MENU", key: item.key});
|
||||||
}
|
}
|
||||||
handleDrawerToggle();
|
handleDrawerToggle();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ListItemIcon
|
<ListItemIcon
|
||||||
sx={{
|
sx={{
|
||||||
minWidth: 0,
|
minWidth: 0,
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
pr: 2,
|
pr: 2,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<InboxIcon />
|
<InboxIcon/>
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<ListItemText primary={t(subitem.key)} />
|
<ListItemText primary={t(subitem.key)}/>
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</List>
|
</List>
|
||||||
</Collapse>
|
</Collapse>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SidebarListSubItem;
|
export default SidebarListSubItem;
|
||||||
|
|||||||
@@ -1,46 +1,46 @@
|
|||||||
import { Box, Drawer } from "@mui/material";
|
import {Box, Drawer} from "@mui/material";
|
||||||
import SidebarDrawer from "./SidebarDrawer";
|
import SidebarDrawer from "./SidebarDrawer";
|
||||||
|
|
||||||
const Sidebar = (props) => {
|
const Sidebar = (props) => {
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
component="nav"
|
component="nav"
|
||||||
sx={{ width: { md: props.drawerWidth }, flexShrink: { sm: 0 } }}
|
sx={{width: {md: props.drawerWidth}, flexShrink: {sm: 0}}}
|
||||||
aria-label="mailbox folders"
|
aria-label="mailbox folders"
|
||||||
>
|
>
|
||||||
<Drawer
|
<Drawer
|
||||||
container={props.container}
|
container={props.container}
|
||||||
variant="temporary"
|
variant="temporary"
|
||||||
open={props.mobileOpen}
|
open={props.mobileOpen}
|
||||||
onClose={props.handleDrawerToggle}
|
onClose={props.handleDrawerToggle}
|
||||||
ModalProps={{
|
ModalProps={{
|
||||||
keepMounted: true,
|
keepMounted: true,
|
||||||
}}
|
}}
|
||||||
sx={{
|
sx={{
|
||||||
display: { xs: "block", md: "none" },
|
display: {xs: "block", md: "none"},
|
||||||
"& .MuiDrawer-paper": {
|
"& .MuiDrawer-paper": {
|
||||||
boxSizing: "border-box",
|
boxSizing: "border-box",
|
||||||
width: props.drawerWidth,
|
width: props.drawerWidth,
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<SidebarDrawer handleDrawerToggle={props.handleDrawerToggle} />
|
<SidebarDrawer handleDrawerToggle={props.handleDrawerToggle}/>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
<Drawer
|
<Drawer
|
||||||
variant="permanent"
|
variant="permanent"
|
||||||
sx={{
|
sx={{
|
||||||
display: { xs: "none", md: "block" },
|
display: {xs: "none", md: "block"},
|
||||||
"& .MuiDrawer-paper": {
|
"& .MuiDrawer-paper": {
|
||||||
boxSizing: "border-box",
|
boxSizing: "border-box",
|
||||||
width: props.drawerWidth,
|
width: props.drawerWidth,
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
open
|
open
|
||||||
>
|
>
|
||||||
<SidebarDrawer handleDrawerToggle={props.handleDrawerToggle} />
|
<SidebarDrawer handleDrawerToggle={props.handleDrawerToggle}/>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Sidebar;
|
export default Sidebar;
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import { createContext } from "react";
|
import {createContext} from "react";
|
||||||
import useDataTable from "../hooks/useDatatable";
|
import useDataTable from "../hooks/useDatatable";
|
||||||
|
|
||||||
export const DataTableContext = createContext();
|
export const DataTableContext = createContext();
|
||||||
|
|
||||||
export const DataTableProvider = (props) => {
|
export const DataTableProvider = (props) => {
|
||||||
const contextValue = useDataTable();
|
const contextValue = useDataTable();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DataTableContext.Provider value={contextValue}>
|
<DataTableContext.Provider value={contextValue}>
|
||||||
{props.children}
|
{props.children}
|
||||||
</DataTableContext.Provider>
|
</DataTableContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import { createContext, useState } from "react";
|
import {createContext, useState} from "react";
|
||||||
|
|
||||||
export const ReloadDataTableContext = createContext();
|
export const ReloadDataTableContext = createContext();
|
||||||
|
|
||||||
export const ReloadDataTableProvider = ({ children }) => {
|
export const ReloadDataTableProvider = ({children}) => {
|
||||||
const [reloadDataTable, setReloadDataTable] = useState(false);
|
const [reloadDataTable, setReloadDataTable] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReloadDataTableContext.Provider
|
<ReloadDataTableContext.Provider
|
||||||
value={{ reloadDataTable, setReloadDataTable }}
|
value={{reloadDataTable, setReloadDataTable}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</ReloadDataTableContext.Provider>
|
</ReloadDataTableContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,99 +1,99 @@
|
|||||||
import { FA_DATATABLE_LOCALIZATION } from "&/locales/fa/datatable";
|
import {FA_DATATABLE_LOCALIZATION} from "&/locales/fa/datatable";
|
||||||
import { useRouter } from "next/router";
|
import {useRouter} from "next/router";
|
||||||
import { createContext, useEffect, useState } from "react";
|
import {createContext, useEffect, useState} from "react";
|
||||||
import useUser from "../hooks/useUser";
|
import useUser from "../hooks/useUser";
|
||||||
|
|
||||||
export const LanguageContext = createContext();
|
export const LanguageContext = createContext();
|
||||||
|
|
||||||
export const LanguageProvider = ({ children }) => {
|
export const LanguageProvider = ({children}) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const languageList = [
|
const languageList = [
|
||||||
{
|
|
||||||
key: "fa",
|
|
||||||
dir: "rtl",
|
|
||||||
name: "فارسی",
|
|
||||||
fontFamily: `IRANSans, sans-serif`,
|
|
||||||
tableLocalization: FA_DATATABLE_LOCALIZATION,
|
|
||||||
}
|
|
||||||
];
|
|
||||||
const { user, userChangedLanguage, changeLanguageState } = useUser();
|
|
||||||
const [languageIsReady, setLanguageIsReady] = useState(false);
|
|
||||||
const [languageApp, setLanguageApp] = useState();
|
|
||||||
const [directionApp, setDirectionApp] = useState(
|
|
||||||
process.env.NEXT_PUBLIC_DEFAULT_DIRECTION
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const lang = localStorage.getItem("_language");
|
|
||||||
|
|
||||||
if (!lang && !languageApp) {
|
|
||||||
setLanguageApp(process.env.NEXT_PUBLIC_DEFAULT_LANGUAGE);
|
|
||||||
} else if (lang) {
|
|
||||||
setLanguageApp(lang);
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!languageApp) return;
|
|
||||||
|
|
||||||
const lang = localStorage.getItem("_language");
|
|
||||||
|
|
||||||
if (!lang) {
|
|
||||||
localStorage.setItem("_language", languageApp);
|
|
||||||
} else {
|
|
||||||
if (languageApp != lang) {
|
|
||||||
localStorage.setItem("_language", languageApp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [languageApp]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!router.isReady) return;
|
|
||||||
if (user.user_language) {
|
|
||||||
if (user.user_language != languageApp) {
|
|
||||||
setLanguageApp(user.user_language);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (languageApp != router.locale) {
|
|
||||||
router.replace(
|
|
||||||
{ pathname: router.pathname, query: router.query },
|
|
||||||
router.asPath,
|
|
||||||
{
|
{
|
||||||
locale: languageApp,
|
key: "fa",
|
||||||
|
dir: "rtl",
|
||||||
|
name: "فارسی",
|
||||||
|
fontFamily: `IRANSans, sans-serif`,
|
||||||
|
tableLocalization: FA_DATATABLE_LOCALIZATION,
|
||||||
}
|
}
|
||||||
);
|
];
|
||||||
return;
|
const {user, userChangedLanguage, changeLanguageState} = useUser();
|
||||||
}
|
const [languageIsReady, setLanguageIsReady] = useState(false);
|
||||||
for (const lang of languageList) {
|
const [languageApp, setLanguageApp] = useState();
|
||||||
if (languageApp != lang.key) continue;
|
const [directionApp, setDirectionApp] = useState(
|
||||||
setDirectionApp(lang.dir);
|
process.env.NEXT_PUBLIC_DEFAULT_DIRECTION
|
||||||
document.dir = lang.dir;
|
);
|
||||||
}
|
|
||||||
|
|
||||||
const timer = setTimeout(() => {
|
useEffect(() => {
|
||||||
changeLanguageState(false);
|
const lang = localStorage.getItem("_language");
|
||||||
setLanguageIsReady(true);
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
return () => {
|
if (!lang && !languageApp) {
|
||||||
clearTimeout(timer);
|
setLanguageApp(process.env.NEXT_PUBLIC_DEFAULT_LANGUAGE);
|
||||||
};
|
} else if (lang) {
|
||||||
}, [router.locale, router.isReady, userChangedLanguage, languageApp]);
|
setLanguageApp(lang);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
useEffect(() => {
|
||||||
<LanguageContext.Provider
|
if (!languageApp) return;
|
||||||
value={{
|
|
||||||
languageApp,
|
const lang = localStorage.getItem("_language");
|
||||||
setLanguageApp,
|
|
||||||
directionApp,
|
if (!lang) {
|
||||||
languageIsReady,
|
localStorage.setItem("_language", languageApp);
|
||||||
setLanguageIsReady,
|
} else {
|
||||||
languageList,
|
if (languageApp != lang) {
|
||||||
}}
|
localStorage.setItem("_language", languageApp);
|
||||||
>
|
}
|
||||||
{children}
|
}
|
||||||
</LanguageContext.Provider>
|
}, [languageApp]);
|
||||||
);
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!router.isReady) return;
|
||||||
|
if (user.user_language) {
|
||||||
|
if (user.user_language != languageApp) {
|
||||||
|
setLanguageApp(user.user_language);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (languageApp != router.locale) {
|
||||||
|
router.replace(
|
||||||
|
{pathname: router.pathname, query: router.query},
|
||||||
|
router.asPath,
|
||||||
|
{
|
||||||
|
locale: languageApp,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const lang of languageList) {
|
||||||
|
if (languageApp != lang.key) continue;
|
||||||
|
setDirectionApp(lang.dir);
|
||||||
|
document.dir = lang.dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
changeLanguageState(false);
|
||||||
|
setLanguageIsReady(true);
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
clearTimeout(timer);
|
||||||
|
};
|
||||||
|
}, [router.locale, router.isReady, userChangedLanguage, languageApp]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LanguageContext.Provider
|
||||||
|
value={{
|
||||||
|
languageApp,
|
||||||
|
setLanguageApp,
|
||||||
|
directionApp,
|
||||||
|
languageIsReady,
|
||||||
|
setLanguageIsReady,
|
||||||
|
languageList,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</LanguageContext.Provider>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import LoadingHardPage from "@/core/components/LoadingHardPage";
|
import LoadingHardPage from "@/core/components/LoadingHardPage";
|
||||||
import { createContext, useState } from "react";
|
import {createContext, useState} from "react";
|
||||||
|
|
||||||
export const LoadingContext = createContext();
|
export const LoadingContext = createContext();
|
||||||
|
|
||||||
export const LoadingProvider = ({ children }) => {
|
export const LoadingProvider = ({children}) => {
|
||||||
const [loadingPage, setLoadingPage] = useState(false);
|
const [loadingPage, setLoadingPage] = useState(false);
|
||||||
return (
|
return (
|
||||||
<LoadingContext.Provider value={{ loadingPage, setLoadingPage }}>
|
<LoadingContext.Provider value={{loadingPage, setLoadingPage}}>
|
||||||
<LoadingHardPage loading={loadingPage} />
|
<LoadingHardPage loading={loadingPage}/>
|
||||||
{children}
|
{children}
|
||||||
</LoadingContext.Provider>
|
</LoadingContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,124 +1,122 @@
|
|||||||
import {
|
import {GET_USER_ROUTE} from "@/core/data/apiRoutes";
|
||||||
GET_USER_ROUTE,
|
|
||||||
SET_LANGUAGE
|
|
||||||
} from "@/core/data/apiRoutes";
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { createContext, useCallback, useEffect, useReducer } from "react";
|
import {createContext, useCallback, useEffect, useReducer} from "react";
|
||||||
|
|
||||||
const initialUser = {
|
const initialUser = {
|
||||||
isAuth: false,
|
isAuth: false,
|
||||||
userChangedLanguage: false,
|
userChangedLanguage: false,
|
||||||
token: null,
|
token: null,
|
||||||
user: {},
|
user: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
const reducer = (state, action) => {
|
const reducer = (state, action) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case "CLEAR_USER":
|
case "CLEAR_USER":
|
||||||
return { ...state, user: {} };
|
return {...state, user: {}};
|
||||||
case "CHANGE_USER":
|
case "CHANGE_USER":
|
||||||
return { ...state, user: action.user };
|
return {...state, user: action.user};
|
||||||
case "CHANGE_USER_LANGUAGE":
|
case "CHANGE_USER_LANGUAGE":
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
user: { ...state.user, user_language: action.language },
|
user: {...state.user, user_language: action.language},
|
||||||
};
|
};
|
||||||
case "CHANGE_AUTH_STATE":
|
case "CHANGE_AUTH_STATE":
|
||||||
return { ...state, isAuth: action.isAuth };
|
return {...state, isAuth: action.isAuth};
|
||||||
case "CHANGE_LANGUAGE_STATE":
|
case "CHANGE_LANGUAGE_STATE":
|
||||||
return { ...state, userChangedLanguage: action.userChangedLanguage };
|
return {...state, userChangedLanguage: action.userChangedLanguage};
|
||||||
case "CLEAR_TOKEN":
|
case "CLEAR_TOKEN":
|
||||||
localStorage.removeItem("_token");
|
localStorage.removeItem("_token");
|
||||||
return { ...state, token: null };
|
return {...state, token: null};
|
||||||
case "SET_TOKEN":
|
case "SET_TOKEN":
|
||||||
localStorage.setItem("_token", action.token);
|
localStorage.setItem("_token", action.token);
|
||||||
return { ...state, token: action.token };
|
return {...state, token: action.token};
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const UserContext = createContext();
|
export const UserContext = createContext();
|
||||||
|
|
||||||
export const UserProvider = ({ children }) => {
|
export const UserProvider = ({children}) => {
|
||||||
const [state, dispatch] = useReducer(reducer, initialUser);
|
const [state, dispatch] = useReducer(reducer, initialUser);
|
||||||
|
|
||||||
const clearUser = useCallback(() => {
|
const clearUser = useCallback(() => {
|
||||||
dispatch({ type: "CLEAR_USER" });
|
dispatch({type: "CLEAR_USER"});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const changeUser = useCallback((user) => {
|
const changeUser = useCallback((user) => {
|
||||||
dispatch({ type: "CHANGE_USER", user });
|
dispatch({type: "CHANGE_USER", user});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const changeUserLanguage = useCallback(/* use in multi language app */);
|
const changeUserLanguage = useCallback(/* use in multi language app */);
|
||||||
|
|
||||||
const changeAuthState = useCallback((isAuth) => {
|
const changeAuthState = useCallback((isAuth) => {
|
||||||
dispatch({ type: "CHANGE_AUTH_STATE", isAuth });
|
dispatch({type: "CHANGE_AUTH_STATE", isAuth});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const changeLanguageState = useCallback((userChangedLanguage) => {
|
const changeLanguageState = useCallback((userChangedLanguage) => {
|
||||||
dispatch({ type: "CHANGE_LANGUAGE_STATE", userChangedLanguage });
|
dispatch({type: "CHANGE_LANGUAGE_STATE", userChangedLanguage});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const clearToken = useCallback(() => {
|
const clearToken = useCallback(() => {
|
||||||
dispatch({ type: "CLEAR_TOKEN" });
|
dispatch({type: "CLEAR_TOKEN"});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const setToken = useCallback((token) => {
|
const setToken = useCallback((token) => {
|
||||||
dispatch({ type: "SET_TOKEN", token });
|
dispatch({type: "SET_TOKEN", token});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const getUser = useCallback(
|
const getUser = useCallback(
|
||||||
(callback = () => {}) => {
|
(callback = () => {
|
||||||
axios
|
}) => {
|
||||||
.get(GET_USER_ROUTE, {
|
axios
|
||||||
headers: { authorization: `Bearer ${state.token}` },
|
.get(GET_USER_ROUTE, {
|
||||||
})
|
headers: {authorization: `Bearer ${state.token}`},
|
||||||
.then(({ data }) => {
|
})
|
||||||
if (typeof callback === "function") callback(data);
|
.then(({data}) => {
|
||||||
|
if (typeof callback === "function") callback(data);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[state.token]
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const localToken = localStorage.getItem("_token");
|
||||||
|
if (localToken) dispatch({type: "SET_TOKEN", token: localToken});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!state.token) {
|
||||||
|
clearUser();
|
||||||
|
changeAuthState(false);
|
||||||
|
changeLanguageState(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getUser((data) => {
|
||||||
|
changeUser(data);
|
||||||
|
changeAuthState(true);
|
||||||
|
changeLanguageState(true);
|
||||||
});
|
});
|
||||||
},
|
}, [state.token]);
|
||||||
[state.token]
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
return (
|
||||||
const localToken = localStorage.getItem("_token");
|
<UserContext.Provider
|
||||||
if (localToken) dispatch({ type: "SET_TOKEN", token: localToken });
|
value={{
|
||||||
}, []);
|
isAuth: state.isAuth,
|
||||||
|
userChangedLanguage: state.userChangedLanguage,
|
||||||
useEffect(() => {
|
token: state.token,
|
||||||
if (!state.token) {
|
user: state.user,
|
||||||
clearUser();
|
getUser,
|
||||||
changeAuthState(false);
|
clearUser,
|
||||||
changeLanguageState(false);
|
changeUser,
|
||||||
return;
|
changeUserLanguage,
|
||||||
}
|
changeAuthState,
|
||||||
getUser((data) => {
|
changeLanguageState,
|
||||||
changeUser(data);
|
clearToken,
|
||||||
changeAuthState(true);
|
setToken,
|
||||||
changeLanguageState(true);
|
}}
|
||||||
});
|
>
|
||||||
}, [state.token]);
|
{children}
|
||||||
|
</UserContext.Provider>
|
||||||
return (
|
);
|
||||||
<UserContext.Provider
|
|
||||||
value={{
|
|
||||||
isAuth: state.isAuth,
|
|
||||||
userChangedLanguage: state.userChangedLanguage,
|
|
||||||
token: state.token,
|
|
||||||
user: state.user,
|
|
||||||
getUser,
|
|
||||||
clearUser,
|
|
||||||
changeUser,
|
|
||||||
changeUserLanguage,
|
|
||||||
changeAuthState,
|
|
||||||
changeLanguageState,
|
|
||||||
clearToken,
|
|
||||||
setToken,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</UserContext.Provider>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,113 +1,113 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { useCallback, useContext, useReducer, useState } from "react";
|
import {useCallback, useContext, useReducer, useState} from "react";
|
||||||
import { ReloadDataTableContext } from "../contexts/ReloadDatatableContext";
|
import {ReloadDataTableContext} from "../contexts/ReloadDatatableContext";
|
||||||
import useUser from "./useUser";
|
import useUser from "./useUser";
|
||||||
import Notifications from "@/core/components/notifications";
|
import Notifications from "@/core/components/notifications";
|
||||||
import useDirection from "./useDirection";
|
import useDirection from "./useDirection";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
|
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
url: "",
|
url: "",
|
||||||
rowID: "",
|
rowID: "",
|
||||||
values: {},
|
values: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
const reducer = (state, action) => {
|
const reducer = (state, action) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case "CONFIRM_DATA":
|
case "CONFIRM_DATA":
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
url: action.url,
|
url: action.url,
|
||||||
rowID: action.rowID,
|
rowID: action.rowID,
|
||||||
};
|
};
|
||||||
case "REJECT_DATA":
|
case "REJECT_DATA":
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
url: action.url,
|
url: action.url,
|
||||||
rowID: action.rowID,
|
rowID: action.rowID,
|
||||||
values: {},
|
values: {},
|
||||||
};
|
};
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const useDataTable = () => {
|
const useDataTable = () => {
|
||||||
const { setReloadDataTable } = useContext(ReloadDataTableContext);
|
const {setReloadDataTable} = useContext(ReloadDataTableContext);
|
||||||
const [state, dispatch] = useReducer(reducer, initialValues);
|
const [state, dispatch] = useReducer(reducer, initialValues);
|
||||||
const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
|
const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
|
||||||
const [openRejectDialog, setOpenRejectDialog] = useState(false);
|
const [openRejectDialog, setOpenRejectDialog] = useState(false);
|
||||||
const [rowId, setRowId] = useState(null);
|
const [rowId, setRowId] = useState(null);
|
||||||
const { directionApp } = useDirection();
|
const {directionApp} = useDirection();
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
|
|
||||||
const { token } = useUser();
|
const {token} = useUser();
|
||||||
|
|
||||||
const confirmData = useCallback(async (url, rowID, values) => {
|
const confirmData = useCallback(async (url, rowID, values) => {
|
||||||
dispatch({ type: "CONFIRM_DATA", url: url, rowID: rowID, values: values });
|
dispatch({type: "CONFIRM_DATA", url: url, rowID: rowID, values: values});
|
||||||
axios
|
axios
|
||||||
.post(`${url}/${rowID}`, values, {
|
.post(`${url}/${rowID}`, values, {
|
||||||
headers: { authorization: `Bearer ${token}` },
|
headers: {authorization: `Bearer ${token}`},
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
setReloadDataTable(true);
|
setReloadDataTable(true);
|
||||||
Notifications(directionApp, response, t);
|
Notifications(directionApp, response, t);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
Notifications(directionApp, error.response, t);
|
Notifications(directionApp, error.response, t);
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const rejectData = useCallback(async (url, rowID, values) => {
|
const rejectData = useCallback(async (url, rowID, values) => {
|
||||||
dispatch({ type: "REJECT_DATA", url: url, rowID: rowID, values: values });
|
dispatch({type: "REJECT_DATA", url: url, rowID: rowID, values: values});
|
||||||
axios
|
axios
|
||||||
.post(`${url}/${rowID}`, values, {
|
.post(`${url}/${rowID}`, values, {
|
||||||
headers: { authorization: `Bearer ${token}` },
|
headers: {authorization: `Bearer ${token}`},
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
setReloadDataTable(true);
|
setReloadDataTable(true);
|
||||||
Notifications(directionApp, response, t);
|
Notifications(directionApp, response, t);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
Notifications(directionApp, error.response, t);
|
Notifications(directionApp, error.response, t);
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
//Confirm Data
|
//Confirm Data
|
||||||
const handleOpenConfirmDialog = (row) => {
|
const handleOpenConfirmDialog = (row) => {
|
||||||
setRowId(row.getValue("id"));
|
setRowId(row.getValue("id"));
|
||||||
setOpenConfirmDialog(true);
|
setOpenConfirmDialog(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCloseConfirmDialog = () => {
|
const handleCloseConfirmDialog = () => {
|
||||||
setOpenConfirmDialog(false);
|
setOpenConfirmDialog(false);
|
||||||
};
|
};
|
||||||
//End Confirm Data
|
//End Confirm Data
|
||||||
|
|
||||||
// Reject Data
|
// Reject Data
|
||||||
const handleOpenRejectDialog = (row) => {
|
const handleOpenRejectDialog = (row) => {
|
||||||
setRowId(row.getValue("id"));
|
setRowId(row.getValue("id"));
|
||||||
setOpenRejectDialog(true);
|
setOpenRejectDialog(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCloseRejectDialog = () => {
|
const handleCloseRejectDialog = () => {
|
||||||
setOpenRejectDialog(false);
|
setOpenRejectDialog(false);
|
||||||
};
|
};
|
||||||
// End Reject Data
|
// End Reject Data
|
||||||
|
|
||||||
const contextValue = {
|
const contextValue = {
|
||||||
handleOpenConfirmDialog,
|
handleOpenConfirmDialog,
|
||||||
handleCloseConfirmDialog,
|
handleCloseConfirmDialog,
|
||||||
handleOpenRejectDialog,
|
handleOpenRejectDialog,
|
||||||
handleCloseRejectDialog,
|
handleCloseRejectDialog,
|
||||||
rowId,
|
rowId,
|
||||||
openConfirmDialog,
|
openConfirmDialog,
|
||||||
openRejectDialog,
|
openRejectDialog,
|
||||||
rejectData,
|
rejectData,
|
||||||
confirmData,
|
confirmData,
|
||||||
};
|
};
|
||||||
return contextValue;
|
return contextValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useDataTable;
|
export default useDataTable;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { useContext } from "react";
|
import {useContext} from "react";
|
||||||
import { LanguageContext } from "../contexts/language";
|
import {LanguageContext} from "../contexts/language";
|
||||||
|
|
||||||
const useDirection = () => {
|
const useDirection = () => {
|
||||||
const { directionApp } = useContext(LanguageContext);
|
const {directionApp} = useContext(LanguageContext);
|
||||||
|
|
||||||
return { directionApp };
|
return {directionApp};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useDirection;
|
export default useDirection;
|
||||||
|
|||||||
@@ -1,28 +1,28 @@
|
|||||||
import { useContext } from "react";
|
import {useContext} from "react";
|
||||||
import { LanguageContext } from "../contexts/language";
|
import {LanguageContext} from "../contexts/language";
|
||||||
import useUser from "./useUser";
|
import useUser from "./useUser";
|
||||||
|
|
||||||
const useLanguage = () => {
|
const useLanguage = () => {
|
||||||
const { isAuth, changeUserLanguage } = useUser();
|
const {isAuth, changeUserLanguage} = useUser();
|
||||||
const {
|
const {
|
||||||
languageApp,
|
languageApp,
|
||||||
setLanguageApp,
|
setLanguageApp,
|
||||||
languageIsReady,
|
languageIsReady,
|
||||||
setLanguageIsReady,
|
setLanguageIsReady,
|
||||||
languageList,
|
languageList,
|
||||||
} = useContext(LanguageContext);
|
} = useContext(LanguageContext);
|
||||||
|
|
||||||
const changeLanguage = (lang) => {
|
const changeLanguage = (lang) => {
|
||||||
if (lang == languageApp) return;
|
if (lang == languageApp) return;
|
||||||
|
|
||||||
setLanguageIsReady(false);
|
setLanguageIsReady(false);
|
||||||
setLanguageApp(lang);
|
setLanguageApp(lang);
|
||||||
if (isAuth) {
|
if (isAuth) {
|
||||||
changeUserLanguage(lang);
|
changeUserLanguage(lang);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return { languageApp, changeLanguage, languageIsReady, languageList };
|
return {languageApp, changeLanguage, languageIsReady, languageList};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useLanguage;
|
export default useLanguage;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { useContext } from "react";
|
import {useContext} from "react";
|
||||||
import { LoadingContext } from "../contexts/loading";
|
import {LoadingContext} from "../contexts/loading";
|
||||||
|
|
||||||
const useLoading = () => {
|
const useLoading = () => {
|
||||||
const { setLoadingPage } = useContext(LoadingContext);
|
const {setLoadingPage} = useContext(LoadingContext);
|
||||||
|
|
||||||
return { setLoadingPage };
|
return {setLoadingPage};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useLoading;
|
export default useLoading;
|
||||||
|
|||||||
@@ -1,34 +1,34 @@
|
|||||||
import { useContext } from "react";
|
import {useContext} from "react";
|
||||||
import { UserContext } from "../contexts/user";
|
import {UserContext} from "../contexts/user";
|
||||||
|
|
||||||
const useUser = () => {
|
const useUser = () => {
|
||||||
const {
|
const {
|
||||||
isAuth,
|
isAuth,
|
||||||
userChangedLanguage,
|
userChangedLanguage,
|
||||||
token,
|
token,
|
||||||
user,
|
user,
|
||||||
getUser,
|
getUser,
|
||||||
clearUser,
|
clearUser,
|
||||||
changeUser,
|
changeUser,
|
||||||
changeAuthState,
|
changeAuthState,
|
||||||
changeLanguageState,
|
changeLanguageState,
|
||||||
clearToken,
|
clearToken,
|
||||||
setToken,
|
setToken,
|
||||||
} = useContext(UserContext);
|
} = useContext(UserContext);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isAuth,
|
isAuth,
|
||||||
userChangedLanguage,
|
userChangedLanguage,
|
||||||
token,
|
token,
|
||||||
user,
|
user,
|
||||||
getUser,
|
getUser,
|
||||||
clearUser,
|
clearUser,
|
||||||
changeUser,
|
changeUser,
|
||||||
changeAuthState,
|
changeAuthState,
|
||||||
changeLanguageState,
|
changeLanguageState,
|
||||||
clearToken,
|
clearToken,
|
||||||
setToken,
|
setToken,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useUser;
|
export default useUser;
|
||||||
|
|||||||
@@ -1,43 +1,43 @@
|
|||||||
import { NextLinkComposed } from "@/core/components/LinkRouting";
|
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
||||||
import Message from "@/core/components/Messages";
|
import Message from "@/core/components/Messages";
|
||||||
import useUser from "@/lib/app/hooks/useUser";
|
import useUser from "@/lib/app/hooks/useUser";
|
||||||
import { Button, Typography } from "@mui/material";
|
import {Button, Typography} from "@mui/material";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
|
|
||||||
const RolePermission = ({ children, requiredPermissions }) => {
|
const RolePermission = ({children, requiredPermissions}) => {
|
||||||
const { user } = useUser();
|
const {user} = useUser();
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
|
|
||||||
const hasPermission = requiredPermissions.some((permission) =>
|
const hasPermission = requiredPermissions.some((permission) =>
|
||||||
user?.role?.includes(permission)
|
user?.role?.includes(permission)
|
||||||
);
|
|
||||||
|
|
||||||
if (!hasPermission) {
|
|
||||||
return (
|
|
||||||
<Message
|
|
||||||
text={
|
|
||||||
<Typography sx={{ textAlign: "center" }}>
|
|
||||||
{t("Permission.typography_you_dont_have_access")}
|
|
||||||
</Typography>
|
|
||||||
}
|
|
||||||
actions={
|
|
||||||
<>
|
|
||||||
<Button
|
|
||||||
variant="contained"
|
|
||||||
component={NextLinkComposed}
|
|
||||||
to={{
|
|
||||||
pathname: "/dashboard",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t("Permission.button_back_dashboard")}
|
|
||||||
</Button>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
return <>{children}</>;
|
if (!hasPermission) {
|
||||||
|
return (
|
||||||
|
<Message
|
||||||
|
text={
|
||||||
|
<Typography sx={{textAlign: "center"}}>
|
||||||
|
{t("Permission.typography_you_dont_have_access")}
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
|
actions={
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
component={NextLinkComposed}
|
||||||
|
to={{
|
||||||
|
pathname: "/dashboard",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("Permission.button_back_dashboard")}
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <>{children}</>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default RolePermission;
|
export default RolePermission;
|
||||||
|
|||||||
@@ -1,42 +1,42 @@
|
|||||||
import { NextLinkComposed } from "@/core/components/LinkRouting";
|
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
||||||
import Message from "@/core/components/Messages";
|
import Message from "@/core/components/Messages";
|
||||||
import useUser from "@/lib/app/hooks/useUser";
|
import useUser from "@/lib/app/hooks/useUser";
|
||||||
import { Button, Typography } from "@mui/material";
|
import {Button, Typography} from "@mui/material";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import { useRouter } from "next/router";
|
import {useRouter} from "next/router";
|
||||||
|
|
||||||
const WithAuthMiddleware = ({ children }) => {
|
const WithAuthMiddleware = ({children}) => {
|
||||||
const { isAuth } = useUser();
|
const {isAuth} = useUser();
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
if (!isAuth)
|
if (!isAuth)
|
||||||
return (
|
return (
|
||||||
<Message
|
<Message
|
||||||
text={
|
text={
|
||||||
<Typography sx={{ textAlign: "center" }}>
|
<Typography sx={{textAlign: "center"}}>
|
||||||
{t(
|
{t(
|
||||||
"Authorization.typography_your_access_to_this_page_has_expired_Please_login_again"
|
"Authorization.typography_your_access_to_this_page_has_expired_Please_login_again"
|
||||||
)}
|
)}
|
||||||
</Typography>
|
</Typography>
|
||||||
}
|
}
|
||||||
actions={
|
actions={
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
component={NextLinkComposed}
|
component={NextLinkComposed}
|
||||||
to={{
|
to={{
|
||||||
pathname: "/login-expert",
|
pathname: "/login-expert",
|
||||||
query: { back_url: encodeURIComponent(router.asPath) },
|
query: {back_url: encodeURIComponent(router.asPath)},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t("login")}
|
{t("login")}
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
return <>{children}</>;
|
return <>{children}</>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default WithAuthMiddleware;
|
export default WithAuthMiddleware;
|
||||||
|
|||||||
@@ -1,56 +1,56 @@
|
|||||||
import Message from "@/core/components/Messages";
|
import Message from "@/core/components/Messages";
|
||||||
import useUser from "@/lib/app/hooks/useUser";
|
import useUser from "@/lib/app/hooks/useUser";
|
||||||
import { Stack, Typography } from "@mui/material";
|
import {Stack, Typography} from "@mui/material";
|
||||||
import { useTranslations } from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import { useSearchParams } from "next/navigation";
|
import {useSearchParams} from "next/navigation";
|
||||||
import { useRouter } from "next/router";
|
import {useRouter} from "next/router";
|
||||||
import { useEffect } from "react";
|
import {useEffect} from "react";
|
||||||
|
|
||||||
const WithoutAuthMiddleware = ({ children }) => {
|
const WithoutAuthMiddleware = ({children}) => {
|
||||||
const { isAuth } = useUser();
|
const {isAuth} = useUser();
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
// gettin url query
|
// gettin url query
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const backUrlDecodedPath = searchParams.get("back_url");
|
const backUrlDecodedPath = searchParams.get("back_url");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isAuth) return;
|
if (!isAuth) return;
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
router.replace(
|
router.replace(
|
||||||
backUrlDecodedPath
|
backUrlDecodedPath
|
||||||
? decodeURIComponent(backUrlDecodedPath)
|
? decodeURIComponent(backUrlDecodedPath)
|
||||||
: "/dashboard"
|
: "/dashboard"
|
||||||
);
|
);
|
||||||
}, 2000);
|
}, 2000);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
clearTimeout(timer);
|
clearTimeout(timer);
|
||||||
};
|
};
|
||||||
}, [isAuth]);
|
}, [isAuth]);
|
||||||
|
|
||||||
if (isAuth)
|
if (isAuth)
|
||||||
return (
|
return (
|
||||||
<Message
|
<Message
|
||||||
text={
|
text={
|
||||||
<Stack alignItems="center" spacing={2}>
|
<Stack alignItems="center" spacing={2}>
|
||||||
<Typography sx={{ textAlign: "center" }}>
|
<Typography sx={{textAlign: "center"}}>
|
||||||
{t(
|
{t(
|
||||||
"Authorization.typography_your_login_is_valid_and_you_do_not_need_to_login_again"
|
"Authorization.typography_your_login_is_valid_and_you_do_not_need_to_login_again"
|
||||||
)}
|
)}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography>
|
<Typography>
|
||||||
{t("Authorization.typography_redirect_to")}{" "}
|
{t("Authorization.typography_redirect_to")}{" "}
|
||||||
{backUrlDecodedPath
|
{backUrlDecodedPath
|
||||||
? t("Authorization.typography_routing_previuos_page")
|
? t("Authorization.typography_routing_previuos_page")
|
||||||
: t("Authorization.typography_routing_dashbaord_page")}
|
: t("Authorization.typography_routing_dashbaord_page")}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Stack>
|
</Stack>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
return <>{children}</>;
|
return <>{children}</>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default WithoutAuthMiddleware;
|
export default WithoutAuthMiddleware;
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
import "&/fontiran.scss";
|
import "&/fontiran.scss";
|
||||||
import AppLayout from "@/layouts/AppLayout";
|
import AppLayout from "@/layouts/AppLayout";
|
||||||
import MuiLayout from "@/layouts/MuiLayout";
|
import MuiLayout from "@/layouts/MuiLayout";
|
||||||
import { LanguageProvider } from "@/lib/app/contexts/language";
|
import {LanguageProvider} from "@/lib/app/contexts/language";
|
||||||
import { LoadingProvider } from "@/lib/app/contexts/loading";
|
import {LoadingProvider} from "@/lib/app/contexts/loading";
|
||||||
import { UserProvider } from "@/lib/app/contexts/user";
|
import {UserProvider} from "@/lib/app/contexts/user";
|
||||||
import "moment/locale/fa";
|
import "moment/locale/fa";
|
||||||
import { NextIntlProvider } from "next-intl";
|
import {NextIntlProvider} from "next-intl";
|
||||||
|
|
||||||
const App = ({ Component, pageProps }) => {
|
const App = ({Component, pageProps}) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<UserProvider>
|
<UserProvider>
|
||||||
<LanguageProvider>
|
<LanguageProvider>
|
||||||
<NextIntlProvider messages={pageProps.messages}>
|
<NextIntlProvider messages={pageProps.messages}>
|
||||||
<MuiLayout isBot={pageProps.isBot}>
|
<MuiLayout isBot={pageProps.isBot}>
|
||||||
<LoadingProvider>
|
<LoadingProvider>
|
||||||
<AppLayout isBot={pageProps.isBot}>
|
<AppLayout isBot={pageProps.isBot}>
|
||||||
<Component {...pageProps} />
|
<Component {...pageProps} />
|
||||||
</AppLayout>
|
</AppLayout>
|
||||||
</LoadingProvider>
|
</LoadingProvider>
|
||||||
</MuiLayout>
|
</MuiLayout>
|
||||||
</NextIntlProvider>
|
</NextIntlProvider>
|
||||||
</LanguageProvider>
|
</LanguageProvider>
|
||||||
</UserProvider>
|
</UserProvider>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|||||||
@@ -1,67 +1,65 @@
|
|||||||
import {
|
import {createEmotionCacheLtr} from "@/core/utils/createEmotionCache";
|
||||||
createEmotionCacheLtr
|
|
||||||
} from "@/core/utils/createEmotionCache";
|
|
||||||
import theme from "@/core/utils/theme";
|
import theme from "@/core/utils/theme";
|
||||||
import createEmotionServer from "@emotion/server/create-instance";
|
import createEmotionServer from "@emotion/server/create-instance";
|
||||||
import Document, { Head, Html, Main, NextScript } from "next/document";
|
import Document, {Head, Html, Main, NextScript} from "next/document";
|
||||||
|
|
||||||
export default function MyDocument(props) {
|
export default function MyDocument(props) {
|
||||||
const { emotionStyleTags } = props;
|
const {emotionStyleTags} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Html>
|
<Html>
|
||||||
<Head>
|
<Head>
|
||||||
<meta name="theme-color" content={theme.palette.primary.main} />
|
<meta name="theme-color" content={theme.palette.primary.main}/>
|
||||||
<meta name="emotion-insertion-point" content="" />
|
<meta name="emotion-insertion-point" content=""/>
|
||||||
<link rel="shortcut icon" href="/icons/favicon.ico" />
|
<link rel="shortcut icon" href="/icons/favicon.ico"/>
|
||||||
<link rel="manifest" href="/manifest.json" />
|
<link rel="manifest" href="/manifest.json"/>
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
|
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
|
||||||
/>
|
/>
|
||||||
{emotionStyleTags}
|
{emotionStyleTags}
|
||||||
</Head>
|
</Head>
|
||||||
<body>
|
<body>
|
||||||
<Main />
|
<Main/>
|
||||||
<NextScript />
|
<NextScript/>
|
||||||
</body>
|
</body>
|
||||||
</Html>
|
</Html>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
MyDocument.getInitialProps = async (ctx) => {
|
MyDocument.getInitialProps = async (ctx) => {
|
||||||
const originalRenderPage = ctx.renderPage;
|
const originalRenderPage = ctx.renderPage;
|
||||||
let cache;
|
let cache;
|
||||||
switch (ctx.locale) {
|
switch (ctx.locale) {
|
||||||
case "fa":
|
case "fa":
|
||||||
cache = createEmotionCacheLtr();
|
cache = createEmotionCacheLtr();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { extractCriticalToChunks } = createEmotionServer(cache);
|
const {extractCriticalToChunks} = createEmotionServer(cache);
|
||||||
|
|
||||||
ctx.renderPage = () =>
|
ctx.renderPage = () =>
|
||||||
originalRenderPage({
|
originalRenderPage({
|
||||||
enhanceApp: (App) =>
|
enhanceApp: (App) =>
|
||||||
function EnhanceApp(props) {
|
function EnhanceApp(props) {
|
||||||
return <App emotionCache={cache} {...props} />;
|
return <App emotionCache={cache} {...props} />;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const initialProps = await Document.getInitialProps(ctx);
|
const initialProps = await Document.getInitialProps(ctx);
|
||||||
|
|
||||||
const emotionStyles = extractCriticalToChunks(initialProps.html);
|
const emotionStyles = extractCriticalToChunks(initialProps.html);
|
||||||
const emotionStyleTags = emotionStyles.styles.map((style) => (
|
const emotionStyleTags = emotionStyles.styles.map((style) => (
|
||||||
<style
|
<style
|
||||||
data-emotion={`${style.key} ${style.ids.join(" ")}`}
|
data-emotion={`${style.key} ${style.ids.join(" ")}`}
|
||||||
key={style.key}
|
key={style.key}
|
||||||
// eslint-disable-next-line react/no-danger
|
// eslint-disable-next-line react/no-danger
|
||||||
dangerouslySetInnerHTML={{ __html: style.css }}
|
dangerouslySetInnerHTML={{__html: style.css}}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...initialProps,
|
...initialProps,
|
||||||
emotionStyleTags,
|
emotionStyleTags,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
import DashboardChangePasswordComponent from "@/components/dashboard/change-password";
|
import DashboardChangePasswordComponent from "@/components/dashboard/change-password";
|
||||||
import TitlePage from "@/core/components/TitlePage";
|
import TitlePage from "@/core/components/TitlePage";
|
||||||
import WithAuthMiddleware from "@/middlewares/WithAuth";
|
import WithAuthMiddleware from "@/middlewares/WithAuth";
|
||||||
import { parse } from "next-useragent";
|
import {parse} from "next-useragent";
|
||||||
|
|
||||||
export default function LoanFollowUp() {
|
export default function LoanFollowUp() {
|
||||||
return (
|
return (
|
||||||
<WithAuthMiddleware>
|
<WithAuthMiddleware>
|
||||||
<TitlePage text="Dashboard.change_password" />
|
<TitlePage text="Dashboard.change_password"/>
|
||||||
<DashboardChangePasswordComponent />
|
<DashboardChangePasswordComponent/>
|
||||||
</WithAuthMiddleware>
|
</WithAuthMiddleware>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getServerSideProps({ req, locale }) {
|
export async function getServerSideProps({req, locale}) {
|
||||||
const { isBot } = parse(req.headers["user-agent"]);
|
const {isBot} = parse(req.headers["user-agent"]);
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||||
isBot,
|
isBot,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
import DashboardEditProfile from "@/components/dashboard/edit-profile";
|
import DashboardEditProfile from "@/components/dashboard/edit-profile";
|
||||||
import TitlePage from "@/core/components/TitlePage";
|
import TitlePage from "@/core/components/TitlePage";
|
||||||
import WithAuthMiddleware from "@/middlewares/WithAuth";
|
import WithAuthMiddleware from "@/middlewares/WithAuth";
|
||||||
import { parse } from "next-useragent";
|
import {parse} from "next-useragent";
|
||||||
|
|
||||||
export default function LoanFollowUp() {
|
export default function LoanFollowUp() {
|
||||||
return (
|
return (
|
||||||
<WithAuthMiddleware>
|
<WithAuthMiddleware>
|
||||||
<TitlePage text="Dashboard.edit_profile" />
|
<TitlePage text="Dashboard.edit_profile"/>
|
||||||
<DashboardEditProfile />
|
<DashboardEditProfile/>
|
||||||
</WithAuthMiddleware>
|
</WithAuthMiddleware>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getServerSideProps({ req, locale }) {
|
export async function getServerSideProps({req, locale}) {
|
||||||
const { isBot } = parse(req.headers["user-agent"]);
|
const {isBot} = parse(req.headers["user-agent"]);
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
messages: (await import(`&/locales/${locale}/app.json`)).default,
|
||||||
isBot,
|
isBot,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||