Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
marekzelinka committed Dec 6, 2024
1 parent 1345f51 commit 2392fa8
Show file tree
Hide file tree
Showing 11 changed files with 251 additions and 231 deletions.
17 changes: 17 additions & 0 deletions app/components/loading-overlay..tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { ReactNode } from "react";
import { useNavigation } from "react-router";
import { useSpinDelay } from "spin-delay";

export function LoadingOverlay({ children }: { children?: ReactNode }) {
const navigation = useNavigation();
const isLoading = navigation.state === "loading";
const isSearching = new URLSearchParams(navigation.location?.search).has("q");

const shouldShow = useSpinDelay(isLoading && !isSearching);

return (
<div className={shouldShow ? "opacity-50 transition-opacity" : undefined}>
{children}
</div>
);
}
158 changes: 81 additions & 77 deletions app/routes/_auth.join.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { getZodConstraint, parseWithZod } from "@conform-to/zod";
import { data, Form, Link, useSearchParams } from "react-router";
import { z } from "zod";
import { ErrorList } from "~/components/forms";
import { Logo } from "~/components/logo";
import { Button } from "~/components/ui/button";
import {
Card,
Expand Down Expand Up @@ -128,95 +129,98 @@ export default function Component({ actionData }: Route.ComponentProps) {
const [searchParams] = useSearchParams();

return (
<Card className="mx-auto max-w-sm">
<CardHeader>
<CardTitle asChild className="text-2xl">
<h1>Sign Up</h1>
</CardTitle>
<CardDescription>
Enter your information to create an account
</CardDescription>
</CardHeader>
<CardContent>
<Form method="post" {...getFormProps(form)}>
<div className="grid gap-4">
<div className="grid gap-2">
<Label htmlFor={fields.username.id}>Username</Label>
<Input
autoComplete="username"
placeholder="m_robinson"
{...getInputProps(fields.username, { type: "text" })}
/>
<ErrorList
id={fields.username.errorId}
errors={fields.username.errors}
/>
</div>
<div className="grid grid-cols-2 items-start gap-4">
<div className="mx-auto w-full max-w-[400px]">
<Logo className="mx-auto h-11 w-auto" />
<Card className="mt-10">
<CardHeader className="items-center">
<CardTitle asChild className="text-2xl">
<h1>Sign Up</h1>
</CardTitle>
<CardDescription>
Enter your information to create an account
</CardDescription>
</CardHeader>
<CardContent>
<Form method="post" {...getFormProps(form)}>
<div className="grid gap-4">
<div className="grid gap-2">
<Label htmlFor={fields.first.id}>First name</Label>
<Label htmlFor={fields.username.id}>Username</Label>
<Input
autoComplete="given-name"
placeholder="Max"
{...getInputProps(fields.first, { type: "text" })}
autoComplete="username"
placeholder="m_robinson"
{...getInputProps(fields.username, { type: "text" })}
/>
<ErrorList
id={fields.first.errorId}
errors={fields.first.errors}
id={fields.username.errorId}
errors={fields.username.errors}
/>
</div>
<div className="grid grid-cols-2 items-start gap-4">
<div className="grid gap-2">
<Label htmlFor={fields.first.id}>First name</Label>
<Input
autoComplete="given-name"
placeholder="Max"
{...getInputProps(fields.first, { type: "text" })}
/>
<ErrorList
id={fields.first.errorId}
errors={fields.first.errors}
/>
</div>
<div className="grid gap-2">
<Label htmlFor={fields.last.id}>Last name</Label>
<Input
autoComplete="family-name"
placeholder="Robinson"
{...getInputProps(fields.last, { type: "text" })}
/>
<ErrorList
id={fields.last.errorId}
errors={fields.last.errors}
/>
</div>
</div>
<div className="grid gap-2">
<Label htmlFor={fields.last.id}>Last name</Label>
<Label htmlFor={fields.email.id}>Email</Label>
<Input
autoComplete="family-name"
placeholder="Robinson"
{...getInputProps(fields.last, { type: "text" })}
autoComplete="email"
placeholder="m@example.com"
{...getInputProps(fields.email, { type: "email" })}
/>
<ErrorList
id={fields.last.errorId}
errors={fields.last.errors}
id={fields.email.errorId}
errors={fields.email.errors}
/>
</div>
<div className="grid gap-2">
<Label htmlFor={fields.password.id}>Password</Label>
<Input
autoComplete="new-password"
{...getInputProps(fields.password, { type: "password" })}
/>
<ErrorList
id={fields.password.errorId}
errors={fields.password.errors}
/>
</div>
<ErrorList id={form.errorId} errors={form.errors} />
<Button type="submit" className="w-full">
Create an account
</Button>
</div>
<div className="grid gap-2">
<Label htmlFor={fields.email.id}>Email</Label>
<Input
autoComplete="email"
placeholder="m@example.com"
{...getInputProps(fields.email, { type: "email" })}
/>
<ErrorList
id={fields.email.errorId}
errors={fields.email.errors}
/>
</div>
<div className="grid gap-2">
<Label htmlFor={fields.password.id}>Password</Label>
<Input
autoComplete="new-password"
{...getInputProps(fields.password, { type: "password" })}
/>
<ErrorList
id={fields.password.errorId}
errors={fields.password.errors}
/>
</div>
<ErrorList id={form.errorId} errors={form.errors} />
<Button type="submit" className="w-full">
Create an account
</Button>
</div>
</Form>
<p className="mt-4 text-center text-sm">
Already have an account?{" "}
<Link
to={{ pathname: "/login", search: searchParams.toString() }}
className="underline"
>
Sign in
</Link>
</p>
</CardContent>
</Card>
</Form>
<p className="mt-4 text-center text-sm">
Already have an account?{" "}
<Link
to={{ pathname: "/login", search: searchParams.toString() }}
className="underline"
>
Sign in
</Link>
</p>
</CardContent>
</Card>
</div>
);
}
106 changes: 55 additions & 51 deletions app/routes/_auth.login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { getZodConstraint, parseWithZod } from "@conform-to/zod";
import { data, Form, Link, useSearchParams } from "react-router";
import { z } from "zod";
import { ErrorList } from "~/components/forms";
import { Logo } from "~/components/logo";
import { Button } from "~/components/ui/button";
import {
Card,
Expand Down Expand Up @@ -88,57 +89,60 @@ export default function Component({ actionData }: Route.ComponentProps) {
const [searchParams] = useSearchParams();

return (
<Card className="mx-auto max-w-sm">
<CardHeader>
<CardTitle asChild className="text-2xl">
<h1>Login</h1>
</CardTitle>
<CardDescription>
Enter your email below to login to your account
</CardDescription>
</CardHeader>
<CardContent>
<Form method="post" {...getFormProps(form)}>
<div className="grid gap-4">
<div className="grid gap-2">
<Label htmlFor={fields.email.id}>Email</Label>
<Input
autoComplete="email"
placeholder="m@example.com"
{...getInputProps(fields.email, { type: "email" })}
/>
<ErrorList
id={fields.email.errorId}
errors={fields.email.errors}
/>
<div className="mx-auto w-full max-w-[400px]">
<Logo className="mx-auto h-11 w-auto" />
<Card className="mt-10">
<CardHeader className="items-center">
<CardTitle asChild className="text-2xl">
<h1>Login</h1>
</CardTitle>
<CardDescription>
Enter your details below to login to your account
</CardDescription>
</CardHeader>
<CardContent>
<Form method="post" {...getFormProps(form)}>
<div className="grid gap-4">
<div className="grid gap-2">
<Label htmlFor={fields.email.id}>Email</Label>
<Input
autoComplete="email"
placeholder="m@example.com"
{...getInputProps(fields.email, { type: "email" })}
/>
<ErrorList
id={fields.email.errorId}
errors={fields.email.errors}
/>
</div>
<div className="grid gap-2">
<Label htmlFor={fields.password.id}>Password</Label>
<Input
autoComplete="current-password"
{...getInputProps(fields.password, { type: "password" })}
/>
<ErrorList
id={fields.password.errorId}
errors={fields.password.errors}
/>
</div>
<ErrorList id={form.errorId} errors={form.errors} />
<Button type="submit" className="w-full">
Login
</Button>
</div>
<div className="grid gap-2">
<Label htmlFor={fields.password.id}>Password</Label>
<Input
autoComplete="current-password"
{...getInputProps(fields.password, { type: "password" })}
/>
<ErrorList
id={fields.password.errorId}
errors={fields.password.errors}
/>
</div>
<ErrorList id={form.errorId} errors={form.errors} />
<Button type="submit" className="w-full">
Login
</Button>
</div>
</Form>
<p className="mt-4 text-center text-sm">
Don&apos;t have an account?{" "}
<Link
to={{ pathname: "/join", search: searchParams.toString() }}
className="underline"
>
Sign up
</Link>
</p>
</CardContent>
</Card>
</Form>
<p className="mt-4 text-center text-sm">
Don&apos;t have an account?{" "}
<Link
to={{ pathname: "/join", search: searchParams.toString() }}
className="underline"
>
Sign up
</Link>
</p>
</CardContent>
</Card>
</div>
);
}
13 changes: 6 additions & 7 deletions app/routes/_dashboard.contacts.$contactId._index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { invariantResponse } from "@epic-web/invariant";
import { Pencil1Icon } from "@radix-ui/react-icons";
import { format, formatDistanceStrict } from "date-fns";
import { Form, Link } from "react-router";
import { data, Form, Link } from "react-router";
import { EmptyState } from "~/components/empty-state";
import { Button } from "~/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
Expand All @@ -26,11 +25,11 @@ export async function loader({ request, params }: Route.LoaderArgs) {
},
where: { id: params.contactId, userId },
});
invariantResponse(
contact,
`No contact with the id "${params.contactId}" exists.`,
{ status: 404 },
);
if (!contact) {
throw data(`No contact with the id "${params.contactId}" exists.`, {
status: 404,
});
}

return { contact };
}
Expand Down
12 changes: 6 additions & 6 deletions app/routes/_dashboard.contacts.$contactId.notes.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { parseWithZod } from "@conform-to/zod";
import { invariantResponse } from "@epic-web/invariant";
import { DotsHorizontalIcon, UpdateIcon } from "@radix-ui/react-icons";
import { compareAsc, format, isToday, isYesterday } from "date-fns";
import { useState } from "react";
Expand Down Expand Up @@ -39,11 +38,11 @@ export async function action({ request, params }: Route.ActionArgs) {
select: { id: true },
where: { id: params.contactId, userId },
});
invariantResponse(
contact,
`No contact with the id "${params.contactId}" exists.`,
{ status: 404 },
);
if (!contact) {
throw data(`No contact with the id "${params.contactId}" exists.`, {
status: 404,
});
}

const formData = await request.formData();

Expand All @@ -56,6 +55,7 @@ export async function action({ request, params }: Route.ActionArgs) {
}

const { text, date } = submission.value;

await db.note.create({
select: { id: true },
data: { text, date, contact: { connect: { id: params.contactId } } },
Expand Down
Loading

0 comments on commit 2392fa8

Please sign in to comment.