diff --git a/.env.development b/.env.development
index 99122df..c8d3730 100644
--- a/.env.development
+++ b/.env.development
@@ -1 +1,2 @@
-NEXT_PUBLIC_API_URL='https://api-silos-kpr.basys.co.id'
+//NEXT_PUBLIC_API_URL='https://api-silos-kpr.basys.co.id'
+NEXT_PUBLIC_API_URL='https://digital-attendance-api.basys.co.id'
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index b85812c..3f2d088 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,6 +10,8 @@
"dependencies": {
"@ant-design/icons": "^5.3.0",
"antd": "^5.12.5",
+ "aos": "^3.0.0-beta.6",
+ "apexcharts": "^3.49.1",
"cookies-next": "^4.1.1",
"dayjs": "^1.11.10",
"docxtemplater": "^3.40.0",
@@ -22,16 +24,15 @@
"next": "14.2.15",
"next-image-export-optimizer": "^1.12.3",
"next-pwa": "^5.6.0",
- "nextjs-toploader": "^1.6.6",
+ "nextjs-toploader": "^1.6.12",
"react": "^18",
+ "react-apexcharts": "^1.4.1",
"react-dom": "^18",
"react-hook-form": "^7.45.4",
"react-query": "^3.39.3",
"sass": "^1.69.5",
"styled-components": "^5.3.9",
"uuid": "^10.0.0",
- "zingchart": "^2.9.14",
- "zingchart-react": "^3.2.0",
"zustand": "^4.4.7"
},
"devDependencies": {
@@ -3293,6 +3294,11 @@
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
"peer": true
},
+ "node_modules/@yr/monotone-cubic-spline": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz",
+ "integrity": "sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA=="
+ },
"node_modules/acorn": {
"version": "8.13.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz",
@@ -3432,6 +3438,30 @@
"react-dom": ">=16.9.0"
}
},
+ "node_modules/aos": {
+ "version": "3.0.0-beta.6",
+ "resolved": "https://registry.npmjs.org/aos/-/aos-3.0.0-beta.6.tgz",
+ "integrity": "sha512-VLWrpq8bfAWcetynVHMMrqdC+89Qq/Ym6UBJbHB4crIwp3RR8uq1dNGgsFzoDl03S43rlVMK+na3r5+oUCZsYw==",
+ "dependencies": {
+ "classlist-polyfill": "^1.2.0",
+ "lodash.debounce": "^4.0.8",
+ "lodash.throttle": "^4.1.1"
+ }
+ },
+ "node_modules/apexcharts": {
+ "version": "3.54.1",
+ "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.54.1.tgz",
+ "integrity": "sha512-E4et0h/J1U3r3EwS/WlqJCQIbepKbp6wGUmaAwJOMjHUP4Ci0gxanLa7FR3okx6p9coi4st6J853/Cb1NP0vpA==",
+ "dependencies": {
+ "@yr/monotone-cubic-spline": "^1.0.3",
+ "svg.draggable.js": "^2.2.2",
+ "svg.easing.js": "^2.0.0",
+ "svg.filter.js": "^2.0.2",
+ "svg.pathmorphing.js": "^0.1.3",
+ "svg.resize.js": "^1.4.3",
+ "svg.select.js": "^3.0.1"
+ }
+ },
"node_modules/archiver": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz",
@@ -4198,6 +4228,11 @@
"node": ">=6.0"
}
},
+ "node_modules/classlist-polyfill": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/classlist-polyfill/-/classlist-polyfill-1.2.0.tgz",
+ "integrity": "sha512-GzIjNdcEtH4ieA2S8NmrSxv7DfEV5fmixQeyTmqmRmRJPGpRBaSnA2a0VrCjyT8iW8JjEdMbKzDotAJf+ajgaQ=="
+ },
"node_modules/classnames": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
@@ -7138,6 +7173,11 @@
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
"integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA=="
},
+ "node_modules/lodash.throttle": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
+ "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ=="
+ },
"node_modules/lodash.union": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz",
@@ -8558,6 +8598,18 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-apexcharts": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/react-apexcharts/-/react-apexcharts-1.4.1.tgz",
+ "integrity": "sha512-G14nVaD64Bnbgy8tYxkjuXEUp/7h30Q0U33xc3AwtGFijJB9nHqOt1a6eG0WBn055RgRg+NwqbKGtqPxy15d0Q==",
+ "dependencies": {
+ "prop-types": "^15.8.1"
+ },
+ "peerDependencies": {
+ "apexcharts": "^3.41.0",
+ "react": ">=0.13"
+ }
+ },
"node_modules/react-dom": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
@@ -9651,6 +9703,89 @@
"node": ">=12.0.0"
}
},
+ "node_modules/svg.draggable.js": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/svg.draggable.js/-/svg.draggable.js-2.2.2.tgz",
+ "integrity": "sha512-JzNHBc2fLQMzYCZ90KZHN2ohXL0BQJGQimK1kGk6AvSeibuKcIdDX9Kr0dT9+UJ5O8nYA0RB839Lhvk4CY4MZw==",
+ "dependencies": {
+ "svg.js": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/svg.easing.js": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/svg.easing.js/-/svg.easing.js-2.0.0.tgz",
+ "integrity": "sha512-//ctPdJMGy22YoYGV+3HEfHbm6/69LJUTAqI2/5qBvaNHZ9uUFVC82B0Pl299HzgH13rKrBgi4+XyXXyVWWthA==",
+ "dependencies": {
+ "svg.js": ">=2.3.x"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/svg.filter.js": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/svg.filter.js/-/svg.filter.js-2.0.2.tgz",
+ "integrity": "sha512-xkGBwU+dKBzqg5PtilaTb0EYPqPfJ9Q6saVldX+5vCRy31P6TlRCP3U9NxH3HEufkKkpNgdTLBJnmhDHeTqAkw==",
+ "dependencies": {
+ "svg.js": "^2.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/svg.js": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/svg.js/-/svg.js-2.7.1.tgz",
+ "integrity": "sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA=="
+ },
+ "node_modules/svg.pathmorphing.js": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/svg.pathmorphing.js/-/svg.pathmorphing.js-0.1.3.tgz",
+ "integrity": "sha512-49HWI9X4XQR/JG1qXkSDV8xViuTLIWm/B/7YuQELV5KMOPtXjiwH4XPJvr/ghEDibmLQ9Oc22dpWpG0vUDDNww==",
+ "dependencies": {
+ "svg.js": "^2.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/svg.resize.js": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/svg.resize.js/-/svg.resize.js-1.4.3.tgz",
+ "integrity": "sha512-9k5sXJuPKp+mVzXNvxz7U0uC9oVMQrrf7cFsETznzUDDm0x8+77dtZkWdMfRlmbkEEYvUn9btKuZ3n41oNA+uw==",
+ "dependencies": {
+ "svg.js": "^2.6.5",
+ "svg.select.js": "^2.1.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/svg.resize.js/node_modules/svg.select.js": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-2.1.2.tgz",
+ "integrity": "sha512-tH6ABEyJsAOVAhwcCjF8mw4crjXSI1aa7j2VQR8ZuJ37H2MBUbyeqYr5nEO7sSN3cy9AR9DUwNg0t/962HlDbQ==",
+ "dependencies": {
+ "svg.js": "^2.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/svg.select.js": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-3.0.1.tgz",
+ "integrity": "sha512-h5IS/hKkuVCbKSieR9uQCj9w+zLHoPh+ce19bBYyqF53g6mnPB8sAtIbe1s9dh2S2fCmYX2xel1Ln3PJBbK4kw==",
+ "dependencies": {
+ "svg.js": "^2.6.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
"node_modules/tapable": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
@@ -10815,33 +10950,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/zingchart": {
- "version": "2.9.15",
- "resolved": "https://registry.npmjs.org/zingchart/-/zingchart-2.9.15.tgz",
- "integrity": "sha512-o0doeMS5VxL+TsQXzkZzNuMBHzlw7wCG/1TN/wAXhs2QOnABfGGz6g4TFx+EMzZYaTx0ZRKM8B+fSYTlHRDu0A=="
- },
- "node_modules/zingchart-constants": {
- "version": "1.0.5",
- "resolved": "git+ssh://git@github.com/zingchart/zingchart-constants.git#37aaeb291bbaab2174d317c1182bbca6a8f70da5",
- "license": "ISC"
- },
- "node_modules/zingchart-react": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/zingchart-react/-/zingchart-react-3.2.0.tgz",
- "integrity": "sha512-VTGhSBIUbbf5dLpVHxyoFRYB7rkx4umlhXKa6zJR0YjVu5tUE4pvogHu9lX5LjeTTXbPRW8quMqs+f+5d9juKw==",
- "dependencies": {
- "zingchart": "latest",
- "zingchart-constants": "github:zingchart/zingchart-constants#master"
- },
- "engines": {
- "node": ">=14",
- "npm": ">=5"
- },
- "peerDependencies": {
- "react": ">=15.0.0",
- "react-dom": ">=15.0.0"
- }
- },
"node_modules/zip-stream": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz",
diff --git a/package.json b/package.json
index db3d763..1634d1f 100644
--- a/package.json
+++ b/package.json
@@ -10,11 +10,9 @@
"export": "next build && next-image-export-optimizer"
},
"dependencies": {
- "react": "^18",
- "react-dom": "^18",
- "next": "14.2.15",
"@ant-design/icons": "^5.3.0",
"antd": "^5.12.5",
+ "aos": "^3.0.0-beta.6",
"cookies-next": "^4.1.1",
"dayjs": "^1.11.10",
"docxtemplater": "^3.40.0",
@@ -24,17 +22,20 @@
"html2canvas": "^1.4.1",
"jspdf": "^2.5.1",
"jspdf-autotable": "^3.8.2",
+ "next": "14.2.15",
"next-image-export-optimizer": "^1.12.3",
"next-pwa": "^5.6.0",
- "nextjs-toploader": "^1.6.6",
+ "nextjs-toploader": "^1.6.12",
+ "react": "^18",
+ "react-dom": "^18",
"react-hook-form": "^7.45.4",
"react-query": "^3.39.3",
"sass": "^1.69.5",
"styled-components": "^5.3.9",
"uuid": "^10.0.0",
"zustand": "^4.4.7",
- "zingchart": "^2.9.14",
- "zingchart-react": "^3.2.0"
+ "apexcharts": "^3.49.1",
+ "react-apexcharts": "^1.4.1"
},
"devDependencies": {
"eslint": "^8",
diff --git a/public/css/button.scss b/public/css/button.scss
index 1fe4ec8..6b31ec3 100644
--- a/public/css/button.scss
+++ b/public/css/button.scss
@@ -1,8 +1,8 @@
.btn.btn-primary {
color: var(--primary-inverse);
- border-color: var(--primary);
- background-color: var(--primary);
+ border: var(--bg-gradient-primary);
+ background: var(--bg-gradient-primary);
}
.btn.btn-primary:hover,
@@ -112,7 +112,8 @@
height: 35px;
padding: 0 28px;
border-radius: 15px;
- font-size: 11px;
+ font-size: 12px;
+ font-weight: 600;
border: none;
outline: none;
cursor: pointer;
diff --git a/public/css/form.scss b/public/css/form.scss
index 8646008..4bcbe4c 100644
--- a/public/css/form.scss
+++ b/public/css/form.scss
@@ -102,9 +102,10 @@
.floating-label {
position: absolute;
- left: 15px;
+ left: 9px;
+ z-index: 111;
top: 8px;
- font-size: 14px;
+ font-size: 12px;
font-weight: 500;
padding: 0 7px;
background: #fff;
diff --git a/public/css/navbar.scss b/public/css/navbar.scss
index a2b8dbf..29ba89e 100644
--- a/public/css/navbar.scss
+++ b/public/css/navbar.scss
@@ -344,24 +344,37 @@
.nav-account {
- position: relative;
- //background: #efefef;
border-radius: 35px;
+ position: absolute;
+ bottom: 56px;
+ width: 100%;
+ padding: 0px 7px;
+ transition: 0.5s ease-in-out;
}
.nav-account .container-account .account {
display: flex;
- justify-content: end;
+ justify-content: space-between;
align-items: center;
gap: 1rem;
- //background: rgba(255, 255, 255, 0);
- padding: 8px 10px 8px 45px;
border-radius: 35px;
cursor: pointer;
+ transition: 0.5s ease-in-out;
}
.nav-account .container-account .account .text {
- text-align: end;
+ text-align: start;
+ width: 0;
+ margin-left: -15px;
+ opacity: 0;
+ visibility: hidden;
+}
+
+.nav-account .container-account .account .text.active{
+ width: 100%;
+ margin-left: 10px;
+ opacity:1;
+ visibility: visible;
}
.nav-account .detail-account .header .text .name {
@@ -405,26 +418,56 @@
}
.nav-account .detail-account {
- background: #fff;
- height: 0;
- right: 0;
opacity: 0;
visibility: hidden;
+ background: #fff;
+ right: 0;
+ left: 65px;
+ top: -200px;
+ height: 270px;
position: absolute;
transition: all 0.3s ease;
- top: 100%;
margin-top: 10px;
min-width: 250px;
border-radius: 20px;
- box-shadow: 0px 0px 50px 0px rgba(82, 63, 105, 0.15);
}
-.nav-account .container-account:hover .detail-account {
+.nav-account .detail-account.active {
+ opacity: 0;
+ visibility: hidden;
+ background: #fff;
+ right: 0;
+ left: 305px;
+ top: -200px;
+ height: 270px;
+ position: absolute;
+ transition: all 0.3s ease;
+ margin-top: 10px;
+ min-width: 250px;
+ border-radius: 20px;
+}
+
+
+.nav-account:hover .detail-account {
height: auto;
opacity: 1;
visibility: visible;
transition: all 0.5s ease;
- transform: translateY(-10px);
+ right: 0;
+ left: 55px;
+ top: -180px;
+ z-index: 1000;
+}
+
+.nav-account:hover .detail-account.active {
+ height: auto;
+ opacity: 1;
+ visibility: visible;
+ transition: all 0.5s ease;
+ right: 0;
+ left: 255px;
+ top: -180px;
+ z-index: 1000;
}
.nav-account .detail-account .header {
@@ -909,6 +952,7 @@
height:35px;
position: absolute;
bottom: 10px;
+ right: 8px;
//background: #00000038;
background: rgba(0, 0, 0, 0.1882352941);
border-radius: 26px;
diff --git a/public/css/table.scss b/public/css/table.scss
index e053f77..d5652d5 100644
--- a/public/css/table.scss
+++ b/public/css/table.scss
@@ -50,7 +50,7 @@
color: var(--primary);
font-weight: 600;
text-align: start;
- background:#d4e8ed;
+ background:#0179c217;
border-bottom: 1px solid #ffffff;
padding: 11px 16px;
}
diff --git a/public/css/template.scss b/public/css/template.scss
index 65ee5d3..5f6783d 100644
--- a/public/css/template.scss
+++ b/public/css/template.scss
@@ -1,5 +1,6 @@
:root {
--primary: #0179c2;
+ --primary-dark: #01314e;
--success: #50cd89;
--info: #1a98ff;
--warning: #FEB82F;
@@ -7,7 +8,7 @@
--secondary: #aaa;
--dark: #181c32;
--dark-grey: #666;
- --primary-light: #9fd6ff;
+ --primary-light: #0179c217;
--secondary-light: #f9f9f9;
--success-light: #e8fff3;
--info-light: #dbe8ff;
@@ -15,7 +16,8 @@
--danger-light: #fff5f8;
--dark-light: #e4e6e7;
--white: #fff;
- --text-muted: #9A9A9A;
+ --text-muted: #a9a9a9;
+ --text-muted-reverse: #ffffff85;
--success-inverse: #ffffff;
--info-inverse: #ffffff;
--warning-inverse: #ffffff;
@@ -53,16 +55,17 @@
--color-step6:#326F71;
--color-step7:#1e5c6b;
+ --color-logo-green: #61c300;
+ --color-logo-orange: #e77c01;
+ --color-logo-purple: #a800c1;
- //--color-step1:#50cd89;
- //--color-step2:#43af7f;
- //--color-step3:#369375;
- //--color-step4:#29776b;
- //--color-step5:#1e5c6b;
- //--color-step6:#1c5064;
- //--color-step7:#19445e;
+ --bg-gradient-transaksi: linear-gradient(316deg, #17374b, var(--primary));
+ --bg-gradient-orange: linear-gradient(316deg, #17374b, var(--color-logo-orange));
+ --bg-gradient-green: linear-gradient(316deg, #17374b, var(--color-logo-green));
+ --bg-gradient-purple: linear-gradient(316deg, #17374b, var(--color-logo-purple));
+ --bg-gradient-dark: linear-gradient(316deg, #17374b, var(--dark));
+ --bg-gradient-primary: linear-gradient(336deg, #0a3865, var(--primary));
- --bg-menu: linear-gradient(90deg, #003775 0%, #0057b9 104.42%);
--bg-sub-menu: #f8f8f840;
}
@@ -110,6 +113,7 @@ button {
body {
overflow-x: hidden;
+ background: #000;
}
.bg-nav {
@@ -131,6 +135,14 @@ body {
}
+.nextjs-toploader {
+ z-index: 9999;
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+}
+
.bg-nav-hov{
background: rgba(0, 0, 0, 0.7);
height: 100px;
@@ -140,6 +152,16 @@ body {
z-index: 2;
}
+.card-content{
+ background: #ffffffe0;
+ width: 100%;
+ height: 100%;
+ border-radius: 30px;
+ padding: 30px;
+ overflow: auto;
+ backdrop-filter: blur(8px);
+}
+
section {
position: fixed;
// top: 10rem;
@@ -147,12 +169,14 @@ section {
overflow: scroll;
height: 100vh;
width: 100%;
- padding: 15px 35px 150px;
- padding-left: 300px;
- border-radius: 15px 15px 0 0;
+ padding: 15px 10px;
+ padding-left: 280px;
+ border-radius: 20px;
transition: all 0.5s ease;
- background: #f3f3f3;
- //background: url(/img/pat29.png);
+ //background: #f3f3f3;
+ background: url(/img/bg14.jpg);
+ background-size: cover;
+
box-shadow: 0px 0px 50px 0px rgba(82, 63, 105, 0.15);
&::-webkit-scrollbar {
height: 0;
@@ -166,7 +190,7 @@ section {
}
section.content.hover{
- padding-left: 120px;
+ padding-left: 80px;
}
.resultCard {
@@ -253,7 +277,6 @@ section.content.hover{
color: var(--dark-grey);
padding: 8px 12px;
border: 0;
- width: 100%;
/* border-top: 1px dashed #e7e7e7; */
outline: 0;
background: transparent;
@@ -614,7 +637,7 @@ section.content.hover{
align-items: start;
flex-direction: column;
margin-right: 10px;
- margin-top: 10px;
+ margin-top: -45px;
width: 50%;
.breadCrumb {
@@ -1789,6 +1812,8 @@ hr.border{
}
.check-auth{
+ color: #fff;
+
.container {
height: 100vh;
position: relative;
@@ -1833,10 +1858,10 @@ hr.border{
.side-menu-container{
position: fixed;
- left: 10px;
+ left: 14px;
z-index: 111;
- height: 95vh;
- top: 18px;
+ height: 97vh;
+ top: 14px;
//background: var(--primary);
border-radius: 30px;
background: linear-gradient(316deg, #17374b, var(--primary));
@@ -1858,7 +1883,7 @@ hr.border{
&:hover {
- background-color: rgba(0, 0, 0, 0.7) !important;
+ background-color: rgba(0, 0, 0, 0.2) !important;
}
}
@@ -2398,4 +2423,12 @@ hr.border{
font-size: 11px;
font-weight: 300;
}
+}
+
+
+.ant-dropdown .ant-dropdown-menu .ant-dropdown-menu-item,
+.ant-dropdown-menu-submenu .ant-dropdown-menu .ant-dropdown-menu-item,
+.ant-dropdown .ant-dropdown-menu .ant-dropdown-menu-submenu-title,
+.ant-dropdown-menu-submenu .ant-dropdown-menu .ant-dropdown-menu-submenu-title {
+ padding: 0;
}
\ No newline at end of file
diff --git a/public/img/gedung.jpeg b/public/img/gedung.jpeg
new file mode 100644
index 0000000..72067eb
Binary files /dev/null and b/public/img/gedung.jpeg differ
diff --git a/src/app/login/page.jsx b/src/app/login/page.jsx
index f635b4d..10e0dd8 100644
--- a/src/app/login/page.jsx
+++ b/src/app/login/page.jsx
@@ -10,6 +10,7 @@ import {getCookie} from "cookies-next";
import {LoadingOutlined} from "@ant-design/icons";
import usePreventBackNavigation from "@/hooks/usePreventBackNavigation";
import CheckAuth from "@/components/util/CheckAuth";
+import packageJson from "@@/package.json";
export default function Login() {
@@ -37,10 +38,8 @@ export default function Login() {
return setErrorLogin(result.message);
}
- await setAuth(result.token, result.users.id);
-
- let userData = await API.GET('/ref/user/' + result?.users?.id)
- localStorage.setItem('user_roleId', userData?.result?.users?.idBranch);
+ await setAuth(result.token, result.userId);
+ localStorage.setItem('user_roleId', result.roleId);
router.push("/main/dashboard");
};
@@ -104,7 +103,7 @@ export default function Login() {
/>
-
v0.1.0
+ v{packageJson.version}
diff --git a/src/app/main/daftarAgen/CardAgen.jsx b/src/app/main/daftarAgen/CardAgen.jsx
new file mode 100644
index 0000000..e9022d6
--- /dev/null
+++ b/src/app/main/daftarAgen/CardAgen.jsx
@@ -0,0 +1,77 @@
+import React, {useEffect, useState} from "react";
+import {Col, Dropdown, Row} from "antd";
+import "./style.scss";
+import {CheckCircleOutlined, CloseCircleOutlined, ContainerOutlined, EditOutlined, SettingOutlined, UserOutlined} from "@ant-design/icons";
+
+export default function CardAgen({data,modalOpen}) {
+
+ return (
+ {data && data?.map((v, k) => {
+
+ let items = [
+ {
+ key: '1',
+ label: ( modalOpen(v?.karyawanId,'edit')} className="dropdown-item w-full">
+ Ubah
+ ),
+ },
+ {
+ key: '2',
+ label: ( modalOpen(v?.karyawanId,'detail')} className="dropdown-item w-full">
+ Detail
+ ),
+ }
+ ]
+
+ return (
+
+
+
{v?.karyawanNm}
+
{v?.jabatanNm}
+
+
+
+
+
+
username
+
{v?.username}
+
+
+
telpon/hp
+
{v?.phoneNo}
+
+
+
+
+
+
+
+ Pengaturan
+
+
+
+
+
+
+ {(v?.profilePict) ?
:
}
+
+
+
+
+
+ )
+ })}
+
+
)
+}
\ No newline at end of file
diff --git a/src/app/main/daftarAgen/FormAgen.jsx b/src/app/main/daftarAgen/FormAgen.jsx
new file mode 100644
index 0000000..2de20c8
--- /dev/null
+++ b/src/app/main/daftarAgen/FormAgen.jsx
@@ -0,0 +1,96 @@
+import {Col, Modal, Row, Spin} from "antd";
+import {CloseOutlined} from "@ant-design/icons";
+import Input from "@/components/util/Input";
+import React, {useEffect, useState} from "react";
+import {useForm} from "react-hook-form";
+import {Helper} from "@/lib/Helper";
+import {DropdownAPI} from "@/lib/DropdownAPI";
+
+export default function FormAgen({modalStatus, actClose, data, loadingModal,jenis}) {
+ const [viewReadonly, setViewReadonly] = useState(false)
+ const [dropdownLoading, setDropdownLoading] = useState(false)
+ const [dropdown, setDropdown] = useState(
+ {
+ roleId : [],
+ branchId : [],
+ jabatanId : [],
+ jenisKelaminId : [],
+ agamaId : [],
+ statusAgenId : []
+ }
+ )
+
+ const {
+ register, setValue, watch, getValues, formState: {errors},
+ } = useForm();
+
+ const dropdownInit = async () => {
+ setDropdownLoading(true)
+ let listRole = await DropdownAPI.role();
+
+ setDropdownLoading(false)
+ }
+
+ const TypeAction = () => {
+ if(jenis === 'detail'){
+ return(
+ <>>
+ )
+ }else{
+ return(
+ Simpan
+ )
+ }
+ }
+
+ useEffect(() => {
+ if (jenis === 'detail'){
+ setViewReadonly(true);
+ }else{
+
+ setViewReadonly(false);
+ }
+ }, [jenis]);
+
+ useEffect(() => {
+ if (data){
+ setValue('karyawanNm',data?.karyawanNm)
+ setValue('roleId',data?.roleId)
+ }
+ }, [data]);
+
+ useEffect(() => {
+ dropdownInit()
+ }, []);
+
+ return (
+
+
+
+
+
+
Data Agen
+
Data Agen
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+
+}
\ No newline at end of file
diff --git a/src/app/main/daftarAgen/page.jsx b/src/app/main/daftarAgen/page.jsx
new file mode 100644
index 0000000..af9e6fc
--- /dev/null
+++ b/src/app/main/daftarAgen/page.jsx
@@ -0,0 +1,251 @@
+"use client"
+import SearchInput from "@/components/util/SearchInput";
+import WrapperContent from "@/components/util/WrapperContent";
+import React, {useEffect, useState} from "react";
+import CardAgen from "./CardAgen";
+import {API} from "@/lib/API";
+import notifStore from "@/store/notifStore";
+import FormAgen from "@/app/main/daftarAgen/FormAgen";
+import {ReloadOutlined} from "@ant-design/icons";
+
+export default function DaftarAgen() {
+ const {notifOpen} = notifStore()
+ const [searchText, setSearchText] = useState(null)
+ const [dataAgen, setDataAgen] = useState([])
+ const [modalAgen, setModalAgen] = useState({
+ loadingModal: false, modalStatus: false, jenis: null, data: []
+ })
+
+ const handleSearch = (event) => {
+ const handler = setTimeout(() => {
+ setSearchText(event.target.value);
+ }, 1000);
+ return () => {
+ clearTimeout(handler);
+ };
+ };
+
+ const getAgen = async () => {
+ // let res = await API.GET('/ref/karyawan')
+ // if (res.status !== 200) {
+ // notifOpen("Gagal", res.result.message, "danger");
+ // return false
+ // }
+
+ let dummyData = {
+ "page": 0,
+ "size": 1,
+ "totalPages": 1,
+ "totalElements": 1,
+ "data": [
+ {
+ "karyawanId": 3,
+ "profilePict": null,
+ "username": "karyawanbackend",
+ "roleId": 4,
+ "roleNm": "Backend Developer",
+ "isActive": true,
+ "statusUserId": 2,
+ "statusUserNm": "Baru",
+ "jenisKelaminId": 1,
+ "jenisKelaminNm": "Laki-laki",
+ "email": "karyawanbackend@basys.co.id",
+ "phoneNo": "085300000003",
+ "companyId": 1,
+ "companyNm": "PT Bayu Sinergi Solusi",
+ "branchId": 1,
+ "branchCode": "001",
+ "branchNm": "Cabang Utama PT. Basys",
+ "divisiId": 1,
+ "divisiNm": "Backend Developer",
+ "jabatanId": 1,
+ "jabatanNm": "Outlet Alzam Store",
+ "statusAgenId": 1,
+ "statusAgenNm": "Pegawai Tetap",
+ "spvId": null,
+ "spvUsername": null,
+ "spvNm": null,
+ "recognizeId": "e12ff5c2-919b-4e40-8841-3b876696d619",
+ "hasRecognized": false,
+ "nik": "0000000000000002",
+ "nip": "0000000000000002",
+ "npwp": 2,
+ "birthPlace": "Kota Bandung",
+ "birthDt": "2000-09-17",
+ "address": "Jalan Jalan 2",
+ "tanggalBekerja": "2023-01-01",
+ "agamaId": 1,
+ "agamaNm": "Islam",
+ "tanggalBerhentiBekerja": null,
+ "userCrtId": 1,
+ "userCrtNm": "Webmin Basys",
+ "userCrtUsername": "webminbasys",
+ "userUpdtId": 1,
+ "userUpdtNm": "Webmin Basys",
+ "userUpdtUsername": "webminbasys",
+ "crtdt": "2024-07-31 11:28:26",
+ "uptdt": "2024-07-31 11:28:26",
+ "karyawanNm": "Nama Agen A"
+ }, {
+ "karyawanId": 3,
+ "profilePict": null,
+ "username": "karyawanbackend",
+ "roleId": 4,
+ "roleNm": "Backend Developer",
+ "isActive": true,
+ "statusUserId": 2,
+ "statusUserNm": "Baru",
+ "jenisKelaminId": 1,
+ "jenisKelaminNm": "Laki-laki",
+ "email": "karyawanbackend@basys.co.id",
+ "phoneNo": "085300000003",
+ "companyId": 1,
+ "companyNm": "PT Bayu Sinergi Solusi",
+ "branchId": 1,
+ "branchCode": "001",
+ "branchNm": "Cabang Utama PT. Basys",
+ "divisiId": 1,
+ "divisiNm": "Backend Developer",
+ "jabatanId": 1,
+ "jabatanNm": "Outlet Alzam Store",
+ "statusAgenId": 1,
+ "statusAgenNm": "Pegawai Tetap",
+ "spvId": null,
+ "spvUsername": null,
+ "spvNm": null,
+ "recognizeId": "e12ff5c2-919b-4e40-8841-3b876696d619",
+ "hasRecognized": false,
+ "nik": "0000000000000002",
+ "nip": "0000000000000002",
+ "npwp": 2,
+ "birthPlace": "Kota Bandung",
+ "birthDt": "2000-09-17",
+ "address": "Jalan Jalan 2",
+ "tanggalBekerja": "2023-01-01",
+ "agamaId": 1,
+ "agamaNm": "Islam",
+ "tanggalBerhentiBekerja": null,
+ "userCrtId": 1,
+ "userCrtNm": "Webmin Basys",
+ "userCrtUsername": "webminbasys",
+ "userUpdtId": 1,
+ "userUpdtNm": "Webmin Basys",
+ "userUpdtUsername": "webminbasys",
+ "crtdt": "2024-07-31 11:28:26",
+ "uptdt": "2024-07-31 11:28:26",
+ "karyawanNm": "Nama Agen A"
+ }, {
+ "karyawanId": 3,
+ "profilePict": null,
+ "username": "karyawanbackend",
+ "roleId": 4,
+ "roleNm": "Backend Developer",
+ "isActive": true,
+ "statusUserId": 2,
+ "statusUserNm": "Baru",
+ "jenisKelaminId": 1,
+ "jenisKelaminNm": "Laki-laki",
+ "email": "karyawanbackend@basys.co.id",
+ "phoneNo": "085300000003",
+ "companyId": 1,
+ "companyNm": "PT Bayu Sinergi Solusi",
+ "branchId": 1,
+ "branchCode": "001",
+ "branchNm": "Cabang Utama PT. Basys",
+ "divisiId": 1,
+ "divisiNm": "Backend Developer",
+ "jabatanId": 1,
+ "jabatanNm": "Outlet Alzam Store",
+ "statusAgenId": 1,
+ "statusAgenNm": "Pegawai Tetap",
+ "spvId": null,
+ "spvUsername": null,
+ "spvNm": null,
+ "recognizeId": "e12ff5c2-919b-4e40-8841-3b876696d619",
+ "hasRecognized": false,
+ "nik": "0000000000000002",
+ "nip": "0000000000000002",
+ "npwp": 2,
+ "birthPlace": "Kota Bandung",
+ "birthDt": "2000-09-17",
+ "address": "Jalan Jalan 2",
+ "tanggalBekerja": "2023-01-01",
+ "agamaId": 1,
+ "agamaNm": "Islam",
+ "tanggalBerhentiBekerja": null,
+ "userCrtId": 1,
+ "userCrtNm": "Webmin Basys",
+ "userCrtUsername": "webminbasys",
+ "userUpdtId": 1,
+ "userUpdtNm": "Webmin Basys",
+ "userUpdtUsername": "webminbasys",
+ "crtdt": "2024-07-31 11:28:26",
+ "uptdt": "2024-07-31 11:28:26",
+ "karyawanNm": "Nama Agen A"
+ }
+ ]
+ }
+
+ // setDataAgen(res.result.data)
+ setDataAgen(dummyData.data)
+ }
+
+ const modalOpen = async (id, type) => {
+ setModalAgen(prev => ({
+ ...prev, modalStatus: true, jenis: type, loadingModal: true
+ }));
+
+ let res = await API.GET('/ref/karyawan/' + id)
+
+ setModalAgen(prev => ({
+ ...prev, data: res.result, loadingModal: false
+ }));
+
+
+ }
+
+ useEffect(() => {
+ getAgen()
+ }, []);
+
+ return (<>
+
+
+
+
+
+
Data Agen
+
Daftar Agen
+
+
Daftar Agen
+
+
+
+ modalOpen(null, 'tambah')}>Registrasi Agen
+ getAgen()}
+ >
+
+
+
+
+
+
+
+
+
+
+ {
+ setModalAgen(prev => ({
+ ...prev, modalStatus: false, loadingModal: false
+ }));
+ }}
+ data={modalAgen?.data}/>
+ >)
+}
\ No newline at end of file
diff --git a/src/app/main/daftarAgen/style.scss b/src/app/main/daftarAgen/style.scss
new file mode 100644
index 0000000..0154d6a
--- /dev/null
+++ b/src/app/main/daftarAgen/style.scss
@@ -0,0 +1,80 @@
+.card-karyawan{
+ background: #fff;
+ padding: 10px;
+ border-radius: 25px;
+ box-shadow: 0px 8px 50px rgb(0 0 0 / 8%);
+ margin-top: 15px;
+ transition: 0.5s ease-in-out;
+
+ &:hover{
+ box-shadow: 0px 25px 50px rgb(0 0 0 / 15%);
+ }
+
+ .content-title{
+ background: #f7f7f7;
+ padding: 10px 15px;
+ border-radius: 20px;
+ width: 60%;
+
+ .name{
+ font-weight: 600;
+ font-size: 14px;
+ color: var(--dark);
+ }
+ .position{
+ font-weight: 400;
+ font-size: 12px;
+ color: var(--text-muted);
+ }
+ }
+
+ .container-karyawan{
+ padding: 15px;
+ }
+
+ .content-karyawan{
+ margin-bottom: 15px;
+
+ .title{
+ font-size: 12px;
+ font-weight: 400;
+ color: var(--text-muted);
+ }
+ .value{
+ font-size: 13px;
+ font-weight: 500;
+ color: #0c111c;
+ }
+ }
+
+ .content-status{
+ position: absolute;
+ top: 5px;
+ right: 20px;
+ border-radius: 20px;
+ padding: 3px 30px 3px 10px;
+
+ .status-flag{
+ display: flex;
+ gap: 0px;
+ font-weight: 400;
+ font-size: 12px;
+ }
+ }
+
+ .content-foto{
+ position: absolute;
+ bottom: 10px;
+ right: 5px;
+
+ .icon{
+ font-size: 180px;
+ color: rgba(0, 0, 0, 0.05);
+ }
+ .img{
+ width: 150px;
+ object-fit: contain;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/app/main/daftarOutlet/CardOutlet.jsx b/src/app/main/daftarOutlet/CardOutlet.jsx
new file mode 100644
index 0000000..ab51106
--- /dev/null
+++ b/src/app/main/daftarOutlet/CardOutlet.jsx
@@ -0,0 +1,80 @@
+import React, {useEffect, useState} from "react";
+import {Col, Dropdown, Row} from "antd";
+import "./style.scss";
+import {CheckCircleOutlined, CloseCircleOutlined, ContainerOutlined, DeleteOutlined, EditOutlined, SettingOutlined, UserOutlined} from "@ant-design/icons";
+
+export default function CardOutlet({data,modalOpen, deleteData}) {
+
+ return (
+ {data && data?.map((v, k) => {
+
+ let items = [
+ {
+ key: '1',
+ label: ( modalOpen(v?.branchId,'edit')} className="dropdown-item w-full">
+ Ubah
+ ),
+ },
+ {
+ key: '2',
+ label: ( modalOpen(v?.branchId,'detail')} className="dropdown-item w-full">
+ Detail
+ ),
+ },
+ {
+ key: '3',
+ label: ( deleteData(v?.branchId)} className="dropdown-item w-full">
+ Hapus
+ ),
+ }
+ ]
+
+ return (
+
+
+
+
+
+
+
Perusahaan A
+
Nama Outlet A
+
{v?.address}
+
+
+
+
+
+
+ Pengaturan
+
+
+
+
+
+
+
+
Jenis Outlet
+
Jenis Outlet A
+
+
+
Penanggungjawab
+
Zamzam Nurzaman
+
+
+
+
+
+
+ )
+ })}
+
+
)
+}
\ No newline at end of file
diff --git a/src/app/main/daftarOutlet/FormOutlet.jsx b/src/app/main/daftarOutlet/FormOutlet.jsx
new file mode 100644
index 0000000..7f7f133
--- /dev/null
+++ b/src/app/main/daftarOutlet/FormOutlet.jsx
@@ -0,0 +1,194 @@
+import { Col, Modal, Row, Spin } from "antd";
+import { CloseOutlined } from "@ant-design/icons";
+import Input from "@/components/util/Input";
+import React, { useEffect, useState } from "react";
+import { useForm } from "react-hook-form";
+import dynamic from "next/dynamic";
+
+let timer;
+export default function FormOutlet({
+ modalStatus,
+ actClose, actStoreData,
+ data,
+ loadingModal,
+ jenis,
+}) {
+
+
+ const [viewReadonly, setViewReadonly] = useState(false);
+ const [latlon, setLatlon] = useState(null);
+ const [showMap, setShowMap] = useState(false);
+
+ const {
+ register,
+ setValue,
+ watch,
+ getValues,
+ reset,
+ handleSubmit,
+ formState: { errors },
+ } = useForm();
+
+ const TypeAction = () => {
+ if (jenis === "detail") {
+ return <>>;
+ } else {
+ return Simpan ;
+ }
+ };
+
+ const onSubmit = async (data) => {
+ actStoreData(data)
+ }
+
+
+ useEffect(() => {
+ if (jenis === "detail") {
+ setViewReadonly(true);
+ } else {
+ setViewReadonly(false);
+ }
+
+
+ }, [jenis]);
+
+ useEffect(() => {
+ if (data) {
+ console.log(data)
+ setValue('address',data.address)
+ setValue('picNm', data.picNm)
+ setValue('phoneNo', data.phoneNo)
+ setValue('lat', data.lat)
+ setValue('lon', data.lon)
+ setValue('companyNm', data.companyNm)
+ setValue('wilayahId', data?.wilayah?.wilayahId)
+ setValue('companyId', data.companyId)
+
+ setLatlon({
+ lat: data.lat,
+ lon: data.lon
+ })
+
+ }
+ }, [data]);
+
+
+ useEffect(() => {
+ if (modalStatus === true){
+ setLatlon(null)
+ reset()
+ timer = setTimeout(() => {
+ setShowMap(true);
+ }, 2000);
+
+ }
+ }, [modalStatus]);
+
+ useEffect(() => {
+ setLatlon({
+ lat: watch('lat'),
+ lon:watch('lon')
+ })
+ }, [watch('lat')]);
+
+ return (
+
+
+
+
+
+
+
+ Data Outlet
+
+
Data Outlet
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/app/main/daftarOutlet/page.jsx b/src/app/main/daftarOutlet/page.jsx
new file mode 100644
index 0000000..0500025
--- /dev/null
+++ b/src/app/main/daftarOutlet/page.jsx
@@ -0,0 +1,185 @@
+"use client"
+import SearchInput from "@/components/util/SearchInput";
+import WrapperContent from "@/components/util/WrapperContent";
+import React, {useEffect, useState} from "react";
+import CardOutlet from "./CardOutlet";
+import {API} from "@/lib/API";
+import notifStore from "@/store/notifStore";
+import FormOutlet from "./FormOutlet";
+import {ReloadOutlined} from "@ant-design/icons";
+import {Pagination} from "antd";
+import confirmStore from "@/store/confirmStore";
+import "./style.scss"
+
+export default function DaftarOutlet() {
+ const {notifOpen} = notifStore()
+ const {confirmOpen, confirmClose, setConfirmLoading} = confirmStore();
+
+ const [searchText, setSearchText] = useState(null)
+ const [currentPage, setCurrentPage] = useState(1)
+
+ const [dataCabang, setDataCabang] = useState([])
+ const [modalCabang, setModalCabang] = useState({
+ loadingModal:false,
+ modalStatus:false,
+ jenis:null,
+ data:[]
+ })
+
+ const handleSearch = (event) => {
+ const handler = setTimeout(() => {
+ setSearchText(event.target.value);
+ }, 1000);
+ return () => {
+ clearTimeout(handler);
+ };
+ };
+
+ const getCabang = async (page,size) => {
+ let setPage = (page) ? page : 0;
+ let setSize = (size) ? size : 6;
+ let res = await API.GET(`/ref/branch?page=${setPage}&size=${setSize}`)
+ if(res.status !== 200){
+ notifOpen("Gagal", res.result.message, "danger");
+ return false
+ }
+ setDataCabang(res.result)
+ }
+
+ const modalOpen = async (id,type) => {
+
+ if (type === 'tambah'){
+ setModalCabang(prev => ({
+ ...prev,
+ modalStatus: true,
+ jenis: type,
+ data:null
+ }));
+
+ }else{
+ setModalCabang(prev => ({
+ ...prev,
+ modalStatus: true,
+ jenis: type,
+ loadingModal: true
+ }));
+ let res = await API.GET('/ref/branch/' + id)
+ setModalCabang(prev => ({
+ ...prev,
+ data: res.result,
+ loadingModal: false
+ }));
+ }
+
+
+
+
+ }
+
+ const storeData = async (data) => {
+ let res = await API.POST('/ref/branch', data)
+ if (res.status === 200) {
+ setModalCabang(prev => ({
+ ...prev,
+ modalStatus: false,
+ }));
+
+ notifOpen("Berhasil", res.result.message);
+ await getCabang();
+ setCurrentPage(1)
+ } else {
+ notifOpen("Gagal", res.result.message, "danger");
+ }
+ }
+
+ const deleteData = async (id) => {
+ confirmOpen("Hapus Data", "Yakin Hapus Data Ini", async () => {
+ setConfirmLoading(true);
+ let response = await API.DELETE(`/ref/branch/${id}`);
+ if (response.status === 200) {
+ notifOpen("Berhasil", "berhasil hapus data");
+ await getCabang();
+ setConfirmLoading(false);
+ confirmClose();
+ setCurrentPage(1)
+ } else {
+ console.log(response);
+ setConfirmLoading(false);
+ notifOpen("Gagal", response.result.message, "danger");
+ confirmClose();
+ }
+ });
+ };
+
+ const onChangePage = (page, pageSize) => {
+ console.log({page, pageSize})
+ setCurrentPage(page)
+ getCabang(page-1,pageSize)
+ }
+
+ const onChangePageSize = (current, size) => {
+ console.log({current, size})
+
+ }
+
+ useEffect(() => {
+ getCabang()
+ }, []);
+
+ return(<>
+
+
+
+
+
+
Data Outlet
+
Daftar Outlet
+
+
Daftar Outlet
+
+
+
+ modalOpen(null,'tambah')}>Registrasi Outlet
+ getCabang()}
+ >
+
+
+
+
+
+
+
+ `${range[0]}-${range[1]} dari ${total} Data`}
+ defaultPageSize={6}
+ pageSizeOptions={['6', '12', '24']}
+ showSizeChanger={true}
+ defaultCurrent={1}
+ current={currentPage}
+ onChange={onChangePage}
+ onShowSizeChange={onChangePageSize}
+ />
+
+
+
+ {
+ setModalCabang(prev => ({
+ ...prev,
+ modalStatus: false,
+ loadingModal: false
+ }));
+ }}
+ actStoreData={storeData}
+ data={modalCabang?.data} />
+ >)
+}
\ No newline at end of file
diff --git a/src/app/main/daftarOutlet/style.scss b/src/app/main/daftarOutlet/style.scss
new file mode 100644
index 0000000..dba14f2
--- /dev/null
+++ b/src/app/main/daftarOutlet/style.scss
@@ -0,0 +1,95 @@
+.card-branch{
+ background: #fff;
+ padding: 10px 10px;
+ border-radius: 25px;
+ box-shadow: 0px 8px 50px rgb(0 0 0 / 8%);
+ margin-top: 15px;
+ transition: 0.5s ease-in-out;
+ position: relative;
+ display: flex;
+ justify-content: space-between;
+
+ &:hover{
+ box-shadow: 0px 25px 50px rgb(0 0 0 / 15%);
+ }
+
+ .content-detail{
+ text-align: right;
+ background: #F1F1F1;
+ padding: 30px;
+ border-radius: 20px;
+ }
+
+ .content-title{
+ margin-bottom: 20px;
+ margin-top: 10px;
+ padding: 10px 15px;
+ border-radius: 20px;
+ width: 100%;
+
+ .name{
+ margin-top: 10px;
+ font-weight: 700;
+ font-size: 14px;
+ color: var(--dark);
+ text-transform: uppercase;
+ }
+ .position{
+ font-weight: 300;
+ font-size: 12px;
+ }
+ }
+
+ .container-branch{
+ padding: 15px;
+ }
+
+ .content-branch{
+ margin-bottom: 15px;
+
+ .title{
+ font-size: 12px;
+ font-weight: 400;
+ color: var(--text-muted);
+ }
+ .value{
+ font-size: 13px;
+ font-weight: 500;
+ color: #0c111c;
+ }
+ }
+
+ .content-status{
+ position: absolute;
+ top: -10px;
+ left: 30px;
+ border-radius: 20px;
+ padding: 3px 30px 3px 10px;
+
+ .status-flag{
+ display: flex;
+ gap: 0px;
+ font-weight: 400;
+ font-size: 12px;
+ }
+ }
+
+ .content-foto{
+ position: absolute;
+ top: 0px;
+ right: 0px;
+ border-radius: 25px;
+
+ .icon{
+ font-size: 180px;
+ color: rgba(0, 0, 0, 0.05);
+ }
+ .img{
+ width: 170px;
+ height: 250px;
+ object-fit: cover;
+ border-radius: 0 25px 100px 100px;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/app/main/daftarPerusahaan/CardPerusahaan.jsx b/src/app/main/daftarPerusahaan/CardPerusahaan.jsx
new file mode 100644
index 0000000..4e985ac
--- /dev/null
+++ b/src/app/main/daftarPerusahaan/CardPerusahaan.jsx
@@ -0,0 +1,79 @@
+import React, {useEffect, useState} from "react";
+import {Col, Dropdown, Row} from "antd";
+import "./style.scss";
+import {CheckCircleOutlined, CloseCircleOutlined, ContainerOutlined, DeleteOutlined, EditOutlined, SettingOutlined, UserOutlined} from "@ant-design/icons";
+
+export default function CardPerusahaan({data,modalOpen, deleteData}) {
+
+ return (
+ {data && data?.map((v, k) => {
+
+ let items = [
+ {
+ key: '1',
+ label: ( modalOpen(v?.companyId,'edit')} className="dropdown-item w-full">
+ Ubah
+ ),
+ },
+ {
+ key: '2',
+ label: ( modalOpen(v?.companyId,'detail')} className="dropdown-item w-full">
+ Detail
+ ),
+ },
+ {
+ key: '3',
+ label: ( deleteData(v?.companyId)} className="dropdown-item w-full">
+ Hapus
+ ),
+ }
+ ]
+
+ return (
+
+
+
{v?.companyNm}
+
{v?.address}
+
+
+
+
+
Jenis Perusahaan
+
PT (Perseroan Terbatas)
+
+
+
Jenis Bisnis
+
Perdagangan
+
+
+
+
+
+
+
+ Pengaturan
+
+
+
+
+
+
+ {(v?.profilePict) ?
:
}
+
+
+
+
+
+ )
+ })}
+
+
)
+}
\ No newline at end of file
diff --git a/src/app/main/daftarPerusahaan/FormPerusahaan.jsx b/src/app/main/daftarPerusahaan/FormPerusahaan.jsx
new file mode 100644
index 0000000..db3d458
--- /dev/null
+++ b/src/app/main/daftarPerusahaan/FormPerusahaan.jsx
@@ -0,0 +1,193 @@
+import { Col, Modal, Row, Spin } from "antd";
+import { CloseOutlined } from "@ant-design/icons";
+import Input from "@/components/util/Input";
+import React, { useEffect, useState } from "react";
+import { useForm } from "react-hook-form";
+
+let timer;
+export default function FormPerusahaan({
+ modalStatus,
+ actClose, actStoreData,
+ data,
+ loadingModal,
+ jenis,
+}) {
+
+
+ const [viewReadonly, setViewReadonly] = useState(false);
+ const [latlon, setLatlon] = useState(null);
+ const [showMap, setShowMap] = useState(false);
+
+ const {
+ register,
+ setValue,
+ watch,
+ getValues,
+ reset,
+ handleSubmit,
+ formState: { errors },
+ } = useForm();
+
+ const TypeAction = () => {
+ if (jenis === "detail") {
+ return <>>;
+ } else {
+ return Simpan ;
+ }
+ };
+
+ const onSubmit = async (data) => {
+ actStoreData(data)
+ }
+
+
+ useEffect(() => {
+ if (jenis === "detail") {
+ setViewReadonly(true);
+ } else {
+ setViewReadonly(false);
+ }
+
+
+ }, [jenis]);
+
+ useEffect(() => {
+ if (data) {
+ console.log(data)
+ setValue('address',data.address)
+ setValue('picNm', data.picNm)
+ setValue('phoneNo', data.phoneNo)
+ setValue('lat', data.lat)
+ setValue('lon', data.lon)
+ setValue('companyNm', data.companyNm)
+ setValue('wilayahId', data?.wilayah?.wilayahId)
+ setValue('companyId', data.companyId)
+
+ setLatlon({
+ lat: data.lat,
+ lon: data.lon
+ })
+
+ }
+ }, [data]);
+
+
+ useEffect(() => {
+ if (modalStatus === true){
+ setLatlon(null)
+ reset()
+ timer = setTimeout(() => {
+ setShowMap(true);
+ }, 2000);
+
+ }
+ }, [modalStatus]);
+
+ useEffect(() => {
+ setLatlon({
+ lat: watch('lat'),
+ lon:watch('lon')
+ })
+ }, [watch('lat')]);
+
+ return (
+
+
+
+
+
+
+
+ Data Perusahaan
+
+
Data Perusahaan
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/app/main/daftarPerusahaan/page.jsx b/src/app/main/daftarPerusahaan/page.jsx
new file mode 100644
index 0000000..ca5b17e
--- /dev/null
+++ b/src/app/main/daftarPerusahaan/page.jsx
@@ -0,0 +1,170 @@
+"use client"
+import SearchInput from "@/components/util/SearchInput";
+import WrapperContent from "@/components/util/WrapperContent";
+import React, {useEffect, useState} from "react";
+import CardPerusahaan from "./CardPerusahaan";
+import {API} from "@/lib/API";
+import notifStore from "@/store/notifStore";
+import {ReloadOutlined} from "@ant-design/icons";
+import {Pagination} from "antd";
+import confirmStore from "@/store/confirmStore";
+import FormPerusahaan from "@/app/main/daftarPerusahaan/FormPerusahaan";
+
+export default function DaftarPerusahaan() {
+ const {notifOpen} = notifStore()
+ const {confirmOpen, confirmClose, setConfirmLoading} = confirmStore();
+
+ const [searchText, setSearchText] = useState(null)
+ const [currentPage, setCurrentPage] = useState(1)
+
+ const [dataPerusahaan, setDataPerusahaan] = useState([])
+ const [modalPerusahaan, setModalPerusahaan] = useState({
+ loadingModal: false, modalStatus: false, jenis: null, data: []
+ })
+
+ const handleSearch = (event) => {
+ const handler = setTimeout(() => {
+ setSearchText(event.target.value);
+ }, 1000);
+ return () => {
+ clearTimeout(handler);
+ };
+ };
+
+ const getPerusahaan = async (page, size) => {
+ let setPage = (page) ? page : 0;
+ let setSize = (size) ? size : 6;
+ let res = await API.GET(`/ref/company?page=${setPage}&size=${setSize}`)
+ if (res.status !== 200) {
+ notifOpen("Gagal", res.result.message, "danger");
+ return false
+ }
+ setDataPerusahaan(res.result)
+ }
+
+ const modalOpen = async (id, type) => {
+
+ if (type === 'tambah') {
+ setModalPerusahaan(prev => ({
+ ...prev, modalStatus: true, jenis: type, data: null
+ }));
+
+ } else {
+ setModalPerusahaan(prev => ({
+ ...prev, modalStatus: true, jenis: type, loadingModal: true
+ }));
+ let res = await API.GET('/ref/company/' + id)
+ setModalPerusahaan(prev => ({
+ ...prev, data: res.result, loadingModal: false
+ }));
+ }
+
+
+ }
+
+ const storeData = async (data) => {
+ let res = await API.POST('/ref/company', data)
+ if (res.status === 200) {
+ setModalPerusahaan(prev => ({
+ ...prev, modalStatus: false,
+ }));
+
+ notifOpen("Berhasil", res.result.message);
+ await getPerusahaan();
+ setCurrentPage(1)
+ } else {
+ notifOpen("Gagal", res.result.message, "danger");
+ }
+ }
+
+ const deleteData = async (id) => {
+ confirmOpen("Hapus Data", "Yakin Hapus Data Ini", async () => {
+ setConfirmLoading(true);
+ let response = await API.DELETE(`/ref/company/${id}`);
+ if (response.status === 200) {
+ notifOpen("Berhasil", "berhasil hapus data");
+ await getPerusahaan();
+ setConfirmLoading(false);
+ confirmClose();
+ setCurrentPage(1)
+ } else {
+ console.log(response);
+ setConfirmLoading(false);
+ notifOpen("Gagal", response.result.message, "danger");
+ confirmClose();
+ }
+ });
+ };
+
+ const onChangePage = (page, pageSize) => {
+ console.log({page, pageSize})
+ setCurrentPage(page)
+ getPerusahaan(page - 1, pageSize)
+ }
+
+ const onChangePageSize = (current, size) => {
+ console.log({current, size})
+
+ }
+
+ useEffect(() => {
+ getPerusahaan()
+ }, []);
+
+ return (<>
+
+
+
+
+
+
Data Perusahaan
+
Daftar Perusahaan
+
+
Daftar Perusahaan
+
+
+
+ modalOpen(null, 'tambah')}>Registrasi Perusahaan
+ getPerusahaan()}
+ >
+
+
+
+
+
+
+
+ `${range[0]}-${range[1]} dari ${total} Data`}
+ defaultPageSize={6}
+ pageSizeOptions={['6', '12', '24']}
+ showSizeChanger={true}
+ defaultCurrent={1}
+ current={currentPage}
+ onChange={onChangePage}
+ onShowSizeChange={onChangePageSize}
+ />
+
+
+
+ {
+ setModalPerusahaan(prev => ({
+ ...prev,
+ modalStatus: false,
+ loadingModal: false
+ }));
+ }}
+ actStoreData={storeData}
+ data={modalPerusahaan?.data} />
+ >)
+}
\ No newline at end of file
diff --git a/src/app/main/daftarPerusahaan/style.scss b/src/app/main/daftarPerusahaan/style.scss
new file mode 100644
index 0000000..5b93b42
--- /dev/null
+++ b/src/app/main/daftarPerusahaan/style.scss
@@ -0,0 +1,84 @@
+.card-company{
+ background: #fff;
+ padding: 15px 20px;
+ border-radius: 25px;
+ box-shadow: 0px 8px 50px rgb(0 0 0 / 8%);
+ margin-top: 15px;
+ transition: 0.5s ease-in-out;
+ position: relative;
+
+ &:hover{
+ box-shadow: 0px 25px 50px rgb(0 0 0 / 15%);
+ }
+
+ .content-title{
+ margin-top: 15px;
+ padding: 10px 15px;
+ border-radius: 20px;
+ width: 60%;
+
+ .name{
+ font-weight: 600;
+ font-size: 14px;
+ color: var(--dark);
+ text-transform: uppercase;
+ }
+ .position{
+ font-weight: 300;
+ font-size: 12px;
+ }
+ }
+
+ .container-company{
+ padding: 15px;
+ }
+
+ .content-company{
+ margin-bottom: 15px;
+
+ .title{
+ font-size: 12px;
+ font-weight: 400;
+ color: var(--text-muted);
+ }
+ .value{
+ font-size: 13px;
+ font-weight: 500;
+ color: #0c111c;
+ }
+ }
+
+ .content-status{
+ position: absolute;
+ top: -10px;
+ left: 30px;
+ border-radius: 20px;
+ padding: 3px 30px 3px 10px;
+
+ .status-flag{
+ display: flex;
+ gap: 0px;
+ font-weight: 400;
+ font-size: 12px;
+ }
+ }
+
+ .content-foto{
+ position: absolute;
+ top: 0px;
+ right: 0px;
+ border-radius: 25px;
+
+ .icon{
+ font-size: 180px;
+ color: rgba(0, 0, 0, 0.05);
+ }
+ .img{
+ width: 170px;
+ height: 250px;
+ object-fit: cover;
+ border-radius: 0 25px 100px 100px;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/app/main/dashboard/GrafikHari.jsx b/src/app/main/dashboard/GrafikHari.jsx
new file mode 100644
index 0000000..f2f9ba0
--- /dev/null
+++ b/src/app/main/dashboard/GrafikHari.jsx
@@ -0,0 +1,107 @@
+import dynamic from "next/dynamic";
+import {useEffect, useState} from "react";
+import {Helper} from "@/lib/Helper";
+
+const ReactApexChart = dynamic(() => import("react-apexcharts"), {ssr: false});
+
+export default function GrafikHari() {
+ const [grafik, setGrafik] = useState([]);
+ const [optionGrafik, setOptionGrafik] = useState(
+ {
+ chart: {
+ type: 'area',
+
+ },
+ dataLabels: {
+ enabled: false
+ },
+ stroke: {
+ curve: 'smooth'
+ },
+ fill: {
+ type: 'gradient',
+ gradient: {
+ shadeIntensity: 1,
+ opacityFrom: 0.1,
+ opacityTo: 0.9,
+ stops: [0, 100]
+ }
+ },
+ yaxis: {
+ labels: {
+ formatter: (val) => {
+ return Helper.numFormat(val)
+ },
+ },
+ },
+ tooltip: {
+ shared: true,
+ intersect: false,
+ y: {
+ formatter: function (y) {
+ if (typeof y !== "undefined") {
+ return Helper.numFormat(y);
+ }
+ return y;
+ }
+ }
+ },
+ colors: ['#0179c2', '#930200'],
+ legend: {
+ markers: {
+ fillColors: ['#0179c2', '#930200']
+ }
+ }
+ }
+ )
+
+ const getChart = (data) => {
+
+ let result = [
+ {
+ name: 'Transaksi',
+ data: [1000000,21000000,31000000,41000000,41000000,71000000, 11000000, 21000000, 31000000, 10000004, 10000004, 71000000, 1000000, 21000000, 31000000, 41000000, 41000000, 71000000, 11000000, 21000000, 31000000, 10000004, 10000004, 71000000]
+ },
+ ]
+
+ let data_jam = [];
+ for (let i = 1; i <= 24; i++) {
+ data_jam.push(i + ':00')
+ }
+
+ setOptionGrafik(prev => ({
+ ...prev,
+ xaxis: {
+ categories: data_jam
+ // categories: ["Jan",
+ // "Feb",
+ // "Mar",
+ // "Apr",
+ // "Mei",
+ // "Jun",
+ // "Jul",
+ // "Ags",
+ // "Sep",
+ // "Okt",
+ // "Nov",
+ // "Des"]
+ },
+ }));
+
+ setGrafik(result);
+ }
+
+ useEffect(() => {
+ getChart()
+ }, []);
+
+ return(<>
+
+
+
Grafik Transaksi Hari Ini
+
Grafik Transaksi Hari Ini
+
+
+
+ >)
+}
\ No newline at end of file
diff --git a/src/app/main/dashboard/GrafikTahun.jsx b/src/app/main/dashboard/GrafikTahun.jsx
new file mode 100644
index 0000000..2263741
--- /dev/null
+++ b/src/app/main/dashboard/GrafikTahun.jsx
@@ -0,0 +1,106 @@
+import dynamic from "next/dynamic";
+import {useEffect, useState} from "react";
+import {Helper} from "@/lib/Helper";
+
+const ReactApexChart = dynamic(() => import("react-apexcharts"), {ssr: false});
+
+export default function GrafikTahun() {
+ const [grafik, setGrafik] = useState([]);
+ const [optionGrafik, setOptionGrafik] = useState(
+ {
+ chart: {
+ type: 'area',
+
+ },
+ dataLabels: {
+ enabled: false
+ },
+ stroke: {
+ curve: 'smooth'
+ },
+ fill: {
+ type: 'gradient',
+ gradient: {
+ shadeIntensity: 1,
+ opacityFrom: 0.1,
+ opacityTo: 0.9,
+ stops: [0, 100]
+ }
+ },
+ yaxis: {
+ labels: {
+ formatter: (val) => {
+ return Helper.numFormat(val)
+ },
+ },
+ },
+ tooltip: {
+ shared: true,
+ intersect: false,
+ y: {
+ formatter: function (y) {
+ if (typeof y !== "undefined") {
+ return Helper.numFormat(y);
+ }
+ return y;
+ }
+ }
+ },
+ colors: ['#0179c2', '#930200'],
+ legend: {
+ markers: {
+ fillColors: ['#0179c2', '#930200']
+ }
+ }
+ }
+ )
+
+ const getChart = (data) => {
+
+ let result = [
+ {
+ name: 'Transaksi',
+ data: [1000000,21000000,31000000,41000000,41000000,71000000, 11000000, 21000000, 31000000, 10000004, 10000004, 71000000]
+ },
+ ]
+
+ let data_jam = [];
+ for (let i = 1; i <= 24; i++) {
+ data_jam.push(i + ':00')
+ }
+
+ setOptionGrafik(prev => ({
+ ...prev,
+ xaxis: {
+ categories: ["Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Ags",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Des"]
+ },
+ }));
+
+ setGrafik(result);
+ }
+
+ useEffect(() => {
+ getChart()
+ }, []);
+
+ return(<>
+
+
+
Grafik Semua Transaksi
+
Data Grafik Semua Transaksi
+
+
+
+ >)
+}
\ No newline at end of file
diff --git a/src/app/main/dashboard/SegmentAgen.jsx b/src/app/main/dashboard/SegmentAgen.jsx
new file mode 100644
index 0000000..531ef50
--- /dev/null
+++ b/src/app/main/dashboard/SegmentAgen.jsx
@@ -0,0 +1,130 @@
+import {IdcardOutlined} from "@ant-design/icons";
+
+export default function SegmentAgen() {
+ return(
+
+
+
Transaksi Per Agen
+
Perolehan Transaksi Per Agen 10 Teratas
+
+
+
+
+
+
+
Agen Alzam Zain Hamizan
+
Outlet Alzam Store
+
+
+
+
Rp 20.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/app/main/dashboard/SegmentJenisTransaksi.jsx b/src/app/main/dashboard/SegmentJenisTransaksi.jsx
new file mode 100644
index 0000000..ec3e7da
--- /dev/null
+++ b/src/app/main/dashboard/SegmentJenisTransaksi.jsx
@@ -0,0 +1,56 @@
+import {CreditCardOutlined} from "@ant-design/icons";
+
+export default function SegmentJenisTransaksi() {
+ return (
+
+
Transaksi Per Jenis Pembayaran
+
Perolehan Transaksi Per Jenis Pembayaran
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
)
+}
\ No newline at end of file
diff --git a/src/app/main/dashboard/SegmentProduk.jsx b/src/app/main/dashboard/SegmentProduk.jsx
new file mode 100644
index 0000000..8aeb8e7
--- /dev/null
+++ b/src/app/main/dashboard/SegmentProduk.jsx
@@ -0,0 +1,131 @@
+import {InboxOutlined} from "@ant-design/icons";
+
+export default function SegmentProduk() {
+ return(
+
+
+
Transaksi Per Produk
+
Perolehan Transaksi Per Produk 10 Teratas
+
+
+
+
+
+
+
Produk A
+
Outlet Alzam Store
+
+
+
+
Rp 20.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/app/main/dashboard/SegmentTransaksiHari.jsx b/src/app/main/dashboard/SegmentTransaksiHari.jsx
new file mode 100644
index 0000000..36bb8da
--- /dev/null
+++ b/src/app/main/dashboard/SegmentTransaksiHari.jsx
@@ -0,0 +1,83 @@
+import {FieldTimeOutlined, UserOutlined} from "@ant-design/icons";
+
+export default function SegmentTransaksiHari() {
+ return(
+
+
+
Transaksi Per Hari
+
Total Transaksi Per Hari
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/app/main/dashboard/page.jsx b/src/app/main/dashboard/page.jsx
index d0d0049..938c157 100644
--- a/src/app/main/dashboard/page.jsx
+++ b/src/app/main/dashboard/page.jsx
@@ -1,5 +1,187 @@
+"use client"
+import {Col, Row, Spin} from "antd";
+import Input from "@/components/util/Input";
+import {useState} from "react";
+import {useForm} from "react-hook-form";
+import "./style.scss"
+import GrafikHari from "@/app/main/dashboard/GrafikHari";
+import CardTransaksiHari from "@/app/main/dashboard/SegmentTransaksiHari";
+import SegmentTransaksiHari from "@/app/main/dashboard/SegmentTransaksiHari";
+import SegmentAgen from "@/app/main/dashboard/SegmentAgen";
+import GrafikTahun from "@/app/main/dashboard/GrafikTahun";
+import SegmentProduk from "@/app/main/dashboard/SegmentProduk";
+import SegmentJenisTransaksi from "@/app/main/dashboard/SegmentJenisTransaksi";
+import {CreditCardOutlined, IdcardOutlined, InboxOutlined, ShakeOutlined, ShopOutlined} from "@ant-design/icons";
+
export default function Dashboard() {
- return(
- <>dashboard>
- )
+ const {register, setValue, watch, getValues, formState: {errors},} = useForm();
+
+ const [dropdownData, setDropdownData] = useState({});
+ const [dropdownLoading, setDropdownLoading] = useState({
+ company: false, outlet: false,
+ });
+
+ return (
+
+
+
+
Dashboard
+
Data Dashboard
+
+
Dashboard
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Total Agen
+
100.000
+
+
+
+
+
+
Total Outlet
+
1.000
+
+
+
+
+
+
Total EDC Aktif
+
100.000
+
+
+
+
+
+
Total Produk
+
5.000
+
+
+
+
+
+
+
+
+
+
+
Total Transaksi
+
Rp 500.000.000
+
Dari 100 Transaksi yang di lakukan. Transaksi rata-rata perhari adalah 10 Transaksi dengan nominal Rata-rata sebesar Rp 100.000
+
+
+
+
+
+
Omzet
+
Rp 50.000.000
+
Dari 100 Transaksi
+
+
+
Laba
+
Rp 50.000.000
+
Dari 100 Transaksi
+
+
+
+
+
Fee Agen
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
Fee Bank
+
Rp 10.000.000
+
Dari 100 Transaksi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
)
}
\ No newline at end of file
diff --git a/src/app/main/dashboard/style.scss b/src/app/main/dashboard/style.scss
new file mode 100644
index 0000000..3d5682f
--- /dev/null
+++ b/src/app/main/dashboard/style.scss
@@ -0,0 +1,229 @@
+.dashboard {
+
+ .card {
+ background: #fff;
+ color: #000;
+ text-align: center;
+ padding: 25px;
+ //border:2px solid #f3f3f3;
+ box-shadow: none;
+ border-radius: 25px;
+
+ .icon-summary{
+ position: absolute;
+ top: 0;
+ font-size: 72px;
+ opacity: 0.09;
+ }
+
+
+ .title {
+ font-size: 13px;
+ font-weight: 400;
+ color: #000;
+ }
+
+ .desc {
+ font-size: 12px;
+ color: #a1a1a1;
+ }
+
+ .nominal {
+ font-size: 24px;
+ font-weight: 600;
+
+ &.low {
+ font-size: 18px;
+ }
+
+ small {
+ font-size: 13px;
+ font-weight: 400;
+ color: var(--text-muted);
+ }
+ }
+
+
+ .transaksi {
+ text-align: left;
+ margin-top: 20px;
+ //padding: 12px 20px;
+ }
+
+ &.dark {
+ border-bottom: 3px solid var(--dark);
+
+ .nominal {
+ color: var(--dark);
+ }
+
+ .icon-summary{
+ color: var(--dark);
+ }
+ }
+
+ &.green {
+ border-bottom: 3px solid var(--color-logo-green);
+
+ .nominal {
+ color: var(--color-logo-green);
+ }
+
+ .icon-summary {
+ color: var(--color-logo-green);
+ }
+ }
+
+ &.purple {
+ border-bottom: 3px solid var(--color-logo-purple);
+
+ .nominal {
+ color: var(--color-logo-purple);
+ }
+
+ .icon-summary {
+ color: var(--color-logo-purple);
+ }
+ }
+
+ &.orange {
+ border-bottom: 3px solid var(--color-logo-orange);
+
+ .nominal {
+ color: var(--color-logo-orange);
+ }
+
+ .icon-summary {
+ color: var(--color-logo-orange);
+ }
+ }
+
+ &.primary {
+ border-bottom: 3px solid var(--primary);
+
+ .nominal {
+ color: var(--primary);
+ }
+ }
+
+
+ }
+
+
+ .transaksi-hari {
+ color: #fff !important;
+
+ &.light {
+ color: var(--dark) !important;
+
+ .subTitle {
+ color: var(--text-muted);
+ }
+
+ .title {
+ color: var(--dark) !important;
+ }
+
+
+ .nominal {
+
+ .amount {
+ small {
+ color: var(--text-muted) !important;
+ }
+
+ }
+
+ .count {
+ color: var(--text-muted) !important;
+ }
+
+ }
+ }
+
+
+ .title {
+ font-size: 14px;
+ font-weight: 600;
+ color: #fff !important;
+ }
+
+ .subTitle {
+ font-size: 12px;
+ font-weight: 400;
+ color: var(--text-muted-reverse);
+ margin-bottom: 30px;
+ }
+
+ .content {
+ display: flex;
+ justify-content: space-between;
+ border-top: 1px solid rgb(255 255 255 / 9%);
+ padding: 15px 0;
+
+ &.reward-product {
+ background: #f7963e24;
+ border-radius: 20px;
+ padding: 15px;
+ margin: 0 -15px;
+
+ .icon {
+ color: #ffffff !important;
+ background: #f7963e;
+ }
+ }
+
+ &.reward-agen {
+ background: #181c3214;
+ border-radius: 20px;
+ padding: 15px;
+ margin: 0 -15px;
+
+ .icon {
+ color: #ffffff !important;
+ background: var(--dark);
+ }
+ }
+
+ .icon {
+ font-size: 16px;
+ background: rgba(0, 0, 0, 0.06);
+ width: 30px;
+ height: 30px;
+ padding: 3px 7px;
+ border-radius: 50%;
+ }
+
+ .name {
+ font-size: 12px;
+ font-weight: 600;
+ display: flex;
+ gap: 10px;
+ align-items: center;
+ text-align: left;
+ }
+
+ .nominal {
+
+ .amount {
+ font-size: 16px;
+ font-weight: 600;
+
+ small {
+ font-size: 12px;
+ font-weight: 400;
+ color: var(--text-muted-reverse);
+ }
+
+ }
+
+ .count {
+ font-size: 11px;
+ color: var(--text-muted-reverse);
+ }
+
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/app/main/layout.jsx b/src/app/main/layout.jsx
index 5f47a96..e686d7a 100644
--- a/src/app/main/layout.jsx
+++ b/src/app/main/layout.jsx
@@ -3,33 +3,33 @@
import React, {useEffect, useState} from "react";
import {QueryClient, QueryClientProvider} from "react-query";
-
-import dynamic from "next/dynamic";
import ModalConfirm from '@/components/util/ModalConfirm';
import ModalNotif from "@/components/util/ModalNotif";
import ChangePassword from "@/app/main/ChangePassword";
import ChangeProfile from "@/app/main/ChangeProfile";
-import LoadingPage from "@/components/util/LoadingPage";
import {getCookie} from "cookies-next";
import {API} from "@/lib/API";
-import {notFound, usePathname, useRouter} from "next/navigation";
-import {LoadingOutlined} from "@ant-design/icons";
+import {usePathname, useRouter} from "next/navigation";
import ModalSessionTimeout from "@/components/util/ModalSessionTimeout";
import useIdleDetection from "@/hooks/useIdleDetection";
import MenuList from "@/components/master/Menu";
import menuStore from "@/store/menuStore";
import CheckAuth from "@/components/util/CheckAuth";
-
-const Navbar = dynamic(() => import("@/components/master/Navbar"), {ssr: false,});
+import LoadingPage from "@/components/util/LoadingPage";
+import {Spin} from "antd";
+import {LoadingOutlined} from "@ant-design/icons";
const queryClient = new QueryClient();
+
export default function MainLayout({children}) {
const pathname = usePathname()
const router = useRouter();
const [checkAuth, setCheckAuth] = useState(true)
const {isIdle, setIsIdle} = useIdleDetection();
- const {toggleStatus} = menuStore()
+ const {toggleStatus, loadingPageStatus} = menuStore()
+
+
const checkToken = async () => {
@@ -61,36 +61,37 @@ export default function MainLayout({children}) {
}
useEffect(() => {
checkToken()
+
}, []);
- return (
-
- <>
- {(checkAuth) ?
-
- : <>
- {isIdle && }
-
+ return (
- {/* */}
-
-
-
-
-
-
-
-
-
+ <>
+ {(checkAuth) ? : <>
+ {isIdle && }
+ {/* */}
+
- >
- }
+
+
+
} style={{color:'var(--primary)'}} tip={
Loading
} spinning={loadingPageStatus}>
+
+ {children}
+
+
+
+
+
+
+
+
+
+ >}
- >
-
- );
+ >
+ );
}
diff --git a/src/app/main/user/menu/page.jsx b/src/app/main/user/menu/page.jsx
index 1eaf9a3..5a520ee 100644
--- a/src/app/main/user/menu/page.jsx
+++ b/src/app/main/user/menu/page.jsx
@@ -1,6 +1,5 @@
"use client";
import React, {useEffect, useRef, useState} from "react";
-import breadcrumbStore from "@/store/breadcrumbStore";
import modalStore from "@/store/modal";
import confirmStore from "@/store/confirmStore";
import {API} from "@/lib/API";
@@ -22,7 +21,6 @@ const MenuPrivilage = () => {
const formRef = useRef();
const {modalOpen, modalClose, FormId, modalStat, setModalLoading, setModalDetail, actionType} = modalStore();
- const {setSubTitle, setTitle} = breadcrumbStore();
const {confirmOpen, confirmClose, setConfirmLoading} = confirmStore();
const {notifOpen} = notifStore()
diff --git a/src/app/main/user/userlist/page.jsx b/src/app/main/user/userlist/page.jsx
index cbfe753..353ca3c 100644
--- a/src/app/main/user/userlist/page.jsx
+++ b/src/app/main/user/userlist/page.jsx
@@ -3,8 +3,6 @@ import {useEffect, useState} from "react";
import {DropdownAPI} from "@/lib/DropdownAPI";
import RefTemplate from "@/components/refTemplate/Main";
-import BadgeStatus from "@/components/util/BadgeStatus";
-import BadgeStatusApproval from "@/components/util/BadgeStatusApproval";
export default function UserList() {
const [listForm, setListForm] = useState()
@@ -142,15 +140,11 @@ export default function UserList() {
{
title: "Status",
dataIndex: 'active',
- render: (active) => ,
- sorter: (a, b) => a.active - b.active,
align: 'center'
},
{
title: "Status Persetujuan",
dataIndex: 'statusApprovalId',
- render: (statusApprovalId) => ,
- sorter: (a, b) => a.statusApprovalId - b.statusApprovalId,
align: 'center'
},
]}
diff --git a/src/app/page.jsx b/src/app/page.jsx
index e22dd9f..9ddf94e 100644
--- a/src/app/page.jsx
+++ b/src/app/page.jsx
@@ -7,6 +7,7 @@ import {LoadingOutlined} from "@ant-design/icons";
import {getCookie} from "cookies-next";
import {useRouter} from "next/navigation";
import {API} from "@/lib/API";
+import CheckAuth from "@/components/util/CheckAuth";
export default function Home(){
const router = useRouter();
@@ -30,17 +31,7 @@ export default function Home(){
return (
<>
-
-
-
-
-
SILOS KPR - Tapera Connect
-
Bank Kalteng
-
check authorization
-
-
-
-
+
{
+ let valTheme = localStorage.getItem('valTheme')
+ let state = null
+ if (valTheme == 'true') {
+ state = true
+ document.body.classList.add('darkMode')
+ } else {
+ state = false
+ }
+ const pathname = usePathname()
- const [MenuList, setMenuList] = useState([])
- const [menuTapera, setMenuTapera] = useState([])
- const [menuSilos, setMenuSilos] = useState([])
- const [menuUsers, setMenuUsers] = useState([])
- const [menuManajemenData, setMenuManajemenData] = useState([])
+ const [menuList, setMenuList] = useState([])
+ const {setModalPassword, setModalProfile} = modalStore()
const [current, setCurrent] = useState(null);
const [collapsed, setCollapsed] = useState(false);
- const {toggleStatus, setToggle} = menuStore()
+ const {toggleStatus, setToggle, setLoadingPageStatus} = menuStore()
const {notifOpen} = notifStore()
+ const {removeAuth} = useAuth()
+ const [isTheme, setTheme] = useState(state);
const toggleCollapsed = () => {
setCollapsed(!collapsed);
@@ -40,11 +51,11 @@ const MenuList = () => {
let resultListChildThird = null
if (vChild.childs) {
resultListChildThird = vChild?.childs?.map((vChildThird, kChildThird) => {
- if(vChildThird.url){
+ if (vChildThird.url) {
return {
- label: ( {vChildThird.menuNm}), key: vChildThird.menuId, icon: (
),
+ label: ( eventChange(vChildThird.url)} href={vChildThird.url}>{vChildThird.menuNm}), key: vChildThird.menuId, icon: (
),
}
- }else{
+ } else {
return {
label: vChildThird.menuNm, key: vChildThird.menuId, icon: (
),
}
@@ -53,11 +64,11 @@ const MenuList = () => {
})
}
- if(vChild.url){
+ if (vChild.url) {
tmpChild.push({
- label: ( {vChild.menuNm}), key: vChild.menuId, icon: (
), children: resultListChildThird
+ label: ( eventChange(vChild.url)} href={vChild.url}>{vChild.menuNm}), key: vChild.menuId, icon: (
), children: resultListChildThird
})
- }else{
+ } else {
tmpChild.push({
label: vChild.menuNm, key: vChild.menuId, icon: (
), children: resultListChildThird
@@ -69,14 +80,14 @@ const MenuList = () => {
tmpChild = null
}
- if(v.url){
+ if (v.url) {
tmpMenu.push({
- label: ( {v.menuNm}), key: v.menuId, icon: (
), children: tmpChild
+ label: ( eventChange(v.url)} href={v.url}>{v.menuNm}), key: v.menuId, icon: (
), children: tmpChild
})
- }else{
+ } else {
tmpMenu.push({
- label: v.menuNm, key: v.menuId, icon: (
), children:[{
- key: 'g1', label: 'Menu '+v.menuNm, type: 'group', children: tmpChild
+ label: v.menuNm, key: v.menuId, icon: (
), children: [{
+ key: 'g1', label: 'Menu ' + v.menuNm, type: 'group', children: tmpChild
}]
})
@@ -86,16 +97,20 @@ const MenuList = () => {
console.log(tmpMenu)
- setMenuTapera(tmpMenu)
+ // setMenuTapera(tmpMenu)
// setMenuTapera(tmpMenu.filter((v)=>v.key === 1))
// setMenuSilos(tmpMenu.filter((v)=>v.key === 2))
// setMenuManajemenData(tmpMenu.filter((v)=>v.key === 3))
- // setMenuUsers(tmpMenu.filter((v)=>v.key === 8))
+ setMenuList(tmpMenu.filter((v)=>v.key === 8))
}
}
+ const eventChange = (url) => {
+ if (pathname !== url) setLoadingPageStatus(true)
+ }
+
const getMenuDummy = () => {
const items = [{
key: 'sub1', label: Tapera Connect
, icon: , children: [{
@@ -113,6 +128,45 @@ const MenuList = () => {
setMenuList(items)
}
+ const modalChangeProfile = () => {
+ setModalProfile(true)
+ }
+ const modalChangePassword = (type) => {
+ setModalPassword(true, type)
+ }
+
+ const ViewImage = ({fotoMember}) => {
+ if (fotoMember == null) return ;
+
+ let getImage = '/';
+ return ;
+ };
+
+ const logout = async () => {
+ let response = await API.POST('/auth/logout');
+ if (response.status === 200) {
+ await removeAuth()
+ // router.push("/login");
+ }
+ }
+
+
+ const buttonHandler = (val) => {
+ setTheme((status) => !status);
+ let theme = null
+ if (val != true) {
+ theme = 'lightMode'
+ document.body.classList.add(theme);
+ document.body.classList.remove('darkMode');
+ } else {
+ theme = 'darkMode'
+ document.body.classList.add(theme);
+ document.body.classList.remove('lightMode');
+ }
+ localStorage.setItem('setTheme', theme)
+ localStorage.setItem('valTheme', val)
+ };
+
useEffect(() => {
getMenu()
// getMenuDummy()
@@ -124,38 +178,73 @@ const MenuList = () => {
return (<>
-
-
-
-
-
-
-
GIS - Digital Transaction
-
version {packageJson.version}
+
+
+
+
+
+
+
GIS - Digital Transaction
+
version {packageJson.version}
+
+
+
+
+
+
+
+
+
+
+
+
Zamzam
+
Administrator
+
+
+
+
+
+
+
+
+
+
Administrator
+
Administrator
+
+
+
+
modalChangeProfile()}>Ubah Profil
+
modalChangePassword('normal')}>Ubah Password
+
+ } unCheckedChildren={ } onChange={buttonHandler} checked={isTheme}/>
+
+
+
+ logout()}>Sign Out
-
-
-
-
-
-
- >);
+
+
+
{toggleStatus ? : }
+
+
+
+ >);
};
export default React.memo(MenuList);
diff --git a/src/components/master/Navbar.jsx b/src/components/master/Navbar.jsx
index d473ca1..e69de29 100644
--- a/src/components/master/Navbar.jsx
+++ b/src/components/master/Navbar.jsx
@@ -1,351 +0,0 @@
-"use client";
-import React, {useEffect, useState} from "react";
-import {BellOutlined, CloseOutlined, MenuFoldOutlined, MenuOutlined, MenuUnfoldOutlined, MoonOutlined, SunOutlined, UserOutlined} from '@ant-design/icons';
-import useAuth from "@/hooks/useAuth";
-import {useRouter} from "next/navigation";
-import {useAPI} from "@/hooks/useAPI";
-import modalStore from "@/store/modal";
-import {API} from "@/lib/API";
-import {Button, Drawer, Menu, Switch} from "antd";
-import Link from "next/link";
-import notifStore from "@/store/notifStore";
-import ExportedImage from "next-image-export-optimizer"
-import menuStore from "@/store/menuStore";
-
-function Navbar() {
- const router = useRouter();
- const {notifOpen} = notifStore()
- const {setToggle} = menuStore()
- const {data: dataUser, isSuccess} = useAPI.GET('user', '/ref/user/' + localStorage.getItem('userId'))
- const {removeAuth} = useAuth()
- const [MenuList, setMenuList] = useState([])
- const {setModalPassword, setModalProfile} = modalStore()
- const [current, setCurrent] = useState(null);
- const [collapsed, setCollapsed] = useState(false);
-
-
- const ViewImage = ({fotoMember}) => {
- if (fotoMember == null) return
;
-
- let getImage = '/';
- return
;
- };
-
-
- const logout = async () => {
- let response = await API.GET('/auth/logout');
- console.log(response)
- if (response.status === 200) {
- await removeAuth()
- router.push("/login");
- }
- }
-
- let valTheme = localStorage.getItem('valTheme')
- let state = null
- if (valTheme == 'true') {
- state = true
- document.body.classList.add('darkMode')
- } else {
- state = false
- }
-
- const [isTheme, setTheme] = useState(state);
-
- const buttonHandler = (val) => {
- setTheme((status) => !status);
- let theme = null
- if (val != true) {
- theme = 'lightMode'
- document.body.classList.add(theme);
- document.body.classList.remove('darkMode');
- } else {
- theme = 'darkMode'
- document.body.classList.add(theme);
- document.body.classList.remove('lightMode');
- }
- localStorage.setItem('setTheme', theme)
- localStorage.setItem('valTheme', val)
- };
-
- const modalChangeProfile = () => {
- setModalProfile(true)
- }
- const modalChangePassword = (type) => {
- console.log(type)
- setModalPassword(true, type)
- }
-
- const getMenu = async () => {
- let menu = await API.GET('/ref/menu');
- if (menu.status !== 200) {
- notifOpen("Gagal", menu?.result?.message, "danger");
- } else {
- let tmpMenu = []
- menu?.result?.forEach((v, k) => {
-
- let tmpChild = []
-
- if (v.childs) {
- v?.childs?.forEach((vChild, kChild) => {
-
- let resultListChildThird = null
- if (vChild.childs) {
- resultListChildThird = vChild?.childs?.map((vChildThird, kChildThird) => {
- return {
- label: (
{vChildThird.menuNm}),
- key: vChildThird.menuId,
- icon: (
),
- }
- })
- }
-
- tmpChild.push(
- {
- label: (
{vChild.menuNm}),
- key: vChild.menuId,
- icon: (
),
- children: resultListChildThird
- }
- )
- })
-
- } else {
- tmpChild = null
- }
-
- tmpMenu.push(
- {
- label: (
{v.menuNm}),
- key: v.menuId,
- icon: (
),
- children: tmpChild
- },
- )
- })
-
- setMenuList(tmpMenu)
- }
- }
-
-
- const checkFirstLogin = () => {
- if (dataUser?.result?.userStatusId === 3) {
- modalChangePassword('first')
- }
- }
-
- const checkPasswordExpired = () => {
- if (dataUser?.result?.passwordExpired) {
- modalChangePassword('expired')
- }
- }
-
- useEffect(() => {
- if (isSuccess) {
- checkFirstLogin()
- checkPasswordExpired()
- }
-
- }, [isSuccess]);
-
-
- useEffect(() => {
- getMenu()
-
- }, []);
-
- const onClickMenu = (e) => {
- // console.log('click ', e);
- setCollapsed(!collapsed);
- // document.querySelector(".backdrop").classList.remove("backdropMenu");
- // document.querySelector(".menuInline").classList.remove("in");
- // document.querySelector(".menuInline").classList.add("out");
- setCurrent(e.key);
- };
-
- const [scroll, setScroll] = useState(false);
- useEffect(() => {
- window.addEventListener("scroll", () => {
- setScroll(window.scrollY > 15);
- });
- }, []);
-
- const [openDraw, setOpenDraw] = useState(false);
- const showDrawer = () => {
- setOpenDraw(true);
- };
- const closeDraw = () => {
- setOpenDraw(false);
- };
-
- const toggleCollapsed = () => {
- setCollapsed(!collapsed);
- };
-
- return (
- <>
- {/*
*/}
-
-
-
-
-
-
-
-
-
-
-
-
-
- v0.1.0 {" "}
-
- {/*
System Activity Monitoring
*/}
-
-
- {collapsed ?
: ''}
-
-
-
-
- {/*
*/}
-
-
- {/*
*/}
-
-
-
-
-
-
-
-
-
-
{dataUser?.result?.fullName}
-
{dataUser?.result?.roleNm}
-
-
-
-
-
-
-
-
-
-
{dataUser?.result?.username}
-
Cabang {dataUser?.result?.branchNm}
-
-
-
-
modalChangeProfile()}>Ubah Profil
-
modalChangePassword('normal')}>Ubah Password
-
- } unCheckedChildren={ } onChange={buttonHandler} checked={isTheme}/>
-
-
-
- logout()}>Sign Out
-
-
-
-
-
-
- 9
-
-
-
-
-
-
-
-
- 20 Januari 2024
-
-
-
-
-
Aktifitas
-
update hasil aktifitas
-
-
-
-
-
-
Aktifitas
-
update hasil aktifitas
-
-
-
-
-
-
Aktifitas
-
update hasil aktifitas
-
-
-
-
-
-
- 19 Januari 2024
-
-
-
-
-
Aktifitas
-
update hasil aktifitas
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
-
-export default React.memo(Navbar);
\ No newline at end of file
diff --git a/src/components/refTemplate/Main.jsx b/src/components/refTemplate/Main.jsx
index 5e67c18..06f6aa0 100644
--- a/src/components/refTemplate/Main.jsx
+++ b/src/components/refTemplate/Main.jsx
@@ -1,6 +1,5 @@
"use client";
import React, {useEffect, useRef, useState} from "react";
-import breadcrumbStore from "@/store/breadcrumbStore";
import modalStore from "@/store/modal";
import confirmStore from "@/store/confirmStore";
import {API} from "@/lib/API";
@@ -33,7 +32,7 @@ const RefTemplate = ({
}) => {
const formRef = useRef();
const {modalOpen, modalClose, FormId, modalStat, setModalLoading, setModalDetail, actionType} = modalStore();
- const {setSubTitle, setTitle, setShow} = breadcrumbStore();
+
const {confirmOpen, confirmClose, setConfirmLoading} = confirmStore();
const {notifOpen} = notifStore()
@@ -458,8 +457,6 @@ const RefTemplate = ({
};
useEffect(() => {
- setTitle(refTitle);
- setSubTitle(refSubTitle);
initColumn();
if (!serverSide){
getData();
@@ -486,8 +483,6 @@ const RefTemplate = ({
-
-
{refTitle}
@@ -496,7 +491,7 @@ const RefTemplate = ({
{refSubTitle}
-
+
{
- let setRequired = (required) ? { required: `Data ${title} Harus di Isi` } : {}
- let setMaxLength = (maxlength) ? { maxLength: { value: maxlength, message: `Maksimal ${maxlength} Karakter` } } : {}
-
- let validateList = {...setRequired,...setMaxLength}
+ title, name, register, error, placeholder, maxlength, required, setValue, format = 'DD MMM YYYY', picker = 'default',
+ }) => {
+ let setRequired = (required) ? {required: `Data ${title} Harus di Isi`} : {}
+ let setMaxLength = (maxlength) ? {maxLength: {value: maxlength, message: `Maksimal ${maxlength} Karakter`}} : {}
+
+ let validateList = {...setRequired, ...setMaxLength}
const onChange = (_, dateString) => {
setValue(name, {
- startDate: dateString[0],
- endDate: dateString[1]
- }, { shouldValidate: true })
+ startDate: dateString[0], endDate: dateString[1]
+ }, {shouldValidate: true})
};
const newFormat = Helper.setFormatInputDate(picker, format)
- return (
-
-
-
- {title}
-
-
- {error[name] &&
{error[name]?.message}
}
-
-
- );
- };
-
- export default InputDateRange;
+ return (
+
+
+ {title}
+
+
+ {error[name] &&
{error[name]?.message}
}
+
+
);
+};
+
+export default InputDateRange;
\ No newline at end of file
diff --git a/src/components/util/Input/InputSelect.jsx b/src/components/util/Input/InputSelect.jsx
index 636cff7..f7c037f 100644
--- a/src/components/util/Input/InputSelect.jsx
+++ b/src/components/util/Input/InputSelect.jsx
@@ -13,6 +13,7 @@ const InputSelect = ({
setDisabled,
val,
loading,
+ style,
withSearch = true,
getDataOnChange
}) => {
@@ -33,7 +34,7 @@ const InputSelect = ({
return (
<>
-
+
{
+ const [data, setData] = useState([]);
+ const [loading, setLoading] = useState(false);
+
+ let setRequired = required ? { required: `Data ${title} Harus di Isi` } : {};
+ let validateList = { ...setRequired };
+
+ const handleChange = (value) => {
+ setValue(name, value, { shouldValidate: true });
+ if (getDataOnChange) getDataOnChange(value, setValue);
+ };
+
+ const defaultData = async () => {
+ setLoading(true);
+ let res = await API.GET(endPoint + "?page=0&size=10");
+ const data = res.result.data.map((v) => ({
+ value: v.wilayahId,
+ text: v.wil,
+ }));
+ setData(data)
+ setLoading(false);
+ }
+
+ const fetch = (value, callback) => {
+ if (timeout) {
+ clearTimeout(timeout);
+ timeout = null;
+ }
+ currentValue = value;
+ const getData = async () => {
+ setLoading(true);
+ let res = await API.GET(endPoint + "?page=0&size=10&search=" + value);
+ console.log(res);
+ const data = res.result.data.map((v) => ({
+ value: v.wilayahId,
+ text: v.wil,
+ }));
+ setLoading(false);
+ callback(data);
+ };
+ if (value) {
+ timeout = setTimeout(getData, 1000);
+ } else {
+ callback([]);
+ }
+ };
+
+ const handleSearch = (newValue) => {
+ setData([[]])
+ fetch(newValue, setData);
+ };
+
+ useEffect(() => {
+ defaultData()
+ }, []);
+
+ const getById = async (id) => {
+ setLoading(true);
+ let res = await API.GET(endPoint + "/" + id);
+
+ setLoading(false);
+ setData([{
+ value: res?.result?.wilayahId,
+ text: res?.result?.wil,
+ }]);
+ }
+
+ useEffect(() => {
+ if (val){
+ getById(val)
+ }
+ }, [val]);
+
+ return (
+ <>
+
+
+ Data tidak ditemukan
}
+ options={(data || []).map((d) => ({
+ value: d.value,
+ label: d.text,
+ }))}
+ />
+
+
+ {title}{" "}
+ {required ? * : ""}
+
+ {error[name] && (
+
{error[name]?.message}
+ )}
+
+
+ >
+ );
+};
+
+export default InputSelectRemote;
diff --git a/src/components/util/Input/index.jsx b/src/components/util/Input/index.jsx
index 0973f1a..8a3e938 100644
--- a/src/components/util/Input/index.jsx
+++ b/src/components/util/Input/index.jsx
@@ -15,12 +15,14 @@ import InputCustom from "./InputCustom";
import InputPercentage from "./InputPercentage";
import InputSwitch from "./InputSwitch";
import InputAntFile from "./InputAntFile";
+import InputSelectRemote from "@/components/util/Input/InputSelectRemote";
const Input = {
Text: InputText,
Number: InputNumber,
Money: InputMoney,
Select: InputSelect,
+ SelectRemote: InputSelectRemote,
Username: InputUsername,
Email: InputEmail,
Password: InputPassword,
@@ -36,23 +38,4 @@ const Input = {
AntFile: InputAntFile
}
-export const REF_INPUT_NAME = {
- TEXT: 'Text',
- NUMBER: 'Number',
- MONEY: 'Money',
- SELECT: 'Select',
- USERNAME: 'Username',
- EMAIL: 'Email',
- PASSWORD: 'Password',
- TEXTAREA: 'Textarea',
- IMAGE: 'Image',
- DATERANGE: 'DateRange',
- TEXT_TASK: 'TextTask',
- DATE: 'Date',
- UPLOAD_IMAGE: 'UploadImage',
- CUSTOM: 'Custom',
- PERCENTAGE: 'Percentage',
- SWITCH: 'Switch',
-}
-
export default Input
diff --git a/src/components/util/LoadingPage.jsx b/src/components/util/LoadingPage.jsx
index 08c763f..84bf79c 100644
--- a/src/components/util/LoadingPage.jsx
+++ b/src/components/util/LoadingPage.jsx
@@ -2,18 +2,18 @@ import React from 'react'
import NextTopLoader from 'nextjs-toploader';
const LoadingPage = () => {
- return (
-
- )
+ return (
+
+ )
}
export default LoadingPage
\ No newline at end of file
diff --git a/src/components/util/WrapperContent.jsx b/src/components/util/WrapperContent.jsx
index 0f77479..e654612 100644
--- a/src/components/util/WrapperContent.jsx
+++ b/src/components/util/WrapperContent.jsx
@@ -1,12 +1,22 @@
import {motion} from "framer-motion"
+import {useEffect} from "react";
+import {useRouter} from "next/navigation";
+import menuStore from "@/store/menuStore";
export default function WrapperContent({children,type}) {
+
+ const router = useRouter()
+ const {setLoadingPageStatus} = menuStore()
+
+ useEffect(() => {
+ setLoadingPageStatus(false)
+ }, [router]);
return(
<>
{children}
diff --git a/src/lib/DropdownAPI.jsx b/src/lib/DropdownAPI.jsx
index cb242db..571da46 100644
--- a/src/lib/DropdownAPI.jsx
+++ b/src/lib/DropdownAPI.jsx
@@ -9,451 +9,89 @@ const role = async () => {
};
});
}
- const cabang = async () => {
+const cabang = async () => {
let response = await API.GET(`/ref/branch`);
return response?.result?.data?.map((v) => {
return {
- value: v.kdCab,
- label: v.namaCabang,
+ value: v.branchId,
+ label: v.nm,
};
});
}
-const productType = async () => {
- let response = await API.GET(`/ref/productType`);
+const divisi = async () => {
+ let response = await API.GET(`/ref/divisi`);
return response?.result?.data?.map((v) => {
return {
- value: v.productTypeId,
- label: v.definition,
+ value: v.divisiId,
+ label: v.divisiNm,
};
});
}
-const product = async () => {
- let response = await API.GET(`/ref/product`);
+const agama = async () => {
+ let response = await API.GET(`/ref/agama`);
return response?.result?.data?.map((v) => {
return {
- value: v.id,
- label: v.prodName,
+ value: v.agamaId,
+ label: v.agamaNm,
};
});
}
-
-const branchType = async () => {
- let response = await API.GET(`/ref/branch-type`);
+const jabatan = async () => {
+ let response = await API.GET(`/ref/jabatan`);
return response?.result?.data?.map((v) => {
return {
- value: v.id,
- label: v.definition,
+ value: v.jabatanId,
+ label: v.jabatanNm,
};
});
}
-
-const branch = async () => {
- let response = await API.GET(`/ref/branch`);
- return response?.result?.data?.map((v) => {
- return {
- value: v.id,
- label: v.branchName,
- };
- });
-}
-
-const wilayah = async () => {
- let response = await API.GET(`/ref/wilayah`);
- return response?.result?.data?.map((v) => {
- return {
- value: v.wilayahId,
- label: v.wil,
- };
- });
-}
-
-const bank = async () => {
- let response = await API.GET(`/ref/bank`);
- return response?.result?.data?.map((v) => {
- return {
- value: v.bankCode,
- label: v.bankDescription,
- };
- });
-}
-
-const productGroup = async () => {
- let response = await API.GET(`/ref/group-product`);
- return response?.result?.data?.map((v) => {
- return {
- value: v.id,
- label: v.productGrpName,
- };
- });
-}
-
-const developer = async () => {
- let response = await API.GET(`/ref/developer`);
- return response?.result?.data?.map((v) => {
- return {
- value: v.id,
- label: v.developerName,
- };
- });
-}
-
-const productCode = async () => {
- let response = await API.GET(`/cbs/loan-product`);
- return response?.result?.data?.map((v) => {
- return {
- value: v.prodid,
- label: v.prodnm,
- };
- });
-}
-
-const aplId = async () => {
- let response = await API.GET(`/cbs-config/applid`);
- return response?.result?.data?.map((v) => {
- return {
- value: v.parmid,
- label: v.parmnm,
- };
- });
-}
-
-const govPRG = async () => {
- let response = await API.GET(`/cbs-config/govprg`);
- return response?.result?.data?.map((v) => {
- return {
- value: v.parmid,
- label: v.parmnm,
- };
- });
-}
-
-const proposalType = async () => {
- let response = await API.GET(`/ref/proposal-type`);
- return response?.result?.data?.map((v) => {
- return {
- value: v.id,
- label: v.definition,
- };
- });
-}
-
-const workflowStatus = async () => {
- let response = await API.GET(`/ref/workflow-status`);
- return response?.result?.data?.map((v) => {
- return {
- value: v.id,
- label: v.statusDefinition,
- };
- });
-}
-
-const groupUser = async () => {
- let response = await API.GET(`/ref/user-group`);
- return response?.result?.data?.map((v) => {
- return {
- value: v.id,
- label: v.groupDefinition,
- };
- });
-}
-
-const workflowType = async () => {
- let response = await API.GET(`/ref/workflow-type`);
- return response?.result?.data?.map((v) => {
- return {
- value: v.id,
- label: v.definition,
- };
- });
-}
-
-const pekerjaanPPDPP = async () => {
- let response = await API.GET(`/ref/pekerjaan-ppdpp`);
- return response?.result?.data?.map((v) => {
- return {
- value: v.pekerjaan,
- label: v.nmPekerjaan,
- };
- });
-}
-
-const statusPembiayaan = async () => {
- let response = await API.GET(`/ref/status-pembiayaan`);
- return response?.result?.data?.map((v) => {
- return {
- value: v.statusPembiayaan,
- label: v.namaStatusPembiayaan,
- };
- });
-}
-
-const pekerjaan = async () => {
- let response = await API.GET(`/ref/pekerjaan`);
- return response?.result?.data?.map((v) => {
- return {
- value: v.idPekerjaan,
- label: v.nmPekerjaan,
- };
- });
-}
-
-const accountTypeFLPP = async () => {
- let response = await API.GET(`/ref/jenis_accflpp`);
- return response?.result?.data?.map((v) => {
- return {
- value: v.id,
- label: v.definition,
- };
- });
-}
-
-const masterGroupScoring = async () => {
- let response = await API.GET(`/ref/master-group-scoring`);
- return response?.result?.data?.map((v) => {
- return {
- value: v.id,
- label: v.paramName,
- };
- });
-}
-
-const developerScoring = async () => {
- let response = await API.GET(`/ref/developer-param-scoring`);
- return response?.result?.data?.map((v) => {
- return {
- value: v.id,
- label: v.definition,
- };
- });
-}
-
-const productTapera = async (filter = '') => {
- if ( filter ) {
- filter = '?' + new URLSearchParams(filter).toString()
- }
-
- let response = await API.GET(`/ref-tapera/product${filter}`);
- return response?.result?.data?.map((v) => {
- return {
- value: v.id,
- label: v.namaProduk,
- };
- });
-}
-
-const jenisPerumahanTapera = async () => {
- let response = await API.GET(`/ref-tapera/jenis-perumahan`);
- return response?.result?.data?.map((v) => {
- return {
- value: v.id,
- label: v.definition,
- };
- });
-}
-
-const perumahanTapera = async () => {
- let response = await API.GET(`/ref-tapera/rumah`);
- return response?.result?.data?.map((v) => {
- return {
- value: v.idRumah,
- label: v.namaPerumahan,
- ...v
- };
- });
-}
-
-const wilayahTapera = async () => {
- let response = await API.GET(`/ref-tapera/wilayah/dropdown`);
- return response?.result?.map((v) => {
- return {
- value: v.wilayahId,
- label: v.wil,
- };
- });
-}
-
-const jenisImbPbg = async () => {
- let response = await API.GET(`/ref-tapera/jenis-imb/dropdown`);
- return response?.result?.map((v) => {
- return {
- value: v.id,
- label: v.definition,
- };
- });
-}
-
-const segemenPekerjaan = async () => {
- let response = await API.GET(`/ref-tapera/segmen-pekerjaan/dropdown`);
- return response?.result?.map((v) => {
- return {
- value: v.segmenCode,
- label: v.definition,
- };
- });
-}
-
-const jenisAkadTapera = async () => {
- let response = await API.GET(`/ref-tapera/jenis-akad/dropdown`);
- return response?.result?.map((v) => {
- return {
- value: v.id,
- label: v.definition,
- };
- });
-}
-
-const jenisBungaTapera = async () => {
- let response = await API.GET(`/ref-tapera/jenis-bunga/dropdown`);
- return response?.result?.map((v) => {
- return {
- value: v.id,
- label: v.definition,
- };
- });
-}
-
-const jenisPembayaranAngsuran = async () => {
- let response = await API.GET(`/ref-tapera/jenis-bayar-angsuran/dropdown`);
- return response?.result?.map((v) => {
- return {
- value: v.id,
- label: v.definition,
- };
- });
-}
-
const jenisKelamin = async () => {
- let response = await API.GET(`/ref/jenis-kelamin`);
+ let response = await API.GET(`/ref/jenisKelamin`);
return response?.result?.data?.map((v) => {
return {
- value: v.id,
- label: v.description,
+ value: v.jenisKelaminId,
+ label: v.jenisKelaminNm,
};
});
}
-
-const statusKawin = async () => {
- let response = await API.GET(`/ref/status-kawin`);
+const statusKaryawan = async () => {
+ let response = await API.GET(`/ref/statusKaryawan`);
return response?.result?.data?.map((v) => {
return {
- value: v.idStatusKawin,
- label: v.nmStatusKawin,
+ value: v.statusKaryawanId,
+ label: v.statusKaryawanNm,
};
});
}
-const jenisPembiayaan = async () => {
- let response = await API.GET(`/ref-tapera/jenis-pembiayaan`);
+const karyawan = async () => {
+ let response = await API.GET(`/ref/karyawan`);
return response?.result?.data?.map((v) => {
return {
- value: v.id,
- label: v.definition,
+ value: v.karyawanId,
+ label: v.karyawanNm,
};
});
}
-
-const prinsipPembiayaan = async () => {
- let response = await API.GET(`/ref-tapera/prinsip-pembiayaan`);
+const jenisPenjadwalan = async () => {
+ let response = await API.GET(`/ref/tipeQuotes`);
return response?.result?.data?.map((v) => {
return {
- value: v.id,
- label: v.definition,
+ value: v.tipeQuotesId,
+ label: v.tipeQuotesNm,
};
});
}
-const tipeProgram = async () => {
- let response = await API.GET(`/ref-tapera/tipe-program`);
- return response?.result?.data?.map((v) => {
- return {
- value: v.id,
- label: v.definition,
- };
- });
-}
-
-const lokasiPerumahanTapera = async () => {
- let response = await API.GET(`/ref-tapera/perumahaan/dropdown`);
- return response?.result?.map((v) => {
- return {
- value: v.idLokasi,
- label: v.namaPerumahan,
- };
- });
-}
-
-const kolektibilitas = async () => {
- let response = await API.GET(`/ref-tapera/kolektibilitas`);
- return response?.result?.data?.map((v) => {
- return {
- value: v.id,
- label: v.definition,
- };
- });
-}
-
-const developerTapera = async () => {
- let response = await API.GET(`/ref-tapera/developer`);
- return response?.result?.data?.map((v) => {
- return {
- value: v.id,
- label: v.developerName,
- };
- });
-}
-
-const jenisSertifikat = async () => {
- let response = await API.GET(`/ref/jenis-sertifikat`);
- return response?.result?.data?.map((v) => {
- return {
- value: v.id,
- label: v.defJenis,
- };
- });
-}
-
-
export const DropdownAPI = {
role,
cabang,
- productType,
- branchType,
- branch,
- bank,
- wilayah,
- productGroup,
- productCode,
- aplId,
- govPRG,
- developer,
- product,
- proposalType,
- workflowStatus,
- groupUser,
- workflowType,
- pekerjaanPPDPP,
- statusPembiayaan,
- pekerjaan,
- accountTypeFLPP,
- masterGroupScoring,
- developerScoring,
- productTapera,
- jenisPerumahanTapera,
- perumahanTapera,
- wilayahTapera,
- jenisImbPbg,
- segemenPekerjaan,
- jenisAkadTapera,
- jenisBungaTapera,
- jenisPembayaranAngsuran,
+ divisi,
+ agama,
+ jabatan,
jenisKelamin,
- statusKawin,
- jenisPembiayaan,
- prinsipPembiayaan,
- tipeProgram,
- lokasiPerumahanTapera,
- kolektibilitas,
- developerTapera,
- jenisSertifikat
+ statusKaryawan,
+ karyawan,
+ jenisPenjadwalan
};
diff --git a/src/store/breadcrumbStore.js b/src/store/breadcrumbStore.js
deleted file mode 100644
index 458d688..0000000
--- a/src/store/breadcrumbStore.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import {create} from 'zustand';
-
-const breadcrumbStore = create((set) => ({
- title: '',
- subTitle: '',
- widthTitle: '0px',
- setTitle: (data) => set(() => ({title: data})),
- setSubTitle: (data) => set(() => ({subTitle: data})),
- setHide: () => set(() => ({widthTitle: '0px'})),
- setShow: () => set(() => ({widthTitle: '270px'})),
-
-
-}));
-
-export default breadcrumbStore;
\ No newline at end of file
diff --git a/src/store/menuStore.js b/src/store/menuStore.js
index 5356db0..3672284 100644
--- a/src/store/menuStore.js
+++ b/src/store/menuStore.js
@@ -2,7 +2,9 @@ import {create} from 'zustand';
const menuStore = create((set) => ({
toggleStatus: true,
+ loadingPageStatus:false,
setToggle: () => set((prev) => ({toggleStatus: !prev.toggleStatus})),
+ setLoadingPageStatus: (stat) => set((prev) => ({loadingPageStatus: stat})),
}));
export default menuStore;
\ No newline at end of file
diff --git a/src/store/modalDashboard.js b/src/store/modalDashboard.js
deleted file mode 100644
index c0fb52b..0000000
--- a/src/store/modalDashboard.js
+++ /dev/null
@@ -1,96 +0,0 @@
-import {create} from "zustand";
-
-const modalDashboardStore = create((set) => ({
- modalStat: false,
- modalLoading: false,
- FormId: null,
- actionType: null,
- typeData: null,
- typeKolek: null,
- datatableDetail: false,
- datatableDetailCabang: false,
- datatableDetailKolektability: false,
- datatableDetailNasabah: false,
- dataNasabah: false,
- kdCabangKonsol: null,
- kdCabang: null,
- nmCabangKonsol: null,
- nmCabang: null,
- customerId: null,
- title: null,
- subTitle: null,
- modalOpen: (id, action) =>
- set(() => ({
- modalStat: true,
- modalLoading: true,
- FormId: id,
- actionType: action
- })),
- modalClose: () =>
- set(() => ({
- modalStat: false,
- FormId: null,
- })),
- setModalLoading: (status, type) =>
- set(() => ({
- modalLoading: status,
- })),
- setTypeData: (text) =>
- set(() => ({
- typeData: text
- })),
- setTypeKolek: (text) =>
- set(() => ({
- typeKolek: text
- })),
- setDatatableDetail: (status) =>
- set(() => ({
- datatableDetail: status
- })),
- setDatatableDetailCabang: (status) =>
- set(() => ({
- datatableDetailCabang: status
- })),
- setDatatableDetailKolektability: (status) =>
- set(() => ({
- datatableDetailKolektability: status
- })),
- setDatatableDetailNasabah: (status) =>
- set(() => ({
- datatableDetailNasabah: status
- })),
- setDataNasabah: (status) =>
- set(() => ({
- dataNasabah: status
- })),
- setKdCabangKonsol: (status) =>
- set(() => ({
- kdCabangKonsol: status
- })),
- setKdCabang: (status) =>
- set(() => ({
- kdCabang: status
- })),
- setNmCabangKonsol: (status) =>
- set(() => ({
- nmCabangKonsol: status
- })),
- setNmCabang: (status) =>
- set(() => ({
- nmCabang: status
- })),
- setCustomerId: (status) =>
- set(() => ({
- customerId: status
- })),
- setTitle: (status) =>
- set(() => ({
- title: status
- })),
- setSubTitle: (status) =>
- set(() => ({
- subTitle: status
- }))
-}));
-
-export default modalDashboardStore;
diff --git a/src/store/store.js b/src/store/store.js
deleted file mode 100644
index 926ff9a..0000000
--- a/src/store/store.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import {create} from 'zustand';
-
-const useStore = create((set) => ({
- count: 0,
- increment: () => set((state) => ({ count: state.count + 1 })),
- decrement: () => set((state) => ({ count: state.count - 1 })),
-}));
-
-export default useStore;
\ No newline at end of file