Compare commits
7 Commits
@nhost/vue
...
@nhost/das
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c625317342 | ||
|
|
8ab75a4146 | ||
|
|
607f465616 | ||
|
|
668c877130 | ||
|
|
4bd870eb96 | ||
|
|
39b3161d91 | ||
|
|
ae090a6585 |
@@ -1,5 +1,11 @@
|
||||
# @nhost/dashboard
|
||||
|
||||
## 0.14.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 668c8771: chore(dialogs): unify dialog management of payment dialogs
|
||||
|
||||
## 0.14.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost/dashboard",
|
||||
"version": "0.14.7",
|
||||
"version": "0.14.8",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"preinstall": "npx only-allow pnpm",
|
||||
|
||||
@@ -124,13 +124,9 @@ export default function ApplicationPaused() {
|
||||
className="mx-auto w-full max-w-[280px]"
|
||||
onClick={() => {
|
||||
openDialog({
|
||||
title: 'Upgrade your plan.',
|
||||
component: <ChangePlanModal />,
|
||||
props: {
|
||||
PaperProps: { className: 'p-0' },
|
||||
hidePrimaryAction: true,
|
||||
hideSecondaryAction: true,
|
||||
hideTitle: true,
|
||||
maxWidth: 'lg',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { BillingPaymentMethodForm } from '@/components/billing-payment-method/BillingPaymentMethodForm';
|
||||
import { useDialog } from '@/components/common/DialogProvider';
|
||||
import { useUI } from '@/context/UIContext';
|
||||
import { BillingPaymentMethodForm } from '@/components/workspace/BillingPaymentMethodForm';
|
||||
import {
|
||||
refetchGetApplicationPlanQuery,
|
||||
useGetAppPlanAndGlobalPlansQuery,
|
||||
@@ -8,18 +7,19 @@ import {
|
||||
useUpdateApplicationMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { useCurrentWorkspaceAndProject } from '@/hooks/v2/useCurrentWorkspaceAndProject';
|
||||
import { Modal } from '@/ui/Modal';
|
||||
import ActivityIndicator from '@/ui/v2/ActivityIndicator';
|
||||
import Box from '@/ui/v2/Box';
|
||||
import Button from '@/ui/v2/Button';
|
||||
import Checkbox from '@/ui/v2/Checkbox';
|
||||
import { BaseDialog } from '@/ui/v2/Dialog';
|
||||
import Text from '@/ui/v2/Text';
|
||||
import { planDescriptions } from '@/utils/planDescriptions';
|
||||
import { triggerToast } from '@/utils/toast';
|
||||
import { useTheme } from '@mui/material';
|
||||
import getServerError from '@/utils/settings/getServerError/getServerError';
|
||||
import { getToastStyleProps } from '@/utils/settings/settingsConstants';
|
||||
import Image from 'next/image';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useState } from 'react';
|
||||
import { toast } from 'react-hot-toast';
|
||||
|
||||
function Plan({
|
||||
planName,
|
||||
@@ -66,13 +66,15 @@ function Plan({
|
||||
}
|
||||
|
||||
export function ChangePlanModalWithData({ app, plans, close }: any) {
|
||||
const theme = useTheme();
|
||||
const [selectedPlanId, setSelectedPlanId] = useState('');
|
||||
const { closeAlertDialog } = useDialog();
|
||||
|
||||
const { currentWorkspace, currentProject } = useCurrentWorkspaceAndProject();
|
||||
const {
|
||||
currentWorkspace,
|
||||
currentProject,
|
||||
refetch: refetchWorkspaceAndProject,
|
||||
} = useCurrentWorkspaceAndProject();
|
||||
|
||||
// get workspace payment methods
|
||||
const { data } = useGetPaymentMethodsQuery({
|
||||
variables: {
|
||||
workspaceId: currentWorkspace?.id,
|
||||
@@ -80,7 +82,7 @@ export function ChangePlanModalWithData({ app, plans, close }: any) {
|
||||
skip: !currentWorkspace,
|
||||
});
|
||||
|
||||
const { openPaymentModal, closePaymentModal, paymentModal } = useUI();
|
||||
const [showPaymentModal, setShowPaymentModal] = useState(false);
|
||||
const paymentMethodAvailable = data?.paymentMethods.length > 0;
|
||||
|
||||
const currentPlan = plans.find((plan) => plan.id === app.plan.id);
|
||||
@@ -88,7 +90,6 @@ export function ChangePlanModalWithData({ app, plans, close }: any) {
|
||||
|
||||
const isDowngrade = currentPlan.price > selectedPlan?.price;
|
||||
|
||||
// graphql mutations
|
||||
const [updateApp] = useUpdateApplicationMutation({
|
||||
refetchQueries: [
|
||||
refetchGetApplicationPlanQuery({
|
||||
@@ -98,28 +99,35 @@ export function ChangePlanModalWithData({ app, plans, close }: any) {
|
||||
],
|
||||
});
|
||||
|
||||
// function handlers
|
||||
const handleUpdateAppPlan = async () => {
|
||||
await updateApp({
|
||||
variables: {
|
||||
appId: app.id,
|
||||
app: {
|
||||
planId: selectedPlan.id,
|
||||
try {
|
||||
await toast.promise(
|
||||
updateApp({
|
||||
variables: {
|
||||
appId: app.id,
|
||||
app: {
|
||||
planId: selectedPlan.id,
|
||||
},
|
||||
},
|
||||
}),
|
||||
{
|
||||
loading: 'Updating plan...',
|
||||
success: `Plan has been updated successfully to ${selectedPlan.name}.`,
|
||||
error: getServerError(
|
||||
'An error occurred while updating the plan. Please try again.',
|
||||
),
|
||||
},
|
||||
},
|
||||
});
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
if (isDowngrade) {
|
||||
if (close) {
|
||||
close();
|
||||
}
|
||||
await refetchWorkspaceAndProject();
|
||||
|
||||
close?.();
|
||||
closeAlertDialog();
|
||||
setShowPaymentModal(false);
|
||||
} catch (error) {
|
||||
// Note: Error is handled by the toast.
|
||||
}
|
||||
|
||||
triggerToast(
|
||||
`${currentProject.name} plan changed to ${selectedPlan.name}.`,
|
||||
);
|
||||
};
|
||||
|
||||
const handleChangePlanClick = async () => {
|
||||
@@ -128,33 +136,30 @@ export function ChangePlanModalWithData({ app, plans, close }: any) {
|
||||
}
|
||||
|
||||
if (!paymentMethodAvailable) {
|
||||
openPaymentModal();
|
||||
setShowPaymentModal(true);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await handleUpdateAppPlan();
|
||||
|
||||
if (close) {
|
||||
close();
|
||||
}
|
||||
|
||||
setShowPaymentModal(false);
|
||||
close?.();
|
||||
closeAlertDialog();
|
||||
};
|
||||
|
||||
return (
|
||||
<Box className="w-full max-w-xl rounded-lg p-6 text-left">
|
||||
<Modal
|
||||
showModal={paymentModal}
|
||||
close={closePaymentModal}
|
||||
dialogStyle={{ zIndex: theme.zIndex.modal + 1 }}
|
||||
<BaseDialog
|
||||
open={showPaymentModal}
|
||||
onClose={() => setShowPaymentModal(false)}
|
||||
>
|
||||
<BillingPaymentMethodForm
|
||||
close={closePaymentModal}
|
||||
onPaymentMethodAdded={handleUpdateAppPlan}
|
||||
workspaceId={currentWorkspace.id}
|
||||
/>
|
||||
</Modal>
|
||||
</BaseDialog>
|
||||
|
||||
<div className="flex flex-col">
|
||||
<div className="mx-auto">
|
||||
<Image
|
||||
@@ -217,14 +222,12 @@ export function ChangePlanModalWithData({ app, plans, close }: any) {
|
||||
|
||||
export interface ChangePlanModalProps {
|
||||
/**
|
||||
* Function to close the modal if mounted on parent component.
|
||||
*
|
||||
* @deprecated Implement modal by using `openAlertDialog` hook instead.
|
||||
* Function to close the modal.
|
||||
*/
|
||||
close?: () => void;
|
||||
onCancel?: () => void;
|
||||
}
|
||||
|
||||
export function ChangePlanModal({ close }: ChangePlanModalProps) {
|
||||
export function ChangePlanModal({ onCancel }: ChangePlanModalProps) {
|
||||
const {
|
||||
query: { workspaceSlug, appSlug },
|
||||
} = useRouter();
|
||||
@@ -250,5 +253,5 @@ export function ChangePlanModal({ close }: ChangePlanModalProps) {
|
||||
const { apps, plans } = data;
|
||||
const app = apps[0];
|
||||
|
||||
return <ChangePlanModalWithData app={app} plans={plans} close={close} />;
|
||||
return <ChangePlanModalWithData app={app} plans={plans} close={onCancel} />;
|
||||
}
|
||||
|
||||
@@ -30,13 +30,9 @@ export function UnlockFeatureByUpgrading({
|
||||
variant="borderless"
|
||||
onClick={() => {
|
||||
openDialog({
|
||||
title: 'Upgrade your plan.',
|
||||
component: <ChangePlanModal />,
|
||||
props: {
|
||||
PaperProps: { className: 'p-0 max-w-xl w-full' },
|
||||
hidePrimaryAction: true,
|
||||
hideSecondaryAction: true,
|
||||
hideTitle: true,
|
||||
},
|
||||
});
|
||||
}}
|
||||
|
||||
@@ -22,7 +22,7 @@ export interface OpenDialogOptions {
|
||||
/**
|
||||
* Title of the dialog.
|
||||
*/
|
||||
title: ReactNode;
|
||||
title?: ReactNode;
|
||||
/**
|
||||
* Component to render inside the dialog skeleton.
|
||||
*/
|
||||
|
||||
@@ -22,6 +22,13 @@ export function CountrySelector({ value, onChange }: CountrySelectorProps) {
|
||||
value={value || null}
|
||||
onChange={(_event, inputValue) => onChange(inputValue as string)}
|
||||
placeholder="Select Country"
|
||||
slotProps={{
|
||||
listbox: { className: 'min-w-0 w-full' },
|
||||
popper: {
|
||||
disablePortal: false,
|
||||
className: 'z-[10000] w-[270px] w-full',
|
||||
},
|
||||
}}
|
||||
>
|
||||
{countries?.map((country) => (
|
||||
<Option key={country.name} value={country.code}>
|
||||
|
||||
@@ -93,13 +93,9 @@ export default function OverviewTopBar() {
|
||||
className="mr-2"
|
||||
onClick={() => {
|
||||
openDialog({
|
||||
title: 'Upgrade your plan.',
|
||||
component: <ChangePlanModal />,
|
||||
props: {
|
||||
PaperProps: { className: 'p-0 max-w-xl w-full' },
|
||||
hidePrimaryAction: true,
|
||||
hideSecondaryAction: true,
|
||||
hideTitle: true,
|
||||
},
|
||||
});
|
||||
}}
|
||||
|
||||
@@ -42,7 +42,7 @@ function AlertDialog({
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
{!hideTitle && (
|
||||
{!hideTitle && !!title && (
|
||||
<Dialog.Title {...titleProps} id="alert-dialog-title">
|
||||
{title}
|
||||
</Dialog.Title>
|
||||
|
||||
@@ -22,7 +22,7 @@ function Dialog({
|
||||
aria-describedby="dialog-description"
|
||||
{...props}
|
||||
>
|
||||
{!hideTitle && (
|
||||
{!hideTitle && !!title && (
|
||||
<DialogTitle
|
||||
sx={{
|
||||
padding: (theme) => theme.spacing(3, 3, 1.5, 3),
|
||||
|
||||
@@ -16,7 +16,7 @@ export interface CommonDialogProps
|
||||
/**
|
||||
* The title of the dialog.
|
||||
*/
|
||||
title: ReactNode;
|
||||
title?: ReactNode;
|
||||
/**
|
||||
* The message to display in the dialog.
|
||||
*/
|
||||
|
||||
@@ -27,13 +27,11 @@ const stripePromise = process.env.NEXT_PUBLIC_STRIPE_PK
|
||||
: null;
|
||||
|
||||
type AddPaymentMethodFormProps = {
|
||||
close: () => void;
|
||||
onPaymentMethodAdded?: () => Promise<void>;
|
||||
onPaymentMethodAdded?: () => void;
|
||||
workspaceId: string;
|
||||
};
|
||||
|
||||
function AddPaymentMethodForm({
|
||||
close,
|
||||
onPaymentMethodAdded,
|
||||
workspaceId,
|
||||
}: AddPaymentMethodFormProps) {
|
||||
@@ -141,9 +139,7 @@ function AddPaymentMethodForm({
|
||||
|
||||
// payment method added successfylly
|
||||
|
||||
triggerToast(`New payment method added`);
|
||||
|
||||
close();
|
||||
triggerToast('New payment method has been added to the workspace.');
|
||||
|
||||
discordAnnounce(
|
||||
`(${user.email}) added a new credit card to workspace id: ${workspaceId}.`,
|
||||
@@ -205,26 +201,27 @@ function AddPaymentMethodForm({
|
||||
);
|
||||
}
|
||||
|
||||
type BillingPaymentMethodFormProps = {
|
||||
close: () => void;
|
||||
onPaymentMethodAdded?: (e?: any) => Promise<void>;
|
||||
export interface BillingPaymentMethodFormProps {
|
||||
/**
|
||||
* Callback function to run after a payment method is added.
|
||||
*/
|
||||
onPaymentMethodAdded?: (e?: any) => void;
|
||||
/**
|
||||
* Workspace identifier.
|
||||
*/
|
||||
workspaceId: string;
|
||||
};
|
||||
}
|
||||
|
||||
export function BillingPaymentMethodForm({
|
||||
close,
|
||||
export default function BillingPaymentMethodForm({
|
||||
onPaymentMethodAdded,
|
||||
workspaceId,
|
||||
}: BillingPaymentMethodFormProps) {
|
||||
return (
|
||||
<Elements stripe={stripePromise}>
|
||||
<AddPaymentMethodForm
|
||||
close={close}
|
||||
onPaymentMethodAdded={onPaymentMethodAdded}
|
||||
workspaceId={workspaceId}
|
||||
/>
|
||||
</Elements>
|
||||
);
|
||||
}
|
||||
|
||||
export default BillingPaymentMethodForm;
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './BillingPaymentMethodForm';
|
||||
export { default as BillingPaymentMethodForm } from './BillingPaymentMethodForm';
|
||||
@@ -1,5 +1,5 @@
|
||||
import { BillingPaymentMethodForm } from '@/components/billing-payment-method/BillingPaymentMethodForm';
|
||||
import { useDialog } from '@/components/common/DialogProvider';
|
||||
import { BillingPaymentMethodForm } from '@/components/workspace/BillingPaymentMethodForm';
|
||||
import type { GetPaymentMethodsFragment } from '@/generated/graphql';
|
||||
import {
|
||||
refetchGetPaymentMethodsQuery,
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
useSetNewDefaultPaymentMethodMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { useCurrentWorkspaceAndProject } from '@/hooks/v2/useCurrentWorkspaceAndProject';
|
||||
import { Modal } from '@/ui/Modal';
|
||||
import ActivityIndicator from '@/ui/v2/ActivityIndicator';
|
||||
import Button from '@/ui/v2/Button';
|
||||
import Table from '@/ui/v2/Table';
|
||||
@@ -21,8 +20,6 @@ import Text from '@/ui/v2/Text';
|
||||
import { triggerToast } from '@/utils/toast';
|
||||
import { useTheme } from '@mui/material';
|
||||
import { formatDistanceToNowStrict } from 'date-fns';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useState } from 'react';
|
||||
|
||||
function CheckCircle() {
|
||||
const theme = useTheme();
|
||||
@@ -44,15 +41,8 @@ function CheckCircle() {
|
||||
}
|
||||
|
||||
export default function WorkspacePaymentMethods() {
|
||||
const router = useRouter();
|
||||
const { action } = router.query;
|
||||
|
||||
const { currentWorkspace } = useCurrentWorkspaceAndProject();
|
||||
const { openAlertDialog } = useDialog();
|
||||
|
||||
const [showAddPaymentMethodModal, setShowAddPaymentMethodModal] = useState(
|
||||
action === 'add-payment-method',
|
||||
);
|
||||
const { openAlertDialog, openDialog, closeDialog } = useDialog();
|
||||
|
||||
const { loading, error, data } = useGetPaymentMethodsQuery({
|
||||
variables: {
|
||||
@@ -230,7 +220,14 @@ export default function WorkspacePaymentMethods() {
|
||||
<Button
|
||||
variant="outlined"
|
||||
onClick={() => {
|
||||
setShowAddPaymentMethodModal(true);
|
||||
openDialog({
|
||||
component: (
|
||||
<BillingPaymentMethodForm
|
||||
workspaceId={currentWorkspace.id}
|
||||
onPaymentMethodAdded={closeDialog}
|
||||
/>
|
||||
),
|
||||
});
|
||||
}}
|
||||
disabled={maxPaymentMethodsReached}
|
||||
>
|
||||
@@ -244,19 +241,6 @@ export default function WorkspacePaymentMethods() {
|
||||
payment methods.
|
||||
</Text>
|
||||
)}
|
||||
{showAddPaymentMethodModal && (
|
||||
<Modal
|
||||
showModal={showAddPaymentMethodModal}
|
||||
close={() =>
|
||||
setShowAddPaymentMethodModal(!showAddPaymentMethodModal)
|
||||
}
|
||||
>
|
||||
<BillingPaymentMethodForm
|
||||
workspaceId={currentWorkspace.id}
|
||||
close={() => setShowAddPaymentMethodModal(false)}
|
||||
/>
|
||||
</Modal>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { useRouter } from 'next/router';
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import { createContext, useContext, useMemo, useReducer } from 'react';
|
||||
import { createContext, useContext, useMemo } from 'react';
|
||||
|
||||
export interface UIContextState {
|
||||
paymentModal: boolean;
|
||||
/**
|
||||
* Determines whether or not the dashboard is in maintenance mode.
|
||||
*/
|
||||
@@ -12,42 +11,18 @@ export interface UIContextState {
|
||||
* The date and time when maintenance mode will end.
|
||||
*/
|
||||
maintenanceEndDate: Date;
|
||||
openPaymentModal: () => void;
|
||||
closePaymentModal: () => void;
|
||||
}
|
||||
|
||||
const initialState: UIContextState = {
|
||||
paymentModal: false,
|
||||
export const UIContext = createContext<UIContextState>({
|
||||
maintenanceActive: false,
|
||||
maintenanceEndDate: null,
|
||||
openPaymentModal: () => {},
|
||||
closePaymentModal: () => {},
|
||||
};
|
||||
|
||||
export const UIContext = createContext<UIContextState>(initialState);
|
||||
});
|
||||
|
||||
UIContext.displayName = 'UIContext';
|
||||
|
||||
function sideReducer(state: any, action: any) {
|
||||
switch (action.type) {
|
||||
case 'TOGGLE_PAYMENT_MODAL': {
|
||||
return {
|
||||
...state,
|
||||
paymentModal: !state.paymentModal,
|
||||
};
|
||||
}
|
||||
default:
|
||||
return { ...state };
|
||||
}
|
||||
}
|
||||
|
||||
export function UIProvider(props: PropsWithChildren<unknown>) {
|
||||
const [state, dispatch] = useReducer(sideReducer, initialState);
|
||||
const router = useRouter();
|
||||
|
||||
const openPaymentModal = () => dispatch({ type: 'TOGGLE_PAYMENT_MODAL' });
|
||||
const closePaymentModal = () => dispatch({ type: 'TOGGLE_PAYMENT_MODAL' });
|
||||
|
||||
const maintenanceUnlocked =
|
||||
process.env.NEXT_PUBLIC_MAINTENANCE_UNLOCK_SECRET &&
|
||||
process.env.NEXT_PUBLIC_MAINTENANCE_UNLOCK_SECRET ===
|
||||
@@ -55,9 +30,6 @@ export function UIProvider(props: PropsWithChildren<unknown>) {
|
||||
|
||||
const value: UIContextState = useMemo(
|
||||
() => ({
|
||||
...state,
|
||||
openPaymentModal,
|
||||
closePaymentModal,
|
||||
maintenanceActive: maintenanceUnlocked
|
||||
? false
|
||||
: process.env.NEXT_PUBLIC_MAINTENANCE_ACTIVE === 'true',
|
||||
@@ -67,7 +39,7 @@ export function UIProvider(props: PropsWithChildren<unknown>) {
|
||||
? new Date(Date.parse(process.env.NEXT_PUBLIC_MAINTENANCE_END_DATE))
|
||||
: null,
|
||||
}),
|
||||
[state, maintenanceUnlocked],
|
||||
[maintenanceUnlocked],
|
||||
);
|
||||
|
||||
return <UIContext.Provider value={value} {...props} />;
|
||||
|
||||
@@ -234,7 +234,6 @@ export default function SettingsGeneralPage() {
|
||||
disabled: maintenanceActive,
|
||||
onClick: () => {
|
||||
openDialog({
|
||||
title: '',
|
||||
component: (
|
||||
<RemoveApplicationModal
|
||||
close={closeDialog}
|
||||
@@ -243,7 +242,6 @@ export default function SettingsGeneralPage() {
|
||||
),
|
||||
props: {
|
||||
PaperProps: { className: 'max-w-sm' },
|
||||
hideTitle: true,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { BillingPaymentMethodForm } from '@/components/billing-payment-method/BillingPaymentMethodForm';
|
||||
import { useDialog } from '@/components/common/DialogProvider';
|
||||
import AuthenticatedLayout from '@/components/layout/AuthenticatedLayout';
|
||||
import Container from '@/components/layout/Container';
|
||||
import { BillingPaymentMethodForm } from '@/components/workspace/BillingPaymentMethodForm';
|
||||
import { useUI } from '@/context/UIContext';
|
||||
import features from '@/data/features.json';
|
||||
import { useSubmitState } from '@/hooks/useSubmitState';
|
||||
import { Alert } from '@/ui/Alert';
|
||||
import { Modal } from '@/ui/Modal';
|
||||
import ActivityIndicator from '@/ui/v2/ActivityIndicator';
|
||||
import Box from '@/ui/v2/Box';
|
||||
import Button from '@/ui/v2/Button';
|
||||
@@ -44,7 +44,7 @@ import type { ApolloError } from '@apollo/client';
|
||||
import { useUserData } from '@nhost/nextjs';
|
||||
import Image from 'next/image';
|
||||
import { useRouter } from 'next/router';
|
||||
import type { ReactElement } from 'react';
|
||||
import type { FormEvent, ReactElement } from 'react';
|
||||
import { cloneElement, isValidElement, useState } from 'react';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import slugify from 'slugify';
|
||||
@@ -67,6 +67,7 @@ export function NewProjectPageContent({
|
||||
preSelectedWorkspace,
|
||||
preSelectedRegion,
|
||||
}: NewAppPageProps) {
|
||||
const { openDialog, closeDialog } = useDialog();
|
||||
const { maintenanceActive } = useUI();
|
||||
const router = useRouter();
|
||||
|
||||
@@ -102,11 +103,7 @@ export function NewProjectPageContent({
|
||||
|
||||
const [plan, setPlan] = useState(defaultSelectedPlan);
|
||||
|
||||
// state
|
||||
const { submitState, setSubmitState } = useSubmitState();
|
||||
const [showPaymentModal, setShowPaymentModal] = useState(false);
|
||||
|
||||
// graphql mutations
|
||||
|
||||
const [insertApp] = useInsertApplicationMutation({
|
||||
refetchQueries: [GetAllWorkspacesAndProjectsDocument],
|
||||
@@ -146,13 +143,8 @@ export function NewProjectPageContent({
|
||||
setDatabasePassword(newRandomDatabasePassword);
|
||||
};
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (!plan.isFree && workspace.paymentMethods.length === 0) {
|
||||
setShowPaymentModal(true);
|
||||
return;
|
||||
}
|
||||
async function handleCreateProject(event: FormEvent) {
|
||||
event.preventDefault();
|
||||
|
||||
setSubmitState({
|
||||
error: null,
|
||||
@@ -225,7 +217,29 @@ export function NewProjectPageContent({
|
||||
loading: false,
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async function handleSubmit(event: FormEvent) {
|
||||
event.preventDefault();
|
||||
|
||||
if (!plan.isFree && workspace.paymentMethods.length === 0) {
|
||||
openDialog({
|
||||
component: (
|
||||
<BillingPaymentMethodForm
|
||||
onPaymentMethodAdded={() => {
|
||||
handleCreateProject(event);
|
||||
closeDialog();
|
||||
}}
|
||||
workspaceId={workspace.id}
|
||||
/>
|
||||
),
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
handleCreateProject(event);
|
||||
}
|
||||
|
||||
if (!selectedWorkspace) {
|
||||
return (
|
||||
@@ -288,7 +302,13 @@ export function NewProjectPageContent({
|
||||
const workspaceInList = workspaces.find(
|
||||
({ id }) => id === value,
|
||||
);
|
||||
setPlan(plans[0]);
|
||||
|
||||
if (numberOfFreeAndLiveProjects >= MAX_FREE_PROJECTS) {
|
||||
setPlan(plans.find((currentPlan) => !currentPlan.isFree));
|
||||
} else {
|
||||
setPlan(plans[0]);
|
||||
}
|
||||
|
||||
setSelectedWorkspace({
|
||||
id: workspaceInList.id,
|
||||
name: workspaceInList.name,
|
||||
@@ -561,23 +581,6 @@ export function NewProjectPageContent({
|
||||
)}
|
||||
|
||||
<div className="flex justify-end">
|
||||
{showPaymentModal && (
|
||||
<Modal
|
||||
showModal={showPaymentModal}
|
||||
close={() => {
|
||||
setShowPaymentModal(false);
|
||||
}}
|
||||
>
|
||||
<BillingPaymentMethodForm
|
||||
close={() => {
|
||||
setShowPaymentModal(false);
|
||||
}}
|
||||
onPaymentMethodAdded={handleSubmit}
|
||||
workspaceId={workspace.id}
|
||||
/>
|
||||
</Modal>
|
||||
)}
|
||||
|
||||
<Button
|
||||
type="submit"
|
||||
loading={submitState.loading}
|
||||
@@ -597,7 +600,9 @@ export default function NewProjectPage() {
|
||||
const router = useRouter();
|
||||
const user = useUserData();
|
||||
|
||||
const { data, loading, error } = usePrefetchNewAppQuery();
|
||||
const { data, loading, error } = usePrefetchNewAppQuery({
|
||||
fetchPolicy: 'cache-and-network',
|
||||
});
|
||||
|
||||
const {
|
||||
data: freeAndActiveProjectsData,
|
||||
|
||||
Reference in New Issue
Block a user