@greatapps/common 1.1.708 → 1.1.712
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/modals/BuyCreditsModal.mjs +14 -15
- package/dist/components/modals/BuyCreditsModal.mjs.map +1 -1
- package/dist/components/ui/data-display/PaymentInfoCard.mjs +1 -1
- package/dist/components/ui/data-display/PaymentInfoCard.mjs.map +1 -1
- package/dist/modules/images/utils/compress-image.mjs +4 -3
- package/dist/modules/images/utils/compress-image.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/modals/BuyCreditsModal.tsx +16 -14
- package/src/components/ui/data-display/PaymentInfoCard.tsx +2 -2
- package/src/modules/images/types/image.type.ts +1 -0
- package/src/modules/images/utils/compress-image.ts +5 -3
|
@@ -61,6 +61,13 @@ function BuyCreditsModal() {
|
|
|
61
61
|
const currentCredits = aiItem?.quantity ?? 0;
|
|
62
62
|
const subscriptionId = subscription?.id;
|
|
63
63
|
const planId = subscription?.id_plan;
|
|
64
|
+
const buildPlanExtras = useCallback(
|
|
65
|
+
(aiQuantity) => [
|
|
66
|
+
...(subscription?.items ?? []).filter((item) => item.id_addon != null && item.id_addon !== ADDON_IDS.AI && Number(item.value ?? 0) > 0).map((item) => ({ id_addon: Number(item.id_addon), quantity: item.quantity ?? 0 })),
|
|
67
|
+
{ id_addon: ADDON_IDS.AI, quantity: aiQuantity }
|
|
68
|
+
],
|
|
69
|
+
[subscription]
|
|
70
|
+
);
|
|
64
71
|
const form = useForm({
|
|
65
72
|
resolver: zodResolver(buyCreditSchema),
|
|
66
73
|
mode: "onChange",
|
|
@@ -85,9 +92,7 @@ function BuyCreditsModal() {
|
|
|
85
92
|
id_product: 1,
|
|
86
93
|
...planId != null && { id_plan: planId },
|
|
87
94
|
...subscriptionId != null && { id_subscription: subscriptionId },
|
|
88
|
-
plan_extras:
|
|
89
|
-
{ id_addon: ADDON_IDS.AI, quantity: currentCredits }
|
|
90
|
-
]
|
|
95
|
+
plan_extras: buildPlanExtras(currentCredits)
|
|
91
96
|
});
|
|
92
97
|
}, [
|
|
93
98
|
open,
|
|
@@ -97,7 +102,8 @@ function BuyCreditsModal() {
|
|
|
97
102
|
form,
|
|
98
103
|
calculate,
|
|
99
104
|
planId,
|
|
100
|
-
subscriptionId
|
|
105
|
+
subscriptionId,
|
|
106
|
+
buildPlanExtras
|
|
101
107
|
]);
|
|
102
108
|
useEffect(() => {
|
|
103
109
|
if (open && defaultCardId && !form.getValues("selectedCardId")) {
|
|
@@ -120,12 +126,10 @@ function BuyCreditsModal() {
|
|
|
120
126
|
id_product: 1,
|
|
121
127
|
...planId != null && { id_plan: planId },
|
|
122
128
|
...subscriptionId != null && { id_subscription: subscriptionId },
|
|
123
|
-
plan_extras:
|
|
124
|
-
{ id_addon: ADDON_IDS.AI, quantity: option.credits, currency: "BRL" }
|
|
125
|
-
]
|
|
129
|
+
plan_extras: buildPlanExtras(option.credits)
|
|
126
130
|
});
|
|
127
131
|
},
|
|
128
|
-
[form, subscriptionId, planId, calculate]
|
|
132
|
+
[form, subscriptionId, planId, calculate, buildPlanExtras]
|
|
129
133
|
);
|
|
130
134
|
const calculatedData = calculateData?.data ?? null;
|
|
131
135
|
const isIncreasingCredits = creditOption > currentCredits;
|
|
@@ -167,12 +171,7 @@ function BuyCreditsModal() {
|
|
|
167
171
|
await updatePlanMutation.mutateAsync({
|
|
168
172
|
subscriptionId,
|
|
169
173
|
data: {
|
|
170
|
-
plan_extras:
|
|
171
|
-
{
|
|
172
|
-
id_addon: ADDON_IDS.AI,
|
|
173
|
-
quantity: option.credits
|
|
174
|
-
}
|
|
175
|
-
]
|
|
174
|
+
plan_extras: buildPlanExtras(option.credits)
|
|
176
175
|
}
|
|
177
176
|
});
|
|
178
177
|
toast.custom((t) => /* @__PURE__ */ jsx(
|
|
@@ -186,7 +185,7 @@ function BuyCreditsModal() {
|
|
|
186
185
|
form.reset();
|
|
187
186
|
closeModal();
|
|
188
187
|
},
|
|
189
|
-
[subscriptionId, updatePlanMutation, form, closeModal]
|
|
188
|
+
[subscriptionId, updatePlanMutation, form, closeModal, buildPlanExtras]
|
|
190
189
|
);
|
|
191
190
|
const renderPriceDisplay = useCallback(() => {
|
|
192
191
|
if (isCalculatePending) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/modals/BuyCreditsModal.tsx"],"sourcesContent":["'use client';\n\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n} from '../ui/overlay/Dialog';\nimport { Button } from '../ui/buttons/Button';\nimport { Separator } from '../ui/data-display/Separator';\nimport { Toast } from '../ui/feedback/Toast';\nimport { SelectField } from '../ui/form/SelectField';\nimport { Skeleton } from '../ui/feedback/Skeleton';\nimport { PaymentInfoCard } from '../ui/data-display/PaymentInfoCard';\nimport { ADDON_IDS } from '../../modules/subscriptions/constants/addons.constants';\nimport {\n AI_CREDIT_OPTIONS,\n AI_CREDIT_VALUES,\n} from '../../modules/subscriptions/constants/addons.constants';\nimport { useBuyCreditsModal } from '../../store/useBuyCreditsModal';\nimport { useModalManager } from '../../store/useModalManager';\nimport { useCards } from '../../modules/cards/hooks/cards.hook';\nimport { useActiveSubscription } from '../../modules/subscriptions/hooks/find-active-subscription.hook';\nimport { useCalculateSubscription } from '../../modules/subscriptions/hooks/calculate-subscription.hook';\nimport { useUpdateSubscriptionPlan } from '../../modules/subscriptions/hooks/update-subscription-plan.hook';\nimport { getPriceFromCalculatedData } from '../../modules/subscriptions/utils/periodicity';\nimport { useIsDefaultWhitelabel, useExternalContracting } from '../../providers/whitelabel.provider';\nimport { IconInfoCircle, IconX, IconLoader2, IconSparkles } from '@tabler/icons-react';\nimport { useTranslations } from 'next-intl';\nimport { useCallback, useEffect, useMemo, useRef } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport z from 'zod';\nimport { toast } from 'sonner';\n\nconst buyCreditSchema = z.object({\n creditOption: z.number().refine((val) => AI_CREDIT_VALUES.has(val), {\n message: 'Selecione uma opção de créditos',\n }),\n selectedCardId: z.string().min(1, 'Selecione um cartão'),\n});\n\ntype BuyCreditFormData = z.infer<typeof buyCreditSchema>;\n\nexport default function BuyCreditsModal() {\n const translate = useTranslations();\n const { open, closeModal } = useBuyCreditsModal();\n const { openModal } = useModalManager();\n const isDefaultWl = useIsDefaultWhitelabel();\n const { isExternalContracting, redirectToExternal } = useExternalContracting();\n const { data: cardsData } = useCards();\n const { data: subscriptionData } = useActiveSubscription();\n const subscription = subscriptionData?.data?.[0] ?? null;\n const defaultCardId =\n cardsData?.data?.find((card) => card.is_default)?.id?.toString() ??\n cardsData?.data?.[0]?.id?.toString() ??\n '';\n\n const {\n mutate: calculate,\n isPending: isCalculatePending,\n data: calculateData,\n } = useCalculateSubscription();\n const updatePlanMutation = useUpdateSubscriptionPlan();\n\n const aiItem = useMemo(\n () => subscription?.items?.find((item) => item.id_addon === ADDON_IDS.AI),\n [subscription]\n );\n\n const currentCredits = aiItem?.quantity ?? 0;\n const subscriptionId = subscription?.id;\n const planId = subscription?.id_plan;\n\n const form = useForm<BuyCreditFormData>({\n resolver: zodResolver(buyCreditSchema),\n mode: 'onChange',\n defaultValues: {\n creditOption: currentCredits,\n selectedCardId: defaultCardId,\n },\n });\n\n const hasInitialized = useRef(false);\n\n useEffect(() => {\n if (!open) {\n hasInitialized.current = false;\n return;\n }\n\n if (hasInitialized.current || !subscription) return;\n hasInitialized.current = true;\n\n form.reset({\n creditOption: currentCredits,\n selectedCardId: defaultCardId,\n });\n\n calculate({\n id_product: 1,\n ...(planId != null && { id_plan: planId }),\n ...(subscriptionId != null && { id_subscription: subscriptionId }),\n plan_extras: [\n { id_addon: ADDON_IDS.AI, quantity: currentCredits },\n ],\n });\n }, [\n open,\n subscription,\n currentCredits,\n defaultCardId,\n form,\n calculate,\n planId,\n subscriptionId,\n ]);\n\n // Sync selectedCardId when cards load after modal opened\n useEffect(() => {\n if (open && defaultCardId && !form.getValues('selectedCardId')) {\n form.setValue('selectedCardId', defaultCardId, { shouldValidate: true });\n }\n }, [open, defaultCardId, form]);\n\n const creditOption = form.watch('creditOption');\n const selectedCardId = form.watch('selectedCardId');\n const { isDirty, isSubmitting, isValid } = form.formState;\n\n\n const handleCreditOptionChange = useCallback(\n (value: string | number | boolean) => {\n const credits = Number(value);\n\n form.setValue('creditOption', credits, {\n shouldValidate: true,\n shouldDirty: true,\n });\n\n const option = AI_CREDIT_OPTIONS.find((opt) => opt.credits === credits);\n if (!option) return;\n\n calculate({\n id_product: 1,\n ...(planId != null && { id_plan: planId }),\n ...(subscriptionId != null && { id_subscription: subscriptionId }),\n plan_extras: [\n { id_addon: ADDON_IDS.AI, quantity: option.credits, currency: 'BRL' },\n ],\n });\n },\n [form, subscriptionId, planId, calculate]\n );\n\n const calculatedData = calculateData?.data ?? null;\n\n const isIncreasingCredits = creditOption > currentCredits;\n const hasChanged = creditOption !== currentCredits;\n\n const immediateChargeTotal = calculatedData?.target?.immediate_charge?.total ?? null;\n\n const totalPrice = useMemo(() => {\n if (!calculatedData) return null;\n return getPriceFromCalculatedData(calculatedData, subscription?.periodicity);\n }, [calculatedData, subscription]);\n\n const formatPrice = useCallback((price: number) => {\n return price.toLocaleString('pt-BR', {\n style: 'currency',\n currency: 'BRL',\n });\n }, []);\n\n const isConfirmDisabled = !isDirty || !isValid || isCalculatePending || isSubmitting;\n\n const handleClose = useCallback(() => {\n form.reset();\n closeModal();\n }, [form, closeModal]);\n\n const handleOpenAddCardModal = useCallback(() => {\n openModal('addCardModal');\n }, [openModal]);\n\n const selectOptions = useMemo(() => {\n return AI_CREDIT_OPTIONS.map((opt) => ({\n value: opt.credits,\n label: (\n <div className=\"flex items-center justify-between gap-2 w-full\">\n <span className=\"paragraph-small-medium text-zinc-950 flex-1\">\n {translate('common.credits.buy.creditsOptionLabel', { credits: opt.credits.toLocaleString('pt-BR') })}\n </span>\n <span className=\"paragraph-small-medium text-zinc-500 opacity-70\">{opt.priceLabel}</span>\n </div>\n ),\n displayValue: translate('common.credits.buy.creditsOptionDisplayValue', { credits: opt.credits.toLocaleString('pt-BR') }),\n }));\n }, [translate]);\n\n const onSubmit = useCallback(\n async (data: BuyCreditFormData) => {\n if (!subscriptionId) return;\n\n const option = AI_CREDIT_OPTIONS.find((opt) => opt.credits === data.creditOption);\n if (!option) return;\n\n await updatePlanMutation.mutateAsync({\n subscriptionId,\n data: {\n plan_extras: [\n {\n id_addon: ADDON_IDS.AI,\n quantity: option.credits,\n },\n ],\n },\n });\n\n toast.custom((t) => (\n <Toast\n variant=\"success\"\n message={translate('common.credits.buy.creditsChangedToast', { credits: data.creditOption.toLocaleString('pt-BR') })}\n toastId={t}\n />\n ));\n form.reset();\n closeModal();\n },\n [subscriptionId, updatePlanMutation, form, closeModal]\n );\n\n const renderPriceDisplay = useCallback(() => {\n if (isCalculatePending) {\n return <Skeleton className=\"h-7 w-24\" />;\n }\n if (totalPrice !== null) {\n return (\n <span className=\"paragraph-xlarge-semibold text-zinc-950\">\n {totalPrice === 0 ? translate('common.credits.buy.defaultPrice') : formatPrice(totalPrice)}\n </span>\n );\n }\n return <span className=\"paragraph-xlarge-semibold text-zinc-400\">--</span>;\n }, [isCalculatePending, totalPrice, formatPrice]);\n\n if (isExternalContracting) {\n return (\n <Dialog open={open} onOpenChange={handleClose}>\n <DialogContent className=\"flex flex-col p-0 gap-0 w-full md:w-[410px] lg:w-[410px]\">\n <DialogHeader className=\"gap-3 text-left p-5\">\n <div className=\"flex items-center justify-center w-10 h-10 bg-zinc-50 rounded-lg\">\n <IconSparkles size={24} className=\"text-zinc-950\" />\n </div>\n <div className=\"flex flex-col gap-2\">\n <DialogTitle className=\"paragraph-medium-semibold text-zinc-950\">\n {translate('common.credits.buy.externalTitle')}\n </DialogTitle>\n <span className=\"paragraph-small-regular text-zinc-600\">\n {translate('common.credits.buy.externalDescription')}\n </span>\n </div>\n </DialogHeader>\n <div className=\"flex items-center gap-2 p-5 border-t border-zinc-200\">\n <Button\n className=\"w-fit h-10!\"\n onClick={() => {\n closeModal();\n redirectToExternal('contracting');\n }}\n >\n {translate('common.credits.buy.externalButton')}\n </Button>\n </div>\n </DialogContent>\n </Dialog>\n );\n }\n\n return (\n <Dialog open={open} onOpenChange={handleClose}>\n <DialogContent\n showCloseButton={false}\n className=\"flex flex-col p-0 gap-0 max-w-full sm:max-w-full border-0 rounded-t-2xl rounded-b-none h-dvh top-0 bottom-0 left-0 right-0 translate-x-0 translate-y-0 lg:max-w-[433px] lg:h-auto lg:max-h-[90vh] lg:rounded-lg lg:border lg:top-[50%] lg:left-[50%] lg:right-auto lg:bottom-auto lg:translate-x-[-50%] lg:translate-y-[-50%] overflow-hidden lg:overflow-y-auto\"\n >\n <DialogHeader className=\"px-4 py-3 border-b border-zinc-200 shrink-0 relative\">\n <DialogTitle className=\"paragraph-medium-semibold text-zinc-950 text-center\">\n {translate('common.credits.buy.title')}\n </DialogTitle>\n <button\n type=\"button\"\n onClick={handleClose}\n className=\"absolute right-3 top-1/2 -translate-y-1/2 size-8 flex items-center justify-center rounded-lg cursor-pointer hover:bg-zinc-100 transition-colors\"\n >\n <IconX size={18} className=\"text-zinc-400\" />\n </button>\n </DialogHeader>\n\n <form\n onSubmit={form.handleSubmit(onSubmit)}\n className=\"flex flex-col flex-1 lg:flex-none overflow-hidden\"\n >\n <div className=\"flex flex-col gap-6 lg:gap-8 p-4 lg:p-5 flex-1 lg:flex-none overflow-y-auto\">\n <div className=\"flex flex-col gap-4\">\n <SelectField\n options={selectOptions}\n value={creditOption}\n onChange={handleCreditOptionChange}\n className=\"h-12!\"\n />\n\n <PaymentInfoCard\n selectedCardId={selectedCardId}\n onCardSelect={(cardId) =>\n form.setValue('selectedCardId', cardId, { shouldValidate: true })\n }\n onOpenAddCard={handleOpenAddCardModal}\n />\n\n {hasChanged && (\n <div className={`flex items-center gap-3 p-4 rounded-lg ${isDefaultWl ? 'bg-cyan-50' : 'bg-zinc-50'}`}>\n <IconInfoCircle className=\"size-4 text-zinc-950 shrink-0\" />\n <span className=\"paragraph-small-regular text-zinc-950\">\n {isIncreasingCredits\n ? translate('common.credits.buy.paymentOnConfirm')\n : translate('common.credits.buy.nextInvoiceChanges')}\n </span>\n </div>\n )}\n </div>\n\n <Separator className=\"bg-zinc-200 hidden lg:block\" />\n\n <div className=\"hidden lg:flex flex-col gap-2\">\n {immediateChargeTotal !== null && immediateChargeTotal > 0 && (\n <div className=\"flex items-center justify-between\">\n <span className=\"paragraph-xsmall-medium text-zinc-500\">{translate('common.credits.buy.immediateCharge')}</span>\n {isCalculatePending ? (\n <Skeleton className=\"h-5 w-20\" />\n ) : (\n <span className=\"paragraph-small-semibold text-zinc-950\">\n {formatPrice(immediateChargeTotal)}\n </span>\n )}\n </div>\n )}\n <div className=\"flex items-center justify-between\">\n <span className=\"paragraph-small-medium text-zinc-500\">{translate('common.credits.buy.totalPlanValue')}</span>\n {renderPriceDisplay()}\n </div>\n </div>\n\n <Button\n type=\"submit\"\n disabled={isConfirmDisabled}\n className=\"w-full hidden lg:inline-flex\"\n >\n {isSubmitting && <IconLoader2 className=\"size-4 animate-spin\" />}\n {translate('common.credits.buy.confirmAndPay')}\n </Button>\n </div>\n\n <div className=\"flex flex-col gap-4 p-4 border-t border-zinc-200 shrink-0 lg:hidden\">\n <div className=\"flex flex-col gap-2\">\n {immediateChargeTotal !== null && immediateChargeTotal > 0 && (\n <div className=\"flex items-center justify-between\">\n <span className=\"paragraph-xsmall-medium text-zinc-500\">{translate('common.credits.buy.immediateCharge')}</span>\n {isCalculatePending ? (\n <Skeleton className=\"h-5 w-20\" />\n ) : (\n <span className=\"paragraph-small-semibold text-zinc-950\">\n {formatPrice(immediateChargeTotal)}\n </span>\n )}\n </div>\n )}\n <div className=\"flex items-center justify-between\">\n <span className=\"paragraph-small-medium text-zinc-500\">{translate('common.credits.buy.totalPlanValue')}</span>\n {renderPriceDisplay()}\n </div>\n </div>\n <Button type=\"submit\" disabled={isConfirmDisabled} className=\"w-full\">\n {isSubmitting && <IconLoader2 className=\"size-4 animate-spin\" />}\n {translate('common.credits.buy.confirmAndPay')}\n </Button>\n </div>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":";AA4LQ,SACE,KADF;AA1LR;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,cAAc;AACvB,SAAS,iBAAiB;AAC1B,SAAS,aAAa;AACtB,SAAS,mBAAmB;AAC5B,SAAS,gBAAgB;AACzB,SAAS,uBAAuB;AAChC,SAAS,iBAAiB;AAC1B;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,0BAA0B;AACnC,SAAS,uBAAuB;AAChC,SAAS,gBAAgB;AACzB,SAAS,6BAA6B;AACtC,SAAS,gCAAgC;AACzC,SAAS,iCAAiC;AAC1C,SAAS,kCAAkC;AAC3C,SAAS,wBAAwB,8BAA8B;AAC/D,SAAS,gBAAgB,OAAO,aAAa,oBAAoB;AACjE,SAAS,uBAAuB;AAChC,SAAS,aAAa,WAAW,SAAS,cAAc;AACxD,SAAS,eAAe;AACxB,SAAS,mBAAmB;AAC5B,OAAO,OAAO;AACd,SAAS,aAAa;AAEtB,MAAM,kBAAkB,EAAE,OAAO;AAAA,EAC/B,cAAc,EAAE,OAAO,EAAE,OAAO,CAAC,QAAQ,iBAAiB,IAAI,GAAG,GAAG;AAAA,IAClE,SAAS;AAAA,EACX,CAAC;AAAA,EACD,gBAAgB,EAAE,OAAO,EAAE,IAAI,GAAG,wBAAqB;AACzD,CAAC;AAIc,SAAR,kBAAmC;AACxC,QAAM,YAAY,gBAAgB;AAClC,QAAM,EAAE,MAAM,WAAW,IAAI,mBAAmB;AAChD,QAAM,EAAE,UAAU,IAAI,gBAAgB;AACtC,QAAM,cAAc,uBAAuB;AAC3C,QAAM,EAAE,uBAAuB,mBAAmB,IAAI,uBAAuB;AAC7E,QAAM,EAAE,MAAM,UAAU,IAAI,SAAS;AACrC,QAAM,EAAE,MAAM,iBAAiB,IAAI,sBAAsB;AACzD,QAAM,eAAe,kBAAkB,OAAO,CAAC,KAAK;AACpD,QAAM,gBACJ,WAAW,MAAM,KAAK,CAAC,SAAS,KAAK,UAAU,GAAG,IAAI,SAAS,KAC/D,WAAW,OAAO,CAAC,GAAG,IAAI,SAAS,KACnC;AAEF,QAAM;AAAA,IACJ,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,MAAM;AAAA,EACR,IAAI,yBAAyB;AAC7B,QAAM,qBAAqB,0BAA0B;AAErD,QAAM,SAAS;AAAA,IACb,MAAM,cAAc,OAAO,KAAK,CAAC,SAAS,KAAK,aAAa,UAAU,EAAE;AAAA,IACxE,CAAC,YAAY;AAAA,EACf;AAEA,QAAM,iBAAiB,QAAQ,YAAY;AAC3C,QAAM,iBAAiB,cAAc;AACrC,QAAM,SAAS,cAAc;AAE7B,QAAM,OAAO,QAA2B;AAAA,IACtC,UAAU,YAAY,eAAe;AAAA,IACrC,MAAM;AAAA,IACN,eAAe;AAAA,MACb,cAAc;AAAA,MACd,gBAAgB;AAAA,IAClB;AAAA,EACF,CAAC;AAED,QAAM,iBAAiB,OAAO,KAAK;AAEnC,YAAU,MAAM;AACd,QAAI,CAAC,MAAM;AACT,qBAAe,UAAU;AACzB;AAAA,IACF;AAEA,QAAI,eAAe,WAAW,CAAC,aAAc;AAC7C,mBAAe,UAAU;AAEzB,SAAK,MAAM;AAAA,MACT,cAAc;AAAA,MACd,gBAAgB;AAAA,IAClB,CAAC;AAED,cAAU;AAAA,MACR,YAAY;AAAA,MACZ,GAAI,UAAU,QAAQ,EAAE,SAAS,OAAO;AAAA,MACxC,GAAI,kBAAkB,QAAQ,EAAE,iBAAiB,eAAe;AAAA,MAChE,aAAa;AAAA,QACX,EAAE,UAAU,UAAU,IAAI,UAAU,eAAe;AAAA,MACrD;AAAA,IACF,CAAC;AAAA,EACH,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAGD,YAAU,MAAM;AACd,QAAI,QAAQ,iBAAiB,CAAC,KAAK,UAAU,gBAAgB,GAAG;AAC9D,WAAK,SAAS,kBAAkB,eAAe,EAAE,gBAAgB,KAAK,CAAC;AAAA,IACzE;AAAA,EACF,GAAG,CAAC,MAAM,eAAe,IAAI,CAAC;AAE9B,QAAM,eAAe,KAAK,MAAM,cAAc;AAC9C,QAAM,iBAAiB,KAAK,MAAM,gBAAgB;AAClD,QAAM,EAAE,SAAS,cAAc,QAAQ,IAAI,KAAK;AAGhD,QAAM,2BAA2B;AAAA,IAC/B,CAAC,UAAqC;AACpC,YAAM,UAAU,OAAO,KAAK;AAE5B,WAAK,SAAS,gBAAgB,SAAS;AAAA,QACrC,gBAAgB;AAAA,QAChB,aAAa;AAAA,MACf,CAAC;AAED,YAAM,SAAS,kBAAkB,KAAK,CAAC,QAAQ,IAAI,YAAY,OAAO;AACtE,UAAI,CAAC,OAAQ;AAEb,gBAAU;AAAA,QACR,YAAY;AAAA,QACZ,GAAI,UAAU,QAAQ,EAAE,SAAS,OAAO;AAAA,QACxC,GAAI,kBAAkB,QAAQ,EAAE,iBAAiB,eAAe;AAAA,QAChE,aAAa;AAAA,UACX,EAAE,UAAU,UAAU,IAAI,UAAU,OAAO,SAAS,UAAU,MAAM;AAAA,QACtE;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IACA,CAAC,MAAM,gBAAgB,QAAQ,SAAS;AAAA,EAC1C;AAEA,QAAM,iBAAiB,eAAe,QAAQ;AAE9C,QAAM,sBAAsB,eAAe;AAC3C,QAAM,aAAa,iBAAiB;AAEpC,QAAM,uBAAuB,gBAAgB,QAAQ,kBAAkB,SAAS;AAEhF,QAAM,aAAa,QAAQ,MAAM;AAC/B,QAAI,CAAC,eAAgB,QAAO;AAC5B,WAAO,2BAA2B,gBAAgB,cAAc,WAAW;AAAA,EAC7E,GAAG,CAAC,gBAAgB,YAAY,CAAC;AAEjC,QAAM,cAAc,YAAY,CAAC,UAAkB;AACjD,WAAO,MAAM,eAAe,SAAS;AAAA,MACnC,OAAO;AAAA,MACP,UAAU;AAAA,IACZ,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAEL,QAAM,oBAAoB,CAAC,WAAW,CAAC,WAAW,sBAAsB;AAExE,QAAM,cAAc,YAAY,MAAM;AACpC,SAAK,MAAM;AACX,eAAW;AAAA,EACb,GAAG,CAAC,MAAM,UAAU,CAAC;AAErB,QAAM,yBAAyB,YAAY,MAAM;AAC/C,cAAU,cAAc;AAAA,EAC1B,GAAG,CAAC,SAAS,CAAC;AAEd,QAAM,gBAAgB,QAAQ,MAAM;AAClC,WAAO,kBAAkB,IAAI,CAAC,SAAS;AAAA,MACrC,OAAO,IAAI;AAAA,MACX,OACE,qBAAC,SAAI,WAAU,kDACb;AAAA,4BAAC,UAAK,WAAU,+CACb,oBAAU,yCAAyC,EAAE,SAAS,IAAI,QAAQ,eAAe,OAAO,EAAE,CAAC,GACtG;AAAA,QACA,oBAAC,UAAK,WAAU,mDAAmD,cAAI,YAAW;AAAA,SACpF;AAAA,MAEF,cAAc,UAAU,gDAAgD,EAAE,SAAS,IAAI,QAAQ,eAAe,OAAO,EAAE,CAAC;AAAA,IAC1H,EAAE;AAAA,EACJ,GAAG,CAAC,SAAS,CAAC;AAEd,QAAM,WAAW;AAAA,IACf,OAAO,SAA4B;AACjC,UAAI,CAAC,eAAgB;AAErB,YAAM,SAAS,kBAAkB,KAAK,CAAC,QAAQ,IAAI,YAAY,KAAK,YAAY;AAChF,UAAI,CAAC,OAAQ;AAEb,YAAM,mBAAmB,YAAY;AAAA,QACnC;AAAA,QACA,MAAM;AAAA,UACJ,aAAa;AAAA,YACX;AAAA,cACE,UAAU,UAAU;AAAA,cACpB,UAAU,OAAO;AAAA,YACnB;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC;AAED,YAAM,OAAO,CAAC,MACZ;AAAA,QAAC;AAAA;AAAA,UACC,SAAQ;AAAA,UACR,SAAS,UAAU,0CAA0C,EAAE,SAAS,KAAK,aAAa,eAAe,OAAO,EAAE,CAAC;AAAA,UACnH,SAAS;AAAA;AAAA,MACX,CACD;AACD,WAAK,MAAM;AACX,iBAAW;AAAA,IACb;AAAA,IACA,CAAC,gBAAgB,oBAAoB,MAAM,UAAU;AAAA,EACvD;AAEA,QAAM,qBAAqB,YAAY,MAAM;AAC3C,QAAI,oBAAoB;AACtB,aAAO,oBAAC,YAAS,WAAU,YAAW;AAAA,IACxC;AACA,QAAI,eAAe,MAAM;AACvB,aACE,oBAAC,UAAK,WAAU,2CACb,yBAAe,IAAI,UAAU,iCAAiC,IAAI,YAAY,UAAU,GAC3F;AAAA,IAEJ;AACA,WAAO,oBAAC,UAAK,WAAU,2CAA0C,gBAAE;AAAA,EACrE,GAAG,CAAC,oBAAoB,YAAY,WAAW,CAAC;AAEhD,MAAI,uBAAuB;AACzB,WACE,oBAAC,UAAO,MAAY,cAAc,aAChC,+BAAC,iBAAc,WAAU,4DACvB;AAAA,2BAAC,gBAAa,WAAU,uBACtB;AAAA,4BAAC,SAAI,WAAU,oEACb,8BAAC,gBAAa,MAAM,IAAI,WAAU,iBAAgB,GACpD;AAAA,QACA,qBAAC,SAAI,WAAU,uBACb;AAAA,8BAAC,eAAY,WAAU,2CACpB,oBAAU,kCAAkC,GAC/C;AAAA,UACA,oBAAC,UAAK,WAAU,yCACb,oBAAU,wCAAwC,GACrD;AAAA,WACF;AAAA,SACF;AAAA,MACA,oBAAC,SAAI,WAAU,wDACb;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,SAAS,MAAM;AACb,uBAAW;AACX,+BAAmB,aAAa;AAAA,UAClC;AAAA,UAEC,oBAAU,mCAAmC;AAAA;AAAA,MAChD,GACF;AAAA,OACF,GACF;AAAA,EAEJ;AAEA,SACE,oBAAC,UAAO,MAAY,cAAc,aAChC;AAAA,IAAC;AAAA;AAAA,MACC,iBAAiB;AAAA,MACjB,WAAU;AAAA,MAEV;AAAA,6BAAC,gBAAa,WAAU,wDACtB;AAAA,8BAAC,eAAY,WAAU,uDACpB,oBAAU,0BAA0B,GACvC;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS;AAAA,cACT,WAAU;AAAA,cAEV,8BAAC,SAAM,MAAM,IAAI,WAAU,iBAAgB;AAAA;AAAA,UAC7C;AAAA,WACF;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,UAAU,KAAK,aAAa,QAAQ;AAAA,YACpC,WAAU;AAAA,YAEV;AAAA,mCAAC,SAAI,WAAU,+EACb;AAAA,qCAAC,SAAI,WAAU,uBACb;AAAA;AAAA,oBAAC;AAAA;AAAA,sBACC,SAAS;AAAA,sBACT,OAAO;AAAA,sBACP,UAAU;AAAA,sBACV,WAAU;AAAA;AAAA,kBACZ;AAAA,kBAEA;AAAA,oBAAC;AAAA;AAAA,sBACC;AAAA,sBACA,cAAc,CAAC,WACb,KAAK,SAAS,kBAAkB,QAAQ,EAAE,gBAAgB,KAAK,CAAC;AAAA,sBAElE,eAAe;AAAA;AAAA,kBACjB;AAAA,kBAEC,cACC,qBAAC,SAAI,WAAW,0CAA0C,cAAc,eAAe,YAAY,IACjG;AAAA,wCAAC,kBAAe,WAAU,iCAAgC;AAAA,oBAC1D,oBAAC,UAAK,WAAU,yCACb,gCACG,UAAU,qCAAqC,IAC/C,UAAU,uCAAuC,GACvD;AAAA,qBACF;AAAA,mBAEJ;AAAA,gBAEA,oBAAC,aAAU,WAAU,+BAA8B;AAAA,gBAEnD,qBAAC,SAAI,WAAU,iCACZ;AAAA,2CAAyB,QAAQ,uBAAuB,KACvD,qBAAC,SAAI,WAAU,qCACb;AAAA,wCAAC,UAAK,WAAU,yCAAyC,oBAAU,oCAAoC,GAAE;AAAA,oBACxG,qBACC,oBAAC,YAAS,WAAU,YAAW,IAE/B,oBAAC,UAAK,WAAU,0CACb,sBAAY,oBAAoB,GACnC;AAAA,qBAEJ;AAAA,kBAEF,qBAAC,SAAI,WAAU,qCACb;AAAA,wCAAC,UAAK,WAAU,wCAAwC,oBAAU,mCAAmC,GAAE;AAAA,oBACtG,mBAAmB;AAAA,qBACtB;AAAA,mBACF;AAAA,gBAEA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,UAAU;AAAA,oBACV,WAAU;AAAA,oBAET;AAAA,sCAAgB,oBAAC,eAAY,WAAU,uBAAsB;AAAA,sBAC7D,UAAU,kCAAkC;AAAA;AAAA;AAAA,gBAC/C;AAAA,iBACF;AAAA,cAEA,qBAAC,SAAI,WAAU,uEACb;AAAA,qCAAC,SAAI,WAAU,uBACZ;AAAA,2CAAyB,QAAQ,uBAAuB,KACvD,qBAAC,SAAI,WAAU,qCACb;AAAA,wCAAC,UAAK,WAAU,yCAAyC,oBAAU,oCAAoC,GAAE;AAAA,oBACxG,qBACC,oBAAC,YAAS,WAAU,YAAW,IAE/B,oBAAC,UAAK,WAAU,0CACb,sBAAY,oBAAoB,GACnC;AAAA,qBAEJ;AAAA,kBAEF,qBAAC,SAAI,WAAU,qCACb;AAAA,wCAAC,UAAK,WAAU,wCAAwC,oBAAU,mCAAmC,GAAE;AAAA,oBACtG,mBAAmB;AAAA,qBACtB;AAAA,mBACF;AAAA,gBACA,qBAAC,UAAO,MAAK,UAAS,UAAU,mBAAmB,WAAU,UAC1D;AAAA,kCAAgB,oBAAC,eAAY,WAAU,uBAAsB;AAAA,kBAC7D,UAAU,kCAAkC;AAAA,mBAC/C;AAAA,iBACF;AAAA;AAAA;AAAA,QACF;AAAA;AAAA;AAAA,EACF,GACF;AAEJ;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/modals/BuyCreditsModal.tsx"],"sourcesContent":["'use client';\n\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n} from '../ui/overlay/Dialog';\nimport { Button } from '../ui/buttons/Button';\nimport { Separator } from '../ui/data-display/Separator';\nimport { Toast } from '../ui/feedback/Toast';\nimport { SelectField } from '../ui/form/SelectField';\nimport { Skeleton } from '../ui/feedback/Skeleton';\nimport { PaymentInfoCard } from '../ui/data-display/PaymentInfoCard';\nimport { ADDON_IDS } from '../../modules/subscriptions/constants/addons.constants';\nimport {\n AI_CREDIT_OPTIONS,\n AI_CREDIT_VALUES,\n} from '../../modules/subscriptions/constants/addons.constants';\nimport { useBuyCreditsModal } from '../../store/useBuyCreditsModal';\nimport { useModalManager } from '../../store/useModalManager';\nimport { useCards } from '../../modules/cards/hooks/cards.hook';\nimport { useActiveSubscription } from '../../modules/subscriptions/hooks/find-active-subscription.hook';\nimport { useCalculateSubscription } from '../../modules/subscriptions/hooks/calculate-subscription.hook';\nimport { useUpdateSubscriptionPlan } from '../../modules/subscriptions/hooks/update-subscription-plan.hook';\nimport { getPriceFromCalculatedData } from '../../modules/subscriptions/utils/periodicity';\nimport { useIsDefaultWhitelabel, useExternalContracting } from '../../providers/whitelabel.provider';\nimport { IconInfoCircle, IconX, IconLoader2, IconSparkles } from '@tabler/icons-react';\nimport { useTranslations } from 'next-intl';\nimport { useCallback, useEffect, useMemo, useRef } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport z from 'zod';\nimport { toast } from 'sonner';\n\nconst buyCreditSchema = z.object({\n creditOption: z.number().refine((val) => AI_CREDIT_VALUES.has(val), {\n message: 'Selecione uma opção de créditos',\n }),\n selectedCardId: z.string().min(1, 'Selecione um cartão'),\n});\n\ntype BuyCreditFormData = z.infer<typeof buyCreditSchema>;\n\nexport default function BuyCreditsModal() {\n const translate = useTranslations();\n const { open, closeModal } = useBuyCreditsModal();\n const { openModal } = useModalManager();\n const isDefaultWl = useIsDefaultWhitelabel();\n const { isExternalContracting, redirectToExternal } = useExternalContracting();\n const { data: cardsData } = useCards();\n const { data: subscriptionData } = useActiveSubscription();\n const subscription = subscriptionData?.data?.[0] ?? null;\n const defaultCardId =\n cardsData?.data?.find((card) => card.is_default)?.id?.toString() ??\n cardsData?.data?.[0]?.id?.toString() ??\n '';\n\n const {\n mutate: calculate,\n isPending: isCalculatePending,\n data: calculateData,\n } = useCalculateSubscription();\n const updatePlanMutation = useUpdateSubscriptionPlan();\n\n const aiItem = useMemo(\n () => subscription?.items?.find((item) => item.id_addon === ADDON_IDS.AI),\n [subscription]\n );\n\n const currentCredits = aiItem?.quantity ?? 0;\n const subscriptionId = subscription?.id;\n const planId = subscription?.id_plan;\n\n const buildPlanExtras = useCallback(\n (aiQuantity: number) => [\n ...(subscription?.items ?? [])\n .filter((item) => item.id_addon != null && item.id_addon !== ADDON_IDS.AI && Number(item.value ?? 0) > 0)\n .map((item) => ({ id_addon: Number(item.id_addon), quantity: item.quantity ?? 0 })),\n { id_addon: ADDON_IDS.AI, quantity: aiQuantity },\n ],\n [subscription]\n );\n\n const form = useForm<BuyCreditFormData>({\n resolver: zodResolver(buyCreditSchema),\n mode: 'onChange',\n defaultValues: {\n creditOption: currentCredits,\n selectedCardId: defaultCardId,\n },\n });\n\n const hasInitialized = useRef(false);\n\n useEffect(() => {\n if (!open) {\n hasInitialized.current = false;\n return;\n }\n\n if (hasInitialized.current || !subscription) return;\n hasInitialized.current = true;\n\n form.reset({\n creditOption: currentCredits,\n selectedCardId: defaultCardId,\n });\n\n calculate({\n id_product: 1,\n ...(planId != null && { id_plan: planId }),\n ...(subscriptionId != null && { id_subscription: subscriptionId }),\n plan_extras: buildPlanExtras(currentCredits),\n });\n }, [\n open,\n subscription,\n currentCredits,\n defaultCardId,\n form,\n calculate,\n planId,\n subscriptionId,\n buildPlanExtras,\n ]);\n\n // Sync selectedCardId when cards load after modal opened\n useEffect(() => {\n if (open && defaultCardId && !form.getValues('selectedCardId')) {\n form.setValue('selectedCardId', defaultCardId, { shouldValidate: true });\n }\n }, [open, defaultCardId, form]);\n\n const creditOption = form.watch('creditOption');\n const selectedCardId = form.watch('selectedCardId');\n const { isDirty, isSubmitting, isValid } = form.formState;\n\n\n const handleCreditOptionChange = useCallback(\n (value: string | number | boolean) => {\n const credits = Number(value);\n\n form.setValue('creditOption', credits, {\n shouldValidate: true,\n shouldDirty: true,\n });\n\n const option = AI_CREDIT_OPTIONS.find((opt) => opt.credits === credits);\n if (!option) return;\n\n calculate({\n id_product: 1,\n ...(planId != null && { id_plan: planId }),\n ...(subscriptionId != null && { id_subscription: subscriptionId }),\n plan_extras: buildPlanExtras(option.credits),\n });\n },\n [form, subscriptionId, planId, calculate, buildPlanExtras]\n );\n\n const calculatedData = calculateData?.data ?? null;\n\n const isIncreasingCredits = creditOption > currentCredits;\n const hasChanged = creditOption !== currentCredits;\n\n const immediateChargeTotal = calculatedData?.target?.immediate_charge?.total ?? null;\n\n const totalPrice = useMemo(() => {\n if (!calculatedData) return null;\n return getPriceFromCalculatedData(calculatedData, subscription?.periodicity);\n }, [calculatedData, subscription]);\n\n const formatPrice = useCallback((price: number) => {\n return price.toLocaleString('pt-BR', {\n style: 'currency',\n currency: 'BRL',\n });\n }, []);\n\n const isConfirmDisabled = !isDirty || !isValid || isCalculatePending || isSubmitting;\n\n const handleClose = useCallback(() => {\n form.reset();\n closeModal();\n }, [form, closeModal]);\n\n const handleOpenAddCardModal = useCallback(() => {\n openModal('addCardModal');\n }, [openModal]);\n\n const selectOptions = useMemo(() => {\n return AI_CREDIT_OPTIONS.map((opt) => ({\n value: opt.credits,\n label: (\n <div className=\"flex items-center justify-between gap-2 w-full\">\n <span className=\"paragraph-small-medium text-zinc-950 flex-1\">\n {translate('common.credits.buy.creditsOptionLabel', { credits: opt.credits.toLocaleString('pt-BR') })}\n </span>\n <span className=\"paragraph-small-medium text-zinc-500 opacity-70\">{opt.priceLabel}</span>\n </div>\n ),\n displayValue: translate('common.credits.buy.creditsOptionDisplayValue', { credits: opt.credits.toLocaleString('pt-BR') }),\n }));\n }, [translate]);\n\n const onSubmit = useCallback(\n async (data: BuyCreditFormData) => {\n if (!subscriptionId) return;\n\n const option = AI_CREDIT_OPTIONS.find((opt) => opt.credits === data.creditOption);\n if (!option) return;\n\n await updatePlanMutation.mutateAsync({\n subscriptionId,\n data: {\n plan_extras: buildPlanExtras(option.credits),\n },\n });\n\n toast.custom((t) => (\n <Toast\n variant=\"success\"\n message={translate('common.credits.buy.creditsChangedToast', { credits: data.creditOption.toLocaleString('pt-BR') })}\n toastId={t}\n />\n ));\n form.reset();\n closeModal();\n },\n [subscriptionId, updatePlanMutation, form, closeModal, buildPlanExtras]\n );\n\n const renderPriceDisplay = useCallback(() => {\n if (isCalculatePending) {\n return <Skeleton className=\"h-7 w-24\" />;\n }\n if (totalPrice !== null) {\n return (\n <span className=\"paragraph-xlarge-semibold text-zinc-950\">\n {totalPrice === 0 ? translate('common.credits.buy.defaultPrice') : formatPrice(totalPrice)}\n </span>\n );\n }\n return <span className=\"paragraph-xlarge-semibold text-zinc-400\">--</span>;\n }, [isCalculatePending, totalPrice, formatPrice]);\n\n if (isExternalContracting) {\n return (\n <Dialog open={open} onOpenChange={handleClose}>\n <DialogContent className=\"flex flex-col p-0 gap-0 w-full md:w-[410px] lg:w-[410px]\">\n <DialogHeader className=\"gap-3 text-left p-5\">\n <div className=\"flex items-center justify-center w-10 h-10 bg-zinc-50 rounded-lg\">\n <IconSparkles size={24} className=\"text-zinc-950\" />\n </div>\n <div className=\"flex flex-col gap-2\">\n <DialogTitle className=\"paragraph-medium-semibold text-zinc-950\">\n {translate('common.credits.buy.externalTitle')}\n </DialogTitle>\n <span className=\"paragraph-small-regular text-zinc-600\">\n {translate('common.credits.buy.externalDescription')}\n </span>\n </div>\n </DialogHeader>\n <div className=\"flex items-center gap-2 p-5 border-t border-zinc-200\">\n <Button\n className=\"w-fit h-10!\"\n onClick={() => {\n closeModal();\n redirectToExternal('contracting');\n }}\n >\n {translate('common.credits.buy.externalButton')}\n </Button>\n </div>\n </DialogContent>\n </Dialog>\n );\n }\n\n return (\n <Dialog open={open} onOpenChange={handleClose}>\n <DialogContent\n showCloseButton={false}\n className=\"flex flex-col p-0 gap-0 max-w-full sm:max-w-full border-0 rounded-t-2xl rounded-b-none h-dvh top-0 bottom-0 left-0 right-0 translate-x-0 translate-y-0 lg:max-w-[433px] lg:h-auto lg:max-h-[90vh] lg:rounded-lg lg:border lg:top-[50%] lg:left-[50%] lg:right-auto lg:bottom-auto lg:translate-x-[-50%] lg:translate-y-[-50%] overflow-hidden lg:overflow-y-auto\"\n >\n <DialogHeader className=\"px-4 py-3 border-b border-zinc-200 shrink-0 relative\">\n <DialogTitle className=\"paragraph-medium-semibold text-zinc-950 text-center\">\n {translate('common.credits.buy.title')}\n </DialogTitle>\n <button\n type=\"button\"\n onClick={handleClose}\n className=\"absolute right-3 top-1/2 -translate-y-1/2 size-8 flex items-center justify-center rounded-lg cursor-pointer hover:bg-zinc-100 transition-colors\"\n >\n <IconX size={18} className=\"text-zinc-400\" />\n </button>\n </DialogHeader>\n\n <form\n onSubmit={form.handleSubmit(onSubmit)}\n className=\"flex flex-col flex-1 lg:flex-none overflow-hidden\"\n >\n <div className=\"flex flex-col gap-6 lg:gap-8 p-4 lg:p-5 flex-1 lg:flex-none overflow-y-auto\">\n <div className=\"flex flex-col gap-4\">\n <SelectField\n options={selectOptions}\n value={creditOption}\n onChange={handleCreditOptionChange}\n className=\"h-12!\"\n />\n\n <PaymentInfoCard\n selectedCardId={selectedCardId}\n onCardSelect={(cardId) =>\n form.setValue('selectedCardId', cardId, { shouldValidate: true })\n }\n onOpenAddCard={handleOpenAddCardModal}\n />\n\n {hasChanged && (\n <div className={`flex items-center gap-3 p-4 rounded-lg ${isDefaultWl ? 'bg-cyan-50' : 'bg-zinc-50'}`}>\n <IconInfoCircle className=\"size-4 text-zinc-950 shrink-0\" />\n <span className=\"paragraph-small-regular text-zinc-950\">\n {isIncreasingCredits\n ? translate('common.credits.buy.paymentOnConfirm')\n : translate('common.credits.buy.nextInvoiceChanges')}\n </span>\n </div>\n )}\n </div>\n\n <Separator className=\"bg-zinc-200 hidden lg:block\" />\n\n <div className=\"hidden lg:flex flex-col gap-2\">\n {immediateChargeTotal !== null && immediateChargeTotal > 0 && (\n <div className=\"flex items-center justify-between\">\n <span className=\"paragraph-xsmall-medium text-zinc-500\">{translate('common.credits.buy.immediateCharge')}</span>\n {isCalculatePending ? (\n <Skeleton className=\"h-5 w-20\" />\n ) : (\n <span className=\"paragraph-small-semibold text-zinc-950\">\n {formatPrice(immediateChargeTotal)}\n </span>\n )}\n </div>\n )}\n <div className=\"flex items-center justify-between\">\n <span className=\"paragraph-small-medium text-zinc-500\">{translate('common.credits.buy.totalPlanValue')}</span>\n {renderPriceDisplay()}\n </div>\n </div>\n\n <Button\n type=\"submit\"\n disabled={isConfirmDisabled}\n className=\"w-full hidden lg:inline-flex\"\n >\n {isSubmitting && <IconLoader2 className=\"size-4 animate-spin\" />}\n {translate('common.credits.buy.confirmAndPay')}\n </Button>\n </div>\n\n <div className=\"flex flex-col gap-4 p-4 border-t border-zinc-200 shrink-0 lg:hidden\">\n <div className=\"flex flex-col gap-2\">\n {immediateChargeTotal !== null && immediateChargeTotal > 0 && (\n <div className=\"flex items-center justify-between\">\n <span className=\"paragraph-xsmall-medium text-zinc-500\">{translate('common.credits.buy.immediateCharge')}</span>\n {isCalculatePending ? (\n <Skeleton className=\"h-5 w-20\" />\n ) : (\n <span className=\"paragraph-small-semibold text-zinc-950\">\n {formatPrice(immediateChargeTotal)}\n </span>\n )}\n </div>\n )}\n <div className=\"flex items-center justify-between\">\n <span className=\"paragraph-small-medium text-zinc-500\">{translate('common.credits.buy.totalPlanValue')}</span>\n {renderPriceDisplay()}\n </div>\n </div>\n <Button type=\"submit\" disabled={isConfirmDisabled} className=\"w-full\">\n {isSubmitting && <IconLoader2 className=\"size-4 animate-spin\" />}\n {translate('common.credits.buy.confirmAndPay')}\n </Button>\n </div>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -113,7 +113,7 @@ function PaymentInfoCard({
|
|
|
113
113
|
/* @__PURE__ */ jsxs(
|
|
114
114
|
"div",
|
|
115
115
|
{
|
|
116
|
-
className: `flex flex-col gap-2 px-4
|
|
116
|
+
className: `flex flex-col gap-2 px-4 transition-all duration-300 ease-in-out ${isExpanded ? "max-h-[167px] overflow-y-auto pb-4 opacity-100" : "max-h-0 overflow-hidden pb-0 opacity-0"}`,
|
|
117
117
|
children: [
|
|
118
118
|
displayedCards.map((card) => /* @__PURE__ */ jsx(
|
|
119
119
|
CardItem,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/ui/data-display/PaymentInfoCard.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useState } from 'react';\nimport { IconChevronDown, IconPlus } from '@tabler/icons-react';\nimport { CardBrandIcon } from './CardBrandIcons';\nimport { CardItem } from './CardItem';\nimport useIsMobile from '../../../hooks/useIsMobile';\nimport { useCards } from '../../../modules/cards/hooks/cards.hook';\nimport { useModalManager } from '../../../store/useModalManager';\nimport { useIsDefaultWhitelabel } from '../../../providers/whitelabel.provider';\nimport type { Card } from '../../../modules/cards/types';\nimport { useTranslations } from 'next-intl';\n\ntype PaymentInfoCardProps = {\n email?: string;\n selectedCardId: string;\n onCardSelect: (cardId: string) => void;\n onManageCards?: () => void;\n onOpenAddCard?: () => void;\n hideDelete?: boolean;\n hideSetDefault?: boolean;\n};\n\nexport function PaymentInfoCard({\n email,\n selectedCardId,\n onCardSelect,\n onManageCards,\n onOpenAddCard,\n hideDelete,\n hideSetDefault,\n}: PaymentInfoCardProps) {\n const translate = useTranslations();\n const isMobile = useIsMobile();\n const { openModal } = useModalManager();\n const isDefaultWl = useIsDefaultWhitelabel();\n\n const [isExpanded, setIsExpanded] = useState(false);\n\n const { data: cardsData } = useCards();\n const cards = cardsData?.data ?? [];\n\n const selectedCard = cards.find(\n (card) => card.id.toString() === selectedCardId.toString(),\n );\n\n const hasCards = cards.length > 0;\n\n const hasMoreThan3Cards = cards.length > 3;\n const shouldShowManageButton = isMobile && hasMoreThan3Cards;\n const displayedCards = shouldShowManageButton ? cards.slice(0, 3) : cards;\n\n const handleOpenAddCardModal = useCallback(() => {\n if (onOpenAddCard) {\n onOpenAddCard();\n return;\n }\n openModal('addCardModal', {\n onCardAdded: (cardId: string) => onCardSelect(cardId),\n });\n }, [openModal, onOpenAddCard, onCardSelect]);\n\n const handleSelectCard = useCallback(\n (cardId: string) => {\n onCardSelect(cardId);\n setIsExpanded(false);\n },\n [onCardSelect],\n );\n\n const handleAfterDelete = useCallback(\n (card: Card) => {\n if (card.id.toString() === selectedCardId.toString()) {\n const remaining = cards.filter((c) => c.id !== card.id);\n if (remaining.length > 0) {\n onCardSelect(remaining[0].id.toString());\n }\n }\n },\n [cards, selectedCardId, onCardSelect],\n );\n\n if (!hasCards) {\n return (\n <div className=\"border border-zinc-200 rounded-lg overflow-hidden\">\n {email && (\n <div className=\"flex items-center h-[60px] px-4 border-b border-zinc-200 gap-3\">\n <span className=\"paragraph-small-medium text-zinc-500 w-[100px]\">{translate('common.cards.paymentInfo.email')}</span>\n <span className=\"paragraph-small-medium text-zinc-950 flex-1\">{email}</span>\n </div>\n )}\n <div className=\"flex items-center h-[60px] px-4 gap-3\">\n <span className=\"paragraph-small-medium text-zinc-500 w-[100px]\">{translate('common.cards.paymentInfo.payment')}</span>\n <button\n type=\"button\"\n onClick={handleOpenAddCardModal}\n className=\"flex items-center h-8 px-2 paragraph-small-semibold text-zinc-950 border border-zinc-200 rounded-md hover:border-zinc-400 transition-colors cursor-pointer w-fit\"\n >\n <IconPlus className=\"size-[18px]\" />\n <span className=\"px-1.5\">{translate('common.cards.paymentInfo.addCard')}</span>\n </button>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"flex flex-col gap-3\">\n <div className=\"border border-zinc-200 rounded-lg overflow-hidden\">\n {email && (\n <div className=\"flex items-center h-[60px] px-4 border-b border-zinc-200 gap-3\">\n <span className=\"paragraph-small-medium text-zinc-500 w-[100px]\">{translate('common.cards.paymentInfo.email')}</span>\n <span className=\"paragraph-small-medium text-zinc-950 flex-1\">{email}</span>\n </div>\n )}\n\n <div\n className=\"flex items-center px-4 py-4 cursor-pointer gap-3\"\n onClick={() => setIsExpanded((prev) => !prev)}\n >\n {!isExpanded ? (\n <>\n <span className=\"paragraph-small-medium text-zinc-500 w-[100px]\">{translate('common.cards.paymentInfo.payment')}</span>\n <div className=\"flex flex-col gap-0.5 flex-1 min-w-0\">\n <span className=\"paragraph-small-semibold text-zinc-950 truncate\">\n {selectedCard?.name}\n </span>\n <span className=\"paragraph-small-medium text-zinc-950\">\n •••• {selectedCard?.number?.replaceAll(/\\D/g, '')?.slice(-4)}\n </span>\n </div>\n {selectedCard && <CardBrandIcon brand={selectedCard.brand} />}\n <div className=\"size-8 flex items-center justify-center rounded-lg\">\n <IconChevronDown className=\"size-[18px] text-zinc-500\" />\n </div>\n </>\n ) : (\n <>\n <span className=\"paragraph-small-semibold text-zinc-950 flex-1\">\n {translate('common.cards.paymentInfo.selectPaymentMethod')}\n </span>\n <div className=\"size-8 flex items-center justify-center rounded-lg\">\n <IconChevronDown className=\"size-[18px] text-zinc-500 rotate-180\" />\n </div>\n </>\n )}\n </div>\n\n <div\n className={`flex flex-col gap-2 px-4 overflow-hidden transition-all duration-300 ease-in-out ${\n isExpanded ? 'max-h-[500px] pb-4 opacity-100' : 'max-h-0 pb-0 opacity-0'\n }`}\n >\n {displayedCards.map((card) => (\n <CardItem\n key={card.id}\n card={card}\n isSelected={card.id.toString() === selectedCardId.toString()}\n onSelect={() => handleSelectCard(card.id.toString())}\n hideDelete={hideDelete}\n hideSetDefault={hideSetDefault}\n onAfterDelete={handleAfterDelete}\n />\n ))}\n {shouldShowManageButton && onManageCards && (\n <button\n type=\"button\"\n onClick={onManageCards}\n className={`flex items-center justify-center h-10 px-4 paragraph-small-semibold rounded-lg transition-colors cursor-pointer mt-2 ${\n isDefaultWl\n ? 'text-cyan-600 border border-cyan-200 hover:bg-cyan-50'\n : 'text-zinc-600 border border-zinc-200 hover:bg-zinc-50'\n }`}\n >\n {translate('common.cards.paymentInfo.manageCards')}\n </button>\n )}\n </div>\n </div>\n\n <button\n type=\"button\"\n onClick={handleOpenAddCardModal}\n className=\"flex items-center h-8 px-2 paragraph-small-semibold text-zinc-950 border border-zinc-200 rounded-md hover:border-zinc-400 transition-colors cursor-pointer w-fit\"\n >\n <IconPlus className=\"size-[18px]\" />\n <span className=\"px-1.5\">\n {isExpanded ? translate('common.cards.paymentInfo.addCard') : translate('common.cards.paymentInfo.newPaymentMethod')}\n </span>\n </button>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/ui/data-display/PaymentInfoCard.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useState } from 'react';\nimport { IconChevronDown, IconPlus } from '@tabler/icons-react';\nimport { CardBrandIcon } from './CardBrandIcons';\nimport { CardItem } from './CardItem';\nimport useIsMobile from '../../../hooks/useIsMobile';\nimport { useCards } from '../../../modules/cards/hooks/cards.hook';\nimport { useModalManager } from '../../../store/useModalManager';\nimport { useIsDefaultWhitelabel } from '../../../providers/whitelabel.provider';\nimport type { Card } from '../../../modules/cards/types';\nimport { useTranslations } from 'next-intl';\n\ntype PaymentInfoCardProps = {\n email?: string;\n selectedCardId: string;\n onCardSelect: (cardId: string) => void;\n onManageCards?: () => void;\n onOpenAddCard?: () => void;\n hideDelete?: boolean;\n hideSetDefault?: boolean;\n};\n\nexport function PaymentInfoCard({\n email,\n selectedCardId,\n onCardSelect,\n onManageCards,\n onOpenAddCard,\n hideDelete,\n hideSetDefault,\n}: PaymentInfoCardProps) {\n const translate = useTranslations();\n const isMobile = useIsMobile();\n const { openModal } = useModalManager();\n const isDefaultWl = useIsDefaultWhitelabel();\n\n const [isExpanded, setIsExpanded] = useState(false);\n\n const { data: cardsData } = useCards();\n const cards = cardsData?.data ?? [];\n\n const selectedCard = cards.find(\n (card) => card.id.toString() === selectedCardId.toString(),\n );\n\n const hasCards = cards.length > 0;\n\n const hasMoreThan3Cards = cards.length > 3;\n const shouldShowManageButton = isMobile && hasMoreThan3Cards;\n const displayedCards = shouldShowManageButton ? cards.slice(0, 3) : cards;\n\n const handleOpenAddCardModal = useCallback(() => {\n if (onOpenAddCard) {\n onOpenAddCard();\n return;\n }\n openModal('addCardModal', {\n onCardAdded: (cardId: string) => onCardSelect(cardId),\n });\n }, [openModal, onOpenAddCard, onCardSelect]);\n\n const handleSelectCard = useCallback(\n (cardId: string) => {\n onCardSelect(cardId);\n setIsExpanded(false);\n },\n [onCardSelect],\n );\n\n const handleAfterDelete = useCallback(\n (card: Card) => {\n if (card.id.toString() === selectedCardId.toString()) {\n const remaining = cards.filter((c) => c.id !== card.id);\n if (remaining.length > 0) {\n onCardSelect(remaining[0].id.toString());\n }\n }\n },\n [cards, selectedCardId, onCardSelect],\n );\n\n if (!hasCards) {\n return (\n <div className=\"border border-zinc-200 rounded-lg overflow-hidden\">\n {email && (\n <div className=\"flex items-center h-[60px] px-4 border-b border-zinc-200 gap-3\">\n <span className=\"paragraph-small-medium text-zinc-500 w-[100px]\">{translate('common.cards.paymentInfo.email')}</span>\n <span className=\"paragraph-small-medium text-zinc-950 flex-1\">{email}</span>\n </div>\n )}\n <div className=\"flex items-center h-[60px] px-4 gap-3\">\n <span className=\"paragraph-small-medium text-zinc-500 w-[100px]\">{translate('common.cards.paymentInfo.payment')}</span>\n <button\n type=\"button\"\n onClick={handleOpenAddCardModal}\n className=\"flex items-center h-8 px-2 paragraph-small-semibold text-zinc-950 border border-zinc-200 rounded-md hover:border-zinc-400 transition-colors cursor-pointer w-fit\"\n >\n <IconPlus className=\"size-[18px]\" />\n <span className=\"px-1.5\">{translate('common.cards.paymentInfo.addCard')}</span>\n </button>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"flex flex-col gap-3\">\n <div className=\"border border-zinc-200 rounded-lg overflow-hidden\">\n {email && (\n <div className=\"flex items-center h-[60px] px-4 border-b border-zinc-200 gap-3\">\n <span className=\"paragraph-small-medium text-zinc-500 w-[100px]\">{translate('common.cards.paymentInfo.email')}</span>\n <span className=\"paragraph-small-medium text-zinc-950 flex-1\">{email}</span>\n </div>\n )}\n\n <div\n className=\"flex items-center px-4 py-4 cursor-pointer gap-3\"\n onClick={() => setIsExpanded((prev) => !prev)}\n >\n {!isExpanded ? (\n <>\n <span className=\"paragraph-small-medium text-zinc-500 w-[100px]\">{translate('common.cards.paymentInfo.payment')}</span>\n <div className=\"flex flex-col gap-0.5 flex-1 min-w-0\">\n <span className=\"paragraph-small-semibold text-zinc-950 truncate\">\n {selectedCard?.name}\n </span>\n <span className=\"paragraph-small-medium text-zinc-950\">\n •••• {selectedCard?.number?.replaceAll(/\\D/g, '')?.slice(-4)}\n </span>\n </div>\n {selectedCard && <CardBrandIcon brand={selectedCard.brand} />}\n <div className=\"size-8 flex items-center justify-center rounded-lg\">\n <IconChevronDown className=\"size-[18px] text-zinc-500\" />\n </div>\n </>\n ) : (\n <>\n <span className=\"paragraph-small-semibold text-zinc-950 flex-1\">\n {translate('common.cards.paymentInfo.selectPaymentMethod')}\n </span>\n <div className=\"size-8 flex items-center justify-center rounded-lg\">\n <IconChevronDown className=\"size-[18px] text-zinc-500 rotate-180\" />\n </div>\n </>\n )}\n </div>\n\n <div\n className={`flex flex-col gap-2 px-4 transition-all duration-300 ease-in-out ${\n isExpanded ? 'max-h-[167px] overflow-y-auto pb-4 opacity-100' : 'max-h-0 overflow-hidden pb-0 opacity-0'\n }`}\n >\n {displayedCards.map((card) => (\n <CardItem\n key={card.id}\n card={card}\n isSelected={card.id.toString() === selectedCardId.toString()}\n onSelect={() => handleSelectCard(card.id.toString())}\n hideDelete={hideDelete}\n hideSetDefault={hideSetDefault}\n onAfterDelete={handleAfterDelete}\n />\n ))}\n {shouldShowManageButton && onManageCards && (\n <button\n type=\"button\"\n onClick={onManageCards}\n className={`flex items-center justify-center h-10 px-4 paragraph-small-semibold rounded-lg transition-colors cursor-pointer mt-2 ${\n isDefaultWl\n ? 'text-cyan-600 border border-cyan-200 hover:bg-cyan-50'\n : 'text-zinc-600 border border-zinc-200 hover:bg-zinc-50'\n }`}\n >\n {translate('common.cards.paymentInfo.manageCards')}\n </button>\n )}\n </div>\n </div>\n\n <button\n type=\"button\"\n onClick={handleOpenAddCardModal}\n className=\"flex items-center h-8 px-2 paragraph-small-semibold text-zinc-950 border border-zinc-200 rounded-md hover:border-zinc-400 transition-colors cursor-pointer w-fit\"\n >\n <IconPlus className=\"size-[18px]\" />\n <span className=\"px-1.5\">\n {isExpanded ? translate('common.cards.paymentInfo.addCard') : translate('common.cards.paymentInfo.newPaymentMethod')}\n </span>\n </button>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import imageCompression from "browser-image-compression";
|
|
2
2
|
async function compressImage(file, options = {}) {
|
|
3
|
-
const { maxSizeMB = 1, maxWidthOrHeight = 1920 } = options;
|
|
4
|
-
|
|
3
|
+
const { maxSizeMB = 1, maxWidthOrHeight = 1920, outputType } = options;
|
|
4
|
+
const needsConversion = !!outputType && outputType !== file.type;
|
|
5
|
+
if (!needsConversion && file.size <= maxSizeMB * 1024 * 1024) {
|
|
5
6
|
return file;
|
|
6
7
|
}
|
|
7
8
|
return imageCompression(file, {
|
|
8
9
|
maxSizeMB,
|
|
9
10
|
maxWidthOrHeight,
|
|
10
11
|
useWebWorker: true,
|
|
11
|
-
fileType: file.type
|
|
12
|
+
fileType: outputType ?? file.type
|
|
12
13
|
});
|
|
13
14
|
}
|
|
14
15
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/modules/images/utils/compress-image.ts"],"sourcesContent":["import imageCompression from 'browser-image-compression'\nimport type { CompressImageOptions } from '../types/image.type'\n\nexport async function compressImage(\n file: File,\n options: CompressImageOptions = {}\n): Promise<File> {\n const { maxSizeMB = 1, maxWidthOrHeight = 1920 } = options\n\n if (file.size <= maxSizeMB * 1024 * 1024) {\n return file\n }\n\n return imageCompression(file, {\n maxSizeMB,\n maxWidthOrHeight,\n useWebWorker: true,\n fileType: file.type as 'image/jpeg' | 'image/png' | 'image/webp',\n })\n}\n"],"mappings":"AAAA,OAAO,sBAAsB;AAG7B,eAAsB,cACpB,MACA,UAAgC,CAAC,GAClB;AACf,QAAM,EAAE,YAAY,GAAG,mBAAmB,
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/images/utils/compress-image.ts"],"sourcesContent":["import imageCompression from 'browser-image-compression'\nimport type { CompressImageOptions } from '../types/image.type'\n\nexport async function compressImage(\n file: File,\n options: CompressImageOptions = {}\n): Promise<File> {\n const { maxSizeMB = 1, maxWidthOrHeight = 1920, outputType } = options\n\n const needsConversion = !!outputType && outputType !== file.type\n \n if (!needsConversion && file.size <= maxSizeMB * 1024 * 1024) {\n return file\n }\n\n return imageCompression(file, {\n maxSizeMB,\n maxWidthOrHeight,\n useWebWorker: true,\n fileType: outputType ?? (file.type as 'image/jpeg' | 'image/png' | 'image/webp'),\n })\n}\n"],"mappings":"AAAA,OAAO,sBAAsB;AAG7B,eAAsB,cACpB,MACA,UAAgC,CAAC,GAClB;AACf,QAAM,EAAE,YAAY,GAAG,mBAAmB,MAAM,WAAW,IAAI;AAE/D,QAAM,kBAAkB,CAAC,CAAC,cAAc,eAAe,KAAK;AAE5D,MAAI,CAAC,mBAAmB,KAAK,QAAQ,YAAY,OAAO,MAAM;AAC5D,WAAO;AAAA,EACT;AAEA,SAAO,iBAAiB,MAAM;AAAA,IAC5B;AAAA,IACA;AAAA,IACA,cAAc;AAAA,IACd,UAAU,cAAe,KAAK;AAAA,EAChC,CAAC;AACH;","names":[]}
|
package/package.json
CHANGED
|
@@ -72,6 +72,16 @@ export default function BuyCreditsModal() {
|
|
|
72
72
|
const subscriptionId = subscription?.id;
|
|
73
73
|
const planId = subscription?.id_plan;
|
|
74
74
|
|
|
75
|
+
const buildPlanExtras = useCallback(
|
|
76
|
+
(aiQuantity: number) => [
|
|
77
|
+
...(subscription?.items ?? [])
|
|
78
|
+
.filter((item) => item.id_addon != null && item.id_addon !== ADDON_IDS.AI && Number(item.value ?? 0) > 0)
|
|
79
|
+
.map((item) => ({ id_addon: Number(item.id_addon), quantity: item.quantity ?? 0 })),
|
|
80
|
+
{ id_addon: ADDON_IDS.AI, quantity: aiQuantity },
|
|
81
|
+
],
|
|
82
|
+
[subscription]
|
|
83
|
+
);
|
|
84
|
+
|
|
75
85
|
const form = useForm<BuyCreditFormData>({
|
|
76
86
|
resolver: zodResolver(buyCreditSchema),
|
|
77
87
|
mode: 'onChange',
|
|
@@ -101,9 +111,7 @@ export default function BuyCreditsModal() {
|
|
|
101
111
|
id_product: 1,
|
|
102
112
|
...(planId != null && { id_plan: planId }),
|
|
103
113
|
...(subscriptionId != null && { id_subscription: subscriptionId }),
|
|
104
|
-
plan_extras:
|
|
105
|
-
{ id_addon: ADDON_IDS.AI, quantity: currentCredits },
|
|
106
|
-
],
|
|
114
|
+
plan_extras: buildPlanExtras(currentCredits),
|
|
107
115
|
});
|
|
108
116
|
}, [
|
|
109
117
|
open,
|
|
@@ -114,6 +122,7 @@ export default function BuyCreditsModal() {
|
|
|
114
122
|
calculate,
|
|
115
123
|
planId,
|
|
116
124
|
subscriptionId,
|
|
125
|
+
buildPlanExtras,
|
|
117
126
|
]);
|
|
118
127
|
|
|
119
128
|
// Sync selectedCardId when cards load after modal opened
|
|
@@ -144,12 +153,10 @@ export default function BuyCreditsModal() {
|
|
|
144
153
|
id_product: 1,
|
|
145
154
|
...(planId != null && { id_plan: planId }),
|
|
146
155
|
...(subscriptionId != null && { id_subscription: subscriptionId }),
|
|
147
|
-
plan_extras:
|
|
148
|
-
{ id_addon: ADDON_IDS.AI, quantity: option.credits, currency: 'BRL' },
|
|
149
|
-
],
|
|
156
|
+
plan_extras: buildPlanExtras(option.credits),
|
|
150
157
|
});
|
|
151
158
|
},
|
|
152
|
-
[form, subscriptionId, planId, calculate]
|
|
159
|
+
[form, subscriptionId, planId, calculate, buildPlanExtras]
|
|
153
160
|
);
|
|
154
161
|
|
|
155
162
|
const calculatedData = calculateData?.data ?? null;
|
|
@@ -207,12 +214,7 @@ export default function BuyCreditsModal() {
|
|
|
207
214
|
await updatePlanMutation.mutateAsync({
|
|
208
215
|
subscriptionId,
|
|
209
216
|
data: {
|
|
210
|
-
plan_extras:
|
|
211
|
-
{
|
|
212
|
-
id_addon: ADDON_IDS.AI,
|
|
213
|
-
quantity: option.credits,
|
|
214
|
-
},
|
|
215
|
-
],
|
|
217
|
+
plan_extras: buildPlanExtras(option.credits),
|
|
216
218
|
},
|
|
217
219
|
});
|
|
218
220
|
|
|
@@ -226,7 +228,7 @@ export default function BuyCreditsModal() {
|
|
|
226
228
|
form.reset();
|
|
227
229
|
closeModal();
|
|
228
230
|
},
|
|
229
|
-
[subscriptionId, updatePlanMutation, form, closeModal]
|
|
231
|
+
[subscriptionId, updatePlanMutation, form, closeModal, buildPlanExtras]
|
|
230
232
|
);
|
|
231
233
|
|
|
232
234
|
const renderPriceDisplay = useCallback(() => {
|
|
@@ -147,8 +147,8 @@ export function PaymentInfoCard({
|
|
|
147
147
|
</div>
|
|
148
148
|
|
|
149
149
|
<div
|
|
150
|
-
className={`flex flex-col gap-2 px-4
|
|
151
|
-
isExpanded ? 'max-h-[
|
|
150
|
+
className={`flex flex-col gap-2 px-4 transition-all duration-300 ease-in-out ${
|
|
151
|
+
isExpanded ? 'max-h-[167px] overflow-y-auto pb-4 opacity-100' : 'max-h-0 overflow-hidden pb-0 opacity-0'
|
|
152
152
|
}`}
|
|
153
153
|
>
|
|
154
154
|
{displayedCards.map((card) => (
|
|
@@ -5,9 +5,11 @@ export async function compressImage(
|
|
|
5
5
|
file: File,
|
|
6
6
|
options: CompressImageOptions = {}
|
|
7
7
|
): Promise<File> {
|
|
8
|
-
const { maxSizeMB = 1, maxWidthOrHeight = 1920 } = options
|
|
8
|
+
const { maxSizeMB = 1, maxWidthOrHeight = 1920, outputType } = options
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
const needsConversion = !!outputType && outputType !== file.type
|
|
11
|
+
|
|
12
|
+
if (!needsConversion && file.size <= maxSizeMB * 1024 * 1024) {
|
|
11
13
|
return file
|
|
12
14
|
}
|
|
13
15
|
|
|
@@ -15,6 +17,6 @@ export async function compressImage(
|
|
|
15
17
|
maxSizeMB,
|
|
16
18
|
maxWidthOrHeight,
|
|
17
19
|
useWebWorker: true,
|
|
18
|
-
fileType: file.type as 'image/jpeg' | 'image/png' | 'image/webp',
|
|
20
|
+
fileType: outputType ?? (file.type as 'image/jpeg' | 'image/png' | 'image/webp'),
|
|
19
21
|
})
|
|
20
22
|
}
|