Skip to content

Commit

Permalink
Implement authentiaction, appwrite and sentry
Browse files Browse the repository at this point in the history
  • Loading branch information
AnslemCode committed Aug 13, 2024
1 parent 14342be commit de00b1a
Show file tree
Hide file tree
Showing 30 changed files with 3,499 additions and 225 deletions.
23 changes: 23 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#NEXT
NEXT_PUBLIC_SITE_URL=http://localhost:3000

#APPWRITE
NEXT_PUBLIC_APPWRITE_ENDPOINT=https://cloud.appwrite.io/v1
NEXT_PUBLIC_APPWRITE_PROJECT=66b990e9002a422561f2
APPWRITE_DATABASE_ID=66b991f300286bd0255f
APPWRITE_USER_COLLECTION_ID=66b992040004b1d8de79
APPWRITE_BANK_COLLECTION_ID=66b9924e0035cfae025a
APPWRITE_TRANSACTION_COLLECTION_ID=66b99230002710ddd1e8
NEXT_APPWRITE_KEY=9288e2db04879a9f3ce5555c7420955a97dc7e39030b30902c3432f02f2387444f970b919eec9db436b1f5f2fa0274abc4f145edc4b61b2acb0d863bac6b23e99f7a7f974ab972287aba97972cf86c6e6b8136f83437f558ffd686ea4425fd85fa52e277aa49e1bc4d402db10e83230f16e4f197fbbae720bef75442f968fb77
#PLAID
PLAID_CLIENT_ID=
PLAID_SECRET=
PLAID_ENV=
PLAID_PRODUCTS=
PLAID_COUNTRY_CODES=

#DWOLLA
DWOLLA_KEY=
DWOLLA_SECRET=
DWOLLA_BASE_URL=
DWOLLA_ENV=
25 changes: 25 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#NEXT
NEXT_PUBLIC_SITE_URL=http://localhost:3000

#APPWRITE
NEXT_PUBLIC_APPWRITE_ENDPOINT=https://cloud.appwrite.io/v1
NEXT_PUBLIC_APPWRITE_PROJECT=
APPWRITE_DATABASE_ID=
APPWRITE_USER_COLLECTION_ID=
APPWRITE_ITEM_COLLECTION_ID=
APPWRITE_BANK_COLLECTION_ID=
APPWRITE_TRANSACTION_COLLECTION_ID=
NEXT_APPWRITE_KEY=

#PLAID
PLAID_CLIENT_ID=
PLAID_SECRET=
PLAID_ENV=
PLAID_PRODUCTS=
PLAID_COUNTRY_CODES=

#DWOLLA
DWOLLA_KEY=
DWOLLA_SECRET=
DWOLLA_BASE_URL=
DWOLLA_ENV=
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,6 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts

# Sentry Config File
.env.sentry-build-plugin
18 changes: 17 additions & 1 deletion app/(auth)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,23 @@
import Image from "next/image";
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return <main>{children}</main>;
return (
<main className="flex min-h-screen w-full justify-between font-inter">
{children}
<div className="auth-asset">
<div>
<Image
src="/icons/auth-image.svg"
alt="Auth image"
width={500}
height={500}
className="rounded-l-xl object-contain"
/>
</div>
</div>
</main>
);
}
7 changes: 6 additions & 1 deletion app/(auth)/sign-in/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import AuthForm from "@/components/AuthForm";
import React from "react";

const SignIn = () => {
return <div>SignIn</div>;
return (
<section className="flex-center size-full max-sm:px-6">
<AuthForm type="sign-in" />
</section>
);
};

export default SignIn;
12 changes: 10 additions & 2 deletions app/(auth)/sign-up/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import AuthForm from "@/components/AuthForm";
import { getLoggedInUser } from "@/lib/actions/user.actions";
import React from "react";

const SignUp = () => {
return <div>SignUp</div>;
const SignUp = async () => {
const loggedInUser = await getLoggedInUser();
console.log(loggedInUser);
return (
<section className="flex-center size-full max-sm:px-6">
<AuthForm type="sign-up" />
</section>
);
};

export default SignUp;
8 changes: 6 additions & 2 deletions app/(root)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import MobileNav from "@/components/MobileNav";
import Sidebar from "@/components/Sidebar";
import { getLoggedInUser } from "@/lib/actions/user.actions";
import Image from "next/image";
import { redirect } from "next/navigation";

export default function RootLayout({
export default async function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
const loggedIn = { firstName: "Angel", lastName: "Nmesoma" };
const loggedIn = await getLoggedInUser();
if (!loggedIn) redirect("/sign-in");
return (
<main className="flex h-screen w-full font-inter">
<Sidebar user={loggedIn} />
Expand Down
11 changes: 4 additions & 7 deletions app/(root)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
import HeaderBox from "@/components/HeaderBox";
import RightSidebar from "@/components/RightSidebar";
import TotalBalanceBox from "@/components/TotalBalanceBox";
import { getLoggedInUser } from "@/lib/actions/user.actions";
import React from "react";

const Home = () => {
const loggedIn = {
firstName: "Nmesoma",
lastName: "Angel",
email: "[email protected]",
};
const Home = async () => {
const loggedIn = await getLoggedInUser();
return (
<section className="home">
<div className="home-content">
<header className="home-header">
<HeaderBox
type="greeting"
title="Welcome"
user={loggedIn.firstName || "Guest"}
user={loggedIn?.name || "Guest"}
subtext="Access and manage your account and transactions effectively"
/>

Expand Down
23 changes: 23 additions & 0 deletions app/global-error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"use client";

import * as Sentry from "@sentry/nextjs";
import NextError from "next/error";
import { useEffect } from "react";

export default function GlobalError({ error }: { error: Error & { digest?: string } }) {
useEffect(() => {
Sentry.captureException(error);
}, [error]);

return (
<html>
<body>
{/* `NextError` is the default Next.js error page component. Its type
definition requires a `statusCode` prop. However, since the App Router
does not expose status codes for errors, we simply pass 0 to render a
generic error message. */}
<NextError statusCode={0} />
</body>
</html>
);
}
207 changes: 207 additions & 0 deletions components/AuthForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
"use client";
import Image from "next/image";
import Link from "next/link";
import { useState } from "react";

import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { Button } from "@/components/ui/button";
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { authFormSchema } from "@/lib/utils";
import CustomInput from "./CustomInput";
import { Loader2 } from "lucide-react";
import { useRouter } from "next/navigation";
import { getLoggedInUser, signIn, signUp } from "@/lib/actions/user.actions";

interface propsType {
type: string;
}

const AuthForm = ({ type }: propsType) => {
const router = useRouter();
const [user, setUser] = useState(null);
const [isLoading, setIsLoading] = useState(false);

const formSchema = authFormSchema(type);

const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
email: "",
password: "",
},
});

// 2. Define a submit handler.
const onSubmit = async (values: z.infer<typeof formSchema>) => {
setIsLoading(true);
try {
// Sign up with Appwrite and create plaid token
if (type === "sign-up") {
const newUser = await signUp(values);
setUser(newUser);
}

if (type === "sign-in") {
const response = await signIn({
email: values.email,
password: values.password,
});
if (response) router.push("/");
}
} catch (error) {
console.log(error);
} finally {
setIsLoading(false);
}
};

return (
<section className="auth-form">
<header className="flex flex-col gap-5 md:gap-8">
<Link href="/" className="cursor-pointer flex items-center gap-1">
<Image
src="/icons/logo.svg"
width={34}
height={34}
alt="Horizon logo"
/>
<h1 className="text-26 font-ibm-plex-serif font-bold text-black-1">
Horizon
</h1>
</Link>

<div>
<h1 className="text-24 lg:text-36 font-semibold text-gray-900">
{user ? "Link Account" : type === "sign-in" ? "Sign in" : "Sign-up"}
<p className="text-16 font-normal text-gray-600">
{user
? "Link your account to get started"
: "Please enter your details"}
</p>
</h1>
</div>
</header>
{user ? (
<div className="flex flex-col gap-4">{/* PlaidLink */}</div>
) : (
<>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
{type === "sign-up" && (
<>
<div className="flex gap-4">
<CustomInput
control={form.control}
name="firstName"
label="First Name"
placeholder="Enter your first name"
/>
<CustomInput
control={form.control}
name="lastName"
label="Last Name"
placeholder="Enter your first name"
/>
</div>
<CustomInput
control={form.control}
name="address1"
label="Address"
placeholder="Enter your specific address"
/>
<CustomInput
control={form.control}
name="city"
label="City"
placeholder="Enter your city"
/>
<div className="flex gap-4">
<CustomInput
control={form.control}
name="state"
label="State"
placeholder="Example: NY"
/>
<CustomInput
control={form.control}
name="postalCode"
label="Postal Code"
placeholder="Example: 11101"
/>
</div>
<div className="flex gap-4">
<CustomInput
control={form.control}
name="dateOfBirth"
label="Date of Birth"
placeholder="YYYY-MM-DD"
/>
<CustomInput
control={form.control}
name="ssn"
label="SSN"
placeholder="Example: 1234"
/>
</div>
</>
)}
<CustomInput
control={form.control}
name="email"
label="Email"
placeholder="Enter your email"
/>
<CustomInput
control={form.control}
name="password"
label="Password"
placeholder="Enter your password"
/>
<div className="flex flex-col gap-4">
<Button type="submit" disabled={isLoading} className="form-btn">
{isLoading ? (
<>
<Loader2 size={20} className="animate-spin" /> &nbsp;
Loading...
</>
) : type === "sign-in" ? (
"Sign In"
) : (
"Sign Up"
)}
</Button>
</div>
</form>
</Form>

<footer className="flex justify-center gap-1">
<p className="text-14 font-normal text-gray-600">
{type === "sign-in"
? "Don't have an account?"
: "Already have an account?"}
</p>
<Link
href={type === "sign-in" ? "/sign-up" : "/sign-in"}
className="form-link"
>
{type === "sign-in" ? "Sign up" : "Sign in"}
</Link>
</footer>
</>
)}
</section>
);
};

export default AuthForm;
Loading

0 comments on commit de00b1a

Please sign in to comment.