@greatapps/common 1.1.542 → 1.1.546
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/ConfigurationsMyAccountModal.mjs +1 -1
- package/dist/components/account/ConfigurationsMyAccountModal.mjs.map +1 -1
- package/dist/components/account/ConfirmDeleteAccountModal.mjs +12 -10
- package/dist/components/account/ConfirmDeleteAccountModal.mjs.map +1 -1
- package/dist/components/account/DeleteAccountModal.mjs +21 -5
- package/dist/components/account/DeleteAccountModal.mjs.map +1 -1
- package/dist/components/account/sections/MyProfileSection.mjs +3 -61
- package/dist/components/account/sections/MyProfileSection.mjs.map +1 -1
- package/dist/components/navigation/CancelledSubscriptionBanner.mjs +5 -4
- package/dist/components/navigation/CancelledSubscriptionBanner.mjs.map +1 -1
- package/dist/modules/accounts/actions/account-management.action.mjs +16 -15
- package/dist/modules/accounts/actions/account-management.action.mjs.map +1 -1
- package/dist/modules/accounts/hooks/useAccountManagement.mjs.map +1 -1
- package/dist/modules/accounts/services/account.service.mjs +5 -2
- package/dist/modules/accounts/services/account.service.mjs.map +1 -1
- package/dist/modules/auth/hooks/useUserQuery.mjs +1 -1
- package/dist/modules/auth/hooks/useUserQuery.mjs.map +1 -1
- package/dist/modules/auth/utils/require-valid-session.mjs +17 -0
- package/dist/modules/auth/utils/require-valid-session.mjs.map +1 -0
- package/dist/modules/cards/actions/create-card.action.mjs +2 -2
- package/dist/modules/cards/actions/create-card.action.mjs.map +1 -1
- package/dist/modules/cards/actions/delete-card.action.mjs +2 -2
- package/dist/modules/cards/actions/delete-card.action.mjs.map +1 -1
- package/dist/modules/cards/actions/set-default-card.action.mjs +2 -2
- package/dist/modules/cards/actions/set-default-card.action.mjs.map +1 -1
- package/dist/modules/cards/types.mjs +13 -12
- package/dist/modules/cards/types.mjs.map +1 -1
- package/dist/modules/plans/utils/map-api-plan-to-ui.mjs +1 -1
- package/dist/modules/plans/utils/map-api-plan-to-ui.mjs.map +1 -1
- package/dist/modules/projects/actions/add-project-user.action.mjs +2 -2
- package/dist/modules/projects/actions/add-project-user.action.mjs.map +1 -1
- package/dist/modules/projects/actions/create-project.action.mjs +2 -2
- package/dist/modules/projects/actions/create-project.action.mjs.map +1 -1
- package/dist/modules/projects/actions/delete-project.action.mjs +2 -2
- package/dist/modules/projects/actions/delete-project.action.mjs.map +1 -1
- package/dist/modules/projects/actions/remove-project-user.action.mjs +2 -2
- package/dist/modules/projects/actions/remove-project-user.action.mjs.map +1 -1
- package/dist/modules/projects/actions/update-project.action.mjs +2 -2
- package/dist/modules/projects/actions/update-project.action.mjs.map +1 -1
- package/dist/modules/subscriptions/actions/update-subscription-plan.action.mjs +2 -2
- package/dist/modules/subscriptions/actions/update-subscription-plan.action.mjs.map +1 -1
- package/dist/modules/subscriptions/types/subscription.type.mjs +2 -1
- package/dist/modules/subscriptions/types/subscription.type.mjs.map +1 -1
- package/dist/modules/users/action/mark-all-messages-as-read.action.mjs +2 -2
- package/dist/modules/users/action/mark-all-messages-as-read.action.mjs.map +1 -1
- package/dist/modules/users/action/mark-message-as-read.action.mjs +2 -2
- package/dist/modules/users/action/mark-message-as-read.action.mjs.map +1 -1
- package/dist/server.mjs +4 -0
- package/dist/server.mjs.map +1 -1
- package/dist/store/useAccountModals.mjs +25 -4
- package/dist/store/useAccountModals.mjs.map +1 -1
- package/dist/utils/safeMutationAction.mjs +13 -0
- package/dist/utils/safeMutationAction.mjs.map +1 -0
- package/package.json +1 -1
- package/src/components/account/ConfigurationsMyAccountModal.tsx +1 -0
- package/src/components/account/ConfirmDeleteAccountModal.tsx +16 -7
- package/src/components/account/DeleteAccountModal.tsx +24 -4
- package/src/components/account/sections/MyProfileSection.tsx +2 -68
- package/src/components/navigation/CancelledSubscriptionBanner.tsx +7 -4
- package/src/modules/accounts/actions/account-management.action.ts +17 -15
- package/src/modules/accounts/hooks/useAccountManagement.ts +2 -1
- package/src/modules/accounts/services/account.service.ts +6 -2
- package/src/modules/accounts/types.ts +4 -0
- package/src/modules/auth/hooks/useUserQuery.ts +1 -1
- package/src/modules/auth/utils/require-valid-session.ts +35 -0
- package/src/modules/cards/actions/create-card.action.ts +2 -2
- package/src/modules/cards/actions/delete-card.action.ts +2 -2
- package/src/modules/cards/actions/set-default-card.action.ts +2 -2
- package/src/modules/cards/types.ts +14 -12
- package/src/modules/plans/utils/map-api-plan-to-ui.ts +1 -1
- package/src/modules/projects/actions/add-project-user.action.ts +2 -2
- package/src/modules/projects/actions/create-project.action.ts +2 -2
- package/src/modules/projects/actions/delete-project.action.ts +2 -2
- package/src/modules/projects/actions/remove-project-user.action.ts +2 -2
- package/src/modules/projects/actions/update-project.action.ts +2 -2
- package/src/modules/subscriptions/actions/update-subscription-plan.action.ts +2 -2
- package/src/modules/subscriptions/types/subscription.type.ts +2 -1
- package/src/modules/users/action/mark-all-messages-as-read.action.ts +2 -2
- package/src/modules/users/action/mark-message-as-read.action.ts +2 -2
- package/src/server.ts +2 -0
- package/src/store/useAccountModals.ts +41 -8
- package/src/utils/safeMutationAction.ts +30 -0
package/dist/server.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["import 'server-only';\r\n\r\n// API Client\r\nexport { ApiClient, api, apiClient } from './infra/api/client';\r\n\r\n// Services\r\nexport { authService } from './modules/auth/services/auth.service';\r\nexport { whitelabelService } from './modules/whitelabel/services/whitelabel.service';\r\nexport { revalidateWhitelabelAction } from './modules/whitelabel/actions/revalidate-whitelabel.action';\r\nexport { assertManagementPermission } from './modules/auth/utils/assert-management-permission';\r\nexport { assertManagementSubscription } from './modules/auth/utils/assert-management-subscription';\r\nexport { assertSubscriptionAddon } from './modules/auth/utils/assert-subscription-addon';\r\nexport { assertPaidSubscription } from './modules/auth/utils/assert-paid-subscription';\r\nexport { subscriptionsService } from './modules/subscriptions/services/subscriptions.service';\r\nexport { plansService } from './modules/plans/services/plans.service';\r\nexport { cardsService } from './modules/cards/services/cards.service';\r\nexport { iaCreditsService } from './modules/ia-credits/services/ia-credits.service';\r\n\r\n// Actions\r\nexport { findWhitelabel } from './modules/whitelabel/actions/find-whitelabel.action';\r\nexport { validateSessionAction } from './modules/auth/actions/validate-session.action';\r\nexport { findUserById } from './modules/users/action/find-user-by-id.action';\r\nexport { findCurrentAccount } from './modules/accounts/actions/find-current-account.action';\r\nexport { getAccountTokenAction } from './modules/accounts/actions/get-account-token.action';\r\nexport { listSubscriptionsAction } from './modules/subscriptions/actions/list-subscriptions.action';\r\nexport { findPlanByIdAction } from './modules/plans/actions/find-plan-by-id.action';\r\nexport { listPlansAction } from './modules/plans/actions/list-plans.action';\r\nexport { calculateSubscriptionAction } from './modules/subscriptions/actions/calculate-subscription.action';\r\nexport { updateSubscriptionPlanAction } from './modules/subscriptions/actions/update-subscription-plan.action';\r\nexport { listCardsAction } from './modules/cards/actions/list-cards.action';\r\nexport { createCardAction } from './modules/cards/actions/create-card.action';\r\nexport { resolvePlanExtrasPrices } from './modules/subscriptions/utils/resolve-plan-extras-prices';\r\nexport { hasSubscriptionExpired } from './modules/subscriptions/utils/has-subscription-expired';\r\nexport { listIaCreditsAction } from './modules/ia-credits/actions/list-ia-credits.action';\r\nexport { countPagesAction } from './modules/pages/actions/count-pages.action';\r\n\r\n// Project Services & Actions (server-only)\r\nexport { projectsService } from './modules/projects/services/projects.service';\r\nexport { listProjectsAction } from './modules/projects/actions/list-projects.action';\r\nexport { findProjectAction } from './modules/projects/actions/find-project.action';\r\nexport { createProjectAction } from './modules/projects/actions/create-project.action';\r\nexport { updateProjectAction } from './modules/projects/actions/update-project.action';\r\nexport { deleteProjectAction } from './modules/projects/actions/delete-project.action';\r\n\r\n// Project Users Services & Actions (server-only)\r\nexport { projectUsersService } from './modules/projects/services/project-users.service';\r\nexport { listProjectUsersAction } from './modules/projects/actions/list-project-users.action';\r\nexport { listAvailableUsersAction } from './modules/projects/actions/list-available-users.action';\r\nexport { addProjectUserAction } from './modules/projects/actions/add-project-user.action';\r\nexport { removeProjectUserAction } from './modules/projects/actions/remove-project-user.action';\r\n\r\n// Account Services & Actions (server-only)\r\nexport { accountService } from './modules/accounts/services/account.service';\r\nexport { twoFactorService } from './modules/accounts/services/two-factor.service';\r\nexport {\r\n listAccountUsersAction,\r\n updateUserAction,\r\n updateAccountAction,\r\n updateAccountUserByIdAction,\r\n deleteAccountUserAction,\r\n deleteAccountAction,\r\n createAccountUserAction,\r\n changePasswordAction,\r\n requestEmailChangeAction,\r\n confirmEmailChangeAction,\r\n requestPhoneChangeAction,\r\n confirmPhoneChangeAction,\r\n generateTwoFactorAction,\r\n confirmTwoFactorAction,\r\n disableTwoFactorAction,\r\n} from './modules/accounts/actions/account-management.action';\r\n\r\n// Server Utils\r\nexport { getClientInfoFromRequest } from './infra/utils/client-info';\r\nexport { getUserContext } from './modules/auth/utils/get-user-context';\r\nexport { buildWlOverride, buildWlOverrideFromJwt } from './modules/auth/utils/build-wl-override';\r\nexport { safeServerAction } from './utils/safeServerAction';\r\n\r\n// Image Processing (server-side)\r\nexport { processImageAction } from './modules/images/actions/process-image.action';\r\nexport { processImage } from './modules/images/services/image-processing.service';\r\nexport type {\r\n ProcessImageInput,\r\n ProcessImageOutput,\r\n ProcessImageActionInput,\r\n ProcessImageActionOutput,\r\n} from './modules/images/types/image.type';\r\n"],"mappings":"AAAA,OAAO;AAGP,SAAS,WAAW,KAAK,iBAAiB;AAG1C,SAAS,mBAAmB;AAC5B,SAAS,yBAAyB;AAClC,SAAS,kCAAkC;AAC3C,SAAS,kCAAkC;AAC3C,SAAS,oCAAoC;AAC7C,SAAS,+BAA+B;AACxC,SAAS,8BAA8B;AACvC,SAAS,4BAA4B;AACrC,SAAS,oBAAoB;AAC7B,SAAS,oBAAoB;AAC7B,SAAS,wBAAwB;AAGjC,SAAS,sBAAsB;AAC/B,SAAS,6BAA6B;AACtC,SAAS,oBAAoB;AAC7B,SAAS,0BAA0B;AACnC,SAAS,6BAA6B;AACtC,SAAS,+BAA+B;AACxC,SAAS,0BAA0B;AACnC,SAAS,uBAAuB;AAChC,SAAS,mCAAmC;AAC5C,SAAS,oCAAoC;AAC7C,SAAS,uBAAuB;AAChC,SAAS,wBAAwB;AACjC,SAAS,+BAA+B;AACxC,SAAS,8BAA8B;AACvC,SAAS,2BAA2B;AACpC,SAAS,wBAAwB;AAGjC,SAAS,uBAAuB;AAChC,SAAS,0BAA0B;AACnC,SAAS,yBAAyB;AAClC,SAAS,2BAA2B;AACpC,SAAS,2BAA2B;AACpC,SAAS,2BAA2B;AAGpC,SAAS,2BAA2B;AACpC,SAAS,8BAA8B;AACvC,SAAS,gCAAgC;AACzC,SAAS,4BAA4B;AACrC,SAAS,+BAA+B;AAGxC,SAAS,sBAAsB;AAC/B,SAAS,wBAAwB;AACjC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP,SAAS,gCAAgC;AACzC,SAAS,sBAAsB;AAC/B,SAAS,iBAAiB,8BAA8B;AACxD,SAAS,wBAAwB;
|
|
1
|
+
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["import 'server-only';\r\n\r\n// API Client\r\nexport { ApiClient, api, apiClient } from './infra/api/client';\r\n\r\n// Services\r\nexport { authService } from './modules/auth/services/auth.service';\r\nexport { whitelabelService } from './modules/whitelabel/services/whitelabel.service';\r\nexport { revalidateWhitelabelAction } from './modules/whitelabel/actions/revalidate-whitelabel.action';\r\nexport { assertManagementPermission } from './modules/auth/utils/assert-management-permission';\r\nexport { assertManagementSubscription } from './modules/auth/utils/assert-management-subscription';\r\nexport { assertSubscriptionAddon } from './modules/auth/utils/assert-subscription-addon';\r\nexport { assertPaidSubscription } from './modules/auth/utils/assert-paid-subscription';\r\nexport { subscriptionsService } from './modules/subscriptions/services/subscriptions.service';\r\nexport { plansService } from './modules/plans/services/plans.service';\r\nexport { cardsService } from './modules/cards/services/cards.service';\r\nexport { iaCreditsService } from './modules/ia-credits/services/ia-credits.service';\r\n\r\n// Actions\r\nexport { findWhitelabel } from './modules/whitelabel/actions/find-whitelabel.action';\r\nexport { validateSessionAction } from './modules/auth/actions/validate-session.action';\r\nexport { findUserById } from './modules/users/action/find-user-by-id.action';\r\nexport { findCurrentAccount } from './modules/accounts/actions/find-current-account.action';\r\nexport { getAccountTokenAction } from './modules/accounts/actions/get-account-token.action';\r\nexport { listSubscriptionsAction } from './modules/subscriptions/actions/list-subscriptions.action';\r\nexport { findPlanByIdAction } from './modules/plans/actions/find-plan-by-id.action';\r\nexport { listPlansAction } from './modules/plans/actions/list-plans.action';\r\nexport { calculateSubscriptionAction } from './modules/subscriptions/actions/calculate-subscription.action';\r\nexport { updateSubscriptionPlanAction } from './modules/subscriptions/actions/update-subscription-plan.action';\r\nexport { listCardsAction } from './modules/cards/actions/list-cards.action';\r\nexport { createCardAction } from './modules/cards/actions/create-card.action';\r\nexport { resolvePlanExtrasPrices } from './modules/subscriptions/utils/resolve-plan-extras-prices';\r\nexport { hasSubscriptionExpired } from './modules/subscriptions/utils/has-subscription-expired';\r\nexport { listIaCreditsAction } from './modules/ia-credits/actions/list-ia-credits.action';\r\nexport { countPagesAction } from './modules/pages/actions/count-pages.action';\r\n\r\n// Project Services & Actions (server-only)\r\nexport { projectsService } from './modules/projects/services/projects.service';\r\nexport { listProjectsAction } from './modules/projects/actions/list-projects.action';\r\nexport { findProjectAction } from './modules/projects/actions/find-project.action';\r\nexport { createProjectAction } from './modules/projects/actions/create-project.action';\r\nexport { updateProjectAction } from './modules/projects/actions/update-project.action';\r\nexport { deleteProjectAction } from './modules/projects/actions/delete-project.action';\r\n\r\n// Project Users Services & Actions (server-only)\r\nexport { projectUsersService } from './modules/projects/services/project-users.service';\r\nexport { listProjectUsersAction } from './modules/projects/actions/list-project-users.action';\r\nexport { listAvailableUsersAction } from './modules/projects/actions/list-available-users.action';\r\nexport { addProjectUserAction } from './modules/projects/actions/add-project-user.action';\r\nexport { removeProjectUserAction } from './modules/projects/actions/remove-project-user.action';\r\n\r\n// Account Services & Actions (server-only)\r\nexport { accountService } from './modules/accounts/services/account.service';\r\nexport { twoFactorService } from './modules/accounts/services/two-factor.service';\r\nexport {\r\n listAccountUsersAction,\r\n updateUserAction,\r\n updateAccountAction,\r\n updateAccountUserByIdAction,\r\n deleteAccountUserAction,\r\n deleteAccountAction,\r\n createAccountUserAction,\r\n changePasswordAction,\r\n requestEmailChangeAction,\r\n confirmEmailChangeAction,\r\n requestPhoneChangeAction,\r\n confirmPhoneChangeAction,\r\n generateTwoFactorAction,\r\n confirmTwoFactorAction,\r\n disableTwoFactorAction,\r\n} from './modules/accounts/actions/account-management.action';\r\n\r\n// Server Utils\r\nexport { getClientInfoFromRequest } from './infra/utils/client-info';\r\nexport { getUserContext } from './modules/auth/utils/get-user-context';\r\nexport { requireValidSession } from './modules/auth/utils/require-valid-session';\r\nexport { buildWlOverride, buildWlOverrideFromJwt } from './modules/auth/utils/build-wl-override';\r\nexport { safeServerAction } from './utils/safeServerAction';\r\nexport { safeMutationAction } from './utils/safeMutationAction';\r\n\r\n// Image Processing (server-side)\r\nexport { processImageAction } from './modules/images/actions/process-image.action';\r\nexport { processImage } from './modules/images/services/image-processing.service';\r\nexport type {\r\n ProcessImageInput,\r\n ProcessImageOutput,\r\n ProcessImageActionInput,\r\n ProcessImageActionOutput,\r\n} from './modules/images/types/image.type';\r\n"],"mappings":"AAAA,OAAO;AAGP,SAAS,WAAW,KAAK,iBAAiB;AAG1C,SAAS,mBAAmB;AAC5B,SAAS,yBAAyB;AAClC,SAAS,kCAAkC;AAC3C,SAAS,kCAAkC;AAC3C,SAAS,oCAAoC;AAC7C,SAAS,+BAA+B;AACxC,SAAS,8BAA8B;AACvC,SAAS,4BAA4B;AACrC,SAAS,oBAAoB;AAC7B,SAAS,oBAAoB;AAC7B,SAAS,wBAAwB;AAGjC,SAAS,sBAAsB;AAC/B,SAAS,6BAA6B;AACtC,SAAS,oBAAoB;AAC7B,SAAS,0BAA0B;AACnC,SAAS,6BAA6B;AACtC,SAAS,+BAA+B;AACxC,SAAS,0BAA0B;AACnC,SAAS,uBAAuB;AAChC,SAAS,mCAAmC;AAC5C,SAAS,oCAAoC;AAC7C,SAAS,uBAAuB;AAChC,SAAS,wBAAwB;AACjC,SAAS,+BAA+B;AACxC,SAAS,8BAA8B;AACvC,SAAS,2BAA2B;AACpC,SAAS,wBAAwB;AAGjC,SAAS,uBAAuB;AAChC,SAAS,0BAA0B;AACnC,SAAS,yBAAyB;AAClC,SAAS,2BAA2B;AACpC,SAAS,2BAA2B;AACpC,SAAS,2BAA2B;AAGpC,SAAS,2BAA2B;AACpC,SAAS,8BAA8B;AACvC,SAAS,gCAAgC;AACzC,SAAS,4BAA4B;AACrC,SAAS,+BAA+B;AAGxC,SAAS,sBAAsB;AAC/B,SAAS,wBAAwB;AACjC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP,SAAS,gCAAgC;AACzC,SAAS,sBAAsB;AAC/B,SAAS,2BAA2B;AACpC,SAAS,iBAAiB,8BAA8B;AACxD,SAAS,wBAAwB;AACjC,SAAS,0BAA0B;AAGnC,SAAS,0BAA0B;AACnC,SAAS,oBAAoB;","names":[]}
|
|
@@ -4,12 +4,33 @@ const useAccountModals = create((set) => ({
|
|
|
4
4
|
activeModal: null,
|
|
5
5
|
config: {},
|
|
6
6
|
initialSection: void 0,
|
|
7
|
+
deleteAccountPayload: null,
|
|
8
|
+
deleteAccountError: null,
|
|
7
9
|
updateConfig: (config) => set({ config }),
|
|
8
|
-
openConfigurations: (initialSection) => set({
|
|
9
|
-
|
|
10
|
+
openConfigurations: (initialSection) => set({
|
|
11
|
+
activeModal: "configurations",
|
|
12
|
+
initialSection,
|
|
13
|
+
deleteAccountPayload: null,
|
|
14
|
+
deleteAccountError: null
|
|
15
|
+
}),
|
|
16
|
+
openDeleteAccount: (error) => set({
|
|
17
|
+
activeModal: "deleteAccount",
|
|
18
|
+
deleteAccountPayload: null,
|
|
19
|
+
deleteAccountError: error ?? null
|
|
20
|
+
}),
|
|
10
21
|
openIsntPossibleDelete: () => set({ activeModal: "isntPossibleDelete" }),
|
|
11
|
-
openConfirmDelete: () => set({
|
|
12
|
-
|
|
22
|
+
openConfirmDelete: (payload) => set({
|
|
23
|
+
activeModal: "confirmDelete",
|
|
24
|
+
deleteAccountPayload: payload,
|
|
25
|
+
deleteAccountError: null
|
|
26
|
+
}),
|
|
27
|
+
clearDeleteAccountError: () => set({ deleteAccountError: null }),
|
|
28
|
+
close: () => set({
|
|
29
|
+
activeModal: null,
|
|
30
|
+
initialSection: void 0,
|
|
31
|
+
deleteAccountPayload: null,
|
|
32
|
+
deleteAccountError: null
|
|
33
|
+
})
|
|
13
34
|
}));
|
|
14
35
|
export {
|
|
15
36
|
useAccountModals
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/store/useAccountModals.ts"],"sourcesContent":["'use client';\n\nimport { create } from 'zustand';\nimport type { AccountSectionType } from '../enums/AccountSectionType';\n\ntype AccountModalType =\n | 'configurations'\n | 'deleteAccount'\n | 'isntPossibleDelete'\n | 'confirmDelete';\n\nexport interface AccountModalsConfig {\n onGoToSubscription?: () => void;\n}\n\ninterface AccountModalsState {\n activeModal: AccountModalType | null;\n config: AccountModalsConfig;\n initialSection?: AccountSectionType;\n\n /** Called by <AccountModals> to keep app-level config in sync */\n updateConfig: (config: AccountModalsConfig) => void;\n\n openConfigurations: (initialSection?: AccountSectionType) => void;\n openDeleteAccount: () => void;\n openIsntPossibleDelete: () => void;\n openConfirmDelete: () => void;\n close: () => void;\n}\n\nexport const useAccountModals = create<AccountModalsState>((set) => ({\n activeModal: null,\n config: {},\n initialSection: undefined,\n\n updateConfig: (config) => set({ config }),\n\n openConfigurations: (initialSection) =>\n set({
|
|
1
|
+
{"version":3,"sources":["../../src/store/useAccountModals.ts"],"sourcesContent":["'use client';\n\nimport { create } from 'zustand';\nimport type { AccountSectionType } from '../enums/AccountSectionType';\n\ntype AccountModalType =\n | 'configurations'\n | 'deleteAccount'\n | 'isntPossibleDelete'\n | 'confirmDelete';\n\nexport interface AccountModalsConfig {\n onGoToSubscription?: () => void;\n}\n\ninterface DeleteAccountPayload {\n password: string;\n}\n\ninterface AccountModalsState {\n activeModal: AccountModalType | null;\n config: AccountModalsConfig;\n initialSection?: AccountSectionType;\n\n /** Payload coletado no DeleteAccountModal, consumido pelo ConfirmDeleteAccountModal. */\n deleteAccountPayload: DeleteAccountPayload | null;\n /** Mensagem de erro do backend quando o delete falha (ex.: senha inválida).\n * Mostrada no DeleteAccountModal quando o usuário é mandado de volta. */\n deleteAccountError: string | null;\n\n /** Called by <AccountModals> to keep app-level config in sync */\n updateConfig: (config: AccountModalsConfig) => void;\n\n openConfigurations: (initialSection?: AccountSectionType) => void;\n openDeleteAccount: (error?: string) => void;\n openIsntPossibleDelete: () => void;\n openConfirmDelete: (payload: DeleteAccountPayload) => void;\n clearDeleteAccountError: () => void;\n close: () => void;\n}\n\nexport const useAccountModals = create<AccountModalsState>((set) => ({\n activeModal: null,\n config: {},\n initialSection: undefined,\n deleteAccountPayload: null,\n deleteAccountError: null,\n\n updateConfig: (config) => set({ config }),\n\n openConfigurations: (initialSection) =>\n set({\n activeModal: 'configurations',\n initialSection,\n deleteAccountPayload: null,\n deleteAccountError: null,\n }),\n\n openDeleteAccount: (error) =>\n set({\n activeModal: 'deleteAccount',\n deleteAccountPayload: null,\n deleteAccountError: error ?? null,\n }),\n\n openIsntPossibleDelete: () =>\n set({ activeModal: 'isntPossibleDelete' }),\n\n openConfirmDelete: (payload) =>\n set({\n activeModal: 'confirmDelete',\n deleteAccountPayload: payload,\n deleteAccountError: null,\n }),\n\n clearDeleteAccountError: () => set({ deleteAccountError: null }),\n\n close: () =>\n set({\n activeModal: null,\n initialSection: undefined,\n deleteAccountPayload: null,\n deleteAccountError: null,\n }),\n}));\n"],"mappings":";AAEA,SAAS,cAAc;AAuChB,MAAM,mBAAmB,OAA2B,CAAC,SAAS;AAAA,EACnE,aAAa;AAAA,EACb,QAAQ,CAAC;AAAA,EACT,gBAAgB;AAAA,EAChB,sBAAsB;AAAA,EACtB,oBAAoB;AAAA,EAEpB,cAAc,CAAC,WAAW,IAAI,EAAE,OAAO,CAAC;AAAA,EAExC,oBAAoB,CAAC,mBACnB,IAAI;AAAA,IACF,aAAa;AAAA,IACb;AAAA,IACA,sBAAsB;AAAA,IACtB,oBAAoB;AAAA,EACtB,CAAC;AAAA,EAEH,mBAAmB,CAAC,UAClB,IAAI;AAAA,IACF,aAAa;AAAA,IACb,sBAAsB;AAAA,IACtB,oBAAoB,SAAS;AAAA,EAC/B,CAAC;AAAA,EAEH,wBAAwB,MACtB,IAAI,EAAE,aAAa,qBAAqB,CAAC;AAAA,EAE3C,mBAAmB,CAAC,YAClB,IAAI;AAAA,IACF,aAAa;AAAA,IACb,sBAAsB;AAAA,IACtB,oBAAoB;AAAA,EACtB,CAAC;AAAA,EAEH,yBAAyB,MAAM,IAAI,EAAE,oBAAoB,KAAK,CAAC;AAAA,EAE/D,OAAO,MACL,IAAI;AAAA,IACF,aAAa;AAAA,IACb,gBAAgB;AAAA,IAChB,sBAAsB;AAAA,IACtB,oBAAoB;AAAA,EACtB,CAAC;AACL,EAAE;","names":[]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import "server-only";
|
|
2
|
+
import { requireValidSession } from "../modules/auth/utils/require-valid-session";
|
|
3
|
+
import { safeServerAction } from "./safeServerAction";
|
|
4
|
+
async function safeMutationAction(fn) {
|
|
5
|
+
return safeServerAction(async () => {
|
|
6
|
+
await requireValidSession();
|
|
7
|
+
return fn();
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
safeMutationAction
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=safeMutationAction.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/safeMutationAction.ts"],"sourcesContent":["import 'server-only';\n\nimport type { ActionResult } from '../infra/api/types';\nimport { requireValidSession } from '../modules/auth/utils/require-valid-session';\nimport { safeServerAction } from './safeServerAction';\n\n/**\n * Wrapper para server actions que mutam estado (delete/update/create/publish/\n * billing/etc.). Faz validação de sessão contra o backend (`POST /auth/keep`)\n * antes de executar a ação e roteia erros via `safeServerAction`.\n *\n * A validação é deduplicada por request — múltiplas actions sensíveis que\n * rodem dentro de uma mesma request pagam 1 round-trip ao backend, não N.\n *\n * Motivação (resumo): o backend confia no par `(whitelabel-token, id_account\n * no path)` nos endpoints de CRUD; o Next.js deriva `id_account` de\n * `atob(cookie)` sem verificar assinatura. Chamar `requireValidSession`\n * aqui garante que o cookie corresponde a uma sessão real no banco antes\n * de qualquer mutação.\n *\n * Para reads não-sensíveis, continue usando `safeServerAction` direto.\n */\nexport async function safeMutationAction<T>(\n fn: () => Promise<T>\n): Promise<ActionResult<T>> {\n return safeServerAction(async () => {\n await requireValidSession();\n return fn();\n });\n}\n"],"mappings":"AAAA,OAAO;AAGP,SAAS,2BAA2B;AACpC,SAAS,wBAAwB;AAkBjC,eAAsB,mBACpB,IAC0B;AAC1B,SAAO,iBAAiB,YAAY;AAClC,UAAM,oBAAoB;AAC1B,WAAO,GAAG;AAAA,EACZ,CAAC;AACH;","names":[]}
|
package/package.json
CHANGED
|
@@ -36,6 +36,7 @@ export default function ConfigurationsMyAccountModal() {
|
|
|
36
36
|
const isBlockingSubscription =
|
|
37
37
|
isPaidSubscriptionType &&
|
|
38
38
|
subscription.active === true &&
|
|
39
|
+
!subscription.date_cancellation &&
|
|
39
40
|
!hasSubscriptionExpired(subscription.date_due);
|
|
40
41
|
|
|
41
42
|
const { user } = useAuth();
|
|
@@ -15,7 +15,7 @@ import { useAuth } from '../../providers/auth.provider';
|
|
|
15
15
|
import { UserProfile } from '../../modules/users/schema';
|
|
16
16
|
|
|
17
17
|
export default function ConfirmDeleteAccountModal() {
|
|
18
|
-
const { activeModal, close } = useAccountModals();
|
|
18
|
+
const { activeModal, deleteAccountPayload, openDeleteAccount, close } = useAccountModals();
|
|
19
19
|
const open = activeModal === 'confirmDelete';
|
|
20
20
|
|
|
21
21
|
const { data: pagesCount = 0 } = useCountPages();
|
|
@@ -30,7 +30,13 @@ export default function ConfirmDeleteAccountModal() {
|
|
|
30
30
|
const handleConfirm = async () => {
|
|
31
31
|
try {
|
|
32
32
|
if (isOwner) {
|
|
33
|
-
|
|
33
|
+
if (!deleteAccountPayload) {
|
|
34
|
+
// Fluxo quebrado (usuário pulou o primeiro modal ou refresh) — manda
|
|
35
|
+
// de volta pro modal inicial pra re-coletar a senha.
|
|
36
|
+
openDeleteAccount('Sessão expirada. Preencha os campos novamente.');
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
await deleteAccount.mutateAsync({ password: deleteAccountPayload.password });
|
|
34
40
|
} else {
|
|
35
41
|
await deleteAccountUser.mutateAsync(user!.id);
|
|
36
42
|
}
|
|
@@ -40,12 +46,15 @@ export default function ConfirmDeleteAccountModal() {
|
|
|
40
46
|
));
|
|
41
47
|
await logout();
|
|
42
48
|
} catch (error) {
|
|
49
|
+
const message = error instanceof Error ? error.message : 'Erro ao excluir. Tente novamente.';
|
|
50
|
+
if (isOwner) {
|
|
51
|
+
// Falha no delete do owner (ex.: senha inválida) — volta pro primeiro
|
|
52
|
+
// modal com a mensagem do backend pra o usuário corrigir e tentar de novo.
|
|
53
|
+
openDeleteAccount(message);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
43
56
|
toast.custom((t) => (
|
|
44
|
-
<Toast
|
|
45
|
-
variant="error"
|
|
46
|
-
message={error instanceof Error ? error.message : 'Erro ao excluir. Tente novamente.'}
|
|
47
|
-
toastId={t}
|
|
48
|
-
/>
|
|
57
|
+
<Toast variant="error" message={message} toastId={t} />
|
|
49
58
|
));
|
|
50
59
|
}
|
|
51
60
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { useState, useCallback } from 'react';
|
|
3
|
+
import { useState, useCallback, useEffect } from 'react';
|
|
4
4
|
import { IconLock, IconAlertTriangle } from '@tabler/icons-react';
|
|
5
5
|
import { toast } from 'sonner';
|
|
6
6
|
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../ui/overlay/Dialog';
|
|
@@ -23,7 +23,13 @@ const REASON_OPTIONS = [
|
|
|
23
23
|
];
|
|
24
24
|
|
|
25
25
|
export default function DeleteAccountModal() {
|
|
26
|
-
const {
|
|
26
|
+
const {
|
|
27
|
+
activeModal,
|
|
28
|
+
deleteAccountError,
|
|
29
|
+
openConfigurations,
|
|
30
|
+
openConfirmDelete,
|
|
31
|
+
clearDeleteAccountError,
|
|
32
|
+
} = useAccountModals();
|
|
27
33
|
const open = activeModal === 'deleteAccount';
|
|
28
34
|
|
|
29
35
|
const [reason, setReason] = useState('');
|
|
@@ -39,6 +45,14 @@ export default function DeleteAccountModal() {
|
|
|
39
45
|
setPassword('');
|
|
40
46
|
}, []);
|
|
41
47
|
|
|
48
|
+
// Quando o modal deixa de estar aberto, limpa o erro residual do store
|
|
49
|
+
// pra não aparecer numa próxima abertura vinda de fluxo limpo.
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
if (!open) {
|
|
52
|
+
clearDeleteAccountError();
|
|
53
|
+
}
|
|
54
|
+
}, [open, clearDeleteAccountError]);
|
|
55
|
+
|
|
42
56
|
const handleClose = () => {
|
|
43
57
|
resetForm();
|
|
44
58
|
openConfigurations(AccountSectionType.SECURITY);
|
|
@@ -52,8 +66,9 @@ export default function DeleteAccountModal() {
|
|
|
52
66
|
));
|
|
53
67
|
return;
|
|
54
68
|
}
|
|
69
|
+
openConfirmDelete({ password });
|
|
70
|
+
// Campos locais podem ser limpos — o payload já está no store.
|
|
55
71
|
resetForm();
|
|
56
|
-
openConfirmDelete();
|
|
57
72
|
};
|
|
58
73
|
|
|
59
74
|
return (
|
|
@@ -104,10 +119,15 @@ export default function DeleteAccountModal() {
|
|
|
104
119
|
placeholder="Informe sua senha"
|
|
105
120
|
leftIcon={IconLock}
|
|
106
121
|
value={password}
|
|
107
|
-
onChange={(e) =>
|
|
122
|
+
onChange={(e) => {
|
|
123
|
+
setPassword(e.target.value);
|
|
124
|
+
if (deleteAccountError) clearDeleteAccountError();
|
|
125
|
+
}}
|
|
108
126
|
classnameContainer="h-10!"
|
|
109
127
|
showPassword={showPassword}
|
|
110
128
|
onTogglePassword={togglePassword}
|
|
129
|
+
error={!!deleteAccountError}
|
|
130
|
+
errorMessage={deleteAccountError ?? undefined}
|
|
111
131
|
/>
|
|
112
132
|
</div>
|
|
113
133
|
|
|
@@ -10,18 +10,12 @@ import { ACCEPTED_IMAGE_FORMATS_STRING } from '../../../modules/images/constants
|
|
|
10
10
|
import { Button } from '../../ui/buttons/Button';
|
|
11
11
|
import { Separator } from '../../ui/data-display/Separator';
|
|
12
12
|
import { Toast } from '../../ui/feedback/Toast';
|
|
13
|
-
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '../../ui/overlay/Dialog';
|
|
14
13
|
import { FormField } from '../../ui/form/FormField';
|
|
15
14
|
import { SelectField } from '../../ui/form/SelectField';
|
|
16
15
|
import PhoneInput from '../../ui/form/PhoneInput';
|
|
17
16
|
import { useAuth } from '../../../providers/auth.provider';
|
|
18
|
-
import { UserProfile } from '../../../modules/users/schema';
|
|
19
17
|
import { myProfileSchema, type MyProfileFormData } from '../../../utils/validators/account';
|
|
20
|
-
import {
|
|
21
|
-
useUpdateAccountUser,
|
|
22
|
-
useDeleteAccount,
|
|
23
|
-
useDeleteAccountUser,
|
|
24
|
-
} from '../../../modules/accounts/hooks/useAccountManagement';
|
|
18
|
+
import { useUpdateAccountUser } from '../../../modules/accounts/hooks/useAccountManagement';
|
|
25
19
|
import { GENDER_OPTIONS } from '../constants';
|
|
26
20
|
import { ChangePhoneModal } from './ChangePhoneModal';
|
|
27
21
|
import { ChangeEmailModal } from './ChangeEmailModal';
|
|
@@ -32,19 +26,13 @@ interface MyProfileSectionProps {
|
|
|
32
26
|
}
|
|
33
27
|
|
|
34
28
|
export function MyProfileSection({ onClose, storageUrl }: MyProfileSectionProps) {
|
|
35
|
-
const { user
|
|
29
|
+
const { user } = useAuth();
|
|
36
30
|
const updateAccountUser = useUpdateAccountUser();
|
|
37
|
-
const deleteAccount = useDeleteAccount();
|
|
38
|
-
const deleteAccountUser = useDeleteAccountUser();
|
|
39
31
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
|
40
32
|
const [selectedPhoto, setSelectedPhoto] = useState<File | null>(null);
|
|
41
33
|
const [photoRemoved, setPhotoRemoved] = useState(false);
|
|
42
34
|
const [changePhoneOpen, setChangePhoneOpen] = useState(false);
|
|
43
35
|
const [changeEmailOpen, setChangeEmailOpen] = useState(false);
|
|
44
|
-
const [deleteConfirmOpen, setDeleteConfirmOpen] = useState(false);
|
|
45
|
-
|
|
46
|
-
const isOwner = user?.profile === UserProfile.owner;
|
|
47
|
-
const isDeleting = deleteAccount.isPending || deleteAccountUser.isPending;
|
|
48
36
|
|
|
49
37
|
const form = useForm<MyProfileFormData>({
|
|
50
38
|
resolver: zodResolver(myProfileSchema),
|
|
@@ -85,26 +73,6 @@ export function MyProfileSection({ onClose, storageUrl }: MyProfileSectionProps)
|
|
|
85
73
|
setPhotoRemoved(true);
|
|
86
74
|
};
|
|
87
75
|
|
|
88
|
-
const handleDelete = async () => {
|
|
89
|
-
try {
|
|
90
|
-
if (isOwner) {
|
|
91
|
-
await deleteAccount.mutateAsync();
|
|
92
|
-
} else {
|
|
93
|
-
await deleteAccountUser.mutateAsync(user!.id);
|
|
94
|
-
}
|
|
95
|
-
await logout();
|
|
96
|
-
} catch (error) {
|
|
97
|
-
toast.custom((t) => (
|
|
98
|
-
<Toast
|
|
99
|
-
variant="error"
|
|
100
|
-
message={error instanceof Error ? error.message : 'Erro ao excluir. Tente novamente.'}
|
|
101
|
-
toastId={t}
|
|
102
|
-
/>
|
|
103
|
-
));
|
|
104
|
-
setDeleteConfirmOpen(false);
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
|
|
108
76
|
const onSubmit = async (data: MyProfileFormData) => {
|
|
109
77
|
try {
|
|
110
78
|
await updateAccountUser.mutateAsync({
|
|
@@ -289,40 +257,6 @@ export function MyProfileSection({ onClose, storageUrl }: MyProfileSectionProps)
|
|
|
289
257
|
|
|
290
258
|
<ChangePhoneModal open={changePhoneOpen} onClose={() => setChangePhoneOpen(false)} />
|
|
291
259
|
<ChangeEmailModal open={changeEmailOpen} onClose={() => setChangeEmailOpen(false)} />
|
|
292
|
-
|
|
293
|
-
<Dialog open={deleteConfirmOpen} onOpenChange={setDeleteConfirmOpen}>
|
|
294
|
-
<DialogContent className="max-w-sm! gap-5">
|
|
295
|
-
<DialogHeader>
|
|
296
|
-
<DialogTitle className="paragraph-large-semibold text-gray-950">
|
|
297
|
-
{isOwner ? 'Excluir conta' : 'Excluir usuário'}
|
|
298
|
-
</DialogTitle>
|
|
299
|
-
</DialogHeader>
|
|
300
|
-
<p className="paragraph-small-regular text-gray-600">
|
|
301
|
-
{isOwner
|
|
302
|
-
? 'Tem certeza que deseja excluir sua conta? Todos os dados serão apagados permanentemente e essa ação não pode ser desfeita.'
|
|
303
|
-
: 'Tem certeza que deseja excluir seu usuário? Você perderá acesso a esta conta permanentemente.'}
|
|
304
|
-
</p>
|
|
305
|
-
<div className="flex items-center gap-3 justify-end">
|
|
306
|
-
<Button
|
|
307
|
-
type="button"
|
|
308
|
-
variant="secondary"
|
|
309
|
-
className="h-10!"
|
|
310
|
-
disabled={isDeleting}
|
|
311
|
-
onClick={() => setDeleteConfirmOpen(false)}
|
|
312
|
-
>
|
|
313
|
-
Cancelar
|
|
314
|
-
</Button>
|
|
315
|
-
<Button
|
|
316
|
-
type="button"
|
|
317
|
-
className="h-10! bg-red-600 hover:bg-red-700 text-white border-0!"
|
|
318
|
-
disabled={isDeleting}
|
|
319
|
-
onClick={handleDelete}
|
|
320
|
-
>
|
|
321
|
-
{isDeleting ? 'Excluindo...' : 'Confirmar exclusão'}
|
|
322
|
-
</Button>
|
|
323
|
-
</div>
|
|
324
|
-
</DialogContent>
|
|
325
|
-
</Dialog>
|
|
326
260
|
</>
|
|
327
261
|
);
|
|
328
262
|
}
|
|
@@ -20,16 +20,19 @@ export function CancelledSubscriptionBanner({ onReactivate }: CancelledSubscript
|
|
|
20
20
|
}, []);
|
|
21
21
|
|
|
22
22
|
const dismiss = useCallback(() => setVisible(false), []);
|
|
23
|
-
|
|
23
|
+
|
|
24
|
+
if (!visible) return null;
|
|
25
|
+
if (!subscription?.date_due) return null;
|
|
26
|
+
|
|
27
|
+
const dueDate = new Date(subscription.date_due);
|
|
24
28
|
const today = new Date();
|
|
25
29
|
const isPastDue = today >= dueDate;
|
|
26
30
|
const formattedDate = formatShortDate(dueDate);
|
|
27
31
|
|
|
28
|
-
const isTrial = subscription
|
|
32
|
+
const isTrial = subscription.type === 'trial';
|
|
29
33
|
|
|
30
|
-
if (!visible) return null;
|
|
31
34
|
if (isTrial && !isPastDue) return null;
|
|
32
|
-
if (!isTrial && (!subscription
|
|
35
|
+
if (!isTrial && (!subscription.date_cancellation || isPastDue)) return null;
|
|
33
36
|
|
|
34
37
|
return (
|
|
35
38
|
<div className="fixed top-[80px] md:top-0 left-0 right-0 z-[60] flex justify-center pointer-events-none px-4 lg:px-0">
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
|
|
3
3
|
import { safeServerAction } from '../../../utils/safeServerAction';
|
|
4
|
+
import { safeMutationAction } from '../../../utils/safeMutationAction';
|
|
4
5
|
import { accountService } from '../services/account.service';
|
|
5
6
|
import type {
|
|
6
7
|
AccountUsersPaginationParams,
|
|
7
8
|
ChangePasswordRequest,
|
|
8
9
|
CreateAccountUserRequest,
|
|
10
|
+
DeleteAccountRequest,
|
|
9
11
|
UpdateAccountRequest,
|
|
10
12
|
UpdateAccountUserRequest,
|
|
11
13
|
} from '../types';
|
|
@@ -22,18 +24,18 @@ export async function listAccountUsersAction(params?: AccountUsersPaginationPara
|
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
export async function updateUserAction(user: UpdateAccountUserRequest) {
|
|
25
|
-
return
|
|
27
|
+
return safeMutationAction(() => accountService.updateAccountUser(user));
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
export async function updateAccountUserByIdAction(
|
|
29
31
|
userId: number,
|
|
30
32
|
user: UpdateAccountUserRequest
|
|
31
33
|
) {
|
|
32
|
-
return
|
|
34
|
+
return safeMutationAction(() => accountService.updateAccountUserById(userId, user));
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
export async function updateAccountAction(data: UpdateAccountRequest) {
|
|
36
|
-
return
|
|
38
|
+
return safeMutationAction(async () => {
|
|
37
39
|
if (data.name !== undefined) {
|
|
38
40
|
const userResult = await findUserById();
|
|
39
41
|
if (!userResult.success || userResult.data?.profile !== UserProfile.owner) {
|
|
@@ -50,39 +52,39 @@ export async function updateAccountAction(data: UpdateAccountRequest) {
|
|
|
50
52
|
}
|
|
51
53
|
|
|
52
54
|
export async function deleteAccountUserAction(userId: number) {
|
|
53
|
-
return
|
|
55
|
+
return safeMutationAction(() => accountService.deleteAccountUser(userId));
|
|
54
56
|
}
|
|
55
57
|
|
|
56
|
-
export async function deleteAccountAction() {
|
|
57
|
-
return
|
|
58
|
+
export async function deleteAccountAction(data: DeleteAccountRequest) {
|
|
59
|
+
return safeMutationAction(() => accountService.deleteAccount(data));
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
export async function createAccountUserAction(user: CreateAccountUserRequest) {
|
|
61
|
-
return
|
|
63
|
+
return safeMutationAction(() => accountService.createAccountUser(user));
|
|
62
64
|
}
|
|
63
65
|
|
|
64
66
|
export async function changePasswordAction(data: ChangePasswordRequest) {
|
|
65
|
-
return
|
|
67
|
+
return safeMutationAction(() => accountService.changePassword(data));
|
|
66
68
|
}
|
|
67
69
|
|
|
68
70
|
export async function requestEmailChangeAction(newEmail: string) {
|
|
69
|
-
return
|
|
71
|
+
return safeMutationAction(() => accountService.requestContactReset('email', newEmail));
|
|
70
72
|
}
|
|
71
73
|
|
|
72
74
|
export async function confirmEmailChangeAction(token: string, newEmail: string) {
|
|
73
|
-
return
|
|
75
|
+
return safeMutationAction(() => accountService.confirmContactReset('email', token, newEmail));
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
export async function requestPhoneChangeAction(newPhone: string, ddi?: string) {
|
|
77
|
-
return
|
|
79
|
+
return safeMutationAction(() => accountService.requestContactReset('phone', newPhone, ddi));
|
|
78
80
|
}
|
|
79
81
|
|
|
80
82
|
export async function confirmPhoneChangeAction(token: string, newPhone: string, ddi?: string) {
|
|
81
|
-
return
|
|
83
|
+
return safeMutationAction(() => accountService.confirmContactReset('phone', token, newPhone, ddi));
|
|
82
84
|
}
|
|
83
85
|
|
|
84
86
|
export async function generateTwoFactorAction() {
|
|
85
|
-
return
|
|
87
|
+
return safeMutationAction(async () => {
|
|
86
88
|
const result = await twoFactorService.generate();
|
|
87
89
|
return {
|
|
88
90
|
qrcode: result.data.qrcode,
|
|
@@ -92,14 +94,14 @@ export async function generateTwoFactorAction() {
|
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
export async function confirmTwoFactorAction(code: string) {
|
|
95
|
-
return
|
|
97
|
+
return safeMutationAction(async () => {
|
|
96
98
|
await twoFactorService.confirm(code);
|
|
97
99
|
await accountService.updateAccountUser({ two_factor_authentication: true });
|
|
98
100
|
});
|
|
99
101
|
}
|
|
100
102
|
|
|
101
103
|
export async function disableTwoFactorAction(code: string) {
|
|
102
|
-
return
|
|
104
|
+
return safeMutationAction(async () => {
|
|
103
105
|
await twoFactorService.verify(code);
|
|
104
106
|
await twoFactorService.disable();
|
|
105
107
|
await accountService.updateAccountUser({ two_factor_authentication: false });
|
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
UpdateAccountRequest,
|
|
8
8
|
UpdateAccountUserRequest,
|
|
9
9
|
DeleteAccountUserResponse,
|
|
10
|
+
DeleteAccountRequest,
|
|
10
11
|
DeleteAccountResponse,
|
|
11
12
|
} from '../types';
|
|
12
13
|
import {
|
|
@@ -85,7 +86,7 @@ export function useDeleteAccountUser(
|
|
|
85
86
|
}
|
|
86
87
|
|
|
87
88
|
export function useDeleteAccount(
|
|
88
|
-
options?: UseMutationOptions<DeleteAccountResponse, Error,
|
|
89
|
+
options?: UseMutationOptions<DeleteAccountResponse, Error, DeleteAccountRequest>
|
|
89
90
|
) {
|
|
90
91
|
return useMutation({
|
|
91
92
|
mutationFn: withAction(deleteAccountAction),
|
|
@@ -15,6 +15,7 @@ import type {
|
|
|
15
15
|
ChangeUserPhotoResponse,
|
|
16
16
|
CreateAccountUserRequest,
|
|
17
17
|
CreateAccountUserResponse,
|
|
18
|
+
DeleteAccountRequest,
|
|
18
19
|
DeleteAccountResponse,
|
|
19
20
|
DeleteAccountUserResponse,
|
|
20
21
|
GetAccountDataResponse,
|
|
@@ -94,9 +95,12 @@ class AccountService {
|
|
|
94
95
|
return response;
|
|
95
96
|
}
|
|
96
97
|
|
|
97
|
-
async deleteAccount(): Promise<DeleteAccountResponse> {
|
|
98
|
+
async deleteAccount(data: DeleteAccountRequest): Promise<DeleteAccountResponse> {
|
|
98
99
|
const { id_account } = await getUserContext();
|
|
99
|
-
const response = await api.apps.delete<DeleteAccountResponse>(
|
|
100
|
+
const response = await api.apps.delete<DeleteAccountResponse>(
|
|
101
|
+
`/accounts/${id_account}`,
|
|
102
|
+
{ body: JSON.stringify(data) }
|
|
103
|
+
);
|
|
100
104
|
|
|
101
105
|
if (response.status === 0) {
|
|
102
106
|
throw new ApiError(response.message || 'Erro ao deletar conta', 'DELETE_ACCOUNT_FAILED', 400);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import 'server-only';
|
|
2
|
+
|
|
3
|
+
import { cache } from 'react';
|
|
4
|
+
|
|
5
|
+
import { ApiError } from '../../../infra/api/types';
|
|
6
|
+
import { getClientInfoFromRequest } from '../../../infra/utils/client-info';
|
|
7
|
+
import { authService } from '../services/auth.service';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Valida a sessão do usuário chamando POST /auth/keep no backend.
|
|
11
|
+
*
|
|
12
|
+
* Garante que o cookie `greatapps`:
|
|
13
|
+
* 1. Existe.
|
|
14
|
+
* 2. Corresponde a uma sessão registrada no banco (não foi forjado).
|
|
15
|
+
* 3. Ainda é considerada válida pelo backend (não foi revogada/expirada).
|
|
16
|
+
*
|
|
17
|
+
* Deduplicada por request via React.cache — múltiplas chamadas dentro do
|
|
18
|
+
* mesmo server action resultam em 1 round-trip ao backend, não N.
|
|
19
|
+
*
|
|
20
|
+
* Use em server actions sensíveis (mutações, billing, destrutivas).
|
|
21
|
+
* Prefira o wrapper `safeMutationAction` que já envelopa isto junto com
|
|
22
|
+
* o `safeServerAction` padrão.
|
|
23
|
+
*
|
|
24
|
+
* Em caso de erro de rede/backend, falha fechada (SESSION_INVALID 401).
|
|
25
|
+
*/
|
|
26
|
+
export const requireValidSession = cache(async (): Promise<void> => {
|
|
27
|
+
if (process.env.DUMMY_AUTH_TOKEN) return;
|
|
28
|
+
|
|
29
|
+
const clientInfo = await getClientInfoFromRequest();
|
|
30
|
+
const isValid = await authService.validateSession(clientInfo);
|
|
31
|
+
|
|
32
|
+
if (!isValid) {
|
|
33
|
+
throw new ApiError('Sessão inválida ou expirada', 'SESSION_INVALID', 401);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { safeMutationAction } from '../../../utils/safeMutationAction';
|
|
4
4
|
import { cardsService } from '../services/cards.service';
|
|
5
5
|
import { CreateCardRequest } from '../types';
|
|
6
6
|
|
|
7
7
|
export async function createCardAction(data: CreateCardRequest) {
|
|
8
|
-
return
|
|
8
|
+
return safeMutationAction(() => cardsService.createCard(data));
|
|
9
9
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { safeMutationAction } from '../../../utils/safeMutationAction';
|
|
4
4
|
import { cardsService } from '../services/cards.service';
|
|
5
5
|
|
|
6
6
|
export async function deleteCardAction(id: string) {
|
|
7
|
-
return
|
|
7
|
+
return safeMutationAction(() => cardsService.deleteCard(id));
|
|
8
8
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { safeMutationAction } from '../../../utils/safeMutationAction';
|
|
4
4
|
import { cardsService } from '../services/cards.service';
|
|
5
5
|
|
|
6
6
|
export async function setDefaultCardAction(cardId: string) {
|
|
7
|
-
return
|
|
7
|
+
return safeMutationAction(() => cardsService.setDefaultCard(cardId));
|
|
8
8
|
}
|