Skip to content

Commit

Permalink
feat: form card makover
Browse files Browse the repository at this point in the history
  • Loading branch information
ephraimduncan committed Feb 21, 2024
1 parent 656b15e commit f8390c0
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 69 deletions.
4 changes: 2 additions & 2 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ const config = {
plugins: ["@typescript-eslint"],
extends: [
"plugin:@next/next/recommended",
"plugin:@typescript-eslint/recommended-type-checked",
"plugin:@typescript-eslint/stylistic-type-checked",
// "plugin:@typescript-eslint/recommended-type-checked",
// "plugin:@typescript-eslint/stylistic-type-checked",
],
rules: {
// These opinionated rules are enabled in stylistic-type-checked above.
Expand Down
Binary file modified bun.lockb
Binary file not shown.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
"arctic": "^1.1.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"data-fns": "^1.1.0",
"date-fns": "^3.3.1",
"drizzle-orm": "^0.29.3",
"json-to-zod": "^1.1.2",
"lucia": "3.0.0",
Expand Down
15 changes: 10 additions & 5 deletions src/app/(main)/dashboard/_components/delete-form-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,19 @@ export function DeleteFormDialog({ formId }: DeleteFormDialogProps) {
const [open, setOpen] = React.useState(false);

const router = useRouter();
const deleteFormMutation = api.form.delete.useMutation();
const { mutateAsync: deleteForm } = api.form.delete.useMutation();

const handleDelete = async () => {
deleteFormMutation.mutate(
{ id: formId },
await deleteForm(
{
id: formId,
},
{
onSuccess: () => {
router.refresh();
toast.success("Form deleted successfully");
toast.success("Your form has been deleted", {
icon: <TrashIcon className="h-4 w-4" />,
});
},
},
);
Expand All @@ -39,8 +43,9 @@ export function DeleteFormDialog({ formId }: DeleteFormDialogProps) {
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<div className="group rounded-md bg-gray-100 p-2 hover:cursor-pointer dark:bg-gray-900">
<div className="group flex items-center gap-2 rounded-md hover:cursor-pointer dark:bg-gray-900">
<TrashIcon className="h-4 w-4 duration-300 group-hover:text-red-500 dark:text-white" />
<span className="hover:text-red-500">Delete</span>
</div>
</DialogTrigger>
<DialogContent className="sm:max-w-[425px]">
Expand Down
108 changes: 52 additions & 56 deletions src/app/(main)/dashboard/_components/form-card.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import { CopyIcon } from "@radix-ui/react-icons";
import Link from "next/link";
import { toast } from "sonner";

import {
Card,
CardContent,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { type RouterOutputs } from "@/trpc/shared";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import type { RouterOutputs } from "@/trpc/shared";

import { DeleteFormDialog } from "./delete-form-dialog";
import { CopyIcon } from "lucide-react";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Button } from "@/components/ui/button";
import { DotsVerticalIcon } from "@radix-ui/react-icons";
import { formatDistanceToNow } from "date-fns";

type FormCardProp = {
form: RouterOutputs["form"]["userForms"][number];
Expand All @@ -26,56 +29,49 @@ export function FormCard({ form }: FormCardProp) {
};

return (
<Card>
<CardHeader>
<div className="flex items-center justify-between">
<div>
<CardTitle className="text-lg">{form.title}</CardTitle>
<div className="flex items-center gap-2">
<p className="text-sm text-muted-foreground">{form.id}</p>
<CopyIcon
className="h-4 w-4 cursor-pointer text-muted-foreground transition-transform hover:scale-110 hover:transform"
onClick={handleCopyAction}
/>
<Link href={`/form/${form.id}`} className="text-sm underline-offset-2">
<Card>
<CardHeader>
<div className="flex items-start justify-between">
<div>
<CardTitle className="text-lg">{form.title}</CardTitle>
<div className="mt-0.5 flex items-center gap-2">
<span className="inline-flex items-center rounded bg-muted px-2 py-0.5 text-xs text-muted-foreground">
{form.id}
</span>
<CopyIcon
className="h-3.5 w-3.5 cursor-pointer text-muted-foreground transition-transform hover:scale-110 hover:transform"
onClick={handleCopyAction}
/>
</div>
</div>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="h-8 w-8 p-0">
<span className="sr-only">Open Form menu</span>
<DotsVerticalIcon className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem>
<DeleteFormDialog formId={form.id} />
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
<DeleteFormDialog formId={form.id} />
</div>
</CardHeader>
<CardContent>
<h3 className="mb-4 font-semibold text-muted-foreground">
Submissions
</h3>
<div className="flex flex-col gap-3">
<div className="flex items-center justify-between">
<p className="text-sm text-muted-foreground">
<span className="text-muted-foreground">Monthly</span>
</p>
<p>343</p>
</div>
<div className="flex items-center justify-between">
<p className="text-sm text-muted-foreground">Last month</p>
<p>24</p>
</div>
<div className="flex items-center justify-between">
<p className="text-sm text-muted-foreground">All time</p>
<p>531</p>
</div>
</div>
</CardContent>
<CardFooter className="flex items-center justify-between">
<div className="flex items-center gap-1">
</CardHeader>

<CardContent>
<p className="mb-1 text-sm text-muted-foreground">10 submissions</p>

<p className="text-sm text-muted-foreground">
Last submission: 2/12/2021
Last submission:{" "}
{formatDistanceToNow(new Date(form.createdAt), {
addSuffix: true,
})}
</p>
</div>
<Link
href={`/form/s/${form.id}`}
className="text-sm underline underline-offset-2"
>
View all
</Link>
</CardFooter>
</Card>
</CardContent>
</Card>
</Link>
);
}
4 changes: 1 addition & 3 deletions src/app/(main)/dashboard/_components/forms.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ export function Forms({ promises }: FormsProps) {

return (
<div className="space-y-8">
<Input placeholder="Search for your form by name or id" />

<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
<div className="grid grid-cols-1 gap-6 md:grid-cols-3">
{forms.map((form) => (
<FormCard form={form} key={form.id} />
))}
Expand Down
5 changes: 3 additions & 2 deletions src/app/(main)/dashboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,16 @@ export default async function DashboardPage() {

return (
<div className="py-10 md:py-8">
<div className="mb-10 flex w-full items-center justify-between">
<div className="mb-10 flex w-full items-end justify-between">
<div className="flex flex-col gap-1">
<h1 className="text-3xl font-bold md:text-4xl">Forms</h1>
<h1 className="text-3xl font-bold">Forms</h1>
<p className="text-sm text-muted-foreground">
Manage your forms here
</p>
</div>
<CreateFormDialog />
</div>

<React.Suspense fallback={<PostsSkeleton />}>
<Forms promises={promises} />
</React.Suspense>
Expand Down
2 changes: 1 addition & 1 deletion src/server/api/routers/stripe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const stripeRouter = createTRPCRouter({
? formatPrice((proPrice.unit_amount ?? 0) / 100, {
currency: proPrice.currency,
})
: formatPrice(0 / 100, { currency: proPrice.currency }),
: formatPrice(0, { currency: proPrice.currency }),
};
});
} catch (err) {
Expand Down

0 comments on commit f8390c0

Please sign in to comment.