From a3249dc8424e5bf98392deefd57cd30769d6febc Mon Sep 17 00:00:00 2001 From: wayanrivan Date: Tue, 20 May 2025 11:17:47 +0700 Subject: [PATCH 01/15] update --- .../blocks/DetailApprovalTransaction.tsx | 39 ++++++++++--------- .../blocks/DetailTransaction.tsx | 10 ++--- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/pages/transaction/approval-transaction/blocks/DetailApprovalTransaction.tsx b/src/pages/transaction/approval-transaction/blocks/DetailApprovalTransaction.tsx index 03e2708..1378a2e 100644 --- a/src/pages/transaction/approval-transaction/blocks/DetailApprovalTransaction.tsx +++ b/src/pages/transaction/approval-transaction/blocks/DetailApprovalTransaction.tsx @@ -683,11 +683,11 @@ const DetailApprovalTransaction = () => { - + + - @@ -861,14 +861,14 @@ const DetailApprovalTransaction = () => { + - {transactionDetails?.p24 && transactionDetails?.p24.length > 0 ? ( - transactionDetails.p24.map((log: { status: string,request_endpoint: string, type: string; request_date: string; response_date: string; request_body: string; response_body: string; response_code: number }, index: number) => ( + transactionDetails.p24.map((log: { status: string, request_endpoint: string, type: string; request_date: string; response_date: string; request_body: string; response_body: string; response_code: number }, index: number) => ( + - diff --git a/src/pages/transaction/history-transaction/blocks/DetailTransaction.tsx b/src/pages/transaction/history-transaction/blocks/DetailTransaction.tsx index 904d901..9e44562 100644 --- a/src/pages/transaction/history-transaction/blocks/DetailTransaction.tsx +++ b/src/pages/transaction/history-transaction/blocks/DetailTransaction.tsx @@ -748,8 +748,8 @@ const DetailTransaction = () => { + - @@ -922,14 +922,14 @@ const DetailTransaction = () => { + - {transactionDetails?.p24 && transactionDetails?.p24.length > 0 ? ( - transactionDetails.p24.map((log: { status: string,request_endpoint: string, type: string; request_date: string; response_date: string; request_body: string; response_body: string; response_code: number }, index: number) => ( + transactionDetails.p24.map((log: { status: string, request_endpoint: string, type: string; request_date: string; response_date: string; request_body: string; response_body: string; response_code: number }, index: number) => (
Transaction StatusStatus Request Date Response DateRequest Body Response BodyResponse Code Request Endpoint
Status Request Date Response DateRequest Body Response BodyResponse Code Request Endpoint
{(() => { @@ -912,6 +912,22 @@ const DetailApprovalTransaction = () => { hour12: false }) : ''} +
+                                                                    {(() => {
+                                                                        try {
+                                                                            if (log.request_body === null) {
+                                                                                return '';
+                                                                            }
+                                                                            const parsed = JSON.parse(log.request_body);
+                                                                            return JSON.stringify(parsed, null, 2) ?? '';
+                                                                        } catch (e) {
+                                                                            return log.request_body ?? ''; // fallback: tampilkan as-is jika gagal parse
+                                                                        }
+                                                                    })()}
+                                                                
+ +
                                                                     {(() => {
@@ -927,22 +943,7 @@ const DetailApprovalTransaction = () => {
                                                                     })()}
                                                                 
-
-                                                                    {(() => {
-                                                                        try {
-                                                                            if (log.request_body === null) {
-                                                                                return '';
-                                                                            }
-                                                                            const parsed = JSON.parse(log.request_body);
-                                                                            return JSON.stringify(parsed, null, 2) ?? '';
-                                                                        } catch (e) {
-                                                                            return log.response_body ?? ''; // fallback: tampilkan as-is jika gagal parse
-                                                                        }
-                                                                    })()}
-                                                                
-
{log.request_endpoint ?? ''}Status Request Date Response DateRequest Body Response BodyResponse Code Request Endpoint
Status Request Date Response DateRequest Body Response BodyResponse Code Request Endpoint
{(() => { @@ -992,10 +992,10 @@ const DetailTransaction = () => {
                                                                     {(() => {
                                                                         try {
-                                                                            if (log.request_body === null) {
+                                                                            if (log.response_body === null) {
                                                                                 return '';
                                                                             }
-                                                                            const parsed = JSON.parse(log.request_body);
+                                                                            const parsed = JSON.parse(log.response_body);
                                                                             return JSON.stringify(parsed, null, 2) ?? '';
                                                                         } catch (e) {
                                                                             return log.response_body ?? ''; // fallback: tampilkan as-is jika gagal parse

From 0569a9d361397ff12d7e1354f7a525376e809911 Mon Sep 17 00:00:00 2001
From: bagusajisaputroo 
Date: Tue, 20 May 2025 11:21:14 +0700
Subject: [PATCH 02/15] credit limit to credit limit per trx on wallet rule

---
 src/pages/master/walletRule/blocks/AddDialog.tsx              | 2 +-
 src/pages/master/walletRule/blocks/EditDialog.tsx             | 2 +-
 src/pages/master/walletRule/hooks/ManageWalletRuleContext.tsx | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/pages/master/walletRule/blocks/AddDialog.tsx b/src/pages/master/walletRule/blocks/AddDialog.tsx
index c9e4d72..92c70cb 100644
--- a/src/pages/master/walletRule/blocks/AddDialog.tsx
+++ b/src/pages/master/walletRule/blocks/AddDialog.tsx
@@ -293,7 +293,7 @@ const AddDialog = () => {
                 
{
row.credit_limit, id: 'credit_limit', - header: ({ column }) => , + header: ({ column }) => , enableSorting: true, enableHiding: false, cell: ({ row }) => currencyFormat(row.original.credit_limit), From 244b0c9bf873bab44d50d1f1eb5c26b3c3ff17a0 Mon Sep 17 00:00:00 2001 From: bagusajisaputroo Date: Tue, 20 May 2025 11:36:02 +0700 Subject: [PATCH 03/15] type should 'D' on disbursement --- .../history-transaction/blocks/UploadBatchDialog.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/disbursement/history-transaction/blocks/UploadBatchDialog.tsx b/src/pages/disbursement/history-transaction/blocks/UploadBatchDialog.tsx index 15bc730..69e4de3 100644 --- a/src/pages/disbursement/history-transaction/blocks/UploadBatchDialog.tsx +++ b/src/pages/disbursement/history-transaction/blocks/UploadBatchDialog.tsx @@ -138,7 +138,7 @@ const UploadBatchDialog = () => { filter: JSON.stringify({}) }); - const validTypes = ['DM', 'DA', 'DE']; + const validTypes = ['D']; const records: TransferType[] = response?.data?.list ?? []; const filtered = records.filter((item) => validTypes.includes(item.type)); @@ -225,7 +225,7 @@ const UploadBatchDialog = () => { setFormField((prev) => ({ ...prev, id_transaction_type: val })) } > - + From 16cd2ca64e5262a1db228abfc13a3ecc4237f166 Mon Sep 17 00:00:00 2001 From: bagusajisaputroo Date: Tue, 20 May 2025 13:24:12 +0700 Subject: [PATCH 04/15] change filter type:D direct from API disbursement --- .../history-transaction/blocks/UploadBatchDialog.tsx | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/pages/disbursement/history-transaction/blocks/UploadBatchDialog.tsx b/src/pages/disbursement/history-transaction/blocks/UploadBatchDialog.tsx index 69e4de3..688d4ac 100644 --- a/src/pages/disbursement/history-transaction/blocks/UploadBatchDialog.tsx +++ b/src/pages/disbursement/history-transaction/blocks/UploadBatchDialog.tsx @@ -135,15 +135,11 @@ const UploadBatchDialog = () => { with_deleted: false, order_field: 'id', order_direction: 'ASC', - filter: JSON.stringify({}) + filter: JSON.stringify({ type: "D" }) }); - const validTypes = ['D']; const records: TransferType[] = response?.data?.list ?? []; - - const filtered = records.filter((item) => validTypes.includes(item.type)); - - setTransferTypes(filtered); + setTransferTypes(records); } catch (error) { console.error('Failed to fetch transfer types', error); } @@ -256,4 +252,4 @@ const UploadBatchDialog = () => { ); }; -export { UploadBatchDialog }; +export { UploadBatchDialog }; \ No newline at end of file From 189a5450841e01983aacfceb1c084ec78f8043b4 Mon Sep 17 00:00:00 2001 From: wayanrivan Date: Tue, 20 May 2025 13:53:52 +0700 Subject: [PATCH 05/15] update page dashboard conditional for cards bank and transaction detail --- src/auth/_models.ts | 1 + src/auth/providers/JWTProvider.tsx | 59 +++-- .../dashboards/home/DashboardHomePage.tsx | 2 +- .../blocks/DetailTransaction.tsx | 210 ++++++++++-------- 4 files changed, 152 insertions(+), 120 deletions(-) diff --git a/src/auth/_models.ts b/src/auth/_models.ts index a580966..8bf87ed 100644 --- a/src/auth/_models.ts +++ b/src/auth/_models.ts @@ -9,6 +9,7 @@ export interface AuthModel { company: any; user: any; // api_token: string; + statusbalance: string; } export interface UserModel { diff --git a/src/auth/providers/JWTProvider.tsx b/src/auth/providers/JWTProvider.tsx index 934d228..ec33b0d 100644 --- a/src/auth/providers/JWTProvider.tsx +++ b/src/auth/providers/JWTProvider.tsx @@ -43,24 +43,6 @@ const AuthProvider = ({ children }: PropsWithChildren) => { const [auth, setAuth] = useState(authHelper.getAuth()); const [currentUser, setCurrentUser] = useState(); - const verify = async () => { - if (auth) { - try { - const { data: user } = await getUser(); - const createCacheUser = { - name: user.name, - email: user.email, - username: user.username, - role_name: auth.role_name - }; - localStorage.setItem('user', JSON.stringify(createCacheUser)); - } catch { - saveAuth(undefined); - setCurrentUser(undefined); - } - } - }; - const saveAuth = (auth: AuthModel | undefined) => { setAuth(auth); if (auth) { @@ -73,11 +55,20 @@ const AuthProvider = ({ children }: PropsWithChildren) => { const login = async (username: string, password: string) => { try { const { data: auth } = await axios - .post(LOGIN_URL, { username, password }) // , { headers: { 'Access-Control-Allow-Origin': "*" }} + .post(LOGIN_URL, { username, password }) .then((response) => response.data); - saveAuth({ ...auth.token, id: auth.user.id, role_name: auth.role_name, user: auth.user }); + const enhancedAuth: AuthModel = { + ...auth.token, + id: auth.user.id, + role_name: auth.role_name, + user: auth.user, + statusbalance: auth.role.status_balance + }; + + saveAuth(enhancedAuth); setCurrentUser(auth.user); + const createActivity = { module: 'Login', description: `Login`, @@ -108,6 +99,33 @@ const AuthProvider = ({ children }: PropsWithChildren) => { return { data: _axios }; }; + const verify = async () => { + if (auth) { + try { + const { data: user } = await getUser(); + + // Perbarui auth yang sekarang dengan statusbalance + saveAuth({ + ...auth, + statusbalance: user.role.status_balance + }); + + const createCacheUser = { + name: user.name, + email: user.email, + username: user.username, + role_name: auth.role_name, + statusbalance: user.role.status_balance + }; + + localStorage.setItem('user', JSON.stringify(createCacheUser)); + } catch { + saveAuth(undefined); + setCurrentUser(undefined); + } + } + }; + const logout = async () => { const createActivity = { module: 'Logout', @@ -130,7 +148,6 @@ const AuthProvider = ({ children }: PropsWithChildren) => { currentUser, setCurrentUser, login, - // register, requestPasswordResetLink, changePassword, getUser, diff --git a/src/pages/dashboards/home/DashboardHomePage.tsx b/src/pages/dashboards/home/DashboardHomePage.tsx index 0353ee8..a42faee 100644 --- a/src/pages/dashboards/home/DashboardHomePage.tsx +++ b/src/pages/dashboards/home/DashboardHomePage.tsx @@ -268,7 +268,7 @@ const DashboardHomePage = () => { ) : null}
- {bankaccount?.data && bankaccount?.data.length > 0 ? ( + {bankaccount?.data && bankaccount?.data.length > 0 && getAuth()?.statusbalance=='Y' ? ( bankaccount?.data.map((bankaccountdatas: { amount: string, creditlimit: string, monthlylimit: string; wallet: string; }, index: number) => ( { {/* )} */} + {transactionDetails?.kind == 'P' && ( + + )} + + {transactionDetails?.kind == 'P' && ( + + )} +
- {/* Tab Content */} + {activeTab === 'purchase' && ( + <> +

+ Purchase +

+
+
+

Amount

+

+ {new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format( + transactionDetails?.purchase?.amount ?? transactionDetails?.transfer?.amount ?? 0 + )} +

+
+
+

Cashback

+

+ {new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format( + transactionDetails?.purchase?.cashback ?? transactionDetails?.transfer?.cashback ?? 0 + )} +

+
+
+

Cashback Point

+

+ {transactionDetails?.purchase?.cashback_point ?? transactionDetails?.transfer?.cashback_point ?? 0} +

+
+
+

Fee Amount

+

+ {new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format( + transactionDetails?.purchase?.fee_amount ?? transactionDetails?.transfer?.fee_amount ?? 0 + )} +

+
+
+ + )} + + {activeTab === 'productdetail' && ( + <> +
+

+ Product Information +

+
+
+

Product Name

+

+ {transactionDetails?.purchase?.product?.name ?? "-"} +

+
+
+

Price Cash

+

+ {transactionDetails?.purchase?.product?.price_cash != null + ? new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(transactionDetails.purchase.product.price_cash) + : "-"} +

+
+
+

Price Point

+

+ {transactionDetails?.purchase?.product?.price_point ?? "-"} +

+
+
+

Product Type

+

+ {transactionDetails?.purchase?.product?.type ?? "-"} +

+
+
+

Provider Name

+

+ {transactionDetails?.purchase?.product?.provider?.description ?? "-"} +

+
+
+

Provider Type

+

+ {transactionDetails?.purchase?.product?.provider?.type === "h2h" + ? "HOST TO HOST" + : transactionDetails?.purchase?.product?.provider?.type === "agent" + ? "AGENT" + : "-"} +

+
+
+
+ + )} +
{activeTab === 'detail' && transactionDetails?.kind === 'P' && (

Transaction Information - - Info -

@@ -363,100 +471,6 @@ const DetailTransaction = () => {
-

- Purchase - - Purchase - -

-
-
-

Amount

-

- {new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format( - transactionDetails?.purchase?.amount ?? transactionDetails?.transfer?.amount ?? 0 - )} -

-
-
-

Cashback

-

- {new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format( - transactionDetails?.purchase?.cashback ?? transactionDetails?.transfer?.cashback ?? 0 - )} -

-
-
-

Cashback Point

-

- {transactionDetails?.purchase?.cashback_point ?? transactionDetails?.transfer?.cashback_point ?? 0} -

-
-
-

Fee Amount

-

- {new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format( - transactionDetails?.purchase?.fee_amount ?? transactionDetails?.transfer?.fee_amount ?? 0 - )} -

-
-
-
- )} - - - {activeTab === 'detail' && transactionDetails?.kind == 'P' && transactionDetails?.kind == 'P' && ( -
-

- Product Information - - Product Info - -

-
-
-

Product Name

-

- {transactionDetails?.purchase?.product?.name ?? "-"} -

-
-
-

Price Cash

-

- {transactionDetails?.purchase?.product?.price_cash != null - ? new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(transactionDetails.purchase.product.price_cash) - : "-"} -

-
-
-

Price Point

-

- {transactionDetails?.purchase?.product?.price_point ?? "-"} -

-
-
-

Product Type

-

- {transactionDetails?.purchase?.product?.type ?? "-"} -

-
-
-

Provider Name

-

- {transactionDetails?.purchase?.product?.provider?.description ?? "-"} -

-
-
-

Provider Type

-

- {transactionDetails?.purchase?.product?.provider?.type === "h2h" - ? "HOST TO HOST" - : transactionDetails?.purchase?.product?.provider?.type === "agent" - ? "AGENT" - : "-"} -

-
-
)} From 933c32f2b53f1eaa9df0f33f46021ef4690836b4 Mon Sep 17 00:00:00 2001 From: wayanrivan Date: Tue, 20 May 2025 14:01:46 +0700 Subject: [PATCH 06/15] update --- .../history-transaction/blocks/DetailTransaction.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/transaction/history-transaction/blocks/DetailTransaction.tsx b/src/pages/transaction/history-transaction/blocks/DetailTransaction.tsx index d99ba71..84e3420 100644 --- a/src/pages/transaction/history-transaction/blocks/DetailTransaction.tsx +++ b/src/pages/transaction/history-transaction/blocks/DetailTransaction.tsx @@ -499,7 +499,7 @@ const DetailTransaction = () => {

Full Name

-

{transactionDetails?.origin_customer?.fullname ?? transactionDetails?.origin_customer?.origin_name}

+

{transactionDetails?.origin_customer?.origin_name ?? ""}

Amount

@@ -611,7 +611,7 @@ const DetailTransaction = () => {

Phone Number

{transactionDetails?.origin_msisdn}

-

{transactionDetails?.origin_customer?.fullname ?? transactionDetails?.origin_customer?.origin_name}

+

{transactionDetails?.origin_customer?.origin_name ?? ""}

Phone Number

From f162db0f1566dc20e8201633dfbadcfd7f5177fb Mon Sep 17 00:00:00 2001 From: wayanrivan Date: Tue, 20 May 2025 14:03:08 +0700 Subject: [PATCH 07/15] update --- .../history-transaction/blocks/DetailTransaction.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/transaction/history-transaction/blocks/DetailTransaction.tsx b/src/pages/transaction/history-transaction/blocks/DetailTransaction.tsx index 84e3420..e9b1186 100644 --- a/src/pages/transaction/history-transaction/blocks/DetailTransaction.tsx +++ b/src/pages/transaction/history-transaction/blocks/DetailTransaction.tsx @@ -367,7 +367,7 @@ const DetailTransaction = () => {

Full Name

-

{transactionDetails?.origin_customer?.fullname ?? transactionDetails?.origin_customer?.origin_name}

+

{transactionDetails?.origin_customer?.origin_name ?? ""}

Amount

From f2319116b9847228756be9e3cf711711c54abf47 Mon Sep 17 00:00:00 2001 From: wayanrivan Date: Tue, 20 May 2025 14:29:49 +0700 Subject: [PATCH 08/15] update --- auth.tsx | 147 +++++++++++++++++++++++++++++ src/auth/providers/JWTProvider.tsx | 5 +- 2 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 auth.tsx diff --git a/auth.tsx b/auth.tsx new file mode 100644 index 0000000..6d34e2a --- /dev/null +++ b/auth.tsx @@ -0,0 +1,147 @@ +/* eslint-disable no-unused-vars */ +import axios, { AxiosResponse } from 'axios'; +import { + createContext, + type Dispatch, + type PropsWithChildren, + type SetStateAction, + useEffect, + useState +} from 'react'; + +import * as authHelper from '../_helpers'; +import { type AuthModel, type UserModel } from '@/auth'; +import { apiConfig } from '@/config/api.config'; +import { doSaveLogActivity } from '@/actions/GlobalActions'; + +const API_URL = apiConfig.service_dashboard; + +export const LOGIN_URL = `${API_URL}/login`; +export const FORGOT_PASSWORD_URL = `${API_URL}/reset_password`; +export const RESET_PASSWORD_URL = `${API_URL}/update_password`; +export const GET_USER_URL = `${API_URL}/user/detail`; + +interface AuthContextProps { + loading: boolean; + setLoading: Dispatch>; + auth: AuthModel | undefined; + saveAuth: (auth: AuthModel | undefined) => void; + currentUser: UserModel | undefined; + setCurrentUser: Dispatch>; + login: (email: string, password: string) => Promise; + requestPasswordResetLink: (email: string) => Promise; + changePassword: (token: string, password: string, password_confirmation: string) => Promise; + getUser: () => Promise | {}>; + logout: () => void; + verify: () => Promise; +} + +const AuthContext = createContext(null); + +const AuthProvider = ({ children }: PropsWithChildren) => { + const [loading, setLoading] = useState(true); + const [auth, setAuth] = useState(authHelper.getAuth()); + const [currentUser, setCurrentUser] = useState(); + + const verify = async () => { + if (auth) { + try { + const { data: user } = await getUser(); + const createCacheUser = { + name: user.name, + email: user.email, + username: user.username, + role_name: auth.role_name, + statusbalance: user.role.status_balance, + }; + localStorage.setItem('user', JSON.stringify(createCacheUser)); + } catch { + saveAuth(undefined); + setCurrentUser(undefined); + } + } + }; + + const saveAuth = (auth: AuthModel | undefined) => { + setAuth(auth); + if (auth) { + authHelper.setAuth(auth); + } else { + authHelper.removeAuth(); + } + }; + + const login = async (username: string, password: string) => { + try { + const { data: auth } = await axios + .post(LOGIN_URL, { username, password }) // , { headers: { 'Access-Control-Allow-Origin': "*" }} + .then((response) => response.data); + + saveAuth({ ...auth.token, id: auth.user.id, role_name: auth.role_name, user: auth.user }); + setCurrentUser(auth.user); + const createActivity = { + module: 'Login', + description: `Login`, + action: 'l' + }; + doSaveLogActivity(createActivity); + } catch (error: any) { + throw error; + } + }; + + const requestPasswordResetLink = async (email: string) => { + await axios.put(FORGOT_PASSWORD_URL + '/' + email); + }; + + const changePassword = async (token: string, password: string, retype_password: string) => { + await axios.put(`${RESET_PASSWORD_URL}/${token}`, { + password, + retype_password + }); + }; + + const getUser = async () => { + let _axios = await axios + .get(`${GET_USER_URL}/${authHelper.getAuth()?.id}`) + .then((response) => response.data.data); + + return { data: _axios }; + }; + + const logout = async () => { + const createActivity = { + module: 'Logout', + description: `Logout`, + action: 'O' + }; + await doSaveLogActivity(createActivity); + + saveAuth(undefined); + setCurrentUser(undefined); + }; + + return ( + + {children} + + ); +}; + +export { AuthContext, AuthProvider }; diff --git a/src/auth/providers/JWTProvider.tsx b/src/auth/providers/JWTProvider.tsx index ec33b0d..8cba25e 100644 --- a/src/auth/providers/JWTProvider.tsx +++ b/src/auth/providers/JWTProvider.tsx @@ -63,7 +63,7 @@ const AuthProvider = ({ children }: PropsWithChildren) => { id: auth.user.id, role_name: auth.role_name, user: auth.user, - statusbalance: auth.role.status_balance + statusbalance: auth.role?.status_balance ?? null // SAFE ACCESS }; saveAuth(enhancedAuth); @@ -76,6 +76,7 @@ const AuthProvider = ({ children }: PropsWithChildren) => { }; doSaveLogActivity(createActivity); } catch (error: any) { + console.error('Login error:', error); throw error; } }; @@ -160,4 +161,4 @@ const AuthProvider = ({ children }: PropsWithChildren) => { ); }; -export { AuthContext, AuthProvider }; +export { AuthContext, AuthProvider }; \ No newline at end of file From 40f67220bd0369169fa94929e15b0b9070a6e292 Mon Sep 17 00:00:00 2001 From: wayanrivan Date: Tue, 20 May 2025 14:30:25 +0700 Subject: [PATCH 09/15] update --- auth.tsx | 147 ------------------------------------------------------- 1 file changed, 147 deletions(-) delete mode 100644 auth.tsx diff --git a/auth.tsx b/auth.tsx deleted file mode 100644 index 6d34e2a..0000000 --- a/auth.tsx +++ /dev/null @@ -1,147 +0,0 @@ -/* eslint-disable no-unused-vars */ -import axios, { AxiosResponse } from 'axios'; -import { - createContext, - type Dispatch, - type PropsWithChildren, - type SetStateAction, - useEffect, - useState -} from 'react'; - -import * as authHelper from '../_helpers'; -import { type AuthModel, type UserModel } from '@/auth'; -import { apiConfig } from '@/config/api.config'; -import { doSaveLogActivity } from '@/actions/GlobalActions'; - -const API_URL = apiConfig.service_dashboard; - -export const LOGIN_URL = `${API_URL}/login`; -export const FORGOT_PASSWORD_URL = `${API_URL}/reset_password`; -export const RESET_PASSWORD_URL = `${API_URL}/update_password`; -export const GET_USER_URL = `${API_URL}/user/detail`; - -interface AuthContextProps { - loading: boolean; - setLoading: Dispatch>; - auth: AuthModel | undefined; - saveAuth: (auth: AuthModel | undefined) => void; - currentUser: UserModel | undefined; - setCurrentUser: Dispatch>; - login: (email: string, password: string) => Promise; - requestPasswordResetLink: (email: string) => Promise; - changePassword: (token: string, password: string, password_confirmation: string) => Promise; - getUser: () => Promise | {}>; - logout: () => void; - verify: () => Promise; -} - -const AuthContext = createContext(null); - -const AuthProvider = ({ children }: PropsWithChildren) => { - const [loading, setLoading] = useState(true); - const [auth, setAuth] = useState(authHelper.getAuth()); - const [currentUser, setCurrentUser] = useState(); - - const verify = async () => { - if (auth) { - try { - const { data: user } = await getUser(); - const createCacheUser = { - name: user.name, - email: user.email, - username: user.username, - role_name: auth.role_name, - statusbalance: user.role.status_balance, - }; - localStorage.setItem('user', JSON.stringify(createCacheUser)); - } catch { - saveAuth(undefined); - setCurrentUser(undefined); - } - } - }; - - const saveAuth = (auth: AuthModel | undefined) => { - setAuth(auth); - if (auth) { - authHelper.setAuth(auth); - } else { - authHelper.removeAuth(); - } - }; - - const login = async (username: string, password: string) => { - try { - const { data: auth } = await axios - .post(LOGIN_URL, { username, password }) // , { headers: { 'Access-Control-Allow-Origin': "*" }} - .then((response) => response.data); - - saveAuth({ ...auth.token, id: auth.user.id, role_name: auth.role_name, user: auth.user }); - setCurrentUser(auth.user); - const createActivity = { - module: 'Login', - description: `Login`, - action: 'l' - }; - doSaveLogActivity(createActivity); - } catch (error: any) { - throw error; - } - }; - - const requestPasswordResetLink = async (email: string) => { - await axios.put(FORGOT_PASSWORD_URL + '/' + email); - }; - - const changePassword = async (token: string, password: string, retype_password: string) => { - await axios.put(`${RESET_PASSWORD_URL}/${token}`, { - password, - retype_password - }); - }; - - const getUser = async () => { - let _axios = await axios - .get(`${GET_USER_URL}/${authHelper.getAuth()?.id}`) - .then((response) => response.data.data); - - return { data: _axios }; - }; - - const logout = async () => { - const createActivity = { - module: 'Logout', - description: `Logout`, - action: 'O' - }; - await doSaveLogActivity(createActivity); - - saveAuth(undefined); - setCurrentUser(undefined); - }; - - return ( - - {children} - - ); -}; - -export { AuthContext, AuthProvider }; From 600570cfdfd42e9d542d8bfae4a9aefd4f482435 Mon Sep 17 00:00:00 2001 From: bagusajisaputroo Date: Tue, 20 May 2025 15:11:42 +0700 Subject: [PATCH 10/15] add new field "status"balance" on manage position --- .../user/manage-position/blocks/AddDialog.tsx | 40 +++++++++++++++++-- .../manage-position/blocks/EditDialog.tsx | 31 ++++++++++++-- 2 files changed, 64 insertions(+), 7 deletions(-) diff --git a/src/pages/settings/user/manage-position/blocks/AddDialog.tsx b/src/pages/settings/user/manage-position/blocks/AddDialog.tsx index a0ea607..da73584 100644 --- a/src/pages/settings/user/manage-position/blocks/AddDialog.tsx +++ b/src/pages/settings/user/manage-position/blocks/AddDialog.tsx @@ -18,6 +18,7 @@ import { useCallApi } from '@/hooks'; import { Checkbox } from '@/components/ui/checkbox'; import { doSaveLogActivity } from '@/actions/GlobalActions'; import { set } from 'date-fns'; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; const API_URL = apiConfig.service_dashboard; @@ -61,7 +62,8 @@ const MenuItemComponent: React.FC<{ }; const initialState = { - name: '' + name: '', + status_balance: '', }; const AddDialog = () => { @@ -86,13 +88,15 @@ const AddDialog = () => { const [isSubmitting, setIsSubmitting] = useState(false); const resetForm = () => { - setFormField(() => ({ name: '' })); + setFormField(initialState); setErrors(() => ({})); setSelectMenus([]); }; const validateForm = () => { - const requiredFields = [{ key: 'name', label: 'Position Name' }]; + const requiredFields = [ + { key: 'name', label: 'Position Name' }, + { key: 'status_balance', label: 'Status Balance' }]; const newErrors: Record = {}; let isValid = true; requiredFields.forEach(({ key, label }) => { @@ -128,7 +132,8 @@ const AddDialog = () => { const response = await PostData(`${API_URL}/user_role/create`, { name: formField.name, roles: selectMenus, - status: 'Y' + status: 'Y', + status_balance: formField.status_balance }); if (response?.status) { @@ -203,6 +208,33 @@ const AddDialog = () => {
+
+
+ +
+ + {errors.status && ( + {errors.status} + )} +
+
+
{menus.map((menu) => ( diff --git a/src/pages/settings/user/manage-position/blocks/EditDialog.tsx b/src/pages/settings/user/manage-position/blocks/EditDialog.tsx index 0bcc443..8b5093c 100644 --- a/src/pages/settings/user/manage-position/blocks/EditDialog.tsx +++ b/src/pages/settings/user/manage-position/blocks/EditDialog.tsx @@ -79,11 +79,15 @@ const EditDialog = () => { const [selectMenus, setSelectMenus] = useState([]); const [formField, setFormField] = useState({ name: '', - status: '' + status: '', + status_balance: '' }); const [errors, setErrors] = useState>({}); const validateForm = () => { - const requiredFields = [{ key: 'name', label: 'Position Name' }]; + const requiredFields = [ + { key: 'name', label: 'Position Name' }, + { key: 'status_balance', label: 'Status Balance' } + ]; const newErrors: Record = {}; let isValid = true; requiredFields.forEach(({ key, label }) => { @@ -131,7 +135,8 @@ const EditDialog = () => { const response = await PutData(`${API_URL}/user_role/update/${selectedPosition.id}`, { name: formField.name, roles: selectMenus, - status: formField.status + status: formField.status, + status_balance: formField.status_balance }); if (response?.status) { @@ -236,6 +241,26 @@ const EditDialog = () => {
+
+
+ + +
+ +
+
+
{menus.map((menu) => ( From 290c3e506dfc49a9fd4580bbb247272e932c01dc Mon Sep 17 00:00:00 2001 From: bagusajisaputroo Date: Tue, 20 May 2025 16:21:57 +0700 Subject: [PATCH 11/15] fixing manage position --- src/pages/settings/user/manage-position/blocks/EditDialog.tsx | 3 ++- .../user/manage-position/hooks/ManagePositionContext.tsx | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pages/settings/user/manage-position/blocks/EditDialog.tsx b/src/pages/settings/user/manage-position/blocks/EditDialog.tsx index 8b5093c..88da385 100644 --- a/src/pages/settings/user/manage-position/blocks/EditDialog.tsx +++ b/src/pages/settings/user/manage-position/blocks/EditDialog.tsx @@ -168,7 +168,8 @@ const EditDialog = () => { setFormField((prev) => ({ ...prev, name: selectedPosition.name, - status: selectedPosition.status + status: selectedPosition.status, + status_balance: selectedPosition.status_balance })); setSelectMenus(selectedPosition.roles); diff --git a/src/pages/settings/user/manage-position/hooks/ManagePositionContext.tsx b/src/pages/settings/user/manage-position/hooks/ManagePositionContext.tsx index 1fa5c30..dc62bdc 100644 --- a/src/pages/settings/user/manage-position/hooks/ManagePositionContext.tsx +++ b/src/pages/settings/user/manage-position/hooks/ManagePositionContext.tsx @@ -23,6 +23,7 @@ interface selectedPosition { name: string; roles: string[]; status: string; + status_balance: string; } const initialProps: ContextProps = { From 6fdea9bf116bb80b99a843e3f506e1656b2b1c39 Mon Sep 17 00:00:00 2001 From: Raja Oktafrianto Date: Wed, 21 May 2025 00:07:45 +0700 Subject: [PATCH 12/15] update filter date time on notification --- src/pages/notification/blocks/ListToolbar.tsx | 96 +++++++++++++++---- 1 file changed, 77 insertions(+), 19 deletions(-) diff --git a/src/pages/notification/blocks/ListToolbar.tsx b/src/pages/notification/blocks/ListToolbar.tsx index 3aca567..9676676 100644 --- a/src/pages/notification/blocks/ListToolbar.tsx +++ b/src/pages/notification/blocks/ListToolbar.tsx @@ -5,22 +5,23 @@ import { useCallback, useEffect, useState } from 'react'; import { toast } from 'sonner'; import { DateRangePicker } from '@/pages/dashboards/home/blocks'; -const formatDate = (date: Date): string => date.toISOString().split('T')[0]; +const formatDate = (date: Date): string => date.toLocaleDateString('sv-SE'); +const formatDateTime = (date: Date): string => date.toISOString(); +const getLocalDateString = (date: Date): string => { + return date.toLocaleDateString('sv-SE'); +}; const ListToolBar = () => { const { table, reload } = useDataGrid(); const { handleAddDialog } = useManageNotificationContext(); - const [dateRange, setDateRange] = useState({ from: '', to: '' }); + const [dateRange, setDateRange] = useState({ + from: getLocalDateString(new Date()), + to: getLocalDateString(new Date()) + }); const [searchValue, setSearchValue] = useState( (table.getColumn('content')?.getFilterValue() as string) ?? '' ); - useEffect(() => { - const today = new Date(); - const formatted = formatDate(today); - setDateRange({ from: formatted, to: formatted }); - }, []); - useEffect(() => { const timer = setTimeout(() => { table.getColumn('content')?.setFilterValue(searchValue); @@ -31,13 +32,25 @@ const ListToolBar = () => { useEffect(() => { const today = new Date(); - const formatted = formatDate(today); - const initialDateRange = { from: formatted, to: formatted }; + // Set waktu ke awal hari (00:00:00) + const startOfDay = new Date(today); + startOfDay.setHours(0, 0, 0, 0); + // Set waktu ke akhir hari (23:59:59) + const endOfDay = new Date(today); + endOfDay.setHours(23, 59, 59, 999); + + const initialDateRange = { + from: formatDate(startOfDay), // << Gunakan formatDate di sini + to: formatDate(endOfDay) + }; setDateRange(initialDateRange); try { - table.getColumn('created_at')?.setFilterValue(initialDateRange); + table.getColumn('created_at')?.setFilterValue({ + from: formatDateTime(startOfDay), + to: formatDateTime(endOfDay) + }); } catch (error) { toast.error('Error applying initial date filter'); console.error('Initial date filter error:', error); @@ -46,16 +59,28 @@ const ListToolBar = () => { const handleClearAllFilters = () => { const today = new Date(); + + const startOfDay = new Date(today); + startOfDay.setHours(0, 0, 0, 0); + + const endOfDay = new Date(today); + endOfDay.setHours(23, 59, 59, 999); + + // Set ulang filter tanggal dengan waktu const resetDateRange = { - from: formatDate(today), - to: formatDate(today) + from: formatDate(startOfDay), // YYYY-MM-DD untuk input date + to: formatDate(endOfDay) }; setSearchValue(''); setDateRange(resetDateRange); table.getColumn('content')?.setFilterValue(''); - table.getColumn('created_at')?.setFilterValue(resetDateRange); + + table.getColumn('created_at')?.setFilterValue({ + from: formatDateTime(startOfDay), + to: formatDateTime(endOfDay) + }); setTimeout(() => { table.setPageIndex(0); @@ -75,9 +100,24 @@ const ListToolBar = () => { useEffect(() => { const checkNewDay = () => { const now = new Date(); - const formattedNow = formatDate(now); - if (formattedNow !== dateRange.from || formattedNow !== dateRange.to) { - setDateRange({ from: formattedNow, to: formattedNow }); + const currentDate = formatDate(now); // Tetap gunakan formatDate untuk perbandingan tanggal saja + + // Periksa apakah tanggal sekarang berbeda dengan tanggal yang difilter + if (currentDate !== formatDate(new Date(dateRange.from))) { + const startOfDay = new Date(now); + startOfDay.setHours(0, 0, 0, 0); + const endOfDay = new Date(now); + endOfDay.setHours(23, 59, 59, 999); + + setDateRange({ + from: formatDate(startOfDay), // hanya YYYY-MM-DD + to: formatDate(endOfDay) + }); + + table.getColumn('created_at')?.setFilterValue({ + from: formatDateTime(startOfDay), + to: formatDateTime(endOfDay) + }); } }; @@ -95,7 +135,16 @@ const ListToolBar = () => { type="date" placeholder="From" value={dateRange.from} - onChange={(event) => setDateRange({ ...dateRange, from: event.target.value })} + onChange={(e) => { + setDateRange({ ...dateRange, from: e.target.value }); + // Untuk filter, konversi ke Date object dengan waktu awal hari + const date = new Date(e.target.value); + date.setHours(0, 0, 0, 0); + table.getColumn('created_at')?.setFilterValue({ + from: date.toISOString(), + to: new Date(dateRange.to).toISOString() + }); + }} name="from" /> @@ -106,7 +155,16 @@ const ListToolBar = () => { type="date" placeholder="To" value={dateRange.to} - onChange={(event) => setDateRange({ ...dateRange, to: event.target.value })} + onChange={(e) => { + setDateRange({ ...dateRange, to: e.target.value }); + // Untuk filter, konversi ke Date object dengan waktu akhir hari + const date = new Date(e.target.value); + date.setHours(23, 59, 59, 999); + table.getColumn('created_at')?.setFilterValue({ + from: new Date(dateRange.from).toISOString(), + to: date.toISOString() + }); + }} name="to" /> From 8e726d2966f62e556e88aaa89d923995ea7d467e Mon Sep 17 00:00:00 2001 From: Raja Oktafrianto Date: Wed, 21 May 2025 07:36:05 +0700 Subject: [PATCH 13/15] add detail statement on wallet statement --- .../wallet/wallet-history/WalletHistory.tsx | 6 +- .../wallet-history/blocks/ListToolbar.tsx | 52 +-- .../blocks/ShowDetailDialog.tsx | 363 ++++++++++++++++++ .../hooks/ManageWalletHistoryContext.tsx | 75 +++- 4 files changed, 433 insertions(+), 63 deletions(-) create mode 100644 src/pages/wallet/wallet-history/blocks/ShowDetailDialog.tsx diff --git a/src/pages/wallet/wallet-history/WalletHistory.tsx b/src/pages/wallet/wallet-history/WalletHistory.tsx index d914746..641ba29 100644 --- a/src/pages/wallet/wallet-history/WalletHistory.tsx +++ b/src/pages/wallet/wallet-history/WalletHistory.tsx @@ -7,11 +7,11 @@ const WalletHistory = () => { return ( <> - TPAY | Wallet History + TPAY | Wallet Statement -

Wallet History

+

Wallet Statement

Dashboard @@ -22,7 +22,7 @@ const WalletHistory = () => { - Wallet History + Wallet Statement diff --git a/src/pages/wallet/wallet-history/blocks/ListToolbar.tsx b/src/pages/wallet/wallet-history/blocks/ListToolbar.tsx index 6eb8298..44ccbb8 100644 --- a/src/pages/wallet/wallet-history/blocks/ListToolbar.tsx +++ b/src/pages/wallet/wallet-history/blocks/ListToolbar.tsx @@ -38,7 +38,6 @@ const ListToolbar = () => { const [searchValue, setSearchValue] = useState( (table.getColumn('msisdn')?.getFilterValue() as string) ?? '' ); - const [dateRange, setDateRange] = useState({ from: '', to: '' }); const [walletId, setWalletId] = useState( (table.getColumn('id_wallet')?.getFilterValue() as string) ?? '' ); @@ -48,12 +47,6 @@ const ListToolbar = () => { const [wallets, setWallets] = useState([]); const [groups, setGroups] = useState([]); - useEffect(() => { - const today = new Date(); - const threeMonthsAgo = getOneMonthsAgo(); - setDateRange({ from: formatDate(threeMonthsAgo), to: formatDate(today) }); - }, []); - useEffect(() => { const timer = setTimeout(() => { table.getColumn('msisdn')?.setFilterValue(searchValue); @@ -62,15 +55,6 @@ const ListToolbar = () => { return () => clearTimeout(timer); }, [searchValue, table]); - const handleFilterByDate = useCallback(() => { - try { - table.getColumn('CreatedAt')?.setFilterValue(dateRange); - } catch (error) { - toast.error('Error applying date filter'); - console.error('Error applying date filter:', error); - } - }, [dateRange, table]); - useEffect(() => { table.getColumn('id_wallet')?.setFilterValue(walletId); table.setPageIndex(0); @@ -81,12 +65,6 @@ const ListToolbar = () => { table.setPageIndex(0); }, [groupId, table]); - useEffect(() => { - if (dateRange.from && dateRange.to) { - handleFilterByDate(); - } - }, [dateRange, handleFilterByDate]); - const fetchWallets = async () => { try { const response = await GetData(`${API_URL_WALLET}/dashboard/wallet/`, { @@ -129,23 +107,22 @@ const ListToolbar = () => { from: formatDate(oneMonthAgo), to: formatDate(today) }; - + setSearchValue(''); setWalletId(''); setGroupId(''); - setDateRange(resetDateRange); - + table.getColumn('msisdn')?.setFilterValue(''); table.getColumn('id_wallet')?.setFilterValue(''); table.getColumn('id_group')?.setFilterValue(''); table.getColumn('CreatedAt')?.setFilterValue(resetDateRange); - + setTimeout(() => { table.setPageIndex(0); reload(); }, 0); }; - + const handleRefresh = () => { const today = new Date(); const threeMonthsAgo = getOneMonthsAgo(); @@ -157,7 +134,6 @@ const ListToolbar = () => { setSearchValue(''); setWalletId(''); setGroupId(''); - setDateRange(resetDateRange); table.setColumnFilters([{ id: 'CreatedAt', value: resetDateRange }]); table.setPageIndex(0); @@ -169,24 +145,6 @@ const ListToolbar = () => {
- - - -
diff --git a/src/pages/transfer/transfertype/hooks/ManageTransferTypeContext.tsx b/src/pages/transfer/transfertype/hooks/ManageTransferTypeContext.tsx index 736d83b..569156e 100644 --- a/src/pages/transfer/transfertype/hooks/ManageTransferTypeContext.tsx +++ b/src/pages/transfer/transfertype/hooks/ManageTransferTypeContext.tsx @@ -34,8 +34,8 @@ const formatInteger = (num: number): string => { return num.toLocaleString('en-US', { style: 'decimal', maximumFractionDigits: 0 - }) -} + }); +}; interface AccountProps { id: string; @@ -224,9 +224,9 @@ const ManageTransferTypeContextProvider = ({ children }: { children: React.React TM: 'Top Up Master Agent', TA: 'Top Up Agent', PL: 'Purchase Loja', - DE: 'Disbursment Escrow', - DM: 'Disbursment Master Agent', - DA: 'Disbursment Agent', + DE: 'Disbursement Escrow', + DM: 'Disbursement Master Agent', + DA: 'Disbursement Agent', WI: 'Withdraw Merchant', IC: 'Income Merchant', DN: 'Donation' @@ -287,7 +287,16 @@ const ManageTransferTypeContextProvider = ({ children }: { children: React.React L: { label: 'Purchase Loja', className: 'bg-rose-100 text-rose-600' }, B: { label: 'Top Up P24', className: 'bg-rose-100 text-rose-600' }, A: { label: 'Transfer Agent', className: 'bg-rose-100 text-rose-600' }, - M: { label: 'Withdraw Agent', className: 'bg-rose-100 text-rose-600' } + M: { label: 'Withdraw Agent', className: 'bg-rose-100 text-rose-600' }, + O: { label: 'Top Up Agent', className: 'bg-rose-100 text-rose-600' }, + S: { label: 'Transfer P24', className: 'bg-rose-100 text-rose-600' }, + I: { label: 'Withdraw Merchant', className: 'bg-rose-100 text-rose-600' }, + D: { label: 'Donation', className: 'bg-rose-100 text-rose-600' }, + F: { label: 'Fee', className: 'bg-rose-100 text-rose-600' }, + V: { label: 'Raversal', className: 'bg-rose-100 text-rose-600' }, + C: { label: 'Cashback Cash', className: 'bg-rose-100 text-rose-600' }, + H: { label: 'Cashback Point', className: 'bg-rose-100 text-rose-600' }, + J: { label: 'Withdraw Admin', className: 'bg-rose-100 text-rose-600' }, }; const kindInfo = mapping[kind] || { @@ -366,7 +375,7 @@ const ManageTransferTypeContextProvider = ({ children }: { children: React.React let filterObject: Record = {}; if (debouncedSearchTerm) { - filterObject['any'] = debouncedSearchTerm.toLowerCase(); + filterObject['name'] = `%${debouncedSearchTerm.toLowerCase()}%`; } if (columnFilters.length > 0) {