From cd173e67e4e0514271371f4a5e5136f7f61d06d1 Mon Sep 17 00:00:00 2001 From: Max Nanis Date: Tue, 29 Sep 2026 11:47:48 -0700 Subject: Redemption Modal. Redemption Magic flow. User Account Icon --- jb-ui/src/models/app.ts | 10 ++++++ jb-ui/src/models/appSlice.ts | 34 +++++++++++++++++++ jb-ui/src/models/authAPI.ts | 21 +++++++++++- jb-ui/src/models/cashoutMethodsSlice.ts | 58 +++++++++++++++++++++++++++++---- jb-ui/src/models/cashoutRequests.ts | 32 ++++++++++++++++++ 5 files changed, 148 insertions(+), 7 deletions(-) create mode 100644 jb-ui/src/models/cashoutRequests.ts (limited to 'jb-ui/src/models') diff --git a/jb-ui/src/models/app.ts b/jb-ui/src/models/app.ts index db54e0d..508afa6 100644 --- a/jb-ui/src/models/app.ts +++ b/jb-ui/src/models/app.ts @@ -7,6 +7,7 @@ import { OfferwallReason, UserLedgerWallet, UserDisplayedWalletBalance, + CashoutMethodOut, } from "@/api_fsb"; import { PaginationState } from "@tanstack/react-table"; @@ -41,7 +42,16 @@ export interface App { userAttemptCreditWallet?: UserLedgerWallet; // --- + // -- Transaction Component --- txPagination: PaginationState; txTotalItems?: number; txTotalPages?: number; + + // -- CashoutMethods Component --- + // cmPagination: PaginationState; + // cmTotalItems?: number; + // cmTotalPages?: number; + + cmSelected?: CashoutMethodOut; + cmShowHistory?: boolean; } diff --git a/jb-ui/src/models/appSlice.ts b/jb-ui/src/models/appSlice.ts index 42a776e..6cb7fc0 100644 --- a/jb-ui/src/models/appSlice.ts +++ b/jb-ui/src/models/appSlice.ts @@ -7,6 +7,7 @@ import { UserDisplayedWalletBalance, UserLedgerWallet, OfferwallReason, + CashoutMethodOut, } from "@/api_fsb"; import { App } from "@/models/app"; import { RootState } from "@/store"; @@ -37,6 +38,12 @@ const initialState: App = { txPagination: { pageIndex: 0, pageSize: 10 }, txTotalItems: undefined, txTotalPages: undefined, + + // cmPagination: { pageIndex: 0, pageSize: 10 }, + // cmTotalItems: undefined, + // cmTotalPages: undefined, + cmSelected: undefined, + cmShowHistory: false, } as App; const appSlice = createSlice({ @@ -144,6 +151,27 @@ const appSlice = createSlice({ setTxTotalPages(state, action: PayloadAction) { state.txTotalPages = action.payload; }, + + // setCmPagination(state, action: PayloadAction) { + // console.log("setCmPagination:payload=", action.payload); + // state.cmPagination = action.payload; + // }, + + // setCmTotalItems(state, action: PayloadAction) { + // state.cmTotalItems = action.payload; + // }, + + // setCmTotalPages(state, action: PayloadAction) { + // state.cmTotalPages = action.payload; + // }, + + setCmSelected(state, action: PayloadAction) { + state.cmSelected = action.payload; + }, + + setCmShowHistory(state, action: PayloadAction) { + state.cmShowHistory = action.payload; + }, }, }); @@ -171,6 +199,12 @@ export const { setTxPagination, setTxTotalItems, setTxTotalPages, + + // setCmPagination, + // setCmTotalItems, + // setCmTotalPages, + setCmSelected, + setCmShowHistory, } = appSlice.actions; export default appSlice.reducer; diff --git a/jb-ui/src/models/authAPI.ts b/jb-ui/src/models/authAPI.ts index 2964d55..a3efbcb 100644 --- a/jb-ui/src/models/authAPI.ts +++ b/jb-ui/src/models/authAPI.ts @@ -1,5 +1,13 @@ import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"; import type { User } from "@/types/authApi"; +export const bpuid = import.meta.env.VITE_BPUID; + +// const DEV_USER: User = { +// blocked: false, +// display_name: null, +// email: "demo@jamesbillings67.com", +// product_user_id: import.meta.env.VITE_BPUID, +// }; export const authApi = createApi({ reducerPath: "authApi", @@ -10,7 +18,16 @@ export const authApi = createApi({ tagTypes: ["User"], endpoints: (builder) => ({ getMe: builder.query({ - query: () => "/session/", + queryFn: async (_arg, _api, _extra, baseQuery) => { + // if (import.meta.env.DEV) { + // return { data: DEV_USER }; + // } + const result = await baseQuery("/session/"); + return result.data + ? { data: result.data as User } + : { error: result.error! }; + }, + providesTags: ["User"], }), // logout: builder.mutation({ @@ -22,3 +39,5 @@ export const authApi = createApi({ // export const { useGetMeQuery, useLogoutMutation } = authApi; export const { useGetMeQuery } = authApi; + +// diff --git a/jb-ui/src/models/cashoutMethodsSlice.ts b/jb-ui/src/models/cashoutMethodsSlice.ts index 92c03da..080cb04 100644 --- a/jb-ui/src/models/cashoutMethodsSlice.ts +++ b/jb-ui/src/models/cashoutMethodsSlice.ts @@ -1,23 +1,69 @@ -import { CashoutMethodOut } from "@/api_fsb"; +import { WalletApi, CashoutMethodOut } from "@/api_fsb"; import type { RootState } from "@/store"; -import { createSlice, createEntityAdapter } from "@reduxjs/toolkit"; +import { + PayloadAction, + createSlice, + createEntityAdapter, +} from "@reduxjs/toolkit"; +import { bpid } from "@/lib/utils"; +import { createAsyncThunk } from "@reduxjs/toolkit"; // Entity adapter for normalized storage const cashoutMethodsAdapter = createEntityAdapter({ selectId: (model: CashoutMethodOut) => model.id!, sortComparer: (a, b) => { - return (b.min_value ?? 0) - (a.min_value ?? 0); + return (a.min_value ?? 0) - (b.min_value ?? 0); }, }); +export const fetchCashoutMethods = createAsyncThunk( + "cashoutMethodsSlice/fetchCashoutMethods", + async (bpuid: string) => { + console.log("cashoutMethodsSlice/fetchCashoutMethods"); + const res = + await new WalletApi().getCashoutMethodsProductIdCashoutMethodsGet( + bpid, + bpuid, + ); + return res.data.cashout_methods as CashoutMethodOut[]; + }, +); + +interface CashoutMethodClientState { + is_active?: boolean; + is_expanded?: boolean; +} + +const withClientDefaults = (method: CashoutMethodOut): CashoutMethodEntity => ({ + ...method, + is_active: false, + is_expanded: false, +}); + +type CashoutMethodEntity = CashoutMethodOut & CashoutMethodClientState; + const cashoutMethodsSlice = createSlice({ name: "cashoutMethods", initialState: cashoutMethodsAdapter.getInitialState(), reducers: { - addCashoutMethod: cashoutMethodsAdapter.addOne, - addCashoutMethods: cashoutMethodsAdapter.addMany, - upsertCashoutMethod: cashoutMethodsAdapter.upsertOne, // Add or Update + addCashoutMethod: (state, action: PayloadAction) => { + cashoutMethodsAdapter.addOne(state, withClientDefaults(action.payload)); + }, + + addCashoutMethods: (state, action: PayloadAction) => { + cashoutMethodsAdapter.addMany( + state, + action.payload.map(withClientDefaults), + ); + }, + + upsertCashoutMethod: (state, action: PayloadAction) => { + cashoutMethodsAdapter.upsertOne( + state, + withClientDefaults(action.payload), + ); + }, }, }); diff --git a/jb-ui/src/models/cashoutRequests.ts b/jb-ui/src/models/cashoutRequests.ts new file mode 100644 index 0000000..985b949 --- /dev/null +++ b/jb-ui/src/models/cashoutRequests.ts @@ -0,0 +1,32 @@ +import { createApi, fakeBaseQuery } from "@reduxjs/toolkit/query/react"; +import { WalletApi } from "@/api_fsb"; +import type { CashoutRequestSummary } from "@/api_fsb"; + +const walletApi = new WalletApi(); + +// //cashout/ + +export const cashoutRequests = createApi({ + reducerPath: "cashoutRequests", + baseQuery: fakeBaseQuery(), + endpoints: (builder) => ({ + getUserCashouts: builder.query< + CashoutRequestSummary[], + { bpid: string; productUserId: string } + >({ + queryFn: async ({ bpid, productUserId }) => { + try { + const res = await walletApi.filterUserCashoutsProductIdCashoutGet( + bpid, + productUserId, + ); + return { data: res.data.cashouts as CashoutRequestSummary[] }; + } catch (e) { + return { error: e instanceof Error ? e.message : "Request failed" }; + } + }, + }), + }), +}); + +export const { useGetUserCashoutsQuery } = cashoutRequests; -- cgit v1.2.3