-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #118 from edgedb/add-remix-auth-example
Add remix auth example
- Loading branch information
Showing
37 changed files
with
13,261 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
/** @type {import('eslint').Linter.Config} */ | ||
module.exports = { | ||
extends: ["@remix-run/eslint-config", "@remix-run/eslint-config/node"], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
/node_modules | ||
|
||
/.cache | ||
/build | ||
/public/build | ||
.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# Welcome to EdgeDB Auth todo example app built with Remix! | ||
|
||
- [EdgeDB Auth](https://www.edgedb.com/docs/guides/auth/index) | ||
- [EdgeDB Docs](https://www.edgedb.com/docs) | ||
- [Remix Docs](https://remix.run/docs) | ||
|
||
## Development | ||
|
||
From your terminal: | ||
|
||
```sh | ||
npm run dev | ||
``` | ||
|
||
This starts your app in development mode, rebuilding assets on file changes. | ||
|
||
## Deployment | ||
|
||
First, build your app for production: | ||
|
||
```sh | ||
npm run build | ||
``` | ||
|
||
Then run the app in production mode: | ||
|
||
```sh | ||
npm start | ||
``` | ||
|
||
Now you'll need to pick a host to deploy it to. | ||
|
||
### DIY | ||
|
||
If you're familiar with deploying node applications, the built-in Remix app server is production-ready. | ||
|
||
Make sure to deploy the output of `remix build` | ||
|
||
- `build/` | ||
- `public/build/` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { Form } from "@remix-run/react"; | ||
import SubmitButton from "./SubmitButton"; | ||
|
||
interface ResetPasswordFormProps { | ||
error?: string | null; | ||
message?: string | null; | ||
} | ||
|
||
export default function ForgotPasswordForm({ | ||
error, | ||
message, | ||
}: ResetPasswordFormProps) { | ||
return ( | ||
<Form className="flex flex-col w-[22rem]" method="post"> | ||
{error ? ( | ||
<div className="bg-rose-100 text-rose-950 px-4 py-3 rounded-md mb-3"> | ||
{error} | ||
</div> | ||
) : null} | ||
|
||
{message ? ( | ||
<div className="bg-sky-200 text-sky-950 px-4 py-3 rounded-md mb-3"> | ||
{message} | ||
</div> | ||
) : ( | ||
<> | ||
<label htmlFor="email" className="font-medium text-sm mb-1 ml-2"> | ||
</label> | ||
<input | ||
type="email" | ||
id="email" | ||
name="email" | ||
required | ||
className="bg-slate-50 border border-slate-200 rounded-lg mb-4 px-4 py-3 outline-teal-600 outline-2 focus:outline focus:bg-white" | ||
/> | ||
<SubmitButton label="Send reset email" /> | ||
</> | ||
)} | ||
</Form> | ||
); | ||
} |
39 changes: 39 additions & 0 deletions
39
remix-auth/app/components/auth/ResendVerificationEmail.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
interface ResendVerificationEmailProps { | ||
verificationToken: string; | ||
error?: string | null; | ||
message?: string | null; | ||
} | ||
|
||
export default function ResendVerificationEmail({ | ||
verificationToken, | ||
error, | ||
message, | ||
}: ResendVerificationEmailProps) { | ||
return ( | ||
<form method="post"> | ||
{error || message ? ( | ||
<div | ||
className={`${ | ||
error ? "bg-rose-100 text-rose-950" : "bg-sky-200 text-sky-950" | ||
} px-4 py-3 rounded-md mb-3`} | ||
> | ||
{error || message} | ||
</div> | ||
) : null} | ||
|
||
<input | ||
type="hidden" | ||
name="verification_token" | ||
defaultValue={verificationToken} | ||
/> | ||
<button | ||
name="action" | ||
value="resendVerEmail" | ||
type="submit" | ||
className="text-sky-600 mt-2" | ||
> | ||
Resend verification email | ||
</button> | ||
</form> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import SubmitButton from "./SubmitButton"; | ||
|
||
interface ResetPasswordFormProps { | ||
error?: string | null; | ||
resetToken: string; | ||
} | ||
|
||
export default function ResetPasswordForm({ | ||
error, | ||
resetToken, | ||
}: ResetPasswordFormProps) { | ||
return ( | ||
<form method="post" className="flex flex-col w-[22rem]"> | ||
{error ? ( | ||
<div className="bg-rose-100 text-rose-950 px-4 py-3 rounded-md mb-3"> | ||
{error} | ||
</div> | ||
) : ( | ||
<> | ||
<label htmlFor="password" className="font-medium text-sm mb-1 ml-2"> | ||
New password | ||
</label> | ||
<input | ||
type="password" | ||
id="password" | ||
name="password" | ||
required | ||
className="bg-slate-50 border border-slate-200 rounded-lg mb-4 px-4 py-3 outline-sky-500 outline-2 focus:outline focus:bg-white" | ||
/> | ||
<input type="hidden" name="reset_token" defaultValue={resetToken} /> | ||
<SubmitButton label="Set new password" /> | ||
</> | ||
)} | ||
</form> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { Form, Link } from "@remix-run/react"; | ||
import SubmitButton from "./SubmitButton"; | ||
|
||
interface SigninFormProps { | ||
error?: string | null; | ||
} | ||
|
||
export default function SigninForm({ error }: SigninFormProps) { | ||
return ( | ||
<Form className="flex flex-col w-[22rem]" method="post"> | ||
{error ? ( | ||
<div className="bg-rose-100 text-rose-950 px-4 py-3 rounded-md mb-3"> | ||
{error} | ||
</div> | ||
) : null} | ||
<label htmlFor="email" className="font-medium text-sm mb-1 ml-2"> | ||
</label> | ||
<input | ||
type="email" | ||
id="email" | ||
name="email" | ||
required | ||
className="bg-slate-50 border border-slate-200 rounded-lg mb-4 px-4 py-3 outline-teal-600 outline-2 focus:outline focus:bg-white" | ||
/> | ||
<div className="flex text-sm"> | ||
<label htmlFor="password" className="font-medium mb-1 ml-2"> | ||
Password | ||
</label> | ||
<Link | ||
to="/forgot-password" | ||
className="ml-auto text-teal-600 hover:text-teal-700" | ||
> | ||
Forgot password? | ||
</Link> | ||
</div> | ||
<input | ||
type="password" | ||
id="password" | ||
name="password" | ||
required | ||
className="bg-slate-50 border border-slate-200 rounded-lg mb-4 px-4 py-3 outline-teal-600 outline-2 focus:outline focus:bg-white" | ||
/> | ||
<SubmitButton label="Sign in" /> | ||
|
||
<div className="text-slate-500 mt-3"> | ||
Don't have an account?{" "} | ||
<Link to="/signup" className="text-teal-600 hover:text-teal-700"> | ||
Sign up | ||
</Link> | ||
</div> | ||
</Form> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { Form, Link } from "@remix-run/react"; | ||
import SubmitButton from "./SubmitButton"; | ||
|
||
interface SignupFormProps { | ||
error?: string | null; | ||
message?: string | null; | ||
} | ||
|
||
export default function SignupForm({ error, message }: SignupFormProps) { | ||
return ( | ||
<Form className="flex flex-col w-[22rem]" method="post"> | ||
{error || message ? ( | ||
<div | ||
className={`${ | ||
error ? "bg-rose-100 text-rose-950" : "bg-sky-200 text-sky-950" | ||
} px-4 py-3 rounded-md mb-3`} | ||
> | ||
{error || message} | ||
</div> | ||
) : null} | ||
|
||
<label htmlFor="email" className="font-medium text-sm mb-1 ml-2"> | ||
</label> | ||
<input | ||
type="email" | ||
id="email" | ||
name="email" | ||
required | ||
className="bg-slate-50 border border-slate-200 rounded-lg mb-4 px-4 py-3 outline-teal-600 outline-2 focus:outline focus:bg-white" | ||
/> | ||
<label htmlFor="password" className="font-medium text-sm mb-1 ml-2"> | ||
Password | ||
</label> | ||
<input | ||
type="password" | ||
id="password" | ||
name="password" | ||
required | ||
className="bg-slate-50 border border-slate-200 rounded-lg mb-4 px-4 py-3 outline-teal-600 outline-2 focus:outline focus:bg-white" | ||
/> | ||
<SubmitButton label="Sign up" /> | ||
|
||
<div className="text-slate-500 mt-3"> | ||
Already have an account?{" "} | ||
<Link to="/signin" className="text-teal-600 hover:text-teal-700"> | ||
Sign in | ||
</Link> | ||
</div> | ||
</Form> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
export default function SubmitButton({ label }: { label: string }) { | ||
return ( | ||
<button | ||
type="submit" | ||
className={`bg-teal-600 text-white p-3 rounded-md mt-3 shadow-md hover:scale-[1.03] transition-transform`} | ||
> | ||
{label} | ||
</button> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { Form } from "@remix-run/react"; | ||
import { CheckIcon, DeleteIcon } from "~/icons"; | ||
|
||
export interface Todo { | ||
id: string; | ||
content: string; | ||
completed: boolean; | ||
created_on: string; | ||
} | ||
|
||
export function TodoCard({ id, content, completed, created_on }: Todo) { | ||
return ( | ||
<div className="bg-white shadow-sm rounded-xl p-4 text-lg flex hover:scale-[1.02] transition-transform duration-75"> | ||
<Form method="put"> | ||
<input | ||
type="hidden" | ||
name="todo" | ||
defaultValue={JSON.stringify({ id, content, completed, created_on })} | ||
/> | ||
<button | ||
type="submit" | ||
className={`w-9 h-9 rounded-full mr-4 flex-shrink-0 flex items-center justify-center cursor-pointer ${ | ||
completed ? "bg-sky-400 text-white" : "border border-slate-400" | ||
}`} | ||
> | ||
{completed ? <CheckIcon /> : null} | ||
</button> | ||
</Form> | ||
|
||
<span | ||
className={`flex-shrink overflow-hidden break-words py-1 mr-auto ${ | ||
completed ? "line-through opacity-70" : "" | ||
}`} | ||
> | ||
{content} | ||
</span> | ||
|
||
<Form method="delete"> | ||
<input | ||
type="hidden" | ||
name="todo" | ||
defaultValue={JSON.stringify({ id, content, completed, created_on })} | ||
/> | ||
<button | ||
type="submit" | ||
className="w-9 h-9 rounded-full ml-4 flex-shrink-0 flex items-center justify-center cursor-pointer text-slate-400 hover:bg-rose-500 hover:text-white" | ||
> | ||
<DeleteIcon /> | ||
</button> | ||
</Form> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { SendIcon } from "~/icons"; | ||
import { Form, useNavigation } from "@remix-run/react"; | ||
import { type Todo, TodoCard } from "./TodoCard"; | ||
import { useEffect, useRef } from "react"; | ||
|
||
export function TodoList({ todos }: { todos: Todo[] | null }) { | ||
const navigation = useNavigation(); | ||
|
||
const isSubmitting = navigation.state === "submitting"; | ||
|
||
const formRef = useRef<HTMLFormElement>(null); | ||
const inputRef = useRef<HTMLInputElement>(null); | ||
|
||
useEffect(() => { | ||
if (isSubmitting) return; | ||
formRef.current?.reset(); | ||
inputRef.current?.focus(); | ||
}, [isSubmitting]); | ||
|
||
return ( | ||
<div className="flex flex-col gap-3 mt-4"> | ||
<Form | ||
ref={formRef} | ||
method="post" | ||
className="flex bg-slate-50 border border-slate-200 rounded-xl mb-4 overflow-hidden outline-teal-600 outline-[3px] focus-within:outline focus-within:bg-white" | ||
> | ||
<input | ||
ref={inputRef} | ||
type="text" | ||
name="newTodo" | ||
placeholder="Add new todo..." | ||
className="flex-grow bg-transparent pl-5 text-lg focus:outline-none focus-visible:ring-0" | ||
/> | ||
<button | ||
type="submit" | ||
className="h-9 w-9 p-3 box-content flex items-center justify-center text-teal-600" | ||
tabIndex={-1} | ||
> | ||
<SendIcon /> | ||
</button> | ||
</Form> | ||
|
||
{todos?.length ? ( | ||
todos.map((todo) => <TodoCard key={todo.id} {...todo} />) | ||
) : ( | ||
<div className="border-dashed border-2 border-slate-300 text-slate-500 h-8 py-4 px-8 box-content flex items-center rounded-xl"> | ||
You have no todo's | ||
</div> | ||
)} | ||
</div> | ||
); | ||
} |
Oops, something went wrong.