@greatapps/common 1.1.804 → 1.1.806
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/account/sections/subscription/PixDetailsDialog.mjs +4 -6
- package/dist/components/account/sections/subscription/PixDetailsDialog.mjs.map +1 -1
- package/dist/components/account/sections/subscription/PixPaymentDialog.mjs +17 -24
- package/dist/components/account/sections/subscription/PixPaymentDialog.mjs.map +1 -1
- package/dist/hooks/useSecondsUntil.mjs +17 -0
- package/dist/hooks/useSecondsUntil.mjs.map +1 -0
- package/dist/i18n/messages/en-us.mjs +2 -0
- package/dist/i18n/messages/en-us.mjs.map +1 -1
- package/dist/i18n/messages/es-es.mjs +2 -0
- package/dist/i18n/messages/es-es.mjs.map +1 -1
- package/dist/i18n/messages/pt-br.mjs +2 -0
- package/dist/i18n/messages/pt-br.mjs.map +1 -1
- package/dist/modules/accounts/services/account.service.mjs +13 -8
- package/dist/modules/accounts/services/account.service.mjs.map +1 -1
- package/dist/modules/subscriptions/types/pending-pix-status.type.mjs +1 -0
- package/dist/modules/subscriptions/types/pending-pix-status.type.mjs.map +1 -1
- package/dist/modules/users/schema.mjs.map +1 -1
- package/dist/modules/users/services/user.service.mjs +2 -1
- package/dist/modules/users/services/user.service.mjs.map +1 -1
- package/dist/providers/query.provider.mjs +1 -1
- package/dist/providers/query.provider.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/account/sections/subscription/PixDetailsDialog.tsx +4 -9
- package/src/components/account/sections/subscription/PixPaymentDialog.tsx +18 -29
- package/src/hooks/useSecondsUntil.ts +17 -0
- package/src/i18n/messages/en-us.ts +2 -0
- package/src/i18n/messages/es-es.ts +2 -0
- package/src/i18n/messages/pt-br.ts +2 -0
- package/src/modules/accounts/services/account.service.ts +16 -8
- package/src/modules/accounts/types.ts +1 -3
- package/src/modules/auth/schema.ts +0 -1
- package/src/modules/subscriptions/types/pending-pix-status.type.ts +1 -0
- package/src/modules/users/schema.ts +1 -1
- package/src/modules/users/services/user.service.ts +3 -1
- package/src/providers/query.provider.tsx +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/modules/accounts/services/account.service.ts"],"sourcesContent":["import 'server-only';\n\nimport { api } from '../../../infra/api/client';\nimport { ApiError } from '../../../infra/api/types';\nimport { buildQueryParams } from '../../../infra/utils/params';\nimport { assertAccountNotFrozen } from '../../auth/utils/assert-account-not-frozen';\nimport { getUserContext } from '../../auth/utils/get-user-context';\nimport { fileToBase64 } from '../../../utils/file/index';\nimport type { RequestConfig } from '../../../infra/api/client';\nimport { buildWlOverride } from '../../auth/utils/build-wl-override';\nimport type {\n Account,\n AccountUserProjectsResponse,\n AccountUsersPaginationParams,\n ChangePasswordRequest,\n ChangePasswordResponse,\n ChangeUserPhotoResponse,\n CreateAccountUserRequest,\n CreateAccountUserResponse,\n DeleteAccountRequest,\n DeleteAccountResponse,\n DeleteAccountUserResponse,\n GetAccountDataResponse,\n ListAccountUsersResponse,\n UpdateAccountRequest,\n UpdateAccountResponse,\n UpdateAccountUserRequest,\n UpdateAccountUserResponse,\n} from '../types';\n\nclass AccountService {\n async findCurrentAccount(config?: RequestConfig): Promise<Account> {\n const { id_wl, id_account } = await getUserContext();\n const effectiveConfig = config ?? await buildWlOverride(id_wl);\n const response = await api.apps.get<GetAccountDataResponse>(`/accounts/${id_account}`, effectiveConfig);\n\n if (response.status === 0 || !response.data?.[0]) {\n throw new ApiError(\n response.message || 'Erro ao buscar dados da conta',\n 'GET_ACCOUNT_FAILED',\n 400\n );\n }\n\n return response.data[0];\n }\n\n async listAccountUsers(params?: Partial<AccountUsersPaginationParams>) {\n const { id_account } = await getUserContext();\n const queryParams = buildQueryParams(params);\n const endpoint = `/accounts/${id_account}/users?${queryParams}`;\n const response = await api.apps.get<ListAccountUsersResponse>(endpoint);\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao listar usuários',\n 'LIST_ACCOUNT_USERS_FAILED',\n 400\n );\n }\n\n return {\n users: response.data || [],\n total: response.total || 0,\n };\n }\n\n /**\n * Usuários da conta com projetos (`total_projects`, `projects`), escopados ao usuário logado:\n * collaborator/viewer só veem quem divide projeto com eles.\n */\n async listAccountMembers(params?: Partial<AccountUsersPaginationParams>) {\n const { id_account, id_user } = await getUserContext();\n const queryParams = buildQueryParams({ ...params, scopeUserId: id_user });\n const response = await api.apps.get<ListAccountUsersResponse>(\n `/accounts/${id_account}/users?${queryParams}`\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao listar usuários',\n 'LIST_ACCOUNT_USERS_FAILED',\n 400\n );\n }\n\n return {\n users: response.data || [],\n total: response.total || 0,\n };\n }\n\n async changeUserPhoto(userId: number, photo: File): Promise<ChangeUserPhotoResponse> {\n const { id_account } = await getUserContext();\n const base64 = await fileToBase64(photo);\n const response = await api.apps.put<ChangeUserPhotoResponse>(\n `/accounts/${id_account}/users/${userId}/file/photo`,\n { file: base64 }\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao mudar foto do usuário',\n 'CHANGE_USER_PHOTO_FAILED',\n 400\n );\n }\n\n return response;\n }\n\n async deleteAccountUser(userId: number): Promise<DeleteAccountUserResponse> {\n const { id_account } = await getUserContext();\n const response = await api.apps.delete<DeleteAccountUserResponse>(\n `/accounts/${id_account}/users/${userId}`\n );\n\n if (response.status === 0) {\n throw new ApiError(response.message || 'Erro ao deletar usuário', 'DELETE_USER_FAILED', 400);\n }\n\n return response;\n }\n\n async deleteAccount(data: DeleteAccountRequest): Promise<DeleteAccountResponse> {\n const { id_account } = await getUserContext();\n const response = await api.apps.delete<DeleteAccountResponse>(\n `/accounts/${id_account}`,\n { body: JSON.stringify(data) }\n );\n\n if (response.status === 0) {\n throw new ApiError(response.message || 'Erro ao deletar conta', 'DELETE_ACCOUNT_FAILED', 400);\n }\n\n return response;\n }\n\n async createAccountUser(user: CreateAccountUserRequest): Promise<CreateAccountUserResponse> {\n const { id_account } = await getUserContext();\n const response = await api.apps.post<CreateAccountUserResponse>(\n `/accounts/${id_account}/users`,\n {\n ...user,\n photo: user.photo ? await fileToBase64(user.photo) : null,\n }\n );\n\n if (response.status === 0) {\n throw new ApiError(response.message || 'Erro ao criar usuário', 'CREATE_USER_FAILED', 400);\n }\n\n return response;\n }\n\n private async resolvePhotoField(user: UpdateAccountUserRequest): Promise<{ photo?: string | null }> {\n if (user.photo === undefined) return {};\n const photo =\n user.photo != null && typeof user.photo !== 'string'\n ? await fileToBase64(user.photo)\n : user.photo;\n return { photo };\n }\n\n async updateAccountUser(user: UpdateAccountUserRequest): Promise<UpdateAccountUserResponse> {\n const { id_account, id_user } = await getUserContext();\n const response = await api.apps.put<UpdateAccountUserResponse>(\n `/accounts/${id_account}/users/${id_user}`,\n { ...user, ...(await this.resolvePhotoField(user)) }\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao atualizar usuário',\n 'UPDATE_USER_FAILED',\n 400\n );\n }\n\n return response;\n }\n\n async updateAccountUserById(\n userId: number,\n user: UpdateAccountUserRequest\n ): Promise<UpdateAccountUserResponse> {\n const { id_account } = await getUserContext();\n const response = await api.apps.put<UpdateAccountUserResponse>(\n `/accounts/${id_account}/users/${userId}`,\n { ...user, ...(await this.resolvePhotoField(user)) }\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao atualizar usuário',\n 'UPDATE_USER_FAILED',\n 400\n );\n }\n\n return response;\n }\n\n async updateAccount(data: UpdateAccountRequest): Promise<UpdateAccountResponse> {\n const { id_account } = await getUserContext();\n const response = await api.apps.put<UpdateAccountResponse>(`/accounts/${id_account}`, data);\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao atualizar conta',\n 'UPDATE_ACCOUNT_FAILED',\n 400\n );\n }\n\n return response;\n }\n\n async requestContactReset(type: 'email' | 'phone', newContact: string, ddi?: string): Promise<void> {\n const { id_account, id_user } = await getUserContext();\n const response = await api.apps.post<{ status: number; message: string }>(\n `/accounts/${id_account}/users/${id_user}/resetContact/request`,\n { type, newContact, ...(ddi ? { ddi } : {}) }\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao solicitar alteração',\n 'REQUEST_CONTACT_RESET_FAILED',\n 400\n );\n }\n }\n\n async confirmContactReset(type: 'email' | 'phone', token: string, newContact: string, ddi?: string): Promise<void> {\n const { id_account, id_user } = await getUserContext();\n const response = await api.apps.post<{ status: number; message: string }>(\n `/accounts/${id_account}/users/${id_user}/resetContact/confirm`,\n { type, token, newContact, ...(ddi ? { ddi } : {}) }\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Código inválido ou expirado',\n 'CONFIRM_CONTACT_RESET_FAILED',\n 400\n );\n }\n }\n\n /** Checagem de e-mail já cadastrado, usada no cadastro de usuário antes de avançar de passo. */\n async checkUserExists(email: string): Promise<{ exists: boolean }> {\n const response = await api.apps.post<{ exist: boolean }>('/users/action/exists', { email });\n\n return { exists: response.exist };\n }\n\n async addUserProjects(userId: number, projectIds: number[]): Promise<AccountUserProjectsResponse> {\n await assertAccountNotFrozen();\n const { id_account } = await getUserContext();\n const response = await api.apps.post<AccountUserProjectsResponse>(\n `/accounts/${id_account}/users/${userId}/action/addProjectsBatch`,\n { projects: projectIds }\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao vincular projetos ao usuário',\n 'ADD_USER_PROJECTS_FAILED',\n 400\n );\n }\n\n return response;\n }\n\n async removeUserProjects(userId: number, projectIds: number[]): Promise<AccountUserProjectsResponse> {\n const { id_account } = await getUserContext();\n const response = await api.apps.post<AccountUserProjectsResponse>(\n `/accounts/${id_account}/users/${userId}/action/removeProjectsBatch`,\n { projects: projectIds }\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao desvincular projetos do usuário',\n 'REMOVE_USER_PROJECTS_FAILED',\n 400\n );\n }\n\n return response;\n }\n\n async changePassword(data: ChangePasswordRequest): Promise<ChangePasswordResponse> {\n const { id_account, id_user } = await getUserContext();\n const response = await api.apps.put<ChangePasswordResponse>(\n `/accounts/${id_account}/users/${id_user}/action/changePassword`,\n data\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao alterar senha',\n 'CHANGE_PASSWORD_FAILED',\n 400\n );\n }\n\n return response;\n }\n}\n\nexport const accountService = new AccountService();\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/accounts/services/account.service.ts"],"sourcesContent":["import 'server-only';\n\nimport { api } from '../../../infra/api/client';\nimport { ApiError } from '../../../infra/api/types';\nimport { buildQueryParams } from '../../../infra/utils/params';\nimport { assertAccountNotFrozen } from '../../auth/utils/assert-account-not-frozen';\nimport { getUserContext } from '../../auth/utils/get-user-context';\nimport { fileToBase64 } from '../../../utils/file/index';\nimport type { RequestConfig } from '../../../infra/api/client';\nimport { buildWlOverride } from '../../auth/utils/build-wl-override';\nimport type {\n Account,\n AccountUserProjectsResponse,\n AccountUsersPaginationParams,\n ChangePasswordRequest,\n ChangePasswordResponse,\n ChangeUserPhotoResponse,\n CreateAccountUserRequest,\n CreateAccountUserResponse,\n DeleteAccountRequest,\n DeleteAccountResponse,\n DeleteAccountUserResponse,\n GetAccountDataResponse,\n ListAccountUsersResponse,\n UpdateAccountRequest,\n UpdateAccountResponse,\n UpdateAccountUserRequest,\n UpdateAccountUserResponse,\n} from '../types';\n\nclass AccountService {\n async findCurrentAccount(config?: RequestConfig): Promise<Account> {\n const { id_wl, id_account } = await getUserContext();\n const effectiveConfig = config ?? await buildWlOverride(id_wl);\n const response = await api.apps.get<GetAccountDataResponse>(`/accounts/${id_account}`, effectiveConfig);\n\n if (response.status === 0 || !response.data?.[0]) {\n throw new ApiError(\n response.message || 'Erro ao buscar dados da conta',\n 'GET_ACCOUNT_FAILED',\n 400\n );\n }\n\n const { user, ...account } = response.data[0];\n\n return account;\n }\n\n private pickUsersQueryParams(params: Partial<AccountUsersPaginationParams> = {}) {\n const { page, limit, search, name, notInProject, profiles, firstId } = params;\n\n return { page, limit, search, name, notInProject, profiles, firstId };\n }\n\n async listAccountUsers(params?: Partial<AccountUsersPaginationParams>) {\n const { id_account } = await getUserContext();\n const queryParams = buildQueryParams(this.pickUsersQueryParams(params));\n const endpoint = `/accounts/${id_account}/users?${queryParams}`;\n const response = await api.apps.get<ListAccountUsersResponse>(endpoint);\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao listar usuários',\n 'LIST_ACCOUNT_USERS_FAILED',\n 400\n );\n }\n\n return {\n users: response.data || [],\n total: response.total || 0,\n };\n }\n\n /**\n * Usuários da conta com projetos (`total_projects`, `projects`), escopados ao usuário logado:\n * collaborator/viewer só veem quem divide projeto com eles.\n */\n async listAccountMembers(params?: Partial<AccountUsersPaginationParams>) {\n const { id_account, id_user } = await getUserContext();\n const queryParams = buildQueryParams({ ...this.pickUsersQueryParams(params), scopeUserId: id_user });\n const response = await api.apps.get<ListAccountUsersResponse>(\n `/accounts/${id_account}/users?${queryParams}`\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao listar usuários',\n 'LIST_ACCOUNT_USERS_FAILED',\n 400\n );\n }\n\n return {\n users: response.data || [],\n total: response.total || 0,\n };\n }\n\n async changeUserPhoto(userId: number, photo: File): Promise<ChangeUserPhotoResponse> {\n const { id_account } = await getUserContext();\n const base64 = await fileToBase64(photo);\n const response = await api.apps.put<ChangeUserPhotoResponse>(\n `/accounts/${id_account}/users/${userId}/file/photo`,\n { file: base64 }\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao mudar foto do usuário',\n 'CHANGE_USER_PHOTO_FAILED',\n 400\n );\n }\n\n return { status: response.status, message: response.message };\n }\n\n async deleteAccountUser(userId: number): Promise<DeleteAccountUserResponse> {\n const { id_account } = await getUserContext();\n const response = await api.apps.delete<DeleteAccountUserResponse>(\n `/accounts/${id_account}/users/${userId}`\n );\n\n if (response.status === 0) {\n throw new ApiError(response.message || 'Erro ao deletar usuário', 'DELETE_USER_FAILED', 400);\n }\n\n return { status: response.status, message: response.message };\n }\n\n async deleteAccount(data: DeleteAccountRequest): Promise<DeleteAccountResponse> {\n const { id_account } = await getUserContext();\n const response = await api.apps.delete<DeleteAccountResponse>(\n `/accounts/${id_account}`,\n { body: JSON.stringify(data) }\n );\n\n if (response.status === 0) {\n throw new ApiError(response.message || 'Erro ao deletar conta', 'DELETE_ACCOUNT_FAILED', 400);\n }\n\n return response;\n }\n\n async createAccountUser(user: CreateAccountUserRequest): Promise<CreateAccountUserResponse> {\n const { id_account } = await getUserContext();\n const response = await api.apps.post<CreateAccountUserResponse>(\n `/accounts/${id_account}/users`,\n {\n ...user,\n photo: user.photo ? await fileToBase64(user.photo) : null,\n }\n );\n\n if (response.status === 0) {\n throw new ApiError(response.message || 'Erro ao criar usuário', 'CREATE_USER_FAILED', 400);\n }\n\n return { status: response.status, message: response.message };\n }\n\n private async resolvePhotoField(user: UpdateAccountUserRequest): Promise<{ photo?: string | null }> {\n if (user.photo === undefined) return {};\n const photo =\n user.photo != null && typeof user.photo !== 'string'\n ? await fileToBase64(user.photo)\n : user.photo;\n return { photo };\n }\n\n async updateAccountUser(user: UpdateAccountUserRequest): Promise<UpdateAccountUserResponse> {\n const { id_account, id_user } = await getUserContext();\n const response = await api.apps.put<UpdateAccountUserResponse>(\n `/accounts/${id_account}/users/${id_user}`,\n { ...user, ...(await this.resolvePhotoField(user)) }\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao atualizar usuário',\n 'UPDATE_USER_FAILED',\n 400\n );\n }\n\n return { status: response.status, message: response.message };\n }\n\n async updateAccountUserById(\n userId: number,\n user: UpdateAccountUserRequest\n ): Promise<UpdateAccountUserResponse> {\n const { id_account } = await getUserContext();\n const response = await api.apps.put<UpdateAccountUserResponse>(\n `/accounts/${id_account}/users/${userId}`,\n { ...user, ...(await this.resolvePhotoField(user)) }\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao atualizar usuário',\n 'UPDATE_USER_FAILED',\n 400\n );\n }\n\n return { status: response.status, message: response.message };\n }\n\n async updateAccount(data: UpdateAccountRequest): Promise<UpdateAccountResponse> {\n const { id_account } = await getUserContext();\n const response = await api.apps.put<UpdateAccountResponse>(`/accounts/${id_account}`, data);\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao atualizar conta',\n 'UPDATE_ACCOUNT_FAILED',\n 400\n );\n }\n\n return response;\n }\n\n async requestContactReset(type: 'email' | 'phone', newContact: string, ddi?: string): Promise<void> {\n const { id_account, id_user } = await getUserContext();\n const response = await api.apps.post<{ status: number; message: string }>(\n `/accounts/${id_account}/users/${id_user}/resetContact/request`,\n { type, newContact, ...(ddi ? { ddi } : {}) }\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao solicitar alteração',\n 'REQUEST_CONTACT_RESET_FAILED',\n 400\n );\n }\n }\n\n async confirmContactReset(type: 'email' | 'phone', token: string, newContact: string, ddi?: string): Promise<void> {\n const { id_account, id_user } = await getUserContext();\n const response = await api.apps.post<{ status: number; message: string }>(\n `/accounts/${id_account}/users/${id_user}/resetContact/confirm`,\n { type, token, newContact, ...(ddi ? { ddi } : {}) }\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Código inválido ou expirado',\n 'CONFIRM_CONTACT_RESET_FAILED',\n 400\n );\n }\n }\n\n /** Checagem de e-mail já cadastrado, usada no cadastro de usuário antes de avançar de passo. */\n async checkUserExists(email: string): Promise<{ exists: boolean }> {\n const response = await api.apps.post<{ exist: boolean }>('/users/action/exists', { email });\n\n return { exists: response.exist };\n }\n\n async addUserProjects(userId: number, projectIds: number[]): Promise<AccountUserProjectsResponse> {\n await assertAccountNotFrozen();\n const { id_account } = await getUserContext();\n const response = await api.apps.post<AccountUserProjectsResponse>(\n `/accounts/${id_account}/users/${userId}/action/addProjectsBatch`,\n { projects: projectIds }\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao vincular projetos ao usuário',\n 'ADD_USER_PROJECTS_FAILED',\n 400\n );\n }\n\n return response;\n }\n\n async removeUserProjects(userId: number, projectIds: number[]): Promise<AccountUserProjectsResponse> {\n const { id_account } = await getUserContext();\n const response = await api.apps.post<AccountUserProjectsResponse>(\n `/accounts/${id_account}/users/${userId}/action/removeProjectsBatch`,\n { projects: projectIds }\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao desvincular projetos do usuário',\n 'REMOVE_USER_PROJECTS_FAILED',\n 400\n );\n }\n\n return response;\n }\n\n async changePassword(data: ChangePasswordRequest): Promise<ChangePasswordResponse> {\n const { id_account, id_user } = await getUserContext();\n const response = await api.apps.put<ChangePasswordResponse>(\n `/accounts/${id_account}/users/${id_user}/action/changePassword`,\n data\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao alterar senha',\n 'CHANGE_PASSWORD_FAILED',\n 400\n );\n }\n\n return response;\n }\n}\n\nexport const accountService = new AccountService();\n"],"mappings":"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","names":[]}
|
|
@@ -11,6 +11,7 @@ const PendingPixStatusDataSchema = z.object({
|
|
|
11
11
|
payment_method: z.number().nullable().optional(),
|
|
12
12
|
subscription_id: z.union([z.number(), z.string()]).optional(),
|
|
13
13
|
completed_at: z.string().nullable().optional(),
|
|
14
|
+
payment_collected: z.boolean().optional(),
|
|
14
15
|
pix: z.object({
|
|
15
16
|
qr_code: z.string().nullable().optional(),
|
|
16
17
|
payment_link: z.string().nullable().optional(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/modules/subscriptions/types/pending-pix-status.type.ts"],"sourcesContent":["import z from 'zod';\n\nexport const PendingPixStatusPhaseSchema = z.enum([\n 'creating',\n 'awaiting_authorization',\n 'completed',\n 'rejected',\n 'expired',\n]);\n\nexport type PendingPixStatusPhase = z.infer<typeof PendingPixStatusPhaseSchema>;\n\nexport const PendingPixStatusDataSchema = z\n .object({\n phase: PendingPixStatusPhaseSchema,\n payment_method: z.number().nullable().optional(),\n subscription_id: z.union([z.number(), z.string()]).optional(),\n completed_at: z.string().nullable().optional(),\n pix: z\n .object({\n qr_code: z.string().nullable().optional(),\n payment_link: z.string().nullable().optional(),\n correlation_id: z.string().nullable().optional(),\n expires_at: z.string().nullable().optional(),\n expires_at_inferred: z.boolean().nullable().optional(),\n expires_at_source: z.string().nullable().optional(),\n authorization_created_at: z.string().nullable().optional(),\n })\n .optional(),\n })\n .passthrough();\n\nexport type PendingPixStatusData = z.infer<typeof PendingPixStatusDataSchema>;\n"],"mappings":"AAAA,OAAO,OAAO;AAEP,MAAM,8BAA8B,EAAE,KAAK;AAAA,EAChD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAIM,MAAM,6BAA6B,EACvC,OAAO;AAAA,EACN,OAAO;AAAA,EACP,gBAAgB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC/C,iBAAiB,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC,EAAE,SAAS;AAAA,EAC5D,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC7C,KAAK,EACF,OAAO;AAAA,IACN,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,IACxC,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,IAC7C,gBAAgB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,IAC/C,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,IAC3C,qBAAqB,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS;AAAA,IACrD,mBAAmB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,IAClD,0BAA0B,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC3D,CAAC,EACA,SAAS;AACd,CAAC,EACA,YAAY;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/subscriptions/types/pending-pix-status.type.ts"],"sourcesContent":["import z from 'zod';\n\nexport const PendingPixStatusPhaseSchema = z.enum([\n 'creating',\n 'awaiting_authorization',\n 'completed',\n 'rejected',\n 'expired',\n]);\n\nexport type PendingPixStatusPhase = z.infer<typeof PendingPixStatusPhaseSchema>;\n\nexport const PendingPixStatusDataSchema = z\n .object({\n phase: PendingPixStatusPhaseSchema,\n payment_method: z.number().nullable().optional(),\n subscription_id: z.union([z.number(), z.string()]).optional(),\n completed_at: z.string().nullable().optional(),\n payment_collected: z.boolean().optional(),\n pix: z\n .object({\n qr_code: z.string().nullable().optional(),\n payment_link: z.string().nullable().optional(),\n correlation_id: z.string().nullable().optional(),\n expires_at: z.string().nullable().optional(),\n expires_at_inferred: z.boolean().nullable().optional(),\n expires_at_source: z.string().nullable().optional(),\n authorization_created_at: z.string().nullable().optional(),\n })\n .optional(),\n })\n .passthrough();\n\nexport type PendingPixStatusData = z.infer<typeof PendingPixStatusDataSchema>;\n"],"mappings":"AAAA,OAAO,OAAO;AAEP,MAAM,8BAA8B,EAAE,KAAK;AAAA,EAChD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAIM,MAAM,6BAA6B,EACvC,OAAO;AAAA,EACN,OAAO;AAAA,EACP,gBAAgB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC/C,iBAAiB,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC,EAAE,SAAS;AAAA,EAC5D,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC7C,mBAAmB,EAAE,QAAQ,EAAE,SAAS;AAAA,EACxC,KAAK,EACF,OAAO;AAAA,IACN,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,IACxC,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,IAC7C,gBAAgB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,IAC/C,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,IAC3C,qBAAqB,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS;AAAA,IACrD,mBAAmB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,IAClD,0BAA0B,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC3D,CAAC,EACA,SAAS;AACd,CAAC,EACA,YAAY;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/modules/users/schema.ts"],"sourcesContent":["export enum UserProfile {\r\n viewer = 'viewer',\r\n collaborator = 'collaborator',\r\n admin = 'admin',\r\n owner = 'owner',\r\n}\r\n\r\nexport interface User {\r\n // Identificação\r\n id: number;\r\n id_wl: number;\r\n id_account: number;\r\n id_api: number;\r\n\r\n // Dados pessoais\r\n name: string;\r\n last_name: string;\r\n email: string;\r\n ddi: string;\r\n phone: string;\r\n rg: string | null;\r\n cpf: string | null;\r\n gender: number;\r\n\r\n // Autenticação e segurança\r\n two_factor_authentication: boolean;\r\n google_sub?: string | null;\r\n google_linked_at?: string | null;\r\n\r\n // Perfil e permissões\r\n profile: UserProfile;\r\n\r\n // Preferências\r\n language: string;\r\n receive_sms: boolean;\r\n receive_email: boolean;\r\n photo: string | null;\r\n\r\n // Metadados\r\n deleted: number;\r\n datetime_alt: string;\r\n datetime_del: string | null;\r\n datetime_add: string;\r\n\r\n total_projects: number;\r\n projects: { id: number; title: string }[];\r\n\r\n initials?: string;\r\n emailVerified?: boolean;\r\n createdAt?: string;\r\n updatedAt?: string;\r\n}\r\n\r\nexport interface GetUserDataResponse {\r\n status: 0 | 1;\r\n total: number;\r\n data: User
|
|
1
|
+
{"version":3,"sources":["../../../src/modules/users/schema.ts"],"sourcesContent":["export enum UserProfile {\r\n viewer = 'viewer',\r\n collaborator = 'collaborator',\r\n admin = 'admin',\r\n owner = 'owner',\r\n}\r\n\r\nexport interface User {\r\n // Identificação\r\n id: number;\r\n id_wl: number;\r\n id_account: number;\r\n id_api: number;\r\n\r\n // Dados pessoais\r\n name: string;\r\n last_name: string;\r\n email: string;\r\n ddi: string;\r\n phone: string;\r\n rg: string | null;\r\n cpf: string | null;\r\n gender: number;\r\n\r\n // Autenticação e segurança\r\n two_factor_authentication: boolean;\r\n google_sub?: string | null;\r\n google_linked_at?: string | null;\r\n\r\n // Perfil e permissões\r\n profile: UserProfile;\r\n\r\n // Preferências\r\n language: string;\r\n receive_sms: boolean;\r\n receive_email: boolean;\r\n photo: string | null;\r\n\r\n // Metadados\r\n deleted: number;\r\n datetime_alt: string;\r\n datetime_del: string | null;\r\n datetime_add: string;\r\n\r\n total_projects: number;\r\n projects: { id: number; title: string }[];\r\n\r\n initials?: string;\r\n emailVerified?: boolean;\r\n createdAt?: string;\r\n updatedAt?: string;\r\n}\r\n\r\nexport interface GetUserDataResponse {\r\n status: 0 | 1;\r\n total: number;\r\n data: Array<User & { password?: string }>;\r\n}\r\n\r\nexport interface JWTPayload {\r\n session: {\r\n location: {\r\n continent: string;\r\n country: string;\r\n region: string;\r\n city: string;\r\n latitude: string;\r\n longitude: string;\r\n };\r\n ip: string;\r\n timezone: string;\r\n agent: string;\r\n code: string | null;\r\n };\r\n id_wl: string;\r\n id_account: number;\r\n id_user: number;\r\n iss: string;\r\n aud: string;\r\n iat: number;\r\n}\r\n"],"mappings":"AAAO,IAAK,cAAL,kBAAKA,iBAAL;AACL,EAAAA,aAAA,YAAS;AACT,EAAAA,aAAA,kBAAe;AACf,EAAAA,aAAA,WAAQ;AACR,EAAAA,aAAA,WAAQ;AAJE,SAAAA;AAAA,GAAA;","names":["UserProfile"]}
|
|
@@ -43,7 +43,8 @@ class UserService {
|
|
|
43
43
|
if (data.status === 0 || !data.data || data.data.length === 0) {
|
|
44
44
|
throw new ApiError("Dados do usu\xE1rio n\xE3o encontrados", "USER_NOT_FOUND", 404);
|
|
45
45
|
}
|
|
46
|
-
|
|
46
|
+
const { password, ...user } = data.data[0];
|
|
47
|
+
return user;
|
|
47
48
|
}
|
|
48
49
|
}
|
|
49
50
|
const userService = new UserService();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/modules/users/services/user.service.ts"],"sourcesContent":["\r\nimport { cookies } from 'next/headers';\r\n\r\nimport { ApiError } from '../../../infra/api/types';\r\nimport { decodeJwtPayload } from '../../../utils/jwt-payload';\r\nimport { GetUserDataResponse, JWTPayload, User } from '../schema';\r\nimport { findWhitelabelToken } from '../../whitelabel/utils/find-whitelabel-token';\r\nimport { buildWlOverride } from '../../auth/utils/build-wl-override';\r\n\r\nconst AUTH_COOKIE_NAME = 'greatapps';\r\nconst API_BASE_URL = process.env.GAPPS_R3_API_URL || 'https://r3-api.greatapps.dev.br';\r\n\r\nclass UserService {\r\n private async getAuthToken(): Promise<string> {\r\n if (process.env.DUMMY_AUTH_TOKEN) return process.env.DUMMY_AUTH_TOKEN;\r\n const cookieStore = await cookies();\r\n const token = cookieStore.get(AUTH_COOKIE_NAME)?.value;\r\n\r\n if (!token) {\r\n throw new ApiError('Não autenticado', 'NOT_AUTHENTICATED_GAT', 401);\r\n }\r\n\r\n return token;\r\n }\r\n\r\n private decodeJWT(token: string): JWTPayload {\r\n try {\r\n return decodeJwtPayload<JWTPayload>(token);\r\n } catch {\r\n throw new ApiError('Token inválido', 'INVALID_TOKEN', 401);\r\n }\r\n }\r\n\r\n async findById(overrides?: { authToken?: string }): Promise<User> {\r\n const token = await this.getAuthToken();\r\n const payload = this.decodeJWT(token);\r\n\r\n const { id_wl, id_account, id_user } = payload;\r\n const wlOverride = overrides ? undefined : await buildWlOverride(Number(id_wl));\r\n const wlToken = overrides?.authToken ?? wlOverride?.authToken ?? (await findWhitelabelToken()).token;\r\n\r\n const url = `${API_BASE_URL}/v1/pt-br/${id_wl}/accounts/${id_account}/users/${id_user}`;\r\n\r\n const response = await fetch(url, {\r\n method: 'GET',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n authorization: wlToken,\r\n },\r\n });\r\n\r\n if (!response.ok) {\r\n throw new ApiError('Erro ao buscar dados do usuário', 'FETCH_ERROR', response.status);\r\n }\r\n\r\n const data = (await response.json()) as GetUserDataResponse;\r\n\r\n if (data.status === 0 || !data.data || data.data.length === 0) {\r\n throw new ApiError('Dados do usuário não encontrados', 'USER_NOT_FOUND', 404);\r\n }\r\n\r\n
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/users/services/user.service.ts"],"sourcesContent":["\r\nimport { cookies } from 'next/headers';\r\n\r\nimport { ApiError } from '../../../infra/api/types';\r\nimport { decodeJwtPayload } from '../../../utils/jwt-payload';\r\nimport { GetUserDataResponse, JWTPayload, User } from '../schema';\r\nimport { findWhitelabelToken } from '../../whitelabel/utils/find-whitelabel-token';\r\nimport { buildWlOverride } from '../../auth/utils/build-wl-override';\r\n\r\nconst AUTH_COOKIE_NAME = 'greatapps';\r\nconst API_BASE_URL = process.env.GAPPS_R3_API_URL || 'https://r3-api.greatapps.dev.br';\r\n\r\nclass UserService {\r\n private async getAuthToken(): Promise<string> {\r\n if (process.env.DUMMY_AUTH_TOKEN) return process.env.DUMMY_AUTH_TOKEN;\r\n const cookieStore = await cookies();\r\n const token = cookieStore.get(AUTH_COOKIE_NAME)?.value;\r\n\r\n if (!token) {\r\n throw new ApiError('Não autenticado', 'NOT_AUTHENTICATED_GAT', 401);\r\n }\r\n\r\n return token;\r\n }\r\n\r\n private decodeJWT(token: string): JWTPayload {\r\n try {\r\n return decodeJwtPayload<JWTPayload>(token);\r\n } catch {\r\n throw new ApiError('Token inválido', 'INVALID_TOKEN', 401);\r\n }\r\n }\r\n\r\n async findById(overrides?: { authToken?: string }): Promise<User> {\r\n const token = await this.getAuthToken();\r\n const payload = this.decodeJWT(token);\r\n\r\n const { id_wl, id_account, id_user } = payload;\r\n const wlOverride = overrides ? undefined : await buildWlOverride(Number(id_wl));\r\n const wlToken = overrides?.authToken ?? wlOverride?.authToken ?? (await findWhitelabelToken()).token;\r\n\r\n const url = `${API_BASE_URL}/v1/pt-br/${id_wl}/accounts/${id_account}/users/${id_user}`;\r\n\r\n const response = await fetch(url, {\r\n method: 'GET',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n authorization: wlToken,\r\n },\r\n });\r\n\r\n if (!response.ok) {\r\n throw new ApiError('Erro ao buscar dados do usuário', 'FETCH_ERROR', response.status);\r\n }\r\n\r\n const data = (await response.json()) as GetUserDataResponse;\r\n\r\n if (data.status === 0 || !data.data || data.data.length === 0) {\r\n throw new ApiError('Dados do usuário não encontrados', 'USER_NOT_FOUND', 404);\r\n }\r\n\r\n const { password, ...user } = data.data[0];\r\n\r\n return user;\r\n }\r\n}\r\n\r\nexport const userService = new UserService();\r\n"],"mappings":"AACA,SAAS,eAAe;AAExB,SAAS,gBAAgB;AACzB,SAAS,wBAAwB;AAEjC,SAAS,2BAA2B;AACpC,SAAS,uBAAuB;AAEhC,MAAM,mBAAmB;AACzB,MAAM,eAAe,QAAQ,IAAI,oBAAoB;AAErD,MAAM,YAAY;AAAA,EAChB,MAAc,eAAgC;AAC5C,QAAI,QAAQ,IAAI,iBAAkB,QAAO,QAAQ,IAAI;AACrD,UAAM,cAAc,MAAM,QAAQ;AAClC,UAAM,QAAQ,YAAY,IAAI,gBAAgB,GAAG;AAEjD,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,SAAS,sBAAmB,yBAAyB,GAAG;AAAA,IACpE;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,UAAU,OAA2B;AAC3C,QAAI;AACF,aAAO,iBAA6B,KAAK;AAAA,IAC3C,QAAQ;AACN,YAAM,IAAI,SAAS,qBAAkB,iBAAiB,GAAG;AAAA,IAC3D;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,WAAmD;AAChE,UAAM,QAAQ,MAAM,KAAK,aAAa;AACtC,UAAM,UAAU,KAAK,UAAU,KAAK;AAEpC,UAAM,EAAE,OAAO,YAAY,QAAQ,IAAI;AACvC,UAAM,aAAa,YAAY,SAAY,MAAM,gBAAgB,OAAO,KAAK,CAAC;AAC9E,UAAM,UAAU,WAAW,aAAa,YAAY,cAAc,MAAM,oBAAoB,GAAG;AAE/F,UAAM,MAAM,GAAG,YAAY,aAAa,KAAK,aAAa,UAAU,UAAU,OAAO;AAErF,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,IACF,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,SAAS,sCAAmC,eAAe,SAAS,MAAM;AAAA,IACtF;AAEA,UAAM,OAAQ,MAAM,SAAS,KAAK;AAElC,QAAI,KAAK,WAAW,KAAK,CAAC,KAAK,QAAQ,KAAK,KAAK,WAAW,GAAG;AAC7D,YAAM,IAAI,SAAS,0CAAoC,kBAAkB,GAAG;AAAA,IAC9E;AAEA,UAAM,EAAE,UAAU,GAAG,KAAK,IAAI,KAAK,KAAK,CAAC;AAEzC,WAAO;AAAA,EACT;AACF;AAEO,MAAM,cAAc,IAAI,YAAY;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/providers/query.provider.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport {\r\n QueryCache,\r\n QueryClient,\r\n QueryClientProvider,\r\n} from \"@tanstack/react-query\";\r\nimport { ReactNode, useEffect, useState } from \"react\";\r\nimport dynamic from \"next/dynamic\";\r\nimport { toast } from \"sonner\";\r\nimport {\r\n PersistedClient,\r\n PersistQueryClientProvider,\r\n} from \"@tanstack/react-query-persist-client\";\r\nimport { set, get, del } from \"idb-keyval\";\r\nimport { isShareableQuery, shareQueryCacheBetweenTabs } from \"./share-query-cache\";\r\n\r\n// React Query Devtools só em desenvolvimento - remove do bundle de produção\r\nconst ReactQueryDevtools =\r\n process.env.NODE_ENV === \"development\"\r\n ? dynamic(\r\n () =>\r\n import(\"@tanstack/react-query-devtools\").then((mod) => ({\r\n default: mod.ReactQueryDevtools,\r\n })),\r\n { ssr: false },\r\n )\r\n : () => null;\r\n\r\nexport const persister = {\r\n persistClient: async (client: PersistedClient) => {\r\n try {\r\n await set(\"rq-cache\", client);\r\n } catch {\r\n console.warn(\"Falha ao persistir cache\");\r\n }\r\n },\r\n restoreClient: async (): Promise<PersistedClient | undefined> => {\r\n try {\r\n return await get(\"rq-cache\");\r\n } catch {\r\n await del(\"rq-cache\").catch(() => {});\r\n return undefined;\r\n }\r\n },\r\n removeClient: async () => {\r\n try {\r\n await del(\"rq-cache\");\r\n } catch {\r\n console.warn(\"Falha ao remover cache\");\r\n }\r\n },\r\n};\r\n\r\ninterface QueryProviderProps {\r\n children: ReactNode;\r\n persisterVersion?: string;\r\n}\r\n\r\nexport function QueryProvider({\r\n children,\r\n persisterVersion = \"
|
|
1
|
+
{"version":3,"sources":["../../src/providers/query.provider.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport {\r\n QueryCache,\r\n QueryClient,\r\n QueryClientProvider,\r\n} from \"@tanstack/react-query\";\r\nimport { ReactNode, useEffect, useState } from \"react\";\r\nimport dynamic from \"next/dynamic\";\r\nimport { toast } from \"sonner\";\r\nimport {\r\n PersistedClient,\r\n PersistQueryClientProvider,\r\n} from \"@tanstack/react-query-persist-client\";\r\nimport { set, get, del } from \"idb-keyval\";\r\nimport { isShareableQuery, shareQueryCacheBetweenTabs } from \"./share-query-cache\";\r\n\r\n// React Query Devtools só em desenvolvimento - remove do bundle de produção\r\nconst ReactQueryDevtools =\r\n process.env.NODE_ENV === \"development\"\r\n ? dynamic(\r\n () =>\r\n import(\"@tanstack/react-query-devtools\").then((mod) => ({\r\n default: mod.ReactQueryDevtools,\r\n })),\r\n { ssr: false },\r\n )\r\n : () => null;\r\n\r\nexport const persister = {\r\n persistClient: async (client: PersistedClient) => {\r\n try {\r\n await set(\"rq-cache\", client);\r\n } catch {\r\n console.warn(\"Falha ao persistir cache\");\r\n }\r\n },\r\n restoreClient: async (): Promise<PersistedClient | undefined> => {\r\n try {\r\n return await get(\"rq-cache\");\r\n } catch {\r\n await del(\"rq-cache\").catch(() => {});\r\n return undefined;\r\n }\r\n },\r\n removeClient: async () => {\r\n try {\r\n await del(\"rq-cache\");\r\n } catch {\r\n console.warn(\"Falha ao remover cache\");\r\n }\r\n },\r\n};\r\n\r\ninterface QueryProviderProps {\r\n children: ReactNode;\r\n persisterVersion?: string;\r\n}\r\n\r\nexport function QueryProvider({\r\n children,\r\n persisterVersion = \"v2\",\r\n}: QueryProviderProps) {\r\n const [queryClient] = useState(\r\n () =>\r\n new QueryClient({\r\n defaultOptions: {\r\n queries: {\r\n staleTime: 15 * 1000,\r\n gcTime: 5 * 60 * 1000,\r\n refetchOnWindowFocus: false,\r\n refetchOnReconnect: true,\r\n retry: 2,\r\n retryDelay: (attempt) => Math.min(1000 * 2 ** attempt, 30000),\r\n },\r\n mutations: {\r\n retry: false,\r\n },\r\n },\r\n }),\r\n );\r\n\r\n useEffect(() => shareQueryCacheBetweenTabs(queryClient), [queryClient]);\r\n\r\n return (\r\n <PersistQueryClientProvider\r\n client={queryClient}\r\n persistOptions={{\r\n persister,\r\n maxAge: 2 * 60 * 60 * 1000,\r\n buster: persisterVersion,\r\n dehydrateOptions: {\r\n shouldDehydrateQuery: isShareableQuery,\r\n },\r\n }}\r\n >\r\n {children}\r\n <ReactQueryDevtools initialIsOpen={false} />\r\n </PersistQueryClientProvider>\r\n );\r\n}\r\n"],"mappings":";AAqFI,SAYE,KAZF;AAnFJ;AAAA,EAEE;AAAA,OAEK;AACP,SAAoB,WAAW,gBAAgB;AAC/C,OAAO,aAAa;AAEpB;AAAA,EAEE;AAAA,OACK;AACP,SAAS,KAAK,KAAK,WAAW;AAC9B,SAAS,kBAAkB,kCAAkC;AAG7D,MAAM,qBACJ,QAAQ,IAAI,aAAa,gBACrB;AAAA,EACE,MACE,OAAO,gCAAgC,EAAE,KAAK,CAAC,SAAS;AAAA,IACtD,SAAS,IAAI;AAAA,EACf,EAAE;AAAA,EACJ,EAAE,KAAK,MAAM;AACf,IACA,MAAM;AAEL,MAAM,YAAY;AAAA,EACvB,eAAe,OAAO,WAA4B;AAChD,QAAI;AACF,YAAM,IAAI,YAAY,MAAM;AAAA,IAC9B,QAAQ;AACN,cAAQ,KAAK,0BAA0B;AAAA,IACzC;AAAA,EACF;AAAA,EACA,eAAe,YAAkD;AAC/D,QAAI;AACF,aAAO,MAAM,IAAI,UAAU;AAAA,IAC7B,QAAQ;AACN,YAAM,IAAI,UAAU,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AACpC,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EACA,cAAc,YAAY;AACxB,QAAI;AACF,YAAM,IAAI,UAAU;AAAA,IACtB,QAAQ;AACN,cAAQ,KAAK,wBAAwB;AAAA,IACvC;AAAA,EACF;AACF;AAOO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA,mBAAmB;AACrB,GAAuB;AACrB,QAAM,CAAC,WAAW,IAAI;AAAA,IACpB,MACE,IAAI,YAAY;AAAA,MACd,gBAAgB;AAAA,QACd,SAAS;AAAA,UACP,WAAW,KAAK;AAAA,UAChB,QAAQ,IAAI,KAAK;AAAA,UACjB,sBAAsB;AAAA,UACtB,oBAAoB;AAAA,UACpB,OAAO;AAAA,UACP,YAAY,CAAC,YAAY,KAAK,IAAI,MAAO,KAAK,SAAS,GAAK;AAAA,QAC9D;AAAA,QACA,WAAW;AAAA,UACT,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACL;AAEA,YAAU,MAAM,2BAA2B,WAAW,GAAG,CAAC,WAAW,CAAC;AAEtE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,QAAQ;AAAA,MACR,gBAAgB;AAAA,QACd;AAAA,QACA,QAAQ,IAAI,KAAK,KAAK;AAAA,QACtB,QAAQ;AAAA,QACR,kBAAkB;AAAA,UAChB,sBAAsB;AAAA,QACxB;AAAA,MACF;AAAA,MAEC;AAAA;AAAA,QACD,oBAAC,sBAAmB,eAAe,OAAO;AAAA;AAAA;AAAA,EAC5C;AAEJ;","names":[]}
|
package/package.json
CHANGED
|
@@ -12,7 +12,7 @@ import { useCurrencyFormatter } from '../../../../modules/accounts/hooks/use-cur
|
|
|
12
12
|
import { useRefreshChargePix } from '../../../../modules/charges/hooks/refresh-pix.hook';
|
|
13
13
|
import type { Charge } from '../../../../modules/charges/types/charge.type';
|
|
14
14
|
import type { PixRefreshData } from '../../../../modules/charges/types/refresh-pix.type';
|
|
15
|
-
import
|
|
15
|
+
import useSecondsUntil from '../../../../hooks/useSecondsUntil';
|
|
16
16
|
import { copyToClipboard } from '../../../../utils/browser/clipboard';
|
|
17
17
|
import { qrCodeToDataUrl } from '../../../../utils/qrcode/to-data-url';
|
|
18
18
|
|
|
@@ -82,12 +82,7 @@ export function PixDetailsDialog({ open, charge, onOpenChange }: PixDetailsDialo
|
|
|
82
82
|
const isRefreshing = needsRefresh && refreshPix.isPending;
|
|
83
83
|
const refreshNotice = refreshPix.data && !refreshPix.data.pix ? refreshPix.data.message : null;
|
|
84
84
|
|
|
85
|
-
const
|
|
86
|
-
expiresAtRaw && mountedAt
|
|
87
|
-
? Math.max(0, Math.floor((new Date(expiresAtRaw).getTime() - mountedAt) / 1000))
|
|
88
|
-
: null;
|
|
89
|
-
const shouldShowCountdown = typeof expiresInSeconds === 'number' && expiresInSeconds > 0;
|
|
90
|
-
const { seconds } = useCountdownTimer({ initialSeconds: shouldShowCountdown ? expiresInSeconds : 1 });
|
|
85
|
+
const secondsUntilExpiry = useSecondsUntil(expiresAtRaw);
|
|
91
86
|
|
|
92
87
|
useEffect(() => {
|
|
93
88
|
if (!qrCode) {
|
|
@@ -185,9 +180,9 @@ export function PixDetailsDialog({ open, charge, onOpenChange }: PixDetailsDialo
|
|
|
185
180
|
</div>
|
|
186
181
|
|
|
187
182
|
<div className="flex flex-col gap-6 p-5 border border-zinc-200 rounded-lg bg-white items-center">
|
|
188
|
-
{
|
|
183
|
+
{!!secondsUntilExpiry && (
|
|
189
184
|
<p className="paragraph-small-semibold text-zinc-950 text-center">
|
|
190
|
-
{translate('payIn')} <span className="text-red-600">{formatCountdown(
|
|
185
|
+
{translate('payIn')} <span className="text-red-600">{formatCountdown(secondsUntilExpiry)}</span>
|
|
191
186
|
</p>
|
|
192
187
|
)}
|
|
193
188
|
|
|
@@ -10,7 +10,7 @@ import { Toast } from '../../../ui/feedback/Toast';
|
|
|
10
10
|
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '../../../ui/overlay/Dialog';
|
|
11
11
|
import { useCurrencyFormatter } from '../../../../modules/accounts/hooks/use-currency-formatter.hook';
|
|
12
12
|
import { usePendingPixStatus } from '../../../../modules/subscriptions/hooks/pending-pix-status.hook';
|
|
13
|
-
import
|
|
13
|
+
import useSecondsUntil from '../../../../hooks/useSecondsUntil';
|
|
14
14
|
import { copyToClipboard } from '../../../../utils/browser/clipboard';
|
|
15
15
|
import { qrCodeToDataUrl } from '../../../../utils/qrcode/to-data-url';
|
|
16
16
|
import { useSubscriptionFlows } from '../../../../store/useSubscriptionFlows';
|
|
@@ -39,20 +39,11 @@ export function PixPaymentDialog() {
|
|
|
39
39
|
const close = useSubscriptionFlows((state) => state.closePixPayment);
|
|
40
40
|
const openPlansCatalog = useSubscriptionFlows((state) => state.openPlansCatalog);
|
|
41
41
|
|
|
42
|
-
const [mountedAt, setMountedAt] = useState<number | null>(null);
|
|
43
42
|
const [generatedQrImage, setGeneratedQrImage] = useState<string | null>(null);
|
|
44
43
|
|
|
45
44
|
const { data: statusData } = usePendingPixStatus(pixPayment?.correlationId);
|
|
46
45
|
const phase = statusData?.data?.phase;
|
|
47
46
|
|
|
48
|
-
useEffect(() => {
|
|
49
|
-
if (!pixPayment) {
|
|
50
|
-
setMountedAt(null);
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
setMountedAt(Date.now());
|
|
54
|
-
}, [pixPayment]);
|
|
55
|
-
|
|
56
47
|
useEffect(() => {
|
|
57
48
|
const qrCode = pixPayment?.qrCode;
|
|
58
49
|
if (!qrCode) {
|
|
@@ -79,19 +70,22 @@ export function PixPaymentDialog() {
|
|
|
79
70
|
};
|
|
80
71
|
}, [pixPayment?.qrCode]);
|
|
81
72
|
|
|
82
|
-
const
|
|
73
|
+
const isCompleted = phase === 'completed';
|
|
74
|
+
const isAuthorizedOnly = statusData?.data?.payment_collected === false;
|
|
75
|
+
const completedTitle = isAuthorizedOnly ? translate('authorizedTitle') : translate('paidTitle');
|
|
76
|
+
const completedMessage = isAuthorizedOnly ? translate('authorizedMessage') : translate('paidToast');
|
|
83
77
|
const isRejected = phase === 'rejected';
|
|
84
78
|
const isExpired = phase === 'expired';
|
|
85
79
|
|
|
86
80
|
// Pago avisa uma vez; a janela fica com a confirmação na tela, como a página do gapps fazia.
|
|
87
81
|
const paidNotifiedRef = useRef(false);
|
|
88
82
|
useEffect(() => {
|
|
89
|
-
if (!
|
|
83
|
+
if (!isCompleted || paidNotifiedRef.current) return;
|
|
90
84
|
paidNotifiedRef.current = true;
|
|
91
85
|
toast.custom((toastId) => (
|
|
92
|
-
<Toast variant="success" message={
|
|
86
|
+
<Toast variant="success" message={completedMessage} toastId={toastId} />
|
|
93
87
|
));
|
|
94
|
-
}, [
|
|
88
|
+
}, [isCompleted, completedMessage]);
|
|
95
89
|
|
|
96
90
|
useEffect(() => {
|
|
97
91
|
if (!pixPayment) paidNotifiedRef.current = false;
|
|
@@ -102,12 +96,7 @@ export function PixPaymentDialog() {
|
|
|
102
96
|
openPlansCatalog();
|
|
103
97
|
};
|
|
104
98
|
|
|
105
|
-
const
|
|
106
|
-
pixPayment?.expiresAt && mountedAt
|
|
107
|
-
? Math.max(0, Math.floor((new Date(pixPayment.expiresAt).getTime() - mountedAt) / 1000))
|
|
108
|
-
: null;
|
|
109
|
-
const shouldShowCountdown = typeof expiresInSeconds === 'number' && expiresInSeconds > 0;
|
|
110
|
-
const { seconds } = useCountdownTimer({ initialSeconds: shouldShowCountdown ? expiresInSeconds : 1 });
|
|
99
|
+
const secondsUntilExpiry = useSecondsUntil(pixPayment?.expiresAt);
|
|
111
100
|
|
|
112
101
|
const handleCopyCode = async () => {
|
|
113
102
|
if (!pixPayment?.qrCode) return;
|
|
@@ -141,15 +130,15 @@ export function PixPaymentDialog() {
|
|
|
141
130
|
|
|
142
131
|
{/* Fechado o ciclo (pago, recusado ou expirado), o QR perde a função: a janela vira o
|
|
143
132
|
desfecho, como a página de pix do gapps. */}
|
|
144
|
-
{
|
|
133
|
+
{isCompleted || isRejected || isExpired ? (
|
|
145
134
|
<div className="flex flex-col items-center justify-center gap-4 p-8 text-center">
|
|
146
135
|
<div
|
|
147
136
|
className={cn(
|
|
148
137
|
'size-12 rounded-full flex items-center justify-center',
|
|
149
|
-
|
|
138
|
+
isCompleted ? 'bg-green-50' : 'bg-red-50'
|
|
150
139
|
)}
|
|
151
140
|
>
|
|
152
|
-
{
|
|
141
|
+
{isCompleted ? (
|
|
153
142
|
<IconCircleCheck size={24} className="text-green-500" />
|
|
154
143
|
) : (
|
|
155
144
|
<IconAlertTriangle size={24} className="text-red-500" />
|
|
@@ -158,18 +147,18 @@ export function PixPaymentDialog() {
|
|
|
158
147
|
|
|
159
148
|
<div className="flex flex-col gap-1">
|
|
160
149
|
<span className="paragraph-xlarge-semibold text-zinc-950">
|
|
161
|
-
{
|
|
162
|
-
?
|
|
150
|
+
{isCompleted
|
|
151
|
+
? completedTitle
|
|
163
152
|
: isRejected
|
|
164
153
|
? translate('rejectedTitle')
|
|
165
154
|
: translate('expiredTitle')}
|
|
166
155
|
</span>
|
|
167
156
|
<span className="paragraph-small-regular text-zinc-500">
|
|
168
|
-
{
|
|
157
|
+
{isCompleted ? completedMessage : translate('rejectedOrExpiredDescription')}
|
|
169
158
|
</span>
|
|
170
159
|
</div>
|
|
171
160
|
|
|
172
|
-
{
|
|
161
|
+
{isCompleted ? (
|
|
173
162
|
<Button variant="secondary" className="h-10" onClick={close}>
|
|
174
163
|
{translateActions('common.actions.close')}
|
|
175
164
|
</Button>
|
|
@@ -189,9 +178,9 @@ export function PixPaymentDialog() {
|
|
|
189
178
|
)}
|
|
190
179
|
|
|
191
180
|
<div className="flex flex-col gap-6 p-5 border border-zinc-200 rounded-lg bg-white items-center">
|
|
192
|
-
{
|
|
181
|
+
{!!secondsUntilExpiry && (
|
|
193
182
|
<p className="paragraph-small-semibold text-zinc-950 text-center">
|
|
194
|
-
{translate('payIn')} <span className="text-red-600">{formatCountdown(
|
|
183
|
+
{translate('payIn')} <span className="text-red-600">{formatCountdown(secondsUntilExpiry)}</span>
|
|
195
184
|
</p>
|
|
196
185
|
)}
|
|
197
186
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState } from 'react';
|
|
4
|
+
|
|
5
|
+
export default function useSecondsUntil(deadline: string | null | undefined): number | null {
|
|
6
|
+
const [now, setNow] = useState<number | null>(null);
|
|
7
|
+
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
if (!deadline) return;
|
|
10
|
+
setNow(Date.now());
|
|
11
|
+
const interval = setInterval(() => setNow(Date.now()), 1000);
|
|
12
|
+
return () => clearInterval(interval);
|
|
13
|
+
}, [deadline]);
|
|
14
|
+
|
|
15
|
+
if (!deadline || now === null) return null;
|
|
16
|
+
return Math.max(0, Math.floor((new Date(deadline).getTime() - now) / 1000));
|
|
17
|
+
}
|
|
@@ -1092,6 +1092,8 @@ const messages = {
|
|
|
1092
1092
|
paidToast: 'Payment processed successfully.',
|
|
1093
1093
|
waitingPayment: 'Waiting for payment confirmation...',
|
|
1094
1094
|
paidTitle: 'PIX paid',
|
|
1095
|
+
authorizedTitle: 'Automatic PIX authorized',
|
|
1096
|
+
authorizedMessage: 'The charge will be made automatically on the due date.',
|
|
1095
1097
|
rejectedTitle: 'PIX rejected',
|
|
1096
1098
|
expiredTitle: 'PIX code expired',
|
|
1097
1099
|
rejectedOrExpiredDescription: 'Click below to generate a new PIX code',
|
|
@@ -1098,6 +1098,8 @@ const messages = {
|
|
|
1098
1098
|
paidToast: 'Pago realizado exitosamente.',
|
|
1099
1099
|
waitingPayment: 'Esperando la confirmación del pago...',
|
|
1100
1100
|
paidTitle: 'PIX pagado',
|
|
1101
|
+
authorizedTitle: 'PIX automático autorizado',
|
|
1102
|
+
authorizedMessage: 'El cobro se realizará automáticamente en la fecha de vencimiento.',
|
|
1101
1103
|
rejectedTitle: 'PIX rechazado',
|
|
1102
1104
|
expiredTitle: 'Código PIX expirado',
|
|
1103
1105
|
rejectedOrExpiredDescription: 'Haz clic abajo para generar un nuevo código PIX',
|
|
@@ -1105,6 +1105,8 @@ const messages = {
|
|
|
1105
1105
|
paidToast: 'Pagamento efetuado com sucesso.',
|
|
1106
1106
|
waitingPayment: 'Aguardando a confirmação do pagamento...',
|
|
1107
1107
|
paidTitle: 'PIX pago',
|
|
1108
|
+
authorizedTitle: 'PIX automático autorizado',
|
|
1109
|
+
authorizedMessage: 'A cobrança será feita automaticamente na data de vencimento.',
|
|
1108
1110
|
rejectedTitle: 'Pix recusado',
|
|
1109
1111
|
expiredTitle: 'Código PIX expirado',
|
|
1110
1112
|
rejectedOrExpiredDescription: 'Clique abaixo para gerar um novo código PIX',
|
|
@@ -42,12 +42,20 @@ class AccountService {
|
|
|
42
42
|
);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
const { user, ...account } = response.data[0];
|
|
46
|
+
|
|
47
|
+
return account;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private pickUsersQueryParams(params: Partial<AccountUsersPaginationParams> = {}) {
|
|
51
|
+
const { page, limit, search, name, notInProject, profiles, firstId } = params;
|
|
52
|
+
|
|
53
|
+
return { page, limit, search, name, notInProject, profiles, firstId };
|
|
46
54
|
}
|
|
47
55
|
|
|
48
56
|
async listAccountUsers(params?: Partial<AccountUsersPaginationParams>) {
|
|
49
57
|
const { id_account } = await getUserContext();
|
|
50
|
-
const queryParams = buildQueryParams(params);
|
|
58
|
+
const queryParams = buildQueryParams(this.pickUsersQueryParams(params));
|
|
51
59
|
const endpoint = `/accounts/${id_account}/users?${queryParams}`;
|
|
52
60
|
const response = await api.apps.get<ListAccountUsersResponse>(endpoint);
|
|
53
61
|
|
|
@@ -71,7 +79,7 @@ class AccountService {
|
|
|
71
79
|
*/
|
|
72
80
|
async listAccountMembers(params?: Partial<AccountUsersPaginationParams>) {
|
|
73
81
|
const { id_account, id_user } = await getUserContext();
|
|
74
|
-
const queryParams = buildQueryParams({ ...params, scopeUserId: id_user });
|
|
82
|
+
const queryParams = buildQueryParams({ ...this.pickUsersQueryParams(params), scopeUserId: id_user });
|
|
75
83
|
const response = await api.apps.get<ListAccountUsersResponse>(
|
|
76
84
|
`/accounts/${id_account}/users?${queryParams}`
|
|
77
85
|
);
|
|
@@ -106,7 +114,7 @@ class AccountService {
|
|
|
106
114
|
);
|
|
107
115
|
}
|
|
108
116
|
|
|
109
|
-
return response;
|
|
117
|
+
return { status: response.status, message: response.message };
|
|
110
118
|
}
|
|
111
119
|
|
|
112
120
|
async deleteAccountUser(userId: number): Promise<DeleteAccountUserResponse> {
|
|
@@ -119,7 +127,7 @@ class AccountService {
|
|
|
119
127
|
throw new ApiError(response.message || 'Erro ao deletar usuário', 'DELETE_USER_FAILED', 400);
|
|
120
128
|
}
|
|
121
129
|
|
|
122
|
-
return response;
|
|
130
|
+
return { status: response.status, message: response.message };
|
|
123
131
|
}
|
|
124
132
|
|
|
125
133
|
async deleteAccount(data: DeleteAccountRequest): Promise<DeleteAccountResponse> {
|
|
@@ -150,7 +158,7 @@ class AccountService {
|
|
|
150
158
|
throw new ApiError(response.message || 'Erro ao criar usuário', 'CREATE_USER_FAILED', 400);
|
|
151
159
|
}
|
|
152
160
|
|
|
153
|
-
return response;
|
|
161
|
+
return { status: response.status, message: response.message };
|
|
154
162
|
}
|
|
155
163
|
|
|
156
164
|
private async resolvePhotoField(user: UpdateAccountUserRequest): Promise<{ photo?: string | null }> {
|
|
@@ -177,7 +185,7 @@ class AccountService {
|
|
|
177
185
|
);
|
|
178
186
|
}
|
|
179
187
|
|
|
180
|
-
return response;
|
|
188
|
+
return { status: response.status, message: response.message };
|
|
181
189
|
}
|
|
182
190
|
|
|
183
191
|
async updateAccountUserById(
|
|
@@ -198,7 +206,7 @@ class AccountService {
|
|
|
198
206
|
);
|
|
199
207
|
}
|
|
200
208
|
|
|
201
|
-
return response;
|
|
209
|
+
return { status: response.status, message: response.message };
|
|
202
210
|
}
|
|
203
211
|
|
|
204
212
|
async updateAccount(data: UpdateAccountRequest): Promise<UpdateAccountResponse> {
|
|
@@ -55,7 +55,7 @@ export interface AccountUsersPaginationParams {
|
|
|
55
55
|
export interface GetAccountDataResponse {
|
|
56
56
|
status: 0 | 1;
|
|
57
57
|
message: string;
|
|
58
|
-
data: Account
|
|
58
|
+
data: Array<Account & { user?: User }>;
|
|
59
59
|
total: number;
|
|
60
60
|
}
|
|
61
61
|
|
|
@@ -92,7 +92,6 @@ export interface CreateAccountUserRequest {
|
|
|
92
92
|
export interface CreateAccountUserResponse {
|
|
93
93
|
status: 0 | 1;
|
|
94
94
|
message: string;
|
|
95
|
-
data: User[];
|
|
96
95
|
}
|
|
97
96
|
|
|
98
97
|
export interface UpdateAccountUserRequest {
|
|
@@ -118,7 +117,6 @@ export interface UpdateAccountUserRequest {
|
|
|
118
117
|
export interface UpdateAccountUserResponse {
|
|
119
118
|
status: 0 | 1;
|
|
120
119
|
message: string;
|
|
121
|
-
data: User[];
|
|
122
120
|
}
|
|
123
121
|
|
|
124
122
|
export interface ChangeUserPhotoResponse {
|
|
@@ -16,6 +16,7 @@ export const PendingPixStatusDataSchema = z
|
|
|
16
16
|
payment_method: z.number().nullable().optional(),
|
|
17
17
|
subscription_id: z.union([z.number(), z.string()]).optional(),
|
|
18
18
|
completed_at: z.string().nullable().optional(),
|
|
19
|
+
payment_collected: z.boolean().optional(),
|
|
19
20
|
pix: z
|
|
20
21
|
.object({
|
|
21
22
|
qr_code: z.string().nullable().optional(),
|