Skip to content

Commit

Permalink
feat: create project from dashboard home page
Browse files Browse the repository at this point in the history
  • Loading branch information
devrsi0n committed Aug 17, 2023
1 parent c39aabe commit fdea75e
Show file tree
Hide file tree
Showing 11 changed files with 57 additions and 114 deletions.
1 change: 0 additions & 1 deletion apps/main/src/pages/create.tsx

This file was deleted.

1 change: 0 additions & 1 deletion apps/main/src/pages/dashboard/[username]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ export const getStaticProps: GetStaticProps<StaticProps, PathParams> = async ({
return {
props: {
projects,
username,
},
revalidate: 60,
};
Expand Down
1 change: 1 addition & 0 deletions apps/main/src/pages/dashboard/project/new.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { New as default } from '@chirpy-dev/ui';
1 change: 1 addition & 0 deletions apps/main/src/pages/new.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { New as default } from '@chirpy-dev/ui';
1 change: 1 addition & 0 deletions packages/trpc/src/router/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export const projectRouter = router({
z.object({
name: z.string(),
domain: z.string(),
queryParameters: z.string().optional(),
teamId: z.string().nullish(),
}),
)
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/blocks/pricing/pricing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export function PricingCards({
}: PricingCardsProps) {
const router = useRouter();
const handleClickCTA = () => {
router.push('/auth/sign-in');
router.push('/new');
};
const hobby = getPlanPrice('HOBBY');
const pro = getPlanPrice('PRO');
Expand Down
116 changes: 8 additions & 108 deletions packages/ui/src/pages/dashboard/home.tsx
Original file line number Diff line number Diff line change
@@ -1,75 +1,23 @@
import { RouterOutputs, trpc } from '@chirpy-dev/trpc/src/client';
import { RouterOutputs } from '@chirpy-dev/trpc/src/client';
import { useRouter } from 'next/router';
import * as React from 'react';

import {
EmptyProjectCard,
PageTitle,
ProjectCard,
SiteLayout,
} from '../../blocks';
import { Button, Dialog, Spinner, TextField } from '../../components';
import { Spinner } from '../../components';
import { useCurrentUser } from '../../contexts';
import { useForm } from '../../hooks';
import { isValidDomain } from '../../utilities';
import { CreateProjectButton } from './create-project-button';

type FormFields = {
name: string;
domain: string;
};

export type DashboardProps = {
username: string;
projects: RouterOutputs['project']['all'];
};

export function DashboardHome({
projects,
username,
}: DashboardProps): JSX.Element {
const { loading: userIsLoading } = useCurrentUser();

const { mutateAsync: createAProject } = trpc.project.create.useMutation();
const handleCreateProject = React.useCallback(() => {
setShowDialog(true);
}, []);
const [showDialog, setShowDialog] = React.useState(false);

const handleCloseDialog = React.useCallback(() => {
setShowDialog(false);
}, []);
const { register, errors, handleSubmit, hasError, setError } =
useForm<FormFields>({
defaultValues: {
name: '',
domain: '',
},
});
const { mutateAsync: revalidate } = trpc.revalidate.url.useMutation();
export function DashboardHome({ projects }: DashboardProps): JSX.Element {
const { loading } = useCurrentUser();
const router = useRouter();
const handleClickSubmit = handleSubmit(
async (fields, _event: unknown): Promise<void> => {
try {
await createAProject({
// TODO: Team id?
name: fields.name,
domain: fields.domain,
});
await revalidate({
url: `/dashboard/${username}`,
});
setShowDialog(false);
router.push(`/dashboard/${username}/${fields.domain}/get-started`);
} catch (error: unknown) {
if ((error as Error)?.message?.includes('Unique constraint')) {
setError('domain', 'A project associated with this domain already');
return;
}
throw error;
}
},
);

return (
<SiteLayout title="Dashboard">
Expand All @@ -78,7 +26,9 @@ export function DashboardHome({
<PageTitle>Dashboard</PageTitle>
<CreateProjectButton
projectCount={projects?.length}
onCreateProject={handleCreateProject}
onCreateProject={() => {
router.push(`/dashboard/project/new`);
}}
/>
</div>
{projects?.length ? (
Expand All @@ -89,64 +39,14 @@ export function DashboardHome({
</li>
))}
</ul>
) : userIsLoading ? (
) : loading ? (
<Spinner />
) : (
<div className="py-6">
<EmptyProjectCard />
</div>
)}
</section>
<Dialog show={showDialog} title="New project" onClose={handleCloseDialog}>
<Dialog.Body>
<form className="flex w-80 flex-col space-y-4">
<TextField
{...register('name', {
required: { value: true, message: 'Name is required' },
pattern: {
value: /^\w+$/,
message: `Only word characters are allowed`,
},
minLength: { value: 1, message: 'At least 1 characters' },
maxLength: { value: 16, message: 'At most 16 characters' },
})}
aria-label="Name of this project"
label="Name"
errorMessage={errors.name}
placeholder="swift"
className="w-full"
/>
<TextField
{...register('domain', {
required: { value: true, message: 'Domain is required' },
pattern: {
value: isValidDomain,
message: 'Invalid domain',
},
})}
label="Domain"
hintText="Associate your domain with this project"
errorMessage={errors.domain}
placeholder="example.com"
className="w-full"
/>
</form>
</Dialog.Body>
<Dialog.Footer>
<Button onClick={handleCloseDialog} className="w-full sm:w-auto">
Cancel
</Button>
<Button
className="w-full sm:w-auto"
disabled={hasError}
color="primary"
variant="solid"
onClick={handleClickSubmit}
>
Create
</Button>
</Dialog.Footer>
</Dialog>
</SiteLayout>
);
}
42 changes: 42 additions & 0 deletions packages/ui/src/pages/dashboard/project/new.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { trpc } from '@chirpy-dev/trpc/src/client';
import { useRouter } from 'next/router';

import { useToast } from '../../../components';
import { useCurrentUser } from '../../../contexts';
import { MUTATION_ERROR } from '../../../strings';
import { logger } from '../../../utilities/logger';
import { CreateProject } from '../../new';

export function New(): JSX.Element {
const router = useRouter();
const { mutateAsync: createAProject } = trpc.project.create.useMutation();
const { mutateAsync: revalidate } = trpc.revalidate.url.useMutation();
const { showToast } = useToast();
const { data } = useCurrentUser();
return (
<CreateProject
onSubmit={async (fields) => {
try {
await createAProject({
// TODO: Team id?
...fields,
});
await revalidate({
url: `/dashboard/${data?.username}`,
});
router.push(
`/dashboard/${data?.username}/${fields.domain}/get-started`,
);
} catch (error: unknown) {
logger.error('Create project failed', error as Error);
showToast({
type: 'error',
title: `Create project failed`,
description: MUTATION_ERROR,
});
throw error;
}
}}
/>
);
}
2 changes: 1 addition & 1 deletion packages/ui/src/pages/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export function HomePage({ buildDate }: HomeProps): JSX.Element {
{strings.heroDescription}
</Text>
<div className="flex items-center justify-center space-x-6">
<Link variant="plain" href="/auth/sign-in" tabIndex={-1}>
<Link variant="plain" href="/new" tabIndex={-1}>
<Button
variant="solid"
color="primary"
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/pages/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ export * from './widget';
export * from './play';
export * from './privacy-policy';
export * from './terms-of-service';
export * from './create';
export * from './new';
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ type FormFields = {
domain: string;
queryParameters: string;
};
export function Create(): JSX.Element {
export function New(): JSX.Element {
// Just save it, we'll create the project after user login
const [savedFields, setSavedFields] = useLocalStorage<FormFields>(
{
Expand Down

0 comments on commit fdea75e

Please sign in to comment.