'use client'; import { Slider } from '@gitroom/react/form/slider'; import React, { FC, useCallback, useEffect, useMemo, useState } from 'react'; import { Button } from '@gitroom/react/form/button'; import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; import { Subscription } from '@prisma/client'; import { useDebouncedCallback } from 'use-debounce'; import ReactLoading from '@gitroom/frontend/components/layout/loading'; import { deleteDialog } from '@gitroom/react/helpers/delete.dialog'; import { useToaster } from '@gitroom/react/toaster/toaster'; import dayjs from 'dayjs'; import clsx from 'clsx'; import { pricing } from '@gitroom/nestjs-libraries/database/prisma/subscriptions/pricing'; import { FAQComponent } from '@gitroom/frontend/components/billing/faq.component'; import { useSWRConfig } from 'swr'; import { useUser } from '@gitroom/frontend/components/layout/user.context'; import { useRouter, useSearchParams } from 'next/navigation'; import { useVariables } from '@gitroom/react/helpers/variable.context'; import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import { Textarea } from '@gitroom/react/form/textarea'; import { useFireEvents } from '@gitroom/helpers/utils/use.fire.events'; import { useUtmUrl } from '@gitroom/helpers/utils/utm.saver'; import { useTrack } from '@gitroom/react/helpers/use.track'; import { TrackEnum } from '@gitroom/nestjs-libraries/user/track.enum'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; import { FinishTrial } from '@gitroom/frontend/components/billing/finish.trial'; import { newDayjs } from '@gitroom/frontend/components/layout/set.timezone'; import { useDubClickId } from '@gitroom/frontend/components/layout/dubAnalytics'; import { LogoutComponent } from '@gitroom/frontend/components/layout/logout.component'; export const Prorate: FC<{ period: 'MONTHLY' | 'YEARLY'; pack: 'STANDARD' | 'PRO'; }> = (props) => { const { period, pack } = props; const t = useT(); const fetch = useFetch(); const [price, setPrice] = useState(0); const [loading, setLoading] = useState(false); const calculatePrice = useDebouncedCallback(async () => { setLoading(true); setPrice( ( await ( await fetch('/billing/prorate', { method: 'POST', body: JSON.stringify({ period, billing: pack, }), }) ).json() ).price ); setLoading(false); }, 500); useEffect(() => { setPrice(false); calculatePrice(); }, [period, pack]); if (loading) { return (
); } if (price === false) { return null; } return (
({t('pay_today', 'Pay Today')} ${(price < 0 ? 0 : price)?.toFixed(1)})
); }; export const Features: FC<{ pack: 'FREE' | 'STANDARD' | 'PRO'; }> = (props) => { const { pack } = props; const features = useMemo(() => { const currentPricing = pricing[pack]; const channelsOr = currentPricing.channel; const list = []; list.push(`${channelsOr} ${channelsOr === 1 ? 'channel' : 'channels'}`); list.push( `${ currentPricing.posts_per_month > 10000 ? 'Unlimited' : currentPricing.posts_per_month } posts per month` ); if (currentPricing.team_members) { list.push(`Unlimited team members`); } if (currentPricing?.ai) { list.push(`AI auto-complete`); list.push(`AI copilots`); list.push(`AI Autocomplete`); } list.push(`Advanced Picture Editor`); if (currentPricing?.image_generator) { list.push( `${currentPricing?.image_generation_count} AI Images per month` ); } if (currentPricing?.generate_videos) { list.push(`${currentPricing?.generate_videos} AI Videos per month`); } return list; }, [pack]); return (
{features.map((feature) => (
{feature}
))}
); }; const Accept: FC<{ resolve: (res: boolean) => void }> = ({ resolve }) => { const [loading, setLoading] = useState(false); const fetch = useFetch(); const toaster = useToaster(); const apply = useCallback(async () => { setLoading(true); await fetch('/billing/apply-discount', { method: 'POST', }); resolve(true); toaster.show('50% discount applied successfully'); }, []); return (
Would you accept 50% discount for 3 months instead? 🙏🏻
); }; const Info: FC<{ proceed: (feedback: string) => void; }> = (props) => { const [feedback, setFeedback] = useState(''); const modal = useModals(); const events = useFireEvents(); const cancel = useCallback(() => { props.proceed(feedback); events('cancel_subscription'); modal.closeAll(); }, [modal, feedback]); const t = useT(); return (
{t( 'would_you_mind_shortly_tell_us_what_we_could_have_done_better', 'Would you mind shortly tell us what we could have done better?' )}